diff --git a/src/app/api/settings/qcItem/actions.ts b/src/app/api/settings/qcItem/actions.ts index bb42451..1c63a19 100644 --- a/src/app/api/settings/qcItem/actions.ts +++ b/src/app/api/settings/qcItem/actions.ts @@ -2,7 +2,8 @@ import { serverFetchJson } from "@/app/utils/fetchUtil"; import { BASE_API_URL } from "@/config/api"; -import { revalidateTag } from "next/cache"; +import { revalidatePath, revalidateTag } from "next/cache"; +import { QcItemResult } from '@/app/api/settings/qcItem'; export interface SaveQcItemInputs { id?: number; @@ -26,7 +27,19 @@ export const saveQcItem = async (data: SaveQcItemInputs) => { headers: { "Content-Type": "application/json" }, }) - revalidateTag(`qcItems`) + revalidateTag("qcItems") + + return response +} + +export const deleteQcItem = async (id: number) => { + const response = await serverFetchJson(`${BASE_API_URL}/qcItems/${id}`, { + method: "DELETE", + headers: { "Content-Type": "application/json" }, + }) + + revalidateTag("qcItems") + revalidatePath("/(main)/settings/qcItem") return response } \ No newline at end of file diff --git a/src/app/api/settings/qcItem/index.ts b/src/app/api/settings/qcItem/index.ts index e0b06f9..75f2277 100644 --- a/src/app/api/settings/qcItem/index.ts +++ b/src/app/api/settings/qcItem/index.ts @@ -22,11 +22,11 @@ export const fetchQcItems = cache(async () => { }); }); -export const fetchQcItemDetail = cache(async (qcItemId: string) => { +export const fetchQcItemDetails = cache(async (qcItemId: string) => { return serverFetchJson( - `${BASE_API_URL}/qcItems/qcItemDetail/${qcItemId}`, + `${BASE_API_URL}/qcItems/qcItemDetails/${qcItemId}`, { - next: { tags: [`qcItemDetail_${qcItemId}`] } + next: { tags: [`qcItemDetails_${qcItemId}`] } } ) }) \ No newline at end of file diff --git a/src/app/utils/fetchUtil.ts b/src/app/utils/fetchUtil.ts index cfc352c..8034c63 100644 --- a/src/app/utils/fetchUtil.ts +++ b/src/app/utils/fetchUtil.ts @@ -45,6 +45,7 @@ export const serverFetch: typeof fetch = async (input, init) => { ...(accessToken ? { Authorization: `Bearer ${accessToken}`, + } : {}), }, @@ -56,13 +57,17 @@ type FetchParams = Parameters; export async function serverFetchJson(...args: FetchParams) { const response = await serverFetch(...args); if (response.ok) { + if (response.status === 204) { + return response.status as T + } + return response.json() as T; } else { switch (response.status) { case 401: signOutUser(); default: - throw Error("Something went wrong fetching data in server."); + throw new ServerFetchError("Something went wrong fetching data in server.", response); } } } diff --git a/src/components/QcItemSave/QcItemDetails.tsx b/src/components/QcItemSave/QcItemDetails.tsx index 4d2b703..838b72c 100644 --- a/src/components/QcItemSave/QcItemDetails.tsx +++ b/src/components/QcItemSave/QcItemDetails.tsx @@ -38,9 +38,10 @@ const QcItemDetails = () => { })} /> - + = ({ errorDialogWithContent(t("Submit Error"), errorContents, t) } else { - router.push("/settings/qcItem") + await successDialog( + t("Submit Success"), + t, + () => router.push("/settings/qcItem")) } }, [] @@ -51,6 +56,22 @@ const QcItemSave: React.FC = ({ }, [] ) + const handleCancel = () => { + router.replace("/qcItem"); + }; + + const handleDelete = () => { + deleteDialog(async () => { + await deleteQcItem(formProps.getValues("id")!); + + await successDialog( + t("Delete Success"), + t, + () => router.replace("/settings/qcItem") + ); + }, t); + }; + return ( <> @@ -59,7 +80,32 @@ const QcItemSave: React.FC = ({ component={"form"} onSubmit={formProps.handleSubmit(onSubmit)} > - + + + {defaultInputs?.id && } + + + diff --git a/src/components/QcItemSave/QcItemSaveWrapper.tsx b/src/components/QcItemSave/QcItemSaveWrapper.tsx index b0f3104..6c7a261 100644 --- a/src/components/QcItemSave/QcItemSaveWrapper.tsx +++ b/src/components/QcItemSave/QcItemSaveWrapper.tsx @@ -1,7 +1,7 @@ import React from "react" import QcItemSaveLoading from "./QcItemSaveLoading" import QcItemSave from "./QcItemSave"; -import { fetchQcItemDetail } from "@/app/api/settings/qcItem"; +import { fetchQcItemDetails } from "@/app/api/settings/qcItem"; interface SubComponents { Loading: typeof QcItemSaveLoading; @@ -16,7 +16,7 @@ type Props = SaveQcItemProps const QcItemSaveWrapper: React.FC & SubComponents = async ( props ) => { - const qcItem = props.id ? await fetchQcItemDetail(props.id) : undefined; + const qcItem = props.id ? await fetchQcItemDetails(props.id) : undefined; return ; }; diff --git a/src/components/QcItemSearch/QcItemSearch.tsx b/src/components/QcItemSearch/QcItemSearch.tsx index 80af2e1..29a1ed2 100644 --- a/src/components/QcItemSearch/QcItemSearch.tsx +++ b/src/components/QcItemSearch/QcItemSearch.tsx @@ -6,9 +6,12 @@ import { useTranslation } from "react-i18next"; import SearchResults, { Column } from "../SearchResults"; import EditNote from "@mui/icons-material/EditNote"; import { QcItemResult } from "@/app/api/settings/qcItem"; -import { useRouter } from "next/navigation"; +import { usePathname, useRouter } from "next/navigation"; import QrCodeScanner from "../QrCodeScanner"; import { Button } from "@mui/material"; +import { Delete } from "@mui/icons-material"; +import { deleteDialog, successDialog } from "../Swal/CustomAlerts"; +import { deleteQcItem } from "@/app/api/settings/qcItem/actions"; interface Props { qcItems: QcItemResult[]; @@ -20,6 +23,7 @@ type SearchParamNames = keyof SearchQuery; const qcItemSearch: React.FC = ({ qcItems }) => { const { t } = useTranslation("qcItems"); const router = useRouter(); + const pathname = usePathname() // If qcItem searching is done on the server-side, then no need for this. const [filteredQcItems, setFilteredQcItems] = useState(qcItems); @@ -40,11 +44,24 @@ const qcItemSearch: React.FC = ({ qcItems }) => { const onQcItemClick = useCallback( (qcItem: QcItemResult) => { - router.push(`/edit/${qcItem.id}`); + router.push(`${pathname}/edit?id=${qcItem.id}`); }, [router] ); + const handleDelete = useCallback( + (qcItem: QcItemResult) => { + deleteDialog(async () => { + qcItems = await deleteQcItem(qcItem.id); + setFilteredQcItems(qcItems) + + await successDialog( + t("Delete Success"), + t + ); + }, t); + }, []) + const columns = useMemo[]>( () => [ { @@ -55,28 +72,35 @@ const qcItemSearch: React.FC = ({ qcItems }) => { }, { name: "code", label: t("Code") }, { name: "name", label: t("Name") }, + { + name: "id", + label: t("Delete"), + onClick: handleDelete, + buttonIcon: , + buttonColor: "error" + } ], [t, onQcItemClick] ); - const [isOpenScanner, setOpenScanner] = useState(false) - const onOpenScanner = useCallback(() => { - setOpenScanner(true) - }, []) + // const [isOpenScanner, setOpenScanner] = useState(false) + // const onOpenScanner = useCallback(() => { + // setOpenScanner(true) + // }, []) - const onCloseScanner = useCallback(() => { - setOpenScanner(false) - }, []) + // const onCloseScanner = useCallback(() => { + // setOpenScanner(false) + // }, []) - const handleScanSuccess = useCallback((result: string) => { - console.log(result) - }, []) + // const handleScanSuccess = useCallback((result: string) => { + // console.log(result) + // }, []) return ( <> - - - {/* + */} + { setFilteredQcItems( @@ -89,9 +113,9 @@ const qcItemSearch: React.FC = ({ qcItems }) => { }} onReset={onReset} /> - items={filteredQcItems} columns={columns} /> */} + items={filteredQcItems} columns={columns} /> - ) + ) }; export default qcItemSearch; diff --git a/src/components/QrCodeScanner/QrCodeScanner.tsx b/src/components/QrCodeScanner/QrCodeScanner.tsx index 9dfeb69..c41b7d1 100644 --- a/src/components/QrCodeScanner/QrCodeScanner.tsx +++ b/src/components/QrCodeScanner/QrCodeScanner.tsx @@ -159,14 +159,14 @@ const QrCodeScanner: React.FC = ({ return ( <> - {title ? + {title && {"Title"} - : null} + }