| @@ -43,7 +43,7 @@ const CreateStaff: React.FC = async () => { | |||||
| const { t } = await getServerI18n("staff"); | const { t } = await getServerI18n("staff"); | ||||
| const title = ['', t('Additional Info')] | const title = ['', t('Additional Info')] | ||||
| // const regex = new RegExp("^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$") | |||||
| // const regex = new RegExp("^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$") | |||||
| // console.log(regex) | // console.log(regex) | ||||
| const fieldLists = [ | const fieldLists = [ | ||||
| [ | [ | ||||
| @@ -52,8 +52,6 @@ const CreateStaff: React.FC = async () => { | |||||
| label: t("Staff ID"), | label: t("Staff ID"), | ||||
| type: "text", | type: "text", | ||||
| value: "", | value: "", | ||||
| pattern: "^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$", | |||||
| message: t("input matching format"), | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| @@ -67,55 +65,55 @@ const CreateStaff: React.FC = async () => { | |||||
| id: "companyId", | id: "companyId", | ||||
| label: t("Company"), | label: t("Company"), | ||||
| type: "combo-Obj", | type: "combo-Obj", | ||||
| options: [{id: 1, key: 1, value: 1, label: "Company A"}, {id: 2, key: 2, value: 2, label: "Company B"}], | |||||
| options: [{id: 1, label: "Company A"}, {id: 2, label: "Company B"}], | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "teamId", | id: "teamId", | ||||
| label: t("Team"), | label: t("Team"), | ||||
| type: "combo-Obj", | type: "combo-Obj", | ||||
| options: [{id: 1, key: 1, value: 1, label: "A"}, {id: 2, key: 2, value: 2, label: "B"}], | |||||
| options: [{id: 1, label: "A"}, {id: 2, label: "B"}], | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "departmentId", | id: "departmentId", | ||||
| label: t("Department"), | label: t("Department"), | ||||
| type: "combo-Obj", | type: "combo-Obj", | ||||
| options: [{id: 1, key: 1, value: 1, label: "Department A"}, {id: 2, key: 2, value: 2, label: "Department B"}], | |||||
| options: [{id: 1, label: "Department A"}, {id: 2, label: "Department B"}], | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "gradeId", | id: "gradeId", | ||||
| label: t("Grade"), | label: t("Grade"), | ||||
| type: "combo-Obj", | type: "combo-Obj", | ||||
| options: [{id: 1, key: 1, value: 1, label: "A"}, {id: 2, key: 2, value: 2, label: "B"}], | |||||
| options: [{id: 1, label: "A"}, {id: 2, label: "B"}], | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "skillSetId", | id: "skillSetId", | ||||
| label: t("Skillset"), | label: t("Skillset"), | ||||
| type: "combo-Obj", | type: "combo-Obj", | ||||
| options: [{id: 1, key: 1, value: 1, label: "excel"}, {id: 2, key: 2, value: 2, label: "word"}], | |||||
| options: [{id: 1, label: "excel"}, {id: 2, label: "word"}], | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "currentPositionId", | id: "currentPositionId", | ||||
| label: t("Current Position"), | label: t("Current Position"), | ||||
| type: "combo-Obj", | type: "combo-Obj", | ||||
| options: [{id: 1, key: 1, value: 1, label: "pos1"}, {id: 2, key: 2, value: 2, label: "pos2"}], | |||||
| options: [{id: 1, label: "pos1"}, {id: 2, label: "pos2"}], | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "salaryEffId", | id: "salaryEffId", | ||||
| label: t("Salary Point"), | label: t("Salary Point"), | ||||
| type: "combo-Obj", | type: "combo-Obj", | ||||
| options: [{id: 1, key: 1, value: 1, label: t("15")}, {id: 2, key: 2, value: 2, label: t("20")}], | |||||
| options: [{id: 1, label: t("15")}, {id: 2, label: t("20")}], | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "hourlyRate", | id: "hourlyRate", | ||||
| label: t("Hourly Rate"), | label: t("Hourly Rate"), | ||||
| type: "numeric", | |||||
| type: "numeric-testing", | |||||
| value: "", | value: "", | ||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| @@ -123,29 +121,35 @@ const CreateStaff: React.FC = async () => { | |||||
| id: "employType", | id: "employType", | ||||
| label: t("Employ Type"), | label: t("Employ Type"), | ||||
| type: "combo-Obj", | type: "combo-Obj", | ||||
| options: [{id: 1, key: "FT", value: "FT", label: t("FT")}, {id: 2, key: "PT", value: "PT", label: t("PT")}], | |||||
| options: [{id: "FT", label: t("FT")}, {id: "PT", label: t("PT")}], | |||||
| value: "", | value: "", | ||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "email", | id: "email", | ||||
| label: t("Email"), | label: t("Email"), | ||||
| type: "email", | |||||
| type: "text", | |||||
| value: "", | value: "", | ||||
| pattern: "^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$", | |||||
| message: t("input matching format"), | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "phone1", | id: "phone1", | ||||
| label: t("Phone1"), | label: t("Phone1"), | ||||
| type: "numeric", | |||||
| type: "text", | |||||
| value: "", | value: "", | ||||
| pattern: "^\\d{8}$", | |||||
| message: t("input correct phone no."), | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "phone2", | id: "phone2", | ||||
| label: t("Phone2"), | label: t("Phone2"), | ||||
| type: "numeric", | |||||
| type: "text", | |||||
| value: "", | value: "", | ||||
| pattern: "^\\d{8}$", | |||||
| message: t("input correct phone no."), | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| ], | ], | ||||
| @@ -160,8 +164,10 @@ const CreateStaff: React.FC = async () => { | |||||
| { | { | ||||
| id: "emergContactPhone", | id: "emergContactPhone", | ||||
| label: t("Emergency Contact Phone"), | label: t("Emergency Contact Phone"), | ||||
| type: "numeric", | |||||
| type: "text", | |||||
| value: "", | value: "", | ||||
| pattern: "^\\d{8}$", | |||||
| message: t("input correct phone no."), | |||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| { | { | ||||
| @@ -0,0 +1,10 @@ | |||||
| const EditStaff: React.FC = async () => { | |||||
| return ( | |||||
| <> | |||||
| sdsadasd | |||||
| </> | |||||
| ) | |||||
| } | |||||
| export default EditStaff; | |||||
| @@ -34,7 +34,7 @@ const Staff: React.FC = async () => { | |||||
| variant="contained" | variant="contained" | ||||
| startIcon={<Add />} | startIcon={<Add />} | ||||
| LinkComponent={Link} | LinkComponent={Link} | ||||
| href="/staff/create" | |||||
| href="/settings/staff/create" | |||||
| > | > | ||||
| {t("Create Staff")} | {t("Create Staff")} | ||||
| </Button> | </Button> | ||||
| @@ -1,7 +1,7 @@ | |||||
| "use server"; | "use server"; | ||||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | import { serverFetchJson } from "@/app/utils/fetchUtil"; | ||||
| import { BASE_API_URL } from "@/config/api"; | import { BASE_API_URL } from "@/config/api"; | ||||
| import { StaffResult } from "."; | |||||
| export interface CreateCustomInputs { | export interface CreateCustomInputs { | ||||
| // Project details | // Project details | ||||
| projectCode: string; | projectCode: string; | ||||
| @@ -22,19 +22,28 @@ export interface CreateStaffInputs { | |||||
| email: string; | email: string; | ||||
| phone1: string; | phone1: string; | ||||
| phone2: string; | phone2: string; | ||||
| hourlyRate: string | number; | |||||
| emergContactName: string; | emergContactName: string; | ||||
| emergContactPhone: string; | emergContactPhone: string; | ||||
| employType: string; | employType: string; | ||||
| joinDate: string | null; | |||||
| departDate: string | null; | departDate: string | null; | ||||
| departReason: string | null; | departReason: string | null; | ||||
| remark: string | null; | remark: string | null; | ||||
| } | } | ||||
| export const saveStaff = async (data: CreateStaffInputs) => { | export const saveStaff = async (data: CreateStaffInputs) => { | ||||
| console.log(`${BASE_API_URL}/staffs/new`) | |||||
| return serverFetchJson(`${BASE_API_URL}/staffs/new`, { | return serverFetchJson(`${BASE_API_URL}/staffs/new`, { | ||||
| method: "POST", | method: "POST", | ||||
| body: JSON.stringify(data), | body: JSON.stringify(data), | ||||
| headers: { "Content-Type": "application/json" }, | headers: { "Content-Type": "application/json" }, | ||||
| }); | }); | ||||
| }; | |||||
| export const deleteStaff = async (id: number) => { | |||||
| return serverFetchJson(`${BASE_API_URL}/staffs/delete/${id}`, { | |||||
| method: "DELETE", | |||||
| // body: JSON.stringify(id), | |||||
| headers: { "Content-Type": "application/json" }, | |||||
| }); | |||||
| }; | }; | ||||
| @@ -25,18 +25,11 @@ interface Field { | |||||
| } | } | ||||
| interface formProps { | interface formProps { | ||||
| // onSubmit: (data: any) => void; | |||||
| // resetForm: () => void; | |||||
| // Title?: string[]; | |||||
| // isActive: boolean; | |||||
| Title?: string[] | |||||
| Title?: string[]; | |||||
| fieldLists: Field[][]; | fieldLists: Field[][]; | ||||
| } | } | ||||
| const CreateStaffForm: React.FC<formProps> = ({ | |||||
| Title, | |||||
| fieldLists | |||||
| }) => { | |||||
| const CreateStaffForm: React.FC<formProps> = ({ Title, fieldLists }) => { | |||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const [serverError, setServerError] = useState(""); | const [serverError, setServerError] = useState(""); | ||||
| @@ -48,16 +41,38 @@ const CreateStaffForm: React.FC<formProps> = ({ | |||||
| async (data) => { | async (data) => { | ||||
| try { | try { | ||||
| console.log(data); | 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") { | |||||
| 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 (haveError) { | |||||
| return | |||||
| } | |||||
| const postData = { | const postData = { | ||||
| ...data, | ...data, | ||||
| emergContactPhone: data.emergContactPhone.toString(), | emergContactPhone: data.emergContactPhone.toString(), | ||||
| phone1: data.phone1.toString(), | phone1: data.phone1.toString(), | ||||
| phone2: data.phone2.toString(), | phone2: data.phone2.toString(), | ||||
| } | |||||
| hourlyRate: typeof data.hourlyRate === 'string' ? parseInt(data.hourlyRate.replace("$", "").replace(",", "")) : 0 | |||||
| }; | |||||
| console.log(postData); | console.log(postData); | ||||
| setServerError(""); | setServerError(""); | ||||
| await saveStaff(postData); | await saveStaff(postData); | ||||
| router.replace("/staff"); | |||||
| router.replace("/settings/staff"); | |||||
| } catch (e) { | } catch (e) { | ||||
| setServerError(t("An error has occurred. Please try again later.")); | setServerError(t("An error has occurred. Please try again later.")); | ||||
| } | } | ||||
| @@ -67,10 +82,10 @@ const CreateStaffForm: React.FC<formProps> = ({ | |||||
| const onSubmitError = useCallback<SubmitErrorHandler<CreateStaffInputs>>( | const onSubmitError = useCallback<SubmitErrorHandler<CreateStaffInputs>>( | ||||
| (errors) => { | (errors) => { | ||||
| console.log(errors) | |||||
| console.log(errors); | |||||
| }, | }, | ||||
| [], | |||||
| ); | |||||
| [] | |||||
| ); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| @@ -29,6 +29,8 @@ import { DatePicker } from "@mui/x-date-pickers/DatePicker"; | |||||
| import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
| import { useCallback, useEffect, useState } from "react"; | import { useCallback, useEffect, useState } from "react"; | ||||
| import { Check, Close } from "@mui/icons-material"; | import { Check, Close } from "@mui/icons-material"; | ||||
| import { NumericFormat, NumericFormatProps } from "react-number-format"; | |||||
| import * as React from "react"; | |||||
| // interface Option { | // interface Option { | ||||
| // // Define properties of each option object | // // Define properties of each option object | ||||
| @@ -52,7 +54,10 @@ interface Field { | |||||
| size?: number; | size?: number; | ||||
| setValue?: any[]; | setValue?: any[]; | ||||
| } | } | ||||
| interface CustomProps { | |||||
| onChange: (event: { target: { name: string; value: string } }) => void; | |||||
| name: string; | |||||
| } | |||||
| interface CustomInputFormProps { | interface CustomInputFormProps { | ||||
| onSubmit: (data: any) => void; | onSubmit: (data: any) => void; | ||||
| onSubmitError?: (data: any) => void; | onSubmitError?: (data: any) => void; | ||||
| @@ -77,7 +82,13 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||||
| // resetForm, | // resetForm, | ||||
| }) => { | }) => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const { reset, register, handleSubmit, control, formState: { errors } } = useForm(); | |||||
| const { | |||||
| reset, | |||||
| register, | |||||
| handleSubmit, | |||||
| control, | |||||
| formState: { errors }, | |||||
| } = useForm(); | |||||
| const [dateObj, setDateObj] = useState<any>(null); | const [dateObj, setDateObj] = useState<any>(null); | ||||
| const [value, setValue] = useState<any>({}); | const [value, setValue] = useState<any>({}); | ||||
| const [checkboxValue, setCheckboxValue] = useState({}); | const [checkboxValue, setCheckboxValue] = useState({}); | ||||
| @@ -105,7 +116,7 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||||
| if (checkboxValue !== null) { | if (checkboxValue !== null) { | ||||
| data = { ...data, ...checkboxValue }; | data = { ...data, ...checkboxValue }; | ||||
| } | } | ||||
| const finalData = { | const finalData = { | ||||
| ...value, | ...value, | ||||
| ...data, | ...data, | ||||
| @@ -176,6 +187,39 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||||
| }); | }); | ||||
| }); | }); | ||||
| const NumericFormatCustom = React.forwardRef<NumericFormatProps, CustomProps>( | |||||
| function NumericFormatCustom(props, ref) { | |||||
| const { onChange, ...other } = props; | |||||
| return ( | |||||
| <NumericFormat | |||||
| {...other} | |||||
| getInputRef={ref} | |||||
| onValueChange={(values) => { | |||||
| onChange({ | |||||
| target: { | |||||
| name: props.name, | |||||
| value: values.value, | |||||
| }, | |||||
| }); | |||||
| }} | |||||
| thousandSeparator | |||||
| valueIsNumericString | |||||
| prefix="$" | |||||
| /> | |||||
| ); | |||||
| } | |||||
| ); | |||||
| const [values, setValues] = React.useState({ | |||||
| hourlyRate: "", | |||||
| }); | |||||
| const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { | |||||
| setValues({ | |||||
| ...values, | |||||
| [event.target.name]: event.target.value, | |||||
| }); | |||||
| }; | |||||
| return ( | return ( | ||||
| <form onSubmit={handleSubmit(handleFormSubmit, onSubmitError)}> | <form onSubmit={handleSubmit(handleFormSubmit, onSubmitError)}> | ||||
| <Card sx={{ display: isActive ? "block" : "none" }}> | <Card sx={{ display: isActive ? "block" : "none" }}> | ||||
| @@ -201,12 +245,16 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||||
| label={field.label} | label={field.label} | ||||
| fullWidth | fullWidth | ||||
| {...register(field.id, { | {...register(field.id, { | ||||
| pattern: field.pattern ? new RegExp(field.pattern) : /.*/, | |||||
| pattern: field.pattern | |||||
| ? new RegExp(field.pattern) | |||||
| : /.*/, | |||||
| })} | })} | ||||
| defaultValue={!field.value ? `${field.value}` : ""} | defaultValue={!field.value ? `${field.value}` : ""} | ||||
| required={field.required ?? false} | required={field.required ?? false} | ||||
| error={Boolean(errors[field.id])} | error={Boolean(errors[field.id])} | ||||
| helperText={Boolean(errors[field.id]) && field.message} | |||||
| helperText={ | |||||
| Boolean(errors[field.id]) && field.message | |||||
| } | |||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| ); | ); | ||||
| @@ -217,16 +265,19 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||||
| label={field.label} | label={field.label} | ||||
| fullWidth | fullWidth | ||||
| {...register(field.id, { | {...register(field.id, { | ||||
| pattern: /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/, | |||||
| pattern: | |||||
| /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/, | |||||
| })} | })} | ||||
| defaultValue={!field.value ? `${field.value}` : ""} | defaultValue={!field.value ? `${field.value}` : ""} | ||||
| required={field.required ?? false} | required={field.required ?? false} | ||||
| error={Boolean(errors[field.id])} | error={Boolean(errors[field.id])} | ||||
| helperText={Boolean(errors[field.id]) && field.message} | |||||
| helperText={ | |||||
| Boolean(errors[field.id]) && field.message | |||||
| } | |||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| ); | ); | ||||
| }else if (field.type === "multiDate") { | |||||
| } else if (field.type === "multiDate") { | |||||
| return ( | return ( | ||||
| <Grid item xs={field.size ?? 6} key={field.id}> | <Grid item xs={field.size ?? 6} key={field.id}> | ||||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | <LocalizationProvider dateAdapter={AdapterDayjs}> | ||||
| @@ -324,6 +375,34 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| ); | ); | ||||
| } else if (field.type === "numeric-testing") { | |||||
| return ( | |||||
| <Grid item xs={field.size ?? 6} key={field.id}> | |||||
| <FormControl fullWidth> | |||||
| <Controller | |||||
| {...register(field.id)} | |||||
| name={field.id} | |||||
| control={control} | |||||
| defaultValue={ | |||||
| !field.value ? `${field.value}` : "" | |||||
| } | |||||
| render={({ field }) => { | |||||
| console.log(field); | |||||
| return ( | |||||
| <NumericFormat | |||||
| {...field} | |||||
| customInput={TextField} | |||||
| thousandSeparator | |||||
| valueIsNumericString | |||||
| prefix="$" | |||||
| label={t(field.name)} | |||||
| /> | |||||
| ); | |||||
| }} | |||||
| /> | |||||
| </FormControl> | |||||
| </Grid> | |||||
| ); | |||||
| } else if (field.type === "numeric-positive") { | } else if (field.type === "numeric-positive") { | ||||
| return ( | return ( | ||||
| <Grid item xs={field.size ?? 6} key={field.id}> | <Grid item xs={field.size ?? 6} key={field.id}> | ||||
| @@ -331,6 +410,7 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||||
| fullWidth | fullWidth | ||||
| {...register(field.id)} | {...register(field.id)} | ||||
| id={field.id} | id={field.id} | ||||
| name={field.id} | |||||
| label={field.label} | label={field.label} | ||||
| defaultValue={!field.value ? `${field.value}` : ""} | defaultValue={!field.value ? `${field.value}` : ""} | ||||
| inputProps={{ | inputProps={{ | ||||
| @@ -0,0 +1,106 @@ | |||||
| "use client"; | |||||
| import React, { useCallback, useMemo, useState } from "react"; | |||||
| import Button from "@mui/material/Button"; | |||||
| import { Card, Modal, Stack, Typography } from "@mui/material"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import { Add } from "@mui/icons-material"; | |||||
| import Check from "@mui/icons-material/Check"; | |||||
| import Close from "@mui/icons-material/Close"; | |||||
| import { TSMS_BUTTON_THEME } from "@/theme/colorConst"; | |||||
| import { ThemeProvider } from "@emotion/react"; | |||||
| interface Props { | |||||
| isOpen: boolean; | |||||
| onConfirm: (data: any) => void; | |||||
| onCancel: (data: any | null) => void; | |||||
| // staff: StaffResult[]; | |||||
| } | |||||
| const ConfirmModal: React.FC<Props> = ({ ...props }) => { | |||||
| const { t } = useTranslation(); | |||||
| return ( | |||||
| <> | |||||
| <Modal open={props.isOpen} onClose={props.onCancel}> | |||||
| <Card | |||||
| style={{ | |||||
| flex: 10, | |||||
| marginBottom: "20px", | |||||
| width: "auto", | |||||
| minWidth: "400px", | |||||
| minHeight: "200px", | |||||
| position: "fixed", | |||||
| top: "50%", | |||||
| left: "50%", | |||||
| transform: "translate(-50%, -50%)", | |||||
| }} | |||||
| > | |||||
| <> | |||||
| <Typography | |||||
| variant="h5" | |||||
| id="modal-title" | |||||
| sx={{ | |||||
| flex: 1, | |||||
| ml: 4, | |||||
| mt: 2, | |||||
| }} | |||||
| > | |||||
| {t("Confirm")} | |||||
| </Typography> | |||||
| <> | |||||
| <Typography | |||||
| variant="h6" | |||||
| id="modal-title" | |||||
| sx={{ | |||||
| flex: 1, | |||||
| mt: 4, | |||||
| justifyContent: "center", | |||||
| textAlign: "center", | |||||
| }} | |||||
| > | |||||
| {t("Are You Sure")} | |||||
| </Typography> | |||||
| </> | |||||
| {/* <ThemeProvider theme={TSMS_BUTTON_THEME}> */} | |||||
| <Stack direction="row"> | |||||
| <Button | |||||
| variant="contained" | |||||
| endIcon={<Check />} | |||||
| sx={{ | |||||
| flex: 1, | |||||
| ml: 5, | |||||
| mr: 2, | |||||
| mt: 4, | |||||
| justifyContent: "space-between", | |||||
| }} | |||||
| onClick={props.onConfirm} | |||||
| // LinkComponent={Link} | |||||
| // href="/settings/department/new" | |||||
| > | |||||
| Proceed | |||||
| </Button> | |||||
| <Button | |||||
| variant="contained" | |||||
| startIcon={<Close />} | |||||
| sx={{ | |||||
| flex: 1, | |||||
| mr: 5, | |||||
| mt: 4, | |||||
| justifyContent: "space-between", | |||||
| }} | |||||
| color="warning" | |||||
| onClick={props.onCancel} | |||||
| // LinkComponent={Link} | |||||
| // href="/settings/department/new" | |||||
| > | |||||
| Cancel | |||||
| </Button> | |||||
| </Stack> | |||||
| {/* </ThemeProvider> */} | |||||
| </> | |||||
| </Card> | |||||
| </Modal> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| export default ConfirmModal; | |||||
| @@ -1,11 +1,14 @@ | |||||
| "use client"; | "use client"; | ||||
| import { StaffResult } from "@/app/api/staff"; | import { StaffResult } from "@/app/api/staff"; | ||||
| import React, { useCallback, useMemo, useState } from "react"; | |||||
| import React, { useCallback, useEffect, useMemo, useState } from "react"; | |||||
| import SearchBox, { Criterion } from "../SearchBox/index"; | import SearchBox, { Criterion } from "../SearchBox/index"; | ||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import SearchResults, { Column } from "../SearchResults/index"; | import SearchResults, { Column } from "../SearchResults/index"; | ||||
| import EditNote from "@mui/icons-material/EditNote"; | import EditNote from "@mui/icons-material/EditNote"; | ||||
| import DeleteIcon from '@mui/icons-material/Delete'; | |||||
| import ConfirmModal from "./ConfirmDeleteModal"; | |||||
| import { deleteStaff } from "@/app/api/staff/actions"; | |||||
| interface Props { | interface Props { | ||||
| staff: StaffResult[]; | staff: StaffResult[]; | ||||
| @@ -16,10 +19,9 @@ type SearchParamNames = keyof SearchQuery; | |||||
| const StaffSearch: React.FC<Props> = ({ staff }) => { | const StaffSearch: React.FC<Props> = ({ staff }) => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| // If claim searching is done on the server-side, then no need for this. | |||||
| const [filteredStaff, setFilteredStaff] = useState(staff); | const [filteredStaff, setFilteredStaff] = useState(staff); | ||||
| // const [filteredStaffRef, setFilteredStaffRef] = useState(staff); | |||||
| const [id, setId] = useState(0); | |||||
| const [isOpen, setIsOpen] = useState(false); | |||||
| const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | ||||
| () => [ | () => [ | ||||
| @@ -59,6 +61,30 @@ const StaffSearch: React.FC<Props> = ({ staff }) => { | |||||
| console.log(staff); | console.log(staff); | ||||
| }, []); | }, []); | ||||
| const deleteClick = (staff: StaffResult) => { | |||||
| console.log(staff.id); | |||||
| const temp = staff.id | |||||
| console.log(temp) | |||||
| setId(temp) | |||||
| setIsOpen(!isOpen) | |||||
| }; | |||||
| const onConfirm = (staff: StaffResult) => { | |||||
| console.log(staff); | |||||
| console.log(id); | |||||
| deleteStaff(id) | |||||
| // setIsOpen(!isOpen) | |||||
| } | |||||
| const onCancel = useCallback((staff: StaffResult) => { | |||||
| console.log(staff); | |||||
| // setId(0) | |||||
| setIsOpen(false) | |||||
| }, []); | |||||
| useEffect(() => { | |||||
| console.log("id"); | |||||
| console.log(id); | |||||
| }, [id]); | |||||
| const columns = useMemo<Column<StaffResult>[]>( | const columns = useMemo<Column<StaffResult>[]>( | ||||
| () => [ | () => [ | ||||
| { | { | ||||
| @@ -72,8 +98,14 @@ const StaffSearch: React.FC<Props> = ({ staff }) => { | |||||
| { name: "staffId", label: t("Staff ID") }, | { name: "staffId", label: t("Staff ID") }, | ||||
| { name: "grade", label: t("Grade") }, | { name: "grade", label: t("Grade") }, | ||||
| { name: "currentPosition", label: t("Current Position") }, | { name: "currentPosition", label: t("Current Position") }, | ||||
| { | |||||
| name: "action", | |||||
| label: t("Actions"), | |||||
| onClick: deleteClick, | |||||
| buttonIcon: <DeleteIcon />, | |||||
| }, | |||||
| ], | ], | ||||
| [t, onStaffClick], | |||||
| [t, onStaffClick, deleteClick], | |||||
| ); | ); | ||||
| return ( | return ( | ||||
| @@ -94,6 +126,11 @@ const StaffSearch: React.FC<Props> = ({ staff }) => { | |||||
| }} | }} | ||||
| /> | /> | ||||
| <SearchResults<StaffResult> items={filteredStaff} columns={columns} /> | <SearchResults<StaffResult> items={filteredStaff} columns={columns} /> | ||||
| <ConfirmModal | |||||
| isOpen={isOpen} | |||||
| onConfirm={onConfirm} | |||||
| onCancel={onCancel} | |||||
| /> | |||||
| </> | </> | ||||
| ); | ); | ||||
| }; | }; | ||||