@@ -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} | |||
/> | |||
</> | |||
); | |||