From fbf161c83f711925becb5d1331caef4c08a88a0e Mon Sep 17 00:00:00 2001 From: "MSI\\derek" Date: Mon, 13 May 2024 16:33:13 +0800 Subject: [PATCH] update create staff --- src/app/api/staff/actions.ts | 26 +- .../ChangePassword/ChangePassword.tsx | 4 +- src/components/CreateStaff/CreateStaff.tsx | 280 +++++----- src/components/CreateStaff/StaffInfo.tsx | 514 ++++++++++++++++++ .../CreateStaffForm/CreateStaffForm.tsx | 224 ++++---- 5 files changed, 763 insertions(+), 285 deletions(-) create mode 100644 src/components/CreateStaff/StaffInfo.tsx diff --git a/src/app/api/staff/actions.ts b/src/app/api/staff/actions.ts index a5e88d4..88375d0 100644 --- a/src/app/api/staff/actions.ts +++ b/src/app/api/staff/actions.ts @@ -15,25 +15,25 @@ export interface CreateCustomInputs { export interface CreateStaffInputs { name: string; - currentPositionId: number; - joinPositionId: number; + staffId: string; companyId: number; - gradeId: number; - teamId: number; salaryId: number; - email: string; + skillSetId?: number[]; + joinDate: string; + currentPositionId: number; + joinPositionId: number; + gradeId?: number; + teamId?: number + departmentId: number; phone1: string; - phone2: string; - hourlyRate: string | number; + phone2?: string; + email: string; emergContactName: string; emergContactPhone: string; employType: string; - joinDate: string | null; - departDate?: string | null; - departReason?: string | null; - remark?: string | null; - staffId: string | null; - skillSetId?: number[] | number | null | undefined + departDate?: string; + departReason?: string; + remark?: string; } export interface records { diff --git a/src/components/ChangePassword/ChangePassword.tsx b/src/components/ChangePassword/ChangePassword.tsx index 33e19ff..1fc384f 100644 --- a/src/components/ChangePassword/ChangePassword.tsx +++ b/src/components/ChangePassword/ChangePassword.tsx @@ -53,8 +53,8 @@ const ChangePassword: React.FC = () => { password: data.password, newPassword: data.newPassword } - // await changePassword(postData) - // router.replace("/home") + await changePassword(postData) + router.replace("/home") } catch (e) { console.log(e) setServerError(t("An error has occurred. Please try again later.")); diff --git a/src/components/CreateStaff/CreateStaff.tsx b/src/components/CreateStaff/CreateStaff.tsx index 00fa507..cc40474 100644 --- a/src/components/CreateStaff/CreateStaff.tsx +++ b/src/components/CreateStaff/CreateStaff.tsx @@ -11,7 +11,7 @@ import { useForm, } from "react-hook-form"; import { CreateStaffInputs, saveStaff, testing } from "@/app/api/staff/actions"; -import { Typography } from "@mui/material"; +import { Button, Stack, Typography } from "@mui/material"; import CreateStaffForm from "../CreateStaffForm"; import { comboProp, fetchCompanyCombo } from "@/app/api/companys/actions"; import { fetchTeamCombo } from "@/app/api/team/actions"; @@ -20,6 +20,8 @@ import { fetchPositionCombo } from "@/app/api/positions/actions"; import { fetchGradeCombo } from "@/app/api/grades/actions"; import { fetchSkillCombo } from "@/app/api/skill/actions"; import { fetchSalaryCombo } from "@/app/api/salarys/actions"; +import StaffInfo from "./StaffInfo"; +import { Check, Close } from "@mui/icons-material"; interface Field { id: string; @@ -43,171 +45,133 @@ export interface comboItem { } interface formProps { - Title?: string[]; + // Title?: string[]; combos: comboItem; } -const CreateStaff: React.FC = ({ Title, combos }) => { +const CreateStaff: React.FC = ({ combos }) => { const { t } = useTranslation(); + const formProps = useForm(); + const [serverError, setServerError] = useState(""); + const router = useRouter(); + const [tabIndex, setTabIndex] = useState(0); + + const errors = formProps.formState.errors; + + const onSubmit = useCallback>( + async (data) => { + try { + console.log(data); + let haveError = false; + let regex_email = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/ + let regex_phone = /^\d{8}$/ + + if (!regex_email.test(data.email)) { + haveError = true + formProps.setError("email", { message: t("Please Enter Correct Email."), type: "required" }) + } + if(!regex_phone.test(data.phone1)) { + haveError = true + formProps.setError("phone1", { message: t("Please Enter Correct Phone No.."), type: "required" }) + } + if(!regex_phone.test(data.emergContactPhone)) { + haveError = true + formProps.setError("emergContactPhone", { message: t("Please Enter Correct Phone No.."), type: "required" }) + } + if (data.phone2 && data.phone2?.length > 0) { + if(!regex_phone.test(data.phone2)) { + haveError = true + formProps.setError("phone2", { message: t("Please Enter Correct Phone No.."), type: "required" }) + } + } + if (!regex_email.test(data.email)) { + haveError = true + formProps.setError("email", { message: t("Please Enter Correct Email."), type: "required" }) + } + if (!data.companyId) { + haveError = true + formProps.setError("companyId", { message: t("Please Enter Company."), type: "required" }) + } + if (!data.gradeId) { + haveError = true + formProps.setError("gradeId", { message: t("Please Enter grade."), type: "required" }) + } + if (!data.employType) { + haveError = true + formProps.setError("employType", { message: t("Please Enter Employ Type."), type: "required" }) + } + if (!data.departmentId) { + haveError = true + formProps.setError("departmentId", { message: t("Please Enter Department."), type: "required" }) + } + if (!data.salaryId) { + haveError = true + formProps.setError("salaryId", { message: t("Please Enter Salary."), type: "required" }) + } + if (!data.joinDate) { + haveError = true + formProps.setError("joinDate", { message: t("Please Enter Join Date."), type: "required" }) + } + if (data.departDate && new Date(data.departDate) <= new Date(data.joinDate)) { + haveError = true + formProps.setError("departDate", { message: t("Depart Date cannot be earlier than Join Date."), type: "required" }) + } + // if (!data.joinPositionId) { + // haveError = true + // formProps.setError("joinPositionId", { message: t("Depart Date cannot be earlier than Join Date."), type: "required" }) + // } + if (haveError) { + return + } + console.log("passed") + await saveStaff(data) + router.replace("/settings/staff") + } catch (e) { + console.log(e); + setServerError(t("An error has occurred. Please try again later.")); + } + }, + [router] + ); + + const handleCancel = () => { + router.back(); + }; - const fieldLists: Field[][] = [ - [ - { - id: "staffId", - label: t("Staff ID"), - type: "text", - required: true, - }, - { - id: "name", - label: t("Staff Name"), - type: "text", - required: true, - }, - { - id: "companyId", - label: t("Company"), - type: "combo-Obj", - options: combos.company || [], - required: true, - }, - { - id: "teamId", - label: t("Team"), - type: "combo-Obj", - options: combos.team || [], - required: false, - }, - { - id: "departmentId", - label: t("Department"), - type: "combo-Obj", - options: combos.department || [], - required: true, - }, - { - id: "gradeId", - label: t("Grade"), - type: "combo-Obj", - options: combos.grade || [], - required: false, - }, - { - id: "skillSetId", - label: t("Skillset"), - type: "multiSelect-Obj", - options: combos.skill || [], - required: false, - }, - { - id: "currentPositionId", - label: t("Current Position"), - type: "combo-Obj", - options: combos.position || [], - required: true, - }, - { - id: "salaryId", - label: t("Salary Point"), - type: "combo-Obj", - options: combos.salary || [], - required: true, - }, - // { - // id: "hourlyRate", - // label: t("Hourly Rate"), - // type: "numeric-testing", - // value: "", - // required: false, - // }, - // { - // id: "hourlyRate", - // label: t("Hourly Rate"), - // type: "numeric-testing", - // required: true, - // }, - { - id: "employType", - label: t("Employ Type"), - type: "combo-Obj", - options: [{id: "FT", label: t("FT")}, {id: "PT", label: t("PT")}], - value: "", - required: true, - }, - { - id: "email", - label: t("Email"), - type: "text", - pattern: "^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$", - message: t("input matching format"), - required: true, - }, - { - id: "phone1", - label: t("Phone1"), - type: "text", - pattern: "^\\d{8}$", - message: t("input correct phone no."), - required: true, - }, - { - id: "phone2", - label: t("Phone2"), - type: "text", - pattern: "^\\d{8}$", - message: t("input correct phone no."), - required: false, - }, - ], - [ - { - id: "emergContactName", - label: t("Emergency Contact Name"), - type: "text", - required: true, - }, - { - id: "emergContactPhone", - label: t("Emergency Contact Phone"), - type: "text", - pattern: "^\\d{8}$", - message: t("input correct phone no."), - required: true, - }, - { - id: "joinDate", - label: t("Join Date"), - type: "multiDate", - required: true, - }, - { - id: "joinPositionId", - label: t("Join Position"), - type: "combo-Obj", - options: combos.position || [], - required: true, - }, - { - id: "departDate", - label: t("Depart Date"), - type: "multiDate", - }, - { - id: "departReason", - label: t("Depart Reason"), - type: "text", - }, - { - id: "remark", - label: t("Remark"), - type: "remarks", - }, - ] - ]; return ( <> - + + + {serverError && ( + + {serverError} + + )} + + + + + + + ); }; diff --git a/src/components/CreateStaff/StaffInfo.tsx b/src/components/CreateStaff/StaffInfo.tsx new file mode 100644 index 0000000..333be87 --- /dev/null +++ b/src/components/CreateStaff/StaffInfo.tsx @@ -0,0 +1,514 @@ +"use client"; +import Stack from "@mui/material/Stack"; +import Box from "@mui/material/Box"; +import Card from "@mui/material/Card"; +import CardContent from "@mui/material/CardContent"; +import Grid from "@mui/material/Grid"; +import TextField from "@mui/material/TextField"; +import Typography from "@mui/material/Typography"; +import { CreateGroupInputs } from "@/app/api/group/actions"; +import { Controller, useFormContext } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { useCallback, useEffect } from "react"; +import { CreateStaffInputs } from "@/app/api/staff/actions"; +import { + Checkbox, + FormControl, + InputLabel, + ListItemText, + MenuItem, + Select, +} from "@mui/material"; +import { comboItem } from "./CreateStaff"; +import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers"; +import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; +import { DemoItem } from "@mui/x-date-pickers/internals/demo"; +import dayjs from "dayjs"; +import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; + +interface Props { + combos: comboItem; +} + +const StaffInfo: React.FC = ({ combos }) => { + const { + t, + i18n: { language }, + } = useTranslation(); + const { + register, + formState: { errors, defaultValues }, + control, + reset, + resetField, + setValue, + getValues, + clearErrors + } = useFormContext(); + + const employType = [ + { id: 1, label: "FT" }, + { id: 2, label: "PT" }, + ]; + + const skillIdNameMap = combos.skill.reduce<{ [id: number]: string }>( + (acc, skill) => ({ ...acc, [skill.id]: skill.label }), + {} + ); + + const resetStaff = useCallback(() => { + console.log(defaultValues); + if (defaultValues !== undefined) { + // resetField("description"); + } + }, [defaultValues]); + + const joinDate = getValues("joinDate"); + const departDate = getValues("departDate"); + + useEffect(() => { + if(joinDate) + clearErrors("joinDate") + if(departDate) + clearErrors("departDate") + }, [joinDate, departDate]) + + return ( + + + + + {t("Staff")} + + + + + + + + + + + {t("Company")} + ( + + )} + /> + + + + + {t("Team")} + ( + + )} + /> + + + + + {t("Department")} + ( + + )} + /> + + + + + {t("Grade")} + ( + + )} + /> + + + + + {t("Skillset")} + ( + + )} + /> + + + + + {t("Current Position")} + ( + + )} + /> + + + + + {t("Salary Point")} + ( + + )} + /> + + + + + {t("Employ Type")} + ( + + )} + /> + + + + + + + + + + + + + + + + + + + + + + { + if (!date) return; + setValue("joinDate", date.format(INPUT_DATE_FORMAT)); + }} + slotProps={{ + textField: { + error: + joinDate === "Invalid Date" || Boolean(errors.joinDate), + // value: errors.joinDate?.message, + }, + }} + /> + + + + + {t("Join Position")} + ( + + )} + /> + + + + + { + if (!date) return; + setValue("departDate", date.format(INPUT_DATE_FORMAT)); + }} + slotProps={{ + textField: { + error: departDate === "Invalid Date", + // value: errors.departDate?.message, + }, + }} + /> + + + + + + + + + + + + + ); +}; + +export default StaffInfo; diff --git a/src/components/CreateStaffForm/CreateStaffForm.tsx b/src/components/CreateStaffForm/CreateStaffForm.tsx index 3ec7ca2..5cf24ca 100644 --- a/src/components/CreateStaffForm/CreateStaffForm.tsx +++ b/src/components/CreateStaffForm/CreateStaffForm.tsx @@ -1,120 +1,120 @@ -import { useCallback, useState } from "react"; -import CustomInputForm from "../CustomInputForm"; -import { useRouter } from "next/navigation"; -import { useTranslation } from "react-i18next"; -import { - FieldErrors, - FormProvider, - SubmitErrorHandler, - SubmitHandler, - useForm, -} from "react-hook-form"; -import { CreateStaffInputs, saveStaff, testing } from "@/app/api/staff/actions"; -import { Typography } from "@mui/material"; +// import { useCallback, useState } from "react"; +// import CustomInputForm from "../CustomInputForm"; +// import { useRouter } from "next/navigation"; +// import { useTranslation } from "react-i18next"; +// import { +// FieldErrors, +// FormProvider, +// SubmitErrorHandler, +// SubmitHandler, +// useForm, +// } from "react-hook-form"; +// import { CreateStaffInputs, saveStaff, testing } from "@/app/api/staff/actions"; +// import { Typography } from "@mui/material"; -interface Field { - // subtitle: string; - id: string; - label: string; - type: string; - value?: any; - required?: boolean; - options?: any[]; - readOnly?: boolean; -} +// interface Field { +// // subtitle: string; +// id: string; +// label: string; +// type: string; +// value?: any; +// required?: boolean; +// options?: any[]; +// readOnly?: boolean; +// } -interface formProps { - Title?: string[]; - fieldLists: Field[][]; -} +// interface formProps { +// Title?: string[]; +// fieldLists: Field[][]; +// } -const CreateStaffForm: React.FC = ({ Title, fieldLists }) => { - const router = useRouter(); - const { t } = useTranslation(); - const [serverError, setServerError] = useState(""); +// const CreateStaffForm: React.FC = ({ Title, fieldLists }) => { +// const router = useRouter(); +// const { t } = useTranslation(); +// const [serverError, setServerError] = useState(""); - const handleCancel = () => { - router.back(); - }; - const onSubmit = useCallback>( - async (data) => { - try { - console.log(data); - let haveError = false; - //check if joinDate exist - if (data.joinDate == null && data.joinDate == "Invalid Date") { - haveError = true; - return haveError; - } - //check if joinDate > departDate - if (data.departDate != null && data.departDate != "Invalid Date" && data.departDate.length != 0) { - if (data.joinDate != null) { - const joinDate = new Date(data.joinDate); - const departDate = new Date(data.departDate); - if (joinDate.getTime() > departDate.getTime()) { - haveError = true; - return haveError; - } - } - if (data.departReason == null || data.departReason.length == 0) { - haveError = true; - return haveError; - } - } +// const handleCancel = () => { +// router.back(); +// }; +// const onSubmit = useCallback>( +// async (data) => { +// try { +// console.log(data); +// let haveError = false; +// //check if joinDate exist +// if (data.joinDate == null && data.joinDate == "Invalid Date") { +// haveError = true; +// return haveError; +// } +// //check if joinDate > departDate +// if (data.departDate != null && data.departDate != "Invalid Date" && data.departDate.length != 0) { +// if (data.joinDate != null) { +// const joinDate = new Date(data.joinDate); +// const departDate = new Date(data.departDate); +// if (joinDate.getTime() > departDate.getTime()) { +// haveError = true; +// return haveError; +// } +// } +// if (data.departReason == null || data.departReason.length == 0) { +// haveError = true; +// return haveError; +// } +// } - if (haveError) { - return - } - const postData = { - ...data, - skillSetId: typeof data.skillSetId === "number" ? [data.skillSetId] : data.skillSetId, - emergContactPhone: data.emergContactPhone.toString(), - phone1: data.phone1.toString(), - phone2: data.phone2.toString(), - hourlyRate: typeof data.hourlyRate === 'string' ? parseInt(data.hourlyRate.replace("$", "").replace(",", "")) : 0 - }; - if (postData.departDate?.length === 0 && postData.departReason?.length === 0) { - delete postData.departDate; - delete postData.departReason; - } - if (postData.remark?.length === 0) { - delete postData.remark; - } - console.log(postData); - setServerError(""); - await saveStaff(postData); - router.replace("/settings/staff"); - } catch (e) { - setServerError(t("An error has occurred. Please try again later.")); - } - }, - [router, t] - ); +// if (haveError) { +// return +// } +// const postData = { +// ...data, +// skillSetId: typeof data.skillSetId === "number" ? [data.skillSetId] : data.skillSetId, +// emergContactPhone: data.emergContactPhone.toString(), +// phone1: data.phone1.toString(), +// phone2: data.phone2.toString(), +// hourlyRate: typeof data.hourlyRate === 'string' ? parseInt(data.hourlyRate.replace("$", "").replace(",", "")) : 0 +// }; +// if (postData.departDate?.length === 0 && postData.departReason?.length === 0) { +// delete postData.departDate; +// delete postData.departReason; +// } +// if (postData.remark?.length === 0) { +// delete postData.remark; +// } +// console.log(postData); +// setServerError(""); +// await saveStaff(postData); +// router.replace("/settings/staff"); +// } catch (e) { +// setServerError(t("An error has occurred. Please try again later.")); +// } +// }, +// [router, t] +// ); - const onSubmitError = useCallback>( - (errors) => { - console.log(errors); - }, - [] - ); +// const onSubmitError = useCallback>( +// (errors) => { +// console.log(errors); +// }, +// [] +// ); - return ( - <> - {serverError && ( - - {serverError} - - )} - - - ); -}; +// return ( +// <> +// {serverError && ( +// +// {serverError} +// +// )} +// +// +// ); +// }; -export default CreateStaffForm; +// export default CreateStaffForm;