|
- "use client";
-
- import React, { useCallback, useEffect, useMemo, useState } from "react";
- import SearchBox, { Criterion } from "../SearchBox";
- import { useTranslation } from "react-i18next";
- import SearchResults, { Column } from "../SearchResults";
- import EditNote from "@mui/icons-material/EditNote";
- import { fetchQcCategoriesForAll } from "@/app/api/settings/qcItemAll/actions";
- import { QcCategoryResult } from "@/app/api/settings/qcItemAll";
- import {
- deleteDialog,
- errorDialogWithContent,
- submitDialog,
- successDialog,
- } from "../Swal/CustomAlerts";
- import {
- deleteQcCategoryWithValidation,
- canDeleteQcCategory,
- saveQcCategoryWithValidation,
- SaveQcCategoryInputs,
- } from "@/app/api/settings/qcItemAll/actions";
- import Delete from "@mui/icons-material/Delete";
- import { Add } from "@mui/icons-material";
- import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Stack } from "@mui/material";
- import QcCategoryDetails from "../QcCategorySave/QcCategoryDetails";
- import { FormProvider, useForm } from "react-hook-form";
-
- type SearchQuery = Partial<Omit<QcCategoryResult, "id">>;
- type SearchParamNames = keyof SearchQuery;
-
- const Tab2QcCategoryManagement: React.FC = () => {
- const { t } = useTranslation("qcItemAll");
- const [qcCategories, setQcCategories] = useState<QcCategoryResult[]>([]);
- const [filteredQcCategories, setFilteredQcCategories] = useState<QcCategoryResult[]>([]);
- const [openDialog, setOpenDialog] = useState(false);
- const [editingCategory, setEditingCategory] = useState<QcCategoryResult | null>(null);
-
- useEffect(() => {
- loadCategories();
- }, []);
-
- const loadCategories = async () => {
- const categories = await fetchQcCategoriesForAll();
- setQcCategories(categories);
- setFilteredQcCategories(categories);
- };
-
- const formProps = useForm<SaveQcCategoryInputs>({
- defaultValues: {
- code: "",
- name: "",
- description: "",
- },
- });
-
- const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
- () => [
- { label: t("Code"), paramName: "code", type: "text" },
- { label: t("Name"), paramName: "name", type: "text" },
- ],
- [t]
- );
-
- const onReset = useCallback(() => {
- setFilteredQcCategories(qcCategories);
- }, [qcCategories]);
-
- const handleEdit = useCallback((qcCategory: QcCategoryResult) => {
- setEditingCategory(qcCategory);
- formProps.reset({
- id: qcCategory.id,
- code: qcCategory.code,
- name: qcCategory.name,
- description: qcCategory.description || "",
- });
- setOpenDialog(true);
- }, [formProps]);
-
- const handleAdd = useCallback(() => {
- setEditingCategory(null);
- formProps.reset({
- code: "",
- name: "",
- description: "",
- });
- setOpenDialog(true);
- }, [formProps]);
-
- const handleSubmit = useCallback(async (data: SaveQcCategoryInputs) => {
- await submitDialog(async () => {
- try {
- const response = await saveQcCategoryWithValidation(data);
- if (response.errors) {
- let errorContents = "";
- for (const [key, value] of Object.entries(response.errors)) {
- formProps.setError(key as keyof SaveQcCategoryInputs, {
- type: "custom",
- message: value,
- });
- errorContents = errorContents + t(value) + "<br>";
- }
- errorDialogWithContent(t("Submit Error"), errorContents, t);
- } else {
- await successDialog(t("Submit Success"), t);
- setOpenDialog(false);
- await loadCategories();
- }
- } catch (error) {
- errorDialogWithContent(t("Submit Error"), String(error), t);
- }
- }, t);
- }, [formProps, t]);
-
- const handleDelete = useCallback(async (qcCategory: QcCategoryResult) => {
- // Check if can delete first
- const canDelete = await canDeleteQcCategory(qcCategory.id); // This is a server action, token handled server-side
-
- if (!canDelete) {
- errorDialogWithContent(
- t("Cannot Delete"),
- t("Cannot delete QcCategory. It has {itemCount} item(s) and {qcItemCount} qc item(s) linked to it.").replace("{itemCount}", "some").replace("{qcItemCount}", "some"),
- t
- );
- return;
- }
-
- deleteDialog(async () => {
- try {
- const response = await deleteQcCategoryWithValidation(qcCategory.id);
- if (!response.success || !response.canDelete) {
- errorDialogWithContent(
- t("Delete Error"),
- response.message || t("Cannot Delete"),
- t
- );
- } else {
- await successDialog(t("Delete Success"), t);
- await loadCategories();
- }
- } catch (error) {
- errorDialogWithContent(t("Delete Error"), String(error), t);
- }
- }, t);
- }, [t]);
-
- const columnWidthSx = (width = "10%") => {
- return { width: width, whiteSpace: "nowrap" };
- };
-
- const columns = useMemo<Column<QcCategoryResult>[]>(
- () => [
- {
- name: "id",
- label: t("Details"),
- onClick: handleEdit,
- buttonIcon: <EditNote />,
- sx: columnWidthSx("5%"),
- },
- { name: "code", label: t("Code"), sx: columnWidthSx("15%") },
- { name: "name", label: t("Name"), sx: columnWidthSx("30%") },
- {
- name: "id",
- label: t("Delete"),
- onClick: handleDelete,
- buttonIcon: <Delete />,
- buttonColor: "error",
- sx: columnWidthSx("5%"),
- },
- ],
- [t, handleEdit, handleDelete]
- );
-
- return (
- <>
- <Stack direction="row" justifyContent="flex-end" sx={{ mb: 2 }}>
- <Button
- variant="contained"
- startIcon={<Add />}
- onClick={handleAdd}
- >
- {t("Create Qc Category")}
- </Button>
- </Stack>
- <SearchBox
- criteria={searchCriteria}
- onSearch={(query) => {
- setFilteredQcCategories(
- qcCategories.filter(
- (qc) =>
- (!query.code || qc.code.toLowerCase().includes(query.code.toLowerCase())) &&
- (!query.name || qc.name.toLowerCase().includes(query.name.toLowerCase()))
- )
- );
- }}
- onReset={onReset}
- />
- <SearchResults<QcCategoryResult>
- items={filteredQcCategories}
- columns={columns}
- />
-
- {/* Add/Edit Dialog */}
- <Dialog open={openDialog} onClose={() => setOpenDialog(false)} maxWidth="md" fullWidth>
- <DialogTitle>
- {editingCategory ? t("Edit Qc Category") : t("Create Qc Category")}
- </DialogTitle>
- <FormProvider {...formProps}>
- <form onSubmit={formProps.handleSubmit(handleSubmit)}>
- <DialogContent>
- <QcCategoryDetails />
- </DialogContent>
- <DialogActions>
- <Button onClick={() => setOpenDialog(false)}>{t("Cancel")}</Button>
- <Button type="submit" variant="contained">
- {t("Submit")}
- </Button>
- </DialogActions>
- </form>
- </FormProvider>
- </Dialog>
- </>
- );
- };
-
- export default Tab2QcCategoryManagement;
|