@@ -6,7 +6,7 @@ import { serverFetchJson } from "../../utils/fetchUtil"; | |||
import { BASE_API_URL } from "../../../config/api"; | |||
import { Uom } from "../settings/uom"; | |||
import { RecordsRes } from "../utils"; | |||
import { IQCItems } from "@/components/DashboardPage/QC/SupervisorQcApproval"; | |||
// import { IQCItems } from "@/components/DashboardPage/QC/SupervisorQcApproval"; | |||
export interface PoResult { | |||
id: number; | |||
@@ -7,6 +7,7 @@ import { cache } from "react"; | |||
export interface EscalationResult { | |||
id: number; | |||
personInCharge?: string; | |||
personInChargeDepartment?: string; | |||
personInChargeName?: string; | |||
personInChargeTitle?: string; | |||
@@ -17,6 +18,10 @@ export interface EscalationResult { | |||
itemName?: string; | |||
demandQty?: number; | |||
acceptedQty?: number; | |||
purchaseUomCode?: string; | |||
purchaseUomDesc?: string; | |||
stockUomCode?: string; | |||
stockUomDesc?: string; | |||
stockInLineId?: number; | |||
stockOutLineId?: number; | |||
qcFailCount?: number; | |||
@@ -147,7 +147,7 @@ export interface GetPickOrderLineInfo { | |||
itemId: number; | |||
itemCode: string; | |||
itemName: string; | |||
availableQty: number; | |||
availableQty: number | null; | |||
requiredQty: number; | |||
uomCode: string; | |||
uomDesc: string; | |||
@@ -14,8 +14,9 @@ import ApplicationCompletionChart from "./chart/ApplicationCompletionChart"; | |||
import OrderCompletionChart from "./chart/OrderCompletionChart"; | |||
import DashboardBox from "./Dashboardbox"; | |||
import CollapsibleCard from "./CollapsibleCard"; | |||
import SupervisorQcApproval, { IQCItems } from "./QC/SupervisorQcApproval"; | |||
// import SupervisorQcApproval, { IQCItems } from "./QC/SupervisorQcApproval"; | |||
import { EscalationResult } from "@/app/api/escalation"; | |||
import EscalationLogTable from "./escalation/EscalationLogTable"; | |||
type Props = { | |||
// iqc: IQCItems[] | undefined | |||
escalationLogs: EscalationResult[] | |||
@@ -32,9 +33,9 @@ const DashboardPage: React.FC<Props> = ({ | |||
<ThemeProvider theme={theme}> | |||
<Grid container spacing={2}> | |||
<Grid item xs={12}> | |||
<CollapsibleCard title={t("stock in escalation list")}> | |||
<CollapsibleCard title={t("Escalation List")}> | |||
<CardContent> | |||
<SupervisorQcApproval items={escalationLogs || []}/> | |||
<EscalationLogTable items={escalationLogs || []}/> | |||
</CardContent> | |||
</CollapsibleCard> | |||
</Grid> | |||
@@ -2,9 +2,13 @@ | |||
import { Box, Card, CardActionArea, CardContent, CardHeader, Grid, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography } from "@mui/material"; | |||
import { useRouter } from "next/navigation"; | |||
import { useCallback, useState } from "react"; | |||
import { useCallback, useMemo, useState } from "react"; | |||
import { usePathname } from "next/navigation"; | |||
import { useTranslation } from "react-i18next"; | |||
import { EscalationResult } from "@/app/api/escalation"; | |||
import { Column } from "@/components/SearchResults"; | |||
import SearchResults from "@/components/SearchResults/SearchResults"; | |||
import { arrayToDateString } from "@/app/utils/formatUtil"; | |||
export type IQCItems = { | |||
id: number; | |||
@@ -18,11 +22,11 @@ export type IQCItems = { | |||
}; | |||
type Props = { | |||
items: IQCItems[]; | |||
items: EscalationResult[]; | |||
}; | |||
const SupervisorQcApproval: React.FC<Props> = ({ | |||
items | |||
const EscalationLogTable: React.FC<Props> = ({ | |||
items | |||
}) => { | |||
const { t } = useTranslation("dashboard"); | |||
const CARD_HEADER = t("stock in escalation list") | |||
@@ -31,8 +35,8 @@ const SupervisorQcApproval: React.FC<Props> = ({ | |||
const router = useRouter(); | |||
const [selectedId, setSelectedId] = useState<number | null>(null); | |||
const navigateTo = useCallback( | |||
(item: IQCItems) => { | |||
const navigateTo = useCallback( | |||
(item: EscalationResult) => { | |||
setSelectedId(item.id); | |||
console.log(pathname) | |||
router.replace(`/po/edit?id=${item.poId}&polId=${item.polId}&stockInLineId=${item.stockInLineId}`); | |||
@@ -40,17 +44,62 @@ const navigateTo = useCallback( | |||
[router, pathname] | |||
); | |||
const handleKeyDown = useCallback( | |||
(e: React.KeyboardEvent, item: IQCItems) => { | |||
if (e.key === 'Enter' || e.key === ' ') { | |||
e.preventDefault(); | |||
navigateTo(item); | |||
} | |||
}, | |||
[navigateTo] | |||
); | |||
const onRowClick = useCallback((item: EscalationResult) => { | |||
router.push(`/po/edit?id=${item.poId}&selectedIds=${item.poId}&polId=${item.polId}&stockInLineId=${item.stockInLineId}`); | |||
}, [router]) | |||
// const handleKeyDown = useCallback( | |||
// (e: React.KeyboardEvent, item: EscalationResult) => { | |||
// if (e.key === 'Enter' || e.key === ' ') { | |||
// e.preventDefault(); | |||
// navigateTo(item); | |||
// } | |||
// }, | |||
// [navigateTo] | |||
// ); | |||
return ( | |||
const columns = useMemo<Column<EscalationResult>[]>( | |||
() => [ | |||
{ | |||
name: "personInCharge", | |||
label: t("Responsible for handling colleagues") | |||
}, | |||
{ | |||
name: "acceptedQty", | |||
label: t("Received Qty"), | |||
align: "right", | |||
headerAlign: "right" | |||
}, | |||
{ | |||
name: "purchaseUomDesc", | |||
label: t("Purchase UoM") | |||
}, | |||
{ | |||
name: "dnDate", | |||
label: t("DN Date"), | |||
renderCell: (params) => { | |||
return params.dnDate ? arrayToDateString(params.dnDate) : "N/A" | |||
} | |||
}, | |||
{ | |||
name: "qcTotalCount", | |||
label: t("QC Completed Count"), | |||
align: "right", | |||
headerAlign: "right" | |||
}, | |||
{ | |||
name: "qcFailCount", | |||
label: t("QC Fail Count"), | |||
align: "right", | |||
headerAlign: "right" | |||
}, | |||
{ | |||
name: "reason", | |||
label: t("Reason"), | |||
}, | |||
], []) | |||
{/* return ( | |||
<TableContainer component={Paper}> | |||
<Table aria-label="Two column navigable table" size="small"> | |||
<TableHead> | |||
@@ -87,7 +136,15 @@ const navigateTo = useCallback( | |||
</TableBody> | |||
</Table> | |||
</TableContainer> | |||
); | |||
}; | |||
);*/} | |||
return ( | |||
<SearchResults | |||
onRowClick={onRowClick} | |||
items={items} | |||
columns={columns} | |||
isAutoPaging={false} | |||
/> | |||
) | |||
}; | |||
export default SupervisorQcApproval; | |||
export default EscalationLogTable; |
@@ -210,6 +210,12 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => { | |||
const searchParams = useSearchParams(); | |||
const [selectedRow, setSelectedRow] = useState<PurchaseOrderLine | null>(null); | |||
const defaultPolId = searchParams.get("polId") | |||
useEffect(() => { | |||
if (defaultPolId) { | |||
setSelectedRow(rows.find((r) => r.id.toString() === defaultPolId) ?? null) | |||
} | |||
}, []) | |||
const [stockInLine, setStockInLine] = useState<StockInLine[]>([]); | |||
const [processedQty, setProcessedQty] = useState(0); | |||
@@ -270,6 +270,7 @@ function PoInputGrid({ | |||
const [newOpen, setNewOpen] = useState(false); | |||
const stockInLineId = searchParams.get("stockInLineId"); | |||
const poLineId = searchParams.get("poLineId"); | |||
const closeNewModal = useCallback(() => { | |||
const newParams = new URLSearchParams(searchParams.toString()); | |||
newParams.delete("stockInLineId"); // Remove the parameter | |||
@@ -282,46 +283,51 @@ const closeNewModal = useCallback(() => { | |||
// Open modal | |||
const openNewModal = useCallback(() => { | |||
setNewOpen(true); | |||
setNewOpen(() => true); | |||
}, []); | |||
// Button handler to update the URL and open the modal | |||
const handleNewQC = useCallback( | |||
(id: GridRowId, params: any) => async () => { | |||
(id: GridRowId, params: any) => async() => { | |||
// console.log(id) | |||
// console.log(params) | |||
setBtnIsLoading(true); | |||
// setBtnIsLoading(true); | |||
setRowModesModel((prev) => ({ | |||
...prev, | |||
[id]: { mode: GridRowModes.View }, | |||
})); | |||
const qcResult = await fetchQcDefaultValue(id); | |||
setModalInfo({ | |||
setModalInfo(() => ({ | |||
...params.row, | |||
qcResult: qcResult, | |||
receivedQty: itemDetail.receivedQty, | |||
}); | |||
})); | |||
setTimeout(() => { | |||
const newParams = new URLSearchParams(searchParams.toString()); | |||
newParams.set("stockInLineId", id.toString()); // Ensure `set` to avoid duplicates | |||
router.replace(`${pathname}?${newParams.toString()}`); | |||
console.log("hello") | |||
// console.log("hello") | |||
openNewModal() | |||
setBtnIsLoading(false); | |||
// setBtnIsLoading(false); | |||
}, 200); | |||
}, | |||
[fetchQcDefaultValue, openNewModal, pathname, router, searchParams] | |||
); | |||
// Open modal if `stockInLineId` exists in the URL | |||
const [firstCheckForSil, setFirstCheckForSil] = useState(false) | |||
useEffect(() => { | |||
if (stockInLineId) { | |||
console.log("heeloo") | |||
console.log(stockInLineId) | |||
handleNewQC(stockInLineId, apiRef.current.getRow(stockInLineId)); | |||
if (stockInLineId && itemDetail && !firstCheckForSil) { | |||
// console.log("heeloo") | |||
// console.log(stockInLineId) | |||
// console.log(apiRef.current.getRow(stockInLineId)) | |||
setFirstCheckForSil(true) | |||
const fn = handleNewQC(stockInLineId, {row: apiRef.current.getRow(stockInLineId)}); | |||
fn(); | |||
} | |||
}, [stockInLineId, newOpen, handleNewQC, apiRef]); | |||
}, [stockInLineId, poLineId, itemDetail]); | |||
const handleEscalation = useCallback( | |||
(id: GridRowId, params: any) => () => { | |||
// setBtnIsLoading(true); | |||
@@ -580,7 +586,7 @@ const closeNewModal = useCallback(() => { | |||
}} | |||
onClick={handleNewQC(params.row.id, params)} | |||
color="inherit" | |||
key="edit" | |||
key={`edit`} | |||
/>, | |||
<GridActionsCellItem | |||
icon={<Button | |||
@@ -70,7 +70,6 @@ const PoQcStockInModalVer2: React.FC<Props> = ({ | |||
qc, | |||
warehouse, | |||
}) => { | |||
console.log(warehouse); | |||
const { | |||
t, | |||
i18n: { language }, | |||
@@ -116,8 +115,10 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||
const [viewOnly, setViewOnly] = useState(false); | |||
useEffect(() => { | |||
const isViewOnly = itemDetail.status.toLowerCase() == "completed" || itemDetail.status.toLowerCase() == "rejected" | |||
setViewOnly(isViewOnly) | |||
if (itemDetail && itemDetail.status) { | |||
const isViewOnly = itemDetail.status.toLowerCase() == "completed" || itemDetail.status.toLowerCase() == "rejected" | |||
setViewOnly(isViewOnly) | |||
} | |||
}, [itemDetail]); | |||
const [openPutaway, setOpenPutaway] = useState(false); | |||
@@ -311,10 +311,10 @@ const StockInFormVer2: React.FC<Props> = ({ | |||
<TextField | |||
label={t("uom")} | |||
fullWidth | |||
{...register("uom", { | |||
{...register("uom.code", { | |||
required: "uom required!", | |||
})} | |||
value={uom.code} | |||
// value={uom?.code} | |||
disabled={true} | |||
/> | |||
</Grid> | |||
@@ -1,39 +1,46 @@ | |||
{ | |||
"Dashboard": "資訊展示面板", | |||
"Order status": "訂單狀態", | |||
"pending": "未收貨", | |||
"receiving": "收貨中", | |||
"total": "未完成總數", | |||
"Warehouse temperature record": "倉庫溫度記錄", | |||
"Warehouse type": "倉庫類型", | |||
"Last 6 hours": "過去6小時", | |||
"Last 24 hours": "過去24小時", | |||
"Cold storage": "冷藏倉", | |||
"Normal temperature storage": "常溫倉", | |||
"Temperature status": "溫度狀態", | |||
"Humidity status": "濕度狀態", | |||
"Warehouse status": "倉庫狀態", | |||
"Progress chart": "進度圖表", | |||
"Purchase Order Code": "採購單號", | |||
"Item Name": "貨品名稱", | |||
"Escalation Level": "上報等級", | |||
"Reason": "原因", | |||
"Order completion": "訂單完成度", | |||
"Raw material": "原料", | |||
"Consumable": "消耗品", | |||
"Shipment": "出貨", | |||
"Extracted order": "已提取提料單", | |||
"Pending order": "待提取提料單", | |||
"Temperature": "溫度", | |||
"Humidity": "濕度", | |||
"Pending storage": "待入倉物料", | |||
"Total storage": "已入倉物料", | |||
"Application completion": "提料申請完成度", | |||
"Processed application": "已處理提料申請", | |||
"Pending application": "待處理提料申請", | |||
"pending inspection material": "待品檢物料", | |||
"inspected material": "已品檢物料", | |||
"total material": "物料總數", | |||
"stock in escalation list": "收貨已上報列表" | |||
} | |||
"Dashboard": "資訊展示面板", | |||
"Order status": "訂單狀態", | |||
"pending": "未收貨", | |||
"receiving": "收貨中", | |||
"total": "未完成總數", | |||
"Warehouse temperature record": "倉庫溫度記錄", | |||
"Warehouse type": "倉庫類型", | |||
"Last 6 hours": "過去6小時", | |||
"Last 24 hours": "過去24小時", | |||
"Cold storage": "冷藏倉", | |||
"Normal temperature storage": "常溫倉", | |||
"Temperature status": "溫度狀態", | |||
"Humidity status": "濕度狀態", | |||
"Warehouse status": "倉庫狀態", | |||
"Progress chart": "進度圖表", | |||
"Purchase Order Code": "採購單號", | |||
"Item Name": "貨品名稱", | |||
"Escalation Level": "上報等級", | |||
"Reason": "原因", | |||
"Order completion": "訂單完成度", | |||
"Raw material": "原料", | |||
"Consumable": "消耗品", | |||
"Shipment": "出貨", | |||
"Extracted order": "已提取提料單", | |||
"Pending order": "待提取提料單", | |||
"Temperature": "溫度", | |||
"Humidity": "濕度", | |||
"Pending storage": "待入倉物料", | |||
"Total storage": "已入倉物料", | |||
"Application completion": "提料申請完成度", | |||
"Processed application": "已處理提料申請", | |||
"Pending application": "待處理提料申請", | |||
"pending inspection material": "待品檢物料", | |||
"inspected material": "已品檢物料", | |||
"total material": "物料總數", | |||
"stock in escalation list": "收貨已上報列表", | |||
"Responsible for handling colleagues": "負責處理同事", | |||
"Completed QC Total": "品檢完成數量", | |||
"QC Fail Count": "品檢不合格數量", | |||
"DN Date": "送貨日期", | |||
"Received Qty": "收貨數量", | |||
"Escalation List": "上報列表", | |||
"Purchase UoM": "計量單位", | |||
"QC Completed Count": "品檢完成數量" | |||
} |