Browse Source

update po detail. Still need to fix "always reloading" issue.

master
cyril.tsui 1 week ago
parent
commit
d425202bab
7 changed files with 213 additions and 93 deletions
  1. +4
    -0
      src/app/api/dashboard/actions.ts
  2. +2
    -0
      src/app/api/po/index.ts
  3. +1
    -0
      src/app/api/settings/item/actions.ts
  4. +4
    -0
      src/app/utils/formatUtil.ts
  5. +1
    -1
      src/components/PoDetail/EscalationComponent.tsx
  6. +193
    -87
      src/components/PoDetail/PoDetail.tsx
  7. +8
    -5
      src/components/PoDetail/PoInputGrid.tsx

+ 4
- 0
src/app/api/dashboard/actions.ts View File

@@ -30,6 +30,9 @@ export interface StockInLineEntry {
acceptedQty: number; acceptedQty: number;
status?: string; status?: string;
expiryDate?: string; expiryDate?: string;
productLotNo?: string;
receiptDate?: string;
dnDate?: string;
} }


export interface PurchaseQcResult { export interface PurchaseQcResult {
@@ -87,6 +90,7 @@ export const fetchStockInLineInfo = cache(async (stockInLineId: number) => {
}); });


export const createStockInLine = async (data: StockInLineEntry) => { export const createStockInLine = async (data: StockInLineEntry) => {
console.log(data)
const stockInLine = await serverFetchJson< const stockInLine = await serverFetchJson<
PostStockInLiineResponse<StockInLineEntry> PostStockInLiineResponse<StockInLineEntry>
>(`${BASE_API_URL}/stockInLine/create`, { >(`${BASE_API_URL}/stockInLine/create`, {


+ 2
- 0
src/app/api/po/index.ts View File

@@ -60,6 +60,8 @@ export interface StockInLine {
poCode: string; poCode: string;
uom: Uom; uom: Uom;
defaultWarehouseId: number; // id for now defaultWarehouseId: number; // id for now
dnNo: string;
dnDate: number[];
} }


export const fetchPoList = cache(async (queryParams?: Record<string, any>) => { export const fetchPoList = cache(async (queryParams?: Record<string, any>) => {


+ 1
- 0
src/app/api/settings/item/actions.ts View File

@@ -56,6 +56,7 @@ export interface ItemCombo {
label: string, label: string,
uomId: number, uomId: number,
uom: string, uom: string,
group?: string,
} }


export const fetchAllItemsInClient = cache(async () => { export const fetchAllItemsInClient = cache(async () => {


+ 4
- 0
src/app/utils/formatUtil.ts View File

@@ -76,6 +76,10 @@ export const dayjsToInputDateTimeString = (date: Dayjs) => {
return date.format(`${INPUT_DATE_FORMAT}T${OUTPUT_TIME_FORMAT}`); return date.format(`${INPUT_DATE_FORMAT}T${OUTPUT_TIME_FORMAT}`);
}; };


export const outputDateStringToInputDateString = (date: string) => {
return dayjsToInputDateString(dateStringToDayjs(date))
}

export const stockInLineStatusMap: { [status: string]: number } = { export const stockInLineStatusMap: { [status: string]: number } = {
draft: 0, draft: 0,
pending: 1, pending: 1,


+ 1
- 1
src/components/PoDetail/EscalationComponent.tsx View File

@@ -61,7 +61,7 @@ const EscalationComponent: React.FC<Props> = ({
]; ];


const handleInputChange = ( const handleInputChange = (
event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | SelectChangeEvent<string>
event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement> | SelectChangeEvent<string>
): void => { ): void => {
const { name, value } = event.target; const { name, value } = event.target;
setFormData((prev) => ({ setFormData((prev) => ({


+ 193
- 87
src/components/PoDetail/PoDetail.tsx View File

@@ -28,6 +28,9 @@ import {
Typography, Typography,
Checkbox, Checkbox,
FormControlLabel, FormControlLabel,
Card,
CardContent,
Radio,
} from "@mui/material"; } from "@mui/material";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
// import InputDataGrid, { TableRow } from "../InputDataGrid/InputDataGrid"; // import InputDataGrid, { TableRow } from "../InputDataGrid/InputDataGrid";
@@ -57,7 +60,7 @@ import PoInputGrid from "./PoInputGrid";
import { QcItemWithChecks } from "@/app/api/qc"; import { QcItemWithChecks } from "@/app/api/qc";
import { useRouter, useSearchParams, usePathname } from "next/navigation"; import { useRouter, useSearchParams, usePathname } from "next/navigation";
import { WarehouseResult } from "@/app/api/warehouse"; import { WarehouseResult } from "@/app/api/warehouse";
import { calculateWeight, returnWeightUnit } from "@/app/utils/formatUtil";
import { calculateWeight, dateStringToDayjs, dayjsToDateString, OUTPUT_DATE_FORMAT, outputDateStringToInputDateString, returnWeightUnit } from "@/app/utils/formatUtil";
import { CameraContext } from "../Cameras/CameraProvider"; import { CameraContext } from "../Cameras/CameraProvider";
import PoQcStockInModal from "./PoQcStockInModal"; import PoQcStockInModal from "./PoQcStockInModal";
import QrModal from "./QrModal"; import QrModal from "./QrModal";
@@ -69,6 +72,11 @@ import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil";
import { fetchPoListClient } from "@/app/api/po/actions"; import { fetchPoListClient } from "@/app/api/po/actions";
import { List, ListItem, ListItemButton, ListItemText, Divider } from "@mui/material"; import { List, ListItem, ListItemButton, ListItemText, Divider } from "@mui/material";
import { createStockInLine } from "@/app/api/dashboard/actions"; import { createStockInLine } from "@/app/api/dashboard/actions";
import { Controller, FormProvider, useForm } from "react-hook-form";
import dayjs, { Dayjs } from "dayjs";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { DatePicker, LocalizationProvider, zhHK } from "@mui/x-date-pickers";
import { debounce } from "lodash";
//import { useRouter } from "next/navigation"; //import { useRouter } from "next/navigation";




@@ -169,6 +177,11 @@ const PoSearchList: React.FC<{
); );
}; };


interface PolInputResult {
lotNo: string,
dnQty: number,
}

const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => { const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
const cameras = useContext(CameraContext); const cameras = useContext(CameraContext);
console.log(cameras); console.log(cameras);
@@ -178,10 +191,20 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
const [rows, setRows] = useState<PurchaseOrderLine[]>( const [rows, setRows] = useState<PurchaseOrderLine[]>(
purchaseOrder.pol || [], purchaseOrder.pol || [],
); );
const [polInputList, setPolInputList] = useState<PolInputResult[]>([])
useEffect(() => {
setPolInputList(
(purchaseOrder.pol ?? []).map(() => ({
lotNo: "",
dnQty: 0,
} as PolInputResult))
);
}, [purchaseOrder.pol]);

const pathname = usePathname() const pathname = usePathname()
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const [row, setRow] = useState(rows[0]);
const [selectedRow, setSelectedRow] = useState<PurchaseOrderLine | null>(null);


const [stockInLine, setStockInLine] = useState<StockInLine[]>([]); const [stockInLine, setStockInLine] = useState<StockInLine[]>([]);
const [processedQty, setProcessedQty] = useState(0); const [processedQty, setProcessedQty] = useState(0);
@@ -191,8 +214,13 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
const [selectedPoId, setSelectedPoId] = useState(po.id); const [selectedPoId, setSelectedPoId] = useState(po.id);
const currentPoId = searchParams.get('id'); const currentPoId = searchParams.get('id');
const selectedIdsParam = searchParams.get('selectedIds'); const selectedIdsParam = searchParams.get('selectedIds');
const [selectedRowId, setSelectedRowId] = useState<number | null>(null);

// const [selectedRowId, setSelectedRowId] = useState<number | null>(null);
const dnFormProps = useForm({
defaultValues: {
dnNo: '',
dnDate: dayjsToDateString(dayjs())
}
})
const fetchPoList = useCallback(async () => { const fetchPoList = useCallback(async () => {
try { try {
if (selectedIdsParam) { if (selectedIdsParam) {
@@ -217,11 +245,12 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
const fetchPoDetail = useCallback(async (poId: string) => { const fetchPoDetail = useCallback(async (poId: string) => {
try { try {
const result = await fetchPoInClient(parseInt(poId)); const result = await fetchPoInClient(parseInt(poId));
console.log(result)
if (result) { if (result) {
setPurchaseOrder(result); setPurchaseOrder(result);
setRows(result.pol || []); setRows(result.pol || []);
if (result.pol && result.pol.length > 0) { if (result.pol && result.pol.length > 0) {
setRow(result.pol[0]);
setSelectedRow(result.pol[0]);
setStockInLine(result.pol[0].stockInLine); setStockInLine(result.pol[0].stockInLine);
setProcessedQty(result.pol[0].processed); setProcessedQty(result.pol[0].processed);
} }
@@ -233,10 +262,15 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
const handlePoSelect = useCallback( const handlePoSelect = useCallback(
async (selectedPo: PoResult) => { async (selectedPo: PoResult) => {
if (selectedPo.id === selectedPoId) return;
setSelectedPoId(selectedPo.id); setSelectedPoId(selectedPo.id);
await fetchPoDetail(selectedPo.id.toString()); await fetchPoDetail(selectedPo.id.toString());
const newSelectedIds = selectedIdsParam || selectedPo.id.toString(); const newSelectedIds = selectedIdsParam || selectedPo.id.toString();
router.push(`/po/edit?id=${selectedPo.id}&start=true&selectedIds=${newSelectedIds}`, { scroll: false });
// router.push(`/po/edit?id=${selectedPo.id}&start=true&selectedIds=${newSelectedIds}`, { scroll: false });
const newUrl = `/po/edit?id=${selectedPo.id}&start=true&selectedIds=${newSelectedIds}`;
if (pathname + searchParams.toString() !== newUrl) {
router.replace(newUrl, { scroll: false });
}
}, },
[router, selectedIdsParam, fetchPoDetail] [router, selectedIdsParam, fetchPoDetail]
); );
@@ -246,7 +280,7 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
setSelectedPoId(parseInt(currentPoId)); setSelectedPoId(parseInt(currentPoId));
fetchPoDetail(currentPoId); fetchPoDetail(currentPoId);
} }
}, [currentPoId, selectedPoId, fetchPoDetail]);
}, [currentPoId, fetchPoDetail]);


useEffect(() => { useEffect(() => {
fetchPoList(); fetchPoList();
@@ -257,13 +291,6 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
setSelectedPoId(parseInt(currentPoId)); setSelectedPoId(parseInt(currentPoId));
} }
}, [currentPoId]); }, [currentPoId]);








const removeParam = (paramToRemove: string) => { const removeParam = (paramToRemove: string) => {
const newParams = new URLSearchParams(searchParams.toString()); const newParams = new URLSearchParams(searchParams.toString());
@@ -296,7 +323,7 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
function Row(props: { row: PurchaseOrderLine }) { function Row(props: { row: PurchaseOrderLine }) {
const { row } = props; const { row } = props;
// const [firstReceiveQty, setFirstReceiveQty] = useState<number>() // const [firstReceiveQty, setFirstReceiveQty] = useState<number>()
const [secondReceiveQty, setSecondReceiveQty] = useState<number>()
// const [secondReceiveQty, setSecondReceiveQty] = useState<number>()
// const [open, setOpen] = useState(false); // const [open, setOpen] = useState(false);
const [processedQty, setProcessedQty] = useState(row.processed); const [processedQty, setProcessedQty] = useState(row.processed);
const [currStatus, setCurrStatus] = useState(row.status); const [currStatus, setCurrStatus] = useState(row.status);
@@ -309,6 +336,9 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
() => returnWeightUnit(row.uom), () => returnWeightUnit(row.uom),
[row.uom], [row.uom],
); );
const rowIndex = useMemo(() => {
return rows.findIndex((r) => r.id === row.id)
}, [])


useEffect(() => { useEffect(() => {
const polId = searchParams.get("polId") != null ? parseInt(searchParams.get("polId")!) : null const polId = searchParams.get("polId") != null ? parseInt(searchParams.get("polId")!) : null
@@ -328,21 +358,18 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
}, [processedQty, row.qty]); }, [processedQty, row.qty]);


const handleRowSelect = () => { const handleRowSelect = () => {
setSelectedRowId(row.id);
setRow(row);
// setSelectedRowId(row.id);
setSelectedRow(row);
setStockInLine(row.stockInLine); setStockInLine(row.stockInLine);
setProcessedQty(row.processed); setProcessedQty(row.processed);
}; };
const changeStockInLines = useCallback( const changeStockInLines = useCallback(
(id: number) => { (id: number) => {
console.log(id)
//rows = purchaseOrderLine //rows = purchaseOrderLine
console.log(rows)
const target = rows.find((r) => r.id === id) const target = rows.find((r) => r.id === id)
const stockInLine = target!.stockInLine const stockInLine = target!.stockInLine
console.log(stockInLine)
setStockInLine(stockInLine) setStockInLine(stockInLine)
setRow(target!)
setSelectedRow(target!)
// console.log(pathname) // console.log(pathname)
// router.replace(`/po/edit?id=${item.poId}&polId=${item.polId}&stockInLineId=${item.stockInLineId}`); // router.replace(`/po/edit?id=${item.poId}&polId=${item.polId}&stockInLineId=${item.stockInLineId}`);
}, },
@@ -355,42 +382,64 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
// post stock in line // post stock in line
const oldId = row.id; const oldId = row.id;
const postData = { const postData = {
dnNo: dnFormProps.watch("dnNo"),
dnDate: outputDateStringToInputDateString(dnFormProps.watch("dnDate")),
itemId: row.itemId, itemId: row.itemId,
itemNo: row.itemNo, itemNo: row.itemNo,
itemName: row.itemName, itemName: row.itemName,
purchaseOrderId: row.purchaseOrderId, purchaseOrderId: row.purchaseOrderId,
purchaseOrderLineId: row.id, purchaseOrderLineId: row.id,
acceptedQty: secondReceiveQty || 0,
acceptedQty: polInputList[rowIndex].dnQty || 0,
productLotNo: polInputList[rowIndex].lotNo || '',
// acceptedQty: secondReceiveQty || 0,
// acceptedQty: row.acceptedQty, // acceptedQty: row.acceptedQty,
}; };
if (secondReceiveQty === 0) return
// if (secondReceiveQty === 0) return
const res = await createStockInLine(postData); const res = await createStockInLine(postData);
if (res) {
fetchPoDetail(selectedPoId.toString());
}
console.log(res); console.log(res);
}, 200); }, 200);
}, },
[],
[polInputList, row, dnFormProps],
); );


const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const raw = e.target.value;

// Allow empty input
if (raw.trim() === '') {
setSecondReceiveQty(undefined);
return;
}

// Keep digits only
const cleaned = raw.replace(/[^\d]/g, '');
if (cleaned === '') {
// If the user typed only non-digits, keep previous value
return;
}

// Parse and clamp to non-negative integer
const next = Math.max(0, Math.floor(Number(cleaned)));
setSecondReceiveQty(next);
};
const handleChange = useCallback(debounce((e: React.ChangeEvent<HTMLInputElement>) => {
const raw = e.target.value;
const id = e.target.id
const temp = [...polInputList]
switch (id) {
case "lotNo":
if (raw.trim() === '') {
temp[rowIndex].lotNo = '';
break;
}
temp[rowIndex].lotNo = raw.trim();
break;
case "dnQty":
// Allow empty input
if (raw.trim() === '') {
temp[rowIndex].dnQty = 0;
break;
}

// Keep digits only
const cleaned = raw.replace(/[^\d]/g, '');
if (cleaned === '') {
// If the user typed only non-digits, keep previous value
break;
}

// Parse and clamp to non-negative integer
const next = Math.max(0, Math.floor(Number(cleaned)));
temp[rowIndex].dnQty = next;
break;
default:
break;
}
setPolInputList(() => temp)
}, 300), [rowIndex]);
return ( return (
<> <>
<TableRow <TableRow
@@ -410,10 +459,10 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
</IconButton> </IconButton>
</TableCell> */} </TableCell> */}
<TableCell align="center" sx={{ width: '60px' }}> <TableCell align="center" sx={{ width: '60px' }}>
<Checkbox
checked={selectedRowId === row.id}
onChange={handleRowSelect}
onClick={(e) => e.stopPropagation()}
<Radio
checked={selectedRow?.id === row.id}
// onChange={handleRowSelect}
// onClick={(e) => e.stopPropagation()}
/> />
</TableCell> </TableCell>
<TableCell align="left">{row.itemNo}</TableCell> <TableCell align="left">{row.itemNo}</TableCell>
@@ -425,16 +474,27 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
{decimalFormatter.format(totalWeight)} {weightUnit} {decimalFormatter.format(totalWeight)} {weightUnit}
</TableCell> */} </TableCell> */}
{/* <TableCell align="left">{weightUnit}</TableCell> */} {/* <TableCell align="left">{weightUnit}</TableCell> */}
<TableCell align="right">{decimalFormatter.format(row.price)}</TableCell>
{/* <TableCell align="right">{decimalFormatter.format(row.price)}</TableCell> */}
{/* <TableCell align="left">{row.expiryDate}</TableCell> */} {/* <TableCell align="left">{row.expiryDate}</TableCell> */}
<TableCell align="left">{t(`${currStatus.toLowerCase()}`)}</TableCell> <TableCell align="left">{t(`${currStatus.toLowerCase()}`)}</TableCell>
<TableCell align="right">{integerFormatter.format(row.receivedQty)}</TableCell> <TableCell align="right">{integerFormatter.format(row.receivedQty)}</TableCell>
<TableCell align="center"> <TableCell align="center">
<TextField <TextField
id="lotNo"
label="輸入貨品批號"
type="text" // Use type="text" to allow validation in the change handler
variant="outlined"
defaultValue={polInputList[rowIndex]?.lotNo ?? ''}
onChange={handleChange}
/>
</TableCell>
<TableCell align="center">
<TextField
id="dnQty"
label="輸入來貨數量" label="輸入來貨數量"
type="text" // Use type="text" to allow validation in the change handler type="text" // Use type="text" to allow validation in the change handler
variant="outlined" variant="outlined"
value={secondReceiveQty}
defaultValue={polInputList[rowIndex]?.dnQty ?? ''}
onChange={handleChange} onChange={handleChange}
InputProps={{ InputProps={{
inputProps: { inputProps: {
@@ -588,6 +648,15 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
} }
}, [searchParams]) }, [searchParams])


const handleDatePickerChange = useCallback((value: Dayjs | null, onChange: (...event: any[]) => void) => {
if (value != null) {
const updatedValue = dayjsToDateString(value)
onChange(updatedValue)
} else {
onChange(value)
}
}, [])

return ( return (
<> <>
<Stack spacing={2}> <Stack spacing={2}>
@@ -614,39 +683,75 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {


{/* right side po info */} {/* right side po info */}
<Grid item xs={8}> <Grid item xs={8}>
<PoInfoCard po={purchaseOrder} />
{true ? (
<Stack spacing={2}>
<TextField
label={t("dnNo")}
type="text"
variant="outlined"
fullWidth
// InputProps={{
// inputProps: {
// min: 0,
// step: 1
// }
// }}
/>
<TextField
label={t("dnDate")}
type="text"
variant="outlined"
defaultValue={"11/08/2025"}
fullWidth
InputProps={{
inputProps: {
min: 0,
step: 1
}
}}
/>
<Button variant="contained" onClick={onOpenScanner} fullWidth>
提交
</Button>
</Stack>
) : undefined}
<Grid container spacing={3} sx={{ maxWidth: 'fit-content' }}>
<Grid item xs={12}>
<PoInfoCard po={purchaseOrder} />
</Grid>
<Grid item xs={12}>
{true ? (
<FormProvider {...dnFormProps}>
<Stack component={"form"} spacing={2}>
<Card sx={{ display: "block" }}>
<CardContent component={Stack} spacing={2}>
<Grid container spacing={2} sx={{ maxWidth: 'fit-content' }}>
<Grid item xs={12}>
<TextField
{...dnFormProps.register("dnNo")}
label={t("dnNo")}
type="text"
variant="outlined"
fullWidth
// InputProps={{
// inputProps: {
// min: 0,
// step: 1
// }
// }}
/>
</Grid>
<Grid item xs={12}>
<LocalizationProvider
dateAdapter={AdapterDayjs}
// TODO: Should maybe use a custom adapterLocale here to support YYYY-MM-DD
adapterLocale="zh-hk"
localeText={zhHK.components.MuiLocalizationProvider.defaultProps.localeText}
>
<Controller
control={dnFormProps.control}
name="dnDate"
render={({ field }) => (
<DatePicker
label={t("dnDate")}
format={`${OUTPUT_DATE_FORMAT}`}
defaultValue={dateStringToDayjs(field.value)}
onChange={(newValue: Dayjs | null) => {
handleDatePickerChange(newValue, field.onChange)
}}
slotProps={{ textField: { fullWidth: true }}}
/>
)}
/>
</LocalizationProvider>
</Grid>
{/* <TextField
label={t("dnDate")}
type="text"
variant="outlined"
defaultValue={"11/08/2025"}
fullWidth
/> */}
</Grid>
{/* <Button variant="contained" onClick={onOpenScanner} fullWidth>
提交
</Button> */}
</CardContent>
</Card>
</Stack>
</FormProvider>
) : undefined}
</Grid>
</Grid>
</Grid> </Grid>
</Grid> </Grid>


@@ -666,9 +771,10 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
<TableCell align="right">{t("processed")}</TableCell> <TableCell align="right">{t("processed")}</TableCell>
<TableCell align="left">{t("uom")}</TableCell> <TableCell align="left">{t("uom")}</TableCell>
{/* <TableCell align="right">{t("total weight")}</TableCell> */} {/* <TableCell align="right">{t("total weight")}</TableCell> */}
<TableCell align="right">{`${t("price")} (HKD)`}</TableCell>
{/* <TableCell align="right">{`${t("price")} (HKD)`}</TableCell> */}
<TableCell align="left" sx={{ width: '75px' }}>{t("status")}</TableCell> <TableCell align="left" sx={{ width: '75px' }}>{t("status")}</TableCell>
{renderFieldCondition(FIRST_IN_FIELD) ? <TableCell align="right">{t("receivedQty")}</TableCell> : undefined} {renderFieldCondition(FIRST_IN_FIELD) ? <TableCell align="right">{t("receivedQty")}</TableCell> : undefined}
<TableCell align="center" sx={{ width: '150px' }}>{t("productLotNo")}</TableCell>
{renderFieldCondition(SECOND_IN_FIELD) ? <TableCell align="center" sx={{ width: '150px' }}>{t("dnQty")}(以訂單單位計算)</TableCell> : undefined} {renderFieldCondition(SECOND_IN_FIELD) ? <TableCell align="center" sx={{ width: '150px' }}>{t("dnQty")}(以訂單單位計算)</TableCell> : undefined}
<TableCell align="center" sx={{ width: '100px' }}></TableCell> <TableCell align="center" sx={{ width: '100px' }}></TableCell>
</TableRow> </TableRow>
@@ -687,11 +793,11 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
<Grid container xs={12} justifyContent="start"> <Grid container xs={12} justifyContent="start">
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="h6"> <Typography variant="h6">
已選擇: {selectedRowId ? row.itemNo : '無'} - {selectedRowId ? row.itemName : '無'}
{selectedRow ? `已選擇: ${selectedRow?.itemNo ? selectedRow.itemNo : 'N/A'} - ${selectedRow?.itemName ? selectedRow?.itemName : 'N/A'}}` : "未選擇貨品"}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12}> <Grid item xs={12}>
{selectedRowId && (
{selectedRow && (
<TableContainer component={Paper} sx={{ width: 'fit-content', overflow: 'auto' }}> <TableContainer component={Paper} sx={{ width: 'fit-content', overflow: 'auto' }}>
<Table> <Table>
<TableBody> <TableBody>
@@ -704,7 +810,7 @@ const PoDetail: React.FC<Props> = ({ po, qc, warehouse }) => {
stockInLine={stockInLine} stockInLine={stockInLine}
setStockInLine={setStockInLine} setStockInLine={setStockInLine}
setProcessedQty={setProcessedQty} setProcessedQty={setProcessedQty}
itemDetail={row}
itemDetail={selectedRow}
warehouse={warehouse} warehouse={warehouse}
/> />
</Box> </Box>


+ 8
- 5
src/components/PoDetail/PoInputGrid.tsx View File

@@ -39,6 +39,7 @@ import {
returnWeightUnit, returnWeightUnit,
calculateWeight, calculateWeight,
stockInLineStatusMap, stockInLineStatusMap,
arrayToDateString,
} from "@/app/utils/formatUtil"; } from "@/app/utils/formatUtil";
// import PoQcStockInModal from "./PoQcStockInModal"; // import PoQcStockInModal from "./PoQcStockInModal";
import NotificationImportantIcon from "@mui/icons-material/NotificationImportant"; import NotificationImportantIcon from "@mui/icons-material/NotificationImportant";
@@ -443,17 +444,19 @@ const closeNewModal = useCallback(() => {
field: "dnNo", field: "dnNo",
headerName: t("dnNo"), headerName: t("dnNo"),
width: 125, width: 125,
renderCell: () => {
return <>DN0000001</>
}
// renderCell: () => {
// return <>DN0000001</>
// }
// flex: 0.4, // flex: 0.4,
}, },
{ {
field: "dnDate", field: "dnDate",
headerName: t("dnDate"), headerName: t("dnDate"),
width: 125, width: 125,
renderCell: () => {
return <>07/08/2025</>
renderCell: (params) => {
console.log(params.row)
// return <>07/08/2025</>
return arrayToDateString(params.value)
} }
// flex: 0.4, // flex: 0.4,
}, },


Loading…
Cancel
Save