Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f93c5b2c2 | |||
| 0a3ca0234e | |||
| a88da5cf0e | |||
| 159f1fcdc8 | |||
| f50df99417 | |||
| 9217e88831 | |||
| 49c6c6afe9 | |||
| ffd00155e0 | |||
| 9fd3636ffd | |||
| 5ff6b4a4d2 | |||
| 22c431c8e0 | |||
| 2db3a4d6f4 | |||
| 1310561e55 | |||
| edcb6cac7d | |||
| be8460c20b | |||
| 0794dfb8e0 | |||
| d950988e62 | |||
| 295473d416 | |||
| acc2c6eab4 | |||
| 9f6db5d13d | |||
| 71e66d3783 | |||
| 2c7085b04b | |||
| 2c7584c00f | |||
| 4d00178d94 | |||
| 863da32f93 | |||
| b9ad9e922e |
@@ -19,3 +19,11 @@ REACT_APP_TIMEOUT=600000
|
|||||||
# show download button
|
# show download button
|
||||||
REACT_APP_SHOW_DOWNLOAD=0
|
REACT_APP_SHOW_DOWNLOAD=0
|
||||||
|
|
||||||
|
REACT_APP_DNS1='dns1.mermsemr.net'
|
||||||
|
REACT_APP_DNS2='dns1.mermsemr.net'
|
||||||
|
REACT_APP_DNS_LINK='https://qa-www.mermsemr.com/info/dns'
|
||||||
|
|
||||||
|
|
||||||
|
#CLOUDFLARE
|
||||||
|
REACT_APP_TURNSTILE_SITE_KEY=0x4AAAAAADQV82wuocFR-u5O
|
||||||
|
|
||||||
|
|||||||
@@ -20,3 +20,10 @@ REACT_APP_TIMEOUT=600000
|
|||||||
# show download button
|
# show download button
|
||||||
REACT_APP_SHOW_DOWNLOAD=0
|
REACT_APP_SHOW_DOWNLOAD=0
|
||||||
|
|
||||||
|
REACT_APP_DNS1='dns1.mermsemr.net'
|
||||||
|
REACT_APP_DNS2='dns1.mermsemr.net'
|
||||||
|
REACT_APP_DNS_LINK='https://qa-www.mermsemr.com/info/dns'
|
||||||
|
|
||||||
|
#CLOUDFLARE
|
||||||
|
REACT_APP_TURNSTILE_SITE_KEY=0x4AAAAAADQV82wuocFR-u5O
|
||||||
|
|
||||||
|
|||||||
@@ -18,3 +18,11 @@ REACT_APP_TIMEOUT=600000
|
|||||||
|
|
||||||
# show download button
|
# show download button
|
||||||
REACT_APP_SHOW_DOWNLOAD=0
|
REACT_APP_SHOW_DOWNLOAD=0
|
||||||
|
|
||||||
|
REACT_APP_DNS1='dns1.mermsemr.net'
|
||||||
|
REACT_APP_DNS2='dns1.mermsemr.net'
|
||||||
|
REACT_APP_DNS_LINK='https://www.mermsemr.com/info/dns'
|
||||||
|
|
||||||
|
#CLOUDFLARE
|
||||||
|
REACT_APP_TURNSTILE_SITE_KEY=0x4AAAAAADQV82wuocFR-u5O
|
||||||
|
|
||||||
|
|||||||
@@ -15,3 +15,11 @@ REACT_APP_TERMS_LINK='https://qa-www.mermsemr.com/terms'
|
|||||||
|
|
||||||
# Inactivity timeout/logout AT 10MINS
|
# Inactivity timeout/logout AT 10MINS
|
||||||
REACT_APP_TIMEOUT=600000
|
REACT_APP_TIMEOUT=600000
|
||||||
|
|
||||||
|
REACT_APP_DNS1='dns1.mermsemr.net'
|
||||||
|
REACT_APP_DNS2='dns1.mermsemr.net'
|
||||||
|
REACT_APP_DNS_LINK='https://qa-www.mermsemr.com/info/dns'
|
||||||
|
|
||||||
|
#CLOUDFLARE
|
||||||
|
REACT_APP_TURNSTILE_SITE_KEY=0x4AAAAAADQV82wuocFR-u5O
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
merms-panel:
|
merms-panel:
|
||||||
image: registry.chiefsoft.net/merms-panel-reactjs:latest
|
# image: registry.chiefsoft.net/merms-panel-reactjs:latest
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: docker/Dockerfile
|
dockerfile: docker/Dockerfile
|
||||||
args:
|
# args:
|
||||||
- NODE_ENV=development
|
# - NODE_ENV=development
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- 8090:3000
|
- 8090:3000
|
||||||
|
|||||||
+22
-22
@@ -1,12 +1,12 @@
|
|||||||
# pull the base image
|
# pull the base image
|
||||||
# FROM node:alpine
|
# FROM node:alpine
|
||||||
|
|
||||||
FROM alpine:3.15
|
FROM alpine:3.22
|
||||||
|
|
||||||
# Build args
|
# Build args
|
||||||
ARG NODE_ENV
|
ARG NODE_ENV
|
||||||
|
|
||||||
ENV NODE_VERSION 14.19.0
|
ENV NODE_VERSION=14.19.0
|
||||||
ENV NODE_ENV=$NODE_ENV
|
ENV NODE_ENV=$NODE_ENV
|
||||||
|
|
||||||
# install nginx
|
# install nginx
|
||||||
@@ -82,26 +82,26 @@ RUN addgroup -g 1000 node \
|
|||||||
&& node --version \
|
&& node --version \
|
||||||
&& npm --version
|
&& npm --version
|
||||||
|
|
||||||
ENV YARN_VERSION 1.22.17
|
# ENV YARN_VERSION 1.22.17
|
||||||
|
|
||||||
RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \
|
# RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \
|
||||||
&& for key in \
|
# && for key in \
|
||||||
6A010C5166006599AA17F08146C2130DFD2497F5 \
|
# 6A010C5166006599AA17F08146C2130DFD2497F5 \
|
||||||
; do \
|
# ; do \
|
||||||
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" || \
|
# gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" || \
|
||||||
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
|
# gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
|
||||||
done \
|
# done \
|
||||||
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
|
# && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
|
||||||
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
|
# && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
|
||||||
&& gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
|
# && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
|
||||||
&& mkdir -p /opt \
|
# && mkdir -p /opt \
|
||||||
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
|
# && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
|
||||||
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
|
# && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
|
||||||
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
|
# && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
|
||||||
&& rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
|
# && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
|
||||||
&& apk del .build-deps-yarn \
|
# && apk del .build-deps-yarn \
|
||||||
# smoke test
|
# # smoke test
|
||||||
&& yarn --version
|
# && yarn --version
|
||||||
|
|
||||||
# set working directory
|
# set working directory
|
||||||
# WORKDIR /app
|
# WORKDIR /app
|
||||||
@@ -109,7 +109,7 @@ RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \
|
|||||||
|
|
||||||
# add `/app/node_modules/.bin` to $PATH
|
# add `/app/node_modules/.bin` to $PATH
|
||||||
# ENV PATH /app/node_modules/.bin:$PATH
|
# ENV PATH /app/node_modules/.bin:$PATH
|
||||||
ENV PATH /usr/src/app/node_modules/.bin:$PATH
|
ENV PATH=/usr/src/app/node_modules/.bin:$PATH
|
||||||
|
|
||||||
COPY nginx.conf ./
|
COPY nginx.conf ./
|
||||||
|
|
||||||
|
|||||||
Generated
+12137
-5671
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@
|
|||||||
"@fullcalendar/interaction": "^6.1.15",
|
"@fullcalendar/interaction": "^6.1.15",
|
||||||
"@fullcalendar/react": "^6.1.15",
|
"@fullcalendar/react": "^6.1.15",
|
||||||
"@fullcalendar/timegrid": "^6.1.15",
|
"@fullcalendar/timegrid": "^6.1.15",
|
||||||
|
"@marsidev/react-turnstile": "^1.5.2",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@reduxjs/toolkit": "^2.4.0",
|
"@reduxjs/toolkit": "^2.4.0",
|
||||||
"@stripe/react-stripe-js": "^3.9.1",
|
"@stripe/react-stripe-js": "^3.9.1",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { Form, Formik } from "formik";
|
import { Form, Formik } from "formik";
|
||||||
|
import { Turnstile } from '@marsidev/react-turnstile'
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
// import LoginImg from '../../assets/bg/login.svg'
|
// import LoginImg from '../../assets/bg/login.svg'
|
||||||
|
|
||||||
@@ -17,13 +18,14 @@ const validationSchema = Yup.object().shape({
|
|||||||
// /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/,
|
// /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/,
|
||||||
// "Invalid email format"
|
// "Invalid email format"
|
||||||
// )
|
// )
|
||||||
.min(3, "Minimum 3 characters")
|
.min(3, "Username must be at least 3 characters")
|
||||||
.max(25, "Maximum 25 characters")
|
.max(25, "Entered Username is too long")
|
||||||
.required("Email is required"),
|
.required("Enter a valid username to continue"),
|
||||||
})
|
})
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
username: ''
|
username: '',
|
||||||
|
turnstileToken: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Forgetpwd2() {
|
export default function Forgetpwd2() {
|
||||||
@@ -77,8 +79,18 @@ export default function Forgetpwd2() {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<div className="text-center col-12 mt-3">
|
||||||
|
<Turnstile
|
||||||
|
siteKey={process.env.REACT_APP_TURNSTILE_SITE_KEY}
|
||||||
|
onSuccess={(token) => props.setFieldValue('turnstileToken', token)}
|
||||||
|
onExpire={() => props.setFieldValue('turnstileToken', null)}
|
||||||
|
onError={() => props.setFieldValue('turnstileToken', null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="col-12 mt-3 text-end">
|
<div className="col-12 mt-3 text-end">
|
||||||
<button type='submit' className="btn btn-primary text-uppercase">{mutation.isPending ? 'loading...' : 'Send'}</button>
|
<button type='submit' disabled={!props.values.turnstileToken || mutation.isPending} className="btn btn-primary text-uppercase">{mutation.isPending ? 'loading...' : 'Send'}</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
:
|
:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { useMutation } from '@tanstack/react-query'
|
import { useMutation } from '@tanstack/react-query'
|
||||||
import { useDispatch, useSelector } from 'react-redux'
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
|
import { Turnstile } from '@marsidev/react-turnstile'
|
||||||
|
|
||||||
// import LoginImg from '../../assets/bg/login.svg'
|
// import LoginImg from '../../assets/bg/login.svg'
|
||||||
|
|
||||||
@@ -26,6 +27,8 @@ export default function Login() {
|
|||||||
remember: false
|
remember: false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [turnstileToken, setTurnstileToken] = useState(null)
|
||||||
|
|
||||||
const handleChange = ({target:{name, value}}) => {
|
const handleChange = ({target:{name, value}}) => {
|
||||||
if(name == 'remember'){
|
if(name == 'remember'){
|
||||||
return setFields(prev => ({...prev, remember:!prev.remember}))
|
return setFields(prev => ({...prev, remember:!prev.remember}))
|
||||||
@@ -34,13 +37,13 @@ export default function Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const login = useMutation({
|
const login = useMutation({
|
||||||
mutationFn: (fields) => {
|
mutationFn: ({ turnstileToken, ...fields }) => {
|
||||||
if(!fields.username || !fields.password){
|
if(!fields.username || !fields.password){
|
||||||
throw new Error('Please provide all fields marked *')
|
throw new Error('Please provide all fields marked *')
|
||||||
}
|
}
|
||||||
rememberMe(fields.remember) // FUNCTION TO SAVE USERNAME OF THE USER TO LOCAL STORAGE
|
rememberMe(fields.remember)
|
||||||
delete fields.remember // REMOVING REMEMBER FROM THE PAYLOAD
|
delete fields.remember
|
||||||
return loginUser(fields)
|
return loginUser({ ...fields, turnstileToken })
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
@@ -69,7 +72,7 @@ export default function Login() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(()=>{ // NAVIGATES USER TO HOME PAGE IF USER IS ACTIVE
|
useEffect(()=>{ // NAVIGATES USER TO HOME PAGE IF USER IS CURRENTLY ACTIVE
|
||||||
if(loggedIn){
|
if(loggedIn){
|
||||||
navigate(siteLinks.dash)
|
navigate(siteLinks.dash)
|
||||||
}
|
}
|
||||||
@@ -101,6 +104,14 @@ export default function Login() {
|
|||||||
<input maxLength={25} name='password' value={fields.password} onChange={handleChange} type="password" className="form-control" placeholder="Password" />
|
<input maxLength={25} name='password' value={fields.password} onChange={handleChange} type="password" className="form-control" placeholder="Password" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-center col-12 mt-3">
|
||||||
|
<Turnstile
|
||||||
|
siteKey={process.env.REACT_APP_TURNSTILE_SITE_KEY}
|
||||||
|
onSuccess={setTurnstileToken}
|
||||||
|
onExpire={() => setTurnstileToken(null)}
|
||||||
|
onError={() => setTurnstileToken(null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="d-block d-sm-flex align-items-center">
|
<div className="d-block d-sm-flex align-items-center">
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
@@ -120,12 +131,12 @@ export default function Login() {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
<div className="col-12 mt-3 text-end">
|
<div className="col-12 mt-3 text-end">
|
||||||
<button type='button' onClick={()=>{login.mutate(fields)}} className="btn btn-primary text-uppercase">{login.isPending ? 'loading...' : 'Sign In'}</button>
|
<button type='button' onClick={()=>{login.mutate({...fields, turnstileToken})}} disabled={!turnstileToken || login.isPending} className="btn btn-primary text-uppercase">{login.isPending ? 'loading...' : 'Sign In'}</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 mt-3">
|
<div className="col-12 mt-3">
|
||||||
<p> <Link to={siteLinks.signup}>
|
<p> <Link to={siteLinks.signup}>
|
||||||
{/*<span style={{fontWeight: 'bolder'}}>Sign Up</span>*/}
|
{/*<span style={{fontWeight: 'bolder'}}>Sign Up</span>*/}
|
||||||
<button className="btn btn-warning text-uppercase">
|
<button type='button' className="btn btn-warning text-uppercase">
|
||||||
Sign Up
|
Sign Up
|
||||||
</button>
|
</button>
|
||||||
</Link><span style={{paddingLeft: '5px' , fontWeight: 'bolder'}}> if you don't have an account yet.</span></p>
|
</Link><span style={{paddingLeft: '5px' , fontWeight: 'bolder'}}> if you don't have an account yet.</span></p>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, {useState} from 'react'
|
import React, {useState} from 'react'
|
||||||
import {Form, Formik} from "formik";
|
import {Form, Formik} from "formik";
|
||||||
|
import { Turnstile } from '@marsidev/react-turnstile'
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
|
|
||||||
// import LoginImg from '../../assets/bg/login.svg'
|
// import LoginImg from '../../assets/bg/login.svg'
|
||||||
@@ -33,6 +34,7 @@ const initialValues = {
|
|||||||
firstname: '',
|
firstname: '',
|
||||||
lastname: '',
|
lastname: '',
|
||||||
isChecked: false,
|
isChecked: false,
|
||||||
|
turnstileToken: '',
|
||||||
// username: '',
|
// username: '',
|
||||||
// password: ''
|
// password: ''
|
||||||
};
|
};
|
||||||
@@ -135,7 +137,15 @@ export default function Signup2() {
|
|||||||
onChange={props.handleChange}/>
|
onChange={props.handleChange}/>
|
||||||
<label className="form-check-label"
|
<label className="form-check-label"
|
||||||
htmlFor="gridCheck">
|
htmlFor="gridCheck">
|
||||||
I accept terms & policy
|
I accept{" "}
|
||||||
|
<a
|
||||||
|
href={process.env.REACT_APP_TERMS_LINK}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
terms & policy
|
||||||
|
</a>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
@@ -149,9 +159,17 @@ export default function Signup2() {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
<div className="text-center col-12 mt-3">
|
||||||
|
<Turnstile
|
||||||
|
siteKey={process.env.REACT_APP_TURNSTILE_SITE_KEY}
|
||||||
|
onSuccess={(token) => props.setFieldValue('turnstileToken', token)}
|
||||||
|
onExpire={() => props.setFieldValue('turnstileToken', null)}
|
||||||
|
onError={() => props.setFieldValue('turnstileToken', null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="col-12 mt-3 text-end">
|
<div className="col-12 mt-3 text-end">
|
||||||
<button type='submit'
|
<button type='submit'
|
||||||
|
disabled={!props.values.turnstileToken || mutation.isPending}
|
||||||
className="btn btn-primary text-uppercase">{mutation.isPending ? 'loading...' : 'Sign up'}</button>
|
className="btn btn-primary text-uppercase">{mutation.isPending ? 'loading...' : 'Sign up'}</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
+243
-219
@@ -2,10 +2,10 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||||
import getImage from "../../utils/getImage";
|
import getImage from "../../utils/getImage";
|
||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { commentsData } from "../../services/services";
|
import { commentsData } from "../../services/services";
|
||||||
import queryKeys from "../../services/queryKeys";
|
// import queryKeys from "../../services/queryKeys";
|
||||||
import getCustomTime from "../../utils/getCustomTime";
|
// import getCustomTime from "../../utils/getCustomTime";
|
||||||
|
|
||||||
export default function Comments() {
|
export default function Comments() {
|
||||||
// const {data:contacts, isFetching, isError, error} = useQuery({
|
// const {data:contacts, isFetching, isError, error} = useQuery({
|
||||||
@@ -65,50 +65,50 @@ export default function Comments() {
|
|||||||
const contactsCategory = getContactData?.data?.data?.category; // LIST OF CATEGORY
|
const contactsCategory = getContactData?.data?.data?.category; // LIST OF CATEGORY
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<BreadcrumbComBS title="Comments" paths={["Dashboard", "Comments"]} />
|
<BreadcrumbComBS title="Comments" paths={["Dashboard", "Comments"]} />
|
||||||
{getContactData?.isPending ? (
|
{getContactData?.isPending ? (
|
||||||
<>
|
<>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<p className="text-mute">Loading...</p>
|
<p className="text-mute">Loading...</p>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) : getContactData?.error ? (
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-12">
|
|
||||||
<p className="text-danger">{getContactData?.error?.message}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
</div>
|
||||||
<div className="row">
|
</>
|
||||||
{/*<div className="vh-100 col-12 flex align-items-center">Coming Soon</div>*/}
|
) : getContactData?.error ? (
|
||||||
<div className="col-12">
|
<div className="row">
|
||||||
<div
|
<div className="col-12">
|
||||||
className="card card-statistics mail-contant"
|
<p className="text-danger">{getContactData?.error?.message}</p>
|
||||||
style={{ minHeight: "200px", borderRadius: "10px" }}
|
</div>
|
||||||
>
|
</div>
|
||||||
<div className="card-body p-0">
|
) : (
|
||||||
<div className="row no-gutters">
|
<div className="row">
|
||||||
<div className="col-md-4 col-xxl-2 col-md-4">
|
{/*<div className="vh-100 col-12 flex align-items-center">Coming Soon</div>*/}
|
||||||
<div className="mail-sidebar">
|
<div className="col-12">
|
||||||
<div className="row justify-content-center">
|
<div
|
||||||
<div className="d-none col-12">
|
className="card card-statistics mail-contant"
|
||||||
<div className="text-center mail-sidebar-title px-4">
|
style={{ minHeight: "200px", borderRadius: "10px" }}
|
||||||
<a
|
>
|
||||||
href="#"
|
<div className="card-body p-0">
|
||||||
className="btn btn-primary btn-block py-3 font-weight-bold font-18"
|
<div className="row no-gutters">
|
||||||
>
|
<div className="col-md-4 col-xxl-2 col-md-4">
|
||||||
<i className="fa fa-plus pl-2"></i>
|
<div className="mail-sidebar">
|
||||||
</a>
|
<div className="row justify-content-center">
|
||||||
</div>
|
<div className="d-none col-12">
|
||||||
</div>
|
<div className="text-center mail-sidebar-title px-4">
|
||||||
<div className="col-12">
|
<a
|
||||||
<div className="px-4 py-4">
|
href="#"
|
||||||
<ul className="pl-0">
|
className="btn btn-primary btn-block py-3 font-weight-bold font-18"
|
||||||
<li className="py-2">
|
>
|
||||||
<a href="#">
|
<i className="fa fa-plus pl-2"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="px-4 py-4">
|
||||||
|
<ul className="pl-0">
|
||||||
|
<li className="py-2">
|
||||||
|
<a href="#">
|
||||||
<span className="nav align-items-center">
|
<span className="nav align-items-center">
|
||||||
<span>
|
<span>
|
||||||
<i className="fa fa-envelope-o text-primary pr-4"></i>
|
<i className="fa fa-envelope-o text-primary pr-4"></i>
|
||||||
@@ -122,84 +122,89 @@ export default function Comments() {
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{/*<li className="py-2">*/}
|
{/*<li className="py-2">*/}
|
||||||
{/* <a href="#">*/}
|
{/* <a href="#">*/}
|
||||||
{/* <span*/}
|
{/* <span*/}
|
||||||
{/* className="nav align-items-center">*/}
|
{/* className="nav align-items-center">*/}
|
||||||
{/* <span>*/}
|
{/* <span>*/}
|
||||||
{/* <i className="fa fa-paper-plane-o pr-4"></i>*/}
|
{/* <i className="fa fa-paper-plane-o pr-4"></i>*/}
|
||||||
{/* </span>*/}
|
{/* </span>*/}
|
||||||
{/* <span>*/}
|
{/* <span>*/}
|
||||||
{/* <span>Replied Mail</span>*/}
|
{/* <span>Replied Mail</span>*/}
|
||||||
{/* </span>*/}
|
{/* </span>*/}
|
||||||
{/* </span>*/}
|
{/* </span>*/}
|
||||||
{/* </a>*/}
|
{/* </a>*/}
|
||||||
{/*</li>*/}
|
{/*</li>*/}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul className="pl-0 mt-5">
|
<ul className="pl-0 mt-5">
|
||||||
<li
|
<li
|
||||||
className="py-2"
|
className="py-2"
|
||||||
onClick={() => changeActiveCategoryUID("0")}
|
onClick={() => changeActiveCategoryUID("0")}
|
||||||
style={{ cursor: "pointer" }}
|
style={{ cursor: "pointer" }}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<span className="nav align-items-center">
|
<span className="nav align-items-center">
|
||||||
<span>
|
<span>
|
||||||
<i
|
<i
|
||||||
className={`fa fa-circle-o pr-4 ${
|
className={`fa fa-circle-o pr-4 ${
|
||||||
activeCategoryUID == "0"
|
activeCategoryUID == "0"
|
||||||
? "text-primary"
|
? "text-primary"
|
||||||
: "text-warning"
|
: "text-warning"
|
||||||
}`}
|
}`}
|
||||||
></i>
|
></i>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<span>All</span>
|
<span>All</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{contactsCategory &&
|
{contactsCategory &&
|
||||||
contactsCategory.map((item) => (
|
contactsCategory.map((item) => (
|
||||||
<li
|
<li
|
||||||
key={item?.cid}
|
key={item?.cid}
|
||||||
className="py-2"
|
className="py-2"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
changeActiveCategoryUID(`${item?.cid}`)
|
changeActiveCategoryUID(`${item?.cid}`)
|
||||||
}
|
}
|
||||||
style={{ cursor: "pointer" }}
|
style={{ cursor: "pointer" }}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<span className="nav align-items-center">
|
<span className="nav align-items-center">
|
||||||
<span>
|
<span>
|
||||||
<i
|
<i
|
||||||
className={`fa fa-circle-o pr-4 ${
|
className={`fa fa-circle-o pr-4 ${
|
||||||
activeCategoryUID ==
|
activeCategoryUID ==
|
||||||
`${item?.cid}`
|
`${item?.cid}`
|
||||||
? "text-primary"
|
? "text-primary"
|
||||||
: "text-warning"
|
: "text-warning"
|
||||||
}`}
|
}`}
|
||||||
></i>
|
></i>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<span>{item?.description}</span>
|
<span>{item?.description}</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`${filteredContactData.length > 0 ? 'col-md-8 col-xxl-4' : 'col-md-8 col-xxl-10'} border-md-t`}>
|
</div>
|
||||||
<div className="mail-content border-right border-n h-100" style={{placeContent: 'center'}}>
|
</div>
|
||||||
{/* <div className="mail-search border-bottom">
|
<div
|
||||||
|
className={`${filteredContactData.length > 0 ? "col-md-8 col-xxl-4" : "col-md-8 col-xxl-10"} border-md-t`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="mail-content border-right border-n h-100"
|
||||||
|
style={{ placeContent: "center" }}
|
||||||
|
>
|
||||||
|
{/* <div className="mail-search border-bottom">
|
||||||
<div className="row align-items-center mx-0">
|
<div className="row align-items-center mx-0">
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="form-group pt-3">
|
<div className="form-group pt-3">
|
||||||
@@ -209,141 +214,160 @@ export default function Comments() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> */}
|
</div> */}
|
||||||
<div className="mail-msg scrollbar scroll_dark">
|
<div className="mail-msg scrollbar scroll_dark">
|
||||||
{ filteredContactData.length ?
|
{filteredContactData.length ? (
|
||||||
filteredContactData?.map((contact, index) => {
|
filteredContactData?.map((contact, index) => {
|
||||||
const isActive =
|
const isActive =
|
||||||
contact?.uid == activeContactUID ||
|
contact?.uid == activeContactUID ||
|
||||||
(!activeContactUID && index == 0);
|
(!activeContactUID && index == 0);
|
||||||
const avtarImage =
|
const avtarImage =
|
||||||
contact?.category === undefined
|
contact?.category === undefined
|
||||||
? "avtar/01.jpg"
|
? "avtar/01.jpg"
|
||||||
: "avtar/" + contact.category + ".png";
|
: "avtar/" + contact.category + ".png";
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={contact?.uid}
|
key={contact?.uid}
|
||||||
onClick={() => changeActiveUID(contact?.uid)}
|
onClick={() => changeActiveUID(contact?.uid)}
|
||||||
className={`mail-msg-item ${
|
className={`mail-msg-item ${
|
||||||
isActive && "bg-light"
|
isActive && "bg-light"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<a href="#">
|
<a href="#">
|
||||||
<div className="media align-items-center">
|
<div className="media align-items-center">
|
||||||
<div className="mr-3">
|
<div className="mr-3">
|
||||||
<div className="bg-img">
|
<div className="bg-img">
|
||||||
<img
|
<img
|
||||||
src={getImage(avtarImage)}
|
src={getImage(avtarImage)}
|
||||||
className="img-fluid"
|
className="img-fluid"
|
||||||
alt="user"
|
alt="user"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-100">
|
<div className="w-100">
|
||||||
<div className="mail-msg-item-titel justify-content-between">
|
<div className="mail-msg-item-titel justify-content-between">
|
||||||
<p>
|
<p>
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
fontSize: "14px",
|
fontSize: "14px",
|
||||||
color: "#148399",
|
color: "#148399",
|
||||||
fontWeight: "bolder",
|
fontWeight: "bolder",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{contact?.sender}
|
{contact?.sender}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
{/* <p className="d-none d-xl-block">06:59 <span> PM </span></p> */}
|
{/* <p className="d-none d-xl-block">06:59 <span> PM </span></p> */}
|
||||||
<p className="d-none d-xl-block">
|
<p className="d-none d-xl-block">
|
||||||
<span style={{ fontSize: "14px" }}>
|
<span style={{ fontSize: "14px" }}>
|
||||||
{new Date(
|
{new Date(
|
||||||
contact?.added
|
contact?.added,
|
||||||
).toDateString()}
|
).toDateString()}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<h5 className="mb-0 my-2">
|
<h5 className="mb-0 my-2">
|
||||||
{contact?.title}
|
{contact?.title}
|
||||||
</h5>
|
</h5>
|
||||||
<p>
|
<p>
|
||||||
{contact?.message?.length < 100
|
{contact?.message?.length < 100
|
||||||
? contact?.message
|
? contact?.message
|
||||||
: contact?.message.substring(0, 101) +
|
: contact?.message.substring(0, 101) +
|
||||||
" ..."}
|
" ..."}
|
||||||
</p>
|
</p>
|
||||||
<p className="d-xl-none">
|
<p className="d-xl-none">
|
||||||
<span>
|
<span>
|
||||||
{new Date(
|
{new Date(
|
||||||
contact?.added
|
contact?.added,
|
||||||
).toDateString()}
|
).toDateString()}
|
||||||
{/* {getCustomTime(contact.added)} */}
|
{/* {getCustomTime(contact.added)} */}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
:
|
) : (
|
||||||
<p className="text-center">Messages will appear here as soon as they are available for selection</p>
|
<p className="text-center">
|
||||||
}
|
Messages will appear here as soon as they are
|
||||||
</div>
|
available for selection
|
||||||
</div>
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{filteredContactData.length > 0 &&
|
|
||||||
<div className="col-xxl-6 border-t border-xxl-t">
|
|
||||||
<div className="mail-chat py-5 px-5">
|
|
||||||
<div className="media align-items-center">
|
|
||||||
<div className="bg-img mr-3">
|
|
||||||
<img
|
|
||||||
src={activeContactUID ? getImage("avtar/" + activeDetail[0].category + ".png") : getImage(filteredContactData[0] == undefined ? "avtar/01.jpg": "avtar/" + filteredContactData[0].category + ".png")}
|
|
||||||
className="img-fluid"
|
|
||||||
alt="user"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 className="mb-0" style={{ color: "#148399" }}>
|
|
||||||
{activeContactUID
|
|
||||||
? activeDetail[0]?.sender
|
|
||||||
: filteredContactData[0]?.sender}
|
|
||||||
</h4>
|
|
||||||
<p>
|
|
||||||
{activeContactUID
|
|
||||||
? new Date(activeDetail[0]?.added).toDateString()
|
|
||||||
: new Date(
|
|
||||||
filteredContactData[0]?.added
|
|
||||||
).toDateString()}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 d-flex justify-content-between">
|
|
||||||
<div>
|
|
||||||
<h3>
|
|
||||||
{activeContactUID
|
|
||||||
? activeDetail[0]?.title
|
|
||||||
: filteredContactData[0]?.title}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div className="d-flex">
|
|
||||||
{/*<a href="javascript:void(0)"><i className="fa fa-reply font-22 pr-3"></i></a>*/}
|
|
||||||
{/*<a href="javascript:void(0)"><i className="fa fa-print font-22"></i></a>*/}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
{activeContactUID
|
|
||||||
? activeDetail[0]?.message
|
|
||||||
: filteredContactData[0]?.message}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{filteredContactData.length > 0 && (
|
||||||
|
<div className="col-xxl-6 border-t border-xxl-t">
|
||||||
|
<div className="mail-chat py-5 px-5">
|
||||||
|
<div className="media align-items-center">
|
||||||
|
<div className="bg-img mr-3">
|
||||||
|
<img
|
||||||
|
src={
|
||||||
|
activeContactUID
|
||||||
|
? getImage(
|
||||||
|
"avtar/" +
|
||||||
|
activeDetail[0].category +
|
||||||
|
".png",
|
||||||
|
)
|
||||||
|
: getImage(
|
||||||
|
filteredContactData[0] == undefined
|
||||||
|
? "avtar/01.jpg"
|
||||||
|
: "avtar/" +
|
||||||
|
filteredContactData[0].category +
|
||||||
|
".png",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className="img-fluid"
|
||||||
|
alt="user"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="mb-0" style={{ color: "#148399" }}>
|
||||||
|
{activeContactUID
|
||||||
|
? activeDetail[0]?.sender
|
||||||
|
: filteredContactData[0]?.sender}
|
||||||
|
</h4>
|
||||||
|
<p>
|
||||||
|
{activeContactUID
|
||||||
|
? new Date(
|
||||||
|
activeDetail[0]?.added,
|
||||||
|
).toDateString()
|
||||||
|
: new Date(
|
||||||
|
filteredContactData[0]?.added,
|
||||||
|
).toDateString()}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4 d-flex justify-content-between">
|
||||||
|
<div>
|
||||||
|
<h3>
|
||||||
|
{activeContactUID
|
||||||
|
? activeDetail[0]?.title
|
||||||
|
: filteredContactData[0]?.title}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div className="d-flex">
|
||||||
|
{/*<a href="javascript:void(0)"><i className="fa fa-reply font-22 pr-3"></i></a>*/}
|
||||||
|
{/*<a href="javascript:void(0)"><i className="fa fa-print font-22"></i></a>*/}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
{activeContactUID
|
||||||
|
? activeDetail[0]?.message
|
||||||
|
: filteredContactData[0]?.message}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
</>
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default function UserFooter(){
|
|||||||
<p>© Copyright {year}. All rights reserved.</p>
|
<p>© Copyright {year}. All rights reserved.</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="col col-sm-6 ml-sm-auto text-center text-sm-right">
|
<div className="col col-sm-6 ml-sm-auto text-center text-sm-right">
|
||||||
<p>A division of autoMedSys A.I.</p>
|
<p>A division of MERMS(AI)</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -1,130 +1,166 @@
|
|||||||
import React, {memo, useState} from 'react'
|
import React, { useState } from "react";
|
||||||
import getImage from "../../../utils/getImage";
|
//import getImage from "../../../utils/getImage";
|
||||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
import queryKeys from '../../../services/queryKeys';
|
import queryKeys from "../../../services/queryKeys";
|
||||||
import {getTemplateConfig} from '../../../services/services';
|
import { getTemplateConfig } from "../../../services/services";
|
||||||
import {Link} from "react-router-dom";
|
//import {Link} from "react-router-dom";
|
||||||
import siteLinks from "../../../links/siteLinks";
|
//import siteLinks from "../../../links/siteLinks";
|
||||||
import UploadModal from './UploadModal';
|
import UploadModal from "./UploadModal";
|
||||||
|
|
||||||
const TemplateConfigure = ({productData}) => {
|
const TemplateConfigure = ({ productData }) => {
|
||||||
|
const [selectedSectionDetails, setSelectedSectionDetails] = useState({});
|
||||||
|
|
||||||
const [selectedSectionDetails, setSelectedSectionDetails] = useState({})
|
const {
|
||||||
|
data: templateData,
|
||||||
|
isFetching,
|
||||||
|
isError,
|
||||||
|
error,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: queryKeys.myTemplateConfig,
|
||||||
|
queryFn: () => {
|
||||||
|
let reqData = {
|
||||||
|
token: localStorage.getItem("token"), // USER TOKEN
|
||||||
|
uid: localStorage.getItem("uid"), // USER UID
|
||||||
|
product_id: productData?.product_id,
|
||||||
|
};
|
||||||
|
return getTemplateConfig(reqData);
|
||||||
|
},
|
||||||
|
staleTime: 0,
|
||||||
|
});
|
||||||
|
|
||||||
// /panel/myproduct/template-config
|
const templateResponse = templateData?.data;
|
||||||
|
const templateImages = Array.isArray(templateResponse?.template_images?.data)
|
||||||
|
? templateResponse.template_images.data
|
||||||
|
: [];
|
||||||
|
console.log("templateResponse", templateResponse);
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
return (
|
||||||
|
<>
|
||||||
|
<div className="card card-statistics">
|
||||||
|
{isFetching ? (
|
||||||
|
<>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<p className="text-mute">Loading...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : isError ? (
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<p className="text-danger">{error?.message}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="card-header">
|
||||||
|
<div className="card-heading">
|
||||||
|
<h4 className="card-title" style={{ textTransform: "none" }}>
|
||||||
|
{templateResponse?.template_name}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
const {data: templateData, isFetching, isError, error} = useQuery({
|
<div>
|
||||||
queryKey: queryKeys.myTemplateConfig,
|
<div className="col-12">
|
||||||
queryFn: () => {
|
<div>
|
||||||
let reqData = {
|
<div>
|
||||||
token: localStorage.getItem('token'), // USER TOKEN
|
<div>
|
||||||
uid: localStorage.getItem('uid'), // USER UID
|
<h4>Image List</h4>
|
||||||
product_id: productData?.product_id
|
|
||||||
}
|
|
||||||
return getTemplateConfig(reqData)
|
|
||||||
},
|
|
||||||
staleTime: 0
|
|
||||||
})
|
|
||||||
|
|
||||||
const templateResponse = templateData?.data
|
|
||||||
const templateImages = templateResponse?.template_images?.data;
|
|
||||||
// debugger;
|
|
||||||
console.log("templateResponse", templateResponse);
|
|
||||||
// const currentColorUID = templateResponse?.current_colorstyle_uid
|
|
||||||
// const color_styles = templateResponse?.color_styles
|
|
||||||
// const custom_template_name = templateResponse?.custom_template_name
|
|
||||||
|
|
||||||
return <>
|
|
||||||
<div className="card card-statistics">
|
|
||||||
{isFetching ?
|
|
||||||
<>
|
|
||||||
<div className="row">
|
|
||||||
<div className="col-12">
|
|
||||||
<p className='text-mute'>Loading...</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
: isError ?
|
<div>
|
||||||
<div className="row">
|
<ul className="list-unstyled">
|
||||||
<div className="col-12">
|
{templateImages &&
|
||||||
<p className='text-danger'>{error?.message}</p>
|
templateImages.map((item) => {
|
||||||
</div>
|
const currImage = item?.default_val;
|
||||||
</div>
|
return (
|
||||||
:
|
<li className="media">
|
||||||
<>
|
<div
|
||||||
<div className="card-header">
|
style={{
|
||||||
<div className="card-heading">
|
display: "flex",
|
||||||
<h4 className="card-title"
|
flexDirection: "row",
|
||||||
style={{textTransform: 'none'}}>{templateResponse?.template_name}</h4>
|
padding: "5px",
|
||||||
</div>
|
backgroundColor: "aliceblue",
|
||||||
</div>
|
margin: "2px",
|
||||||
|
maxHeight: "150px",
|
||||||
|
width: "100%",
|
||||||
<div>
|
}}
|
||||||
<div className="col-12">
|
>
|
||||||
<div>
|
<div
|
||||||
<div>
|
className="d-flex justify-content-center align-items-center"
|
||||||
<div>
|
style={{
|
||||||
<h4>Image List</h4>
|
padding: "6px",
|
||||||
</div>
|
width: "120px",
|
||||||
</div>
|
height: "100px",
|
||||||
<div>
|
}}
|
||||||
<ul className="list-unstyled">
|
>
|
||||||
{templateImages && templateImages.map(
|
<img
|
||||||
(item) => {
|
className="mb-xxs-0 img-fluid"
|
||||||
const currImage = item?.default_val;
|
style={{
|
||||||
return (
|
height: "auto",
|
||||||
<li className="media">
|
maxHeight: "100px",
|
||||||
<div style={{
|
}}
|
||||||
display: 'flex',
|
src={currImage}
|
||||||
flexDirection: 'row',
|
alt="image"
|
||||||
padding: '5px',
|
/>
|
||||||
backgroundColor: 'aliceblue',
|
|
||||||
margin: '2px',
|
|
||||||
maxHeight: '150px'
|
|
||||||
}}>
|
|
||||||
<div className='d-flex justify-content-center align-items-center' style={{padding: '6px', width: '120px', height: '100px'}}>
|
|
||||||
<img className="mb-xxs-0 img-fluid"
|
|
||||||
style={{height: 'auto', maxHeight: '100px'}}
|
|
||||||
src={currImage} alt="image"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="media-body" style={{padding: '2px'}}>
|
|
||||||
<div style={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column'
|
|
||||||
}}>
|
|
||||||
<div style={{textAlign: 'right',width: '100%'}}></div>
|
|
||||||
{/* [Change Image] */}
|
|
||||||
<label onClick={()=>setSelectedSectionDetails(item)} className='w-100 text-end' data-bs-toggle="modal" data-bs-target="#verticalCenter" style={{cursor: 'pointer'}}>[Change Image]</label>
|
|
||||||
{/* <input id={item?.id} name={item?.id} className="d-none form-control form-control-sm" type="file" onChange={handleFileChange}/> */}
|
|
||||||
<div>
|
|
||||||
<h5 className="mt-0 mb-1">{item?.name}</h5>
|
|
||||||
{item?.description}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</>
|
<div
|
||||||
|
className="media-body"
|
||||||
|
style={{ padding: "2px" }}
|
||||||
} </div>
|
>
|
||||||
<UploadModal productId={productData?.product_id} selectedSectionDetails={selectedSectionDetails} />
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
textAlign: "right",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
{/* [Change Image] */}
|
||||||
|
<label
|
||||||
|
onClick={() =>
|
||||||
|
setSelectedSectionDetails(item)
|
||||||
|
}
|
||||||
|
className="w-100 text-end"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#verticalCenter"
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
[Change Image]
|
||||||
|
</label>
|
||||||
|
{/* <input id={item?.id} name={item?.id} className="d-none form-control form-control-sm" type="file" onChange={handleFileChange}/> */}
|
||||||
|
<div>
|
||||||
|
<h5 className="mt-0 mb-1">
|
||||||
|
{item?.name}
|
||||||
|
</h5>
|
||||||
|
{item?.description}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}{" "}
|
||||||
|
</div>
|
||||||
|
<UploadModal
|
||||||
|
productId={productData?.product_id}
|
||||||
|
selectedSectionDetails={selectedSectionDetails}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
}
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default TemplateConfigure
|
export default TemplateConfigure;
|
||||||
|
|||||||
@@ -1,141 +1,196 @@
|
|||||||
import {Form, Formik} from "formik";
|
import { Form, Formik } from "formik";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import {useMutation} from '@tanstack/react-query';
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import {setExternalURL} from '../../../services/services';
|
import { setExternalURL } from "../../../services/services";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
url: Yup.string().required("URL is required").matches(/^https?:\/\/[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-]+\.[a-zA-Z]+/, 'Must be like: https://example.mysite.com'),
|
url: Yup.string()
|
||||||
})
|
.required("URL is required")
|
||||||
|
.matches(
|
||||||
|
/^https?:\/\/[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-]+\.[a-zA-Z]+/,
|
||||||
|
"Must be like: https://example.mysite.com",
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
// const initialValues = {
|
// const initialValues = {
|
||||||
// url: '',
|
// url: '',
|
||||||
// };
|
// };
|
||||||
|
|
||||||
const URLConfiguration = ({productData}) => {
|
const URLConfiguration = ({ productData }) => {
|
||||||
|
const [externalURLChanged, setExternalURLChanged] = useState(true);
|
||||||
|
|
||||||
const [externalURLChanged, setExternalURLChanged] = useState(true)
|
const initialValues = {
|
||||||
|
url: productData?.external_url || "",
|
||||||
|
};
|
||||||
|
|
||||||
const initialValues = {
|
let defaultUrl = "https://" + productData?.internal_url;
|
||||||
url: productData?.external_url || '',
|
let externalUrl = productData?.external_url;
|
||||||
|
|
||||||
|
const handleExternalURLChanged = (e) => {
|
||||||
|
if (e.target.value == externalUrl) {
|
||||||
|
setExternalURLChanged(true);
|
||||||
|
} else {
|
||||||
|
setExternalURLChanged(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// API to set url
|
||||||
|
const setURL = useMutation({
|
||||||
|
mutationFn: (fields) => {
|
||||||
|
return setExternalURL(fields);
|
||||||
|
},
|
||||||
|
onSuccess: (res) => {
|
||||||
|
if (res.data.resultCode != "0") {
|
||||||
|
// throw({message: res?.data?.resultDescription})
|
||||||
|
throw { message: "Something went wrong!" };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSettled: () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
setURL.reset();
|
||||||
|
}, 3000);
|
||||||
|
},
|
||||||
|
// onError: (err) => {
|
||||||
|
// console.log('err', err)
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSubmit = (values) => {
|
||||||
|
let reqData = {
|
||||||
|
token: localStorage.getItem("token"), // USER TOKEN
|
||||||
|
uid: localStorage.getItem("uid"), // USER UID
|
||||||
|
subscription_uid: productData?.subscription_uid,
|
||||||
|
external_url: values.url,
|
||||||
};
|
};
|
||||||
|
setURL.mutate(reqData);
|
||||||
|
};
|
||||||
|
|
||||||
let defaultUrl = 'https://' + productData?.internal_url
|
return (
|
||||||
let externalUrl = productData?.external_url
|
<>
|
||||||
|
<div className="card card-statistics">
|
||||||
const handleExternalURLChanged = (e) => {
|
<div className="card-header">
|
||||||
if(e.target.value == externalUrl){
|
<div className="card-heading">
|
||||||
setExternalURLChanged(true)
|
<h4 className="card-title" style={{ textTransform: "none" }}>
|
||||||
}else{
|
{defaultUrl}
|
||||||
setExternalURLChanged(false)
|
</h4>
|
||||||
}
|
</div>
|
||||||
}
|
|
||||||
|
|
||||||
// API to set url
|
|
||||||
const setURL = useMutation({
|
|
||||||
mutationFn: (fields) => {
|
|
||||||
return setExternalURL(fields)
|
|
||||||
},
|
|
||||||
onSuccess: (res) => {
|
|
||||||
if (res.data.resultCode != '0') {
|
|
||||||
// throw({message: res?.data?.resultDescription})
|
|
||||||
throw({message: 'Something went wrong!'})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSettled: () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
setURL.reset()
|
|
||||||
}, 3000)
|
|
||||||
}
|
|
||||||
// onError: (err) => {
|
|
||||||
// console.log('err', err)
|
|
||||||
// }
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleSubmit = (values) => {
|
|
||||||
let reqData = {
|
|
||||||
token: localStorage.getItem('token'), // USER TOKEN
|
|
||||||
uid: localStorage.getItem('uid'), // USER UID
|
|
||||||
subscription_uid: productData?.subscription_uid,
|
|
||||||
external_url: values.url
|
|
||||||
}
|
|
||||||
setURL.mutate(reqData)
|
|
||||||
}
|
|
||||||
|
|
||||||
return <>
|
|
||||||
<div className="card card-statistics">
|
|
||||||
<div className="card-header">
|
|
||||||
<div className="card-heading">
|
|
||||||
<h4 className="card-title" style={{textTransform: 'none'}}>{defaultUrl}</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/*<div className="card-body">*/}
|
|
||||||
{/* <div className="form-group">*/}
|
|
||||||
{/* /!*<label htmlFor="exampleInputEmail1">Email address</label>*!/*/}
|
|
||||||
{/* <input type="email" className="form-control"*/}
|
|
||||||
{/* aria-describedby="defaultUrlHelp" value={defaultUrl} readOnly={true} />*/}
|
|
||||||
{/* </div>*/}
|
|
||||||
{/*</div>*/}
|
|
||||||
</div>
|
</div>
|
||||||
|
{/*<div className="card-body">*/}
|
||||||
|
{/* <div className="form-group">*/}
|
||||||
|
{/* /!*<label htmlFor="exampleInputEmail1">Email address</label>*!/*/}
|
||||||
|
{/* <input type="email" className="form-control"*/}
|
||||||
|
{/* aria-describedby="defaultUrlHelp" value={defaultUrl} readOnly={true} />*/}
|
||||||
|
{/* </div>*/}
|
||||||
|
{/*</div>*/}
|
||||||
|
</div>
|
||||||
|
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
{(props) => {
|
{(props) => {
|
||||||
return (
|
return (
|
||||||
<Form className='w-full'>
|
<Form className="w-full">
|
||||||
<div className="card card-statistics" style={{backgroundColor: '#b6e5ef'}}>
|
<div
|
||||||
<div className="card-header">
|
className="card card-statistics"
|
||||||
<div className="card-heading">
|
style={{ backgroundColor: "#b6e5ef" }}
|
||||||
<h4 className="card-title" style={{textTransform: 'none'}}>Set your own URL</h4>
|
>
|
||||||
</div>
|
<div className="card-header">
|
||||||
</div>
|
<div className="card-heading">
|
||||||
<div className="card-body">
|
<h4
|
||||||
<div className="form-group">
|
className="card-title"
|
||||||
<label htmlFor="exampleInputEmail1">Enter your full URL <span
|
style={{ textTransform: "none" }}
|
||||||
className={`${(props.errors.url && props.touched.url) && 'text-danger'}`}>{props.errors.url}</span></label>
|
>
|
||||||
<input value={props.values.url} onChange={(e)=>{props.handleChange(e); handleExternalURLChanged(e)}} type="text"
|
Set your own URL
|
||||||
className="form-control" id="url" aria-describedby="url"
|
</h4>
|
||||||
placeholder="https://example.mysite.com"/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{width: '100%', textAlign: 'right'}}>
|
<div className="card-body">
|
||||||
<button
|
<div className="form-group">
|
||||||
type="submit"
|
<label htmlFor="exampleInputEmail1">
|
||||||
disabled={setURL.isPending || externalURLChanged}
|
Enter your full URL{" "}
|
||||||
className="btn btn-primary"
|
<span
|
||||||
>
|
className={`${props.errors.url && props.touched.url && "text-danger"}`}
|
||||||
{setURL.isPending ? 'Loading...' : 'Submit'}
|
>
|
||||||
</button>
|
{props.errors.url}
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</label>
|
||||||
|
<input
|
||||||
|
value={props.values.url}
|
||||||
|
onChange={(e) => {
|
||||||
|
props.handleChange(e);
|
||||||
|
handleExternalURLChanged(e);
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
id="url"
|
||||||
|
aria-describedby="url"
|
||||||
|
placeholder="https://example.mysite.com"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ width: "100%", textAlign: "right" }}>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={setURL.isPending || externalURLChanged}
|
||||||
|
className="btn btn-primary"
|
||||||
|
>
|
||||||
|
{setURL.isPending ? "Loading..." : "Submit"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{setURL.error &&
|
{setURL.error && (
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<p className='text-danger'>{setURL.error.message}</p>
|
<p className="text-danger">{setURL.error.message}</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
)}
|
||||||
|
|
||||||
{setURL.isSuccess &&
|
|
||||||
<div className="col-12">
|
|
||||||
<p className='text-success'>{'Completed successfully'}</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div style={{backgroundColor: '#94b8c0', borderRadius: '10px', padding: '10px'}}>
|
|
||||||
Final steps to configure your URL:<br/>
|
|
||||||
DNS:<br/>
|
|
||||||
DNS:<br/>
|
|
||||||
DNS:<br/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Formik>
|
|
||||||
|
|
||||||
|
{setURL.isSuccess && (
|
||||||
|
<div className="col-12">
|
||||||
|
<p className="text-success">{"Completed successfully"}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: "#148399",
|
||||||
|
borderRadius: "10px",
|
||||||
|
padding: "10px",
|
||||||
|
color: "white",
|
||||||
|
fontWeight: "bolder",
|
||||||
|
fontSize: "14px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
To link your domain to your website, update your DNS record to
|
||||||
|
point to our hosting provider.
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
Enter the following DNS servers in your domain settings
|
||||||
|
<br />
|
||||||
|
{process.env.REACT_APP_DNS1}
|
||||||
|
<br />
|
||||||
|
{process.env.REACT_APP_DNS2}
|
||||||
|
<hr />
|
||||||
|
<Link
|
||||||
|
target="_blank"
|
||||||
|
to={process.env.REACT_APP_DNS_LINK}
|
||||||
|
style={{ color: "#f6f5f6" }}
|
||||||
|
>
|
||||||
|
Click here for detailed instructions.
|
||||||
|
</Link>
|
||||||
|
<hr />
|
||||||
|
After updating your DNS settings, click “Start Verification.”
|
||||||
|
You will receive a status notification within 24 hours.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Formik>
|
||||||
</>
|
</>
|
||||||
}
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default URLConfiguration
|
export default URLConfiguration;
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ export default function ProfileForm({data}) {
|
|||||||
const handleSetInfoToUpdate = (values, helpers) => {
|
const handleSetInfoToUpdate = (values, helpers) => {
|
||||||
delete values.email
|
delete values.email
|
||||||
delete values.country
|
delete values.country
|
||||||
|
delete values?.picture
|
||||||
setInfoToUpdate(values)
|
setInfoToUpdate(values)
|
||||||
var modal = new Modal(document.getElementById('modal'));
|
var modal = new Modal(document.getElementById('modal'));
|
||||||
modal.show();
|
modal.show();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useMemo, useState } from "react";
|
import React, { useMemo, useState } from "react";
|
||||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||||
import getImage from "../../utils/getImage";
|
//import getImage from "../../utils/getImage";
|
||||||
import queryKeys from "../../services/queryKeys";
|
import queryKeys from "../../services/queryKeys";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { profileDetails } from "../../services/services";
|
import { profileDetails } from "../../services/services";
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import ReactDOM from 'react-dom/client';
|
|||||||
import { BrowserRouter } from 'react-router-dom';
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import App from './App';
|
import App from './App';
|
||||||
//import reportWebVitals from './reportWebVitals';
|
|
||||||
import 'bootstrap/dist/css/bootstrap.css';
|
import 'bootstrap/dist/css/bootstrap.css';
|
||||||
import 'bootstrap/dist/js/bootstrap.min.js'
|
import 'bootstrap/dist/js/bootstrap.min.js'
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ const postAuxEnd = (path, postData, media=false) => {
|
|||||||
return axios.post(`${basePath}${path}`, newPostData).then(res => {
|
return axios.post(`${basePath}${path}`, newPostData).then(res => {
|
||||||
return res
|
return res
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
// throw new Error(err.response.data.error_message);
|
throw new Error(err.response.data.error_message);
|
||||||
throw new Error(err);
|
// throw new Error(err);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user