diff --git a/src/app/(main)/settings/department/edit/page.tsx b/src/app/(main)/settings/department/edit/page.tsx new file mode 100644 index 0000000..748003e --- /dev/null +++ b/src/app/(main)/settings/department/edit/page.tsx @@ -0,0 +1,31 @@ +import CreateDepartment from "@/components/CreateDepartment"; +import { I18nProvider, getServerI18n } from "@/i18n"; +import Typography from "@mui/material/Typography"; +import { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Create Department", +}; + +interface Props { + searchParams: { [key: string]: string | undefined }; +} + +const Department: React.FC = async ({searchParams}) => { + const { t } = await getServerI18n("departments"); + + // Preload necessary dependencies + // Assume projectId is string here + const departmentId = searchParams["id"]; + + return ( + <> + {t("Create Department")} + + + + + ); +}; + +export default Department; diff --git a/src/app/(main)/settings/department/new/page.tsx b/src/app/(main)/settings/department/new/page.tsx index 1f94edc..2121dc6 100644 --- a/src/app/(main)/settings/department/new/page.tsx +++ b/src/app/(main)/settings/department/new/page.tsx @@ -16,7 +16,7 @@ const Department: React.FC = async () => { <> {t("Create Department")} - + ); diff --git a/src/app/api/departments/actions.ts b/src/app/api/departments/actions.ts index c6bdfd2..48a3174 100644 --- a/src/app/api/departments/actions.ts +++ b/src/app/api/departments/actions.ts @@ -1,6 +1,6 @@ "use server" -import { serverFetchJson } from "@/app/utils/fetchUtil"; +import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; import { BASE_API_URL } from "@/config/api"; import { cache } from "react"; @@ -14,8 +14,9 @@ export interface combo { records: comboProp[]; } export interface CreateDepartmentInputs { - departmentCode: string; - departmentName: string; + id: number; + code: string; + name: string; description: string; } @@ -25,7 +26,19 @@ export const saveDepartment = async (data: CreateDepartmentInputs) => { body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }); - }; +}; + +export const deleteDepartment = async (id: number) => { + const department = await serverFetchWithNoContent( + `${BASE_API_URL}/departments/${id}`, + { + method: "DELETE", + headers: { "Content-Type": "application/json" }, + }, + ); + + return department +}; export const fetchDepartmentCombo = cache(async () => { diff --git a/src/app/api/departments/index.ts b/src/app/api/departments/index.ts index 9bb4354..580b302 100644 --- a/src/app/api/departments/index.ts +++ b/src/app/api/departments/index.ts @@ -2,6 +2,7 @@ import { serverFetchJson } from "@/app/utils/fetchUtil"; import { BASE_API_URL } from "@/config/api"; import { cache } from "react"; import "server-only"; +import { CreateDepartmentInputs } from "./actions"; export interface DepartmentResult { id: number; @@ -18,4 +19,13 @@ export const fetchDepartments = cache(async () => { return serverFetchJson(`${BASE_API_URL}/departments`, { next: { tags: ["departments"] }, }); +}); + +export const fetchDepartmentDetails = cache(async (departmentId: string) => { + return serverFetchJson( + `${BASE_API_URL}/departments/departmentDetails/${departmentId}`, + { + next: { tags: [`departmentDetail${departmentId}`] }, + }, + ); }); \ No newline at end of file diff --git a/src/app/api/positions/actions.ts b/src/app/api/positions/actions.ts index 2f69990..8826cc7 100644 --- a/src/app/api/positions/actions.ts +++ b/src/app/api/positions/actions.ts @@ -1,6 +1,6 @@ "use server" -import { serverFetchJson } from "@/app/utils/fetchUtil"; +import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; import { BASE_API_URL } from "@/config/api"; import { cache } from "react"; import { PositionResult } from "."; @@ -15,15 +15,15 @@ export interface combo { } export interface CreatePositionInputs { - positionCode: string; - positionName: string; + code: string; + name: string; description: string; } export interface EditPositionInputs { id: number; - positionCode: string; - positionName: string; + code: string; + name: string; description: string; } @@ -35,13 +35,25 @@ export const savePosition = async (data: CreatePositionInputs) => { }); }; - export const editPosition = async (data: EditPositionInputs) => { - return serverFetchJson(`${BASE_API_URL}/positions/new`, { - method: "POST", - body: JSON.stringify(data), - headers: { "Content-Type": "application/json" }, - }); - }; +export const editPosition = async (data: EditPositionInputs) => { + return serverFetchJson(`${BASE_API_URL}/positions/new`, { + method: "POST", + body: JSON.stringify(data), + headers: { "Content-Type": "application/json" }, + }); +}; + +export const deletePosition = async (id: number) => { + const position = await serverFetchWithNoContent( + `${BASE_API_URL}/positions/${id}`, + { + method: "DELETE", + headers: { "Content-Type": "application/json" }, + }, + ); + + return position +}; export const fetchPositionCombo = cache(async () => { return serverFetchJson(`${BASE_API_URL}/positions/combo`, { diff --git a/src/components/CreateDepartment/CreateDepartment.tsx b/src/components/CreateDepartment/CreateDepartment.tsx index 42088fe..2d95d28 100644 --- a/src/components/CreateDepartment/CreateDepartment.tsx +++ b/src/components/CreateDepartment/CreateDepartment.tsx @@ -22,18 +22,23 @@ import { Error } from "@mui/icons-material"; import { ProjectCategory } from "@/app/api/projects"; import { Typography } from "@mui/material"; import DepartmentDetails from "./DepartmentDetails"; +import { DepartmentResult } from "@/app/api/departments"; +interface Props { + isEdit: Boolean; + department?: CreateDepartmentInputs; +} -const CreateDepartment: React.FC = ({ - // allTasks, - // projectCategories, - // taskTemplates, - // teamLeads, +const CreateDepartment: React.FC = ({ + isEdit, + department, }) => { const [serverError, setServerError] = useState(""); const { t } = useTranslation(); const router = useRouter(); + console.log(department) + const handleCancel = () => { router.back(); }; @@ -62,9 +67,10 @@ const CreateDepartment: React.FC = ({ const formProps = useForm({ defaultValues: { - departmentCode: "", - departmentName: "", - description: "", + id: department?.id, + code: department?.code, + name: department?.name, + description: department?.description, }, }); diff --git a/src/components/CreateDepartment/CreateDepartmentWrapper.tsx b/src/components/CreateDepartment/CreateDepartmentWrapper.tsx index cf32044..199ed1c 100644 --- a/src/components/CreateDepartment/CreateDepartmentWrapper.tsx +++ b/src/components/CreateDepartment/CreateDepartmentWrapper.tsx @@ -1,18 +1,24 @@ import { fetchAllTasks, fetchTaskTemplates } from "@/app/api/tasks"; import CreateDepartment from "./CreateDepartment"; import { fetchTeamLeads } from "@/app/api/staff"; +import { DepartmentResult, fetchDepartmentDetails } from "@/app/api/departments"; -const CreateDepartmentWrapper: React.FC = async () => { - // const [tasks, taskTemplates, DepartmentCategories, teamLeads] = - // await Promise.all([ - // fetchAllTasks(), - // fetchTaskTemplates(), - // fetchDepartmentCategories(), - // fetchTeamLeads(), - // ]); +type CreateDepartmentProps = { isEdit: false }; +interface EditDepartmentProps { + isEdit: true; + departmentId?: string; +} + +type Props = CreateDepartmentProps | EditDepartmentProps; + +const CreateDepartmentWrapper: React.FC = async (props) => { + + const departmentInfo = props.isEdit + ? await fetchDepartmentDetails(props.departmentId!) + : undefined; return ( - ); }; diff --git a/src/components/CreateDepartment/DepartmentDetails.tsx b/src/components/CreateDepartment/DepartmentDetails.tsx index 4039587..8cd559c 100644 --- a/src/components/CreateDepartment/DepartmentDetails.tsx +++ b/src/components/CreateDepartment/DepartmentDetails.tsx @@ -39,20 +39,20 @@ const DepartmentDetails: React.FC = ({ diff --git a/src/components/CreatePosition/PositionDetails.tsx b/src/components/CreatePosition/PositionDetails.tsx index 5e03acd..22542c5 100644 --- a/src/components/CreatePosition/PositionDetails.tsx +++ b/src/components/CreatePosition/PositionDetails.tsx @@ -39,20 +39,20 @@ const PositionDetails: React.FC = ({ diff --git a/src/components/DepartmentSearch/DepartmentSearch.tsx b/src/components/DepartmentSearch/DepartmentSearch.tsx index 57cd3ab..b881bb4 100644 --- a/src/components/DepartmentSearch/DepartmentSearch.tsx +++ b/src/components/DepartmentSearch/DepartmentSearch.tsx @@ -5,8 +5,11 @@ import SearchBox, { Criterion } from "../SearchBox"; import { useTranslation } from "react-i18next"; import SearchResults, { Column } from "../SearchResults"; import EditNote from "@mui/icons-material/EditNote"; -import uniq from "lodash/uniq"; import { DepartmentResult } from "@/app/api/departments"; +import { useRouter } from "next/navigation"; +import DeleteIcon from '@mui/icons-material/Delete'; +import { deleteDialog, successDialog } from "../Swal/CustomAlerts"; +import { deleteDepartment } from "@/app/api/departments/actions"; interface Props { departments: DepartmentResult[]; @@ -17,6 +20,7 @@ type SearchParamNames = keyof SearchQuery; const DepartmentSearch: React.FC = ({ departments }) => { const { t } = useTranslation("departments"); + const router = useRouter(); const [filteredDepartments, setFilteredDepartments] = useState(departments); @@ -33,8 +37,20 @@ const DepartmentSearch: React.FC = ({ departments }) => { setFilteredDepartments(departments); }, [departments]); - const onProjectClick = useCallback((project: DepartmentResult) => { - console.log(project); + const onProjectClick = useCallback((department: DepartmentResult) => { + console.log(department.id) + router.push(`/settings/department/edit?id=${department.id}`); + }, [router]); + + const onDeleteClick = useCallback((department: DepartmentResult) => { + + deleteDialog(async() => { + await deleteDepartment(department.id) + + successDialog("Delete Success", t) + + setFilteredDepartments((prev) => prev.filter((obj) => obj.id !== department.id)) + }, t) }, []); const columns = useMemo[]>( @@ -48,6 +64,13 @@ const DepartmentSearch: React.FC = ({ departments }) => { { name: "code", label: t("Department Code") }, { name: "name", label: t("Department Name") }, { name: "description", label: t("Department Description") }, + { + name: "id", + label: t("Delete"), + onClick: onDeleteClick, + buttonIcon: , + color: "error" + }, ], [t, onProjectClick], ); diff --git a/src/components/EditPosition/EditPosition.tsx b/src/components/EditPosition/EditPosition.tsx index 92cf871..602f489 100644 --- a/src/components/EditPosition/EditPosition.tsx +++ b/src/components/EditPosition/EditPosition.tsx @@ -45,16 +45,8 @@ const EditPosition: React.FC = ({ try{ if (positionId !== null && parseInt(positionId) > 0) { const postionDetails = await fetchPositionDetails(parseInt(positionId)) - const updatedArray: EditPositionInputs[] = postionDetails.map((obj) => { - return { - id: obj.id, - positionCode: obj.code, - positionName: obj.name, - description: obj.description - }; - }); - setPositionDetails(updatedArray[0]) + setPositionDetails(postionDetails[0]) } } catch (error){ console.log(error) diff --git a/src/components/EditPosition/PositionDetails.tsx b/src/components/EditPosition/PositionDetails.tsx index 086998e..91ac18d 100644 --- a/src/components/EditPosition/PositionDetails.tsx +++ b/src/components/EditPosition/PositionDetails.tsx @@ -46,20 +46,20 @@ const PositionDetails: React.FC = ({ diff --git a/src/components/PositionSearch/PositionSearch.tsx b/src/components/PositionSearch/PositionSearch.tsx index d0b3ee4..e700e2a 100644 --- a/src/components/PositionSearch/PositionSearch.tsx +++ b/src/components/PositionSearch/PositionSearch.tsx @@ -7,6 +7,9 @@ import SearchResults, { Column } from "../SearchResults"; import EditNote from "@mui/icons-material/EditNote"; import { PositionResult } from "@/app/api/positions"; import { useRouter } from "next/navigation"; +import DeleteIcon from '@mui/icons-material/Delete'; +import { deleteDialog, successDialog } from "../Swal/CustomAlerts"; +import { deletePosition } from "@/app/api/positions/actions"; interface Props { positions: PositionResult[]; @@ -34,12 +37,23 @@ const PositionSearch: React.FC = ({ positions }) => { setFilteredPositions(positions); }, [positions]); - const onPositionClick = useCallback((project: PositionResult) => { - console.log(project); - const id = project.id + const onPositionClick = useCallback((position: PositionResult) => { + console.log(position); + const id = position.id router.push(`/settings/position/edit?id=${id}`); }, []); + const onDeleteClick = useCallback((position: PositionResult) => { + + deleteDialog(async() => { + await deletePosition(position.id) + + successDialog("Delete Success", t) + + setFilteredPositions((prev) => prev.filter((obj) => obj.id !== position.id)) + }, t) +}, []); + const columns = useMemo[]>( () => [ { @@ -51,6 +65,13 @@ const PositionSearch: React.FC = ({ positions }) => { { name: "code", label: t("Position Code") }, { name: "name", label: t("Position Name") }, { name: "description", label: t("Position Description") }, + { + name: "id", + label: t("Delete"), + onClick: onDeleteClick, + buttonIcon: , + color: "error" + }, ], [t, onPositionClick], );