"use client"; import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react'; import { Box, Typography, Card, CardContent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, CircularProgress, TablePagination, } from '@mui/material'; import { useTranslation } from 'react-i18next'; import dayjs from 'dayjs'; import { arrayToDayjs } from '@/app/utils/formatUtil'; import { fetchMaterialPickStatus, MaterialPickStatusItem } from '@/app/api/jo/actions'; const REFRESH_INTERVAL = 10 * 60 * 1000; // 10 minutes in milliseconds const MaterialPickStatusTable: React.FC = () => { const { t } = useTranslation("jo"); const [data, setData] = useState([]); const [loading, setLoading] = useState(true); const refreshCountRef = useRef(0); const [paginationController, setPaginationController] = useState({ pageNum: 0, pageSize: 10, }); const loadData = useCallback(async () => { setLoading(true); try { const result = await fetchMaterialPickStatus(); // On second refresh, clear completed pick orders if (refreshCountRef.current >= 1) { // const filtered = result.filter(item => // item.pickStatus?.toLowerCase() !== 'completed' //); setData(result); } else { setData(result || []); } refreshCountRef.current += 1; } catch (error) { console.error('Error fetching material pick status:', error); setData([]); // Set empty array on error to stop loading } finally { setLoading(false); } }, []); // Remove refreshCount from dependencies useEffect(() => { // Initial load loadData(); // Set up auto-refresh every 10 minutes const interval = setInterval(() => { loadData(); }, REFRESH_INTERVAL); return () => clearInterval(interval); }, [loadData]); // Only depend on loadData, which is now stable const formatTime = (timeData: any): string => { if (!timeData) return ''; // Handle LocalDateTime ISO string format (e.g., "2026-01-09T18:01:54") if (typeof timeData === 'string') { // Try parsing as ISO string first (most common format from LocalDateTime) const parsed = dayjs(timeData); if (parsed.isValid()) { return parsed.format('HH:mm'); } // Try parsing as custom format YYYYMMDDHHmmss const customParsed = dayjs(timeData, 'YYYYMMDDHHmmss'); if (customParsed.isValid()) { return customParsed.format('HH:mm'); } // Try parsing as time string (HH:mm or HH:mm:ss) const parts = timeData.split(':'); if (parts.length >= 2) { const hour = parseInt(parts[0], 10); const minute = parseInt(parts[1] || '0', 10); if (!isNaN(hour) && !isNaN(minute)) { return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`; } } } else if (Array.isArray(timeData)) { // Handle array format [year, month, day, hour, minute, second] const hour = timeData[3] ?? timeData[0] ?? 0; const minute = timeData[4] ?? timeData[1] ?? 0; return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`; } return ''; }; const calculatePickTime = (startTime: any, endTime: any): number => { if (!startTime || !endTime) return 0; let start: dayjs.Dayjs; let end: dayjs.Dayjs; // Parse start time if (Array.isArray(startTime)) { // Array format: [year, month, day, hour, minute, second] if (startTime.length >= 5) { const year = startTime[0] || 0; const month = (startTime[1] || 1) - 1; // month is 0-indexed in JS Date const day = startTime[2] || 1; const hour = startTime[3] || 0; const minute = startTime[4] || 0; const second = startTime[5] || 0; // Create Date object and convert to dayjs const date = new Date(year, month, day, hour, minute, second); start = dayjs(date); console.log('Parsed start time:', { array: startTime, date: date.toISOString(), dayjs: start.format('YYYY-MM-DD HH:mm:ss'), isValid: start.isValid() }); } else { // Fallback to arrayToDayjs for shorter arrays start = arrayToDayjs(startTime, true); } } else if (typeof startTime === 'string') { // Try ISO format first start = dayjs(startTime); if (!start.isValid()) { // Try custom format start = dayjs(startTime, 'YYYYMMDDHHmmss'); } } else { start = dayjs(startTime); } // Parse end time if (Array.isArray(endTime)) { // Array format: [year, month, day, hour, minute, second] if (endTime.length >= 5) { const year = endTime[0] || 0; const month = (endTime[1] || 1) - 1; // month is 0-indexed in JS Date const day = endTime[2] || 1; const hour = endTime[3] || 0; const minute = endTime[4] || 0; const second = endTime[5] || 0; // Create Date object and convert to dayjs const date = new Date(year, month, day, hour, minute, second); end = dayjs(date); console.log('Parsed end time:', { array: endTime, date: date.toISOString(), dayjs: end.format('YYYY-MM-DD HH:mm:ss'), isValid: end.isValid() }); } else { // Fallback to arrayToDayjs for shorter arrays end = arrayToDayjs(endTime, true); } } else if (typeof endTime === 'string') { // Try ISO format first end = dayjs(endTime); if (!end.isValid()) { // Try custom format end = dayjs(endTime, 'YYYYMMDDHHmmss'); } } else { end = dayjs(endTime); } if (!start.isValid() || !end.isValid()) { console.warn('Invalid time values:', { startTime, endTime, startValid: start.isValid(), endValid: end.isValid(), startFormat: start.isValid() ? start.format() : 'invalid', endFormat: end.isValid() ? end.format() : 'invalid' }); return 0; } // Calculate difference in seconds first, then convert to minutes // This handles sub-minute differences correctly const diffSeconds = end.diff(start, 'second'); const diffMinutes = Math.ceil(diffSeconds / 60); // Round up to nearest minute console.log('Time calculation:', { start: start.format('YYYY-MM-DD HH:mm:ss'), end: end.format('YYYY-MM-DD HH:mm:ss'), diffSeconds, diffMinutes }); return diffMinutes > 0 ? diffMinutes : 0; }; const handlePageChange = useCallback((event: unknown, newPage: number) => { setPaginationController(prev => ({ ...prev, pageNum: newPage, })); }, []); const handlePageSizeChange = useCallback((event: React.ChangeEvent) => { const newPageSize = parseInt(event.target.value, 10); setPaginationController({ pageNum: 0, pageSize: newPageSize, }); }, []); const paginatedData = useMemo(() => { const startIndex = paginationController.pageNum * paginationController.pageSize; const endIndex = startIndex + paginationController.pageSize; return data.slice(startIndex, endIndex); }, [data, paginationController]); return ( {/* Title */} {t("Material Pick Status")} {loading ? ( ) : ( <> {t("Pick Order No.- Job Order No.- Item")} {t("Job Order Qty")} {t("No. of Items to be Picked")} {t("No. of Items with Issue During Pick")} {t("Pick Start Time")} {t("Pick End Time")} {t("Pick Time Taken (minutes)")} {paginatedData.length === 0 ? ( {t("No data available")} ) : ( paginatedData.map((row) => { const pickTimeTaken = calculatePickTime(row.pickStartTime, row.pickEndTime); return ( {row.pickOrderCode || '-'}
{row.jobOrderCode || '-'}
{row.itemCode || '-'} {row.itemName || '-'}
{row.jobOrderQty !== null && row.jobOrderQty !== undefined ? `${row.jobOrderQty} ${row.uom || ''}` : '-'} {row.numberOfItemsToPick ?? 0} {row.numberOfItemsWithIssue ?? 0} {formatTime(row.pickStartTime) || '-'} {formatTime(row.pickEndTime) || '-'} {pickTimeTaken > 0 ? `${pickTimeTaken} ${t("minutes")}` : '-'}
); }) )}
{data.length > 0 && ( )} )}
); }; export default MaterialPickStatusTable;