Created
May 27, 2023 18:55
-
-
Save zourdyzou/8c8414ca8e4324329b5f9b8e325df4af to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useEffect, useRef, useState } from 'react'; | |
| import * as React from 'react'; | |
| import { DragDropContext, DragStart, DropResult } from 'react-beautiful-dnd'; | |
| import { useSelector } from 'react-redux'; | |
| import AddIcon from '@mui/icons-material/Add'; | |
| import ExpandMoreIcon from '@mui/icons-material/ArrowForwardIos'; | |
| import DeleteIcon from '@mui/icons-material/Delete'; | |
| import DragHandleIcon from '@mui/icons-material/DragHandle'; | |
| import ModeEditIcon from '@mui/icons-material/ModeEdit'; | |
| import { Box, Button, Grid, IconButton } from '@mui/material'; | |
| import { useFormik } from 'formik'; | |
| import * as Yup from 'yup'; | |
| import { useRouter } from 'next/router'; | |
| import { EditableTextField } from '@/components/shared/Forms/ReusableFormInput'; | |
| import { ReusableCreationFormHeader } from '@/components/shared/Headers/CreationFormHeader'; | |
| import { ReusablePageHeader } from '@/components/shared/Headers/PageHeader'; | |
| import { ReusableConfirmationDialog } from '@/components/shared/Modals/ReusableConfirmationDialog'; | |
| import TableDataOptionsOperation from '@/components/shared/Tables/options/TableDataOptionsOperation'; | |
| import { | |
| confirmationModalActions, | |
| confirmationModalThunkActions, | |
| } from '@/features/confirmation'; | |
| import { selectGroupsState } from '@/features/groups'; | |
| import { useAppDispatch, useAppSelector } from '@/shared/hooks'; | |
| import { useConfirmationModalManagement } from '@/shared/hooks/use-confirmation-modal'; | |
| import { useMounted } from '@/shared/hooks/use-mounted'; | |
| import GeneralInformationProject from './ProjectGeneralInformation'; | |
| export type DroppableAreaTypeEquipmentSet = | |
| | 'available-droppable' | |
| | 'result-droppable'; | |
| function SettingProjectCreateUpdate() { | |
| const dispatch = useAppDispatch(); | |
| const isMounted = useMounted(); | |
| const router = useRouter(); | |
| const groupsData = useSelector(selectGroupsState).value; | |
| const anchorRef = useRef<HTMLButtonElement>(null); | |
| const fileInputRef = useRef<HTMLInputElement>(null); | |
| const [open, setOpen] = useState(false); | |
| const [testWbsData, setTestWbsData] = useState< | |
| Array<{ id: string; name: string }> | |
| >([]); | |
| const [startDraggingFrom, setStartDraggingFrom] = useState< | |
| DroppableAreaTypeEquipmentSet | undefined | |
| >(); | |
| const [initialValues, setInitialValues] = useState({ | |
| name: ``, | |
| reference: ``, | |
| group: { id: ``, name: `` }, | |
| description: ``, | |
| wbs: null, | |
| submit: null, | |
| }); | |
| const { | |
| open: openConfirmation, | |
| isOpened, | |
| confirm, | |
| decline, | |
| } = useConfirmationModalManagement( | |
| dispatch, | |
| confirmationModalThunkActions.importConfirmationOpen, | |
| confirmationModalActions.confirmConfirmationImport, | |
| confirmationModalActions.declineConfirmationImport, | |
| `isImportConfirmationOpen`, | |
| ); | |
| const { | |
| setFieldValue, | |
| values, | |
| touched, | |
| errors, | |
| isSubmitting, | |
| handleSubmit, | |
| handleBlur, | |
| } = useFormik({ | |
| initialValues, | |
| enableReinitialize: true, | |
| validationSchema: Yup.object({ | |
| name: Yup.string() | |
| .max(255) | |
| .required(`Field name cannot be empty!`) | |
| .matches(/^\S*$/, `Whitespace is not allowed in the field`), | |
| reference: Yup.string() | |
| .matches(/^([a-zA-Z0-9-_. ]+)$/, `The format is not valid`) | |
| .max(255) | |
| .nullable() | |
| .notRequired(), | |
| description: Yup.string().max(255).nullable().notRequired(), | |
| group: Yup.object({ | |
| id: Yup.string().max(255).required(`Group ID is empty!`), | |
| name: Yup.string().max(255).required(`Group name is not present!`), | |
| }), | |
| }), | |
| onSubmit: async (values, helpers): Promise<void> => { | |
| try { | |
| const bodyRequest = { | |
| name: values.name, | |
| reference: values.reference, | |
| groupId: [values.group.id], | |
| description: values.description, | |
| active: false, | |
| ownerOrganization: { id: values.group.id }, | |
| }; | |
| } catch (err) { | |
| console.error(err); | |
| if (isMounted()) { | |
| helpers.setStatus({ success: false }); | |
| helpers.setErrors({ submit: (err as Error).message }); | |
| helpers.setSubmitting(false); | |
| } | |
| } | |
| }, | |
| }); | |
| const handleClick = () => { | |
| fileInputRef.current!.click(); | |
| }; | |
| const handleUploadConfirmation = async (fileData: File) => { | |
| const isConfirmed = await openConfirmation(); | |
| if (isConfirmed) { | |
| // dispatch(uploadImportProjects(fileData)); | |
| } | |
| }; | |
| const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => { | |
| const { files } = event.target; | |
| const selectedFiles = files as FileList; | |
| if (selectedFiles[0]) { | |
| handleUploadConfirmation(selectedFiles[0]); | |
| } | |
| }; | |
| const handleToggle = () => { | |
| setOpen((prevOpen) => !prevOpen); | |
| }; | |
| const handleClose = (event: Event | React.SyntheticEvent) => { | |
| if ( | |
| anchorRef.current && | |
| anchorRef.current.contains(event.target as HTMLElement) | |
| ) { | |
| return; | |
| } | |
| setOpen(false); | |
| }; | |
| function handleListKeyDown(event: React.KeyboardEvent) { | |
| if (event.key === `Tab`) { | |
| event.preventDefault(); | |
| setOpen(false); | |
| } else if (event.key === `Escape`) { | |
| setOpen(false); | |
| } | |
| } | |
| // return focus to the button when we transitioned from !open -> open | |
| const prevOpen = React.useRef(open); | |
| useEffect(() => { | |
| if (prevOpen.current && !open) { | |
| anchorRef.current!.focus(); | |
| } | |
| prevOpen.current = open; | |
| }, [open]); | |
| const onDropWbs = (result: DropResult) => { | |
| setStartDraggingFrom(undefined); | |
| if ( | |
| !result.destination || | |
| result.source.droppableId === result.destination.droppableId | |
| ) { | |
| return; | |
| } | |
| if (result.destination.droppableId === `result-droppable`) { | |
| } else { | |
| } | |
| }; | |
| const onDragStarted = (start: DragStart) => { | |
| setStartDraggingFrom( | |
| start.source.droppableId as DroppableAreaTypeEquipmentSet, | |
| ); | |
| }; | |
| return ( | |
| <> | |
| <form noValidate onSubmit={handleSubmit}> | |
| <Grid container spacing={1}> | |
| <ReusableCreationFormHeader | |
| titlePage={router.query?.id ? `Edit project` : `New project`} | |
| textButton="Save project" | |
| isSubmitting={isSubmitting} | |
| handleClick={() => { | |
| router.push({ | |
| pathname: `/settings/projects`, | |
| }); | |
| }} | |
| /> | |
| <Grid item xs={4}> | |
| <GeneralInformationProject | |
| touched={touched} | |
| errors={errors} | |
| values={values} | |
| setFieldValue={setFieldValue} | |
| groupsData={groupsData} | |
| handleBlur={handleBlur} | |
| /> | |
| </Grid> | |
| <Grid item xs={8}> | |
| <ReusablePageHeader title="Work Breakdown Structure"> | |
| <Box sx={{ display: `flex`, gap: 1 }}> | |
| <TableDataOptionsOperation | |
| anchorRef={anchorRef} | |
| fileInputRef={fileInputRef} | |
| openPopover={open} | |
| templateOption={{ | |
| url: `projects/importTemplate`, | |
| fileName: `projects-imported`, | |
| type: `template`, | |
| }} | |
| exportOption={{ | |
| url: `projects/export`, | |
| fileName: `projects-exported`, | |
| type: `export`, | |
| }} | |
| handleClick={handleClick} | |
| handleToggle={handleToggle} | |
| handleClose={handleClose} | |
| handleListKeyDown={handleListKeyDown} | |
| handleFileChange={handleFileChange} | |
| /> | |
| </Box> | |
| </ReusablePageHeader> | |
| <DragDropContext onDragEnd={onDropWbs} onDragStart={onDragStarted}> | |
| <Grid container spacing={1} sx={{ mt: 0.5 }}> | |
| <Grid item xs={12}> | |
| <Button fullWidth variant="contained" color="primary"> | |
| <Box | |
| sx={{ | |
| display: `flex`, | |
| justifyContent: `space-between`, | |
| alignItems: `center`, | |
| width: `100%`, | |
| }} | |
| onClick={() => | |
| setTestWbsData((prevState) => { | |
| return [ | |
| ...prevState, | |
| { id: `${Date.now()}`, name: `snoop` }, | |
| ]; | |
| }) | |
| } | |
| > | |
| <Box>Add new WBS root element</Box> | |
| <AddIcon /> | |
| </Box> | |
| </Button> | |
| {testWbsData.length > 0 && | |
| testWbsData.map((item) => { | |
| return ( | |
| <Box | |
| sx={{ | |
| display: `flex`, | |
| alignItems: `center`, | |
| justifyContent: `space-between`, | |
| width: `100%`, | |
| borderRadius: `5px`, | |
| backgroundColor: `white`, | |
| mt: 1, | |
| }} | |
| key={item.id} | |
| > | |
| <Box | |
| sx={{ | |
| display: `flex`, | |
| alignItems: `center`, | |
| gap: 1, | |
| flex: 2, | |
| pl: 1, | |
| }} | |
| > | |
| <Button | |
| size="medium" | |
| color="info" | |
| variant="contained" | |
| sx={{ minWidth: `34px` }} | |
| > | |
| <ExpandMoreIcon | |
| fontSize="medium" | |
| fontWeight="800" | |
| /> | |
| </Button> | |
| <EditableTextField | |
| isTextFieldDisabled={false} | |
| handleChangeEvent={(event) => null} | |
| type="text" | |
| textValue="Snoop Dogg" | |
| name="name" | |
| handleBlur={() => null} | |
| placeholder="Name" | |
| size="small" | |
| customSx={{ py: 1 }} | |
| /> | |
| <EditableTextField | |
| isTextFieldDisabled={false} | |
| handleChangeEvent={(event) => null} | |
| type="text" | |
| textValue="Dogg-1" | |
| name="name" | |
| handleBlur={() => null} | |
| placeholder="Reference" | |
| size="small" | |
| customSx={{ py: 1 }} | |
| /> | |
| </Box> | |
| <Box | |
| sx={{ | |
| display: `flex`, | |
| alignItems: `center`, | |
| flex: 0.5, | |
| justifyContent: `end`, | |
| pr: 1, | |
| }} | |
| > | |
| <IconButton onClick={() => null} color="info"> | |
| <ModeEditIcon /> | |
| </IconButton> | |
| <IconButton onClick={() => null} color="error"> | |
| <DeleteIcon /> | |
| </IconButton> | |
| <IconButton> | |
| <DragHandleIcon /> | |
| </IconButton> | |
| </Box> | |
| </Box> | |
| ); | |
| })} | |
| </Grid> | |
| </Grid> | |
| </DragDropContext> | |
| </Grid> | |
| </Grid> | |
| </form> | |
| <ReusableConfirmationDialog | |
| title={`Warning`} | |
| bodyMessage={`If the WBS that you are about to import don't have a reference, new entries will be created and assigned an auto-generated reference.`} | |
| actionText={`Are you sure you want to proceed with the import?`} | |
| onConfirm={confirm} | |
| onDecline={decline} | |
| open={isOpened} | |
| /> | |
| </> | |
| ); | |
| } | |
| export default SettingProjectCreateUpdate; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment