# Conflicts: # src/components/Jodetail/JobmatchForm.tsxmaster
| @@ -25,7 +25,7 @@ const Profile: React.FC<Props> = ({ avatarImageSrc, profileName }) => { | |||
| setProfileMenuAnchorEl(undefined); | |||
| }; | |||
| const { t } = useTranslation("login"); | |||
| const { t } = useTranslation("common"); | |||
| return ( | |||
| <> | |||
| @@ -35,6 +35,7 @@ import dayjs from "dayjs"; | |||
| import arraySupport from "dayjs/plugin/arraySupport"; | |||
| import SearchBox, { Criterion } from "../SearchBox"; | |||
| import { fetchPickOrderItemsByPageClient } from "@/app/api/settings/item/actions"; | |||
| import { RESPONSE_LIMIT_DEFAULT } from "next/dist/server/api-utils"; | |||
| dayjs.extend(arraySupport); | |||
| @@ -159,7 +160,7 @@ const AssignAndRelease: React.FC<Props> = ({ filterArgs }) => { | |||
| console.log("First record targetDate:", res.records[0]?.targetDate); | |||
| console.log("First record targetDate type:", typeof res.records[0]?.targetDate); | |||
| console.log("First record targetDate parsed:", new Date(res.records[0]?.targetDate)); | |||
| console.log("First record targetDate formatted:", new Date(res.records[0]?.targetDate).toLocaleDateString()); | |||
| console.log("First record targetDate formatted:", dayjs(res.records[0]?.targetDate).format(OUTPUT_DATE_FORMAT)); | |||
| // 新增:在前端也过滤掉 "assigned" 状态的项目 | |||
| const filteredRecords = res.records.filter((item: any) => item.status !== "assigned"); | |||
| @@ -130,7 +130,7 @@ const CombinedLotTable: React.FC<CombinedLotTableProps> = ({ | |||
| <TableCell sx={{ color: textColor }}>{lot.itemName}</TableCell> | |||
| <TableCell sx={{ color: textColor }}>{lot.lotNo}</TableCell> | |||
| {/* <TableCell sx={{ color: textColor }}> | |||
| {lot.expiryDate ? new Date(lot.expiryDate).toLocaleDateString() : 'N/A'} | |||
| {lot.expiryDate ? dayjs(lot.expiryDate).format(OUTPUT_DATE_FORMAT) : 'N/A'} | |||
| </TableCell> | |||
| */} | |||
| <TableCell sx={{ color: textColor }}>{lot.location}</TableCell> | |||
| @@ -17,6 +17,8 @@ import { | |||
| MenuItem, | |||
| } from '@mui/material'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil'; | |||
| import dayjs from 'dayjs'; | |||
| interface CreatedItem { | |||
| itemId: number; | |||
| @@ -179,7 +181,7 @@ const CreatedItemsTable: React.FC<CreatedItemsTableProps> = ({ | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -4,6 +4,8 @@ import { FGPickOrderResponse } from "@/app/api/pickOrder/actions"; | |||
| import { Box, Card, CardContent, Grid, Stack, TextField, Button } from "@mui/material"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import QrCodeIcon from '@mui/icons-material/QrCode'; | |||
| import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import dayjs from "dayjs"; | |||
| type Props = { | |||
| fgOrder: FGPickOrderResponse; | |||
| @@ -58,7 +60,7 @@ const FGPickOrderCard: React.FC<Props> = ({ fgOrder, onQrCodeClick }) => { | |||
| label={t("Delivery Date")} | |||
| fullWidth | |||
| disabled={true} | |||
| value={new Date(fgOrder.deliveryDate).toLocaleDateString()} | |||
| value={dayjs(fgOrder.deliveryDate).format(OUTPUT_DATE_FORMAT)} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| @@ -21,6 +21,9 @@ import { useTranslation } from "react-i18next"; | |||
| import { GetPickOrderLineInfo, PickExecutionIssueData } from "@/app/api/pickOrder/actions"; | |||
| import { fetchEscalationCombo } from "@/app/api/user/actions"; | |||
| import { useRef } from "react"; | |||
| import dayjs from 'dayjs'; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| interface LotPickData { | |||
| id: number; | |||
| lotId: number; | |||
| @@ -127,12 +130,15 @@ const PickExecutionForm: React.FC<PickExecutionFormProps> = ({ | |||
| if (initKeyRef.current === key) return; | |||
| const getSafeDate = (dateValue: any): string => { | |||
| if (!dateValue) return new Date().toISOString().split('T')[0]; | |||
| if (!dateValue) return dayjs().format(INPUT_DATE_FORMAT); | |||
| try { | |||
| const d = new Date(dateValue); | |||
| return isNaN(d.getTime()) ? new Date().toISOString().split('T')[0] : d.toISOString().split('T')[0]; | |||
| const date = dayjs(dateValue); | |||
| if (!date.isValid()) { | |||
| return dayjs().format(INPUT_DATE_FORMAT); | |||
| } | |||
| return date.format(INPUT_DATE_FORMAT); | |||
| } catch { | |||
| return new Date().toISOString().split('T')[0]; | |||
| return dayjs().format(INPUT_DATE_FORMAT); | |||
| } | |||
| }; | |||
| @@ -140,7 +146,7 @@ const PickExecutionForm: React.FC<PickExecutionFormProps> = ({ | |||
| pickOrderId: pickOrderId, | |||
| pickOrderCode: selectedPickOrderLine.pickOrderCode, | |||
| pickOrderCreateDate: getSafeDate(pickOrderCreateDate), | |||
| pickExecutionDate: new Date().toISOString().split('T')[0], | |||
| pickExecutionDate: dayjs().format(INPUT_DATE_FORMAT), | |||
| pickOrderLineId: selectedPickOrderLine.id, | |||
| itemId: selectedPickOrderLine.itemId, | |||
| itemCode: selectedPickOrderLine.itemCode, | |||
| @@ -61,6 +61,8 @@ import { SessionWithTokens } from "@/config/authConfig"; | |||
| import { fetchStockInLineInfo } from "@/app/api/po/actions"; | |||
| import GoodPickExecutionForm from "./GoodPickExecutionForm"; | |||
| import FGPickOrderCard from "./FGPickOrderCard"; | |||
| import dayjs from "dayjs"; | |||
| import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| interface Props { | |||
| filterArgs: Record<string, any>; | |||
| @@ -343,7 +345,7 @@ const GoodPickExecutionRecord: React.FC<Props> = ({ filterArgs }) => { | |||
| <Box> | |||
| {/* 结果统计 */} | |||
| <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}> | |||
| {t("Total")}: {filteredDoPickOrders.length} {t("completed DO pick orders")} | |||
| {t("Completed DO pick orders: ")} {filteredDoPickOrders.length} | |||
| </Typography> | |||
| {/* 列表 */} | |||
| @@ -367,7 +369,7 @@ const GoodPickExecutionRecord: React.FC<Props> = ({ filterArgs }) => { | |||
| {doPickOrder.shopName} - {doPickOrder.deliveryNo} | |||
| </Typography> | |||
| <Typography variant="body2" color="text.secondary"> | |||
| {t("Completed")}: {new Date(doPickOrder.completedDate).toLocaleString()} | |||
| {t("Completed")}: {dayjs(doPickOrder.completedDate).format(OUTPUT_DATE_FORMAT)} | |||
| </Typography> | |||
| </Box> | |||
| <Box> | |||
| @@ -33,7 +33,7 @@ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||
| import dayjs from "dayjs"; | |||
| import { Check, Search, RestartAlt } from "@mui/icons-material"; | |||
| import { ItemCombo, fetchAllItemsInClient } from "@/app/api/settings/item/actions"; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import SearchResults, { Column } from "../SearchResults/SearchResults"; | |||
| import { fetchJobOrderDetailByCode } from "@/app/api/jo/actions"; | |||
| import SearchBox, { Criterion } from "../SearchBox"; | |||
| @@ -835,7 +835,7 @@ const JobCreateItem: React.FC<Props> = ({ filterArgs, searchQuery, onPickOrderCr | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -942,7 +942,7 @@ const JobCreateItem: React.FC<Props> = ({ filterArgs, searchQuery, onPickOrderCr | |||
| label: t("Target Date"), | |||
| renderCell: (item) => ( | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| ), | |||
| }, | |||
| @@ -1601,7 +1601,7 @@ const CustomSearchResultsTable = () => { | |||
| {/* Target Date - Show the item's own target date (or "-" if not selected) */} | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -17,6 +17,8 @@ import { | |||
| MenuItem, | |||
| } from '@mui/material'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil'; | |||
| import dayjs from 'dayjs'; | |||
| interface SearchItemWithQty { | |||
| id: number; | |||
| @@ -213,7 +215,7 @@ const SearchResultsTable: React.FC<SearchResultsTableProps> = ({ | |||
| {/* Target Date */} | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -33,7 +33,7 @@ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||
| import dayjs from "dayjs"; | |||
| import { Check, Search, RestartAlt } from "@mui/icons-material"; | |||
| import { ItemCombo, fetchAllItemsInClient } from "@/app/api/settings/item/actions"; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import SearchResults, { Column } from "../SearchResults/SearchResults"; | |||
| import { fetchJobOrderDetailByCode } from "@/app/api/jo/actions"; | |||
| import SearchBox, { Criterion } from "../SearchBox"; | |||
| @@ -837,7 +837,7 @@ const NewCreateItem: React.FC<Props> = ({ filterArgs, searchQuery, onPickOrderCr | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -33,7 +33,7 @@ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||
| import dayjs from "dayjs"; | |||
| import { Check, Search, RestartAlt } from "@mui/icons-material"; | |||
| import { ItemCombo, fetchAllItemsInClient,fetchItemsWithDetails } from "@/app/api/settings/item/actions"; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import SearchResults, { Column } from "../SearchResults/SearchResults"; | |||
| import { fetchJobOrderDetailByCode } from "@/app/api/jo/actions"; | |||
| import SearchBox, { Criterion } from "../SearchBox"; | |||
| @@ -954,7 +954,7 @@ const handleQtyBlur = useCallback((itemId: number) => { | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate&& item.targetDate !== "" ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate&& item.targetDate !== "" ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -1061,7 +1061,7 @@ const handleQtyBlur = useCallback((itemId: number) => { | |||
| label: t("Target Date"), | |||
| renderCell: (item) => ( | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| ), | |||
| }, | |||
| @@ -1806,7 +1806,7 @@ const CustomSearchResultsTable = () => { | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -130,7 +130,7 @@ const CombinedLotTable: React.FC<CombinedLotTableProps> = ({ | |||
| <TableCell sx={{ color: textColor }}>{lot.itemName}</TableCell> | |||
| <TableCell sx={{ color: textColor }}>{lot.lotNo}</TableCell> | |||
| {/* <TableCell sx={{ color: textColor }}> | |||
| {lot.expiryDate ? new Date(lot.expiryDate).toLocaleDateString() : 'N/A'} | |||
| {lot.expiryDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : 'N/A'} | |||
| </TableCell> | |||
| */} | |||
| <TableCell sx={{ color: textColor }}>{lot.location}</TableCell> | |||
| @@ -17,6 +17,8 @@ import { | |||
| MenuItem, | |||
| } from '@mui/material'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import dayjs from 'dayjs'; | |||
| import { OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil'; | |||
| interface CreatedItem { | |||
| itemId: number; | |||
| @@ -179,7 +181,7 @@ const CreatedItemsTable: React.FC<CreatedItemsTableProps> = ({ | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -4,6 +4,8 @@ import { FGPickOrderResponse } from "@/app/api/pickOrder/actions"; | |||
| import { Box, Card, CardContent, Grid, Stack, TextField, Button } from "@mui/material"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import QrCodeIcon from '@mui/icons-material/QrCode'; | |||
| import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import dayjs from "dayjs"; | |||
| type Props = { | |||
| fgOrder: FGPickOrderResponse; | |||
| @@ -72,7 +74,7 @@ const FGPickOrderCard: React.FC<Props> = ({ fgOrder, onQrCodeClick }) => { | |||
| label={t("Delivery Date")} | |||
| fullWidth | |||
| disabled={true} | |||
| value={new Date(fgOrder.deliveryDate).toLocaleDateString()} | |||
| value={dayjs(fgOrder.deliveryDate).format(OUTPUT_DATE_FORMAT)} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| @@ -22,6 +22,9 @@ import { GetPickOrderLineInfo, PickExecutionIssueData } from "@/app/api/pickOrde | |||
| import { fetchEscalationCombo } from "@/app/api/user/actions"; | |||
| import { useSession } from "next-auth/react"; | |||
| import { SessionWithTokens } from "@/config/authConfig"; | |||
| import dayjs from 'dayjs'; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| interface LotPickData { | |||
| id: number; | |||
| lotId: number; | |||
| @@ -111,18 +114,18 @@ const PickExecutionForm: React.FC<PickExecutionFormProps> = ({ | |||
| // 初始化表单数据 - 每次打开时都重新初始化 | |||
| useEffect(() => { | |||
| if (open && selectedLot && selectedPickOrderLine && pickOrderId) { | |||
| const getSafeDate = (dateValue: any): string => { | |||
| if (!dateValue) return new Date().toISOString().split('T')[0]; | |||
| try { | |||
| const date = new Date(dateValue); | |||
| if (isNaN(date.getTime())) { | |||
| return new Date().toISOString().split('T')[0]; | |||
| } | |||
| return date.toISOString().split('T')[0]; | |||
| } catch { | |||
| return new Date().toISOString().split('T')[0]; | |||
| const getSafeDate = (dateValue: any): string => { | |||
| if (!dateValue) return dayjs().format(INPUT_DATE_FORMAT); | |||
| try { | |||
| const date = dayjs(dateValue); | |||
| if (!date.isValid()) { | |||
| return dayjs().format(INPUT_DATE_FORMAT); | |||
| } | |||
| }; | |||
| return date.format(INPUT_DATE_FORMAT); | |||
| } catch { | |||
| return dayjs().format(INPUT_DATE_FORMAT); | |||
| } | |||
| }; | |||
| // ✅ Initialize verified quantity to the received quantity (actualPickQty) | |||
| const initialVerifiedQty = selectedLot.actualPickQty || 0; | |||
| @@ -137,7 +140,7 @@ const PickExecutionForm: React.FC<PickExecutionFormProps> = ({ | |||
| pickOrderId: pickOrderId, | |||
| pickOrderCode: selectedPickOrderLine.pickOrderCode, | |||
| pickOrderCreateDate: getSafeDate(pickOrderCreateDate), | |||
| pickExecutionDate: new Date().toISOString().split('T')[0], | |||
| pickExecutionDate: dayjs().format(INPUT_DATE_FORMAT), | |||
| pickOrderLineId: selectedPickOrderLine.id, | |||
| itemId: selectedPickOrderLine.itemId, | |||
| itemCode: selectedPickOrderLine.itemCode, | |||
| @@ -33,7 +33,7 @@ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||
| import dayjs from "dayjs"; | |||
| import { Check, Search, RestartAlt } from "@mui/icons-material"; | |||
| import { ItemCombo, fetchAllItemsInClient } from "@/app/api/settings/item/actions"; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import SearchResults, { Column } from "../SearchResults/SearchResults"; | |||
| import { fetchJobOrderDetailByCode } from "@/app/api/jo/actions"; | |||
| import SearchBox, { Criterion } from "../SearchBox"; | |||
| @@ -835,7 +835,7 @@ const JobCreateItem: React.FC<Props> = ({ filterArgs, searchQuery, onPickOrderCr | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -942,7 +942,7 @@ const JobCreateItem: React.FC<Props> = ({ filterArgs, searchQuery, onPickOrderCr | |||
| label: t("Target Date"), | |||
| renderCell: (item) => ( | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| ), | |||
| }, | |||
| @@ -1601,7 +1601,7 @@ const CustomSearchResultsTable = () => { | |||
| {/* Target Date - Show the item's own target date (or "-" if not selected) */} | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -22,6 +22,8 @@ import { GetPickOrderLineInfo, PickExecutionIssueData } from "@/app/api/pickOrde | |||
| import { fetchEscalationCombo } from "@/app/api/user/actions"; | |||
| import { useSession } from "next-auth/react"; | |||
| import { SessionWithTokens } from "@/config/authConfig"; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import dayjs from "dayjs"; | |||
| interface LotPickData { | |||
| id: number; | |||
| @@ -113,19 +115,19 @@ const PickExecutionForm: React.FC<PickExecutionFormProps> = ({ | |||
| // 初始化表单数据 - 每次打开时都重新初始化 | |||
| useEffect(() => { | |||
| if (open && selectedLot && selectedPickOrderLine && pickOrderId) { | |||
| const getSafeDate = (dateValue: any): string => { | |||
| if (!dateValue) return new Date().toISOString().split('T')[0]; | |||
| try { | |||
| const date = new Date(dateValue); | |||
| if (isNaN(date.getTime())) { | |||
| return new Date().toISOString().split('T')[0]; | |||
| } | |||
| return date.toISOString().split('T')[0]; | |||
| } catch { | |||
| return new Date().toISOString().split('T')[0]; | |||
| const getSafeDate = (dateValue: any): string => { | |||
| if (!dateValue) return dayjs().format(INPUT_DATE_FORMAT); | |||
| try { | |||
| const date = dayjs(dateValue); | |||
| if (!date.isValid()) { | |||
| return dayjs().format(INPUT_DATE_FORMAT); | |||
| } | |||
| }; | |||
| return date.format(INPUT_DATE_FORMAT); | |||
| } catch { | |||
| return dayjs().format(INPUT_DATE_FORMAT); | |||
| } | |||
| }; | |||
| // ✅ Initialize verified quantity to the received quantity (actualPickQty) | |||
| const initialVerifiedQty = selectedLot.actualPickQty || 0; | |||
| setVerifiedQty(initialVerifiedQty); | |||
| @@ -139,7 +141,7 @@ const PickExecutionForm: React.FC<PickExecutionFormProps> = ({ | |||
| pickOrderId: pickOrderId, | |||
| pickOrderCode: selectedPickOrderLine.pickOrderCode, | |||
| pickOrderCreateDate: getSafeDate(pickOrderCreateDate), | |||
| pickExecutionDate: new Date().toISOString().split('T')[0], | |||
| pickExecutionDate: dayjs().format(INPUT_DATE_FORMAT), | |||
| pickOrderLineId: selectedPickOrderLine.id, | |||
| itemId: selectedPickOrderLine.itemId, | |||
| itemCode: selectedPickOrderLine.itemCode, | |||
| @@ -17,6 +17,8 @@ import { | |||
| MenuItem, | |||
| } from '@mui/material'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil'; | |||
| import dayjs from 'dayjs'; | |||
| interface SearchItemWithQty { | |||
| id: number; | |||
| @@ -213,7 +215,7 @@ const SearchResultsTable: React.FC<SearchResultsTableProps> = ({ | |||
| {/* Target Date */} | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -17,6 +17,8 @@ import { | |||
| MenuItem, | |||
| } from '@mui/material'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil'; | |||
| import dayjs from 'dayjs'; | |||
| interface CreatedItem { | |||
| itemId: number; | |||
| @@ -179,7 +181,7 @@ const CreatedItemsTable: React.FC<CreatedItemsTableProps> = ({ | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -33,7 +33,7 @@ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||
| import dayjs from "dayjs"; | |||
| import { Check, Search, RestartAlt } from "@mui/icons-material"; | |||
| import { ItemCombo, fetchAllItemsInClient } from "@/app/api/settings/item/actions"; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import SearchResults, { Column } from "../SearchResults/SearchResults"; | |||
| import { fetchJobOrderDetailByCode } from "@/app/api/jo/actions"; | |||
| import SearchBox, { Criterion } from "../SearchBox"; | |||
| @@ -835,7 +835,7 @@ const JobCreateItem: React.FC<Props> = ({ filterArgs, searchQuery, onPickOrderCr | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -942,7 +942,7 @@ const JobCreateItem: React.FC<Props> = ({ filterArgs, searchQuery, onPickOrderCr | |||
| label: t("Target Date"), | |||
| renderCell: (item) => ( | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| ), | |||
| }, | |||
| @@ -1601,7 +1601,7 @@ const CustomSearchResultsTable = () => { | |||
| {/* Target Date - Show the item's own target date (or "-" if not selected) */} | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -56,7 +56,7 @@ import { | |||
| SubmitHandler, | |||
| useForm, | |||
| } from "react-hook-form"; | |||
| import { pickOrderStatusMap } from "@/app/utils/formatUtil"; | |||
| import { OUTPUT_DATE_FORMAT, pickOrderStatusMap } from "@/app/utils/formatUtil"; | |||
| import { QcItemWithChecks } from "@/app/api/qc"; | |||
| import { fetchQcItemCheck, fetchPickOrderQcResult } from "@/app/api/qc/actions"; | |||
| @@ -610,7 +610,7 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { | |||
| id: lot.id, | |||
| lotId: lot.lotId, | |||
| lotNo: lot.lotNo, | |||
| expiryDate: lot.expiryDate ? new Date(lot.expiryDate).toLocaleDateString() : 'N/A', | |||
| expiryDate: lot.expiryDate ? dayjs(lot.expiryDate).format(OUTPUT_DATE_FORMAT) : 'N/A', | |||
| location: lot.location, | |||
| stockUnit: lot.stockUnit, | |||
| inQty: lot.inQty, | |||
| @@ -20,6 +20,9 @@ import { useCallback, useEffect, useState } from "react"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { GetPickOrderLineInfo, PickExecutionIssueData } from "@/app/api/pickOrder/actions"; | |||
| import { fetchEscalationCombo } from "@/app/api/user/actions"; | |||
| import dayjs from 'dayjs'; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| interface LotPickData { | |||
| id: number; | |||
| @@ -108,18 +111,18 @@ const calculateRequiredQty = useCallback((lot: LotPickData) => { | |||
| // 初始化表单数据 - 每次打开时都重新初始化 | |||
| useEffect(() => { | |||
| if (open && selectedLot && selectedPickOrderLine && pickOrderId) { | |||
| const getSafeDate = (dateValue: any): string => { | |||
| if (!dateValue) return new Date().toISOString().split('T')[0]; | |||
| try { | |||
| const date = new Date(dateValue); | |||
| if (isNaN(date.getTime())) { | |||
| return new Date().toISOString().split('T')[0]; | |||
| } | |||
| return date.toISOString().split('T')[0]; | |||
| } catch { | |||
| return new Date().toISOString().split('T')[0]; | |||
| const getSafeDate = (dateValue: any): string => { | |||
| if (!dateValue) return dayjs().format(INPUT_DATE_FORMAT); | |||
| try { | |||
| const date = dayjs(dateValue); | |||
| if (!date.isValid()) { | |||
| return dayjs().format(INPUT_DATE_FORMAT); | |||
| } | |||
| }; | |||
| return date.format(INPUT_DATE_FORMAT); | |||
| } catch { | |||
| return dayjs().format(INPUT_DATE_FORMAT); | |||
| } | |||
| }; | |||
| // 计算剩余可用数量 | |||
| const remainingAvailableQty = calculateRemainingAvailableQty(selectedLot); | |||
| @@ -136,7 +139,7 @@ const calculateRequiredQty = useCallback((lot: LotPickData) => { | |||
| pickOrderId: pickOrderId, | |||
| pickOrderCode: selectedPickOrderLine.pickOrderCode, | |||
| pickOrderCreateDate: getSafeDate(pickOrderCreateDate), | |||
| pickExecutionDate: new Date().toISOString().split('T')[0], | |||
| pickExecutionDate: dayjs().format(INPUT_DATE_FORMAT), | |||
| pickOrderLineId: selectedPickOrderLine.id, | |||
| itemId: selectedPickOrderLine.itemId, | |||
| itemCode: selectedPickOrderLine.itemCode, | |||
| @@ -17,6 +17,8 @@ import { | |||
| MenuItem, | |||
| } from '@mui/material'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil'; | |||
| import dayjs from 'dayjs'; | |||
| interface SearchItemWithQty { | |||
| id: number; | |||
| @@ -213,7 +215,7 @@ const SearchResultsTable: React.FC<SearchResultsTableProps> = ({ | |||
| {/* Target Date */} | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -33,7 +33,7 @@ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||
| import dayjs from "dayjs"; | |||
| import { Check, Search, RestartAlt } from "@mui/icons-material"; | |||
| import { ItemCombo, fetchAllItemsInClient } from "@/app/api/settings/item/actions"; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import SearchResults, { Column } from "../SearchResults/SearchResults"; | |||
| import { fetchJobOrderDetailByCode } from "@/app/api/jo/actions"; | |||
| import SearchBox, { Criterion } from "../SearchBox"; | |||
| @@ -837,7 +837,7 @@ const NewCreateItem: React.FC<Props> = ({ filterArgs, searchQuery, onPickOrderCr | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -944,7 +944,7 @@ const NewCreateItem: React.FC<Props> = ({ filterArgs, searchQuery, onPickOrderCr | |||
| label: t("Target Date"), | |||
| renderCell: (item) => ( | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| ), | |||
| }, | |||
| @@ -33,7 +33,7 @@ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||
| import dayjs from "dayjs"; | |||
| import { Check, Search, RestartAlt } from "@mui/icons-material"; | |||
| import { ItemCombo, fetchAllItemsInClient,fetchItemsWithDetails } from "@/app/api/settings/item/actions"; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| import SearchResults, { Column } from "../SearchResults/SearchResults"; | |||
| import { fetchJobOrderDetailByCode } from "@/app/api/jo/actions"; | |||
| import SearchBox, { Criterion } from "../SearchBox"; | |||
| @@ -960,7 +960,7 @@ const handleQtyBlur = useCallback((itemId: number) => { | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate&& item.targetDate !== "" ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate&& item.targetDate !== "" ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -1067,7 +1067,7 @@ const handleQtyBlur = useCallback((itemId: number) => { | |||
| label: t("Target Date"), | |||
| renderCell: (item) => ( | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| ), | |||
| }, | |||
| @@ -1812,7 +1812,7 @@ const CustomSearchResultsTable = () => { | |||
| <TableCell align="right"> | |||
| <Typography variant="body2"> | |||
| {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} | |||
| {item.targetDate ? dayjs(item.targetDate).format(OUTPUT_DATE_FORMAT) : "-"} | |||
| </Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| @@ -19,6 +19,8 @@ import { Operator, Machine } from "@/app/api/jo"; | |||
| import OperatorScanner from "./OperatorScanner"; | |||
| import MachineScanner from "./MachineScanner"; | |||
| import MaterialLotScanner from "./MaterialLotScanner"; | |||
| import dayjs from 'dayjs'; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| interface ProductionRecordingModalProps { | |||
| isOpen: boolean; | |||
| @@ -43,7 +45,7 @@ const ProductionRecordingModal: React.FC<ProductionRecordingModalProps> = ({ | |||
| formState: { errors }, | |||
| } = useForm<FormData>({ | |||
| defaultValues: { | |||
| productionDate: new Date().toISOString().split("T")[0], | |||
| productionDate: dayjs().format(INPUT_DATE_FORMAT), | |||
| notes: "", | |||
| operators: [], | |||
| machines: [], | |||
| @@ -128,7 +130,7 @@ const ProductionRecordingModal: React.FC<ProductionRecordingModalProps> = ({ | |||
| const handleClose = (): void => { | |||
| reset({ | |||
| productionDate: new Date().toISOString().split("T")[0], | |||
| productionDate: dayjs().format(INPUT_DATE_FORMAT), | |||
| notes: "", | |||
| operators: [], | |||
| machines: [], | |||
| @@ -22,6 +22,8 @@ import { | |||
| import { getStatusIcon, getStatusColor } from "./utils/QualityCheckHelper"; | |||
| import DefectsSection from "./DefectsSection"; | |||
| import OperatorScanner from "./OperatorScanner"; | |||
| import dayjs from 'dayjs'; | |||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | |||
| const QualityCheckModal: React.FC<QualityCheckModalProps> = ({ | |||
| isOpen, | |||
| @@ -39,8 +41,7 @@ const QualityCheckModal: React.FC<QualityCheckModalProps> = ({ | |||
| formState: { errors, isValid }, | |||
| } = useForm<QualityCheckData>({ | |||
| defaultValues: { | |||
| inspectors: [], | |||
| checkDate: new Date().toISOString().split("T")[0], | |||
| checkDate: dayjs().format(INPUT_DATE_FORMAT), | |||
| status: "pending", | |||
| notes: "", | |||
| defects: [], | |||
| @@ -94,7 +95,7 @@ const QualityCheckModal: React.FC<QualityCheckModalProps> = ({ | |||
| const handleClose = (): void => { | |||
| reset({ | |||
| inspectors: [], | |||
| checkDate: new Date().toISOString().split("T")[0], | |||
| checkDate: dayjs().format(INPUT_DATE_FORMAT), | |||
| status: "pending", | |||
| notes: "", | |||
| defects: [], | |||
| @@ -103,6 +103,7 @@ | |||
| "All Pick Order Lots": "所有提料單批號", | |||
| "Row per page": "每頁行數", | |||
| "No data available": "沒有資料", | |||
| "jodetail": "工單細節" | |||
| "jodetail": "工單細節", | |||
| "Sign out": "登出" | |||
| } | |||
| @@ -270,7 +270,8 @@ | |||
| "success": "成功", | |||
| "Total (Verified + Bad + Missing) must equal Required quantity": "驗證數量 + 不良數量 + 缺失數量必須等於需求數量", | |||
| "BOM Status": "材料預備狀況", | |||
| "Estimated Production Date": "預計生產日期", | |||
| "Plan Start": "預計生產日期", | |||
| "Plan Start To": "預計生產日期(至)" | |||
| "Estimated Production Date": "預計生產日期及時間", | |||
| "Plan Start": "預計生產日期及時間", | |||
| "Plan Start From": "預計生產日期及時間", | |||
| "Plan Start To": "預計生產日期及時間至" | |||
| } | |||
| @@ -282,7 +282,7 @@ | |||
| "Pick Execution Record":"提料執行記錄", | |||
| "Delivery No.":"送貨單編號", | |||
| "Total":"總數", | |||
| "completed DO pick orders":"已完成送貨單提料單", | |||
| "Completed DO pick orders: ":"已完成送貨單提料單:", | |||
| "No completed DO pick orders found":"沒有已完成送貨單提料單", | |||
| "Print DN Label":"列印送貨單標貼", | |||