diff --git a/src/app/(main)/tasks/edit/not-found.tsx b/src/app/(main)/tasks/edit/not-found.tsx
new file mode 100644
index 0000000..b99e85e
--- /dev/null
+++ b/src/app/(main)/tasks/edit/not-found.tsx
@@ -0,0 +1,17 @@
+import { getServerI18n } from "@/i18n";
+import { Stack, Typography, Link } from "@mui/material";
+import NextLink from "next/link";
+
+export default async function NotFound() {
+ const { t } = await getServerI18n("tasks", "common");
+
+ return (
+
+ {t("Not Found")}
+ {t("The task template was not found!")}
+
+ {t("Return to all task templates")}
+
+
+ );
+}
diff --git a/src/app/(main)/tasks/edit/page.tsx b/src/app/(main)/tasks/edit/page.tsx
index 2b2c02c..4872daf 100644
--- a/src/app/(main)/tasks/edit/page.tsx
+++ b/src/app/(main)/tasks/edit/page.tsx
@@ -1,23 +1,44 @@
-import { preloadAllTasks } from "@/app/api/tasks";
+import { fetchTaskTemplate, preloadAllTasks } from "@/app/api/tasks";
import CreateTaskTemplate from "@/components/CreateTaskTemplate";
import { getServerI18n } from "@/i18n";
import Typography from "@mui/material/Typography";
import { Metadata } from "next";
import { I18nProvider } from "@/i18n";
+import { ServerFetchError } from "@/app/utils/fetchUtil";
+import { isArray } from "lodash";
+import { notFound } from "next/navigation";
export const metadata: Metadata = {
title: "Edit Task Template",
};
-const TaskTemplates: React.FC = async () => {
+interface Props {
+ searchParams: { [key: string]: string | string[] | undefined };
+}
+
+const TaskTemplates: React.FC = async ({ searchParams }) => {
const { t } = await getServerI18n("tasks");
+ const taskTemplateId = searchParams["id"];
+
+ if (!taskTemplateId || isArray(taskTemplateId)) {
+ notFound();
+ }
+
preloadAllTasks();
+ try {
+ await fetchTaskTemplate(taskTemplateId);
+ } catch (e) {
+ if (e instanceof ServerFetchError && e.response?.status === 404) {
+ notFound();
+ }
+ }
+
return (
<>
{t("Edit Task Template")}
-
+
>
);
diff --git a/src/app/api/tasks/actions.ts b/src/app/api/tasks/actions.ts
index 2c043be..3414bf6 100644
--- a/src/app/api/tasks/actions.ts
+++ b/src/app/api/tasks/actions.ts
@@ -4,13 +4,26 @@ import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil
import { BASE_API_URL } from "@/config/api";
import { TaskTemplate } from ".";
import { revalidateTag } from "next/cache";
+import { ManhourAllocation } from "@/app/api/projects/actions";
+import { Task, TaskGroup } from '@/app/api/tasks';
export interface NewTaskTemplateFormInputs {
+
+ // task template
code: string;
name: string;
taskIds: number[];
id: number | null;
+
+ // resource allocation template
+ manhourPercentageByGrade: ManhourAllocation;
+ taskGroups: {
+ [taskGroup: TaskGroup["id"]]: {
+ taskIds: Task["id"][];
+ percentAllocation: number;
+ };
+ };
}
export const saveTaskTemplate = async (data: NewTaskTemplateFormInputs) => {
diff --git a/src/app/api/tasks/index.ts b/src/app/api/tasks/index.ts
index f701cca..ba993f0 100644
--- a/src/app/api/tasks/index.ts
+++ b/src/app/api/tasks/index.ts
@@ -39,3 +39,15 @@ export const preloadAllTasks = () => {
export const fetchAllTasks = cache(async () => {
return serverFetchJson(`${BASE_API_URL}/tasks`);
});
+
+export const fetchTaskTemplate = cache(async (id: string) => {
+ const taskTemplate = await serverFetchJson(
+ `${BASE_API_URL}/tasks/templatesDetails/${id}`,
+ {
+ method: "GET",
+ headers: { "Content-Type": "application/json" },
+ },
+ );
+
+ return taskTemplate;
+});
diff --git a/src/components/CreateTaskTemplate/CreateTaskTemplate.tsx b/src/components/CreateTaskTemplate/CreateTaskTemplate.tsx
index f7d5912..856f66e 100644
--- a/src/components/CreateTaskTemplate/CreateTaskTemplate.tsx
+++ b/src/components/CreateTaskTemplate/CreateTaskTemplate.tsx
@@ -13,7 +13,7 @@ import Close from "@mui/icons-material/Close";
import { useRouter, useSearchParams } from "next/navigation";
import React from "react";
import Stack from "@mui/material/Stack";
-import { Task } from "@/app/api/tasks";
+import { Task, TaskTemplate } from "@/app/api/tasks";
import {
NewTaskTemplateFormInputs,
fetchTaskTemplate,
@@ -24,9 +24,10 @@ import { errorDialog, submitDialog, successDialog } from "../Swal/CustomAlerts";
interface Props {
tasks: Task[];
+ defaultInputs?: TaskTemplate;
}
-const CreateTaskTemplate: React.FC = ({ tasks }) => {
+const CreateTaskTemplate: React.FC = ({ tasks, defaultInputs }) => {
const { t } = useTranslation();
const searchParams = useSearchParams()
@@ -54,45 +55,45 @@ const CreateTaskTemplate: React.FC = ({ tasks }) => {
watch,
resetField,
formState: { errors, isSubmitting },
- } = useForm({ defaultValues: { taskIds: [] } });
+ } = useForm({ defaultValues: defaultInputs });
const currentTaskIds = watch("taskIds");
const selectedItems = React.useMemo(() => {
return items.filter((item) => currentTaskIds.includes(item.id));
}, [currentTaskIds, items]);
- const [refTaskTemplate, setRefTaskTemplate] = React.useState()
- const id = searchParams.get('id')
-
- const fetchCurrentTaskTemplate = async () => {
- try {
- const taskTemplate = await fetchTaskTemplate(parseInt(id!!))
-
- const defaultValues = {
- id: parseInt(id!!),
- code: taskTemplate.code ?? null,
- name: taskTemplate.name ?? null,
- taskIds: taskTemplate.tasks.map(task => task.id) ?? [],
- }
-
- setRefTaskTemplate(defaultValues)
- } catch (e) {
- console.log(e)
- }
- }
-
- React.useLayoutEffect(() => {
- if (id !== null && parseInt(id) > 0) fetchCurrentTaskTemplate()
- }, [id])
-
- React.useEffect(() => {
- if (refTaskTemplate) {
- setValue("taskIds", refTaskTemplate.taskIds)
- resetField("code", { defaultValue: refTaskTemplate.code })
- resetField("name", { defaultValue: refTaskTemplate.name })
- setValue("id", refTaskTemplate.id)
- }
- }, [refTaskTemplate])
+ // const [refTaskTemplate, setRefTaskTemplate] = React.useState()
+ // const id = searchParams.get('id')
+
+ // const fetchCurrentTaskTemplate = async () => {
+ // try {
+ // const taskTemplate = await fetchTaskTemplate(parseInt(id!!))
+
+ // const defaultValues = {
+ // id: parseInt(id!!),
+ // code: taskTemplate.code ?? null,
+ // name: taskTemplate.name ?? null,
+ // taskIds: taskTemplate.tasks.map(task => task.id) ?? [],
+ // }
+
+ // setRefTaskTemplate(defaultValues)
+ // } catch (e) {
+ // console.log(e)
+ // }
+ // }
+
+ // React.useLayoutEffect(() => {
+ // if (id !== null && parseInt(id) > 0) fetchCurrentTaskTemplate()
+ // }, [id])
+
+ // React.useEffect(() => {
+ // if (refTaskTemplate) {
+ // setValue("taskIds", refTaskTemplate.taskIds)
+ // resetField("code", { defaultValue: refTaskTemplate.code })
+ // resetField("name", { defaultValue: refTaskTemplate.name })
+ // setValue("id", refTaskTemplate.id)
+ // }
+ // }, [refTaskTemplate])
const onSubmit: SubmitHandler = React.useCallback(
async (data) => {
@@ -120,9 +121,9 @@ const CreateTaskTemplate: React.FC = ({ tasks }) => {
return (
<>
- {
- (id === null || refTaskTemplate !== undefined) &&
+
+ {/* Task List Setup */}
{t("Task List Setup")}
= ({ tasks }) => {
allItemsLabel={t("Task Pool")}
selectedItemsLabel={t("Task List Template")}
/>
+ {/* Task List Setup */}
+ {/* Task List Setup */}
+
{
@@ -188,7 +192,7 @@ const CreateTaskTemplate: React.FC = ({ tasks }) => {
{t("Confirm")}
- }
+
>
);
};
diff --git a/src/components/CreateTaskTemplate/CreateTaskTemplateWrapper.tsx b/src/components/CreateTaskTemplate/CreateTaskTemplateWrapper.tsx
index 77888a2..50a131b 100644
--- a/src/components/CreateTaskTemplate/CreateTaskTemplateWrapper.tsx
+++ b/src/components/CreateTaskTemplate/CreateTaskTemplateWrapper.tsx
@@ -1,11 +1,18 @@
import React from "react";
import CreateTaskTemplate from "./CreateTaskTemplate";
-import { fetchAllTasks } from "@/app/api/tasks";
+import { fetchAllTasks, fetchTaskTemplate } from "@/app/api/tasks";
-const CreateTaskTemplateWrapper: React.FC = async () => {
- const tasks = await fetchAllTasks();
+interface Props {
+ taskTemplateId?: string;
+}
- return ;
+const CreateTaskTemplateWrapper: React.FC = async (props) => {
+ const [tasks] = await Promise.all([
+ fetchAllTasks(),
+ ]);
+
+ const taskTemplateInfo = props.taskTemplateId ? await fetchTaskTemplate(props.taskTemplateId) : undefined
+ return ;
};
export default CreateTaskTemplateWrapper;
diff --git a/src/components/Swal/CustomAlerts.js b/src/components/Swal/CustomAlerts.js
index ad1aec6..5780460 100644
--- a/src/components/Swal/CustomAlerts.js
+++ b/src/components/Swal/CustomAlerts.js
@@ -51,13 +51,17 @@ export const warningDialog = (text, t) => {
})
}
-export const submitDialog = async (confirmAction, t, {...props}) => {
+export const submitDialog = async (confirmAction, t, {...props} = {
+ title: null,
+ confirmButtonText: null
+}) => {
+ // console.log(props)
// const { t } = useTranslation("common")
const result = await Swal.fire({
icon: "question",
- title: props.title ?? t("Do you want to submit?"),
+ title: props?.title ?? t("Do you want to submit?"),
cancelButtonText: t("Cancel"),
- confirmButtonText: props.confirmButtonText ?? t("Submit"),
+ confirmButtonText: props?.confirmButtonText ?? t("Submit"),
showCancelButton: true,
showConfirmButton: true,
customClass: {