@@ -32,11 +32,7 @@ interface CreateCustomInputs { | |||||
projectCode: string; | projectCode: string; | ||||
projectName: string; | projectName: string; | ||||
} | } | ||||
const createCustomInputs: CreateCustomInputs = { | |||||
// Project details | |||||
projectCode: "", | |||||
projectName: "", | |||||
} | |||||
// const Title = ["title1", "title2"]; | // const Title = ["title1", "title2"]; | ||||
const CreateStaff: React.FC = async () => { | const CreateStaff: React.FC = async () => { | ||||
@@ -58,7 +54,7 @@ const CreateStaff: React.FC = async () => { | |||||
id: "name", | id: "name", | ||||
label: t("Staff Name"), | label: t("Staff Name"), | ||||
type: "text", | type: "text", | ||||
value: "asdasd", | |||||
value: "", | |||||
required: true, | 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 { preloadClaims } from "@/app/api/claims"; | ||||
import { preloadStaff, preloadTeamLeads } from "@/app/api/staff"; | import { preloadStaff, preloadTeamLeads } from "@/app/api/staff"; | ||||
import StaffSearch from "@/components/StaffSearch"; | 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 { serverFetchJson } from "@/app/utils/fetchUtil"; | ||||
import { BASE_API_URL } from "@/config/api"; | 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 { | export interface CreateDepartmentInputs { | ||||
departmentCode: string; | departmentCode: string; | ||||
departmentName: string; | departmentName: string; | ||||
@@ -15,4 +25,11 @@ export const saveDepartment = async (data: CreateDepartmentInputs) => { | |||||
body: JSON.stringify(data), | body: JSON.stringify(data), | ||||
headers: { "Content-Type": "application/json" }, | 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 { serverFetchJson } from "@/app/utils/fetchUtil"; | ||||
import { BASE_API_URL } from "@/config/api"; | 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 { | export interface CreatePositionInputs { | ||||
positionCode: string; | positionCode: string; | ||||
@@ -15,4 +25,11 @@ export const savePosition = async (data: CreatePositionInputs) => { | |||||
body: JSON.stringify(data), | body: JSON.stringify(data), | ||||
headers: { "Content-Type": "application/json" }, | 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"; | "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 "."; | |||||
import { StaffResult, data } from "."; | |||||
import { cache } from "react"; | |||||
export interface CreateCustomInputs { | export interface CreateCustomInputs { | ||||
// Project details | // Project details | ||||
projectCode: string; | projectCode: string; | ||||
@@ -33,17 +34,29 @@ export interface CreateStaffInputs { | |||||
} | } | ||||
export const saveStaff = async (data: CreateStaffInputs) => { | export const saveStaff = async (data: CreateStaffInputs) => { | ||||
return serverFetchJson(`${BASE_API_URL}/staffs/new`, { | |||||
return serverFetchJson(`${BASE_API_URL}/staffs/save`, { | |||||
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}`, { | |||||
export const deleteStaff = async (data: StaffResult) => { | |||||
return serverFetchJson(`${BASE_API_URL}/staffs/delete/${data.id}`, { | |||||
method: "DELETE", | method: "DELETE", | ||||
// body: JSON.stringify(id), | |||||
body: JSON.stringify(data), | |||||
headers: { "Content-Type": "application/json" }, | 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 { cache } from "react"; | ||||
import "server-only"; | import "server-only"; | ||||
export interface data { | |||||
[key: string]: any; | |||||
} | |||||
export interface StaffResult { | export interface StaffResult { | ||||
action: any; | action: any; | ||||
id: number; | id: number; | ||||
@@ -12,6 +15,7 @@ export interface StaffResult { | |||||
grade: string; | grade: string; | ||||
joinPosition: string; | joinPosition: string; | ||||
currentPosition: string; | currentPosition: string; | ||||
data: data | |||||
} | } | ||||
export interface searchInput { | export interface searchInput { | ||||
staffId: string; | 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 { NumericFormat, NumericFormatProps } from "react-number-format"; | ||||
import * as React from "react"; | 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; | // subtitle: string; | ||||
id: string; | id: string; | ||||
label: string; | label: string; | ||||
@@ -49,7 +47,7 @@ interface Field { | |||||
required?: boolean; | required?: boolean; | ||||
pattern?: string; | pattern?: string; | ||||
message?: string; | message?: string; | ||||
options?: any[]; | |||||
options?: Options[] | null; | |||||
readOnly?: boolean; | readOnly?: boolean; | ||||
size?: number; | size?: number; | ||||
setValue?: any[]; | setValue?: any[]; | ||||
@@ -249,7 +247,10 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||||
? new RegExp(field.pattern) | ? new RegExp(field.pattern) | ||||
: /.*/, | : /.*/, | ||||
})} | })} | ||||
defaultValue={!field.value ? `${field.value}` : ""} | |||||
defaultValue={field.value ? `${field.value}` : ""} | |||||
inputProps={{ | |||||
readOnly: field.readOnly, | |||||
}} | |||||
required={field.required ?? false} | required={field.required ?? false} | ||||
error={Boolean(errors[field.id])} | error={Boolean(errors[field.id])} | ||||
helperText={ | helperText={ | ||||
@@ -347,9 +348,9 @@ const CustomInputForm: React.FC<CustomInputFormProps> = ({ | |||||
: option | : option | ||||
} | } | ||||
> | > | ||||
{option.id !== undefined | |||||
{option.id | |||||
? option.label | ? option.label | ||||
: option} | |||||
: ""} | |||||
</MenuItem> | </MenuItem> | ||||
))} | ))} | ||||
</Select> | </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 DeleteIcon from '@mui/icons-material/Delete'; | ||||
import ConfirmModal from "./ConfirmDeleteModal"; | import ConfirmModal from "./ConfirmDeleteModal"; | ||||
import { deleteStaff } from "@/app/api/staff/actions"; | import { deleteStaff } from "@/app/api/staff/actions"; | ||||
import { useRouter } from "next/navigation"; | |||||
interface Props { | interface Props { | ||||
staff: StaffResult[]; | staff: StaffResult[]; | ||||
@@ -20,8 +21,9 @@ type SearchParamNames = keyof SearchQuery; | |||||
const StaffSearch: React.FC<Props> = ({ staff }) => { | const StaffSearch: React.FC<Props> = ({ staff }) => { | ||||
const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
const [filteredStaff, setFilteredStaff] = useState(staff); | const [filteredStaff, setFilteredStaff] = useState(staff); | ||||
const [id, setId] = useState(0); | |||||
const [data, setData] = useState<StaffResult>(); | |||||
const [isOpen, setIsOpen] = useState(false); | const [isOpen, setIsOpen] = useState(false); | ||||
const router = useRouter(); | |||||
const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | ||||
() => [ | () => [ | ||||
@@ -59,31 +61,32 @@ const StaffSearch: React.FC<Props> = ({ staff }) => { | |||||
const onStaffClick = useCallback((staff: StaffResult) => { | const onStaffClick = useCallback((staff: StaffResult) => { | ||||
console.log(staff); | console.log(staff); | ||||
}, []); | |||||
const id = staff.id | |||||
router.push(`/settings/staff/edit?id=${id}`); | |||||
}, [router, t]); | |||||
const deleteClick = (staff: StaffResult) => { | const deleteClick = (staff: StaffResult) => { | ||||
console.log(staff.id); | |||||
const temp = staff.id | |||||
console.log(temp) | |||||
setId(temp) | |||||
console.log(staff); | |||||
setData(staff) | |||||
setIsOpen(!isOpen) | setIsOpen(!isOpen) | ||||
}; | }; | ||||
const onConfirm = (staff: StaffResult) => { | |||||
const onConfirm = useCallback(async (staff: StaffResult) => { | |||||
console.log(staff); | 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) => { | const onCancel = useCallback((staff: StaffResult) => { | ||||
console.log(staff); | console.log(staff); | ||||
// setId(0) | |||||
setIsOpen(false) | setIsOpen(false) | ||||
}, []); | }, []); | ||||
useEffect(() => { | |||||
console.log("id"); | |||||
console.log(id); | |||||
}, [id]); | |||||
// useEffect(() => { | |||||
// console.log("id"); | |||||
// console.log(id); | |||||
// }, [id]); | |||||
const columns = useMemo<Column<StaffResult>[]>( | const columns = useMemo<Column<StaffResult>[]>( | ||||
() => [ | () => [ | ||||
@@ -1,3 +1,4 @@ | |||||
import { fetchStaff, fetchTeamLeads } from "@/app/api/staff"; | import { fetchStaff, fetchTeamLeads } from "@/app/api/staff"; | ||||
import React from "react"; | import React from "react"; | ||||
import StaffSearch from "./StaffSearch"; | import StaffSearch from "./StaffSearch"; | ||||
@@ -10,9 +11,7 @@ interface SubComponents { | |||||
const StaffSearchWrapper: React.FC & SubComponents = async () => { | const StaffSearchWrapper: React.FC & SubComponents = async () => { | ||||
const staff = await fetchStaff(); | const staff = await fetchStaff(); | ||||
// const try = ...staff | |||||
console.log(staff) | |||||
// const records = staff.records; | |||||
// console.log(staff) | |||||
return <StaffSearch staff={staff} />; | return <StaffSearch staff={staff} />; | ||||
}; | }; | ||||
@@ -12,8 +12,8 @@ | |||||
"Skillset": "技能", | "Skillset": "技能", | ||||
"Salary Point": "薪金點", | "Salary Point": "薪金點", | ||||
"Employ Type": "職位類別", | "Employ Type": "職位類別", | ||||
"Hourly Rate": "時薪", | |||||
"Email": "時薪", | |||||
"hourlyRate": "時薪", | |||||
"Email": "電郵地址", | |||||
"Phone1": "聯絡電話", | "Phone1": "聯絡電話", | ||||
"Phone2": "次要聯絡電話", | "Phone2": "次要聯絡電話", | ||||
"Additional Info": "更多資料", | "Additional Info": "更多資料", | ||||
@@ -23,5 +23,7 @@ | |||||
"Join Position": "入職職位", | "Join Position": "入職職位", | ||||
"Depart Date": "離職日期", | "Depart Date": "離職日期", | ||||
"Depart Reason": "離職原因", | "Depart Reason": "離職原因", | ||||
"Remark": "備註" | |||||
"Remark": "備註", | |||||
"Confirm": "確認", | |||||
"Cancel": "取消" | |||||
} | } |