irongit

'can see create by in meeting'

huncholanehuncholaneauthored
parent fe636a2commit 455f345f9a4dff3996fa8a82ff78ced0487b2e1aBrowse files

5 files changed, +983 -481

+307-161Client/src/views/admin/meeting/View.js
@@ -1,4 +1,12 @@
1-import { Box, Button, Flex, Grid, GridItem, Heading, Text } from "@chakra-ui/react";
1+import {
2+ Box,
3+ Button,
4+ Flex,
5+ Grid,
6+ GridItem,
7+ Heading,
8+ Text,
9+} from "@chakra-ui/react";
210 import Card from "components/card/Card";
311 import { HSeparator } from "components/separator/Separator";
412 import Spinner from "components/spinner/Spinner";
@@ -14,180 +22,318 @@ import CommonDeleteModel from "components/commonDeleteModel";
1422 import { FaFilePdf } from "react-icons/fa";
1523 import html2pdf from "html2pdf.js";
1624 const View = () => {
25+ const param = useParams();
1726
18- const param = useParams()
27+ const [data, setData] = useState();
28+ const [deleteMany, setDeleteMany] = useState(false);
29+ const user = JSON.parse(localStorage.getItem("user"));
30+ const [isLoding, setIsLoding] = useState(false);
31+ const [loading, setLoading] = useState(false);
32+ const navigate = useNavigate();
33+ const params = useParams();
1934
20- const [data, setData] = useState()
21- const [deleteMany, setDeleteMany] = useState(false);
22- const user = JSON.parse(localStorage.getItem("user"))
23- const [isLoding, setIsLoding] = useState(false)
24- const [loading, setLoading] = useState(false)
25- const navigate = useNavigate()
26- const params = useParams();
35+ const fetchData = async () => {
36+ setIsLoding(true);
37+ let response = await getApi("api/meeting/view/", param.id);
38+ setData(response?.data);
39+ setIsLoding(false);
40+ };
2741
42+ useEffect(() => {
43+ fetchData();
44+ }, []);
2845
29- const fetchData = async () => {
30- setIsLoding(true)
31- let response = await getApi('api/meeting/view/', param.id)
32- setData(response?.data);
33- setIsLoding(false)
46+ const generatePDF = () => {
47+ setLoading(true);
48+ const element = document.getElementById("reports");
49+ const hideBtn = document.getElementById("hide-btn");
50+ if (element) {
51+ hideBtn.style.display = "none";
52+ html2pdf()
53+ .from(element)
54+ .set({
55+ margin: [0, 0, 0, 0],
56+ filename: `Meeting_Details_${moment().format("DD-MM-YYYY")}.pdf`,
57+ image: { type: "jpeg", quality: 0.98 },
58+ html2canvas: { scale: 2, useCORS: true, allowTaint: true },
59+ jsPDF: { unit: "in", format: "letter", orientation: "portrait" },
60+ })
61+ .save()
62+ .then(() => {
63+ setLoading(false);
64+ hideBtn.style.display = "";
65+ });
66+ // }, 500);
67+ } else {
68+ console.error("Element with ID 'reports' not found.");
69+ setLoading(false);
3470 }
71+ };
3572
36- useEffect(() => {
37- fetchData()
38- }, [])
39-
40- const generatePDF = () => {
41- setLoading(true)
42- const element = document.getElementById("reports");
43- const hideBtn = document.getElementById("hide-btn");
44- if (element) {
45- hideBtn.style.display = 'none';
46- html2pdf()
47- .from(element)
48- .set({
49- margin: [0, 0, 0, 0],
50- filename: `Meeting_Details_${moment().format("DD-MM-YYYY")}.pdf`,
51- image: { type: "jpeg", quality: 0.98 },
52- html2canvas: { scale: 2, useCORS: true, allowTaint: true },
53- jsPDF: { unit: "in", format: "letter", orientation: "portrait" },
54- })
55- .save().then(() => {
56- setLoading(false)
57- hideBtn.style.display = '';
58- })
59- // }, 500);
60- } else {
61- console.error("Element with ID 'reports' not found.");
62- setLoading(false)
63- }
64- };
65-
66- const handleDeleteMeeting = async (ids) => {
67- try {
68- setIsLoding(true)
69- let response = await deleteApi('api/meeting/delete/', params.id)
70- if (response.status === 200) {
71- setDeleteMany(false)
72- navigate(-1)
73- }
74- } catch (error) {
75- console.log(error)
76- }
77- finally {
78- setIsLoding(false)
79- }
73+ const handleDeleteMeeting = async (ids) => {
74+ try {
75+ setIsLoding(true);
76+ let response = await deleteApi("api/meeting/delete/", params.id);
77+ if (response.status === 200) {
78+ setDeleteMany(false);
79+ navigate(-1);
80+ }
81+ } catch (error) {
82+ console.log(error);
83+ } finally {
84+ setIsLoding(false);
8085 }
86+ };
8187
82- const [permission, contactAccess, leadAccess] = HasAccess(['Meetings', 'Contacts', 'Leads'])
88+ const [permission, contactAccess, leadAccess] = HasAccess([
89+ "Meetings",
90+ "Contacts",
91+ "Leads",
92+ ]);
8393
84- return (
94+ return (
95+ <>
96+ {isLoding ? (
97+ <Flex justifyContent={"center"} alignItems={"center"} width="100%">
98+ <Spinner />
99+ </Flex>
100+ ) : (
85101 <>
86- {isLoding ?
87- <Flex justifyContent={'center'} alignItems={'center'} width="100%" >
88- <Spinner />
89- </Flex> : <>
90-
91- <Grid templateColumns="repeat(4, 1fr)" gap={3} id="reports">
92- <GridItem colSpan={{ base: 4 }}>
93- <Heading size="lg" m={3}>
94- {data?.agenda || ""}
95- </Heading>
96- </GridItem>
97- <GridItem colSpan={{ base: 4 }}>
98- <Card>
99- <Grid gap={4}>
100- <GridItem colSpan={2}>
101- <Box>
102- <Flex justifyContent={"space-between"}>
103- <Heading size="md" mb={3}>
104- Meeting Details
105- </Heading>
106- <Box id="hide-btn">
107- <Button leftIcon={<FaFilePdf />} size='sm' variant="brand" onClick={generatePDF} disabled={loading}>
108- {loading ? "Please Wait..." : "Print as PDF"}
109- </Button>
110- <Button leftIcon={<IoIosArrowBack />} size='sm' variant="brand" onClick={() => navigate(-1)} style={{ marginLeft: 10 }}>
111- Back
112- </Button>
113- </Box>
114- </Flex>
115- <HSeparator />
116- </Box>
117- </GridItem>
118- <GridItem colSpan={{ base: 2, md: 1 }}>
119- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Agenda </Text>
120- <Text>{data?.agenda ? data?.agenda : ' - '}</Text>
121- </GridItem>
122- <GridItem colSpan={{ base: 2, md: 1 }}>
123- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Created By </Text>
124- <Text>{data?.createdByName ? data?.createdByName : ' - '}</Text>
125- </GridItem>
102+ <Grid templateColumns="repeat(4, 1fr)" gap={3} id="reports">
103+ <GridItem colSpan={{ base: 4 }}>
104+ <Heading size="lg" m={3}>
105+ {data?.agenda || ""}
106+ </Heading>
107+ </GridItem>
108+ <GridItem colSpan={{ base: 4 }}>
109+ <Card>
110+ <Grid gap={4}>
111+ <GridItem colSpan={2}>
112+ <Box>
113+ <Flex justifyContent={"space-between"}>
114+ <Heading size="md" mb={3}>
115+ Meeting Details
116+ </Heading>
117+ <Box id="hide-btn">
118+ <Button
119+ leftIcon={<FaFilePdf />}
120+ size="sm"
121+ variant="brand"
122+ onClick={generatePDF}
123+ disabled={loading}
124+ >
125+ {loading ? "Please Wait..." : "Print as PDF"}
126+ </Button>
127+ <Button
128+ leftIcon={<IoIosArrowBack />}
129+ size="sm"
130+ variant="brand"
131+ onClick={() => navigate(-1)}
132+ style={{ marginLeft: 10 }}
133+ >
134+ Back
135+ </Button>
136+ </Box>
137+ </Flex>
138+ <HSeparator />
139+ </Box>
140+ </GridItem>
141+ <GridItem colSpan={{ base: 2, md: 1 }}>
142+ <Text
143+ fontSize="sm"
144+ fontWeight="bold"
145+ color={"blackAlpha.900"}
146+ >
147+ {" "}
148+ Agenda{" "}
149+ </Text>
150+ <Text>{data?.agenda ? data?.agenda : " - "}</Text>
151+ </GridItem>
152+ <GridItem colSpan={{ base: 2, md: 1 }}>
153+ <Text
154+ fontSize="sm"
155+ fontWeight="bold"
156+ color={"blackAlpha.900"}
157+ >
158+ {" "}
159+ Created By{" "}
160+ </Text>
161+ <Text>
162+ {/* this was a typo, createdByName -> createByName to keep the same as others */}
163+ {data?.createByName ? data?.createByName : " - "}
164+ </Text>
165+ </GridItem>
126166
127- <GridItem colSpan={{ base: 2, md: 1 }}>
128- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> DateTime </Text>
129- <Text> {data?.dateTime ? moment(data?.dateTime).format('DD-MM-YYYY h:mma ') : ' - '} [{data?.dateTime ? moment(data?.dateTime).toNow() : ' - '}]</Text>
130- </GridItem>
131- <GridItem colSpan={{ base: 2, md: 1 }}>
132- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Timestamp </Text>
133- <Text> {data?.timestamp ? moment(data?.timestamp).format('DD-MM-YYYY h:mma ') : ' - '} [{data?.timestamp ? moment(data?.timestamp).toNow() : ' - '}]</Text>
134- </GridItem>
135- <GridItem colSpan={{ base: 2, md: 1 }}>
136- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Location </Text>
137- <Text>{data?.location ? data?.location : ' - '}</Text>
138- </GridItem>
139- <GridItem colSpan={{ base: 2, md: 1 }}>
140- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Notes </Text>
141- <Text>{data?.notes ? data?.notes : ' - '}</Text>
142- </GridItem>
143- <GridItem colSpan={{ base: 2, md: 1 }}>
144- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Attendes </Text>
145- {data?.related === 'Contact' && contactAccess?.view ? data?.attendes && data?.attendes.map((item) => {
146- return (
147- <Link to={`/contactView/${item._id}`}>
148- <Text color='brand.600' sx={{ '&:hover': { color: 'blue.500', textDecoration: 'underline' } }}>{item.firstName + ' ' + item.lastName}</Text>
149- </Link>
150- )
151- }) : data?.related === 'Lead' && leadAccess?.view ? data?.attendesLead && data?.attendesLead.map((item) => {
152- return (
153- <Link to={`/leadView/${item._id}`}>
154- <Text color='brand.600' sx={{ '&:hover': { color: 'blue.500', textDecoration: 'underline' } }}>{item.leadName}</Text>
155- </Link>
156- )
157- }) : data?.related === 'contact' ? data?.attendes && data?.attendes.map((item) => {
158- return (
159- <Text color='blackAlpha.900' >{item.firstName + ' ' + item.lastName}</Text>
160- )
161- }) : data?.related === 'lead' ? data?.attendesLead && data?.attendesLead.map((item) => {
162- return (
163- <Text color='blackAlpha.900' >{item.leadName}</Text>
164- )
165- }) : '-'}
166- </GridItem>
167- {/* <Grid templateColumns={'repeat(2, 1fr)'} gap={4} id="reports">
167+ <GridItem colSpan={{ base: 2, md: 1 }}>
168+ <Text
169+ fontSize="sm"
170+ fontWeight="bold"
171+ color={"blackAlpha.900"}
172+ >
173+ {" "}
174+ DateTime{" "}
175+ </Text>
176+ <Text>
177+ {" "}
178+ {data?.dateTime
179+ ? moment(data?.dateTime).format("DD-MM-YYYY h:mma ")
180+ : " - "}{" "}
181+ [{data?.dateTime ? moment(data?.dateTime).toNow() : " - "}
182+ ]
183+ </Text>
184+ </GridItem>
185+ <GridItem colSpan={{ base: 2, md: 1 }}>
186+ <Text
187+ fontSize="sm"
188+ fontWeight="bold"
189+ color={"blackAlpha.900"}
190+ >
191+ {" "}
192+ Timestamp{" "}
193+ </Text>
194+ <Text>
195+ {" "}
196+ {data?.timestamp
197+ ? moment(data?.timestamp).format("DD-MM-YYYY h:mma ")
198+ : " - "}{" "}
199+ [
200+ {data?.timestamp
201+ ? moment(data?.timestamp).toNow()
202+ : " - "}
203+ ]
204+ </Text>
205+ </GridItem>
206+ <GridItem colSpan={{ base: 2, md: 1 }}>
207+ <Text
208+ fontSize="sm"
209+ fontWeight="bold"
210+ color={"blackAlpha.900"}
211+ >
212+ {" "}
213+ Location{" "}
214+ </Text>
215+ <Text>{data?.location ? data?.location : " - "}</Text>
216+ </GridItem>
217+ <GridItem colSpan={{ base: 2, md: 1 }}>
218+ <Text
219+ fontSize="sm"
220+ fontWeight="bold"
221+ color={"blackAlpha.900"}
222+ >
223+ {" "}
224+ Notes{" "}
225+ </Text>
226+ <Text>{data?.notes ? data?.notes : " - "}</Text>
227+ </GridItem>
228+ <GridItem colSpan={{ base: 2, md: 1 }}>
229+ <Text
230+ fontSize="sm"
231+ fontWeight="bold"
232+ color={"blackAlpha.900"}
233+ >
234+ {" "}
235+ Attendes{" "}
236+ </Text>
237+ {data?.related === "Contact" && contactAccess?.view
238+ ? data?.attendes &&
239+ data?.attendes.map((item) => {
240+ return (
241+ <Link to={`/contactView/${item._id}`}>
242+ <Text
243+ color="brand.600"
244+ sx={{
245+ "&:hover": {
246+ color: "blue.500",
247+ textDecoration: "underline",
248+ },
249+ }}
250+ >
251+ {item.firstName + " " + item.lastName}
252+ </Text>
253+ </Link>
254+ );
255+ })
256+ : data?.related === "Lead" && leadAccess?.view
257+ ? data?.attendesLead &&
258+ data?.attendesLead.map((item) => {
259+ return (
260+ <Link to={`/leadView/${item._id}`}>
261+ <Text
262+ color="brand.600"
263+ sx={{
264+ "&:hover": {
265+ color: "blue.500",
266+ textDecoration: "underline",
267+ },
268+ }}
269+ >
270+ {item.leadName}
271+ </Text>
272+ </Link>
273+ );
274+ })
275+ : data?.related === "contact"
276+ ? data?.attendes &&
277+ data?.attendes.map((item) => {
278+ return (
279+ <Text color="blackAlpha.900">
280+ {item.firstName + " " + item.lastName}
281+ </Text>
282+ );
283+ })
284+ : data?.related === "lead"
285+ ? data?.attendesLead &&
286+ data?.attendesLead.map((item) => {
287+ return (
288+ <Text color="blackAlpha.900">{item.leadName}</Text>
289+ );
290+ })
291+ : "-"}
292+ </GridItem>
293+ {/* <Grid templateColumns={'repeat(2, 1fr)'} gap={4} id="reports">
168294
169295 </Grid> */}
170- </Grid>
171- </Card>
172- </GridItem>
173-
174- </Grid>
175- {(user.role === 'superAdmin' || (permission?.update || permission?.delete)) && <Card mt={3}>
176- <Grid templateColumns="repeat(6, 1fr)" gap={1}>
177- <GridItem colStart={6} >
178- <Flex justifyContent={"right"}>
179- {(user.role === 'superAdmin' || permission?.delete) ? <Button size='sm' style={{ background: 'red.800' }} onClick={() => setDeleteMany(true)} leftIcon={<DeleteIcon />} colorScheme="red" >Delete</Button> : ''}
180- </Flex>
181- </GridItem>
182- </Grid>
183- </Card>
184- }
185-
186- </>}
187- {/* Delete model */}
188- <CommonDeleteModel isOpen={deleteMany} onClose={() => setDeleteMany(false)} type='Meetings' handleDeleteData={handleDeleteMeeting} ids={params.id} />
296+ </Grid>
297+ </Card>
298+ </GridItem>
299+ </Grid>
300+ {(user.role === "superAdmin" ||
301+ permission?.update ||
302+ permission?.delete) && (
303+ <Card mt={3}>
304+ <Grid templateColumns="repeat(6, 1fr)" gap={1}>
305+ <GridItem colStart={6}>
306+ <Flex justifyContent={"right"}>
307+ {user.role === "superAdmin" || permission?.delete ? (
308+ <Button
309+ size="sm"
310+ style={{ background: "red.800" }}
311+ onClick={() => setDeleteMany(true)}
312+ leftIcon={<DeleteIcon />}
313+ colorScheme="red"
314+ >
315+ Delete
316+ </Button>
317+ ) : (
318+ ""
319+ )}
320+ </Flex>
321+ </GridItem>
322+ </Grid>
323+ </Card>
324+ )}
189325 </>
190- );
326+ )}
327+ {/* Delete model */}
328+ <CommonDeleteModel
329+ isOpen={deleteMany}
330+ onClose={() => setDeleteMany(false)}
331+ type="Meetings"
332+ handleDeleteData={handleDeleteMeeting}
333+ ids={params.id}
334+ />
335+ </>
336+ );
191337 };
192338
193339 export default View;
+358-190Client/src/views/admin/meeting/components/Addmeeting.js
@@ -1,206 +1,374 @@
1-import { Button, Flex, FormLabel, Grid, GridItem, IconButton, Input, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Radio, RadioGroup, Stack, Text, Textarea } from '@chakra-ui/react';
2-import { CUIAutoComplete } from 'chakra-ui-autocomplete';
3-import MultiContactModel from 'components/commonTableModel/MultiContactModel';
4-import MultiLeadModel from 'components/commonTableModel/MultiLeadModel';
5-import Spinner from 'components/spinner/Spinner';
6-import dayjs from 'dayjs';
7-import { useFormik } from 'formik';
8-import { useEffect, useState } from 'react';
9-import { LiaMousePointerSolid } from 'react-icons/lia';
10-import { useSelector } from 'react-redux';
11-import { toast } from 'react-toastify';
12-import { MeetingSchema } from 'schema';
13-import { getApi, postApi } from 'services/api';
1+import {
2+ Button,
3+ Flex,
4+ FormLabel,
5+ Grid,
6+ GridItem,
7+ IconButton,
8+ Input,
9+ Modal,
10+ ModalBody,
11+ ModalCloseButton,
12+ ModalContent,
13+ ModalFooter,
14+ ModalHeader,
15+ ModalOverlay,
16+ Radio,
17+ RadioGroup,
18+ Stack,
19+ Text,
20+ Textarea,
21+} from "@chakra-ui/react";
22+import { CUIAutoComplete } from "chakra-ui-autocomplete";
23+import MultiContactModel from "components/commonTableModel/MultiContactModel";
24+import MultiLeadModel from "components/commonTableModel/MultiLeadModel";
25+import Spinner from "components/spinner/Spinner";
26+import dayjs from "dayjs";
27+import { useFormik } from "formik";
28+import { useEffect, useState } from "react";
29+import { LiaMousePointerSolid } from "react-icons/lia";
30+import { useSelector } from "react-redux";
31+import { toast } from "react-toastify";
32+import { MeetingSchema } from "schema";
33+import { getApi, postApi } from "services/api";
1434
1535 const AddMeeting = (props) => {
16- const { onClose, isOpen, setAction, from, fetchData, view } = props
17- const [leaddata, setLeadData] = useState([])
18- const [contactdata, setContactData] = useState([])
19- const [isLoding, setIsLoding] = useState(false)
20- const [contactModelOpen, setContactModel] = useState(false);
21- const [leadModelOpen, setLeadModel] = useState(false);
22- const todayTime = new Date().toISOString().split('.')[0];
23- const leadData = useSelector((state) => state?.leadData?.data);
36+ const { onClose, isOpen, setAction, from, fetchData, view } = props;
37+ const [leaddata, setLeadData] = useState([]);
38+ const [contactdata, setContactData] = useState([]);
39+ const [isLoding, setIsLoding] = useState(false);
40+ const [contactModelOpen, setContactModel] = useState(false);
41+ const [leadModelOpen, setLeadModel] = useState(false);
42+ const todayTime = new Date().toISOString().split(".")[0];
43+ const leadData = useSelector((state) => state?.leadData?.data);
2444
45+ const user = JSON.parse(localStorage.getItem("user"));
2546
26- const user = JSON.parse(localStorage.getItem('user'))
47+ const contactList = useSelector((state) => state?.contactData?.data);
2748
28- const contactList = useSelector((state) => state?.contactData?.data)
49+ const initialValues = {
50+ agenda: "",
51+ attendes: props.leadContect === "contactView" && props.id ? [props.id] : [],
52+ attendesLead:
53+ props.leadContect === "leadView" && props.id ? [props.id] : [],
54+ location: "",
55+ related:
56+ props.leadContect === "contactView"
57+ ? "Contact"
58+ : props.leadContect === "leadView"
59+ ? "Lead"
60+ : "None",
61+ dateTime: "",
62+ notes: "",
63+ createBy: user?._id,
64+ };
2965
66+ const formik = useFormik({
67+ initialValues: initialValues,
68+ validationSchema: MeetingSchema,
69+ onSubmit: (values, { resetForm }) => {
70+ AddData();
71+ },
72+ });
3073
31- const initialValues = {
32- agenda: '',
33- attendes: props.leadContect === 'contactView' && props.id ? [props.id] : [],
34- attendesLead: props.leadContect === 'leadView' && props.id ? [props.id] : [],
35- location: '',
36- related: props.leadContect === 'contactView' ? 'Contact' : props.leadContect === 'leadView' ? 'Lead' : 'None',
37- dateTime: '',
38- notes: '',
39- createBy: user?._id,
40- }
41-
42- const formik = useFormik({
43- initialValues: initialValues,
44- validationSchema: MeetingSchema,
45- onSubmit: (values, { resetForm }) => {
46-
47- },
48- });
49- const { errors, touched, values, handleBlur, handleChange, handleSubmit, setFieldValue } = formik
50-
51- const AddData = async () => {
74+ const {
75+ errors,
76+ touched,
77+ values,
78+ handleBlur,
79+ handleChange,
80+ handleSubmit,
81+ setFieldValue,
82+ } = formik;
5283
53- };
54-
55- const fetchAllData = async () => {
56-
84+ const AddData = async () => {
85+ try {
86+ setIsLoding(true);
87+ let response = await postApi("api/meeting/add", {
88+ ...values,
89+ });
90+ if (response.status === 200) {
91+ props.onClose();
92+ formik.resetForm();
93+ props.setAction((pre) => !pre);
94+ toast.success(`Added a meeting for ${values.dateTime} 😄`);
95+ }
96+ } catch (e) {
97+ console.log(e);
98+ toast.error("Failed to add meeting 😞");
99+ } finally {
100+ setIsLoding(false);
57101 }
102+ };
58103
59- useEffect(() => {
60-
61- }, [props.id, values.related])
62-
63- const extractLabels = (selectedItems) => {
64- return selectedItems.map((item) => item._id);
65- };
66-
67- const countriesWithEmailAsLabel = (values.related === "Contact" ? contactdata : leaddata)?.map((item) => ({
68- ...item,
69- value: item._id,
70- label: values.related === "Contact" ? `${item.firstName} ${item.lastName}` : item.leadName,
71- }));
72-
73- return (
74- <Modal onClose={onClose} isOpen={isOpen} isCentered>
75- <ModalOverlay />
76- <ModalContent height={"580px"}>
77- <ModalHeader>Add Meeting </ModalHeader>
78- <ModalCloseButton />
79- <ModalBody overflowY={"auto"} height={"400px"}>
80- {/* Contact Model */}
81- <MultiContactModel data={contactdata} isOpen={contactModelOpen} onClose={setContactModel} fieldName='attendes' setFieldValue={setFieldValue} />
82- {/* Lead Model */}
83- <MultiLeadModel data={leaddata} isOpen={leadModelOpen} onClose={setLeadModel} fieldName='attendesLead' setFieldValue={setFieldValue} />
84-
85- <Grid templateColumns="repeat(12, 1fr)" gap={3}>
86- <GridItem colSpan={{ base: 12 }}>
87- <FormLabel display='flex' ms='4px' fontSize='sm' fontWeight='500' mb='8px'>
88- Agenda<Text color={"red"}>*</Text>
89- </FormLabel>
90- <Input
91- fontSize='sm'
92- onChange={handleChange} onBlur={handleBlur}
93- value={values.agenda}
94- name="agenda"
95- placeholder='Agenda'
96- fontWeight='500'
97- borderColor={errors.agenda && touched.agenda ? "red.300" : null}
98- />
99- <Text fontSize='sm' mb='10px' color={'red'}> {errors.agenda && touched.agenda && errors.agenda}</Text>
100- </GridItem>
101- <GridItem colSpan={{ base: 12 }} >
102- <FormLabel display='flex' ms='4px' fontSize='sm' fontWeight='500' mb='8px'>
103- Related To<Text color={"red"}>*</Text>
104- </FormLabel>
105- <RadioGroup onChange={(e) => setFieldValue('related', e)} value={values.related}>
106- <Stack direction='row'>
107- {props.leadContect === 'contactView' && <Radio value='Contact'>Contact</Radio>}
108- {props.leadContect === 'leadView' && <Radio value='Lead'>Lead</Radio>}
109- {!props.leadContect && <> <Radio value='Contact'>Contact</Radio><Radio value='Lead'>Lead</Radio></>}
110- </Stack>
111- </RadioGroup>
112- <Text mb='10px' color={'red'} fontSize='sm'> {errors.related && touched.related && errors.related}</Text>
113- </GridItem>
114- {(values.related === "Contact" ? (contactdata?.length ?? 0) > 0 : (leaddata?.length ?? 0) > 0) && values.related &&
104+ const fetchAllData = async () => {};
115105
116- <GridItem colSpan={{ base: 12 }}>
117- <Flex alignItems={'end'} justifyContent={'space-between'} >
118- <Text w={'100%'} >
119- <CUIAutoComplete
120- label={`Choose Preferred Attendes ${values.related === "Contact" ? "Contact" : values.related === "Lead" && "Lead"}`}
121- placeholder="Type a Name"
122- name="attendes"
123- items={countriesWithEmailAsLabel}
124- className='custom-autoComplete'
125- selectedItems={countriesWithEmailAsLabel?.filter((item) => values.related === "Contact" ? values?.attendes.includes(item._id) : values.related === "Lead" && values?.attendesLead.includes(item._id))}
126- onSelectedItemsChange={(changes) => {
127- const selectedLabels = extractLabels(changes.selectedItems);
128- values.related === "Contact" ? setFieldValue('attendes', selectedLabels) : values.related === "Lead" && setFieldValue('attendesLead', selectedLabels)
129- }}
130- />
131- </Text>
132- <IconButton mb={6} onClick={() => values.related === "Contact" ? setContactModel(true) : values.related === "Lead" && setLeadModel(true)} fontSize='25px' icon={<LiaMousePointerSolid />} />
133- </Flex>
134- <Text color={'red'}> {errors.attendes && touched.attendes && errors.attendes}</Text>
135- </GridItem>
136- }
137- <GridItem colSpan={{ base: 12 }}>
138- <FormLabel display='flex' ms='4px' fontSize='sm' fontWeight='500' mb='8px'>
139- Location
140- </FormLabel>
141- <Input
142- fontSize='sm'
143- onChange={handleChange} onBlur={handleBlur}
144- value={values.location}
145- name="location"
146- placeholder='Location'
147- fontWeight='500'
148- borderColor={errors.location && touched.location ? "red.300" : null}
149- />
150- <Text mb='10px' color={'red'} fontSize='sm'> {errors.location && touched.location && errors.location}</Text>
151- </GridItem>
152- <GridItem colSpan={{ base: 12 }}>
153- <FormLabel display='flex' ms='4px' fontSize='sm' fontWeight='500' mb='8px'>
154- Date Time<Text color={"red"}>*</Text>
155- </FormLabel>
156- <Input
157- fontSize='sm'
158- type='datetime-local'
159- onChange={handleChange} onBlur={handleBlur}
160- min={dayjs(todayTime).format('YYYY-MM-DD HH:mm')}
161- value={values.dateTime}
162- name="dateTime"
163- placeholder='Date Time'
164- fontWeight='500'
165- borderColor={errors.dateTime && touched.dateTime ? "red.300" : null}
166- />
167- <Text fontSize='sm' mb='10px' color={'red'}> {errors.dateTime && touched.dateTime && errors.dateTime}</Text>
168- </GridItem>
169- <GridItem colSpan={{ base: 12 }}>
170- <FormLabel display='flex' ms='4px' fontSize='sm' fontWeight='500' mb='8px'>
171- Notes
172- </FormLabel>
173- <Textarea
174- resize={'none'}
175- fontSize='sm'
176- placeholder='Notes'
177- onChange={handleChange} onBlur={handleBlur}
178- value={values.notes}
179- name="notes"
180- fontWeight='500'
181- borderColor={errors.notes && touched.notes ? "red.300" : null}
182- />
183- <Text mb='10px' color={'red'}> {errors.notes && touched.notes && errors.notes}</Text>
184- </GridItem>
106+ useEffect(() => {}, [props.id, values.related]);
185107
186- </Grid>
108+ const extractLabels = (selectedItems) => {
109+ return selectedItems.map((item) => item._id);
110+ };
187111
112+ const countriesWithEmailAsLabel = (
113+ values.related === "Contact" ? contactdata : leaddata
114+ )?.map((item) => ({
115+ ...item,
116+ value: item._id,
117+ label:
118+ values.related === "Contact"
119+ ? `${item.firstName} ${item.lastName}`
120+ : item.leadName,
121+ }));
188122
189- </ModalBody>
190- <ModalFooter>
191- <Button size="sm" variant='brand' me={2} disabled={isLoding ? true : false} onClick={handleSubmit}>{isLoding ? <Spinner /> : 'Save'}</Button>
192- <Button sx={{
193- textTransform: "capitalize",
194- }} variant="outline"
195- colorScheme="red" size="sm" onClick={() => {
196- formik.resetForm()
197- onClose()
198- }}>Close</Button>
199- </ModalFooter>
200- </ModalContent>
201- </Modal>
202- )
203-}
123+ return (
124+ <Modal onClose={onClose} isOpen={isOpen} isCentered>
125+ <ModalOverlay />
126+ <ModalContent height={"580px"}>
127+ <ModalHeader>Add Meeting </ModalHeader>
128+ <ModalCloseButton />
129+ <ModalBody overflowY={"auto"} height={"400px"}>
130+ {/* Contact Model */}
131+ <MultiContactModel
132+ data={contactdata}
133+ isOpen={contactModelOpen}
134+ onClose={setContactModel}
135+ fieldName="attendes"
136+ setFieldValue={setFieldValue}
137+ />
138+ {/* Lead Model */}
139+ <MultiLeadModel
140+ data={leaddata}
141+ isOpen={leadModelOpen}
142+ onClose={setLeadModel}
143+ fieldName="attendesLead"
144+ setFieldValue={setFieldValue}
145+ />
204146
205-export default AddMeeting
147+ <Grid templateColumns="repeat(12, 1fr)" gap={3}>
148+ <GridItem colSpan={{ base: 12 }}>
149+ <FormLabel
150+ display="flex"
151+ ms="4px"
152+ fontSize="sm"
153+ fontWeight="500"
154+ mb="8px"
155+ >
156+ Agenda<Text color={"red"}>*</Text>
157+ </FormLabel>
158+ <Input
159+ fontSize="sm"
160+ onChange={handleChange}
161+ onBlur={handleBlur}
162+ value={values.agenda}
163+ name="agenda"
164+ placeholder="Agenda"
165+ fontWeight="500"
166+ borderColor={errors.agenda && touched.agenda ? "red.300" : null}
167+ />
168+ <Text fontSize="sm" mb="10px" color={"red"}>
169+ {" "}
170+ {errors.agenda && touched.agenda && errors.agenda}
171+ </Text>
172+ </GridItem>
173+ <GridItem colSpan={{ base: 12 }}>
174+ <FormLabel
175+ display="flex"
176+ ms="4px"
177+ fontSize="sm"
178+ fontWeight="500"
179+ mb="8px"
180+ >
181+ Related To<Text color={"red"}>*</Text>
182+ </FormLabel>
183+ <RadioGroup
184+ onChange={(e) => setFieldValue("related", e)}
185+ value={values.related}
186+ >
187+ <Stack direction="row">
188+ {props.leadContect === "contactView" && (
189+ <Radio value="Contact">Contact</Radio>
190+ )}
191+ {props.leadContect === "leadView" && (
192+ <Radio value="Lead">Lead</Radio>
193+ )}
194+ {!props.leadContect && (
195+ <>
196+ {" "}
197+ <Radio value="Contact">Contact</Radio>
198+ <Radio value="Lead">Lead</Radio>
199+ </>
200+ )}
201+ </Stack>
202+ </RadioGroup>
203+ <Text mb="10px" color={"red"} fontSize="sm">
204+ {" "}
205+ {errors.related && touched.related && errors.related}
206+ </Text>
207+ </GridItem>
208+ {(values.related === "Contact"
209+ ? (contactdata?.length ?? 0) > 0
210+ : (leaddata?.length ?? 0) > 0) &&
211+ values.related && (
212+ <GridItem colSpan={{ base: 12 }}>
213+ <Flex alignItems={"end"} justifyContent={"space-between"}>
214+ <Text w={"100%"}>
215+ <CUIAutoComplete
216+ label={`Choose Preferred Attendes ${
217+ values.related === "Contact"
218+ ? "Contact"
219+ : values.related === "Lead" && "Lead"
220+ }`}
221+ placeholder="Type a Name"
222+ name="attendes"
223+ items={countriesWithEmailAsLabel}
224+ className="custom-autoComplete"
225+ selectedItems={countriesWithEmailAsLabel?.filter(
226+ (item) =>
227+ values.related === "Contact"
228+ ? values?.attendes.includes(item._id)
229+ : values.related === "Lead" &&
230+ values?.attendesLead.includes(item._id)
231+ )}
232+ onSelectedItemsChange={(changes) => {
233+ const selectedLabels = extractLabels(
234+ changes.selectedItems
235+ );
236+ values.related === "Contact"
237+ ? setFieldValue("attendes", selectedLabels)
238+ : values.related === "Lead" &&
239+ setFieldValue("attendesLead", selectedLabels);
240+ }}
241+ />
242+ </Text>
243+ <IconButton
244+ mb={6}
245+ onClick={() =>
246+ values.related === "Contact"
247+ ? setContactModel(true)
248+ : values.related === "Lead" && setLeadModel(true)
249+ }
250+ fontSize="25px"
251+ icon={<LiaMousePointerSolid />}
252+ />
253+ </Flex>
254+ <Text color={"red"}>
255+ {" "}
256+ {errors.attendes && touched.attendes && errors.attendes}
257+ </Text>
258+ </GridItem>
259+ )}
260+ <GridItem colSpan={{ base: 12 }}>
261+ <FormLabel
262+ display="flex"
263+ ms="4px"
264+ fontSize="sm"
265+ fontWeight="500"
266+ mb="8px"
267+ >
268+ Location
269+ </FormLabel>
270+ <Input
271+ fontSize="sm"
272+ onChange={handleChange}
273+ onBlur={handleBlur}
274+ value={values.location}
275+ name="location"
276+ placeholder="Location"
277+ fontWeight="500"
278+ borderColor={
279+ errors.location && touched.location ? "red.300" : null
280+ }
281+ />
282+ <Text mb="10px" color={"red"} fontSize="sm">
283+ {" "}
284+ {errors.location && touched.location && errors.location}
285+ </Text>
286+ </GridItem>
287+ <GridItem colSpan={{ base: 12 }}>
288+ <FormLabel
289+ display="flex"
290+ ms="4px"
291+ fontSize="sm"
292+ fontWeight="500"
293+ mb="8px"
294+ >
295+ Date Time<Text color={"red"}>*</Text>
296+ </FormLabel>
297+ <Input
298+ fontSize="sm"
299+ type="datetime-local"
300+ onChange={handleChange}
301+ onBlur={handleBlur}
302+ min={dayjs(todayTime).format("YYYY-MM-DD HH:mm")}
303+ value={values.dateTime}
304+ name="dateTime"
305+ placeholder="Date Time"
306+ fontWeight="500"
307+ borderColor={
308+ errors.dateTime && touched.dateTime ? "red.300" : null
309+ }
310+ />
311+ <Text fontSize="sm" mb="10px" color={"red"}>
312+ {" "}
313+ {errors.dateTime && touched.dateTime && errors.dateTime}
314+ </Text>
315+ </GridItem>
316+ <GridItem colSpan={{ base: 12 }}>
317+ <FormLabel
318+ display="flex"
319+ ms="4px"
320+ fontSize="sm"
321+ fontWeight="500"
322+ mb="8px"
323+ >
324+ Notes
325+ </FormLabel>
326+ <Textarea
327+ resize={"none"}
328+ fontSize="sm"
329+ placeholder="Notes"
330+ onChange={handleChange}
331+ onBlur={handleBlur}
332+ value={values.notes}
333+ name="notes"
334+ fontWeight="500"
335+ borderColor={errors.notes && touched.notes ? "red.300" : null}
336+ />
337+ <Text mb="10px" color={"red"}>
338+ {" "}
339+ {errors.notes && touched.notes && errors.notes}
340+ </Text>
341+ </GridItem>
342+ </Grid>
343+ </ModalBody>
344+ <ModalFooter>
345+ <Button
346+ size="sm"
347+ variant="brand"
348+ me={2}
349+ disabled={isLoding ? true : false}
350+ onClick={handleSubmit}
351+ >
352+ {isLoding ? <Spinner /> : "Save"}
353+ </Button>
354+ <Button
355+ sx={{
356+ textTransform: "capitalize",
357+ }}
358+ variant="outline"
359+ colorScheme="red"
360+ size="sm"
361+ onClick={() => {
362+ formik.resetForm();
363+ onClose();
364+ }}
365+ >
366+ Close
367+ </Button>
368+ </ModalFooter>
369+ </ModalContent>
370+ </Modal>
371+ );
372+};
206373
374+export default AddMeeting;
+246-113Client/src/views/admin/meeting/meetingView.js
@@ -1,126 +1,259 @@
1-import { CloseIcon, DeleteIcon, EditIcon, ViewIcon } from '@chakra-ui/icons'
2-import { DrawerFooter, Flex, Grid, GridItem, IconButton, Modal, ModalBody, ModalContent, ModalHeader, ModalOverlay, Text } from '@chakra-ui/react'
3-import Spinner from "components/spinner/Spinner"
4-import moment from 'moment'
5-import { useEffect, useState } from 'react'
6-import { BiLink } from 'react-icons/bi'
7-import { Link } from 'react-router-dom'
8-import { getApi } from 'services/api'
1+import { CloseIcon, DeleteIcon, EditIcon, ViewIcon } from "@chakra-ui/icons";
2+import {
3+ DrawerFooter,
4+ Flex,
5+ Grid,
6+ GridItem,
7+ IconButton,
8+ Modal,
9+ ModalBody,
10+ ModalContent,
11+ ModalHeader,
12+ ModalOverlay,
13+ Text,
14+} from "@chakra-ui/react";
15+import Spinner from "components/spinner/Spinner";
16+import moment from "moment";
17+import { useEffect, useState } from "react";
18+import { BiLink } from "react-icons/bi";
19+import { Link } from "react-router-dom";
20+import { getApi } from "services/api";
921 // import DeleteTask from './components/deleteTask'
10-import { useNavigate } from 'react-router-dom';
22+import { useNavigate } from "react-router-dom";
1123 import { HasAccess } from "../../../redux/accessUtils";
1224
1325 const MeetingView = (props) => {
14- const { onClose, isOpen, info, fetchData, setAction, action, access } = props
15- const [data, setData] = useState();
16- const [edit, setEdit] = useState(false);
17- const [deleteModel, setDelete] = useState(false);
18- const user = JSON.parse(localStorage.getItem("user"))
19- const [isLoding, setIsLoding] = useState(false)
20- const navigate = useNavigate()
26+ const { onClose, isOpen, info, fetchData, setAction, action, access } = props;
27+ const [data, setData] = useState();
28+ const [edit, setEdit] = useState(false);
29+ const [deleteModel, setDelete] = useState(false);
30+ const user = JSON.parse(localStorage.getItem("user"));
31+ const [isLoding, setIsLoding] = useState(false);
32+ const navigate = useNavigate();
2133
22- const fetchViewData = async () => {
23- if (info) {
24- setIsLoding(true)
25- let result = await getApi('api/meeting/view/', info?.event ? info?.event?.id : info);
26- setData(result?.data);
27- setIsLoding(false)
28- }
34+ const fetchViewData = async () => {
35+ if (info) {
36+ setIsLoding(true);
37+ let result = await getApi(
38+ "api/meeting/view/",
39+ info?.event ? info?.event?.id : info
40+ );
41+ setData(result?.data);
42+ setIsLoding(false);
2943 }
44+ };
3045
31- useEffect(() => {
32- fetchViewData()
33- }, [action, info])
46+ useEffect(() => {
47+ fetchViewData();
48+ }, [action, info]);
3449
35- const [contactAccess, leadAccess] = HasAccess(['Contacts', 'Leads'])
50+ const [contactAccess, leadAccess] = HasAccess(["Contacts", "Leads"]);
3651
37- const handleViewOpen = () => {
38- if (info?.event) {
39- navigate(`/view/${info?.event?.id}`)
40- }
41- else {
42- navigate(`/view/${info}`)
43- }
52+ const handleViewOpen = () => {
53+ if (info?.event) {
54+ navigate(`/view/${info?.event?.id}`);
55+ } else {
56+ navigate(`/view/${info}`);
4457 }
45- return (
46- <Modal isOpen={isOpen} size={'md'} isCentered>
47- <ModalOverlay />
48- <ModalContent height={"70%"}>
49- <ModalHeader justifyContent='space-between' display='flex' >
50- Meeting
51- <IconButton onClick={() => onClose(false)} icon={<CloseIcon />} />
52- </ModalHeader>
53- {isLoding ?
54- <Flex justifyContent={'center'} alignItems={'center'} mb={30} width="100%" >
55- <Spinner />
56- </Flex> : <>
58+ };
59+ return (
60+ <Modal isOpen={isOpen} size={"md"} isCentered>
61+ <ModalOverlay />
62+ <ModalContent height={"70%"}>
63+ <ModalHeader justifyContent="space-between" display="flex">
64+ Meeting
65+ <IconButton onClick={() => onClose(false)} icon={<CloseIcon />} />
66+ </ModalHeader>
67+ {isLoding ? (
68+ <Flex
69+ justifyContent={"center"}
70+ alignItems={"center"}
71+ mb={30}
72+ width="100%"
73+ >
74+ <Spinner />
75+ </Flex>
76+ ) : (
77+ <>
78+ <ModalBody overflowY={"auto"}>
79+ <Grid templateColumns="repeat(12, 1fr)" gap={3}>
80+ <GridItem colSpan={{ base: 12, md: 6 }}>
81+ <Text
82+ fontSize="sm"
83+ fontWeight="bold"
84+ color={"blackAlpha.900"}
85+ >
86+ {" "}
87+ Agenda{" "}
88+ </Text>
89+ <Text>{data?.agenda ? data?.agenda : " - "}</Text>
90+ </GridItem>
91+ <GridItem colSpan={{ base: 12, md: 6 }}>
92+ <Text
93+ fontSize="sm"
94+ fontWeight="bold"
95+ color={"blackAlpha.900"}
96+ >
97+ {" "}
98+ Date&Time{" "}
99+ </Text>
100+ <Text>
101+ {data?.dateTime
102+ ? moment(data?.dateTime).format("lll ")
103+ : " - "}
104+ </Text>
105+ </GridItem>
106+ <GridItem colSpan={{ base: 12, md: 6 }}>
107+ <Text
108+ fontSize="sm"
109+ fontWeight="bold"
110+ color={"blackAlpha.900"}
111+ >
112+ {" "}
113+ Created By{" "}
114+ </Text>
115+ <Text>{data?.createdByName ? data?.createdByName : "-"}</Text>
116+ </GridItem>
117+ <GridItem colSpan={{ base: 12, md: 6 }}>
118+ <Text
119+ fontSize="sm"
120+ fontWeight="bold"
121+ color={"blackAlpha.900"}
122+ >
123+ {" "}
124+ Related{" "}
125+ </Text>
126+ <Text>{data?.related ? data?.related : "-"}</Text>
127+ </GridItem>
128+ <GridItem colSpan={{ base: 12, md: 6 }}>
129+ <Text
130+ fontSize="sm"
131+ fontWeight="bold"
132+ color={"blackAlpha.900"}
133+ >
134+ {" "}
135+ Location{" "}
136+ </Text>
137+ <Text>{data?.location ? data?.location : "-"}</Text>
138+ </GridItem>
139+ <GridItem colSpan={{ base: 12, md: 6 }}>
140+ <Text
141+ fontSize="sm"
142+ fontWeight="bold"
143+ color={"blackAlpha.900"}
144+ >
145+ {" "}
146+ Notes{" "}
147+ </Text>
148+ <Text>{data?.notes ? data?.notes : "-"}</Text>
149+ </GridItem>
150+ <GridItem colSpan={{ base: 12, md: 6 }}>
151+ <Text
152+ fontSize="sm"
153+ fontWeight="bold"
154+ color={"blackAlpha.900"}
155+ >
156+ {" "}
157+ attendes{" "}
158+ </Text>
159+ {data?.related === "Contact" && contactAccess?.view
160+ ? data?.attendes &&
161+ data?.attendes.map((item) => {
162+ return (
163+ <Link to={`/contactView/${item._id}`}>
164+ <Text
165+ color="brand.600"
166+ sx={{
167+ "&:hover": {
168+ color: "blue.500",
169+ textDecoration: "underline",
170+ },
171+ }}
172+ >
173+ {item.firstName + " " + item.lastName}
174+ </Text>
175+ </Link>
176+ );
177+ })
178+ : data?.related === "Lead" && leadAccess?.view
179+ ? data?.attendesLead &&
180+ data?.attendesLead.map((item) => {
181+ return (
182+ <Link to={`/leadView/${item._id}`}>
183+ <Text
184+ color="brand.600"
185+ sx={{
186+ "&:hover": {
187+ color: "blue.500",
188+ textDecoration: "underline",
189+ },
190+ }}
191+ >
192+ {item.leadName}
193+ </Text>
194+ </Link>
195+ );
196+ })
197+ : data?.related === "Contact"
198+ ? data?.attendes &&
199+ data?.attendes.map((item) => {
200+ return (
201+ <Text color="blackAlpha.900">
202+ {item.firstName + " " + item.lastName}
203+ </Text>
204+ );
205+ })
206+ : data?.related === "Lead"
207+ ? data?.attendesLead &&
208+ data?.attendesLead.map((item) => {
209+ return (
210+ <Text color="blackAlpha.900">{item.leadName}</Text>
211+ );
212+ })
213+ : "-"}
214+ </GridItem>
215+ </Grid>
216+ </ModalBody>
217+ <DrawerFooter>
218+ {access?.view && (
219+ <IconButton
220+ variant="outline"
221+ colorScheme={"green"}
222+ onClick={() => handleViewOpen()}
223+ borderRadius="10px"
224+ size="md"
225+ icon={<ViewIcon />}
226+ />
227+ )}
228+ {access?.update && (
229+ <IconButton
230+ variant="outline"
231+ onClick={() => setEdit(true)}
232+ ml={3}
233+ borderRadius="10px"
234+ size="md"
235+ icon={<EditIcon />}
236+ />
237+ )}
238+ {access?.delete && (
239+ <IconButton
240+ colorScheme="red"
241+ onClick={() => setDelete(true)}
242+ ml={3}
243+ borderRadius="10px"
244+ size="md"
245+ icon={<DeleteIcon />}
246+ />
247+ )}
57248
58- <ModalBody overflowY={"auto"}>
59- <Grid templateColumns="repeat(12, 1fr)" gap={3} >
60- <GridItem colSpan={{ base: 12, md: 6 }} >
61- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Agenda </Text>
62- <Text>{data?.agenda ? data?.agenda : ' - '}</Text>
63- </GridItem>
64- <GridItem colSpan={{ base: 12, md: 6 }} >
65- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Date&Time </Text>
66- <Text>{data?.dateTime ? moment(data?.dateTime).format('lll ') : ' - '}</Text>
67- </GridItem>
68- <GridItem colSpan={{ base: 12, md: 6 }} >
69- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Created By </Text>
70- <Text>{data?.createdByName ? data?.createdByName : '-'}</Text>
71- </GridItem>
72- <GridItem colSpan={{ base: 12, md: 6 }} >
73- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Related </Text>
74- <Text>{data?.related ? data?.related : '-'}</Text>
75- </GridItem>
76- <GridItem colSpan={{ base: 12, md: 6 }} >
77- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Location </Text>
78- <Text>{data?.location ? data?.location : '-'}</Text>
79- </GridItem>
80- <GridItem colSpan={{ base: 12, md: 6 }} >
81- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> Notes </Text>
82- <Text>{data?.notes ? data?.notes : '-'}</Text>
83- </GridItem>
84- <GridItem colSpan={{ base: 12, md: 6 }} >
85- <Text fontSize="sm" fontWeight="bold" color={'blackAlpha.900'}> attendes </Text>
86- {data?.related === 'Contact' && contactAccess?.view ? data?.attendes && data?.attendes.map((item) => {
87- return (
88- <Link to={`/contactView/${item._id}`}>
89- <Text color='brand.600' sx={{ '&:hover': { color: 'blue.500', textDecoration: 'underline' } }}>{item.firstName + ' ' + item.lastName}</Text>
90- </Link>
91- )
92- }) : data?.related === 'Lead' && leadAccess?.view ? data?.attendesLead && data?.attendesLead.map((item) => {
93- return (
94- <Link to={`/leadView/${item._id}`}>
95- <Text color='brand.600' sx={{ '&:hover': { color: 'blue.500', textDecoration: 'underline' } }}>{item.leadName}</Text>
96- </Link>
97- )
98- }) : data?.related === 'Contact' ? data?.attendes && data?.attendes.map((item) => {
99- return (
100- <Text color='blackAlpha.900' >{item.firstName + ' ' + item.lastName}</Text>
101- )
102- }) : data?.related === 'Lead' ? data?.attendesLead && data?.attendesLead.map((item) => {
103- return (
104- <Text color='blackAlpha.900' >{item.leadName}</Text>
105- )
106- }) : '-'}
107- </GridItem>
108-
109- </Grid>
110-
111- </ModalBody>
112- <DrawerFooter>
113- {access?.view && <IconButton variant='outline' colorScheme={'green'} onClick={() => handleViewOpen()} borderRadius="10px" size="md" icon={<ViewIcon />} />}
114- {access?.update && <IconButton variant='outline' onClick={() => setEdit(true)} ml={3} borderRadius="10px" size="md" icon={<EditIcon />} />}
115- {access?.delete && <IconButton colorScheme='red' onClick={() => setDelete(true)} ml={3} borderRadius="10px" size="md" icon={<DeleteIcon />} />}
116-
117- {/*
249+ {/*
118250 <DeleteTask fetchData={props.fetchData} isOpen={deleteModel} onClose={setDelete} viewClose={onClose} url='api/task/delete/' method='one' id={info?.event ? info?.event?.id : info} /> */}
119- </DrawerFooter>
120- </>}
121- </ModalContent>
122- </Modal>
123- )
124-}
251+ </DrawerFooter>
252+ </>
253+ )}
254+ </ModalContent>
255+ </Modal>
256+ );
257+};
125258
126-export default MeetingView
259+export default MeetingView;
+13-2server/controllers/meeting/_routes.js
@@ -1,5 +1,16 @@
1-const express = require('express');
1+const express = require("express");
2+const auth = require("../../middelwares/auth");
3+const meeting = require("./meeting");
24
35 const router = express.Router();
46
5-module.exports = router
7+router.get("/", auth, meeting.index);
8+router.post("/add", auth, meeting.add);
9+// router.post("/addMany", auth, meeting.addMany);
10+router.get("/view/:id", auth, meeting.view);
11+// router.put("/edit/:id", auth, meeting.edit);
12+// router.put("/changeStatus/:id", auth, meeting.changeStatus);
13+// router.delete("/delete/:id", auth, meeting.deleteData);
14+// router.post("/deleteMany", auth, meeting.deleteMany);
15+
16+module.exports = router;
+59-15server/controllers/meeting/meeting.js
@@ -1,24 +1,68 @@
1-const MeetingHistory = require('../../model/schema/meeting')
2-const mongoose = require('mongoose');
1+const MeetingHistory = require("../../model/schema/meeting");
2+const mongoose = require("mongoose");
33
44 const add = async (req, res) => {
5-
6-}
5+ try {
6+ req.body.createdDate = new Date();
7+ const user = new MeetingHistory(req.body);
8+ await user.save();
9+ res.status(200).json(user);
10+ } catch (err) {
11+ console.error("Failed to create Lead:", err);
12+ res.status(400).json({ error: "Failed to create Lead" });
13+ }
14+};
715
816 const index = async (req, res) => {
9-
10-}
17+ const query = req.query;
18+ query.deleted = false;
19+
20+ // let result = await Lead.find(query)
21+
22+ let allData = await MeetingHistory.find(query)
23+ .populate({
24+ path: "createBy",
25+ match: { deleted: false }, // Populate only if createBy.deleted is false
26+ })
27+ .exec();
28+
29+ const result = allData.filter((item) => item.createBy !== null);
30+ res.send(result);
31+};
1132
1233 const view = async (req, res) => {
13-
14-}
34+ console.log("getting view");
35+ try {
36+ let response = await MeetingHistory.findOne({ _id: req.params.id });
37+ if (!response) return res.status(404).json({ message: "no Data Found." });
38+ let result = await MeetingHistory.aggregate([
39+ { $match: { _id: response._id } },
40+ {
41+ $lookup: {
42+ from: "User",
43+ localField: "createBy",
44+ foreignField: "_id",
45+ as: "users",
46+ },
47+ },
48+ { $unwind: { path: "$users", preserveNullAndEmptyArrays: true } },
49+ {
50+ $addFields: {
51+ createByName: "$users.username",
52+ },
53+ },
54+ { $project: { contact: 0, users: 0, Lead: 0, createdByName: 0 } },
55+ ]);
56+ console.log(result[0]);
57+ res.status(200).json(result[0]);
58+ } catch (err) {
59+ console.log("Error:", err);
60+ res.status(400).json({ Error: err });
61+ }
62+};
1563
16-const deleteData = async (req, res) => {
17-
18-}
64+const deleteData = async (req, res) => {};
1965
20-const deleteMany = async (req, res) => {
21-
22-}
66+const deleteMany = async (req, res) => {};
2367
24-module.exports = { add, index, view, deleteData, deleteMany }
68+module.exports = { add, index, view, deleteData, deleteMany };