| @@ -67,6 +67,12 @@ export const fetchStaff = cache(async () => { | |||
| }); | |||
| }); | |||
| export const fetchStaffWithoutTeam = cache(async () => { | |||
| return serverFetchJson<StaffResult[]>(`${BASE_API_URL}/staffs/noteam`, { | |||
| next: { tags: ["staffs"] }, | |||
| }); | |||
| }); | |||
| // export const fetchStaffCombo = cache(async () => { | |||
| // return serverFetchJson<Staff4TransferList>(`${BASE_API_URL}/staffs/combo`, { | |||
| // next: { tags: ["staffs"] }, | |||
| @@ -51,3 +51,12 @@ export const saveTeam = async (data: CreateTeamInputs) => { | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| }; | |||
| export const deleteTeam = async (data: TeamResult) => { | |||
| return serverFetchJson(`${BASE_API_URL}/team/delete/${data.id}`, { | |||
| method: "DELETE", | |||
| // body: JSON.stringify(data), | |||
| headers: { "Content-Type": "application/json" }, | |||
| }); | |||
| }; | |||
| @@ -47,7 +47,7 @@ const CreateStaffForm: React.FC<formProps> = ({ Title, fieldLists }) => { | |||
| return haveError; | |||
| } | |||
| //check if joinDate > departDate | |||
| if (data.departDate != null && data.departDate != "Invalid Date") { | |||
| 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); | |||
| @@ -56,6 +56,10 @@ const CreateStaffForm: React.FC<formProps> = ({ Title, fieldLists }) => { | |||
| return haveError; | |||
| } | |||
| } | |||
| if (data.departReason == null || data.departReason.length == 0) { | |||
| haveError = true; | |||
| return haveError; | |||
| } | |||
| } | |||
| if (haveError) { | |||
| @@ -68,6 +72,13 @@ const CreateStaffForm: React.FC<formProps> = ({ Title, fieldLists }) => { | |||
| 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); | |||
| @@ -3,7 +3,7 @@ import CreateTeam from "./CreateTeam"; | |||
| import CreateTeamLoading from "./CreateTeamLoading"; | |||
| // import { fetchTeam, fetchTeamLeads } from "@/app/api/team"; | |||
| import { useSearchParams } from "next/navigation"; | |||
| import { fetchStaff } from "@/app/api/staff"; | |||
| import { fetchStaff, fetchStaffWithoutTeam } from "@/app/api/staff"; | |||
| interface SubComponents { | |||
| Loading: typeof CreateTeamLoading; | |||
| @@ -14,7 +14,7 @@ const CreateTeamWrapper: React.FC & SubComponents = async () => { | |||
| const [ | |||
| staff, | |||
| ] = await Promise.all([ | |||
| fetchStaff(), | |||
| fetchStaffWithoutTeam(), | |||
| ]); | |||
| return <CreateTeam allstaff={staff}/>; | |||
| @@ -67,8 +67,8 @@ const Allocation: React.FC<Props> = ({ allStaffs: staff }) => { | |||
| const removeStaff = useCallback((staff: StaffResult) => { | |||
| setSelectedStaff((s) => s.filter((s) => s.id !== staff.id)); | |||
| setDeletedStaffIds((s) => s) | |||
| // setValue("deleteStaffIds", [...staff.id]) | |||
| // setDeletedStaffIds((s) => s) | |||
| setDeletedStaffIds((prevIds) => [...prevIds, staff.id]); | |||
| }, []); | |||
| const setTeamLead = useCallback( | |||
| @@ -118,7 +118,7 @@ const Allocation: React.FC<Props> = ({ allStaffs: staff }) => { | |||
| useEffect(() => { | |||
| setValue("deleteStaffIds", deletedStaffIds) | |||
| console.log(deletedStaffIds) | |||
| }, [deletedStaffIds, setValue]); | |||
| }, [deletedStaffIds]); | |||
| const StaffPoolColumns = useMemo<Column<StaffResult>[]>( | |||
| () => [ | |||
| @@ -70,7 +70,7 @@ const EditTeam: React.FC<Props> = async ({ staff, desc }) => { | |||
| const tempDesc = desc.filter( | |||
| (item) => item.id === parseInt(idString) | |||
| ) | |||
| // console.log(filteredTeam); | |||
| if (filteredTeam.length > 0) { | |||
| const filteredIds: number[] = filteredTeam.map((i) => ( | |||
| i.id | |||
| @@ -82,21 +82,7 @@ const EditTeam: React.FC<Props> = async ({ staff, desc }) => { | |||
| formProps.reset({description: tempDesc[0].description, addStaffIds: idList}) | |||
| setFilteredDesc(tempDesc[0].description) | |||
| } | |||
| // console.log(staff); | |||
| // const desc = staff[0]?.description | |||
| // setDesc(desc) | |||
| // const staff = staff.map((item) => { | |||
| // return { | |||
| // id: item.id, | |||
| // name: item.name, | |||
| // staffId: item.staffId, | |||
| // teamId: item.teamId, | |||
| // staffName: item.staffName, | |||
| // currentPosition: item.currentPosition | |||
| // } as StaffResult | |||
| // }) | |||
| console.log(staff) | |||
| setAllStaffs(staff) | |||
| }, [searchParams]); | |||
| @@ -124,11 +110,12 @@ const EditTeam: React.FC<Props> = async ({ staff, desc }) => { | |||
| const tempData = { | |||
| description: data.description, | |||
| addStaffIds: data.addStaffIds, | |||
| deleteStaffIds: data.deleteStaffIds, | |||
| id: parseInt(idString!!) | |||
| } | |||
| console.log(tempData) | |||
| // await saveTeam(tempData); | |||
| // router.replace("/settings/staff"); | |||
| await saveTeam(tempData); | |||
| router.replace("/settings/team"); | |||
| } catch (e) { | |||
| console.log(e); | |||
| setServerError(t("An error has occurred. Please try again later.")); | |||
| @@ -0,0 +1,105 @@ | |||
| "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; | |||
| } | |||
| 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; | |||
| @@ -9,6 +9,9 @@ import EditNote from "@mui/icons-material/EditNote"; | |||
| import DeleteIcon from '@mui/icons-material/Delete'; | |||
| import { deleteStaff } from "@/app/api/staff/actions"; | |||
| import { useRouter } from "next/navigation"; | |||
| import ConfirmModal from "./ConfirmDeleteModal"; | |||
| import { deleteTeam } from "@/app/api/team/actions"; | |||
| interface Props { | |||
| team: TeamResult[]; | |||
| @@ -50,23 +53,47 @@ const TeamSearch: React.FC<Props> = ({ team }) => { | |||
| router.push(`/settings/team/edit?id=${id}`); | |||
| }, [router, t]); | |||
| // const onDeleteClick = useCallback((team: TeamResult) => { | |||
| // console.log(team); | |||
| // deleteTeam | |||
| // }, [router, t]); | |||
| const onDeleteClick = (team: TeamResult) => { | |||
| console.log(team); | |||
| setData(team) | |||
| setIsOpen(!isOpen) | |||
| }; | |||
| const onConfirm = useCallback(async (team: TeamResult) => { | |||
| console.log(team); | |||
| if (data) | |||
| await deleteTeam(data) | |||
| setIsOpen(false) | |||
| window.location.reload; | |||
| }, [deleteTeam, data]); | |||
| const onCancel = useCallback(() => { | |||
| setIsOpen(false) | |||
| }, []); | |||
| const columns = useMemo<Column<TeamResult>[]>( | |||
| () => [ | |||
| { | |||
| name: "action", | |||
| label: t("Actions"), | |||
| label: t("Edit"), | |||
| onClick: onTeamClick, | |||
| buttonIcon: <EditNote />, | |||
| }, | |||
| { name: "name", label: t("Name") }, | |||
| { name: "code", label: t("Code") }, | |||
| { name: "description", label: t("description") }, | |||
| // { | |||
| // name: "action", | |||
| // label: t("Actions"), | |||
| // onClick: deleteClick, | |||
| // buttonIcon: <DeleteIcon />, | |||
| // }, | |||
| { | |||
| name: "action", | |||
| label: t("Delete"), | |||
| onClick: onDeleteClick, | |||
| buttonIcon: <DeleteIcon />, | |||
| }, | |||
| ], | |||
| [t], | |||
| ); | |||
| @@ -89,6 +116,11 @@ const TeamSearch: React.FC<Props> = ({ team }) => { | |||
| }} | |||
| /> | |||
| <SearchResults<TeamResult> items={filteredTeam} columns={columns} /> | |||
| <ConfirmModal | |||
| isOpen={isOpen} | |||
| onConfirm={onConfirm} | |||
| onCancel={onCancel} | |||
| /> | |||
| </> | |||
| ); | |||