| @@ -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("schedule", "common"); | |||||
| return ( | |||||
| <Stack spacing={2}> | |||||
| <Typography variant="h4">{t("Not Found")}</Typography> | |||||
| <Typography variant="body1">{t("The production schedule detail page was not found!")}</Typography> | |||||
| <Link href="/settings/scheduling" component={NextLink} variant="body2"> | |||||
| {t("Return to all scheduling")} | |||||
| </Link> | |||||
| </Stack> | |||||
| ); | |||||
| } | |||||
| @@ -8,15 +8,35 @@ import Typography from "@mui/material/Typography"; | |||||
| import { Metadata } from "next"; | import { Metadata } from "next"; | ||||
| import Link from "next/link"; | import Link from "next/link"; | ||||
| import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
| import RoughScheduleDetailView from "@/components/RoughScheduleDetail/RoughScheudleDetailView"; | |||||
| import RoughScheduleDetailView from "@/components/RoughScheduleDetail"; | |||||
| import { SearchParams, ServerFetchError } from "@/app/utils/fetchUtil"; | |||||
| import { isArray, parseInt } from "lodash"; | |||||
| import { notFound } from "next/navigation"; | |||||
| import { fetchProdScheduleDetail } from "@/app/api/scheduling"; | |||||
| export const metadata: Metadata = { | export const metadata: Metadata = { | ||||
| title: "Demand Forecast Detail", | title: "Demand Forecast Detail", | ||||
| }; | }; | ||||
| const roughSchedulingDetail: React.FC = async () => { | |||||
| // const project = TypeEnum.PRODUCT | |||||
| const { t } = await getServerI18n("project"); | |||||
| type Props = SearchParams | |||||
| const roughSchedulingDetail: React.FC<Props> = async ({ searchParams }) => { | |||||
| const { t } = await getServerI18n("schedule"); | |||||
| const id = searchParams["id"] | |||||
| const type = "rough" | |||||
| if (!id || isArray(id) || !isFinite(parseInt(id))) { | |||||
| notFound() | |||||
| } | |||||
| try { | |||||
| await fetchProdScheduleDetail(parseInt(id)) | |||||
| } catch(e) { | |||||
| if (e instanceof ServerFetchError && (e.response?.status === 404 || e.response?.status === 400)) { | |||||
| console.log(e) | |||||
| notFound(); | |||||
| } | |||||
| } | |||||
| // preloadClaims(); | // preloadClaims(); | ||||
| return ( | return ( | ||||
| @@ -39,9 +59,9 @@ const roughSchedulingDetail: React.FC = async () => { | |||||
| {t("Create product")} | {t("Create product")} | ||||
| </Button> */} | </Button> */} | ||||
| </Stack> | </Stack> | ||||
| <I18nProvider namespaces={["schedule","project","common"]}> | |||||
| <I18nProvider namespaces={["schedule","common"]}> | |||||
| <Suspense fallback={<RoughScheduleDetailView.Loading />}> | <Suspense fallback={<RoughScheduleDetailView.Loading />}> | ||||
| <RoughScheduleDetailView /> | |||||
| <RoughScheduleDetailView type={type} id={parseInt(id)}/> | |||||
| </Suspense> | </Suspense> | ||||
| </I18nProvider> | </I18nProvider> | ||||
| </> | </> | ||||
| @@ -19,6 +19,7 @@ export const metadata: Metadata = { | |||||
| const roughScheduling: React.FC = async () => { | const roughScheduling: React.FC = async () => { | ||||
| // const project = TypeEnum.PRODUCT | // const project = TypeEnum.PRODUCT | ||||
| const { t } = await getServerI18n("schedule"); | const { t } = await getServerI18n("schedule"); | ||||
| const type = "rough" | |||||
| // preloadClaims(); | // preloadClaims(); | ||||
| return ( | return ( | ||||
| @@ -44,7 +45,7 @@ const roughScheduling: React.FC = async () => { | |||||
| </Stack> | </Stack> | ||||
| <I18nProvider namespaces={["schedule", "common","items","project"]}> | <I18nProvider namespaces={["schedule", "common","items","project"]}> | ||||
| <Suspense fallback={<RoughSchedule.Loading />}> | <Suspense fallback={<RoughSchedule.Loading />}> | ||||
| <RoughSchedule /> | |||||
| <RoughSchedule type={type}/> | |||||
| </Suspense> | </Suspense> | ||||
| </I18nProvider> | </I18nProvider> | ||||
| </> | </> | ||||
| @@ -0,0 +1,43 @@ | |||||
| "use server" | |||||
| import { convertObjToURLSearchParams } from "@/app/utils/commonUtil"; | |||||
| import { serverFetchJson } from "@/app/utils/fetchUtil" | |||||
| import { BASE_API_URL } from "@/config/api" | |||||
| import { cache } from "react" | |||||
| export interface SearchProdSchedule { | |||||
| scheduleAt?: string; | |||||
| schedulePeriod?: string; | |||||
| schedulePeriodTo?: string; | |||||
| totalEstProdCount?: number; | |||||
| type?: "manual" | "detailed" | "rough"; | |||||
| pageSize?: number; | |||||
| pageNum?: number; | |||||
| } | |||||
| export interface ProdScheduleResult { | |||||
| id: number; | |||||
| scheduleAt: number[]; | |||||
| schedulePeriod: number[]; | |||||
| schedulePeriodTo: number[]; | |||||
| totalEstProdCount: number; | |||||
| totalFGType: number; | |||||
| type: string; | |||||
| } | |||||
| export interface ProdScheduleResultByPage { | |||||
| total: number; | |||||
| records: ProdScheduleResult[]; | |||||
| } | |||||
| export const fetchProdSchedules = cache(async (data: SearchProdSchedule | null) => { | |||||
| const params = convertObjToURLSearchParams<SearchProdSchedule>(data) | |||||
| // console.log(params) | |||||
| return serverFetchJson<ProdScheduleResultByPage>(`${BASE_API_URL}/productionSchedule/getRecordByPage?${params}`, { | |||||
| method: "GET", | |||||
| headers: { "Content-Type": "application/json" }, | |||||
| next: { | |||||
| tags: ["prodSchedules"] | |||||
| } | |||||
| }) | |||||
| }) | |||||
| @@ -0,0 +1,82 @@ | |||||
| import { serverFetchJson } from "@/app/utils/fetchUtil" | |||||
| import { BASE_API_URL } from "@/config/api" | |||||
| import { cache } from "react" | |||||
| import "server-only" | |||||
| export type ScheduleType = "rough" | "detail"; | |||||
| export interface ProdScheduleResult { | |||||
| id: number; | |||||
| scheduleAt: number[]; | |||||
| schedulePeriod: number[]; | |||||
| schedulePeriodTo: number[]; | |||||
| totalEstProdCount: number; | |||||
| totalFGType: number; | |||||
| type: string; | |||||
| prodScheduleLinesByFg: ProdScheduleLineResultByFg[]; | |||||
| prodScheduleLinesByFgByDate: { [assignDate: number]: ProdScheduleLineResultByFg[] }; | |||||
| prodScheduleLinesByBom: ProdScheduleLineResultByBom[]; | |||||
| prodScheduleLinesByBomByDate: { [assignDate: number]: ProdScheduleLineResultByBomByDate[] }; | |||||
| } | |||||
| export interface ProdScheduleLineResultByFg { | |||||
| id: number; | |||||
| code: string; | |||||
| name: string; | |||||
| type: string; | |||||
| availableQty: number; | |||||
| prodQty: number; | |||||
| lastMonthAvgSales: number; | |||||
| estCloseBal: number; | |||||
| priority: number; | |||||
| assignDate: number; | |||||
| bomMaterials: ProdScheduleLineBomMaterialResult[]; | |||||
| } | |||||
| export interface ProdScheduleLineBomMaterialResult { | |||||
| id: number; | |||||
| code: string; | |||||
| name: string; | |||||
| type: string; | |||||
| availableQty: number; | |||||
| demandQty: number; | |||||
| uomName: string; | |||||
| } | |||||
| export interface ProdScheduleLineResultByBom { | |||||
| id: number, | |||||
| code: string, | |||||
| name: string, | |||||
| type: string, | |||||
| availableQty: number, | |||||
| totalDemandQty: number, | |||||
| demandQty1: number, | |||||
| demandQty2: number, | |||||
| demandQty3: number, | |||||
| demandQty4: number, | |||||
| demandQty5: number, | |||||
| demandQty6: number, | |||||
| demandQty7: number, | |||||
| uomName: string, | |||||
| } | |||||
| export interface ProdScheduleLineResultByBomByDate { | |||||
| id: number, | |||||
| code: string, | |||||
| name: string, | |||||
| type: string, | |||||
| availableQty: number, | |||||
| demandQty: number, | |||||
| assignDate: number, | |||||
| uomName: string, | |||||
| } | |||||
| export const fetchProdScheduleDetail = cache(async (id: number) => { | |||||
| return serverFetchJson<ProdScheduleResult>(`${BASE_API_URL}/productionSchedule/detail/${id}`, { | |||||
| method: "GET", | |||||
| headers: { "Content-Type": "application/json" }, | |||||
| next: { | |||||
| tags: ["prodSchedule"] | |||||
| } | |||||
| }) | |||||
| }) | |||||
| @@ -1,65 +1,60 @@ | |||||
| "use client"; | "use client"; | ||||
| import React, {useCallback, useEffect, useMemo, useState} from "react"; | |||||
| import React, { useCallback, useEffect, useMemo, useState } from "react"; | |||||
| import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
| import { ItemsResult} from "@/app/api/settings/item"; | |||||
| import { ItemsResult } from "@/app/api/settings/item"; | |||||
| import SearchResults, { Column } from "../SearchResults"; | import SearchResults, { Column } from "../SearchResults"; | ||||
| import { EditNote } from "@mui/icons-material"; | import { EditNote } from "@mui/icons-material"; | ||||
| import { useRouter, useSearchParams } from "next/navigation"; | import { useRouter, useSearchParams } from "next/navigation"; | ||||
| import { GridDeleteIcon } from "@mui/x-data-grid"; | import { GridDeleteIcon } from "@mui/x-data-grid"; | ||||
| import { TypeEnum } from "@/app/utils/typeEnum"; | import { TypeEnum } from "@/app/utils/typeEnum"; | ||||
| import axios from "axios"; | import axios from "axios"; | ||||
| import {BASE_API_URL, NEXT_PUBLIC_API_URL} from "@/config/api"; | |||||
| import { BASE_API_URL, NEXT_PUBLIC_API_URL } from "@/config/api"; | |||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import axiosInstance from "@/app/(main)/axios/axiosInstance"; | import axiosInstance from "@/app/(main)/axios/axiosInstance"; | ||||
| import Qs from 'qs'; | import Qs from 'qs'; | ||||
| import EditableSearchResults from "@/components/SearchResults/EditableSearchResults"; // Make sure to import Qs | import EditableSearchResults from "@/components/SearchResults/EditableSearchResults"; // Make sure to import Qs | ||||
| type RecordStructure ={ | |||||
| id: number, | |||||
| schedulePeriod: string, | |||||
| scheduleAt: string | |||||
| }; | |||||
| import { ProdScheduleResult, ProdScheduleResultByPage, SearchProdSchedule, fetchProdSchedules } from "@/app/api/scheduling/actions"; | |||||
| import { arrayToDateString, decimalFormatter } from "@/app/utils/formatUtil"; | |||||
| import { isEqual, uniqBy } from "lodash"; | |||||
| import dayjs from "dayjs"; | |||||
| import { defaultPagingController } from "../SearchResults/SearchResults"; | |||||
| // type RecordStructure ={ | |||||
| // id: number, | |||||
| // schedulePeriod: string, | |||||
| // scheduleAt: string | |||||
| // }; | |||||
| type Props = { | type Props = { | ||||
| records: RecordStructure[]; | |||||
| type: SearchProdSchedule["type"]; | |||||
| // initProdSchedules: ProdScheduleResultByPage; | |||||
| defaultInputs: SearchProdSchedule; | |||||
| }; | }; | ||||
| type SearchQuery = Partial<Omit<ItemsResult, "id">>; | |||||
| type SearchQuery = Partial<Omit<SearchProdSchedule, "id" | "type" | "pageSize" | "pageNum">>; | |||||
| type SearchParamNames = keyof SearchQuery; | type SearchParamNames = keyof SearchQuery; | ||||
| const RSOverview: React.FC<Props> = ({ records }) => { | |||||
| const [filteredItems, setFilteredItems] = useState<Object[]>(records ?? []); | |||||
| const { t } = useTranslation("items"); | |||||
| const RSOverview: React.FC<Props> = ({ type, defaultInputs }) => { | |||||
| const [filteredSchedules, setFilteredSchedules] = useState<ProdScheduleResult[]>([]); | |||||
| const { t } = useTranslation("scheduling"); | |||||
| const router = useRouter(); | 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 | |||||
| var title = ""; | |||||
| var mode = "Search"; | |||||
| var redirPath = ""; | |||||
| title = "Product"; | |||||
| redirPath = "/scheduling/rough"; | |||||
| return [mode, redirPath]; | |||||
| }, []); | |||||
| // const [filterObj, setFilterObj] = useState({}); | |||||
| // const [tempSelectedValue, setTempSelectedValue] = useState({}); | |||||
| const [pagingController, setPagingController] = useState(defaultPagingController) | |||||
| const [totalCount, setTotalCount] = useState(0) | |||||
| const [inputs, setInputs] = useState(defaultInputs) | |||||
| const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | ||||
| () => { | () => { | ||||
| var searchCriteria: Criterion<SearchParamNames>[] = [ | var searchCriteria: Criterion<SearchParamNames>[] = [ | ||||
| { label: t("Schedule Period"), paramName: "schedulePeriod", type: "dateRange" }, | |||||
| { label: t("Schedule Period"), label2: t("Schedule Period To"), paramName: "schedulePeriod", type: "dateRange" }, | |||||
| { label: t("Scheduled At"), paramName: "scheduleAt", type: "date" }, | { label: t("Scheduled At"), paramName: "scheduleAt", type: "date" }, | ||||
| { label: t("Product Count"), paramName: "productCount", type: "input" }, | |||||
| { label: t("Product Count"), paramName: "totalEstProdCount", type: "text" }, | |||||
| ] | ] | ||||
| return searchCriteria | return searchCriteria | ||||
| }, | }, | ||||
| [t, records] | |||||
| [t] | |||||
| ); | ); | ||||
| // const onDetailClick = useCallback( | // const onDetailClick = useCallback( | ||||
| @@ -70,7 +65,7 @@ const RSOverview: React.FC<Props> = ({ records }) => { | |||||
| // ); | // ); | ||||
| const onDeleteClick = useCallback( | const onDeleteClick = useCallback( | ||||
| (item: ItemsResult) => {}, | |||||
| (item: ItemsResult) => { }, | |||||
| [router] | [router] | ||||
| ); | ); | ||||
| @@ -79,25 +74,36 @@ const RSOverview: React.FC<Props> = ({ records }) => { | |||||
| router.push(`/scheduling/rough/edit?id=${record.id}`); | router.push(`/scheduling/rough/edit?id=${record.id}`); | ||||
| } | } | ||||
| const columns = useMemo<Column<ItemsResult>[]>( | |||||
| const columns = useMemo<Column<ProdScheduleResult>[]>( | |||||
| () => [ | () => [ | ||||
| { | { | ||||
| name: "id", | name: "id", | ||||
| label: t("Details"), | label: t("Details"), | ||||
| onClick: (record)=>onDetailClick(record), | |||||
| onClick: (record) => onDetailClick(record), | |||||
| buttonIcon: <EditNote />, | buttonIcon: <EditNote />, | ||||
| }, | }, | ||||
| { | { | ||||
| name: "scheduledPeriod", | |||||
| name: "schedulePeriod", | |||||
| label: t("Demand Forecast Period"), | label: t("Demand Forecast Period"), | ||||
| renderCell: (params) => { | |||||
| return `${arrayToDateString(params.schedulePeriod)} - ${arrayToDateString(params.schedulePeriodTo)}` | |||||
| } | |||||
| }, | }, | ||||
| { | { | ||||
| name: "scheduledAt", | |||||
| label: t("Scheduled At"), | |||||
| name: "scheduleAt", | |||||
| label: t("Schedule At"), | |||||
| renderCell: (params) => { | |||||
| return arrayToDateString(params.scheduleAt) | |||||
| } | |||||
| }, | }, | ||||
| { | { | ||||
| name: "productCount", | |||||
| name: "totalEstProdCount", | |||||
| label: t("Product Count(s)"), | label: t("Product Count(s)"), | ||||
| headerAlign: "right", | |||||
| align: "right", | |||||
| renderCell: (params) => { | |||||
| return decimalFormatter.format(params.totalEstProdCount) | |||||
| } | |||||
| }, | }, | ||||
| // { | // { | ||||
| // name: "action", | // name: "action", | ||||
| @@ -106,92 +112,134 @@ const RSOverview: React.FC<Props> = ({ records }) => { | |||||
| // onClick: onDeleteClick, | // onClick: onDeleteClick, | ||||
| // }, | // }, | ||||
| ], | ], | ||||
| [filteredItems] | |||||
| [filteredSchedules] | |||||
| ); | ); | ||||
| useEffect(() => { | |||||
| refetchData(filterObj); | |||||
| }, [filterObj, pagingController.pageNum, pagingController.pageSize]); | |||||
| const refetchData = async (filterObj: SearchQuery) => { | |||||
| const authHeader = axiosInstance.defaults.headers['Authorization']; | |||||
| if (!authHeader) { | |||||
| return; // Exit the function if the token is not set | |||||
| // useEffect(() => { | |||||
| // refetchData(filterObj); | |||||
| // }, [filterObj, pagingController.pageNum, pagingController.pageSize]); | |||||
| const refetchData = useCallback(async (query: Record<SearchParamNames, string> | SearchProdSchedule, actionType: "reset" | "search" | "paging") => { | |||||
| // console.log(query) | |||||
| const params: SearchProdSchedule = { | |||||
| scheduleAt: dayjs(query?.scheduleAt).isValid() ? query?.scheduleAt : undefined, | |||||
| schedulePeriod: dayjs(query?.schedulePeriod).isValid() ? query?.schedulePeriod : undefined, | |||||
| schedulePeriodTo: dayjs(query?.schedulePeriodTo).isValid() ? query?.schedulePeriodTo : undefined, | |||||
| totalEstProdCount: query?.totalEstProdCount ? Number(query?.totalEstProdCount) : undefined, | |||||
| type: "rough", | |||||
| pageNum: pagingController.pageNum - 1, | |||||
| pageSize: pagingController.pageSize | |||||
| } | } | ||||
| const params ={ | |||||
| pageNum: pagingController.pageNum, | |||||
| pageSize: pagingController.pageSize, | |||||
| ...filterObj, | |||||
| ...tempSelectedValue, | |||||
| const response = await fetchProdSchedules(params) | |||||
| // console.log(response) | |||||
| if (response) { | |||||
| setTotalCount(response.total) | |||||
| switch (actionType) { | |||||
| case "reset": | |||||
| case "search": | |||||
| setFilteredSchedules(() => response.records) | |||||
| break; | |||||
| case "paging": | |||||
| setFilteredSchedules((fs) => uniqBy([...fs, ...response.records], "id")) | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| }, [pagingController, setPagingController]) | |||||
| 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 | |||||
| } | |||||
| }; | |||||
| useEffect(() => { | |||||
| refetchData(inputs, "paging") | |||||
| }, [pagingController]) | |||||
| // const refetchData = async (filterObj: SearchQuery) => { | |||||
| // 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' }); | |||||
| // // }, | |||||
| // // }); | |||||
| // //setFilteredSchedules(response.data.records); | |||||
| // // setFilteredSchedules([ | |||||
| // // { | |||||
| // // 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(() => { | const onReset = useCallback(() => { | ||||
| //setFilteredItems(items ?? []); | |||||
| setFilterObj({}); | |||||
| setTempSelectedValue({}); | |||||
| refetchData(); | |||||
| }, [records]); | |||||
| // setFilteredSchedules(items ?? []); | |||||
| // setFilterObj({}); | |||||
| // setTempSelectedValue({}); | |||||
| refetchData(inputs, "reset"); | |||||
| }, []); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <SearchBox | <SearchBox | ||||
| criteria={searchCriteria} | criteria={searchCriteria} | ||||
| onSearch={(query) => { | onSearch={(query) => { | ||||
| setFilterObj({ | |||||
| ...query | |||||
| }) | |||||
| // resetPagingController() | |||||
| setInputs(() => ( | |||||
| { | |||||
| scheduleAt: query?.scheduleAt, | |||||
| schedulePeriod: query?.schedulePeriod, | |||||
| schedulePeriodTo: query?.schedulePeriodTo, | |||||
| totalEstProdCount: Number(query?.totalEstProdCount) | |||||
| } | |||||
| )) | |||||
| refetchData(query, "search") | |||||
| // setFilterObj({ | |||||
| // ...query | |||||
| // }) | |||||
| }} | }} | ||||
| onReset={onReset} | onReset={onReset} | ||||
| /> | /> | ||||
| <SearchResults<ItemsResult> | |||||
| items={filteredItems} | |||||
| <SearchResults<ProdScheduleResult> | |||||
| items={filteredSchedules} | |||||
| columns={columns} | columns={columns} | ||||
| setPagingController={setPagingController} | setPagingController={setPagingController} | ||||
| pagingController={pagingController} | pagingController={pagingController} | ||||
| isAutoPaging={false} | |||||
| hasCollapse={false} | |||||
| totalCount={totalCount} | |||||
| // isAutoPaging={false} | |||||
| /> | /> | ||||
| </> | </> | ||||
| ); | ); | ||||
| @@ -1,21 +1,35 @@ | |||||
| import { fetchAllItems } from "@/app/api/settings/item"; | import { fetchAllItems } from "@/app/api/settings/item"; | ||||
| import { RoughScheduleLoading } from "./RoughScheduleLoading"; | import { RoughScheduleLoading } from "./RoughScheduleLoading"; | ||||
| import RSOverview from "./RoughSchedileSearchView"; | import RSOverview from "./RoughSchedileSearchView"; | ||||
| import { SearchProdSchedule, fetchProdSchedules } from "@/app/api/scheduling/actions"; | |||||
| interface SubComponents { | interface SubComponents { | ||||
| Loading: typeof RoughScheduleLoading; | Loading: typeof RoughScheduleLoading; | ||||
| } | } | ||||
| type Props = {}; | |||||
| type Props = { | |||||
| type: SearchProdSchedule["type"] | |||||
| }; | |||||
| const RoughScheduleWrapper: React.FC<Props> & SubComponents = async ( | const RoughScheduleWrapper: React.FC<Props> & SubComponents = async ( | ||||
| { | { | ||||
| // type, | |||||
| type | |||||
| } | } | ||||
| ) => { | ) => { | ||||
| // console.log(type) | // console.log(type) | ||||
| var result = await fetchAllItems(); | |||||
| return <RSOverview records={[]} />; | |||||
| const defaultInputs: SearchProdSchedule = { | |||||
| type: "rough" | |||||
| } | |||||
| // const [ | |||||
| // items, | |||||
| // prodSchedules | |||||
| // ] = await Promise.all([ | |||||
| // fetchAllItems(), | |||||
| // fetchProdSchedules(defaultInputs) | |||||
| // ]) | |||||
| return <RSOverview type={type} defaultInputs={defaultInputs}/>; | |||||
| }; | }; | ||||
| RoughScheduleWrapper.Loading = RoughScheduleLoading; | RoughScheduleWrapper.Loading = RoughScheduleLoading; | ||||
| @@ -3,48 +3,53 @@ import { | |||||
| Box, | Box, | ||||
| Card, | Card, | ||||
| CardContent, | CardContent, | ||||
| FormControl, | |||||
| Grid, | Grid, | ||||
| Stack, | Stack, | ||||
| TextField, | TextField, | ||||
| Typography, | Typography, | ||||
| } from "@mui/material"; | } from "@mui/material"; | ||||
| import { useFormContext } from "react-hook-form"; | |||||
| import { Controller, useFormContext } from "react-hook-form"; | |||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import InputDataGrid from "../InputDataGrid"; | import InputDataGrid from "../InputDataGrid"; | ||||
| import {useCallback, useEffect, useMemo, useState} from "react"; | |||||
| import { useCallback, useEffect, useMemo, useState } from "react"; | |||||
| import { GridColDef, GridRowModel } from "@mui/x-data-grid"; | import { GridColDef, GridRowModel } from "@mui/x-data-grid"; | ||||
| import { InputDataGridProps, TableRow } from "../InputDataGrid/InputDataGrid"; | import { InputDataGridProps, TableRow } from "../InputDataGrid/InputDataGrid"; | ||||
| import { TypeEnum } from "@/app/utils/typeEnum"; | import { TypeEnum } from "@/app/utils/typeEnum"; | ||||
| import { CreateItemInputs } from "@/app/api/settings/item/actions"; | |||||
| import {NumberInputProps} from "@/components/CreateItem/NumberInputProps"; | |||||
| import { integerFormatter } from "@/app/utils/formatUtil"; | |||||
| import { NumberInputProps } from "@/components/CreateItem/NumberInputProps"; | |||||
| import { arrayToDateString, integerFormatter } from "@/app/utils/formatUtil"; | |||||
| import { ProdScheduleResult } from "@/app/api/scheduling"; | |||||
| import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers"; | |||||
| import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||||
| type Props = { | type Props = { | ||||
| // isEditMode: boolean; | |||||
| // type: TypeEnum; | |||||
| isEditing: boolean; | |||||
| }; | }; | ||||
| const DetailInfoCard: React.FC<Props> = ({ recordDetails, isEditing}) => { | |||||
| const DetailInfoCard: React.FC<Props> = ({ isEditing }) => { | |||||
| const { | const { | ||||
| t, | t, | ||||
| i18n: { language }, | i18n: { language }, | ||||
| } = useTranslation(); | } = useTranslation(); | ||||
| const { | const { | ||||
| control, | |||||
| register, | register, | ||||
| getValues, | |||||
| watch, | |||||
| formState: { errors, defaultValues, touchedFields }, | formState: { errors, defaultValues, touchedFields }, | ||||
| } = useFormContext<CreateItemInputs>(); | |||||
| } = useFormContext<ProdScheduleResult>(); | |||||
| const [details, setDetails] = useState(null); | |||||
| // const [details, setDetails] = useState(null); | |||||
| useEffect(()=>{ | |||||
| console.log("[debug] record details", recordDetails) | |||||
| setDetails(recordDetails); | |||||
| },[recordDetails]) | |||||
| useEffect(() => { | |||||
| console.log("[debug] record details", getValues) | |||||
| // setDetails(recordDetails); | |||||
| }, [getValues]) | |||||
| useEffect(()=>{ | |||||
| useEffect(() => { | |||||
| console.log("[debug] isEdit", isEditing) | console.log("[debug] isEdit", isEditing) | ||||
| },[isEditing]) | |||||
| }, [isEditing]) | |||||
| return ( | return ( | ||||
| <Card sx={{ display: "block" }}> | <Card sx={{ display: "block" }}> | ||||
| @@ -58,39 +63,39 @@ const DetailInfoCard: React.FC<Props> = ({ recordDetails, isEditing}) => { | |||||
| <TextField | <TextField | ||||
| label={t("Date")} | label={t("Date")} | ||||
| fullWidth | fullWidth | ||||
| {...register("scheduledPeriod", { | |||||
| required: "name required!", | |||||
| })} | |||||
| defaultValue={details?.scheduledPeriod} | |||||
| // {...register("scheduledPeriod", { | |||||
| // required: "name required!", | |||||
| // })} | |||||
| defaultValue={`${arrayToDateString(getValues("schedulePeriod"))} - ${arrayToDateString(getValues("schedulePeriodTo"))}`} | |||||
| disabled={!isEditing} | disabled={!isEditing} | ||||
| error={Boolean(errors.name)} | |||||
| helperText={errors.name?.message} | |||||
| // error={Boolean(errors.name)} | |||||
| // helperText={errors.name?.message} | |||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| <Grid item xs={6}> | <Grid item xs={6}> | ||||
| <TextField | <TextField | ||||
| label={t("Total FG Item")} | label={t("Total FG Item")} | ||||
| fullWidth | fullWidth | ||||
| {...register("productCount", { | |||||
| required: "code required!", | |||||
| })} | |||||
| defaultValue={details?.productCount} | |||||
| // {...register("totalFGType", { | |||||
| // required: "Total FG Item required!", | |||||
| // })} | |||||
| defaultValue={typeof (getValues("totalFGType")) == "number" ? integerFormatter.format(getValues("totalFGType")) : getValues("totalFGType")} | |||||
| disabled={!isEditing} | disabled={!isEditing} | ||||
| error={Boolean(errors.code)} | |||||
| helperText={errors.code?.message} | |||||
| // error={Boolean(errors.code)} | |||||
| // helperText={errors.code?.message} | |||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| <Grid item xs={6}> | <Grid item xs={6}> | ||||
| <TextField | <TextField | ||||
| label={t("Total Estimated Demand Qty")} | |||||
| fullWidth | |||||
| {...register("productionCount", { | |||||
| required: "type required!", | |||||
| })} | |||||
| disabled={!isEditing} | |||||
| defaultValue={typeof(details?.productionCount) == "number" ? integerFormatter.format(details?.productionCount) : details?.productionCount} | |||||
| error={Boolean(errors.type)} | |||||
| helperText={errors.type?.message} | |||||
| label={t("Total Estimated Demand Qty")} | |||||
| fullWidth | |||||
| // {...register("totalEstProdCount", { | |||||
| // required: "Qty required!", | |||||
| // })} | |||||
| disabled={!isEditing} | |||||
| defaultValue={typeof (getValues("totalFGType")) == "number" ? integerFormatter.format(getValues("totalEstProdCount")) : getValues("totalEstProdCount")} | |||||
| // error={Boolean(errors.type)} | |||||
| // helperText={errors.type?.message} | |||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| </Grid> | </Grid> | ||||
| @@ -2,46 +2,25 @@ import { CreateItemInputs } from "@/app/api/settings/item/actions"; | |||||
| import { fetchItem } from "@/app/api/settings/item"; | import { fetchItem } from "@/app/api/settings/item"; | ||||
| import GeneralLoading from "@/components/General/GeneralLoading"; | import GeneralLoading from "@/components/General/GeneralLoading"; | ||||
| import RoughScheduleDetailView from "@/components/RoughScheduleDetail/RoughScheudleDetailView"; | import RoughScheduleDetailView from "@/components/RoughScheduleDetail/RoughScheudleDetailView"; | ||||
| import React from "react"; | |||||
| import { ScheduleType, fetchProdScheduleDetail } from "@/app/api/scheduling"; | |||||
| interface SubComponents { | interface SubComponents { | ||||
| Loading: typeof GeneralLoading; | Loading: typeof GeneralLoading; | ||||
| } | } | ||||
| type Props = { | type Props = { | ||||
| id?: number | id?: number | ||||
| // type: TypeEnum; | |||||
| type: ScheduleType; | |||||
| }; | }; | ||||
| const RoughScheduleDetailWrapper: (id: { id: any }) => Promise<JSX.Element> = async ({ id: any }) => { | |||||
| var result | |||||
| var defaultValues: Partial<CreateItemInputs> | undefined | |||||
| // console.log(type) | |||||
| var qcChecks | |||||
| if (id) { | |||||
| result = await fetchItem(id); | |||||
| const item = result.item | |||||
| qcChecks = result.qcChecks | |||||
| const activeRows = qcChecks.filter(it => it.isActive).map(i => i.id) | |||||
| console.log(qcChecks) | |||||
| defaultValues = { | |||||
| type: item?.type, | |||||
| id: item?.id, | |||||
| code: item?.code, | |||||
| name: item?.name, | |||||
| description: item?.description, | |||||
| remarks: item?.remarks, | |||||
| shelfLife: item?.shelfLife, | |||||
| countryOfOrigin: item?.countryOfOrigin, | |||||
| maxQty: item?.maxQty, | |||||
| qcChecks: qcChecks, | |||||
| qcChecks_active: activeRows | |||||
| }; | |||||
| } | |||||
| const RoughScheduleDetailWrapper: React.FC<Props> & SubComponents = async ({ id, type }) => { | |||||
| const prodSchedule = id ? await fetchProdScheduleDetail(id) : undefined | |||||
| return ( | return ( | ||||
| <RoughScheduleDetailView | <RoughScheduleDetailView | ||||
| isEditMode={Boolean(id)} | isEditMode={Boolean(id)} | ||||
| defaultValues={defaultValues} | |||||
| qcChecks={qcChecks || []} | |||||
| type={type} | |||||
| defaultValues={prodSchedule} | |||||
| /> | /> | ||||
| ); | ); | ||||
| }; | }; | ||||
| @@ -14,28 +14,30 @@ import { | |||||
| useForm, | useForm, | ||||
| } from "react-hook-form"; | } from "react-hook-form"; | ||||
| import { deleteDialog } from "../Swal/CustomAlerts"; | 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 { 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 { useGridApiRef } from "@mui/x-data-grid"; | ||||
| import ProductDetails from "@/components/CreateItem/ProductDetails"; | import ProductDetails from "@/components/CreateItem/ProductDetails"; | ||||
| import DetailInfoCard from "@/components/RoughScheduleDetail/DetailInfoCard"; | import DetailInfoCard from "@/components/RoughScheduleDetail/DetailInfoCard"; | ||||
| import ViewByFGDetails, {FGRecord} from "@/components/RoughScheduleDetail/ViewByFGDetails"; | |||||
| import ViewByFGDetails from "@/components/RoughScheduleDetail/ViewByFGDetails"; | |||||
| import ViewByBomDetails from "@/components/RoughScheduleDetail/ViewByBomDetails"; | import ViewByBomDetails from "@/components/RoughScheduleDetail/ViewByBomDetails"; | ||||
| import EditableSearchResults, {Column} from "@/components/SearchResults/EditableSearchResults"; | |||||
| import ScheduleTable from "@/components/ScheduleTable"; | |||||
| import { Column } from "@/components/ScheduleTable/ScheduleTable"; | |||||
| import { ProdScheduleResult, ScheduleType } from "@/app/api/scheduling"; | |||||
| import { arrayToDayjs, dayjsToDateString } from "@/app/utils/formatUtil"; | |||||
| type Props = { | type Props = { | ||||
| isEditMode: boolean; | isEditMode: boolean; | ||||
| // type: TypeEnum; | |||||
| defaultValues: Partial<CreateItemInputs> | undefined; | |||||
| qcChecks: ItemQc[] | |||||
| type: ScheduleType; | |||||
| defaultValues: Partial<ProdScheduleResult> | undefined; | |||||
| // qcChecks: ItemQc[] | |||||
| }; | }; | ||||
| const RoughScheduleDetailView: React.FC<Props> = ({ | const RoughScheduleDetailView: React.FC<Props> = ({ | ||||
| isEditMode, | isEditMode, | ||||
| // type, | |||||
| type, | |||||
| defaultValues, | defaultValues, | ||||
| qcChecks | |||||
| }) => { | }) => { | ||||
| // console.log(type) | // console.log(type) | ||||
| const apiRef = useGridApiRef(); | const apiRef = useGridApiRef(); | ||||
| @@ -47,35 +49,9 @@ const RoughScheduleDetailView: React.FC<Props> = ({ | |||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const [isEdit, setIsEdit] = useState(false); | const [isEdit, setIsEdit] = useState(false); | ||||
| //const title = "Demand Forecast Detail" | //const title = "Demand Forecast Detail" | ||||
| const [mode, redirPath] = useMemo(() => { | |||||
| // var typeId = TypeEnum.CONSUMABLE_ID | |||||
| var title = ""; | |||||
| var mode = ""; | |||||
| var 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/rough/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) | // console.log(typeId) | ||||
| const formProps = useForm<CreateItemInputs>({ | |||||
| const formProps = useForm<ProdScheduleResult>({ | |||||
| defaultValues: defaultValues ? defaultValues : { | defaultValues: defaultValues ? defaultValues : { | ||||
| }, | }, | ||||
| }); | }); | ||||
| @@ -88,7 +64,18 @@ const RoughScheduleDetailView: React.FC<Props> = ({ | |||||
| [], | [], | ||||
| ); | ); | ||||
| const dayPeriod = useMemo<string[]>(() => { | |||||
| const from = arrayToDayjs(formProps.getValues("schedulePeriod")) | |||||
| const to = arrayToDayjs(formProps.getValues("schedulePeriodTo")) | |||||
| const diffDays = Math.abs(from.diff(to, "day")) | |||||
| let result: string[] = [] | |||||
| for (let i = 0; i <= diffDays; i++) { | |||||
| result.push(dayjsToDateString(from.add(i, "day"))) | |||||
| } | |||||
| return result; | |||||
| }, []) | |||||
| const [pagingController, setPagingController] = useState({ | const [pagingController, setPagingController] = useState({ | ||||
| pageNum: 1, | pageNum: 1, | ||||
| @@ -101,7 +88,7 @@ const RoughScheduleDetailView: React.FC<Props> = ({ | |||||
| router.replace(`/scheduling/rough`); | router.replace(`/scheduling/rough`); | ||||
| }; | }; | ||||
| const onSubmit = useCallback<SubmitHandler<CreateItemInputs & {}>>( | |||||
| const onSubmit = useCallback<SubmitHandler<ProdScheduleResult>>( | |||||
| async (data, event) => { | async (data, event) => { | ||||
| let hasErrors = false; | let hasErrors = false; | ||||
| console.log(errors) | console.log(errors) | ||||
| @@ -122,12 +109,12 @@ const RoughScheduleDetailView: React.FC<Props> = ({ | |||||
| ); | ); | ||||
| // multiple tabs | // multiple tabs | ||||
| const onSubmitError = useCallback<SubmitErrorHandler<CreateItemInputs>>( | |||||
| (errors) => {}, | |||||
| const onSubmitError = useCallback<SubmitErrorHandler<ProdScheduleResult>>( | |||||
| (errors) => { }, | |||||
| [] | [] | ||||
| ); | ); | ||||
| const onClickEdit = () =>{ | |||||
| const onClickEdit = () => { | |||||
| setIsEdit(!isEdit) | setIsEdit(!isEdit) | ||||
| } | } | ||||
| @@ -139,57 +126,57 @@ const RoughScheduleDetailView: React.FC<Props> = ({ | |||||
| component="form" | component="form" | ||||
| onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)} | onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)} | ||||
| > | > | ||||
| {/*<Grid>*/} | |||||
| {/* <Typography mb={2} variant="h4">*/} | |||||
| {/* {t(`${mode} ${title}`)}*/} | |||||
| {/* </Typography>*/} | |||||
| {/*</Grid>*/} | |||||
| <DetailInfoCard | |||||
| recordDetails={{ | |||||
| id: 1, | |||||
| scheduledPeriod: "2025-05-11 to 2025-05-17", | |||||
| scheduledAt: "2025-05-07", | |||||
| productCount: 13, | |||||
| productionCount: 21000 | |||||
| }} | |||||
| {/*<Grid>*/} | |||||
| {/* <Typography mb={2} variant="h4">*/} | |||||
| {/* {t(`${mode} ${title}`)}*/} | |||||
| {/* </Typography>*/} | |||||
| {/*</Grid>*/} | |||||
| <DetailInfoCard | |||||
| // recordDetails={{ | |||||
| // id: 1, | |||||
| // scheduledPeriod: "2025-05-11 to 2025-05-17", | |||||
| // scheduledAt: "2025-05-07", | |||||
| // productCount: 13, | |||||
| // productionCount: 21000 | |||||
| // }} | |||||
| isEditing={isEdit} | isEditing={isEdit} | ||||
| /> | |||||
| <Stack | |||||
| /> | |||||
| {/* <Stack | |||||
| direction="row" | direction="row" | ||||
| justifyContent="space-between" | justifyContent="space-between" | ||||
| flexWrap="wrap" | flexWrap="wrap" | ||||
| rowGap={2} | rowGap={2} | ||||
| > | |||||
| <Button | |||||
| > | |||||
| <Button | |||||
| variant="contained" | variant="contained" | ||||
| onClick={onClickEdit} | onClick={onClickEdit} | ||||
| // startIcon={<Add />} | |||||
| //LinkComponent={Link} | |||||
| //href="qcCategory/create" | |||||
| > | |||||
| {isEdit ? t("Save") : t("Edit")} | |||||
| </Button> | |||||
| </Stack> | |||||
| // 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 ? t(" (Selected)") : "")} iconPosition="end"/> | |||||
| <Tab label={t("View By Material") + (tabIndex === 1 ? t(" (Selected)") : "")} iconPosition="end" /> | |||||
| </Tabs> | |||||
| <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | |||||
| <Tab label={t("View By FG") + (tabIndex === 0 ? t(" (Selected)") : "")} iconPosition="end" /> | |||||
| <Tab label={t("View By Material") + (tabIndex === 1 ? t(" (Selected)") : "")} iconPosition="end" /> | |||||
| </Tabs> | |||||
| {serverError && ( | {serverError && ( | ||||
| <Typography variant="body2" color="error" alignSelf="flex-end"> | <Typography variant="body2" color="error" alignSelf="flex-end"> | ||||
| {serverError} | {serverError} | ||||
| </Typography> | </Typography> | ||||
| )} | )} | ||||
| {tabIndex === 0 && <ViewByFGDetails isEdit={isEdit} apiRef={apiRef}/>} | |||||
| {tabIndex === 1 && <ViewByBomDetails isEdit={isEdit} apiRef={apiRef} isHideButton={true} />} | |||||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | |||||
| {tabIndex === 0 && <ViewByFGDetails type={type} isEdit={isEdit} apiRef={apiRef} dayPeriod={dayPeriod} />} | |||||
| {tabIndex === 1 && <ViewByBomDetails type={type} isEdit={isEdit} apiRef={apiRef} dayPeriod={dayPeriod}/>} | |||||
| {/* <Stack direction="row" justifyContent="flex-end" gap={1}> | |||||
| <Button | <Button | ||||
| name="submit" | name="submit" | ||||
| variant="contained" | variant="contained" | ||||
| startIcon={<Check />} | startIcon={<Check />} | ||||
| type="submit" | type="submit" | ||||
| // disabled={submitDisabled} | |||||
| // disabled={submitDisabled} | |||||
| > | > | ||||
| {isEditMode ? t("Save") : t("Confirm")} | {isEditMode ? t("Save") : t("Confirm")} | ||||
| </Button> | </Button> | ||||
| @@ -200,7 +187,7 @@ const RoughScheduleDetailView: React.FC<Props> = ({ | |||||
| > | > | ||||
| {t("Cancel")} | {t("Cancel")} | ||||
| </Button> | </Button> | ||||
| </Stack> | |||||
| </Stack> */} | |||||
| </Stack> | </Stack> | ||||
| </FormProvider> | </FormProvider> | ||||
| </> | </> | ||||
| @@ -0,0 +1,592 @@ | |||||
| // View By Bom Details | |||||
| const dayPeriod = [ | |||||
| '2025-05-11', | |||||
| '2025-05-12', | |||||
| '2025-05-13', | |||||
| '2025-05-14', | |||||
| '2025-05-15', | |||||
| '2025-05-16', | |||||
| '2025-05-17', | |||||
| ]; | |||||
| // const fakeRecordLine = useMemo<FGRecord[][]>( | |||||
| const fakeRecordLine = [ | |||||
| [ | |||||
| { 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[][]>( | |||||
| const fakeRecords = [ | |||||
| [ | |||||
| { | |||||
| 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", 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 fakeOverallRecords = useMemo<FGRecord[]>( | |||||
| const fakeOverallRecords = [ | |||||
| { | |||||
| id: 1, 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: 2, 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: 3, 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 }, | |||||
| ] | |||||
| }, | |||||
| { | |||||
| id: 4, 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 }, | |||||
| ] | |||||
| }, | |||||
| ] | |||||
| // View By Bom Details | |||||
| const dayPeriod1 = [ | |||||
| '2025-05-11', | |||||
| '2025-05-12', | |||||
| '2025-05-13', | |||||
| '2025-05-14', | |||||
| '2025-05-15', | |||||
| '2025-05-16', | |||||
| '2025-05-17', | |||||
| ]; | |||||
| // const fakeOverallRecords = useMemo<FGOverallRecord[]>( | |||||
| const fakeOverallRecords1 = [ | |||||
| { | |||||
| 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 fakeRecords = useMemo<FGRecord[][]>( | |||||
| const fakeRecords1 = [ | |||||
| [ | |||||
| { 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 }, | |||||
| ], | |||||
| ] | |||||
| @@ -9,248 +9,67 @@ import { | |||||
| GridRowSelectionModel, | GridRowSelectionModel, | ||||
| useGridApiRef, | useGridApiRef, | ||||
| } from "@mui/x-data-grid"; | } from "@mui/x-data-grid"; | ||||
| import {MutableRefObject, useCallback, useEffect, useMemo, useState} from "react"; | |||||
| import { useFormContext } from "react-hook-form"; | |||||
| import { MutableRefObject, useCallback, useEffect, useMemo, useState } from "react"; | |||||
| import { useFieldArray, useFormContext } from "react-hook-form"; | |||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import InputDataGrid, { TableRow } from "../InputDataGrid/InputDataGrid"; | import InputDataGrid, { TableRow } from "../InputDataGrid/InputDataGrid"; | ||||
| import {Box, Grid, Tooltip, Typography} from "@mui/material"; | |||||
| import { Box, Grid, Tooltip, Typography } from "@mui/material"; | |||||
| import { ItemQc } from "@/app/api/settings/item"; | import { ItemQc } from "@/app/api/settings/item"; | ||||
| import { QcChecksInputs } from "@/app/api/settings/qcCheck/actions"; | import { QcChecksInputs } from "@/app/api/settings/qcCheck/actions"; | ||||
| import { GridApiCommunity } from "@mui/x-data-grid/internals"; | import { GridApiCommunity } from "@mui/x-data-grid/internals"; | ||||
| import { RiceBowl } from "@mui/icons-material"; | import { RiceBowl } from "@mui/icons-material"; | ||||
| import EditableSearchResults, {Column} from "@/components/SearchResults/EditableSearchResults"; | |||||
| // import EditableSearchResults, { Column } from "@/components/SearchResults/EditableSearchResults"; | |||||
| import { decimalFormatter } from "@/app/utils/formatUtil"; | import { decimalFormatter } from "@/app/utils/formatUtil"; | ||||
| import { GridRenderCellParams } from "@mui/x-data-grid"; | import { GridRenderCellParams } from "@mui/x-data-grid"; | ||||
| import { ProdScheduleLineResultByBom, ProdScheduleLineResultByBomByDate, ProdScheduleResult, ScheduleType } from "@/app/api/scheduling"; | |||||
| import ScheduleTable from "@/components/ScheduleTable"; | |||||
| import { Column } from "@/components/ScheduleTable/ScheduleTable"; | |||||
| type Props = { | type Props = { | ||||
| apiRef: MutableRefObject<GridApiCommunity> | apiRef: MutableRefObject<GridApiCommunity> | ||||
| isEdit: boolean | |||||
| type: ScheduleType | |||||
| dayPeriod: string[] | |||||
| }; | }; | ||||
| type EntryError = | |||||
| | { | |||||
| [field in keyof QcChecksInputs]?: string; | |||||
| } | |||||
| | undefined; | |||||
| export type FGRecord = { | |||||
| id: string | number | |||||
| code: string; | |||||
| name: string; | |||||
| inStockQty: number; | |||||
| purchaseQty: number; | |||||
| } | |||||
| // 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; | |||||
| } | |||||
| // 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"); | |||||
| console.log("lang:", i18n.language, "t(code):", t("code")); | |||||
| const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit, type, dayPeriod }) => { | |||||
| const { t, i18n: { language }, } = useTranslation("schedule"); | |||||
| const { | const { | ||||
| control, | |||||
| getValues, | |||||
| formState: { errors, defaultValues, touchedFields }, | formState: { errors, defaultValues, touchedFields }, | ||||
| } = useFormContext<CreateItemInputs>(); | |||||
| // const apiRef = useGridApiRef(); | |||||
| } = useFormContext<ProdScheduleResult>(); | |||||
| // 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 { fields } = useFieldArray({ | |||||
| control, | |||||
| name: "prodScheduleLinesByBom" | |||||
| }) | |||||
| const [pagingController, setPagingController] = useState([ | const [pagingController, setPagingController] = useState([ | ||||
| { | { | ||||
| @@ -295,10 +114,15 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| }, | }, | ||||
| ]) | ]) | ||||
| const updatePagingController = (updatedObj) => { | |||||
| const updatePagingController = (updatedObj: { | |||||
| pageNum: number; | |||||
| pageSize: number; | |||||
| totalCount: number; | |||||
| index?: number | undefined; | |||||
| }) => { | |||||
| setPagingController((prevState) => { | setPagingController((prevState) => { | ||||
| return prevState.map((item, index) => { | return prevState.map((item, index) => { | ||||
| if (index === updatedObj?.index){ | |||||
| if (index === updatedObj?.index) { | |||||
| return { | return { | ||||
| ...item, | ...item, | ||||
| pageNum: item.pageNum, | pageNum: item.pageNum, | ||||
| @@ -329,139 +153,142 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "type", | field: "type", | ||||
| label: t("type"), | label: t("type"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| renderCell: (params) => { | |||||
| return t(params.type) | |||||
| } | |||||
| // editable: true, | // editable: true, | ||||
| }, | }, | ||||
| { | { | ||||
| field: "inStockQty", | |||||
| field: "availableQty", | |||||
| label: t("Available Qty"), | label: t("Available Qty"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.inStockQty) == "number") { | |||||
| return decimalFormatter.format(row.inStockQty) | |||||
| renderCell: (row: ProdScheduleLineResultByBom) => { | |||||
| if (typeof (row.availableQty) == "number") { | |||||
| return decimalFormatter.format(row.availableQty) | |||||
| } | } | ||||
| return row.inStockQty | |||||
| return row.availableQty | |||||
| } | } | ||||
| // editable: true, | // editable: true, | ||||
| }, | }, | ||||
| { | { | ||||
| field: "overallPurchaseQty", | |||||
| field: "totalDemandQty", | |||||
| label: t("Total Demand Qty"), | label: t("Total Demand Qty"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.overallPurchaseQty) == "number") { | |||||
| return decimalFormatter.format(row.overallPurchaseQty) | |||||
| renderCell: (row: ProdScheduleLineResultByBom) => { | |||||
| if (typeof (row.totalDemandQty) == "number") { | |||||
| return decimalFormatter.format(row.totalDemandQty) | |||||
| } | } | ||||
| return row.overallPurchaseQty | |||||
| return row.totalDemandQty | |||||
| } | } | ||||
| }, | }, | ||||
| { | { | ||||
| field: "purchaseQty1", | |||||
| field: "demandQty1", | |||||
| label: t("Demand Qty (Day1)"), | label: t("Demand Qty (Day1)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty1) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty1) | |||||
| renderCell: (row: ProdScheduleLineResultByBom) => { | |||||
| if (typeof (row.demandQty1) == "number") { | |||||
| return decimalFormatter.format(row.demandQty1) | |||||
| } | } | ||||
| return row.purchaseQty1 | |||||
| return row.demandQty1 | |||||
| } | } | ||||
| }, | }, | ||||
| { | { | ||||
| field: "purchaseQty2", | |||||
| field: "demandQty2", | |||||
| label: t("Demand Qty (Day2)"), | label: t("Demand Qty (Day2)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty2) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty2) | |||||
| renderCell: (row: ProdScheduleLineResultByBom) => { | |||||
| if (typeof (row.demandQty2) == "number") { | |||||
| return decimalFormatter.format(row.demandQty2) | |||||
| } | } | ||||
| return row.purchaseQty2 | |||||
| return row.demandQty2 | |||||
| } | } | ||||
| }, | }, | ||||
| { | { | ||||
| field: "purchaseQty3", | |||||
| field: "demandQty3", | |||||
| label: t("Demand Qty (Day3)"), | label: t("Demand Qty (Day3)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty3) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty3) | |||||
| renderCell: (row: ProdScheduleLineResultByBom) => { | |||||
| if (typeof (row.demandQty3) == "number") { | |||||
| return decimalFormatter.format(row.demandQty3) | |||||
| } | } | ||||
| return row.purchaseQty3 | |||||
| return row.demandQty3 | |||||
| } | } | ||||
| }, | }, | ||||
| { | { | ||||
| field: "purchaseQty4", | |||||
| field: "demandQty4", | |||||
| label: t("Demand Qty (Day4)"), | label: t("Demand Qty (Day4)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty4) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty4) | |||||
| renderCell: (row: ProdScheduleLineResultByBom) => { | |||||
| if (typeof (row.demandQty4) == "number") { | |||||
| return decimalFormatter.format(row.demandQty4) | |||||
| } | } | ||||
| return row.purchaseQty4 | |||||
| return row.demandQty4 | |||||
| } | } | ||||
| },{ | |||||
| field: "purchaseQty5", | |||||
| }, { | |||||
| field: "demandQty5", | |||||
| label: t("Demand Qty (Day5)"), | label: t("Demand Qty (Day5)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty5) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty5) | |||||
| renderCell: (row: ProdScheduleLineResultByBom) => { | |||||
| if (typeof (row.demandQty5) == "number") { | |||||
| return decimalFormatter.format(row.demandQty5) | |||||
| } | } | ||||
| return row.purchaseQty5 | |||||
| return row.demandQty5 | |||||
| } | } | ||||
| }, | }, | ||||
| { | { | ||||
| field: "purchaseQty6", | |||||
| field: "demandQty6", | |||||
| label: t("Demand Qty (Day6)"), | label: t("Demand Qty (Day6)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty6) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty6) | |||||
| renderCell: (row: ProdScheduleLineResultByBom) => { | |||||
| if (typeof (row.demandQty6) == "number") { | |||||
| return decimalFormatter.format(row.demandQty6) | |||||
| } | } | ||||
| return row.purchaseQty6 | |||||
| return row.demandQty6 | |||||
| } | } | ||||
| }, | }, | ||||
| { | { | ||||
| field: "purchaseQty7", | |||||
| field: "demandQty7", | |||||
| label: t("Demand Qty (Day7)"), | label: t("Demand Qty (Day7)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGOverallRecord) => { | |||||
| if (typeof(row.purchaseQty7) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty7) | |||||
| renderCell: (row: ProdScheduleLineResultByBom) => { | |||||
| if (typeof (row.demandQty7) == "number") { | |||||
| return decimalFormatter.format(row.demandQty7) | |||||
| } | } | ||||
| return row.purchaseQty7 | |||||
| return row.demandQty7 | |||||
| } | } | ||||
| }, | }, | ||||
| ], | ], | ||||
| [t] | [t] | ||||
| ); | ); | ||||
| const columns = useMemo<Column<any>[]>( | |||||
| const columns = useMemo<Column<ProdScheduleLineResultByBomByDate>[]>( | |||||
| () => [ | () => [ | ||||
| { | { | ||||
| field: "code", | field: "code", | ||||
| @@ -478,56 +305,62 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "type", | field: "type", | ||||
| label: t("type"), | label: t("type"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| renderCell: (params) => { | |||||
| return t(params.type) | |||||
| } | |||||
| }, | }, | ||||
| { | { | ||||
| field: "inStockQty", | |||||
| field: "availableQty", | |||||
| label: t("Available Qty"), | label: t("Available Qty"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| // editable: true, | // editable: true, | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof(row.inStockQty) == "number") { | |||||
| return decimalFormatter.format(row.inStockQty) | |||||
| renderCell: (row: ProdScheduleLineResultByBomByDate) => { | |||||
| if (typeof (row.availableQty) == "number") { | |||||
| return decimalFormatter.format(row.availableQty) | |||||
| } | } | ||||
| return row.inStockQty | |||||
| return row.availableQty | |||||
| } | } | ||||
| }, | }, | ||||
| { | { | ||||
| field: "purchaseQty", | |||||
| field: "demandQty", | |||||
| label: t("Demand Qty"), | label: t("Demand Qty"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof(row.purchaseQty) == "number") { | |||||
| return decimalFormatter.format(row.purchaseQty) | |||||
| renderCell: (row: ProdScheduleLineResultByBomByDate) => { | |||||
| if (typeof (row.demandQty) == "number") { | |||||
| return decimalFormatter.format(row.demandQty) | |||||
| } | } | ||||
| return row.purchaseQty | |||||
| return row.demandQty | |||||
| } | } | ||||
| }, | }, | ||||
| ], | ], | ||||
| [] | [] | ||||
| ); | ); | ||||
| console.log(getValues("prodScheduleLinesByBom")) | |||||
| return ( | return ( | ||||
| <Grid container spacing={2}> | <Grid container spacing={2}> | ||||
| <Grid item xs={12} key={"all"}> | <Grid item xs={12} key={"all"}> | ||||
| <Typography variant="overline" display="block" marginBlockEnd={1}> | <Typography variant="overline" display="block" marginBlockEnd={1}> | ||||
| {t("Material Demand List (7 Days)")} | {t("Material Demand List (7 Days)")} | ||||
| </Typography> | </Typography> | ||||
| <EditableSearchResults<FGRecord> | |||||
| index={7} | |||||
| items={fakeOverallRecords} | |||||
| isMockUp={true} | |||||
| <ScheduleTable<ProdScheduleLineResultByBom> | |||||
| // index={7} | |||||
| type={type} | |||||
| items={getValues("prodScheduleLinesByBom")} | |||||
| columns={overallColumns} | columns={overallColumns} | ||||
| setPagingController={updatePagingController} | setPagingController={updatePagingController} | ||||
| pagingController={pagingController[7]} | pagingController={pagingController[7]} | ||||
| isAutoPaging={true} | isAutoPaging={true} | ||||
| isEditable={false} | isEditable={false} | ||||
| isEdit={false} | isEdit={false} | ||||
| hasCollapse={false} | |||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| {dayPeriod.map((date, index) => ( | {dayPeriod.map((date, index) => ( | ||||
| @@ -535,15 +368,17 @@ const ViewByBomDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| <Typography variant="overline" display="block" marginBlockEnd={1}> | <Typography variant="overline" display="block" marginBlockEnd={1}> | ||||
| {`${t("Material Demand Date")}: ${date}`} | {`${t("Material Demand Date")}: ${date}`} | ||||
| </Typography> | </Typography> | ||||
| <EditableSearchResults<FGRecord> | |||||
| index={index} | |||||
| items={fakeRecords[index]} // Use the corresponding records for the day | |||||
| <ScheduleTable<ProdScheduleLineResultByBomByDate> | |||||
| // index={index} | |||||
| type={type} | |||||
| items={getValues("prodScheduleLinesByBomByDate")[index + 1]} // Use the corresponding records for the day | |||||
| columns={columns} | columns={columns} | ||||
| setPagingController={updatePagingController} | setPagingController={updatePagingController} | ||||
| pagingController={pagingController[index]} | pagingController={pagingController[index]} | ||||
| isAutoPaging={true} | isAutoPaging={true} | ||||
| isEditable={false} | isEditable={false} | ||||
| isEdit={isEdit} | isEdit={isEdit} | ||||
| hasCollapse={false} | |||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| ))} | ))} | ||||
| @@ -9,379 +9,56 @@ import { | |||||
| GridRowSelectionModel, | GridRowSelectionModel, | ||||
| useGridApiRef, | useGridApiRef, | ||||
| } from "@mui/x-data-grid"; | } from "@mui/x-data-grid"; | ||||
| import {MutableRefObject, useCallback, useMemo, useState} from "react"; | |||||
| import { useFormContext } from "react-hook-form"; | |||||
| import { MutableRefObject, useCallback, useMemo, useState } from "react"; | |||||
| import { useFieldArray, useFormContext } from "react-hook-form"; | |||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import InputDataGrid, { TableRow } from "../InputDataGrid/InputDataGrid"; | import InputDataGrid, { TableRow } from "../InputDataGrid/InputDataGrid"; | ||||
| import {Box, Grid, Tooltip, Typography} from "@mui/material"; | |||||
| import { Box, Grid, Tooltip, Typography } from "@mui/material"; | |||||
| import { ItemQc } from "@/app/api/settings/item"; | import { ItemQc } from "@/app/api/settings/item"; | ||||
| import { QcChecksInputs } from "@/app/api/settings/qcCheck/actions"; | import { QcChecksInputs } from "@/app/api/settings/qcCheck/actions"; | ||||
| import { GridApiCommunity } from "@mui/x-data-grid/internals"; | import { GridApiCommunity } from "@mui/x-data-grid/internals"; | ||||
| import { RiceBowl } from "@mui/icons-material"; | import { RiceBowl } from "@mui/icons-material"; | ||||
| import EditableSearchResults, {Column} from "@/components/SearchResults/EditableSearchResults"; | |||||
| import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; | |||||
| import ScheduleTable from "@/components/ScheduleTable"; | |||||
| import { Column } from "@/components/ScheduleTable/ScheduleTable"; | |||||
| import { arrayToDayjs, dayjsToDateString, decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; | |||||
| import { ProdScheduleLineResultByFg, ProdScheduleResult, ScheduleType } from "@/app/api/scheduling"; | |||||
| type Props = { | type Props = { | ||||
| apiRef: MutableRefObject<GridApiCommunity> | apiRef: MutableRefObject<GridApiCommunity> | ||||
| isEdit: Boolean | |||||
| isEdit: boolean | |||||
| type: ScheduleType | |||||
| dayPeriod: string[] | |||||
| }; | }; | ||||
| type EntryError = | |||||
| | { | |||||
| [field in keyof QcChecksInputs]?: string; | |||||
| } | |||||
| | undefined; | |||||
| export type FGRecord = { | |||||
| id: string | number | |||||
| code: string; | |||||
| name: string; | |||||
| inStockQty: number; | |||||
| productionQty?: number; | |||||
| purchaseQty?: number | |||||
| } | |||||
| // export type FGRecord = { | |||||
| // id: string | number | |||||
| // code: string; | |||||
| // name: string; | |||||
| // inStockQty: number; | |||||
| // productionQty?: number; | |||||
| // purchaseQty?: number | |||||
| // } | |||||
| const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit, type, dayPeriod }) => { | |||||
| const { | const { | ||||
| t, | t, | ||||
| i18n: { language }, | i18n: { language }, | ||||
| } = useTranslation("schedule"); | } = useTranslation("schedule"); | ||||
| const { | const { | ||||
| control, | |||||
| getValues, | |||||
| formState: { errors, defaultValues, touchedFields }, | formState: { errors, defaultValues, touchedFields }, | ||||
| } = useFormContext<CreateItemInputs>(); | |||||
| // const apiRef = useGridApiRef(); | |||||
| } = useFormContext<ProdScheduleResult>(); | |||||
| const dayPeriod = [ | |||||
| '2025-05-11', | |||||
| '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 { fields } = useFieldArray({ | |||||
| control, | |||||
| name: "prodScheduleLinesByFg" | |||||
| }) | |||||
| // const apiRef = useGridApiRef(); | |||||
| const fakeRecords = useMemo<FGRecord[][]>( | |||||
| () => [ | |||||
| [ | |||||
| { 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", 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 }, | |||||
| ] | |||||
| }, | |||||
| ], | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| console.log("%c DayPeriod: ", 'background: #222; color: #bada55', dayPeriod) | |||||
| const [pagingController, setPagingController] = useState([ | const [pagingController, setPagingController] = useState([ | ||||
| { | { | ||||
| @@ -426,10 +103,15 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| }, | }, | ||||
| ]) | ]) | ||||
| const updatePagingController = (updatedObj) => { | |||||
| const updatePagingController = (updatedObj: { | |||||
| pageNum: number; | |||||
| pageSize: number; | |||||
| totalCount: number; | |||||
| index?: number | undefined; | |||||
| }) => { | |||||
| setPagingController((prevState) => { | setPagingController((prevState) => { | ||||
| return prevState.map((item, index) => { | return prevState.map((item, index) => { | ||||
| if (index === updatedObj?.index){ | |||||
| if (index === updatedObj?.index) { | |||||
| return { | return { | ||||
| ...item, | ...item, | ||||
| pageNum: item.pageNum, | pageNum: item.pageNum, | ||||
| @@ -443,7 +125,7 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| }); | }); | ||||
| }; | }; | ||||
| const columns = useMemo<Column<any>[]>( | |||||
| const columns = useMemo<Column<ProdScheduleLineResultByFg>[]>( | |||||
| () => [ | () => [ | ||||
| { | { | ||||
| field: "code", | field: "code", | ||||
| @@ -463,39 +145,39 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| // editable: true, | // editable: true, | ||||
| }, | }, | ||||
| { | { | ||||
| field: "inStockQty", | |||||
| field: "availableQty", | |||||
| label: t("Available Qty"), | label: t("Available Qty"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| // editable: true, | // editable: true, | ||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof(row.inStockQty) == "number") { | |||||
| return decimalFormatter.format(row.inStockQty) | |||||
| renderCell: (row) => { | |||||
| if (typeof (row.availableQty) == "number") { | |||||
| return decimalFormatter.format(row.availableQty) | |||||
| } | } | ||||
| return row.inStockQty | |||||
| return row.availableQty | |||||
| } | } | ||||
| }, | }, | ||||
| { | { | ||||
| field: "productionQty", | |||||
| field: "prodQty", | |||||
| label: t("Demand Qty"), | label: t("Demand Qty"), | ||||
| type: 'input', | type: 'input', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof(row.productionQty) == "number") { | |||||
| return decimalFormatter.format(row.productionQty ?? 0) | |||||
| renderCell: (row) => { | |||||
| if (typeof (row.prodQty) == "number") { | |||||
| return decimalFormatter.format(row.prodQty ?? 0) | |||||
| } | } | ||||
| return row.productionQty | |||||
| return row.prodQty | |||||
| } | } | ||||
| }, | }, | ||||
| ], | ], | ||||
| [] | [] | ||||
| ); | ); | ||||
| const overallColumns = useMemo<Column<any>[]>( | |||||
| const overallColumns = useMemo<Column<ProdScheduleLineResultByFg>[]>( | |||||
| () => [ | () => [ | ||||
| { | { | ||||
| field: "code", | field: "code", | ||||
| @@ -512,114 +194,75 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| field: "type", | field: "type", | ||||
| label: t("type"), | label: t("type"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| renderCell: (params) => { | |||||
| return t(params.type) | |||||
| } | |||||
| // editable: true, | // editable: true, | ||||
| }, | }, | ||||
| { | { | ||||
| field: "lastMonthAvgStock", | |||||
| field: "lastMonthAvgSales", | |||||
| label: t("Last Month Average Stock"), | label: t("Last Month Average Stock"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof(row.lastMonthAvgStock) == "number") { | |||||
| return decimalFormatter.format(row.lastMonthAvgStock) | |||||
| renderCell: (row) => { | |||||
| if (typeof (row.lastMonthAvgSales) == "number") { | |||||
| return decimalFormatter.format(row.lastMonthAvgSales) | |||||
| } | } | ||||
| return row.lastMonthAvgStock | |||||
| return row.lastMonthAvgSales | |||||
| } | } | ||||
| // editable: true, | // editable: true, | ||||
| }, | }, | ||||
| { | { | ||||
| field: "safetyStock", | |||||
| field: "estCloseBal", | |||||
| label: t("Safety Stock"), | label: t("Safety Stock"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof(row.safetyStock) == "number") { | |||||
| return decimalFormatter.format(row.safetyStock) | |||||
| renderCell: (row) => { | |||||
| if (typeof (row.estCloseBal) == "number") { | |||||
| return decimalFormatter.format(row.estCloseBal) | |||||
| } | } | ||||
| return row.safetyStock | |||||
| return row.estCloseBal | |||||
| } | } | ||||
| // editable: true, | // editable: true, | ||||
| }, | }, | ||||
| { | { | ||||
| field: "inStockQty", | |||||
| field: "availableQty", | |||||
| label: t("Available Qty"), | label: t("Available Qty"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof(row.inStockQty) == "number") { | |||||
| return decimalFormatter.format(row.inStockQty) | |||||
| renderCell: (row) => { | |||||
| if (typeof (row.availableQty) == "number") { | |||||
| return decimalFormatter.format(row.availableQty) | |||||
| } | } | ||||
| return row.inStockQty | |||||
| return row.availableQty | |||||
| } | } | ||||
| // editable: true, | // editable: true, | ||||
| }, | }, | ||||
| { | { | ||||
| field: "productionQty", | |||||
| field: "prodQty", | |||||
| label: t("Demand Qty (7 Days)"), | label: t("Demand Qty (7 Days)"), | ||||
| type: 'read-only', | type: 'read-only', | ||||
| style: { | style: { | ||||
| textAlign: "right", | textAlign: "right", | ||||
| }, | }, | ||||
| renderCell: (row: FGRecord) => { | |||||
| if (typeof(row.productionQty) == "number") { | |||||
| return decimalFormatter.format(row.productionQty) | |||||
| renderCell: (row) => { | |||||
| if (typeof (row.prodQty) == "number") { | |||||
| return decimalFormatter.format(row.prodQty) | |||||
| } | } | ||||
| return row.productionQty | |||||
| return row.prodQty | |||||
| } | } | ||||
| }, | }, | ||||
| ], | ], | ||||
| [] | [] | ||||
| ); | ); | ||||
| const fakeOverallRecords = useMemo<FGRecord[]>( | |||||
| () => [ | |||||
| { id: 1, 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: 2, 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: 3, 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 }, | |||||
| ] | |||||
| }, | |||||
| { id: 4, 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 }, | |||||
| ] | |||||
| }, | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| console.log(getValues("prodScheduleLinesByFg")) | |||||
| return ( | return ( | ||||
| <Grid container spacing={2}> | <Grid container spacing={2}> | ||||
| @@ -627,9 +270,10 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| <Typography variant="overline" display="block" marginBlockEnd={1}> | <Typography variant="overline" display="block" marginBlockEnd={1}> | ||||
| {t("FG Demand List (7 Days)")} | {t("FG Demand List (7 Days)")} | ||||
| </Typography> | </Typography> | ||||
| <EditableSearchResults<FGRecord> | |||||
| index={7} | |||||
| items={fakeOverallRecords} | |||||
| <ScheduleTable<ProdScheduleLineResultByFg> | |||||
| // index={7} | |||||
| type={type} | |||||
| items={getValues("prodScheduleLinesByFg")} | |||||
| columns={overallColumns} | columns={overallColumns} | ||||
| setPagingController={updatePagingController} | setPagingController={updatePagingController} | ||||
| pagingController={pagingController[7]} | pagingController={pagingController[7]} | ||||
| @@ -644,8 +288,9 @@ const ViewByFGDetails: React.FC<Props> = ({ apiRef, isEdit }) => { | |||||
| <Typography variant="overline" display="block" marginBlockEnd={1}> | <Typography variant="overline" display="block" marginBlockEnd={1}> | ||||
| {`${t("FG Demand Date")}: ${date}`} | {`${t("FG Demand Date")}: ${date}`} | ||||
| </Typography> | </Typography> | ||||
| <EditableSearchResults<FGRecord> | |||||
| items={fakeRecords[index]} // Use the corresponding records for the day | |||||
| <ScheduleTable<ProdScheduleLineResultByFg> | |||||
| type={type} | |||||
| items={getValues("prodScheduleLinesByFgByDate")[index + 1]} // Use the corresponding records for the day | |||||
| columns={columns} | columns={columns} | ||||
| setPagingController={updatePagingController} | setPagingController={updatePagingController} | ||||
| pagingController={pagingController[index]} | pagingController={pagingController[index]} | ||||
| @@ -0,0 +1,255 @@ | |||||
| "use client"; | |||||
| import { | |||||
| FooterPropsOverrides, | |||||
| GridActionsCellItem, | |||||
| GridCellParams, | |||||
| GridRowId, | |||||
| GridRowIdGetter, | |||||
| GridRowModel, | |||||
| GridRowModes, | |||||
| GridRowModesModel, | |||||
| GridToolbarContainer, | |||||
| useGridApiRef, | |||||
| } from "@mui/x-data-grid"; | |||||
| import { | |||||
| Dispatch, | |||||
| MutableRefObject, | |||||
| SetStateAction, | |||||
| useCallback, | |||||
| useEffect, | |||||
| useMemo, | |||||
| useState, | |||||
| } from "react"; | |||||
| import StyledDataGrid from "../StyledDataGrid"; | |||||
| import { GridColDef } from "@mui/x-data-grid"; | |||||
| import { Box, Button, Grid, Icon, Typography } from "@mui/material"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import { Add } from "@mui/icons-material"; | |||||
| import SaveIcon from "@mui/icons-material/Save"; | |||||
| import DeleteIcon from "@mui/icons-material/Delete"; | |||||
| import CancelIcon from "@mui/icons-material/Cancel"; | |||||
| import FactCheckIcon from "@mui/icons-material/FactCheck"; | |||||
| import ShoppingCartIcon from "@mui/icons-material/ShoppingCart"; | |||||
| // import PoQcModal from "./PoQcModal"; | |||||
| import PlayArrowIcon from "@mui/icons-material/PlayArrow"; | |||||
| import { useSearchParams } from "next/navigation"; | |||||
| import { decimalFormatter } from "@/app/utils/formatUtil"; | |||||
| import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; | |||||
| import HighlightOffIcon from '@mui/icons-material/HighlightOff'; | |||||
| import { ProdScheduleLineBomMaterialResult, ScheduleType } from "@/app/api/scheduling"; | |||||
| interface ResultWithId { | |||||
| id: number; | |||||
| } | |||||
| interface Props { | |||||
| bomMaterial: ProdScheduleLineBomMaterialResult[]; | |||||
| type: ScheduleType | |||||
| } | |||||
| export type BomMaterialEntryError = { | |||||
| [field in keyof any]?: string; | |||||
| }; | |||||
| export type BomMaterialRow = Partial< | |||||
| any & { | |||||
| isActive: boolean | undefined; | |||||
| _isNew: boolean; | |||||
| _error: BomMaterialEntryError; | |||||
| } & ResultWithId | |||||
| >; | |||||
| class ProcessRowUpdateError extends Error { | |||||
| public readonly row: BomMaterialRow; | |||||
| public readonly errors: BomMaterialEntryError | undefined; | |||||
| constructor(row: BomMaterialRow, message?: string, errors?: BomMaterialEntryError) { | |||||
| super(message); | |||||
| this.row = row; | |||||
| this.errors = errors; | |||||
| Object.setPrototypeOf(this, ProcessRowUpdateError.prototype); | |||||
| } | |||||
| } | |||||
| function BomMaterialTable({ bomMaterial }: Props) { | |||||
| const { t } = useTranslation("schedule"); | |||||
| const apiRef = useGridApiRef(); | |||||
| const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({}); | |||||
| const getRowId = useCallback<GridRowIdGetter<BomMaterialRow>>( | |||||
| (row) => row.id as number, | |||||
| [] | |||||
| ); | |||||
| const [entries, setEntries] = useState<BomMaterialRow[]>(bomMaterial || []); | |||||
| const columns = useMemo<GridColDef[]>( | |||||
| () => [ | |||||
| { | |||||
| field: "code", | |||||
| headerName: t("Code"), | |||||
| flex: 1, | |||||
| }, | |||||
| { | |||||
| field: "name", | |||||
| headerName: t("Name"), | |||||
| flex: 1, | |||||
| }, | |||||
| { | |||||
| field: "type", | |||||
| headerName: t("type"), | |||||
| flex: 1, | |||||
| renderCell: (row) => { | |||||
| return t(row.value) | |||||
| } | |||||
| }, | |||||
| { | |||||
| field: "availableQty", | |||||
| headerName: t("Available Qty"), | |||||
| flex: 0.5, | |||||
| type: "number", | |||||
| editable: true, | |||||
| align: "right", | |||||
| headerAlign: "right", | |||||
| renderCell: (row) => { | |||||
| return decimalFormatter.format(row.value) | |||||
| } | |||||
| // replace with tooltip + content | |||||
| }, | |||||
| { | |||||
| field: "demandQty", | |||||
| headerName: t("Demand Qty"), | |||||
| flex: 0.5, | |||||
| editable: true, | |||||
| align: "right", | |||||
| headerAlign: "right", | |||||
| renderCell: (row) => { | |||||
| return decimalFormatter.format(row.value) | |||||
| } | |||||
| }, | |||||
| { | |||||
| field: "status", | |||||
| headerName: t("status"), | |||||
| flex: 0.5, | |||||
| editable: true, | |||||
| align: "center", | |||||
| headerAlign: "center", | |||||
| renderCell: (params) => { | |||||
| return params.row.availableQty - params.row.demandQty >= 0 ? | |||||
| <CheckCircleOutlineIcon | |||||
| color="success" | |||||
| fontSize="small" | |||||
| /> : | |||||
| <HighlightOffIcon | |||||
| color="error" | |||||
| fontSize="small" | |||||
| /> | |||||
| } | |||||
| }, | |||||
| ], | |||||
| [] | |||||
| ); | |||||
| const validation = useCallback( | |||||
| ( | |||||
| newRow: GridRowModel<BomMaterialRow> | |||||
| ): BomMaterialEntryError | undefined => { | |||||
| const error: BomMaterialEntryError = {}; | |||||
| console.log(newRow); | |||||
| return Object.keys(error).length > 0 ? error : undefined; | |||||
| }, | |||||
| [] | |||||
| ); | |||||
| const processRowUpdate = useCallback( | |||||
| (newRow: GridRowModel<BomMaterialRow>, originalRow: GridRowModel<BomMaterialRow>) => { | |||||
| const errors = validation(newRow); // change to validation | |||||
| if (errors) { | |||||
| throw new ProcessRowUpdateError( | |||||
| originalRow, | |||||
| "validation error", | |||||
| errors | |||||
| ); | |||||
| } | |||||
| const { _isNew, _error, ...updatedRow } = newRow; | |||||
| const rowToSave = { | |||||
| ...updatedRow, | |||||
| } satisfies BomMaterialRow; | |||||
| const newEntries = entries.map((e) => | |||||
| getRowId(e) === getRowId(originalRow) ? rowToSave : e | |||||
| ); | |||||
| setEntries(newEntries); | |||||
| //update remaining qty | |||||
| const total = newEntries.reduce((acc, curr) => acc + (curr.acceptedQty || 0), 0); | |||||
| return rowToSave; | |||||
| }, | |||||
| [getRowId, entries] | |||||
| ); | |||||
| const onProcessRowUpdateError = useCallback( | |||||
| (updateError: ProcessRowUpdateError) => { | |||||
| const errors = updateError.errors; | |||||
| const oldRow = updateError.row; | |||||
| apiRef.current.updateRows([{ ...oldRow, _error: errors }]); | |||||
| }, | |||||
| [apiRef] | |||||
| ); | |||||
| return ( | |||||
| <> | |||||
| <StyledDataGrid | |||||
| getRowId={getRowId} | |||||
| apiRef={apiRef} | |||||
| autoHeight | |||||
| sx={{ | |||||
| "--DataGrid-overlayHeight": "100px", | |||||
| ".MuiDataGrid-row .MuiDataGrid-cell.hasError": { | |||||
| border: "1px solid", | |||||
| borderColor: "error.main", | |||||
| }, | |||||
| ".MuiDataGrid-row .MuiDataGrid-cell.hasWarning": { | |||||
| border: "1px solid", | |||||
| borderColor: "warning.main", | |||||
| }, | |||||
| }} | |||||
| disableColumnMenu | |||||
| editMode="row" | |||||
| rows={entries} | |||||
| rowModesModel={rowModesModel} | |||||
| onRowModesModelChange={setRowModesModel} | |||||
| processRowUpdate={processRowUpdate} | |||||
| onProcessRowUpdateError={onProcessRowUpdateError} | |||||
| columns={columns} | |||||
| getCellClassName={(params: GridCellParams<BomMaterialRow>) => { | |||||
| let classname = ""; | |||||
| if (params.row._error) { | |||||
| classname = "hasError"; | |||||
| } | |||||
| return classname; | |||||
| }} | |||||
| // slots={{ | |||||
| // footer: FooterToolbar, | |||||
| // noRowsOverlay: NoRowsOverlay, | |||||
| // }} | |||||
| // slotProps={{ | |||||
| // footer: { child: footer }, | |||||
| // }} | |||||
| /> | |||||
| </> | |||||
| ); | |||||
| } | |||||
| const NoRowsOverlay: React.FC = () => { | |||||
| const { t } = useTranslation("home"); | |||||
| return ( | |||||
| <Box | |||||
| display="flex" | |||||
| justifyContent="center" | |||||
| alignItems="center" | |||||
| height="100%" | |||||
| > | |||||
| <Typography variant="caption">{t("Add some entries!")}</Typography> | |||||
| </Box> | |||||
| ); | |||||
| }; | |||||
| const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => { | |||||
| return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>; | |||||
| }; | |||||
| export default BomMaterialTable; | |||||
| @@ -0,0 +1,334 @@ | |||||
| "use client"; | |||||
| import React, { CSSProperties, DetailedHTMLProps, HTMLAttributes, useEffect, useState } from "react"; | |||||
| import Paper from "@mui/material/Paper"; | |||||
| import Table from "@mui/material/Table"; | |||||
| import TableBody from "@mui/material/TableBody"; | |||||
| import TableCell from "@mui/material/TableCell"; | |||||
| import TableContainer from "@mui/material/TableContainer"; | |||||
| import TableHead from "@mui/material/TableHead"; | |||||
| import TablePagination from "@mui/material/TablePagination"; | |||||
| import TableRow from "@mui/material/TableRow"; | |||||
| import IconButton from "@mui/material/IconButton"; | |||||
| import EditIcon from "@mui/icons-material/Edit"; | |||||
| import SaveIcon from "@mui/icons-material/Save"; | |||||
| import CancelIcon from "@mui/icons-material/Close"; | |||||
| import DeleteIcon from "@mui/icons-material/Delete"; | |||||
| import TextField from "@mui/material/TextField"; | |||||
| import MultiSelect from "@/components/SearchBox/MultiSelect"; | |||||
| import { Collapse, Typography } from "@mui/material"; | |||||
| import BomMaterialTable from "./BomMaterialTable"; | |||||
| import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; | |||||
| import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; | |||||
| import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; | |||||
| import PlayCircleOutlineIcon from '@mui/icons-material/PlayCircleOutline'; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import { ProdScheduleLineBomMaterialResult, ProdScheduleLineResultByFg, ProdScheduleResult, ScheduleType } from "@/app/api/scheduling"; | |||||
| export interface ResultWithId { | |||||
| id: string | number; | |||||
| // id: number; | |||||
| } | |||||
| interface BaseColumn<T extends ResultWithId> { | |||||
| field: keyof T; | |||||
| label: string; | |||||
| type: string; | |||||
| options?: T[]; | |||||
| renderCell?: (params: T) => React.ReactNode; | |||||
| style?: Partial<HTMLElement["style"]> & { [propName: string]: string } & CSSProperties; | |||||
| } | |||||
| interface ColumnWithAction<T extends ResultWithId> extends BaseColumn<T> { | |||||
| onClick: (item: T) => void; | |||||
| buttonIcon: React.ReactNode; | |||||
| buttonColor?: "inherit" | "default" | "primary" | "secondary"; | |||||
| } | |||||
| export type Column<T extends ResultWithId> = | |||||
| | BaseColumn<T> | |||||
| | ColumnWithAction<T>; | |||||
| interface Props<T extends ResultWithId> { | |||||
| index?: number, | |||||
| items: T[], | |||||
| columns: Column<T>[], | |||||
| noWrapper?: boolean, | |||||
| setPagingController: (value: { pageNum: number; pageSize: number; totalCount: number, index?: number }) => void, | |||||
| pagingController: { pageNum: number; pageSize: number; totalCount: number }, | |||||
| isAutoPaging: boolean, | |||||
| isEdit: boolean, | |||||
| isEditable: boolean, | |||||
| hasCollapse: boolean, | |||||
| type: ScheduleType | |||||
| } | |||||
| function ScheduleTable<T extends ResultWithId>({ | |||||
| type, | |||||
| index = 7, | |||||
| items, | |||||
| columns, | |||||
| noWrapper, | |||||
| pagingController, | |||||
| setPagingController, | |||||
| isAutoPaging = true, | |||||
| isEdit = false, | |||||
| isEditable = true, | |||||
| hasCollapse = false, | |||||
| }: Props<T>) { | |||||
| const [page, setPage] = useState(0); | |||||
| const [rowsPerPage, setRowsPerPage] = useState(10); | |||||
| const [editingRowId, setEditingRowId] = useState<number | null>(null); | |||||
| const [editedItems, setEditedItems] = useState<T[]>(items); | |||||
| const { t } = useTranslation("schedule"); | |||||
| useEffect(() => { | |||||
| setEditedItems(items) | |||||
| }, [items]) | |||||
| const handleChangePage = (_event: unknown, newPage: number) => { | |||||
| setPage(newPage); | |||||
| if (setPagingController) { | |||||
| setPagingController({ ...pagingController, pageNum: newPage + 1, index: (index ?? -1)}); | |||||
| } | |||||
| }; | |||||
| const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => { | |||||
| setRowsPerPage(+event.target.value); | |||||
| setPage(0); | |||||
| if (setPagingController) { | |||||
| setPagingController({ ...pagingController, pageSize: +event.target.value, pageNum: 1, index: index }); | |||||
| } | |||||
| }; | |||||
| const handleEditClick = (id: number) => { | |||||
| setEditingRowId(id); | |||||
| }; | |||||
| const handleSaveClick = (item: T) => { | |||||
| setEditingRowId(null); | |||||
| // Call API or any save logic here | |||||
| setEditedItems((prev) => | |||||
| prev.map((row) => (row.id === item.id ? { ...row } : row)) | |||||
| ); | |||||
| }; | |||||
| const handleInputChange = (id: number, field: keyof T, value: string | number[]) => { | |||||
| setEditedItems((prev) => | |||||
| prev.map((item) => | |||||
| item.id === id ? { ...item, [field]: value } : item | |||||
| ) | |||||
| ); | |||||
| }; | |||||
| const handleDeleteClick = (id: number) => { | |||||
| // Implement delete logic here | |||||
| setEditedItems((prev) => prev.filter(item => item.id !== id)); | |||||
| }; | |||||
| useEffect(() => { | |||||
| console.log("[debug] isEdit in table", isEdit) | |||||
| //TODO: switch all record to not in edit mode and save the changes | |||||
| if (!isEdit) { | |||||
| editedItems?.forEach(item => { | |||||
| // Call save logic here | |||||
| // console.log("Saving item:", item); | |||||
| // Reset editing state if needed | |||||
| }); | |||||
| setEditingRowId(null); | |||||
| } | |||||
| }, [isEdit]) | |||||
| function isRoughType( | |||||
| type: ScheduleType | |||||
| ): type is "rough" { | |||||
| return type === "rough"; | |||||
| } | |||||
| function isDetailType( | |||||
| type: ScheduleType | |||||
| ): type is "detail" { | |||||
| return type === "detail"; | |||||
| } | |||||
| function Row(props: { row: T }) { | |||||
| const { row } = props; | |||||
| const [open, setOpen] = useState(false); | |||||
| // console.log(row) | |||||
| return ( | |||||
| <> | |||||
| <TableRow hover tabIndex={-1} key={row.id}> | |||||
| {isDetailType(type) && <TableCell> | |||||
| <IconButton disabled={!isEdit}> | |||||
| <PlayCircleOutlineIcon /> | |||||
| </IconButton> | |||||
| </TableCell>} | |||||
| { | |||||
| (isEditable || hasCollapse) && <TableCell> | |||||
| {(editingRowId === row.id) ? ( | |||||
| <> | |||||
| { | |||||
| isDetailType(type) && isEditable && <IconButton disabled={!isEdit} onClick={() => handleSaveClick(row)}> | |||||
| <SaveIcon /> | |||||
| </IconButton> | |||||
| } | |||||
| { | |||||
| isDetailType(type) && isEditable && <IconButton disabled={!isEdit} onClick={() => setEditingRowId(null)}> | |||||
| <CancelIcon /> | |||||
| </IconButton> | |||||
| } | |||||
| { | |||||
| hasCollapse && <IconButton | |||||
| aria-label="expand row" | |||||
| size="small" | |||||
| onClick={() => setOpen(!open)} | |||||
| > | |||||
| {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} | |||||
| <Typography>{t("View BoM")}</Typography> | |||||
| </IconButton> | |||||
| } | |||||
| </> | |||||
| ) : ( | |||||
| <> | |||||
| { | |||||
| isDetailType(type) && isEditable && <IconButton disabled={!isEdit} | |||||
| onClick={() => handleEditClick(row.id as number)}> | |||||
| <EditIcon /> | |||||
| </IconButton> | |||||
| } | |||||
| { | |||||
| isDetailType(type) && isEditable && <IconButton disabled={!isEdit} | |||||
| onClick={() => handleDeleteClick(row.id as number)}> | |||||
| <DeleteIcon /> | |||||
| </IconButton> | |||||
| } | |||||
| { | |||||
| hasCollapse && <IconButton | |||||
| aria-label="expand row" | |||||
| size="small" | |||||
| onClick={() => setOpen(!open)} | |||||
| > | |||||
| {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} | |||||
| <Typography>{t("View BoM")}</Typography> | |||||
| </IconButton> | |||||
| } | |||||
| </> | |||||
| )} | |||||
| </TableCell> | |||||
| } | |||||
| {columns.map((column, idx) => { | |||||
| const columnName = column.field; | |||||
| return ( | |||||
| <TableCell key={`${columnName.toString()}-${idx}`}> | |||||
| {editingRowId === row.id ? ( | |||||
| (() => { | |||||
| switch (column.type) { | |||||
| case 'input': | |||||
| return ( | |||||
| <TextField | |||||
| hiddenLabel={true} | |||||
| fullWidth | |||||
| defaultValue={row[columnName] as string} | |||||
| onChange={(e) => handleInputChange(row.id as number, columnName, e.target.value)} | |||||
| /> | |||||
| ); | |||||
| // case 'multi-select': | |||||
| // //TODO: May need update if use | |||||
| // return ( | |||||
| // <MultiSelect | |||||
| // //label={column.label} | |||||
| // options={column.options ?? []} | |||||
| // selectedValues={[]} | |||||
| // onChange={(selectedValues) => handleInputChange(row.id as number, columnName, selectedValues)} | |||||
| // /> | |||||
| // ); | |||||
| case 'read-only': | |||||
| return ( | |||||
| <span> | |||||
| {row[columnName] as string} | |||||
| </span> | |||||
| ); | |||||
| default: | |||||
| return null; // Handle any default case if needed | |||||
| } | |||||
| })() | |||||
| ) : ( | |||||
| column.renderCell ? | |||||
| <div style={column.style}> | |||||
| {column.renderCell(row)} | |||||
| </div> | |||||
| : | |||||
| <div style={column.style}> | |||||
| <span onDoubleClick={() => isEdit && handleEditClick(row.id as number)}> | |||||
| {row[columnName] as String} | |||||
| </span> | |||||
| </div> | |||||
| )} | |||||
| </TableCell> | |||||
| ); | |||||
| })} | |||||
| </TableRow> | |||||
| <TableRow> | |||||
| { | |||||
| hasCollapse && | |||||
| <TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}> | |||||
| <Collapse in={open} timeout="auto" unmountOnExit> | |||||
| <Table> | |||||
| <TableBody> | |||||
| <TableRow> | |||||
| <TableCell> | |||||
| <BomMaterialTable | |||||
| type={type} | |||||
| bomMaterial={(row as unknown as ProdScheduleLineResultByFg).bomMaterials} | |||||
| /> | |||||
| </TableCell> | |||||
| </TableRow> | |||||
| </TableBody> | |||||
| </Table> | |||||
| </Collapse> | |||||
| </TableCell> | |||||
| } | |||||
| </TableRow> | |||||
| </> | |||||
| ) | |||||
| } | |||||
| const table = ( | |||||
| <> | |||||
| <TableContainer sx={{ maxHeight: 440 }}> | |||||
| <Table stickyHeader> | |||||
| <TableHead> | |||||
| <TableRow> | |||||
| {isDetailType(type) && <TableCell>{t("Release")}</TableCell>} | |||||
| {(isEditable || hasCollapse) && <TableCell>{t("Actions")}</TableCell>} {/* Action Column Header */} | |||||
| {columns.map((column, idx) => ( | |||||
| <TableCell style={column.style} key={`${column.field.toString()}${idx}`}> | |||||
| {column.label} | |||||
| </TableCell> | |||||
| ))} | |||||
| </TableRow> | |||||
| </TableHead> | |||||
| <TableBody> | |||||
| {/* {(isAutoPaging ? editedItems.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) : editedItems).map((item) => ( */} | |||||
| {(editedItems?.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage))?.map((item) => ( | |||||
| <Row key={item.id} row={item} /> | |||||
| ))} | |||||
| </TableBody> | |||||
| </Table> | |||||
| </TableContainer> | |||||
| <TablePagination | |||||
| rowsPerPageOptions={[10, 25, 100]} | |||||
| component="div" | |||||
| // count={pagingController.totalCount === 0 ? editedItems.length : pagingController.totalCount} | |||||
| count={editedItems?.length ?? 0} | |||||
| rowsPerPage={rowsPerPage} | |||||
| page={page} | |||||
| onPageChange={handleChangePage} | |||||
| onRowsPerPageChange={handleChangeRowsPerPage} | |||||
| /> | |||||
| </> | |||||
| ); | |||||
| return noWrapper ? table : <Paper sx={{ overflow: "hidden" }}>{table}</Paper>; | |||||
| } | |||||
| export default ScheduleTable; | |||||
| @@ -0,0 +1 @@ | |||||
| export { default } from "./ScheduleTable" | |||||
| @@ -24,20 +24,20 @@ | |||||
| "Product Count": "產品數量", | "Product Count": "產品數量", | ||||
| "Scheduled At": "排程時間", | "Scheduled At": "排程時間", | ||||
| "Demand Forecast Period": "需求預測期間", | "Demand Forecast Period": "需求預測期間", | ||||
| "FG & Material Demand Forecast Detail": "FG 及材料需求預測詳情", | |||||
| "FG & Material Demand Forecast": "FG 及材料需求預測", | |||||
| "FG & Material Demand Forecast Detail": "成品及物料需求預測詳情", | |||||
| "FG & Material Demand Forecast": "成品及物料需求預測", | |||||
| "Total Estimated Demand Qty": "總預估需求量", | "Total Estimated Demand Qty": "總預估需求量", | ||||
| "View By FG": "依 FG 分類", | |||||
| "View By Material": "依材料分類", | |||||
| "View By FG": "依成品分類", | |||||
| "View By Material": "依物料分類", | |||||
| " (Selected)": " (已選擇)", | " (Selected)": " (已選擇)", | ||||
| "Total FG Item": "總 FG 項目", | |||||
| "Total FG Item": "總成品項目", | |||||
| "Release": "發佈", | "Release": "發佈", | ||||
| "Actions": "動作", | "Actions": "動作", | ||||
| "FG Demand List (7 Days)": "FG 需求列表(7 天)", | |||||
| "FG Demand Date": "FG 需求日期", | |||||
| "FG Demand Qty": "FG 需求數量", | |||||
| "Material Demand Date": "材料需求日期", | |||||
| "Material Demand List": "材料需求列表", | |||||
| "FG Demand List (7 Days)": "成品需求列表(7 天)", | |||||
| "FG Demand Date": "成品需求日期", | |||||
| "FG Demand Qty": "成品需求數量", | |||||
| "Material Demand Date": "物料需求日期", | |||||
| "Material Demand List": "物料需求列表", | |||||
| "Available Qty": "可用數量", | "Available Qty": "可用數量", | ||||
| "Demand Qty": "需求數量", | "Demand Qty": "需求數量", | ||||
| "Confirm": "確認", | "Confirm": "確認", | ||||
| @@ -50,7 +50,7 @@ | |||||
| "Selected": "已選擇", | "Selected": "已選擇", | ||||
| "Unselected": "未選擇", | "Unselected": "未選擇", | ||||
| "status": "狀態", | "status": "狀態", | ||||
| "Material Demand List (7 Days)": "材料需求列表(7 天)", | |||||
| "Material Demand List (7 Days)": "物料需求列表(7 天)", | |||||
| "Mon": "週一", | "Mon": "週一", | ||||
| "Tue": "週二", | "Tue": "週二", | ||||
| "Wed": "週三", | "Wed": "週三", | ||||
| @@ -59,14 +59,15 @@ | |||||
| "Sat": "週六", | "Sat": "週六", | ||||
| "Sun": "週日", | "Sun": "週日", | ||||
| "Last Month Average Stock": "上個月平均庫存", | "Last Month Average Stock": "上個月平均庫存", | ||||
| "Last Month Average Sales": "上個月平均銷售", | |||||
| "Safety Stock": "安全庫存", | "Safety Stock": "安全庫存", | ||||
| "Demand Qty (7 Days)": "需求數量(7 天)", | "Demand Qty (7 Days)": "需求數量(7 天)", | ||||
| "Estimated Production Time": "預估生產時間", | "Estimated Production Time": "預估生產時間", | ||||
| "Production Priority": "生產優先順序", | "Production Priority": "生產優先順序", | ||||
| "View BoM": "查看 BoM", | |||||
| "View BoM": "查看物料清單", | |||||
| "Date": "日期", | "Date": "日期", | ||||
| "Detail Scheduling": "詳細排程", | "Detail Scheduling": "詳細排程", | ||||
| "FG Production Schedule": "FG 生產排程", | |||||
| "FG Production Schedule": "成品生產排程", | |||||
| "Production Date": "生產日期", | "Production Date": "生產日期", | ||||
| "Total Job Order": "總工單數量", | "Total Job Order": "總工單數量", | ||||
| "Total Production Qty": "總生產數量", | "Total Production Qty": "總生產數量", | ||||
| @@ -76,6 +77,6 @@ | |||||
| "Job Status": "工單狀態", | "Job Status": "工單狀態", | ||||
| "Job Priority": "工單優先順序", | "Job Priority": "工單優先順序", | ||||
| "Job Date": "工單日期", | "Job Date": "工單日期", | ||||
| "Job Qty": "工單數量" | |||||
| "Job Qty": "工單數量", | |||||
| "mat": "物料" | |||||
| } | } | ||||