Browse Source

[Prod Schedule] Update rough

master
cyril.tsui 1 month ago
parent
commit
9648260537
7 changed files with 53 additions and 46 deletions
  1. +14
    -10
      src/app/(main)/scheduling/rough/page.tsx
  2. +10
    -9
      src/components/RoughSchedule/RoughSchedileSearchView.tsx
  3. +3
    -2
      src/components/RoughSchedule/RoughScheduleWrapper.tsx
  4. +2
    -2
      src/components/ScheduleTable/BomMaterialTable.tsx
  5. +11
    -11
      src/components/ScheduleTable/ScheduleTable.tsx
  6. +10
    -10
      src/components/SearchBox/SearchBox.tsx
  7. +3
    -2
      src/i18n/zh/schedule.json

+ 14
- 10
src/app/(main)/scheduling/rough/page.tsx View File

@@ -1,6 +1,7 @@
// import { TypeEnum } from "@/app/utils/typeEnum"; // import { TypeEnum } from "@/app/utils/typeEnum";
// import RoughSchedule from "@/components/RoughSchedule"; // import RoughSchedule from "@/components/RoughSchedule";
// import { getServerI18n, I18nProvider } from "@/i18n"; // import { getServerI18n, I18nProvider } from "@/i18n";
import { testRoughSchedule } from "@/app/api/scheduling/actions";
import { TypeEnum } from "../../../../app/utils/typeEnum"; import { TypeEnum } from "../../../../app/utils/typeEnum";
import RoughSchedule from "../../../../components/RoughSchedule"; import RoughSchedule from "../../../../components/RoughSchedule";
import { getServerI18n, I18nProvider } from "../../../../i18n"; import { getServerI18n, I18nProvider } from "../../../../i18n";
@@ -22,6 +23,10 @@ const roughScheduling: React.FC = async () => {
const type = "rough" const type = "rough"
// preloadClaims(); // preloadClaims();


// async function testingRoughSchedule() {
// await testRoughSchedule();
// }

return ( return (
<> <>
<Stack <Stack
@@ -33,19 +38,18 @@ const roughScheduling: React.FC = async () => {
<Typography variant="h4" marginInlineEnd={2}> <Typography variant="h4" marginInlineEnd={2}>
{t("Demand Forecast")} {t("Demand Forecast")}
</Typography> </Typography>
{/* <Button {/* <Button
variant="contained"
startIcon={<Add />}
LinkComponent={Link}
href="product/create"
>
{t("Create product")}
</Button> */}
variant="contained"
startIcon={<Add />}
onClick={() => testingRoughSchedule}
>
{t("Test Rough Scheduling")}
</Button> */}
</Stack> </Stack>
<I18nProvider namespaces={["schedule", "common","items","project"]}>
<I18nProvider namespaces={["schedule", "common"]}>
<Suspense fallback={<RoughSchedule.Loading />}> <Suspense fallback={<RoughSchedule.Loading />}>
<RoughSchedule type={type}/>
<RoughSchedule type={type} />
</Suspense> </Suspense>
</I18nProvider> </I18nProvider>
</> </>


+ 10
- 9
src/components/RoughSchedule/RoughSchedileSearchView.tsx View File

@@ -19,6 +19,7 @@ import { arrayToDateString, decimalFormatter } from "@/app/utils/formatUtil";
import { isEqual, uniqBy } from "lodash"; import { isEqual, uniqBy } from "lodash";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { defaultPagingController } from "../SearchResults/SearchResults"; import { defaultPagingController } from "../SearchResults/SearchResults";
import { ScheduleType } from "@/app/api/scheduling";


// type RecordStructure ={ // type RecordStructure ={
// id: number, // id: number,
@@ -27,17 +28,17 @@ import { defaultPagingController } from "../SearchResults/SearchResults";
// }; // };


type Props = { type Props = {
type: SearchProdSchedule["type"];
type: ScheduleType;
// initProdSchedules: ProdScheduleResultByPage; // initProdSchedules: ProdScheduleResultByPage;
defaultInputs: SearchProdSchedule; defaultInputs: SearchProdSchedule;
}; };


type SearchQuery = Partial<Omit<SearchProdSchedule, "id" | "type" | "pageSize" | "pageNum">>;
type SearchQuery = Partial<Omit<SearchProdSchedule, "id" | "types" | "pageSize" | "pageNum">>;
type SearchParamNames = keyof SearchQuery; type SearchParamNames = keyof SearchQuery;


const RSOverview: React.FC<Props> = ({ type, defaultInputs }) => { const RSOverview: React.FC<Props> = ({ type, defaultInputs }) => {
const [filteredSchedules, setFilteredSchedules] = useState<ProdScheduleResult[]>([]); const [filteredSchedules, setFilteredSchedules] = useState<ProdScheduleResult[]>([]);
const { t } = useTranslation("scheduling");
const { t } = useTranslation("schedule");
const router = useRouter(); const router = useRouter();
// const [filterObj, setFilterObj] = useState({}); // const [filterObj, setFilterObj] = useState({});
// const [tempSelectedValue, setTempSelectedValue] = useState({}); // const [tempSelectedValue, setTempSelectedValue] = useState({});
@@ -64,12 +65,12 @@ const RSOverview: React.FC<Props> = ({ type, defaultInputs }) => {
// [router] // [router]
// ); // );


const onDeleteClick = useCallback(
(item: ItemsResult) => { },
[router]
);
// const onDeleteClick = useCallback(
// (item: ItemsResult) => { },
// [router]
// );


const onDetailClick = (record: any) => {
const onDetailClick = (record: ProdScheduleResult) => {
console.log("[debug] record", record); console.log("[debug] record", record);
router.push(`/scheduling/rough/edit?id=${record.id}`); router.push(`/scheduling/rough/edit?id=${record.id}`);
} }
@@ -127,7 +128,7 @@ const RSOverview: React.FC<Props> = ({ type, defaultInputs }) => {
schedulePeriod: dayjs(query?.schedulePeriod).isValid() ? query?.schedulePeriod : undefined, schedulePeriod: dayjs(query?.schedulePeriod).isValid() ? query?.schedulePeriod : undefined,
schedulePeriodTo: dayjs(query?.schedulePeriodTo).isValid() ? query?.schedulePeriodTo : undefined, schedulePeriodTo: dayjs(query?.schedulePeriodTo).isValid() ? query?.schedulePeriodTo : undefined,
totalEstProdCount: query?.totalEstProdCount ? Number(query?.totalEstProdCount) : undefined, totalEstProdCount: query?.totalEstProdCount ? Number(query?.totalEstProdCount) : undefined,
type: "rough",
types: ["rough"],
pageNum: pagingController.pageNum - 1, pageNum: pagingController.pageNum - 1,
pageSize: pagingController.pageSize pageSize: pagingController.pageSize
} }


+ 3
- 2
src/components/RoughSchedule/RoughScheduleWrapper.tsx View File

@@ -2,13 +2,14 @@ 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"; import { SearchProdSchedule, fetchProdSchedules } from "@/app/api/scheduling/actions";
import { ScheduleType } from "@/app/api/scheduling";


interface SubComponents { interface SubComponents {
Loading: typeof RoughScheduleLoading; Loading: typeof RoughScheduleLoading;
} }


type Props = { type Props = {
type: SearchProdSchedule["type"]
type: ScheduleType
}; };


const RoughScheduleWrapper: React.FC<Props> & SubComponents = async ( const RoughScheduleWrapper: React.FC<Props> & SubComponents = async (
@@ -18,7 +19,7 @@ const RoughScheduleWrapper: React.FC<Props> & SubComponents = async (
) => { ) => {
// console.log(type) // console.log(type)
const defaultInputs: SearchProdSchedule = { const defaultInputs: SearchProdSchedule = {
type: "rough"
types: ["rough"]
} }


// const [ // const [


+ 2
- 2
src/components/ScheduleTable/BomMaterialTable.tsx View File

@@ -36,14 +36,14 @@ import { useSearchParams } from "next/navigation";
import { decimalFormatter } from "@/app/utils/formatUtil"; import { decimalFormatter } from "@/app/utils/formatUtil";
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
import HighlightOffIcon from '@mui/icons-material/HighlightOff'; import HighlightOffIcon from '@mui/icons-material/HighlightOff';
import { ProdScheduleLineBomMaterialResult, ScheduleType } from "@/app/api/scheduling";
import { RoughProdScheduleLineBomMaterialResult, ScheduleType } from "@/app/api/scheduling";


interface ResultWithId { interface ResultWithId {
id: number; id: number;
} }


interface Props { interface Props {
bomMaterial: ProdScheduleLineBomMaterialResult[];
bomMaterial: RoughProdScheduleLineBomMaterialResult[];
type: ScheduleType type: ScheduleType
} }




+ 11
- 11
src/components/ScheduleTable/ScheduleTable.tsx View File

@@ -23,7 +23,7 @@ import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil";
import PlayCircleOutlineIcon from '@mui/icons-material/PlayCircleOutline'; import PlayCircleOutlineIcon from '@mui/icons-material/PlayCircleOutline';
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { ProdScheduleLineBomMaterialResult, ProdScheduleLineResultByFg, ProdScheduleResult, ScheduleType } from "@/app/api/scheduling";
import { RoughProdScheduleLineBomMaterialResult, RoughProdScheduleLineResultByFg, RoughProdScheduleResult, ScheduleType } from "@/app/api/scheduling";


export interface ResultWithId { export interface ResultWithId {
id: string | number; id: string | number;
@@ -144,10 +144,10 @@ function ScheduleTable<T extends ResultWithId>({
return type === "rough"; return type === "rough";
} }


function isDetailType(
function isDetailedType(
type: ScheduleType type: ScheduleType
): type is "detail" {
return type === "detail";
): type is "detailed" {
return type === "detailed";
} }


function Row(props: { row: T }) { function Row(props: { row: T }) {
@@ -157,7 +157,7 @@ function ScheduleTable<T extends ResultWithId>({
return ( return (
<> <>
<TableRow hover tabIndex={-1} key={row.id}> <TableRow hover tabIndex={-1} key={row.id}>
{isDetailType(type) && <TableCell>
{isDetailedType(type) && <TableCell>
<IconButton disabled={!isEdit}> <IconButton disabled={!isEdit}>
<PlayCircleOutlineIcon /> <PlayCircleOutlineIcon />
</IconButton> </IconButton>
@@ -167,12 +167,12 @@ function ScheduleTable<T extends ResultWithId>({
{(editingRowId === row.id) ? ( {(editingRowId === row.id) ? (
<> <>
{ {
isDetailType(type) && isEditable && <IconButton disabled={!isEdit} onClick={() => handleSaveClick(row)}>
isDetailedType(type) && isEditable && <IconButton disabled={!isEdit} onClick={() => handleSaveClick(row)}>
<SaveIcon /> <SaveIcon />
</IconButton> </IconButton>
} }
{ {
isDetailType(type) && isEditable && <IconButton disabled={!isEdit} onClick={() => setEditingRowId(null)}>
isDetailedType(type) && isEditable && <IconButton disabled={!isEdit} onClick={() => setEditingRowId(null)}>
<CancelIcon /> <CancelIcon />
</IconButton> </IconButton>
} }
@@ -190,13 +190,13 @@ function ScheduleTable<T extends ResultWithId>({
) : ( ) : (
<> <>
{ {
isDetailType(type) && isEditable && <IconButton disabled={!isEdit}
isDetailedType(type) && isEditable && <IconButton disabled={!isEdit}
onClick={() => handleEditClick(row.id as number)}> onClick={() => handleEditClick(row.id as number)}>
<EditIcon /> <EditIcon />
</IconButton> </IconButton>
} }
{ {
isDetailType(type) && isEditable && <IconButton disabled={!isEdit}
isDetailedType(type) && isEditable && <IconButton disabled={!isEdit}
onClick={() => handleDeleteClick(row.id as number)}> onClick={() => handleDeleteClick(row.id as number)}>
<DeleteIcon /> <DeleteIcon />
</IconButton> </IconButton>
@@ -278,7 +278,7 @@ function ScheduleTable<T extends ResultWithId>({
<TableCell> <TableCell>
<BomMaterialTable <BomMaterialTable
type={type} type={type}
bomMaterial={(row as unknown as ProdScheduleLineResultByFg).bomMaterials}
bomMaterial={(row as unknown as RoughProdScheduleLineResultByFg).bomMaterials}
/> />
</TableCell> </TableCell>
</TableRow> </TableRow>
@@ -298,7 +298,7 @@ function ScheduleTable<T extends ResultWithId>({
<Table stickyHeader> <Table stickyHeader>
<TableHead> <TableHead>
<TableRow> <TableRow>
{isDetailType(type) && <TableCell>{t("Release")}</TableCell>}
{isDetailedType(type) && <TableCell>{t("Release")}</TableCell>}
{(isEditable || hasCollapse) && <TableCell>{t("Actions")}</TableCell>} {/* Action Column Header */} {(isEditable || hasCollapse) && <TableCell>{t("Actions")}</TableCell>} {/* Action Column Header */}
{columns.map((column, idx) => ( {columns.map((column, idx) => (
<TableCell style={column.style} key={`${column.field.toString()}${idx}`}> <TableCell style={column.style} key={`${column.field.toString()}${idx}`}>


+ 10
- 10
src/components/SearchBox/SearchBox.tsx View File

@@ -196,7 +196,7 @@ function SearchBox<T extends string>({
<Grid key={c.paramName} item xs={6}> <Grid key={c.paramName} item xs={6}>
{c.type === "text" && ( {c.type === "text" && (
<TextField <TextField
label={c.label}
label={t(c.label)}
fullWidth fullWidth
onChange={makeInputChangeHandler(c.paramName)} onChange={makeInputChangeHandler(c.paramName)}
value={inputs[c.paramName]} value={inputs[c.paramName]}
@@ -204,7 +204,7 @@ function SearchBox<T extends string>({
)} )}
{c.type === "multi-select" && ( {c.type === "multi-select" && (
<MultiSelect <MultiSelect
label={c.label}
label={t(c.label)}
options={c?.options} options={c?.options}
selectedValues={c.filterObj?.[c.paramName] ?? []} selectedValues={c.filterObj?.[c.paramName] ?? []}
onChange={c.handleSelectionChange} onChange={c.handleSelectionChange}
@@ -213,9 +213,9 @@ function SearchBox<T extends string>({
)} )}
{c.type === "select" && ( {c.type === "select" && (
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>{c.label}</InputLabel>
<InputLabel>{t(c.label)}</InputLabel>
<Select <Select
label={c.label}
label={t(c.label)}
onChange={makeSelectChangeHandler(c.paramName)} onChange={makeSelectChangeHandler(c.paramName)}
value={inputs[c.paramName]} value={inputs[c.paramName]}
> >
@@ -230,9 +230,9 @@ function SearchBox<T extends string>({
)} )}
{c.type === "select-labelled" && ( {c.type === "select-labelled" && (
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>{c.label}</InputLabel>
<InputLabel>{t(c.label)}</InputLabel>
<Select <Select
label={c.label}
label={t(c.label)}
onChange={makeSelectChangeHandler(c.paramName)} onChange={makeSelectChangeHandler(c.paramName)}
value={inputs[c.paramName]} value={inputs[c.paramName]}
> >
@@ -312,7 +312,7 @@ function SearchBox<T extends string>({
</MenuItem> </MenuItem>
); );
}} }}
renderInput={(params) => <TextField {...params} variant="outlined" label={c.label} />}
renderInput={(params) => <TextField {...params} variant="outlined" label={t(c.label)} />}
/> />
)} )}
{c.type === "dateRange" && ( {c.type === "dateRange" && (
@@ -324,7 +324,7 @@ function SearchBox<T extends string>({
<Box display="flex"> <Box display="flex">
<FormControl fullWidth> <FormControl fullWidth>
<DatePicker <DatePicker
label={c.label}
label={t(c.label)}
onChange={makeDateChangeHandler(c.paramName)} onChange={makeDateChangeHandler(c.paramName)}
value={dayjs(inputs[c.paramName]).isValid() ? dayjs(inputs[c.paramName]) : null} value={dayjs(inputs[c.paramName]).isValid() ? dayjs(inputs[c.paramName]) : null}
/> />
@@ -339,7 +339,7 @@ function SearchBox<T extends string>({
</Box> </Box>
<FormControl fullWidth> <FormControl fullWidth>
<DatePicker <DatePicker
label={c.label2}
label={c.label2 ? t(c.label2) : null}
onChange={makeDateToChangeHandler(c.paramName)} onChange={makeDateToChangeHandler(c.paramName)}
value={dayjs(inputs[`${c.paramName}To`]).isValid() ? dayjs(inputs[`${c.paramName}To`]) : null} value={dayjs(inputs[`${c.paramName}To`]).isValid() ? dayjs(inputs[`${c.paramName}To`]) : null}
/> />
@@ -356,7 +356,7 @@ function SearchBox<T extends string>({
<Box display="flex"> <Box display="flex">
<FormControl fullWidth> <FormControl fullWidth>
<DatePicker <DatePicker
label={c.label}
label={t(c.label)}
onChange={makeDateChangeHandler(c.paramName)} onChange={makeDateChangeHandler(c.paramName)}
/> />
</FormControl> </FormControl>


+ 3
- 2
src/i18n/zh/schedule.json View File

@@ -10,7 +10,8 @@
"Demand Forecast Detail": "需求預測詳情", "Demand Forecast Detail": "需求預測詳情",
"Details": "詳情", "Details": "詳情",
"Schedule": "排程", "Schedule": "排程",
"Schedule Period": "排程期間",
"Schedule Period": "排程時期",
"Schedule Period To": "排程時期至",
"Schedule Detail": "排程詳情", "Schedule Detail": "排程詳情",
"Schedule At": "排程時間", "Schedule At": "排程時間",
"Search": "搜尋", "Search": "搜尋",
@@ -23,7 +24,7 @@
"CODE": "編號", "CODE": "編號",
"Product Count": "產品數量", "Product Count": "產品數量",
"Scheduled At": "排程時間", "Scheduled At": "排程時間",
"Demand Forecast Period": "需求預測期",
"Demand Forecast Period": "需求預測期",
"FG & Material Demand Forecast Detail": "成品及物料需求預測詳情", "FG & Material Demand Forecast Detail": "成品及物料需求預測詳情",
"FG & Material Demand Forecast": "成品及物料需求預測", "FG & Material Demand Forecast": "成品及物料需求預測",
"Total Estimated Demand Qty": "總預估需求量", "Total Estimated Demand Qty": "總預估需求量",


Loading…
Cancel
Save