irongit

'got the add modal for meeting'

huncholanehuncholaneauthored
parent 4091e1dcommit 2e348d3a166bb334b23dbc4132d87d271507dd55Browse files

2 files changed, +191 -358

+4-3Client/src/views/admin/meeting/View.js
@@ -13,6 +13,7 @@ import { deleteApi } from 'services/api';
1313 import CommonDeleteModel from 'components/commonDeleteModel';
1414 import { FaFilePdf } from 'react-icons/fa';
1515 import html2pdf from 'html2pdf.js';
16+import AddMeeting from './components/Addmeeting';
1617 const View = () => {
1718 const param = useParams();
1819
@@ -21,6 +22,7 @@ const View = () => {
2122 const user = JSON.parse(localStorage.getItem('user'));
2223 const [isLoding, setIsLoding] = useState(false);
2324 const [loading, setLoading] = useState(false);
25+ const [edit, setEdit] = useState(false);
2426 const navigate = useNavigate();
2527 const params = useParams();
2628
@@ -37,8 +39,6 @@ const View = () => {
3739
3840 const handleClick = () => {};
3941
40- const setEdit = () => {};
41-
4242 const setDeleteManyModel = () => {};
4343
4444 const generatePDF = () => {
@@ -141,7 +141,7 @@ const View = () => {
141141 {(user.role === 'superAdmin' || permission?.delete) && (
142142 <>
143143 <MenuDivider />
144- <MenuItem alignItems={'start'} onClick={() => setDeleteManyModel(true)} color={'red'} icon={<DeleteIcon />}>
144+ <MenuItem alignItems={'start'} onClick={() => setDeleteMany(true)} color={'red'} icon={<DeleteIcon />}>
145145 Delete
146146 </MenuItem>
147147 </>
@@ -294,6 +294,7 @@ const View = () => {
294294 )}
295295 {/* Delete model */}
296296 <CommonDeleteModel isOpen={deleteMany} onClose={() => setDeleteMany(false)} type="Meetings" handleDeleteData={handleDeleteMeeting} ids={params.id} />
297+ <AddMeeting isOpen={edit} fetchData={fetchData} onClose={() => setEdit(false)} userAction={'edit'} id={params.id} />
297298 </>
298299 );
299300 };
+187-355Client/src/views/admin/meeting/components/Addmeeting.js
@@ -1,374 +1,206 @@
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";
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';
3414
3515 const AddMeeting = (props) => {
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);
16+ const { onClose, isOpen, setAction, from, fetchData, view, meetingId } = 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);
4424
45- const user = JSON.parse(localStorage.getItem("user"));
25+ const user = JSON.parse(localStorage.getItem('user'));
4626
47- const contactList = useSelector((state) => state?.contactData?.data);
27+ const contactList = useSelector((state) => state?.contactData?.data);
4828
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- };
29+ const initialValues = {
30+ agenda: '',
31+ attendes: props.leadContect === 'contactView' && props.id ? [props.id] : [],
32+ attendesLead: props.leadContect === 'leadView' && props.id ? [props.id] : [],
33+ location: '',
34+ related: props.leadContect === 'contactView' ? 'Contact' : props.leadContect === 'leadView' ? 'Lead' : 'None',
35+ dateTime: '',
36+ notes: '',
37+ createBy: user?._id,
38+ };
6539
66- const formik = useFormik({
67- initialValues: initialValues,
68- validationSchema: MeetingSchema,
69- onSubmit: (values, { resetForm }) => {
70- AddData();
71- },
72- });
40+ const formik = useFormik({
41+ initialValues: initialValues,
42+ validationSchema: MeetingSchema,
43+ onSubmit: (values, { resetForm }) => {
44+ AddData();
45+ },
46+ });
7347
74- const {
75- errors,
76- touched,
77- values,
78- handleBlur,
79- handleChange,
80- handleSubmit,
81- setFieldValue,
82- } = formik;
48+ const { errors, touched, values, handleBlur, handleChange, handleSubmit, setFieldValue } = formik;
8349
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);
101- }
102- };
50+ const AddData = async () => {
51+ try {
52+ setIsLoding(true);
53+ let response = await postApi('api/meeting/add', {
54+ ...values,
55+ });
56+ if (response.status === 200) {
57+ props.onClose();
58+ formik.resetForm();
59+ props.setAction((pre) => !pre);
60+ toast.success(`Added a meeting for ${values.dateTime} ๐Ÿ˜„`);
61+ }
62+ } catch (e) {
63+ console.log(e);
64+ toast.error('Failed to add meeting ๐Ÿ˜ž');
65+ } finally {
66+ setIsLoding(false);
67+ }
68+ };
10369
104- const fetchAllData = async () => {};
70+ const fetchAllData = async () => {};
10571
106- useEffect(() => {}, [props.id, values.related]);
72+ useEffect(() => {}, [props.id, values.related]);
10773
108- const extractLabels = (selectedItems) => {
109- return selectedItems.map((item) => item._id);
110- };
74+ const extractLabels = (selectedItems) => {
75+ return selectedItems.map((item) => item._id);
76+ };
11177
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- }));
78+ const countriesWithEmailAsLabel = (values.related === 'Contact' ? contactdata : leaddata)?.map((item) => ({
79+ ...item,
80+ value: item._id,
81+ label: values.related === 'Contact' ? `${item.firstName} ${item.lastName}` : item.leadName,
82+ }));
12283
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- />
84+ return (
85+ <Modal onClose={onClose} isOpen={isOpen} isCentered>
86+ <ModalOverlay />
87+ <ModalContent height={'580px'}>
88+ <ModalHeader>Add Meeting </ModalHeader>
89+ <ModalCloseButton />
90+ <ModalBody overflowY={'auto'} height={'400px'}>
91+ {/* Contact Model */}
92+ <MultiContactModel data={contactdata} isOpen={contactModelOpen} onClose={setContactModel} fieldName="attendes" setFieldValue={setFieldValue} />
93+ {/* Lead Model */}
94+ <MultiLeadModel data={leaddata} isOpen={leadModelOpen} onClose={setLeadModel} fieldName="attendesLead" setFieldValue={setFieldValue} />
14695
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)
96+ <Grid templateColumns="repeat(12, 1fr)" gap={3}>
97+ <GridItem colSpan={{ base: 12 }}>
98+ <FormLabel display="flex" ms="4px" fontSize="sm" fontWeight="500" mb="8px">
99+ Agenda<Text color={'red'}>*</Text>
100+ </FormLabel>
101+ <Input fontSize="sm" onChange={handleChange} onBlur={handleBlur} value={values.agenda} name="agenda" placeholder="Agenda" fontWeight="500" borderColor={errors.agenda && touched.agenda ? 'red.300' : null} />
102+ <Text fontSize="sm" mb="10px" color={'red'}>
103+ {' '}
104+ {errors.agenda && touched.agenda && errors.agenda}
105+ </Text>
106+ </GridItem>
107+ <GridItem colSpan={{ base: 12 }}>
108+ <FormLabel display="flex" ms="4px" fontSize="sm" fontWeight="500" mb="8px">
109+ Related To<Text color={'red'}>*</Text>
110+ </FormLabel>
111+ <RadioGroup onChange={(e) => setFieldValue('related', e)} value={values.related}>
112+ <Stack direction="row">
113+ {props.leadContect === 'contactView' && <Radio value="Contact">Contact</Radio>}
114+ {props.leadContect === 'leadView' && <Radio value="Lead">Lead</Radio>}
115+ {!props.leadContect && (
116+ <>
117+ {' '}
118+ <Radio value="Contact">Contact</Radio>
119+ <Radio value="Lead">Lead</Radio>
120+ </>
121+ )}
122+ </Stack>
123+ </RadioGroup>
124+ <Text mb="10px" color={'red'} fontSize="sm">
125+ {' '}
126+ {errors.related && touched.related && errors.related}
127+ </Text>
128+ </GridItem>
129+ {(values.related === 'Contact' ? (contactdata?.length ?? 0) > 0 : (leaddata?.length ?? 0) > 0) && values.related && (
130+ <GridItem colSpan={{ base: 12 }}>
131+ <Flex alignItems={'end'} justifyContent={'space-between'}>
132+ <Text w={'100%'}>
133+ <CUIAutoComplete
134+ label={`Choose Preferred Attendes ${values.related === 'Contact' ? 'Contact' : values.related === 'Lead' && 'Lead'}`}
135+ placeholder="Type a Name"
136+ name="attendes"
137+ items={countriesWithEmailAsLabel}
138+ className="custom-autoComplete"
139+ selectedItems={countriesWithEmailAsLabel?.filter((item) => (values.related === 'Contact' ? values?.attendes.includes(item._id) : values.related === 'Lead' && values?.attendesLead.includes(item._id)))}
140+ onSelectedItemsChange={(changes) => {
141+ const selectedLabels = extractLabels(changes.selectedItems);
142+ values.related === 'Contact' ? setFieldValue('attendes', selectedLabels) : values.related === 'Lead' && setFieldValue('attendesLead', selectedLabels);
143+ }}
144+ />
145+ </Text>
146+ <IconButton mb={6} onClick={() => (values.related === 'Contact' ? setContactModel(true) : values.related === 'Lead' && setLeadModel(true))} fontSize="25px" icon={<LiaMousePointerSolid />} />
147+ </Flex>
148+ <Text color={'red'}> {errors.attendes && touched.attendes && errors.attendes}</Text>
149+ </GridItem>
231150 )}
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);
151+ <GridItem colSpan={{ base: 12 }}>
152+ <FormLabel display="flex" ms="4px" fontSize="sm" fontWeight="500" mb="8px">
153+ Location
154+ </FormLabel>
155+ <Input fontSize="sm" onChange={handleChange} onBlur={handleBlur} value={values.location} name="location" placeholder="Location" fontWeight="500" borderColor={errors.location && touched.location ? 'red.300' : null} />
156+ <Text mb="10px" color={'red'} fontSize="sm">
157+ {' '}
158+ {errors.location && touched.location && errors.location}
159+ </Text>
160+ </GridItem>
161+ <GridItem colSpan={{ base: 12 }}>
162+ <FormLabel display="flex" ms="4px" fontSize="sm" fontWeight="500" mb="8px">
163+ Date Time<Text color={'red'}>*</Text>
164+ </FormLabel>
165+ <Input fontSize="sm" type="datetime-local" onChange={handleChange} onBlur={handleBlur} min={dayjs(todayTime).format('YYYY-MM-DD HH:mm')} value={values.dateTime} name="dateTime" placeholder="Date Time" fontWeight="500" borderColor={errors.dateTime && touched.dateTime ? 'red.300' : null} />
166+ <Text fontSize="sm" mb="10px" color={'red'}>
167+ {' '}
168+ {errors.dateTime && touched.dateTime && errors.dateTime}
169+ </Text>
170+ </GridItem>
171+ <GridItem colSpan={{ base: 12 }}>
172+ <FormLabel display="flex" ms="4px" fontSize="sm" fontWeight="500" mb="8px">
173+ Notes
174+ </FormLabel>
175+ <Textarea resize={'none'} fontSize="sm" placeholder="Notes" onChange={handleChange} onBlur={handleBlur} value={values.notes} name="notes" fontWeight="500" borderColor={errors.notes && touched.notes ? 'red.300' : null} />
176+ <Text mb="10px" color={'red'}>
177+ {' '}
178+ {errors.notes && touched.notes && errors.notes}
179+ </Text>
180+ </GridItem>
181+ </Grid>
182+ </ModalBody>
183+ <ModalFooter>
184+ <Button size="sm" variant="brand" me={2} disabled={isLoding ? true : false} onClick={handleSubmit}>
185+ {isLoding ? <Spinner /> : 'Save'}
186+ </Button>
187+ <Button
188+ sx={{
189+ textTransform: 'capitalize',
240190 }}
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- );
191+ variant="outline"
192+ colorScheme="red"
193+ size="sm"
194+ onClick={() => {
195+ formik.resetForm();
196+ onClose();
197+ }}>
198+ Close
199+ </Button>
200+ </ModalFooter>
201+ </ModalContent>
202+ </Modal>
203+ );
372204 };
373205
374206 export default AddMeeting;