@@ -9,6 +9,12 @@ export interface QcCategoryResult { | |||||
name: string; | name: string; | ||||
} | } | ||||
export interface QcCategoryCombo { | |||||
id: number; | |||||
value: number; | |||||
label: string; | |||||
} | |||||
export const preloadQcCategory = () => { | export const preloadQcCategory = () => { | ||||
fetchQcCategories(); | fetchQcCategories(); | ||||
}; | }; | ||||
@@ -18,3 +24,9 @@ export const fetchQcCategories = cache(async () => { | |||||
next: { tags: ["qcCategories"] }, | next: { tags: ["qcCategories"] }, | ||||
}); | }); | ||||
}); | }); | ||||
export const fetchQcCategoryCombo = cache(async () => { | |||||
return serverFetchJson<QcCategoryCombo[]>(`${BASE_API_URL}/qcCategories/combo`, { | |||||
next: { tags: ["qcCategoryCombo"] }, | |||||
}); | |||||
}); |
@@ -0,0 +1,20 @@ | |||||
"server only" | |||||
import { BASE_API_URL } from '@/config/api'; | |||||
import { serverFetchJson } from '@/app/utils/fetchUtil'; | |||||
import { cache } from "react"; | |||||
export interface ShopCombo { | |||||
id: number; | |||||
value: number; // id | |||||
label: string; | |||||
} | |||||
export const fetchSupplierCombo = cache(async() => { | |||||
return serverFetchJson<ShopCombo[]>(`${BASE_API_URL}/shop/combo/supplier`, { | |||||
method: "GET", | |||||
headers: { "Content-Type": "application/json"}, | |||||
next: { | |||||
tags: ["supplierCombo"] | |||||
} | |||||
}) | |||||
}) |
@@ -29,12 +29,14 @@ import QcDetails from "./QcDetails"; | |||||
import { ItemQc } from "@/app/api/settings/item"; | import { ItemQc } from "@/app/api/settings/item"; | ||||
import { saveItemQcChecks } from "@/app/api/settings/qcCheck/actions"; | import { saveItemQcChecks } from "@/app/api/settings/qcCheck/actions"; | ||||
import { useGridApiRef } from "@mui/x-data-grid"; | import { useGridApiRef } from "@mui/x-data-grid"; | ||||
import { QcCategoryCombo } from "@/app/api/settings/qcCategory"; | |||||
type Props = { | type Props = { | ||||
isEditMode: boolean; | isEditMode: boolean; | ||||
// type: TypeEnum; | // type: TypeEnum; | ||||
defaultValues: Partial<CreateItemInputs> | undefined; | defaultValues: Partial<CreateItemInputs> | undefined; | ||||
qcChecks: ItemQc[]; | qcChecks: ItemQc[]; | ||||
qcCategoryCombo: QcCategoryCombo[] | |||||
}; | }; | ||||
const CreateItem: React.FC<Props> = ({ | const CreateItem: React.FC<Props> = ({ | ||||
@@ -42,6 +44,7 @@ const CreateItem: React.FC<Props> = ({ | |||||
// type, | // type, | ||||
defaultValues, | defaultValues, | ||||
qcChecks, | qcChecks, | ||||
qcCategoryCombo, | |||||
}) => { | }) => { | ||||
// console.log(type) | // console.log(type) | ||||
const apiRef = useGridApiRef(); | const apiRef = useGridApiRef(); | ||||
@@ -192,7 +195,7 @@ const CreateItem: React.FC<Props> = ({ | |||||
{serverError} | {serverError} | ||||
</Typography> | </Typography> | ||||
)} | )} | ||||
{tabIndex === 0 && <ProductDetails isEditMode={isEditMode} />} | |||||
{tabIndex === 0 && <ProductDetails isEditMode={isEditMode} qcCategoryCombo={qcCategoryCombo}/>} | |||||
{tabIndex === 1 && <QcDetails apiRef={apiRef} />} | {tabIndex === 1 && <QcDetails apiRef={apiRef} />} | ||||
{/* {type === TypeEnum.MATERIAL && <MaterialDetails />} */} | {/* {type === TypeEnum.MATERIAL && <MaterialDetails />} */} | ||||
{/* {type === TypeEnum.BYPRODUCT && <ByProductDetails />} */} | {/* {type === TypeEnum.BYPRODUCT && <ByProductDetails />} */} | ||||
@@ -5,6 +5,7 @@ import { CreateItemInputs } from "@/app/api/settings/item/actions"; | |||||
import { notFound } from "next/navigation"; | import { notFound } from "next/navigation"; | ||||
import { fetchItem } from "@/app/api/settings/item"; | import { fetchItem } from "@/app/api/settings/item"; | ||||
import { fetchQcItems } from "@/app/api/settings/qcItem"; | import { fetchQcItems } from "@/app/api/settings/qcItem"; | ||||
import { fetchQcCategoryCombo } from "@/app/api/settings/qcCategory"; | |||||
interface SubComponents { | interface SubComponents { | ||||
Loading: typeof CreateItemLoading; | Loading: typeof CreateItemLoading; | ||||
} | } | ||||
@@ -37,14 +38,18 @@ const CreateItemWrapper: React.FC<Props> & SubComponents = async ({ id }) => { | |||||
maxQty: item?.maxQty, | maxQty: item?.maxQty, | ||||
qcChecks: qcChecks, | qcChecks: qcChecks, | ||||
qcChecks_active: activeRows, | qcChecks_active: activeRows, | ||||
qcCategoryId: item.qcCategory?.id | |||||
}; | }; | ||||
} | } | ||||
const qcCategoryCombo = await fetchQcCategoryCombo(); | |||||
return ( | return ( | ||||
<CreateItem | <CreateItem | ||||
isEditMode={Boolean(id)} | isEditMode={Boolean(id)} | ||||
defaultValues={defaultValues} | defaultValues={defaultValues} | ||||
qcChecks={qcChecks || []} | qcChecks={qcChecks || []} | ||||
qcCategoryCombo={qcCategoryCombo} | |||||
/> | /> | ||||
); | ); | ||||
}; | }; | ||||
@@ -1,5 +1,6 @@ | |||||
"use client"; | "use client"; | ||||
import { | import { | ||||
Autocomplete, | |||||
Box, | Box, | ||||
Button, | Button, | ||||
Card, | Card, | ||||
@@ -10,11 +11,11 @@ import { | |||||
Typography, | Typography, | ||||
} from "@mui/material"; | } from "@mui/material"; | ||||
import { Check, Close, EditNote } from "@mui/icons-material"; | import { Check, Close, EditNote } from "@mui/icons-material"; | ||||
import { useFormContext } from "react-hook-form"; | |||||
import { Controller, useFormContext } from "react-hook-form"; | |||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import InputDataGrid from "../InputDataGrid"; | import InputDataGrid from "../InputDataGrid"; | ||||
import { useCallback, useMemo, useState } from "react"; | |||||
import { SyntheticEvent, useCallback, useMemo, useState } from "react"; | |||||
import { GridColDef, GridRowModel } from "@mui/x-data-grid"; | import { GridColDef, GridRowModel } from "@mui/x-data-grid"; | ||||
import { InputDataGridProps, TableRow } from "../InputDataGrid/InputDataGrid"; | import { InputDataGridProps, TableRow } from "../InputDataGrid/InputDataGrid"; | ||||
import { TypeEnum } from "@/app/utils/typeEnum"; | import { TypeEnum } from "@/app/utils/typeEnum"; | ||||
@@ -22,6 +23,7 @@ import { NumberInputProps } from "./NumberInputProps"; | |||||
import { CreateItemInputs } from "@/app/api/settings/item/actions"; | import { CreateItemInputs } from "@/app/api/settings/item/actions"; | ||||
import { RestartAlt } from "@mui/icons-material"; | import { RestartAlt } from "@mui/icons-material"; | ||||
import { ItemQc } from "@/app/api/settings/item"; | import { ItemQc } from "@/app/api/settings/item"; | ||||
import { QcCategoryCombo } from "@/app/api/settings/qcCategory"; | |||||
type Props = { | type Props = { | ||||
// isEditMode: boolean; | // isEditMode: boolean; | ||||
// type: TypeEnum; | // type: TypeEnum; | ||||
@@ -29,9 +31,10 @@ type Props = { | |||||
// type: TypeEnum; | // type: TypeEnum; | ||||
defaultValues?: Partial<CreateItemInputs> | undefined; | defaultValues?: Partial<CreateItemInputs> | undefined; | ||||
qcChecks?: ItemQc[]; | qcChecks?: ItemQc[]; | ||||
qcCategoryCombo: QcCategoryCombo[]; | |||||
}; | }; | ||||
const ProductDetails: React.FC<Props> = ({ isEditMode }) => { | |||||
const ProductDetails: React.FC<Props> = ({ isEditMode, qcCategoryCombo }) => { | |||||
const { | const { | ||||
t, | t, | ||||
i18n: { language }, | i18n: { language }, | ||||
@@ -104,6 +107,11 @@ const ProductDetails: React.FC<Props> = ({ isEditMode }) => { | |||||
// router.replace(`/settings/product`); | // router.replace(`/settings/product`); | ||||
console.log("cancel"); | console.log("cancel"); | ||||
}; | }; | ||||
const handleAutoCompleteChange = useCallback((event: SyntheticEvent<Element, Event>, value: QcCategoryCombo, onChange: (...event: any[]) => void) => { | |||||
onChange(value.id) | |||||
}, []) | |||||
return ( | return ( | ||||
<Card sx={{ display: "block" }}> | <Card sx={{ display: "block" }}> | ||||
<CardContent component={Stack} spacing={4}> | <CardContent component={Stack} spacing={4}> | ||||
@@ -202,7 +210,31 @@ const ProductDetails: React.FC<Props> = ({ isEditMode }) => { | |||||
helperText={errors.maxQty?.message} | helperText={errors.maxQty?.message} | ||||
/> | /> | ||||
</Grid> | </Grid> | ||||
<Grid item xs={0}> | |||||
<Grid item xs={6}> | |||||
<Controller | |||||
control={control} | |||||
name="qcCategoryId" | |||||
render={({ field }) => ( | |||||
<Autocomplete | |||||
disableClearable | |||||
options={qcCategoryCombo} | |||||
defaultValue={qcCategoryCombo.find(qc => qc.id === field.value)} | |||||
onChange={(event, value) => { | |||||
handleAutoCompleteChange(event, value, field.onChange) | |||||
}} | |||||
onBlur={field.onBlur} | |||||
renderInput={(params) => ( | |||||
<TextField | |||||
{...params} | |||||
variant="outlined" | |||||
label={t("Qc Category")} | |||||
/> | |||||
)} | |||||
/> | |||||
)} | |||||
/> | |||||
</Grid> | |||||
<Grid item xs={12}> | |||||
<Stack | <Stack | ||||
direction="row" | direction="row" | ||||
justifyContent="flex-end" | justifyContent="flex-end" | ||||
@@ -82,23 +82,23 @@ const InventoryLotLineTable: React.FC<Props> = ({ inventoryLotLines, pagingContr | |||||
}, | }, | ||||
{ | { | ||||
name: "uom", | name: "uom", | ||||
label: t("Sales UoM"), | |||||
align: "left", | |||||
headerAlign: "left", | |||||
}, | |||||
{ | |||||
name: "qtyPerSmallestUnit", | |||||
label: t("Available Qty Per Smallest Unit"), | |||||
align: "right", | |||||
headerAlign: "right", | |||||
type: "integer", | |||||
}, | |||||
{ | |||||
name: "baseUom", | |||||
label: t("Base UoM"), | |||||
label: t("Stock UoM"), | |||||
align: "left", | align: "left", | ||||
headerAlign: "left", | headerAlign: "left", | ||||
}, | }, | ||||
// { | |||||
// name: "qtyPerSmallestUnit", | |||||
// label: t("Available Qty Per Smallest Unit"), | |||||
// align: "right", | |||||
// headerAlign: "right", | |||||
// type: "integer", | |||||
// }, | |||||
// { | |||||
// name: "baseUom", | |||||
// label: t("Base UoM"), | |||||
// align: "left", | |||||
// headerAlign: "left", | |||||
// }, | |||||
{ | { | ||||
name: "expiryDate", | name: "expiryDate", | ||||
label: t("Expiry Date"), | label: t("Expiry Date"), | ||||
@@ -41,25 +41,25 @@ const InventoryTable: React.FC<Props> = ({ inventories, pagingController, setPag | |||||
}, | }, | ||||
{ | { | ||||
name: "uomUdfudesc", | name: "uomUdfudesc", | ||||
label: t("Sales UoM"), | |||||
align: "left", | |||||
headerAlign: "left", | |||||
}, | |||||
{ | |||||
name: "qtyPerSmallestUnit", | |||||
label: t("Available Qty Per Smallest Unit"), | |||||
align: "right", | |||||
headerAlign: "right", | |||||
type: "integer", | |||||
}, | |||||
{ | |||||
name: "baseUom", | |||||
label: t("Base UoM"), | |||||
label: t("Stock UoM"), | |||||
align: "left", | align: "left", | ||||
headerAlign: "left", | headerAlign: "left", | ||||
}, | }, | ||||
// { | // { | ||||
// name: "qtyPerSmallestUnit", | // name: "qtyPerSmallestUnit", | ||||
// label: t("Available Qty Per Smallest Unit"), | |||||
// align: "right", | |||||
// headerAlign: "right", | |||||
// type: "integer", | |||||
// }, | |||||
// { | |||||
// name: "baseUom", | |||||
// label: t("Base UoM"), | |||||
// align: "left", | |||||
// headerAlign: "left", | |||||
// }, | |||||
// { | |||||
// name: "qtyPerSmallestUnit", | |||||
// label: t("Qty Per Smallest Unit"), | // label: t("Qty Per Smallest Unit"), | ||||
// align: "right", | // align: "right", | ||||
// headerAlign: "right", | // headerAlign: "right", | ||||
@@ -8,12 +8,13 @@ | |||||
"UoM": "單位", | "UoM": "單位", | ||||
"mat": "物料", | "mat": "物料", | ||||
"fg": "成品", | "fg": "成品", | ||||
"Available Qty": "可用數量 (銷售單位)", | |||||
"Available Qty": "可用數量 (倉存單位)", | |||||
"Sales UoM": "銷售單位", | "Sales UoM": "銷售單位", | ||||
"Stock UoM": "倉存單位", | |||||
"Available Qty Per Smallest Unit": "可用數量 (基本單位)", | "Available Qty Per Smallest Unit": "可用數量 (基本單位)", | ||||
"Base UoM": "基本單位", | "Base UoM": "基本單位", | ||||
"Lot No": "批號", | "Lot No": "批號", | ||||
"Expiry Date": "到期日", | "Expiry Date": "到期日", | ||||
"No items are selected yet.": "未選擇項目", | "No items are selected yet.": "未選擇項目", | ||||
"Item selected": "已選擇項目" | "Item selected": "已選擇項目" | ||||
} | |||||
} |
@@ -10,6 +10,7 @@ | |||||
"Product / Material": "產品 / 材料", | "Product / Material": "產品 / 材料", | ||||
"Product / Material Details": "產品 / 材料詳情", | "Product / Material Details": "產品 / 材料詳情", | ||||
"Qc items": "QC 項目", | "Qc items": "QC 項目", | ||||
"Qc Category": "質檢模板", | |||||
"Name": "名稱", | "Name": "名稱", | ||||
"name": "名稱", | "name": "名稱", | ||||
"description": "描述", | "description": "描述", | ||||