| @@ -32,11 +32,7 @@ interface CreateCustomInputs { | |||
| projectCode: string; | |||
| projectName: string; | |||
| } | |||
| const createCustomInputs: CreateCustomInputs = { | |||
| // Project details | |||
| projectCode: "", | |||
| projectName: "", | |||
| } | |||
| // const Title = ["title1", "title2"]; | |||
| const CreateStaff: React.FC = async () => { | |||
| @@ -58,7 +54,7 @@ const CreateStaff: React.FC = async () => { | |||
| id: "name", | |||
| label: t("Staff Name"), | |||
| type: "text", | |||
| value: "asdasd", | |||
| value: "", | |||
| required: true, | |||
| }, | |||
| { | |||
| @@ -1,10 +1,31 @@ | |||
| const EditStaff: React.FC = async () => { | |||
| // "use client"; | |||
| import { Edit } from "@mui/icons-material"; | |||
| import { useSearchParams } from "next/navigation"; | |||
| import EditStaff from "@/components/EditStaff"; | |||
| import { Suspense } from "react"; | |||
| import { I18nProvider } from "@/i18n"; | |||
| import EditStaffWrapper from "@/components/EditStaff/EditStaffWrapper"; | |||
| import { Metadata } from "next"; | |||
| return ( | |||
| <> | |||
| sdsadasd | |||
| </> | |||
| ) | |||
| } | |||
| // export const metadata: Metadata = { | |||
| // title: "staff-edit", | |||
| // }; | |||
| export default EditStaff; | |||
| const EditStaffPage: React.FC = () => { | |||
| // const searchParams = useSearchParams(); | |||
| // const userId = searchParams.get('param'); | |||
| // console.log(userId); // Access the value of the "user_id" parameter | |||
| return ( | |||
| <> | |||
| <I18nProvider namespaces={["staff", "common"]}> | |||
| <Suspense fallback={<EditStaff.Loading />}> | |||
| <EditStaff /> | |||
| </Suspense> | |||
| </I18nProvider> | |||
| {/* <EditStaff /> */} | |||
| </> | |||
| ); | |||
| }; | |||
| export default EditStaffPage; | |||
| @@ -1,4 +1,3 @@ | |||
| // 'use client'; | |||
| import { preloadClaims } from "@/app/api/claims"; | |||
| import { preloadStaff, preloadTeamLeads } from "@/app/api/staff"; | |||
| import StaffSearch from "@/components/StaffSearch"; | |||
| @@ -0,0 +1,19 @@ | |||
| "use server"; | |||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| import { cache } from "react"; | |||
| export interface comboProp { | |||
| id: any; | |||
| label: string; | |||
| } | |||
| export interface combo { | |||
| records: comboProp; | |||
| } | |||
| export const fetchCompanyCombo = cache(async () => { | |||
| return serverFetchJson<combo>(`${BASE_API_URL}/companys/combo`, { | |||
| next: { tags: ["company"] }, | |||
| }); | |||
| }); | |||
| @@ -2,7 +2,17 @@ | |||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| import { cache } from "react"; | |||
| export interface comboProp { | |||
| id: any; | |||
| label: string; | |||
| } | |||
| export interface combo { | |||
| records: comboProp; | |||
| } | |||
| export interface CreateDepartmentInputs { | |||
| departmentCode: string; | |||
| departmentName: string; | |||
| @@ -15,4 +25,11 @@ export const saveDepartment = async (data: CreateDepartmentInputs) => { | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| }; | |||
| }; | |||
| export const fetchDepartmentCombo = cache(async () => { | |||
| return serverFetchJson<combo>(`${BASE_API_URL}/departments/combo`, { | |||
| next: { tags: ["department"] }, | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,20 @@ | |||
| "use server" | |||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| import { cache } from "react"; | |||
| export interface comboProp { | |||
| id: any; | |||
| label: string; | |||
| } | |||
| export interface combo { | |||
| records: comboProp; | |||
| } | |||
| export const fetchGradeCombo = cache(async () => { | |||
| return serverFetchJson<combo>(`${BASE_API_URL}/grades/combo`, { | |||
| next: { tags: ["grades"] }, | |||
| }); | |||
| }); | |||
| @@ -2,6 +2,16 @@ | |||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| import { cache } from "react"; | |||
| export interface comboProp { | |||
| id: any; | |||
| label: string; | |||
| } | |||
| export interface combo { | |||
| records: comboProp; | |||
| } | |||
| export interface CreatePositionInputs { | |||
| positionCode: string; | |||
| @@ -15,4 +25,11 @@ export const savePosition = async (data: CreatePositionInputs) => { | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| }; | |||
| }; | |||
| export const fetchPositionCombo = cache(async () => { | |||
| return serverFetchJson<combo>(`${BASE_API_URL}/positions/combo`, { | |||
| next: { tags: ["positions"] }, | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,21 @@ | |||
| "use server" | |||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| import { cache } from "react"; | |||
| export interface comboProp { | |||
| id: any; | |||
| label: string; | |||
| } | |||
| export interface combo { | |||
| records: comboProp; | |||
| } | |||
| export const fetchSkillCombo = cache(async () => { | |||
| return serverFetchJson<combo>(`${BASE_API_URL}/skill/combo`, { | |||
| next: { tags: ["skill"] }, | |||
| }); | |||
| }); | |||
| @@ -1,7 +1,8 @@ | |||
| "use server"; | |||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| import { StaffResult } from "."; | |||
| import { StaffResult, data } from "."; | |||
| import { cache } from "react"; | |||
| export interface CreateCustomInputs { | |||
| // Project details | |||
| projectCode: string; | |||
| @@ -33,17 +34,29 @@ export interface CreateStaffInputs { | |||
| } | |||
| export const saveStaff = async (data: CreateStaffInputs) => { | |||
| return serverFetchJson(`${BASE_API_URL}/staffs/new`, { | |||
| return serverFetchJson(`${BASE_API_URL}/staffs/save`, { | |||
| method: "POST", | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| }; | |||
| export const deleteStaff = async (id: number) => { | |||
| return serverFetchJson(`${BASE_API_URL}/staffs/delete/${id}`, { | |||
| export const deleteStaff = async (data: StaffResult) => { | |||
| return serverFetchJson(`${BASE_API_URL}/staffs/delete/${data.id}`, { | |||
| method: "DELETE", | |||
| // body: JSON.stringify(id), | |||
| body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| }; | |||
| }; | |||
| export const fetchStaffEdit = cache(async (id: number) => { | |||
| return serverFetchJson<data>(`${BASE_API_URL}/staffs/${id}`, { | |||
| next: { tags: ["staffs"] }, | |||
| }); | |||
| }); | |||
| // export const preloadStaffEdit = (id: number) => { | |||
| // fetchStaffEdit(id); | |||
| // }; | |||
| @@ -3,6 +3,9 @@ import { BASE_API_URL } from "@/config/api"; | |||
| import { cache } from "react"; | |||
| import "server-only"; | |||
| export interface data { | |||
| [key: string]: any; | |||
| } | |||
| export interface StaffResult { | |||
| action: any; | |||
| id: number; | |||
| @@ -12,6 +15,7 @@ export interface StaffResult { | |||
| grade: string; | |||
| joinPosition: string; | |||
| currentPosition: string; | |||
| data: data | |||
| } | |||
| export interface searchInput { | |||
| staffId: string; | |||
| @@ -41,3 +45,5 @@ export const fetchStaff = cache(async () => { | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,19 @@ | |||
| "use server"; | |||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| import { cache } from "react"; | |||
| export interface comboProp { | |||
| id: any; | |||
| label: string; | |||
| } | |||
| export interface combo { | |||
| records: comboProp; | |||
| } | |||
| export const fetchTeamCombo = cache(async () => { | |||
| return serverFetchJson<combo>(`${BASE_API_URL}/team/combo`, { | |||
| next: { tags: ["team"] }, | |||
| }); | |||
| }); | |||
| @@ -32,15 +32,13 @@ import { Check, Close } from "@mui/icons-material"; | |||
| import { NumericFormat, NumericFormatProps } from "react-number-format"; | |||
| import * as React from "react"; | |||
| // interface Option { | |||
| // // Define properties of each option object | |||
| // // based on your specific requirements | |||
| // id: any; | |||
| // value: any; | |||
| // label: string; | |||
| // } | |||
| interface Options { | |||
| id: any; | |||
| label: string; | |||
| [key: string]: any; | |||
| } | |||
| interface Field { | |||
| export interface Field { | |||
| // subtitle: string; | |||
| id: string; | |||
| label: string; | |||
| @@ -49,7 +47,7 @@ interface Field { | |||
| required?: boolean; | |||
| pattern?: string; | |||
| message?: string; | |||
| options?: any[]; | |||
| options?: Options[] | null; | |||
| readOnly?: boolean; | |||
| size?: number; | |||
| setValue?: any[]; | |||
| @@ -249,7 +247,10 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||
| ? new RegExp(field.pattern) | |||
| : /.*/, | |||
| })} | |||
| defaultValue={!field.value ? `${field.value}` : ""} | |||
| defaultValue={field.value ? `${field.value}` : ""} | |||
| inputProps={{ | |||
| readOnly: field.readOnly, | |||
| }} | |||
| required={field.required ?? false} | |||
| error={Boolean(errors[field.id])} | |||
| helperText={ | |||
| @@ -347,9 +348,9 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||
| : option | |||
| } | |||
| > | |||
| {option.id !== undefined | |||
| {option.id | |||
| ? option.label | |||
| : option} | |||
| : ""} | |||
| </MenuItem> | |||
| ))} | |||
| </Select> | |||
| @@ -0,0 +1,244 @@ | |||
| "use client"; | |||
| import EditStaffForm from "../EditStaffForm"; | |||
| import { useSearchParams } from "next/navigation"; | |||
| import { useEffect, useState } from "react"; | |||
| import { BASE_API_URL } from "@/config/api"; | |||
| import { fetchStaffEdit } from "@/app/api/staff/actions"; | |||
| import { getServerI18n } from "@/i18n"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { comboProp, fetchCompanyCombo } from "@/app/api/companys/actions"; | |||
| import { fetchTeamCombo } from "@/app/api/team/actions"; | |||
| import { fetchDepartmentCombo } from "@/app/api/departments/actions"; | |||
| import { fetchPositionCombo } from "@/app/api/positions/actions"; | |||
| import { fetchGradeCombo } from "@/app/api/grades/actions"; | |||
| import { fetchSkillCombo } from "@/app/api/skill/actions"; | |||
| // import { Field } from "react-hook-form"; | |||
| interface dataType { | |||
| [key: string]: any; | |||
| } | |||
| interface Options { | |||
| id: any; | |||
| label: string; | |||
| [key: string]: any; | |||
| } | |||
| // interface Field { | |||
| // id: string; | |||
| // label: string; | |||
| // type: string; | |||
| // value: any; | |||
| // required?: boolean; | |||
| // options?: comboProp[] | undefined | null; | |||
| // readOnly?: boolean; | |||
| // } | |||
| export interface Field { | |||
| // subtitle: string; | |||
| id: string; | |||
| label: string; | |||
| type: string; | |||
| value?: any; | |||
| required?: boolean; | |||
| pattern?: string; | |||
| message?: string; | |||
| options?: Options[]| null; | |||
| readOnly?: boolean; | |||
| size?: number; | |||
| setValue?: any[]; | |||
| } | |||
| const EditStaff: React.FC = async () => { | |||
| const searchParams = useSearchParams(); | |||
| const { t } = useTranslation(); | |||
| const idString = searchParams.get("id"); | |||
| const [id, setId] = useState(0); | |||
| const [fieldLists, setFieldLists] = useState<Field[][]>(); | |||
| const [companyCombo, setCompanyCombo] = useState<comboProp>(); | |||
| const [teamCombo, setTeamCombo] = useState<comboProp>(); | |||
| const [departmentCombo, setDepartmentCombo] = useState<comboProp>(); | |||
| const [positionCombo, setPositionCombo] = useState<comboProp>(); | |||
| const [gradeCombo, setGradeCombo] = useState<comboProp>(); | |||
| const [skillCombo, setSkillCombo] = useState<comboProp>(); | |||
| // const employTypeCombo = [{id: "FT", label: t("FT")}, {id: "PT", label: t("PT")}]; | |||
| const employTypeCombo = [{id: "FT", label: t("FT")}, {id: "PT", label: t("PT")}]; | |||
| //fetch all combo | |||
| useEffect(() => { | |||
| fetchCompanyCombo().then((data) => { | |||
| console.log(data.records); | |||
| setCompanyCombo(data.records); | |||
| }); | |||
| fetchTeamCombo().then((data) => { | |||
| setTeamCombo(data.records); | |||
| }) | |||
| fetchDepartmentCombo().then((data) => { | |||
| setDepartmentCombo(data.records); | |||
| }) | |||
| fetchPositionCombo().then((data) => { | |||
| setPositionCombo(data.records); | |||
| }) | |||
| fetchGradeCombo().then((data) => { | |||
| setGradeCombo(data.records); | |||
| }) | |||
| fetchSkillCombo().then((data) => { | |||
| setSkillCombo(data.records); | |||
| }) | |||
| }, [searchParams]); | |||
| useEffect(() => { | |||
| let id = 0; | |||
| if (idString) { | |||
| id = parseInt(idString); | |||
| setId(id) | |||
| } | |||
| fetchStaffEdit(id).then((staff) => { | |||
| console.log(staff.data); | |||
| const data = staff.data; | |||
| const keyOrder = [ | |||
| "staffId", | |||
| "name", | |||
| "company", | |||
| "team", | |||
| "department", | |||
| "grade", | |||
| "skill", | |||
| "currentPosition", | |||
| "salaryEffective", | |||
| "hourlySalary", | |||
| "employType", | |||
| "email", | |||
| "phone1", | |||
| "phone2", | |||
| ]; | |||
| const list1 = keyOrder | |||
| .map((key) => { | |||
| switch (key) { | |||
| case "staffId": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "text", | |||
| value: data[key], | |||
| }; | |||
| case "name": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "text", | |||
| value: data[key], | |||
| }; | |||
| case "company": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "combo-Obj", | |||
| options: companyCombo, | |||
| value: data[key].id, | |||
| }; | |||
| case "team": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "combo-Obj", | |||
| options: teamCombo, | |||
| value: data[key].id, | |||
| }; | |||
| case "department": | |||
| // console.log(data[key]) | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "combo-Obj", | |||
| options: departmentCombo, | |||
| value: data[key]?.id ?? "", | |||
| // later check | |||
| }; | |||
| case "grade": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "combo-Obj", | |||
| options: gradeCombo, | |||
| value: data[key].id, | |||
| }; | |||
| case "skill": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "combo-Obj", | |||
| options: skillCombo, | |||
| value: data[key].id, | |||
| }; | |||
| case "currentPosition": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "combo-Obj", | |||
| options: positionCombo, | |||
| value: data[key].id, | |||
| }; | |||
| case "salaryEffective": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "text", | |||
| value: data[key], | |||
| }; | |||
| case "hourlySalary": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "text", | |||
| // value: data[key], | |||
| readOnly: true | |||
| }; | |||
| case "employType": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "combo-Obj", | |||
| options: employTypeCombo, | |||
| value: data[key], | |||
| }; | |||
| case "email": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "text", | |||
| value: data[key], | |||
| }; | |||
| case "phone1": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "text", | |||
| value: data[key], | |||
| }; | |||
| case "phone2": | |||
| return { | |||
| id: `${key}`, | |||
| label: t(`${key}`), | |||
| type: "text", | |||
| value: data[key], | |||
| } as Field; | |||
| // Add more cases for each property | |||
| default: | |||
| return null; | |||
| } | |||
| }) | |||
| .filter((item): item is Field => item !== null); | |||
| console.log([list1]); | |||
| setFieldLists([list1]); | |||
| }); | |||
| }, [companyCombo]); | |||
| return ( | |||
| <> | |||
| <EditStaffForm id={id} fieldLists={fieldLists || [[]]} /> | |||
| </> | |||
| ); | |||
| }; | |||
| export default EditStaff; | |||
| @@ -0,0 +1,40 @@ | |||
| import Card from "@mui/material/Card"; | |||
| import CardContent from "@mui/material/CardContent"; | |||
| import Skeleton from "@mui/material/Skeleton"; | |||
| import Stack from "@mui/material/Stack"; | |||
| import React from "react"; | |||
| // Can make this nicer | |||
| export const EditStaffLoading: React.FC = () => { | |||
| return ( | |||
| <> | |||
| <Card> | |||
| <CardContent> | |||
| <Stack spacing={2}> | |||
| <Skeleton variant="rounded" height={60} /> | |||
| <Skeleton variant="rounded" height={60} /> | |||
| <Skeleton variant="rounded" height={60} /> | |||
| <Skeleton | |||
| variant="rounded" | |||
| height={50} | |||
| width={100} | |||
| sx={{ alignSelf: "flex-end" }} | |||
| /> | |||
| </Stack> | |||
| </CardContent> | |||
| </Card> | |||
| <Card>EditStaff | |||
| <CardContent> | |||
| <Stack spacing={2}> | |||
| <Skeleton variant="rounded" height={40} /> | |||
| <Skeleton variant="rounded" height={40} /> | |||
| <Skeleton variant="rounded" height={40} /> | |||
| <Skeleton variant="rounded" height={40} /> | |||
| </Stack> | |||
| </CardContent> | |||
| </Card> | |||
| </> | |||
| ); | |||
| }; | |||
| export default EditStaffLoading; | |||
| @@ -0,0 +1,19 @@ | |||
| import React from "react"; | |||
| import EditStaff from "./EditStaff"; | |||
| import EditStaffLoading from "./EditStaffLoading"; | |||
| import { fetchStaff, fetchTeamLeads } from "@/app/api/staff"; | |||
| import { useSearchParams } from "next/navigation"; | |||
| interface SubComponents { | |||
| Loading: typeof EditStaffLoading; | |||
| } | |||
| const EditStaffWrapper: React.FC & SubComponents = async () => { | |||
| return <EditStaff/>; | |||
| }; | |||
| EditStaffWrapper.Loading = EditStaffLoading; | |||
| export default EditStaffWrapper; | |||
| @@ -0,0 +1 @@ | |||
| export { default } from "./EditStaffWrapper"; | |||
| @@ -0,0 +1,83 @@ | |||
| // import { fetchStaffEdit } from "@/app/api/staff"; | |||
| import { useRouter, useSearchParams } from "next/navigation"; | |||
| import { useCallback, useEffect, useState } from "react"; | |||
| import CustomInputForm from "../CustomInputForm"; | |||
| import { SubmitErrorHandler, SubmitHandler } from "react-hook-form"; | |||
| import { CreateStaffInputs, saveStaff } from "@/app/api/staff/actions"; | |||
| import { Typography } from "@mui/material"; | |||
| import { useTranslation } from "react-i18next"; | |||
| interface Options { | |||
| id: any; | |||
| label: string; | |||
| [key: string]: any; | |||
| } | |||
| interface Field { | |||
| // subtitle: string; | |||
| id: string; | |||
| label: string; | |||
| type: string; | |||
| value?: any; | |||
| required?: boolean; | |||
| options?: any[] | null; | |||
| readOnly?: boolean; | |||
| } | |||
| interface formProps { | |||
| id: number; | |||
| Title?: string[]; | |||
| fieldLists: Field[][]; | |||
| } | |||
| const EditStaffForm: React.FC<formProps> = ({ id, Title, fieldLists }) => { | |||
| const router = useRouter(); | |||
| const { t } = useTranslation(); | |||
| const [serverError, setServerError] = useState(""); | |||
| // make new inputs | |||
| const onSubmit = useCallback<SubmitHandler<CreateStaffInputs>>( | |||
| async (data) => { | |||
| try { | |||
| console.log(data); | |||
| const temp = { | |||
| id: id, | |||
| ...data | |||
| } | |||
| console.log(temp) | |||
| setServerError(""); | |||
| await saveStaff(temp); | |||
| } catch (e) { | |||
| setServerError(t("An error has occurred. Please try again later.")); | |||
| } | |||
| }, | |||
| [router, t] | |||
| ); | |||
| const onSubmitError = useCallback<SubmitErrorHandler<CreateStaffInputs>>( | |||
| (errors) => { | |||
| console.log(errors); | |||
| }, | |||
| [] | |||
| ); | |||
| const handleCancel = () => { | |||
| router.back(); | |||
| }; | |||
| return ( | |||
| <> | |||
| {serverError && ( | |||
| <Typography variant="body2" color="error" alignSelf="flex-end"> | |||
| {serverError} | |||
| </Typography> | |||
| )} | |||
| <CustomInputForm | |||
| Title={Title} | |||
| fieldLists={fieldLists} | |||
| isActive={true} | |||
| onSubmit={onSubmit} | |||
| onSubmitError={onSubmitError} | |||
| onCancel={handleCancel} | |||
| /> | |||
| </> | |||
| ); | |||
| }; | |||
| export default EditStaffForm; | |||
| @@ -0,0 +1 @@ | |||
| export { default } from "./EditStaffForm"; | |||
| @@ -9,6 +9,7 @@ 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"; | |||
| import { useRouter } from "next/navigation"; | |||
| interface Props { | |||
| staff: StaffResult[]; | |||
| @@ -20,8 +21,9 @@ type SearchParamNames = keyof SearchQuery; | |||
| const StaffSearch: React.FC<Props> = ({ staff }) => { | |||
| const { t } = useTranslation(); | |||
| const [filteredStaff, setFilteredStaff] = useState(staff); | |||
| const [id, setId] = useState(0); | |||
| const [data, setData] = useState<StaffResult>(); | |||
| const [isOpen, setIsOpen] = useState(false); | |||
| const router = useRouter(); | |||
| const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | |||
| () => [ | |||
| @@ -59,31 +61,32 @@ const StaffSearch: React.FC<Props> = ({ staff }) => { | |||
| const onStaffClick = useCallback((staff: StaffResult) => { | |||
| console.log(staff); | |||
| }, []); | |||
| const id = staff.id | |||
| router.push(`/settings/staff/edit?id=${id}`); | |||
| }, [router, t]); | |||
| const deleteClick = (staff: StaffResult) => { | |||
| console.log(staff.id); | |||
| const temp = staff.id | |||
| console.log(temp) | |||
| setId(temp) | |||
| console.log(staff); | |||
| setData(staff) | |||
| setIsOpen(!isOpen) | |||
| }; | |||
| const onConfirm = (staff: StaffResult) => { | |||
| const onConfirm = useCallback(async (staff: StaffResult) => { | |||
| console.log(staff); | |||
| console.log(id); | |||
| deleteStaff(id) | |||
| // setIsOpen(!isOpen) | |||
| } | |||
| // if (data) | |||
| // await deleteStaff(data) | |||
| window.location.reload; | |||
| }, [deleteStaff, data]); | |||
| const onCancel = useCallback((staff: StaffResult) => { | |||
| console.log(staff); | |||
| // setId(0) | |||
| setIsOpen(false) | |||
| }, []); | |||
| useEffect(() => { | |||
| console.log("id"); | |||
| console.log(id); | |||
| }, [id]); | |||
| // useEffect(() => { | |||
| // console.log("id"); | |||
| // console.log(id); | |||
| // }, [id]); | |||
| const columns = useMemo<Column<StaffResult>[]>( | |||
| () => [ | |||
| @@ -1,3 +1,4 @@ | |||
| import { fetchStaff, fetchTeamLeads } from "@/app/api/staff"; | |||
| import React from "react"; | |||
| import StaffSearch from "./StaffSearch"; | |||
| @@ -10,9 +11,7 @@ interface SubComponents { | |||
| const StaffSearchWrapper: React.FC & SubComponents = async () => { | |||
| const staff = await fetchStaff(); | |||
| // const try = ...staff | |||
| console.log(staff) | |||
| // const records = staff.records; | |||
| // console.log(staff) | |||
| return <StaffSearch staff={staff} />; | |||
| }; | |||
| @@ -12,8 +12,8 @@ | |||
| "Skillset": "技能", | |||
| "Salary Point": "薪金點", | |||
| "Employ Type": "職位類別", | |||
| "Hourly Rate": "時薪", | |||
| "Email": "時薪", | |||
| "hourlyRate": "時薪", | |||
| "Email": "電郵地址", | |||
| "Phone1": "聯絡電話", | |||
| "Phone2": "次要聯絡電話", | |||
| "Additional Info": "更多資料", | |||
| @@ -23,5 +23,7 @@ | |||
| "Join Position": "入職職位", | |||
| "Depart Date": "離職日期", | |||
| "Depart Reason": "離職原因", | |||
| "Remark": "備註" | |||
| "Remark": "備註", | |||
| "Confirm": "確認", | |||
| "Cancel": "取消" | |||
| } | |||