Skip to content

Instantly share code, notes, and snippets.

@zourdyzou
Created May 27, 2023 18:55
Show Gist options
  • Select an option

  • Save zourdyzou/8c8414ca8e4324329b5f9b8e325df4af to your computer and use it in GitHub Desktop.

Select an option

Save zourdyzou/8c8414ca8e4324329b5f9b8e325df4af to your computer and use it in GitHub Desktop.
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