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