@@ -1,6 +1,7 @@ | |||
// import { TypeEnum } from "@/app/utils/typeEnum"; | |||
// import RoughSchedule from "@/components/RoughSchedule"; | |||
// import { getServerI18n, I18nProvider } from "@/i18n"; | |||
import { testRoughSchedule } from "@/app/api/scheduling/actions"; | |||
import { TypeEnum } from "../../../../app/utils/typeEnum"; | |||
import RoughSchedule from "../../../../components/RoughSchedule"; | |||
import { getServerI18n, I18nProvider } from "../../../../i18n"; | |||
@@ -22,6 +23,10 @@ const roughScheduling: React.FC = async () => { | |||
const type = "rough" | |||
// preloadClaims(); | |||
// async function testingRoughSchedule() { | |||
// await testRoughSchedule(); | |||
// } | |||
return ( | |||
<> | |||
<Stack | |||
@@ -33,19 +38,18 @@ const roughScheduling: React.FC = async () => { | |||
<Typography variant="h4" marginInlineEnd={2}> | |||
{t("Demand Forecast")} | |||
</Typography> | |||
{/* <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> | |||
<I18nProvider namespaces={["schedule", "common","items","project"]}> | |||
<I18nProvider namespaces={["schedule", "common"]}> | |||
<Suspense fallback={<RoughSchedule.Loading />}> | |||
<RoughSchedule type={type}/> | |||
<RoughSchedule type={type} /> | |||
</Suspense> | |||
</I18nProvider> | |||
</> | |||
@@ -19,6 +19,7 @@ import { arrayToDateString, decimalFormatter } from "@/app/utils/formatUtil"; | |||
import { isEqual, uniqBy } from "lodash"; | |||
import dayjs from "dayjs"; | |||
import { defaultPagingController } from "../SearchResults/SearchResults"; | |||
import { ScheduleType } from "@/app/api/scheduling"; | |||
// type RecordStructure ={ | |||
// id: number, | |||
@@ -27,17 +28,17 @@ import { defaultPagingController } from "../SearchResults/SearchResults"; | |||
// }; | |||
type Props = { | |||
type: SearchProdSchedule["type"]; | |||
type: ScheduleType; | |||
// initProdSchedules: ProdScheduleResultByPage; | |||
defaultInputs: SearchProdSchedule; | |||
}; | |||
type SearchQuery = Partial<Omit<SearchProdSchedule, "id" | "type" | "pageSize" | "pageNum">>; | |||
type SearchQuery = Partial<Omit<SearchProdSchedule, "id" | "types" | "pageSize" | "pageNum">>; | |||
type SearchParamNames = keyof SearchQuery; | |||
const RSOverview: React.FC<Props> = ({ type, defaultInputs }) => { | |||
const [filteredSchedules, setFilteredSchedules] = useState<ProdScheduleResult[]>([]); | |||
const { t } = useTranslation("scheduling"); | |||
const { t } = useTranslation("schedule"); | |||
const router = useRouter(); | |||
// const [filterObj, setFilterObj] = useState({}); | |||
// const [tempSelectedValue, setTempSelectedValue] = useState({}); | |||
@@ -64,12 +65,12 @@ const RSOverview: React.FC<Props> = ({ type, defaultInputs }) => { | |||
// [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); | |||
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, | |||
schedulePeriodTo: dayjs(query?.schedulePeriodTo).isValid() ? query?.schedulePeriodTo : undefined, | |||
totalEstProdCount: query?.totalEstProdCount ? Number(query?.totalEstProdCount) : undefined, | |||
type: "rough", | |||
types: ["rough"], | |||
pageNum: pagingController.pageNum - 1, | |||
pageSize: pagingController.pageSize | |||
} | |||
@@ -2,13 +2,14 @@ import { fetchAllItems } from "@/app/api/settings/item"; | |||
import { RoughScheduleLoading } from "./RoughScheduleLoading"; | |||
import RSOverview from "./RoughSchedileSearchView"; | |||
import { SearchProdSchedule, fetchProdSchedules } from "@/app/api/scheduling/actions"; | |||
import { ScheduleType } from "@/app/api/scheduling"; | |||
interface SubComponents { | |||
Loading: typeof RoughScheduleLoading; | |||
} | |||
type Props = { | |||
type: SearchProdSchedule["type"] | |||
type: ScheduleType | |||
}; | |||
const RoughScheduleWrapper: React.FC<Props> & SubComponents = async ( | |||
@@ -18,7 +19,7 @@ const RoughScheduleWrapper: React.FC<Props> & SubComponents = async ( | |||
) => { | |||
// console.log(type) | |||
const defaultInputs: SearchProdSchedule = { | |||
type: "rough" | |||
types: ["rough"] | |||
} | |||
// const [ | |||
@@ -36,14 +36,14 @@ 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"; | |||
import { RoughProdScheduleLineBomMaterialResult, ScheduleType } from "@/app/api/scheduling"; | |||
interface ResultWithId { | |||
id: number; | |||
} | |||
interface Props { | |||
bomMaterial: ProdScheduleLineBomMaterialResult[]; | |||
bomMaterial: RoughProdScheduleLineBomMaterialResult[]; | |||
type: ScheduleType | |||
} | |||
@@ -23,7 +23,7 @@ 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"; | |||
import { RoughProdScheduleLineBomMaterialResult, RoughProdScheduleLineResultByFg, RoughProdScheduleResult, ScheduleType } from "@/app/api/scheduling"; | |||
export interface ResultWithId { | |||
id: string | number; | |||
@@ -144,10 +144,10 @@ function ScheduleTable<T extends ResultWithId>({ | |||
return type === "rough"; | |||
} | |||
function isDetailType( | |||
function isDetailedType( | |||
type: ScheduleType | |||
): type is "detail" { | |||
return type === "detail"; | |||
): type is "detailed" { | |||
return type === "detailed"; | |||
} | |||
function Row(props: { row: T }) { | |||
@@ -157,7 +157,7 @@ function ScheduleTable<T extends ResultWithId>({ | |||
return ( | |||
<> | |||
<TableRow hover tabIndex={-1} key={row.id}> | |||
{isDetailType(type) && <TableCell> | |||
{isDetailedType(type) && <TableCell> | |||
<IconButton disabled={!isEdit}> | |||
<PlayCircleOutlineIcon /> | |||
</IconButton> | |||
@@ -167,12 +167,12 @@ function ScheduleTable<T extends ResultWithId>({ | |||
{(editingRowId === row.id) ? ( | |||
<> | |||
{ | |||
isDetailType(type) && isEditable && <IconButton disabled={!isEdit} onClick={() => handleSaveClick(row)}> | |||
isDetailedType(type) && isEditable && <IconButton disabled={!isEdit} onClick={() => handleSaveClick(row)}> | |||
<SaveIcon /> | |||
</IconButton> | |||
} | |||
{ | |||
isDetailType(type) && isEditable && <IconButton disabled={!isEdit} onClick={() => setEditingRowId(null)}> | |||
isDetailedType(type) && isEditable && <IconButton disabled={!isEdit} onClick={() => setEditingRowId(null)}> | |||
<CancelIcon /> | |||
</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)}> | |||
<EditIcon /> | |||
</IconButton> | |||
} | |||
{ | |||
isDetailType(type) && isEditable && <IconButton disabled={!isEdit} | |||
isDetailedType(type) && isEditable && <IconButton disabled={!isEdit} | |||
onClick={() => handleDeleteClick(row.id as number)}> | |||
<DeleteIcon /> | |||
</IconButton> | |||
@@ -278,7 +278,7 @@ function ScheduleTable<T extends ResultWithId>({ | |||
<TableCell> | |||
<BomMaterialTable | |||
type={type} | |||
bomMaterial={(row as unknown as ProdScheduleLineResultByFg).bomMaterials} | |||
bomMaterial={(row as unknown as RoughProdScheduleLineResultByFg).bomMaterials} | |||
/> | |||
</TableCell> | |||
</TableRow> | |||
@@ -298,7 +298,7 @@ function ScheduleTable<T extends ResultWithId>({ | |||
<Table stickyHeader> | |||
<TableHead> | |||
<TableRow> | |||
{isDetailType(type) && <TableCell>{t("Release")}</TableCell>} | |||
{isDetailedType(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}`}> | |||
@@ -196,7 +196,7 @@ function SearchBox<T extends string>({ | |||
<Grid key={c.paramName} item xs={6}> | |||
{c.type === "text" && ( | |||
<TextField | |||
label={c.label} | |||
label={t(c.label)} | |||
fullWidth | |||
onChange={makeInputChangeHandler(c.paramName)} | |||
value={inputs[c.paramName]} | |||
@@ -204,7 +204,7 @@ function SearchBox<T extends string>({ | |||
)} | |||
{c.type === "multi-select" && ( | |||
<MultiSelect | |||
label={c.label} | |||
label={t(c.label)} | |||
options={c?.options} | |||
selectedValues={c.filterObj?.[c.paramName] ?? []} | |||
onChange={c.handleSelectionChange} | |||
@@ -213,9 +213,9 @@ function SearchBox<T extends string>({ | |||
)} | |||
{c.type === "select" && ( | |||
<FormControl fullWidth> | |||
<InputLabel>{c.label}</InputLabel> | |||
<InputLabel>{t(c.label)}</InputLabel> | |||
<Select | |||
label={c.label} | |||
label={t(c.label)} | |||
onChange={makeSelectChangeHandler(c.paramName)} | |||
value={inputs[c.paramName]} | |||
> | |||
@@ -230,9 +230,9 @@ function SearchBox<T extends string>({ | |||
)} | |||
{c.type === "select-labelled" && ( | |||
<FormControl fullWidth> | |||
<InputLabel>{c.label}</InputLabel> | |||
<InputLabel>{t(c.label)}</InputLabel> | |||
<Select | |||
label={c.label} | |||
label={t(c.label)} | |||
onChange={makeSelectChangeHandler(c.paramName)} | |||
value={inputs[c.paramName]} | |||
> | |||
@@ -312,7 +312,7 @@ function SearchBox<T extends string>({ | |||
</MenuItem> | |||
); | |||
}} | |||
renderInput={(params) => <TextField {...params} variant="outlined" label={c.label} />} | |||
renderInput={(params) => <TextField {...params} variant="outlined" label={t(c.label)} />} | |||
/> | |||
)} | |||
{c.type === "dateRange" && ( | |||
@@ -324,7 +324,7 @@ function SearchBox<T extends string>({ | |||
<Box display="flex"> | |||
<FormControl fullWidth> | |||
<DatePicker | |||
label={c.label} | |||
label={t(c.label)} | |||
onChange={makeDateChangeHandler(c.paramName)} | |||
value={dayjs(inputs[c.paramName]).isValid() ? dayjs(inputs[c.paramName]) : null} | |||
/> | |||
@@ -339,7 +339,7 @@ function SearchBox<T extends string>({ | |||
</Box> | |||
<FormControl fullWidth> | |||
<DatePicker | |||
label={c.label2} | |||
label={c.label2 ? t(c.label2) : null} | |||
onChange={makeDateToChangeHandler(c.paramName)} | |||
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"> | |||
<FormControl fullWidth> | |||
<DatePicker | |||
label={c.label} | |||
label={t(c.label)} | |||
onChange={makeDateChangeHandler(c.paramName)} | |||
/> | |||
</FormControl> | |||
@@ -10,7 +10,8 @@ | |||
"Demand Forecast Detail": "需求預測詳情", | |||
"Details": "詳情", | |||
"Schedule": "排程", | |||
"Schedule Period": "排程期間", | |||
"Schedule Period": "排程時期", | |||
"Schedule Period To": "排程時期至", | |||
"Schedule Detail": "排程詳情", | |||
"Schedule At": "排程時間", | |||
"Search": "搜尋", | |||
@@ -23,7 +24,7 @@ | |||
"CODE": "編號", | |||
"Product Count": "產品數量", | |||
"Scheduled At": "排程時間", | |||
"Demand Forecast Period": "需求預測期間", | |||
"Demand Forecast Period": "需求預測時期", | |||
"FG & Material Demand Forecast Detail": "成品及物料需求預測詳情", | |||
"FG & Material Demand Forecast": "成品及物料需求預測", | |||
"Total Estimated Demand Qty": "總預估需求量", | |||