| @@ -0,0 +1,17 @@ | |||||
| import { getServerI18n } from "@/i18n"; | |||||
| import { Stack, Typography, Link } from "@mui/material"; | |||||
| import NextLink from "next/link"; | |||||
| export default async function NotFound() { | |||||
| const { t } = await getServerI18n("qcItem", "common"); | |||||
| return ( | |||||
| <Stack spacing={2}> | |||||
| <Typography variant="h4">{t("Not Found")}</Typography> | |||||
| <Typography variant="body1">{t("The edit detail scheduling page was not found!")}</Typography> | |||||
| <Link href="/scheduling/detail" component={NextLink} variant="body2"> | |||||
| {t("Return to all detail scheduling")} | |||||
| </Link> | |||||
| </Stack> | |||||
| ); | |||||
| } | |||||
| @@ -0,0 +1,47 @@ | |||||
| import { Metadata } from "next"; | |||||
| import { getServerI18n, I18nProvider } from "@/i18n"; | |||||
| import Typography from "@mui/material/Typography"; | |||||
| import { fetchQcItemDetails, preloadQcItem } from "@/app/api/settings/qcItem"; | |||||
| import QcItemSave from "@/components/QcItemSave"; | |||||
| import { isArray } from "lodash"; | |||||
| import { notFound } from "next/navigation"; | |||||
| import { ServerFetchError } from "@/app/utils/fetchUtil"; | |||||
| import DetailScheduleDetail from "@/components/DetailScheduleDetail"; | |||||
| export const metadata: Metadata = { | |||||
| title: "Qc Item", | |||||
| }; | |||||
| interface Props { | |||||
| searchParams: { [key: string]: string | string[] | undefined }; | |||||
| } | |||||
| const DetailScheduling: React.FC<Props> = async ({ searchParams }) => { | |||||
| const { t } = await getServerI18n("schedule") | |||||
| const id = searchParams["id"] | |||||
| if (!id || isArray(id)) { | |||||
| notFound() | |||||
| } | |||||
| // try { | |||||
| // await fetchQcItemDetails(id) | |||||
| // } catch (e) { | |||||
| // if (e instanceof ServerFetchError && (e.response?.status === 404 || e.response?.status === 400)) { | |||||
| // console.log(e) | |||||
| // notFound(); | |||||
| // } | |||||
| // } | |||||
| return <> | |||||
| <Typography variant="h4" marginInlineEnd={2}> | |||||
| {t("FG Production Schedule")} | |||||
| </Typography> | |||||
| <I18nProvider namespaces={["schedule"]}> | |||||
| <DetailScheduleDetail id={id}/> | |||||
| </I18nProvider> | |||||
| </>; | |||||
| }; | |||||
| export default DetailScheduling; | |||||
| @@ -9,7 +9,7 @@ export default async function NotFound() { | |||||
| <Stack spacing={2}> | <Stack spacing={2}> | ||||
| <Typography variant="h4">{t("Not Found")}</Typography> | <Typography variant="h4">{t("Not Found")}</Typography> | ||||
| <Typography variant="body1">{t("The edit qc item page was not found!")}</Typography> | <Typography variant="body1">{t("The edit qc item page was not found!")}</Typography> | ||||
| <Link href="/qcItems" component={NextLink} variant="body2"> | |||||
| <Link href="/settings/qcItems" component={NextLink} variant="body2"> | |||||
| {t("Return to all qc items")} | {t("Return to all qc items")} | ||||
| </Link> | </Link> | ||||
| </Stack> | </Stack> | ||||
| @@ -17,6 +17,7 @@ const pathToLabelMap: { [path: string]: string } = { | |||||
| "/scheduling/rough": "Demand Forecast", | "/scheduling/rough": "Demand Forecast", | ||||
| "/scheduling/rough/edit": "FG & Material Demand Forecast Detail", | "/scheduling/rough/edit": "FG & Material Demand Forecast Detail", | ||||
| "/scheduling/detail": "Detail Scheduling", | "/scheduling/detail": "Detail Scheduling", | ||||
| "/scheduling/detail/edit": "FG Production Schedule", | |||||
| }; | }; | ||||
| const Breadcrumb = () => { | const Breadcrumb = () => { | ||||
| @@ -0,0 +1,40 @@ | |||||
| import Card from "@mui/material/Card"; | |||||
| import CardContent from "@mui/material/CardContent"; | |||||
| import Skeleton from "@mui/material/Skeleton"; | |||||
| import Stack from "@mui/material/Stack"; | |||||
| import React from "react"; | |||||
| // Can make this nicer | |||||
| export const DetailScheduleLoading: React.FC = () => { | |||||
| return ( | |||||
| <> | |||||
| <Card> | |||||
| <CardContent> | |||||
| <Stack spacing={2}> | |||||
| <Skeleton variant="rounded" height={60} /> | |||||
| <Skeleton variant="rounded" height={60} /> | |||||
| <Skeleton variant="rounded" height={60} /> | |||||
| <Skeleton | |||||
| variant="rounded" | |||||
| height={50} | |||||
| width={100} | |||||
| sx={{ alignSelf: "flex-end" }} | |||||
| /> | |||||
| </Stack> | |||||
| </CardContent> | |||||
| </Card> | |||||
| <Card> | |||||
| <CardContent> | |||||
| <Stack spacing={2}> | |||||
| <Skeleton variant="rounded" height={40} /> | |||||
| <Skeleton variant="rounded" height={40} /> | |||||
| <Skeleton variant="rounded" height={40} /> | |||||
| <Skeleton variant="rounded" height={40} /> | |||||
| </Stack> | |||||
| </CardContent> | |||||
| </Card> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| export default DetailScheduleLoading; | |||||
| @@ -0,0 +1,202 @@ | |||||
| "use client"; | |||||
| import React, {useCallback, useEffect, useMemo, useState} from "react"; | |||||
| import SearchBox, { Criterion } from "../SearchBox"; | |||||
| import { ItemsResult} from "@/app/api/settings/item"; | |||||
| import SearchResults, { Column } from "../SearchResults"; | |||||
| import { EditNote } from "@mui/icons-material"; | |||||
| import { useRouter, useSearchParams } from "next/navigation"; | |||||
| import { GridDeleteIcon } from "@mui/x-data-grid"; | |||||
| import { TypeEnum } from "@/app/utils/typeEnum"; | |||||
| import axios from "axios"; | |||||
| import {BASE_API_URL, NEXT_PUBLIC_API_URL} from "@/config/api"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import axiosInstance from "@/app/(main)/axios/axiosInstance"; | |||||
| import Qs from 'qs'; | |||||
| import EditableSearchResults from "@/components/SearchResults/EditableSearchResults"; // Make sure to import Qs | |||||
| // may need move to "index" or "actions" | |||||
| type RecordStructure = { | |||||
| id: number, | |||||
| scheduledPeriod: string, | |||||
| scheduledAt: string, | |||||
| productCount: number, | |||||
| }; | |||||
| type Props = { | |||||
| records: RecordStructure[]; | |||||
| }; | |||||
| type SearchQuery = Partial<Omit<RecordStructure, "id">>; | |||||
| type SearchParamNames = keyof SearchQuery; | |||||
| const DSOverview: React.FC<Props> = ({ records }) => { | |||||
| const [filteredItems, setFilteredItems] = useState<RecordStructure[]>(records ?? []); | |||||
| const { t } = useTranslation("items"); | |||||
| const router = useRouter(); | |||||
| const [filterObj, setFilterObj] = useState({}); | |||||
| const [tempSelectedValue, setTempSelectedValue] = useState({}); | |||||
| const [pagingController, setPagingController] = useState({ | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }) | |||||
| const [mode, redirPath] = useMemo(() => { | |||||
| // var typeId = TypeEnum.CONSUMABLE_ID | |||||
| let title = ""; | |||||
| const mode = "Search"; | |||||
| let redirPath = ""; | |||||
| title = "Product"; | |||||
| redirPath = "/scheduling/detail"; | |||||
| return [mode, redirPath]; | |||||
| }, []); | |||||
| const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | |||||
| () => | |||||
| [ | |||||
| { label: t("Schedule Period"), paramName: "scheduledPeriod", type: "dateRange" }, | |||||
| { label: t("Scheduled At"), paramName: "scheduledAt", type: "dateRange" }, | |||||
| { label: t("Product Count"), paramName: "productCount", type: "text" }, | |||||
| ] | |||||
| , | |||||
| [t, records] | |||||
| ); | |||||
| // const onDetailClick = useCallback( | |||||
| // (item: ItemsResult) => { | |||||
| // router.push(`/settings/items/edit?id=${item.id}`); | |||||
| // }, | |||||
| // [router] | |||||
| // ); | |||||
| const onDeleteClick = useCallback( | |||||
| (item: ItemsResult) => {}, | |||||
| [router] | |||||
| ); | |||||
| const onDetailClick = (record: any) => { | |||||
| console.log("[debug] record", record); | |||||
| router.push(`/scheduling/detail/edit?id=${record.id}`); | |||||
| } | |||||
| const columns = useMemo<Column<RecordStructure>[]>( | |||||
| () => [ | |||||
| { | |||||
| name: "id", | |||||
| label: t("Details"), | |||||
| onClick: (record)=>onDetailClick(record), | |||||
| buttonIcon: <EditNote />, | |||||
| }, | |||||
| { | |||||
| name: "scheduledPeriod", | |||||
| label: "Demand Forecast Period", | |||||
| }, | |||||
| { | |||||
| name: "scheduledAt", | |||||
| label: t("Scheduled At"), | |||||
| }, | |||||
| { | |||||
| name: "productCount", | |||||
| label: t("Product Count(s)"), | |||||
| }, | |||||
| // { | |||||
| // name: "action", | |||||
| // label: t(""), | |||||
| // buttonIcon: <GridDeleteIcon />, | |||||
| // onClick: onDeleteClick, | |||||
| // }, | |||||
| ], | |||||
| [filteredItems] | |||||
| ); | |||||
| useEffect(() => { | |||||
| refetchData(filterObj); | |||||
| }, [filterObj, pagingController.pageNum, pagingController.pageSize]); | |||||
| const refetchData = async (filterObj: SearchQuery | null) => { | |||||
| const authHeader = axiosInstance.defaults.headers['Authorization']; | |||||
| if (!authHeader) { | |||||
| return; // Exit the function if the token is not set | |||||
| } | |||||
| const params ={ | |||||
| pageNum: pagingController.pageNum, | |||||
| pageSize: pagingController.pageSize, | |||||
| ...filterObj, | |||||
| ...tempSelectedValue, | |||||
| } | |||||
| try { | |||||
| const response = await axiosInstance.get<ItemsResult[]>(`${NEXT_PUBLIC_API_URL}/items/getRecordByPage`, { | |||||
| params, | |||||
| paramsSerializer: (params) => { | |||||
| return Qs.stringify(params, { arrayFormat: 'repeat' }); | |||||
| }, | |||||
| }); | |||||
| //setFilteredItems(response.data.records); | |||||
| setFilteredItems([ | |||||
| { | |||||
| id: 1, | |||||
| scheduledPeriod: "2025-05-11 to 2025-05-17", | |||||
| scheduledAt: "2025-05-07", | |||||
| productCount: 13, | |||||
| }, | |||||
| { | |||||
| id: 2, | |||||
| scheduledPeriod: "2025-05-18 to 2025-05-24", | |||||
| scheduledAt: "2025-05-14", | |||||
| productCount: 15, | |||||
| }, | |||||
| { | |||||
| id: 3, | |||||
| scheduledPeriod: "2025-05-25 to 2025-05-31", | |||||
| scheduledAt: "2025-05-21", | |||||
| productCount: 13, | |||||
| }, | |||||
| ]) | |||||
| setPagingController({ | |||||
| ...pagingController, | |||||
| totalCount: response.data.total | |||||
| }) | |||||
| return response; // Return the data from the response | |||||
| } catch (error) { | |||||
| console.error('Error fetching items:', error); | |||||
| throw error; // Rethrow the error for further handling | |||||
| } | |||||
| }; | |||||
| const onReset = useCallback(() => { | |||||
| //setFilteredItems(items ?? []); | |||||
| setFilterObj({}); | |||||
| setTempSelectedValue({}); | |||||
| refetchData(null); | |||||
| }, [records]); | |||||
| return ( | |||||
| <> | |||||
| <SearchBox | |||||
| criteria={searchCriteria} | |||||
| onSearch={(query) => { | |||||
| setFilterObj({ | |||||
| ...query | |||||
| }) | |||||
| }} | |||||
| onReset={onReset} | |||||
| /> | |||||
| <SearchResults<RecordStructure> | |||||
| items={filteredItems} | |||||
| columns={columns} | |||||
| setPagingController={setPagingController} | |||||
| pagingController={pagingController} | |||||
| isAutoPaging={false} | |||||
| // hasCollapse={false} | |||||
| /> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| export default DSOverview; | |||||
| @@ -0,0 +1,16 @@ | |||||
| import React from "react"; | |||||
| import {DetailScheduleLoading} from "./DetailScheduleLoading"; | |||||
| import DSOverview from "./DetailScheduleSearchView"; | |||||
| interface SubComponents { | |||||
| Loading: typeof DetailScheduleLoading; | |||||
| } | |||||
| const DetailScheduleWrapper: React.FC & SubComponents = async () => { | |||||
| return <DSOverview records={[]} />; | |||||
| }; | |||||
| DetailScheduleWrapper.Loading = DetailScheduleLoading; | |||||
| export default DetailScheduleWrapper; | |||||
| @@ -0,0 +1 @@ | |||||
| export { default } from "./DetailScheduleWrapper"; | |||||
| @@ -0,0 +1,112 @@ | |||||
| "use client"; | |||||
| import { | |||||
| Box, | |||||
| Card, | |||||
| CardContent, | |||||
| Grid, | |||||
| Stack, | |||||
| TextField, | |||||
| Typography, | |||||
| } from "@mui/material"; | |||||
| import { Controller, useFormContext } from "react-hook-form"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import InputDataGrid from "../InputDataGrid"; | |||||
| import { useCallback, useEffect, useMemo, useState } from "react"; | |||||
| import { GridColDef, GridRowModel } from "@mui/x-data-grid"; | |||||
| import { InputDataGridProps, TableRow } from "../InputDataGrid/InputDataGrid"; | |||||
| import { TypeEnum } from "@/app/utils/typeEnum"; | |||||
| import { CreateItemInputs } from "@/app/api/settings/item/actions"; | |||||
| import { NumberInputProps } from "@/components/CreateItem/NumberInputProps"; | |||||
| import { integerFormatter } from "@/app/utils/formatUtil"; | |||||
| import { SaveDetailSchedule } from "./DetailScheudleDetailView"; | |||||
| // temp interface input | |||||
| type Props = { | |||||
| recordDetails: SaveDetailSchedule; | |||||
| isEditing: boolean; | |||||
| }; | |||||
| const DetailInfoCard: React.FC<Props> = ({ recordDetails, isEditing }) => { | |||||
| const { | |||||
| t, | |||||
| i18n: { language }, | |||||
| } = useTranslation(); | |||||
| const { | |||||
| control, | |||||
| register, | |||||
| formState: { errors, defaultValues, touchedFields }, | |||||
| } = useFormContext<SaveDetailSchedule>(); | |||||
| const [details, setDetails] = useState<SaveDetailSchedule|null>(null); | |||||
| useEffect(() => { | |||||
| console.log("[debug] record details", recordDetails) | |||||
| setDetails(recordDetails); | |||||
| }, [recordDetails]) | |||||
| useEffect(() => { | |||||
| console.log("[debug] isEdit", isEditing) | |||||
| }, [isEditing]) | |||||
| return ( | |||||
| <Card sx={{ display: "block" }}> | |||||
| <CardContent component={Stack} spacing={4}> | |||||
| <Box> | |||||
| {/* <Typography variant="overline" display="block" marginBlockEnd={1}> | |||||
| {t("Schedule Detail")} | |||||
| </Typography> */} | |||||
| <Grid container spacing={2} columns={{ xs: 6, sm: 12 }}> | |||||
| <Grid item xs={6}> | |||||
| <TextField | |||||
| label={t("Production Date")} | |||||
| fullWidth | |||||
| {...register("productionDate", { | |||||
| required: "name required!", | |||||
| })} | |||||
| // defaultValue={details?.scheduledPeriod} | |||||
| disabled={!isEditing} | |||||
| // error={Boolean(errors.name)} | |||||
| // helperText={errors.name?.message} | |||||
| /> | |||||
| </Grid> | |||||
| <Grid item xs={6}> | |||||
| <TextField | |||||
| label={t("Total Job Orders")} | |||||
| fullWidth | |||||
| {...register("totalJobOrders", { | |||||
| required: "code required!", | |||||
| })} | |||||
| // defaultValue={details?.productCount} | |||||
| disabled={!isEditing} | |||||
| // error={Boolean(errors.code)} | |||||
| // helperText={errors.code?.message} | |||||
| /> | |||||
| </Grid> | |||||
| <Grid item xs={6}> | |||||
| <Controller | |||||
| name="totalProductionQty" | |||||
| control={control} | |||||
| render={({ field }) => ( | |||||
| <TextField | |||||
| {...field} | |||||
| label={t("Total Production Qty")} | |||||
| fullWidth | |||||
| disabled={!isEditing} | |||||
| value={typeof (field.value) == "number" ? integerFormatter.format(field.value) : field.value} | |||||
| // defaultValue={typeof (details?.productionCount) == "number" ? integerFormatter.format(details?.productionCount) : details?.productionCount} | |||||
| // error={Boolean(errors.type)} | |||||
| // helperText={errors.type?.message} | |||||
| required | |||||
| /> | |||||
| )} | |||||
| /> | |||||
| </Grid> | |||||
| </Grid> | |||||
| </Box> | |||||
| </CardContent> | |||||
| </Card> | |||||
| ); | |||||
| }; | |||||
| export default DetailInfoCard; | |||||
| @@ -0,0 +1,38 @@ | |||||
| import { CreateItemInputs } from "@/app/api/settings/item/actions"; | |||||
| import { fetchItem } from "@/app/api/settings/item"; | |||||
| import GeneralLoading from "@/components/General/GeneralLoading"; | |||||
| import DetailScheduleDetailView from "@/components/DetailScheduleDetail/DetailScheudleDetailView"; | |||||
| interface SubComponents { | |||||
| Loading: typeof GeneralLoading; | |||||
| } | |||||
| type EditDetailScheduleDetailProps = { | |||||
| id?: string | number | |||||
| } | |||||
| type Props = EditDetailScheduleDetailProps | |||||
| const DetailScheduleDetailWrapper: React.FC<Props> & SubComponents = async ({ | |||||
| id | |||||
| }) => { | |||||
| const defaultValues = { | |||||
| id: 1, | |||||
| productionDate: "2025-05-07", | |||||
| totalJobOrders: 13, | |||||
| totalProductionQty: 21000, | |||||
| } | |||||
| return ( | |||||
| <DetailScheduleDetailView | |||||
| isEditMode={Boolean(id)} | |||||
| defaultValues={defaultValues} | |||||
| // qcChecks={qcChecks || []} | |||||
| /> | |||||
| ); | |||||
| }; | |||||
| DetailScheduleDetailWrapper.Loading = GeneralLoading; | |||||
| export default DetailScheduleDetailWrapper; | |||||
| @@ -0,0 +1,216 @@ | |||||
| "use client"; | |||||
| import { useCallback, useEffect, useMemo, useState } from "react"; | |||||
| import { useRouter, useSearchParams } from "next/navigation"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import { | |||||
| SaveDetailSchedule, | |||||
| saveItem, | |||||
| } from "@/app/api/settings/item/actions"; | |||||
| import { | |||||
| FormProvider, | |||||
| SubmitErrorHandler, | |||||
| SubmitHandler, | |||||
| useForm, | |||||
| } from "react-hook-form"; | |||||
| import { deleteDialog } from "../Swal/CustomAlerts"; | |||||
| import { Box, Button, Grid, Link, Stack, Tab, Tabs, TabsProps, Typography } from "@mui/material"; | |||||
| import { Add, Check, Close, EditNote } from "@mui/icons-material"; | |||||
| import { ItemQc, ItemsResult } from "@/app/api/settings/item"; | |||||
| import { useGridApiRef } from "@mui/x-data-grid"; | |||||
| import ProductDetails from "@/components/CreateItem/ProductDetails"; | |||||
| import DetailInfoCard from "@/components/DetailScheduleDetail/DetailInfoCard"; | |||||
| import ViewByFGDetails, { FGRecord } from "@/components/DetailScheduleDetail/ViewByFGDetails"; | |||||
| import ViewByBomDetails from "@/components/DetailScheduleDetail/ViewByBomDetails"; | |||||
| import EditableSearchResults, { Column } from "@/components/SearchResults/EditableSearchResults"; | |||||
| // temp interface input | |||||
| export interface SaveDetailSchedule { | |||||
| id: number, | |||||
| productionDate: string, | |||||
| totalJobOrders: number, | |||||
| totalProductionQty: number | |||||
| } | |||||
| type Props = { | |||||
| isEditMode: boolean; | |||||
| // type: TypeEnum; | |||||
| defaultValues: Partial<SaveDetailSchedule> | undefined; | |||||
| qcChecks: ItemQc[] | |||||
| }; | |||||
| const DetailScheduleDetailView: React.FC<Props> = ({ | |||||
| isEditMode, | |||||
| // type, | |||||
| defaultValues, | |||||
| // qcChecks | |||||
| }) => { | |||||
| // console.log(type) | |||||
| const apiRef = useGridApiRef(); | |||||
| const params = useSearchParams() | |||||
| console.log(params.get("id")) | |||||
| const [serverError, setServerError] = useState(""); | |||||
| const [tabIndex, setTabIndex] = useState(0); | |||||
| const { t } = useTranslation("schedule") | |||||
| const router = useRouter(); | |||||
| const [isEdit, setIsEdit] = useState(false); | |||||
| //const title = "Demand Forecast Detail" | |||||
| const [mode, redirPath] = useMemo(() => { | |||||
| // var typeId = TypeEnum.CONSUMABLE_ID | |||||
| let title = ""; | |||||
| let mode = ""; | |||||
| let redirPath = ""; | |||||
| // if (type === TypeEnum.MATERIAL) { | |||||
| // typeId = TypeEnum.MATERIAL_ID | |||||
| // title = "Material"; | |||||
| // redirPath = "/settings/material"; | |||||
| // } | |||||
| // if (type === TypeEnum.PRODUCT) { | |||||
| // typeId = TypeEnum.PRODUCT_ID | |||||
| title = "Product"; | |||||
| redirPath = "scheduling/detail/edit"; | |||||
| // } | |||||
| // if (type === TypeEnum.BYPRODUCT) { | |||||
| // typeId = TypeEnum.BYPRODUCT_ID | |||||
| // title = "By-Product"; | |||||
| // redirPath = "/settings/byProduct"; | |||||
| // } | |||||
| if (isEditMode) { | |||||
| mode = "Edit"; | |||||
| } else { | |||||
| mode = "Create"; | |||||
| } | |||||
| return [mode, redirPath]; | |||||
| }, [isEditMode]); | |||||
| // console.log(typeId) | |||||
| const formProps = useForm<SaveDetailSchedule>({ | |||||
| defaultValues: defaultValues ? defaultValues : { | |||||
| id: 1, | |||||
| productionDate: "2025-05-07", | |||||
| totalJobOrders: 13, | |||||
| totalProductionQty: 21000, | |||||
| }, | |||||
| }); | |||||
| const errors = formProps.formState.errors; | |||||
| const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>( | |||||
| (_e, newValue) => { | |||||
| setTabIndex(newValue); | |||||
| }, | |||||
| [], | |||||
| ); | |||||
| const [pagingController, setPagingController] = useState({ | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }) | |||||
| const handleCancel = () => { | |||||
| router.replace(`/scheduling/Detail`); | |||||
| }; | |||||
| const onSubmit = useCallback<SubmitHandler<SaveDetailSchedule>>( | |||||
| async (data, event) => { | |||||
| const hasErrors = false; | |||||
| console.log(errors) | |||||
| // console.log(apiRef.current.getCellValue(2, "lowerLimit")) | |||||
| // apiRef.current. | |||||
| try { | |||||
| if (hasErrors) { | |||||
| setServerError(t("An error has occurred. Please try again later.")); | |||||
| return false; | |||||
| } | |||||
| } catch (e) { | |||||
| // backend error | |||||
| setServerError(t("An error has occurred. Please try again later.")); | |||||
| console.log(e); | |||||
| } | |||||
| }, | |||||
| [apiRef, router, t] | |||||
| ); | |||||
| // multiple tabs | |||||
| const onSubmitError = useCallback<SubmitErrorHandler<SaveDetailSchedule>>( | |||||
| (errors) => { }, | |||||
| [] | |||||
| ); | |||||
| const onClickEdit = () => { | |||||
| setIsEdit(!isEdit) | |||||
| } | |||||
| return ( | |||||
| <> | |||||
| <FormProvider {...formProps}> | |||||
| <Stack | |||||
| spacing={2} | |||||
| component="form" | |||||
| onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)} | |||||
| > | |||||
| {/*<Grid>*/} | |||||
| {/* <Typography mb={2} variant="h4">*/} | |||||
| {/* {t(`${mode} ${title}`)}*/} | |||||
| {/* </Typography>*/} | |||||
| {/*</Grid>*/} | |||||
| <DetailInfoCard | |||||
| recordDetails={formProps.formState.defaultValues} | |||||
| isEditing={isEdit} | |||||
| /> | |||||
| <Stack | |||||
| direction="row" | |||||
| justifyContent="space-between" | |||||
| flexWrap="wrap" | |||||
| rowGap={2} | |||||
| > | |||||
| <Button | |||||
| variant="contained" | |||||
| onClick={onClickEdit} | |||||
| // startIcon={<Add />} | |||||
| //LinkComponent={Link} | |||||
| //href="qcCategory/create" | |||||
| > | |||||
| {isEdit ? t("Save") : t("Edit")} | |||||
| </Button> | |||||
| </Stack> | |||||
| {/* <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | |||||
| <Tab label={t("View By FG") + (tabIndex === 0 ? " (Selected)" : "")} iconPosition="end" /> | |||||
| <Tab label={t("View By Material") + (tabIndex === 1 ? " (Selected)" : "")} iconPosition="end" /> | |||||
| </Tabs> */} | |||||
| {serverError && ( | |||||
| <Typography variant="body2" color="error" alignSelf="flex-end"> | |||||
| {serverError} | |||||
| </Typography> | |||||
| )} | |||||
| {/* {tabIndex === 0 && <ViewByFGDetails isEdit={isEdit} apiRef={apiRef} />} */} | |||||
| <ViewByFGDetails isEdit={isEdit} apiRef={apiRef} /> | |||||
| {/* {tabIndex === 1 && <ViewByBomDetails isEdit={isEdit} apiRef={apiRef} isHideButton={true} />} */} | |||||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | |||||
| <Button | |||||
| name="submit" | |||||
| variant="contained" | |||||
| startIcon={<Check />} | |||||
| type="submit" | |||||
| // disabled={submitDisabled} | |||||
| > | |||||
| {isEditMode ? t("Save") : t("Confirm")} | |||||
| </Button> | |||||
| <Button | |||||
| variant="outlined" | |||||
| startIcon={<Close />} | |||||
| onClick={handleCancel} | |||||
| > | |||||
| {t("Cancel")} | |||||
| </Button> | |||||
| </Stack> | |||||
| </Stack> | |||||
| </FormProvider> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| export default DetailScheduleDetailView; | |||||
| @@ -0,0 +1,556 @@ | |||||
| "use client"; | |||||
| import { CreateItemInputs } from "@/app/api/settings/item/actions"; | |||||
| import { | |||||
| GridColDef, | |||||
| GridRowModel, | |||||
| GridRenderEditCellParams, | |||||
| GridEditInputCell, | |||||
| GridRowSelectionModel, | |||||
| useGridApiRef, | |||||
| } from "@mui/x-data-grid"; | |||||
| import {MutableRefObject, useCallback, useEffect, useMemo, useState} from "react"; | |||||
| import { useFormContext } from "react-hook-form"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import InputDataGrid, { TableRow } from "../InputDataGrid/InputDataGrid"; | |||||
| import {Box, Grid, Tooltip, Typography} from "@mui/material"; | |||||
| import { ItemQc } from "@/app/api/settings/item"; | |||||
| import { QcChecksInputs } from "@/app/api/settings/qcCheck/actions"; | |||||
| import { GridApiCommunity } from "@mui/x-data-grid/internals"; | |||||
| import { RiceBowl } from "@mui/icons-material"; | |||||
| import EditableSearchResults, {Column} from "@/components/SearchResults/EditableSearchResults"; | |||||
| import { decimalFormatter } from "@/app/utils/formatUtil"; | |||||
| import { GridRenderCellParams } from "@mui/x-data-grid"; | |||||
| type Props = { | |||||
| apiRef: MutableRefObject<GridApiCommunity> | |||||
| }; | |||||
| type EntryError = | |||||
| | { | |||||
| [field in keyof QcChecksInputs]?: string; | |||||
| } | |||||
| | undefined; | |||||
| export type FGRecord = { | |||||
| id: string | number | |||||
| code: string; | |||||
| name: string; | |||||
| inStockQty: number; | |||||
| purchaseQty: number; | |||||
| } | |||||
| export type FGOverallRecord = { | |||||
| id: string | number | |||||
| code: string; | |||||
| name: string; | |||||
| type: string; | |||||
| inStockQty: number; | |||||
| purchaseQty: number; | |||||
| purchaseQty1: number; | |||||
| purchaseQty2: number; | |||||
| purchaseQty3: number; | |||||
| purchaseQty4: number; | |||||
| purchaseQty5: number; | |||||
| purchaseQty6: number; | |||||
| purchaseQty7: number; | |||||
| overallPurchaseQty: number; | |||||
| } | |||||
| const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| const { | |||||
| t, | |||||
| i18n: { language }, | |||||
| } = useTranslation("schedule"); | |||||
| const { | |||||
| formState: { errors, defaultValues, touchedFields }, | |||||
| } = useFormContext<CreateItemInputs>(); | |||||
| // const apiRef = useGridApiRef(); | |||||
| const dayPeriod = [ | |||||
| '2025-05-11', | |||||
| '2025-05-12', | |||||
| '2025-05-13', | |||||
| '2025-05-14', | |||||
| '2025-05-15', | |||||
| '2025-05-16', | |||||
| '2025-05-17', | |||||
| ]; | |||||
| const fakeRecords = useMemo<FGRecord[][]>( | |||||
| () => [ | |||||
| [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, | |||||
| { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, | |||||
| { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, | |||||
| { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, | |||||
| { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| ], | |||||
| [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, | |||||
| { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, | |||||
| { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, | |||||
| { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, | |||||
| { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| ], | |||||
| [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, | |||||
| { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, | |||||
| { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, | |||||
| { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, | |||||
| { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| ], | |||||
| [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, | |||||
| { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, | |||||
| { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, | |||||
| { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, | |||||
| { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| ], | |||||
| [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, | |||||
| { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, | |||||
| { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, | |||||
| { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, | |||||
| { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| ], | |||||
| [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, | |||||
| { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, | |||||
| { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, | |||||
| { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, | |||||
| { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| ], | |||||
| [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , purchaseQty: 972.12 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , purchaseQty: 3175.2 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , purchaseQty: 90 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , purchaseQty: 60.4 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , purchaseQty: 66.45 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , purchaseQty: 78.55 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, | |||||
| { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, | |||||
| { id: 12, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, | |||||
| { id: 13, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, | |||||
| { id: 14, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 15, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| { id: 16, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| ], | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| const fakeOverallRecords = useMemo<FGOverallRecord[]>( | |||||
| () => [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44 , | |||||
| purchaseQty1: 972.12, purchaseQty2: 972.12, purchaseQty3: 972.12, | |||||
| purchaseQty4: 972.12, purchaseQty5: 972.12, purchaseQty6: 972.12, | |||||
| purchaseQty7: 972.12, overallPurchaseQty: 6804.84 | |||||
| }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52 , | |||||
| purchaseQty1: 3175.2, purchaseQty2: 3175.2, purchaseQty3: 3175.2, | |||||
| purchaseQty4: 3175.2, purchaseQty5: 3175.2, purchaseQty6: 3175.2, | |||||
| purchaseQty7: 3175.2, overallPurchaseQty: 22226.4 | |||||
| }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00 , | |||||
| purchaseQty1: 90, purchaseQty2: 90, purchaseQty3: 90, | |||||
| purchaseQty4: 90, purchaseQty5: 90, purchaseQty6: 90, | |||||
| purchaseQty7: 90, overallPurchaseQty: 630 | |||||
| }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04 , | |||||
| purchaseQty1: 60.4, purchaseQty2: 60.4, purchaseQty3: 60.4, | |||||
| purchaseQty4: 60.4, purchaseQty5: 60.4, purchaseQty6: 60.4, | |||||
| purchaseQty7: 60.4, overallPurchaseQty: 422.8 | |||||
| }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04 , | |||||
| purchaseQty1: 66.45, purchaseQty2: 66.45, purchaseQty3: 66.45, | |||||
| purchaseQty4: 66.45, purchaseQty5: 66.45, purchaseQty6: 66.45, | |||||
| purchaseQty7: 66.45, overallPurchaseQty: 465.15 | |||||
| }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04 , | |||||
| purchaseQty1: 78.55, purchaseQty2: 78.55, purchaseQty3: 78.55, | |||||
| purchaseQty4: 78.55, purchaseQty5: 78.55, purchaseQty6: 78.55, | |||||
| purchaseQty7: 78.55, overallPurchaseQty: 549.85 | |||||
| }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98 , purchaseQty: 2419.8 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00 , purchaseQty: 0 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42 , purchaseQty: 774.2 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00 , purchaseQty: 0 }, | |||||
| { id: 11, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00 , purchaseQty: 6000 }, | |||||
| { id: 12, code: "MH0040",type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 972.12 }, | |||||
| { id: 13, code: "FA0161",type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 28.15 }, | |||||
| { id: 14, code: "MG1288", type: "Material",name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 15, code: "MG0066", type: "Material",name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| { id: 16, code: "MH0040", type: "Material",name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| const [pagingController, setPagingController] = useState([ | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| ]) | |||||
| const updatePagingController = (updatedObj) => { | |||||
| setPagingController((prevState) => { | |||||
| return prevState.map((item, index) => { | |||||
| if (index === updatedObj?.index){ | |||||
| return { | |||||
| ...item, | |||||
| pageNum: item.pageNum, | |||||
| pageSize: item.pageSize, | |||||
| totalCount: item.totalCount, | |||||
| }; | |||||
| } | |||||
| else | |||||
| return item | |||||
| }); | |||||
| }); | |||||
| }; | |||||
| const overallColumns = useMemo<Column<any>[]>( | |||||
| () => [ | |||||
| { | |||||
| field: "code", | |||||
| label: "code", | |||||
| type: 'read-only', | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "name", | |||||
| label: t("name"), | |||||
| type: 'read-only', | |||||
| }, | |||||
| { | |||||
| field: "type", | |||||
| label: "type", | |||||
| type: 'read-only', | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "inStockQty", | |||||
| label: t("Available Qty"), | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.inStockQty) == "number") { | |||||
| return decimalFormatter.format(row.inStockQty) | |||||
| } | |||||
| return row.inStockQty | |||||
| } | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "overallPurchaseQty", | |||||
| label: t("Total Demand Qty"), | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.overallPurchaseQty) == "number") { | |||||
| return decimalFormatter.format(row.overallPurchaseQty) | |||||
| } | |||||
| return row.overallPurchaseQty | |||||
| } | |||||
| }, | |||||
| { | |||||
| field: "purchaseQty1", | |||||
| label: t("Demand Qty (Day1)"), | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty1) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty1) | |||||
| } | |||||
| return row.purchaseQty1 | |||||
| } | |||||
| }, | |||||
| { | |||||
| field: "purchaseQty2", | |||||
| label: t("Demand Qty (Day2)"), | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty2) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty2) | |||||
| } | |||||
| return row.purchaseQty2 | |||||
| } | |||||
| }, | |||||
| { | |||||
| field: "purchaseQty3", | |||||
| label: t("Demand Qty (Day3)"), | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty3) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty3) | |||||
| } | |||||
| return row.purchaseQty3 | |||||
| } | |||||
| }, | |||||
| { | |||||
| field: "purchaseQty4", | |||||
| label: t("Demand Qty (Day4)"), | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty4) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty4) | |||||
| } | |||||
| return row.purchaseQty4 | |||||
| } | |||||
| },{ | |||||
| field: "purchaseQty5", | |||||
| label: t("Demand Qty (Day5)"), | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty5) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty5) | |||||
| } | |||||
| return row.purchaseQty5 | |||||
| } | |||||
| }, | |||||
| { | |||||
| field: "purchaseQty6", | |||||
| label: t("Demand Qty (Day6)"), | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty6) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty6) | |||||
| } | |||||
| return row.purchaseQty6 | |||||
| } | |||||
| }, | |||||
| { | |||||
| field: "purchaseQty7", | |||||
| label: t("Demand Qty (Day7)"), | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty7) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty7) | |||||
| } | |||||
| return row.purchaseQty7 | |||||
| } | |||||
| }, | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| const columns = useMemo<Column<any>[]>( | |||||
| () => [ | |||||
| { | |||||
| field: "code", | |||||
| label: "code", | |||||
| type: 'read-only', | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "name", | |||||
| label: "name", | |||||
| type: 'read-only', | |||||
| }, | |||||
| { | |||||
| field: "type", | |||||
| label: "type", | |||||
| type: 'read-only', | |||||
| }, | |||||
| { | |||||
| field: "inStockQty", | |||||
| label: "Available Qty", | |||||
| type: 'read-only', | |||||
| // editable: true, | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof(row.inStockQty) == "number") { | |||||
| return decimalFormatter.format(row.inStockQty) | |||||
| } | |||||
| return row.inStockQty | |||||
| } | |||||
| }, | |||||
| { | |||||
| field: "purchaseQty", | |||||
| label: "Demand Qty", | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof(row.purchaseQty) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty) | |||||
| } | |||||
| return row.purchaseQty | |||||
| } | |||||
| }, | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| return ( | |||||
| <Grid container spacing={2}> | |||||
| <Grid item xs={12} key={"all"}> | |||||
| <Typography variant="overline" display="block" marginBlockEnd={1}> | |||||
| {t("Material Demand List (7 Days)")} | |||||
| </Typography> | |||||
| <EditableSearchResults<FGRecord> | |||||
| index={7} | |||||
| items={fakeOverallRecords} | |||||
| isMockUp={true} | |||||
| columns={overallColumns} | |||||
| setPagingController={updatePagingController} | |||||
| pagingController={pagingController[7]} | |||||
| isAutoPaging={true} | |||||
| isEditable={false} | |||||
| isEdit={false} | |||||
| /> | |||||
| </Grid> | |||||
| {dayPeriod.map((date, index) => ( | |||||
| <Grid item xs={12} key={index}> | |||||
| <Typography variant="overline" display="block" marginBlockEnd={1}> | |||||
| {`${t("Material Demand Date")}: ${date}`} | |||||
| </Typography> | |||||
| <EditableSearchResults<FGRecord> | |||||
| index={index} | |||||
| items={fakeRecords[index]} // Use the corresponding records for the day | |||||
| columns={columns} | |||||
| setPagingController={updatePagingController} | |||||
| pagingController={pagingController[index]} | |||||
| isAutoPaging={true} | |||||
| isEditable={false} | |||||
| isEdit={isEdit} | |||||
| /> | |||||
| </Grid> | |||||
| ))} | |||||
| </Grid> | |||||
| ); | |||||
| }; | |||||
| export default ViewByBomDetails; | |||||
| @@ -0,0 +1,709 @@ | |||||
| "use client"; | |||||
| import { CreateItemInputs } from "@/app/api/settings/item/actions"; | |||||
| import { | |||||
| GridColDef, | |||||
| GridRowModel, | |||||
| GridRenderEditCellParams, | |||||
| GridEditInputCell, | |||||
| GridRowSelectionModel, | |||||
| useGridApiRef, | |||||
| } from "@mui/x-data-grid"; | |||||
| import { MutableRefObject, useCallback, useMemo, useState } from "react"; | |||||
| import { useFormContext } from "react-hook-form"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import InputDataGrid, { TableRow } from "../InputDataGrid/InputDataGrid"; | |||||
| import { Box, Grid, Tooltip, Typography } from "@mui/material"; | |||||
| import { ItemQc } from "@/app/api/settings/item"; | |||||
| import { QcChecksInputs } from "@/app/api/settings/qcCheck/actions"; | |||||
| import { GridApiCommunity } from "@mui/x-data-grid/internals"; | |||||
| import { RiceBowl } from "@mui/icons-material"; | |||||
| import EditableSearchResults, { Column } from "@/components/SearchResults/EditableSearchResults"; | |||||
| import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; | |||||
| type Props = { | |||||
| apiRef: MutableRefObject<GridApiCommunity> | |||||
| isEdit: Boolean | |||||
| }; | |||||
| type EntryError = | |||||
| | { | |||||
| [field in keyof QcChecksInputs]?: string; | |||||
| } | |||||
| | undefined; | |||||
| export type FGRecord = { | |||||
| id: string | number | |||||
| code: string; | |||||
| name: string; | |||||
| inStockQty: number; | |||||
| productionQty?: number; | |||||
| purchaseQty?: number | |||||
| } | |||||
| const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| const { | |||||
| t, | |||||
| i18n: { language }, | |||||
| } = useTranslation(); | |||||
| const { | |||||
| formState: { errors, defaultValues, touchedFields }, | |||||
| } = useFormContext<CreateItemInputs>(); | |||||
| // const apiRef = useGridApiRef(); | |||||
| const dayPeriod = [ | |||||
| '2025-05-07', | |||||
| // '2025-05-12', | |||||
| // '2025-05-13', | |||||
| // '2025-05-14', | |||||
| // '2025-05-15', | |||||
| // '2025-05-16', | |||||
| // '2025-05-17', | |||||
| ]; | |||||
| const fakeRecordLine = useMemo<FGRecord[][]>( | |||||
| () => [ | |||||
| [ | |||||
| { id: 1, code: "mt1", name: "material 1", inStockQty: 10, purchaseQty: 1 }, | |||||
| { id: 2, code: "mt2", name: "material 2", inStockQty: 20, purchaseQty: 199 }, | |||||
| ], | |||||
| [ | |||||
| { id: 3, code: "mt3", name: "material 3", inStockQty: 30, purchaseQty: 3 }, | |||||
| { id: 4, code: "mt4", name: "material 4", inStockQty: 40, purchaseQty: 499 }, | |||||
| ], | |||||
| [ | |||||
| { id: 5, code: "mt5", name: "material 5", inStockQty: 50, purchaseQty: 5 }, | |||||
| { id: 6, code: "mt6", name: "material 6", inStockQty: 60, purchaseQty: 699 }, | |||||
| ], | |||||
| [ | |||||
| { id: 7, code: "mt7", name: "material 7", inStockQty: 70, purchaseQty: 7 }, | |||||
| { id: 8, code: "mt8", name: "material 8", inStockQty: 80, purchaseQty: 899 }, | |||||
| ], | |||||
| [ | |||||
| { id: 9, code: "mt9", name: "material 9", inStockQty: 90, purchaseQty: 9 }, | |||||
| { id: 10, code: "mt10", name: "material 10", inStockQty: 100, purchaseQty: 999 }, | |||||
| ], | |||||
| [ | |||||
| { id: 11, code: "mt11", name: "material 11", inStockQty: 110, purchaseQty: 11 }, | |||||
| { id: 12, code: "mt12", name: "material 12", inStockQty: 120, purchaseQty: 1299 }, | |||||
| ], | |||||
| [ | |||||
| { id: 13, code: "mt13", name: "material 13", inStockQty: 130, purchaseQty: 13 }, | |||||
| { id: 14, code: "mt14", name: "material 14", inStockQty: 140, purchaseQty: 1499 }, | |||||
| ], | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| const fakeRecords = useMemo<FGRecord[][]>( | |||||
| () => [ | |||||
| [ | |||||
| { | |||||
| id: 1, jobNo: "JO20250507001", priority: 85, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 100, purchaseQty: 20 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 80, purchaseQty: 10 } | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 2, jobNo: "JO20250507002", priority: 80, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 1000, purchaseQty: 190.00 }, | |||||
| { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 1000, purchaseQty: 250.00 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 3, jobNo: "JO20250507003", priority: 35, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, | |||||
| { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 4, jobNo: "JO20250507004", priority: 20, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| ] | |||||
| }, | |||||
| ], | |||||
| [ | |||||
| { | |||||
| id: 1, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, | |||||
| { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 2, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 3, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 4, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, | |||||
| { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, | |||||
| ] | |||||
| }, | |||||
| ], | |||||
| [ | |||||
| { | |||||
| id: 1, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, | |||||
| { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 2, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 3, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 4, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, | |||||
| { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, | |||||
| ] | |||||
| }, | |||||
| ], | |||||
| [ | |||||
| { | |||||
| id: 1, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, | |||||
| { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 2, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 3, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 4, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, | |||||
| { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, | |||||
| ] | |||||
| }, | |||||
| ], | |||||
| [ | |||||
| { | |||||
| id: 1, code: "PP1080", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, | |||||
| { id: 2, code: "GI3236", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, | |||||
| { id: 3, code: "MG1700", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, | |||||
| { id: 4, code: "FA0533", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, | |||||
| { id: 5, code: "FA0210", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 6, code: "FA0608", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 7, code: "FA0056", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, | |||||
| { id: 8, code: "PP1188", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, | |||||
| { id: 9, code: "PP8001", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, | |||||
| { id: 10, code: "PP1096", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, | |||||
| { id: 10, code: "NA0476", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.00 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 2, code: "PP1193", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, | |||||
| { id: 2, code: "FA0161", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 3, code: " PP1188", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, | |||||
| { id: 2, code: "FA0161", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 3, code: "FA0608", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 4, code: "MG1288", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 5, code: "FA0210", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 6, code: "MG0066", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 4, code: " PP1096", name: "白麵撈", inStockQty: 1040, productionQty: 520, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, | |||||
| { id: 1, code: "MH0040", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| { id: 2, code: "FA0161", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, | |||||
| ] | |||||
| }, | |||||
| ], | |||||
| [ | |||||
| { | |||||
| id: 1, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, | |||||
| { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 2, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 3, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 4, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, | |||||
| { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, | |||||
| ] | |||||
| }, | |||||
| ], | |||||
| [ | |||||
| { | |||||
| id: 1, code: "PP1080", type: "FG", name: "咖哩汁", inStockQty: 2400, productionQty: 1200.0, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 108.88 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 635.04 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 18.00 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 12.08 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 12.08 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 483.96 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 72.00 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 154.84 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 120.00 }, | |||||
| { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 200.0 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 2, code: "PP1193", type: "FG", name: "蔥油(1磅) ", inStockQty: 1322, productionQty: 661, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 } | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 3, code: " PP1188", type: "FG", name: "咖喱膽", inStockQty: 1016.2, productionQty: 508.1, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 }, | |||||
| { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 }, | |||||
| { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 4, code: " PP1096", type: "FG", name: "白麵撈", inStockQty: 1040, productionQty: 520, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 }, | |||||
| { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, | |||||
| ] | |||||
| }, | |||||
| ], | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| const [pagingController, setPagingController] = useState([ | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| { | |||||
| pageNum: 1, | |||||
| pageSize: 10, | |||||
| totalCount: 0, | |||||
| }, | |||||
| ]) | |||||
| const updatePagingController = (updatedObj) => { | |||||
| setPagingController((prevState) => { | |||||
| return prevState.map((item, index) => { | |||||
| if (index === updatedObj?.index) { | |||||
| return { | |||||
| ...item, | |||||
| pageNum: item.pageNum, | |||||
| pageSize: item.pageSize, | |||||
| totalCount: item.totalCount, | |||||
| }; | |||||
| } | |||||
| else | |||||
| return item | |||||
| }); | |||||
| }); | |||||
| }; | |||||
| const columns = useMemo<Column<any>[]>( | |||||
| () => [ | |||||
| { | |||||
| field: "jobNo", | |||||
| label: "Job No.", | |||||
| type: 'read-only', | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "code", | |||||
| label: "code", | |||||
| type: 'read-only', | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "name", | |||||
| label: "name", | |||||
| type: 'read-only', | |||||
| }, | |||||
| { | |||||
| field: "type", | |||||
| label: "type", | |||||
| type: 'read-only', | |||||
| // editable: true, | |||||
| }, | |||||
| // { | |||||
| // field: "inStockQty", | |||||
| // label: "Available Qty", | |||||
| // type: 'read-only', | |||||
| // style: { | |||||
| // textAlign: "right", | |||||
| // }, | |||||
| // // editable: true, | |||||
| // renderCell: (row: FGRecord) => { | |||||
| // if (typeof (row.inStockQty) == "number") { | |||||
| // return decimalFormatter.format(row.inStockQty) | |||||
| // } | |||||
| // return row.inStockQty | |||||
| // } | |||||
| // }, | |||||
| { | |||||
| field: "productionQty", | |||||
| label: "Demand Qty", | |||||
| type: 'input', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof (row.productionQty) == "number") { | |||||
| return decimalFormatter.format(row.productionQty ?? 0) | |||||
| } | |||||
| return row.productionQty | |||||
| } | |||||
| }, | |||||
| { | |||||
| field: "priority", | |||||
| label: "Production Priority", | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| // editable: true, | |||||
| }, | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| const overallColumns = useMemo<Column<any>[]>( | |||||
| () => [ | |||||
| { | |||||
| field: "code", | |||||
| label: "code", | |||||
| type: 'read-only', | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "name", | |||||
| label: "name", | |||||
| type: 'read-only', | |||||
| }, | |||||
| { | |||||
| field: "type", | |||||
| label: "type", | |||||
| type: 'read-only', | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "lastMonthAvgStock", | |||||
| label: "Last Month Average Stock", | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof (row.lastMonthAvgStock) == "number") { | |||||
| return decimalFormatter.format(row.lastMonthAvgStock) | |||||
| } | |||||
| return row.lastMonthAvgStock | |||||
| } | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "safetyStock", | |||||
| label: "Safety Stock", | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof (row.safetyStock) == "number") { | |||||
| return decimalFormatter.format(row.safetyStock) | |||||
| } | |||||
| return row.safetyStock | |||||
| } | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "inStockQty", | |||||
| label: "Available Qty", | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof (row.inStockQty) == "number") { | |||||
| return decimalFormatter.format(row.inStockQty) | |||||
| } | |||||
| return row.inStockQty | |||||
| } | |||||
| // editable: true, | |||||
| }, | |||||
| { | |||||
| field: "productionQty", | |||||
| label: "Demand Qty (7 Days)", | |||||
| type: 'read-only', | |||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof (row.productionQty) == "number") { | |||||
| return decimalFormatter.format(row.productionQty) | |||||
| } | |||||
| return row.productionQty | |||||
| } | |||||
| }, | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| const fakeOverallRecords = useMemo<FGRecord[]>( | |||||
| () => [ | |||||
| { | |||||
| id: 1, jobNo: "JO20250507001", priority: 20, code: "PP1193", type: "FG", name: "蔥油(1磅) ", lastMonthAvgStock: 1320, safetyStock: 1322, inStockQty: 1322, productionQty: 4627, | |||||
| lines: [ | |||||
| { id: 2, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 20 * 7 }, | |||||
| { id: 3, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 10 * 7 } | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 2, jobNo: "JO20250507002", priority: 25, code: " PP1096", type: "FG", name: "白麵撈", lastMonthAvgStock: 1040, safetyStock: 1040, inStockQty: 1040, productionQty: 3640, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 190.00 * 7 }, | |||||
| { id: 1, code: "MH0040", type: "Material", name: "星加坡綠富貴花牌幼白麵粉 (50磅/包)", inStockQty: 0, purchaseQty: 250.00 * 7 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "蔥油", inStockQty: 1322, purchaseQty: 0 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 3, jobNo: "JO20250507003", priority: 70, code: "PP1080", type: "FG", name: "咖哩汁", lastMonthAvgStock: 2400, safetyStock: 2400, inStockQty: 2400, productionQty: 8400.0 * 7, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 54.44, purchaseQty: 544.4 * 7 }, | |||||
| { id: 2, code: "GI3236", type: "Material", name: "清水(煮過牛腩)", inStockQty: 317.52, purchaseQty: 3175.2 * 7 }, | |||||
| { id: 3, code: "MG1700", type: "Material", name: "STERILTOM 意大利茄粒", inStockQty: 9.00, purchaseQty: 90 * 7 }, | |||||
| { id: 4, code: "FA0533", type: "Material", name: "乾蔥茸", inStockQty: 6.04, purchaseQty: 60.4 * 7 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 6.04, purchaseQty: 60.4 * 7 }, | |||||
| { id: 6, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 6.04, purchaseQty: 60.4 * 7 }, | |||||
| { id: 7, code: "FA0056", type: "Material", name: "洋蔥肉", inStockQty: 241.98, purchaseQty: 2419.8 * 7 }, | |||||
| { id: 8, code: "PP1188", type: "Material", name: "咖喱膽", inStockQty: 36.00, purchaseQty: 360 * 7 }, | |||||
| { id: 9, code: "PP8001", type: "Material", name: "咖哩汁箱料粉", inStockQty: 77.42, purchaseQty: 774.2 * 7 }, | |||||
| { id: 10, code: "PP1096", type: "Material", name: "白麵撈", inStockQty: 60.00, purchaseQty: 600 * 7 }, | |||||
| { id: 10, code: "NA0476", type: "Material", name: "2磅份量三邊覆合袋 (0.1x225x260mm)個計", inStockQty: 600.00, purchaseQty: 6000 * 7 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 4, jobNo: "JO20250507004", priority: 80, code: " PP1188", type: "FG", name: "咖喱膽", lastMonthAvgStock: 1017, safetyStock: 1017, inStockQty: 1016.2, productionQty: 3556.7, | |||||
| lines: [ | |||||
| { id: 1, code: "MH0040", type: "Material", name: "大豆油(1噸/桶)", inStockQty: 0, purchaseQty: 217.72 * 7 }, | |||||
| { id: 2, code: "FA0161", type: "Material", name: "洋蔥粒", inStockQty: 0, purchaseQty: 18.15 * 7 }, | |||||
| { id: 3, code: "FA0608", type: "Material", name: "粗蒜茸", inStockQty: 0, purchaseQty: 18.15 * 7 }, | |||||
| { id: 4, code: "MG1288", type: "Material", name: "炸紅蔥頭", inStockQty: 0, purchaseQty: 6.05 * 7 }, | |||||
| { id: 5, code: "FA0210", type: "Material", name: "薑茸", inStockQty: 0, purchaseQty: 6.05 * 7 }, | |||||
| { id: 6, code: "MG0066", type: "Material", name: "咖哩料(5斤x16包+2斤/包)", inStockQty: 0, purchaseQty: 241.98 * 7 }, | |||||
| ] | |||||
| }, | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| return ( | |||||
| <Grid container spacing={2}> | |||||
| {/* <Grid item xs={12} key={"all"}> | |||||
| <Typography variant="overline" display="block" marginBlockEnd={1}> | |||||
| {t("FG Demand List (7 Days)")} | |||||
| </Typography> | |||||
| <EditableSearchResults<FGRecord> | |||||
| index={7} | |||||
| items={fakeOverallRecords} | |||||
| columns={overallColumns} | |||||
| setPagingController={updatePagingController} | |||||
| pagingController={pagingController[7]} | |||||
| isAutoPaging={false} | |||||
| isEditable={false} | |||||
| isEdit={isEdit} | |||||
| hasCollapse={true} | |||||
| /> | |||||
| </Grid> */} | |||||
| {dayPeriod.map((date, index) => ( | |||||
| <Grid item xs={12} key={index}> | |||||
| {/* <Typography variant="overline" display="block" marginBlockEnd={1}> | |||||
| {`${t("FG Demand Date")}: ${date}`} | |||||
| </Typography> */} | |||||
| <EditableSearchResults<FGRecord> | |||||
| items={fakeRecords[index]} // Use the corresponding records for the day | |||||
| columns={columns} | |||||
| setPagingController={updatePagingController} | |||||
| pagingController={pagingController[index]} | |||||
| isAutoPaging={false} | |||||
| isEditable={true} | |||||
| isEdit={isEdit} | |||||
| hasCollapse={true} | |||||
| /> | |||||
| </Grid> | |||||
| ))} | |||||
| </Grid> | |||||
| ); | |||||
| }; | |||||
| export default ViewByFGDetails; | |||||
| @@ -0,0 +1 @@ | |||||
| export { default } from "./DetailScheduleDetailWrapper"; | |||||
| @@ -82,7 +82,7 @@ const DetailInfoCard: React.FC<Props> = ({ recordDetails, isEditing}) => { | |||||
| </Grid> | </Grid> | ||||
| <Grid item xs={6}> | <Grid item xs={6}> | ||||
| <TextField | <TextField | ||||
| label={t("Total Estimated Demand Count")} | |||||
| label={t("Total Estimated Demand Qty")} | |||||
| fullWidth | fullWidth | ||||
| {...register("productionCount", { | {...register("productionCount", { | ||||
| required: "type required!", | required: "type required!", | ||||
| @@ -338,6 +338,9 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "inStockQty", | field: "inStockQty", | ||||
| label: t("Available Qty"), | label: t("Available Qty"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | renderCell: (row: FGOverallRecord) => { | ||||
| if (typeof(row.inStockQty) == "number") { | if (typeof(row.inStockQty) == "number") { | ||||
| return decimalFormatter.format(row.inStockQty) | return decimalFormatter.format(row.inStockQty) | ||||
| @@ -350,6 +353,9 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "overallPurchaseQty", | field: "overallPurchaseQty", | ||||
| label: t("Total Demand Qty"), | label: t("Total Demand Qty"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | renderCell: (row: FGOverallRecord) => { | ||||
| if (typeof(row.overallPurchaseQty) == "number") { | if (typeof(row.overallPurchaseQty) == "number") { | ||||
| return decimalFormatter.format(row.overallPurchaseQty) | return decimalFormatter.format(row.overallPurchaseQty) | ||||
| @@ -361,6 +367,9 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "purchaseQty1", | field: "purchaseQty1", | ||||
| label: t("Demand Qty (Day1)"), | label: t("Demand Qty (Day1)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | renderCell: (row: FGOverallRecord) => { | ||||
| if (typeof(row.purchaseQty1) == "number") { | if (typeof(row.purchaseQty1) == "number") { | ||||
| return decimalFormatter.format(row.purchaseQty1) | return decimalFormatter.format(row.purchaseQty1) | ||||
| @@ -372,6 +381,9 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "purchaseQty2", | field: "purchaseQty2", | ||||
| label: t("Demand Qty (Day2)"), | label: t("Demand Qty (Day2)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | renderCell: (row: FGOverallRecord) => { | ||||
| if (typeof(row.purchaseQty2) == "number") { | if (typeof(row.purchaseQty2) == "number") { | ||||
| return decimalFormatter.format(row.purchaseQty2) | return decimalFormatter.format(row.purchaseQty2) | ||||
| @@ -383,6 +395,9 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "purchaseQty3", | field: "purchaseQty3", | ||||
| label: t("Demand Qty (Day3)"), | label: t("Demand Qty (Day3)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | renderCell: (row: FGOverallRecord) => { | ||||
| if (typeof(row.purchaseQty3) == "number") { | if (typeof(row.purchaseQty3) == "number") { | ||||
| return decimalFormatter.format(row.purchaseQty3) | return decimalFormatter.format(row.purchaseQty3) | ||||
| @@ -394,6 +409,9 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "purchaseQty4", | field: "purchaseQty4", | ||||
| label: t("Demand Qty (Day4)"), | label: t("Demand Qty (Day4)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | renderCell: (row: FGOverallRecord) => { | ||||
| if (typeof(row.purchaseQty4) == "number") { | if (typeof(row.purchaseQty4) == "number") { | ||||
| return decimalFormatter.format(row.purchaseQty4) | return decimalFormatter.format(row.purchaseQty4) | ||||
| @@ -404,6 +422,9 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "purchaseQty5", | field: "purchaseQty5", | ||||
| label: t("Demand Qty (Day5)"), | label: t("Demand Qty (Day5)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | renderCell: (row: FGOverallRecord) => { | ||||
| if (typeof(row.purchaseQty5) == "number") { | if (typeof(row.purchaseQty5) == "number") { | ||||
| return decimalFormatter.format(row.purchaseQty5) | return decimalFormatter.format(row.purchaseQty5) | ||||
| @@ -415,6 +436,9 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "purchaseQty6", | field: "purchaseQty6", | ||||
| label: t("Demand Qty (Day6)"), | label: t("Demand Qty (Day6)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | renderCell: (row: FGOverallRecord) => { | ||||
| if (typeof(row.purchaseQty6) == "number") { | if (typeof(row.purchaseQty6) == "number") { | ||||
| return decimalFormatter.format(row.purchaseQty6) | return decimalFormatter.format(row.purchaseQty6) | ||||
| @@ -426,6 +450,9 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "purchaseQty7", | field: "purchaseQty7", | ||||
| label: t("Demand Qty (Day7)"), | label: t("Demand Qty (Day7)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGOverallRecord) => { | renderCell: (row: FGOverallRecord) => { | ||||
| if (typeof(row.purchaseQty7) == "number") { | if (typeof(row.purchaseQty7) == "number") { | ||||
| return decimalFormatter.format(row.purchaseQty7) | return decimalFormatter.format(row.purchaseQty7) | ||||
| @@ -460,6 +487,9 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| label: "Available Qty", | label: "Available Qty", | ||||
| type: 'read-only', | type: 'read-only', | ||||
| // editable: true, | // editable: true, | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGRecord) => { | renderCell: (row: FGRecord) => { | ||||
| if (typeof(row.inStockQty) == "number") { | if (typeof(row.inStockQty) == "number") { | ||||
| return decimalFormatter.format(row.inStockQty) | return decimalFormatter.format(row.inStockQty) | ||||
| @@ -469,8 +499,11 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| }, | }, | ||||
| { | { | ||||
| field: "purchaseQty", | field: "purchaseQty", | ||||
| label: "Purchase Qty", | |||||
| label: "Demand Qty", | |||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGRecord) => { | renderCell: (row: FGRecord) => { | ||||
| if (typeof(row.purchaseQty) == "number") { | if (typeof(row.purchaseQty) == "number") { | ||||
| return decimalFormatter.format(row.purchaseQty) | return decimalFormatter.format(row.purchaseQty) | ||||
| @@ -466,6 +466,9 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "inStockQty", | field: "inStockQty", | ||||
| label: "Available Qty", | label: "Available Qty", | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| // editable: true, | // editable: true, | ||||
| renderCell: (row: FGRecord) => { | renderCell: (row: FGRecord) => { | ||||
| if (typeof(row.inStockQty) == "number") { | if (typeof(row.inStockQty) == "number") { | ||||
| @@ -478,6 +481,9 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "productionQty", | field: "productionQty", | ||||
| label: "Demand Qty", | label: "Demand Qty", | ||||
| type: 'input', | type: 'input', | ||||
| style: { | |||||
| textAlign: "right", | |||||
| }, | |||||
| renderCell: (row: FGRecord) => { | renderCell: (row: FGRecord) => { | ||||
| if (typeof(row.productionQty) == "number") { | if (typeof(row.productionQty) == "number") { | ||||
| return decimalFormatter.format(row.productionQty ?? 0) | return decimalFormatter.format(row.productionQty ?? 0) | ||||
| @@ -513,7 +519,7 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| label: "Last Month Average Stock", | label: "Last Month Average Stock", | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "center", | |||||
| textAlign: "right", | |||||
| }, | }, | ||||
| renderCell: (row: FGRecord) => { | renderCell: (row: FGRecord) => { | ||||
| if (typeof(row.lastMonthAvgStock) == "number") { | if (typeof(row.lastMonthAvgStock) == "number") { | ||||
| @@ -528,7 +534,7 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| label: "Safety Stock", | label: "Safety Stock", | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "center", | |||||
| textAlign: "right", | |||||
| }, | }, | ||||
| renderCell: (row: FGRecord) => { | renderCell: (row: FGRecord) => { | ||||
| if (typeof(row.safetyStock) == "number") { | if (typeof(row.safetyStock) == "number") { | ||||
| @@ -543,7 +549,7 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| label: "Available Qty", | label: "Available Qty", | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "center", | |||||
| textAlign: "right", | |||||
| }, | }, | ||||
| renderCell: (row: FGRecord) => { | renderCell: (row: FGRecord) => { | ||||
| if (typeof(row.inStockQty) == "number") { | if (typeof(row.inStockQty) == "number") { | ||||
| @@ -30,7 +30,7 @@ interface BaseCriterion<T extends string> { | |||||
| paramName2?: T; | paramName2?: T; | ||||
| options?: T[]; | options?: T[]; | ||||
| filterObj?: T; | filterObj?: T; | ||||
| handleSelectionChange: (selectedOptions: T[]) => void; | |||||
| handleSelectionChange?: (selectedOptions: T[]) => void; | |||||
| } | } | ||||
| interface TextCriterion<T extends string> extends BaseCriterion<T> { | interface TextCriterion<T extends string> extends BaseCriterion<T> { | ||||
| @@ -16,11 +16,12 @@ import CancelIcon from "@mui/icons-material/Close"; | |||||
| import DeleteIcon from "@mui/icons-material/Delete"; | import DeleteIcon from "@mui/icons-material/Delete"; | ||||
| import TextField from "@mui/material/TextField"; | import TextField from "@mui/material/TextField"; | ||||
| import MultiSelect from "@/components/SearchBox/MultiSelect"; | import MultiSelect from "@/components/SearchBox/MultiSelect"; | ||||
| import { Collapse } from "@mui/material"; | |||||
| import { Collapse, Typography } from "@mui/material"; | |||||
| import TempInputGridForMockUp from "./TempInputGridForMockUp"; | import TempInputGridForMockUp from "./TempInputGridForMockUp"; | ||||
| import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; | import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; | ||||
| import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; | import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; | ||||
| import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; | import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; | ||||
| import PlayCircleOutlineIcon from '@mui/icons-material/PlayCircleOutline'; | |||||
| export interface ResultWithId { | export interface ResultWithId { | ||||
| id: string | number; | id: string | number; | ||||
| @@ -131,6 +132,11 @@ function EditableSearchResults<T extends ResultWithId>({ | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <TableRow hover tabIndex={-1} key={row.id}> | <TableRow hover tabIndex={-1} key={row.id}> | ||||
| <TableCell> | |||||
| <IconButton disable={!isEdit}> | |||||
| <PlayCircleOutlineIcon /> | |||||
| </IconButton> | |||||
| </TableCell> | |||||
| { | { | ||||
| (isEditable || hasCollapse) && <TableCell> | (isEditable || hasCollapse) && <TableCell> | ||||
| {(editingRowId === row.id) ? ( | {(editingRowId === row.id) ? ( | ||||
| @@ -152,6 +158,7 @@ function EditableSearchResults<T extends ResultWithId>({ | |||||
| onClick={() => setOpen(!open)} | onClick={() => setOpen(!open)} | ||||
| > | > | ||||
| {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} | {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} | ||||
| <Typography>View BoM</Typography> | |||||
| </IconButton> | </IconButton> | ||||
| } | } | ||||
| </> | </> | ||||
| @@ -176,6 +183,7 @@ function EditableSearchResults<T extends ResultWithId>({ | |||||
| onClick={() => setOpen(!open)} | onClick={() => setOpen(!open)} | ||||
| > | > | ||||
| {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} | {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} | ||||
| <Typography>View BoM</Typography> | |||||
| </IconButton> | </IconButton> | ||||
| } | } | ||||
| </> | </> | ||||
| @@ -183,7 +191,6 @@ function EditableSearchResults<T extends ResultWithId>({ | |||||
| </TableCell> | </TableCell> | ||||
| } | } | ||||
| {columns.map((column, idx) => { | {columns.map((column, idx) => { | ||||
| console.log(column) | |||||
| const columnName = column.field; | const columnName = column.field; | ||||
| return ( | return ( | ||||
| <TableCell key={`${columnName.toString()}-${idx}`}> | <TableCell key={`${columnName.toString()}-${idx}`}> | ||||
| @@ -227,7 +234,7 @@ function EditableSearchResults<T extends ResultWithId>({ | |||||
| : | : | ||||
| <div style={column.style}> | <div style={column.style}> | ||||
| <span onDoubleClick={() => isEdit && handleEditClick(row.id as number)}> | <span onDoubleClick={() => isEdit && handleEditClick(row.id as number)}> | ||||
| {row[columnName] as String} | |||||
| {row[columnName] as String} | |||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| )} | )} | ||||
| @@ -265,6 +272,7 @@ function EditableSearchResults<T extends ResultWithId>({ | |||||
| <Table stickyHeader> | <Table stickyHeader> | ||||
| <TableHead> | <TableHead> | ||||
| <TableRow> | <TableRow> | ||||
| <TableCell>Release</TableCell> | |||||
| {(isEditable || hasCollapse) && <TableCell>Actions</TableCell>} {/* Action Column Header */} | {(isEditable || hasCollapse) && <TableCell>Actions</TableCell>} {/* Action Column Header */} | ||||
| {columns.map((column, idx) => ( | {columns.map((column, idx) => ( | ||||
| <TableCell style={column.style} key={`${column.field.toString()}${idx}`}> | <TableCell style={column.style} key={`${column.field.toString()}${idx}`}> | ||||
| @@ -22,7 +22,7 @@ import { | |||||
| } from "react"; | } from "react"; | ||||
| import StyledDataGrid from "../StyledDataGrid"; | import StyledDataGrid from "../StyledDataGrid"; | ||||
| import { GridColDef } from "@mui/x-data-grid"; | import { GridColDef } from "@mui/x-data-grid"; | ||||
| import { Box, Button, Grid, Typography } from "@mui/material"; | |||||
| import { Box, Button, Grid, Icon, Typography } from "@mui/material"; | |||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import { Add } from "@mui/icons-material"; | import { Add } from "@mui/icons-material"; | ||||
| import SaveIcon from "@mui/icons-material/Save"; | import SaveIcon from "@mui/icons-material/Save"; | ||||
| @@ -36,6 +36,7 @@ import PlayArrowIcon from "@mui/icons-material/PlayArrow"; | |||||
| import { createStockInLine, testFetch } from "@/app/api/po/actions"; | import { createStockInLine, testFetch } from "@/app/api/po/actions"; | ||||
| import { useSearchParams } from "next/navigation"; | import { useSearchParams } from "next/navigation"; | ||||
| import { decimalFormatter, stockInLineStatusMap } from "@/app/utils/formatUtil"; | import { decimalFormatter, stockInLineStatusMap } from "@/app/utils/formatUtil"; | ||||
| import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; | |||||
| interface ResultWithId { | interface ResultWithId { | ||||
| id: number; | id: number; | ||||
| @@ -184,6 +185,8 @@ function TempInputGridForMockUp({ stockInLine }: Props) { | |||||
| flex: 0.5, | flex: 0.5, | ||||
| type: "number", | type: "number", | ||||
| editable: true, | editable: true, | ||||
| align: "right", | |||||
| headerAlign: "right", | |||||
| renderCell: (row) => { | renderCell: (row) => { | ||||
| return decimalFormatter.format(row.value) | return decimalFormatter.format(row.value) | ||||
| } | } | ||||
| @@ -194,10 +197,26 @@ function TempInputGridForMockUp({ stockInLine }: Props) { | |||||
| headerName: "Demand Qty", | headerName: "Demand Qty", | ||||
| flex: 0.5, | flex: 0.5, | ||||
| editable: true, | editable: true, | ||||
| align: "right", | |||||
| headerAlign: "right", | |||||
| renderCell: (row) => { | renderCell: (row) => { | ||||
| return decimalFormatter.format(row.value) | return decimalFormatter.format(row.value) | ||||
| } | } | ||||
| }, | }, | ||||
| { | |||||
| field: "status", | |||||
| headerName: "status", | |||||
| flex: 0.5, | |||||
| editable: true, | |||||
| align: "center", | |||||
| headerAlign: "center", | |||||
| renderCell: () => { | |||||
| return <CheckCircleOutlineIcon | |||||
| color="success" | |||||
| fontSize="small" | |||||
| /> | |||||
| } | |||||
| }, | |||||
| // { | // { | ||||
| // field: "actions", | // field: "actions", | ||||
| // type: "actions", | // type: "actions", | ||||
| @@ -398,13 +417,13 @@ function TempInputGridForMockUp({ stockInLine }: Props) { | |||||
| } | } | ||||
| return classname; | return classname; | ||||
| }} | }} | ||||
| // slots={{ | |||||
| // footer: FooterToolbar, | |||||
| // noRowsOverlay: NoRowsOverlay, | |||||
| // }} | |||||
| // slotProps={{ | |||||
| // footer: { child: footer }, | |||||
| // }} | |||||
| // slots={{ | |||||
| // footer: FooterToolbar, | |||||
| // noRowsOverlay: NoRowsOverlay, | |||||
| // }} | |||||
| // slotProps={{ | |||||
| // footer: { child: footer }, | |||||
| // }} | |||||
| /> | /> | ||||
| </> | </> | ||||
| ); | ); | ||||