Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/frontend/src/components/NERFormModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ReactNode } from 'react';
import { FieldValues, UseFormHandleSubmit, UseFormReset } from 'react-hook-form';
import NERModal, { NERModalProps } from './NERModal';
import { useToast } from '../hooks/toasts.hooks';

interface NERFormModalProps<T extends FieldValues> extends NERModalProps {
reset: UseFormReset<T>;
Expand All @@ -27,18 +28,23 @@ const NERFormModal = ({
hideBackDrop = false,
paperProps
}: NERFormModalProps<any>) => {
const toast = useToast();
/**
* Wrapper function for onSubmit so that form data is reset after submit
*/
const onSubmitWrapper = async (data: any) => {
await onFormSubmit(data);
reset();
try {
await onFormSubmit(data);
reset();
} catch (e: unknown) {
if (e instanceof Error) toast.error(e.message, 6000);
}
};

const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
const handleFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
e.stopPropagation(); // Prevent event bubbling
handleUseFormSubmit(onSubmitWrapper)(e);
await handleUseFormSubmit(onSubmitWrapper)(e);
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,14 @@ import { yupResolver } from '@hookform/resolvers/yup';
import { Autocomplete, FormControl, FormHelperText, FormLabel, Grid, MenuItem, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { Controller, useForm } from 'react-hook-form';
import { countWords, isGuest, isUnderWordCount, notGuest, Task, TaskPriority, TeamPreview } from 'shared';
import { countWords, isGuest, isUnderWordCount, notGuest, Task, TaskStatus, TaskPriority, TeamPreview } from 'shared';
import { useAllUsers, useCurrentUser } from '../../../../hooks/users.hooks';
import * as yup from 'yup';
import { taskUserToAutocompleteOption } from '../../../../utils/task.utils';
import NERFormModal from '../../../../components/NERFormModal';
import LoadingIndicator from '../../../../components/LoadingIndicator';
import ErrorPage from '../../../ErrorPage';

const schema = yup.object().shape({
notes: yup.string().optional(),
startDate: yup.date().optional(),
deadline: yup.date().optional(),
priority: yup.mixed<TaskPriority>().oneOf(Object.values(TaskPriority)).required(),
assignees: yup.array().required(),
title: yup.string().required(),
taskId: yup.string().required()
});

export interface EditTaskFormInput {
taskId: string;
title: string;
Expand All @@ -32,14 +22,53 @@ export interface EditTaskFormInput {

interface TaskFormModalProps {
task?: Task;
status?: Task['status'];
teams: TeamPreview[];
modalShow: boolean;
onHide: () => void;
onSubmit: (data: EditTaskFormInput) => Promise<void>;
onReset?: () => void;
}

const TaskFormModal: React.FC<TaskFormModalProps> = ({ task, onSubmit, modalShow, onHide, onReset }) => {
const TaskFormModal: React.FC<TaskFormModalProps> = ({ task, status, onSubmit, modalShow, onHide, onReset }) => {
let schema;

if (status === TaskStatus.IN_PROGRESS) {
schema = yup.object().shape({
notes: yup
.string()
.optional()
.test((value) => {
if (!value) return true;
const wordCount = countWords(value);
return wordCount < 250;
}),
startDate: yup.date().optional(),
deadline: yup.date().required('Deadline is required for In Progress tasks'),
priority: yup.mixed<TaskPriority>().oneOf(Object.values(TaskPriority)).required(),
assignees: yup.array().required().min(1, 'At least one assignee is required for In Progress tasks'),
title: yup.string().required(),
taskId: yup.string().required()
});
} else {
schema = yup.object().shape({
notes: yup
.string()
.optional()
.test((value) => {
if (!value) return true;
const wordCount = countWords(value);
return wordCount < 250;
}),
startDate: yup.date().optional(),
deadline: yup.date().optional(),
priority: yup.mixed<TaskPriority>().oneOf(Object.values(TaskPriority)).required(),
assignees: yup.array().required(),
title: yup.string().required(),
taskId: yup.string().required()
});
}

const user = useCurrentUser();

const { data: users, isLoading, isError, error } = useAllUsers();
Expand Down Expand Up @@ -161,6 +190,7 @@ const TaskFormModal: React.FC<TaskFormModalProps> = ({ task, onSubmit, modalShow
/>
)}
/>
<FormHelperText error={!!errors.assignees}>{errors.assignees?.message}</FormHelperText>
</FormControl>
</Grid>
<Grid item md={6}>
Expand Down Expand Up @@ -199,6 +229,7 @@ const TaskFormModal: React.FC<TaskFormModalProps> = ({ task, onSubmit, modalShow
/>
)}
/>
<FormHelperText error={!!errors.deadline}>{errors.deadline?.message}</FormHelperText>
</FormControl>
</Grid>
<Grid item xs={12} md={12}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,25 @@ export const TaskColumn = ({
const theme = useTheme();

const handleCreateTask = async ({ notes, title, deadline, assignees, priority, startDate }: EditTaskFormInput) => {
try {
const task = await createTask({
wbsNum: project.wbsNum,
title,
deadline: deadline ? transformDate(deadline) : undefined,
startDate: startDate ? transformDate(startDate) : undefined,
priority,
status: status as TaskStatus,
assignees,
notes
});
onAddTask(task);
toast.success('Task Successfully Created!');
} catch (e: unknown) {
if (e instanceof Error) {
toast.error(e.message, 6000);
}
}
const task = await createTask({
wbsNum: project.wbsNum,
title,
deadline: deadline ? transformDate(deadline) : undefined,
startDate: startDate ? transformDate(startDate) : undefined,
priority,
status: status as TaskStatus,
assignees,
notes
});
onAddTask(task);
toast.success('Task Successfully Created!');
setShowCreateTaskModal(false);
};

return (
<>
<TaskFormModal
status={status}
onSubmit={handleCreateTask}
onHide={() => setShowCreateTaskModal(false)}
modalShow={showCreateTaskModal}
Expand Down
Loading