"use client"; import React, { useEffect, useRef, useState } from 'react'; import { useTranslation } from "react-i18next"; import { Dialog, DialogTitle, DialogContent, DialogActions, Button, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Chip, Typography, } from '@mui/material'; import DownloadIcon from '@mui/icons-material/Download'; import dayjs from 'dayjs'; import { fetchSemiFGItemCodesWithCategory, generateSemiFGProductionAnalysisReport, generateSemiFGProductionAnalysisReportExcel, generateSemiFGProductionAnalysisReportExcelDaily, ItemCodeWithCategory, } from './semiFGProductionAnalysisApi'; import { parseItemCodeTokens } from './parseItemCodeTokens'; type ExportFormat = 'pdf' | 'excel' | 'excel-daily'; interface SemiFGProductionAnalysisReportProps { criteria: Record; prepareCriteria?: () => Record; requiredFieldLabels: string[]; loading: boolean; setLoading: (loading: boolean) => void; reportTitle?: string; onExportSuccess?: (format: "pdf" | "excel") => void; } export default function SemiFGProductionAnalysisReport({ criteria, prepareCriteria, requiredFieldLabels, loading, setLoading, reportTitle = '成品/半成品生產分析報告', onExportSuccess, }: SemiFGProductionAnalysisReportProps) { const { t } = useTranslation("report"); const [showConfirmDialog, setShowConfirmDialog] = useState(false); const [selectedItemCodesInfo, setSelectedItemCodesInfo] = useState([]); const [itemCodesWithCategory, setItemCodesWithCategory] = useState>({}); const [exportFormat, setExportFormat] = useState('pdf'); const inFlightRef = useRef(false); // Fetch item codes with category when stockCategory changes useEffect(() => { const stockCategory = criteria.stockCategory || ''; if (stockCategory) { fetchSemiFGItemCodesWithCategory(stockCategory) .then((items) => { const categoryMap: Record = {}; items.forEach((item) => { categoryMap[item.code] = item; }); setItemCodesWithCategory((prev) => ({ ...prev, ...categoryMap })); }) .catch((error) => { console.error('Failed to fetch item codes with category:', error); }); } }, [criteria.stockCategory]); const dailyRangeError = (activeCriteria: Record): string | null => { const start = (activeCriteria.lastOutDateStart || '').trim(); const end = (activeCriteria.lastOutDateEnd || '').trim(); if (!start || !end) return t('semiFgDailyRangeRequired'); const startDate = dayjs(start); const endDate = dayjs(end); if (!startDate.isValid() || !endDate.isValid()) return t('semiFgDailyRangeRequired'); if (endDate.isBefore(startDate, 'day')) return t('semiFgDailyRangeInvalid'); if (endDate.diff(startDate, 'day') + 1 > 366) return t('semiFgDailyRangeTooLong'); return null; }; const handleExportClick = async (format: ExportFormat) => { if (inFlightRef.current) return; const activeCriteria = prepareCriteria?.() ?? criteria; setExportFormat(format); if (requiredFieldLabels.length > 0) { alert(t('missingRequired', { fields: requiredFieldLabels.join('\n- ') })); return; } if (format === 'excel-daily') { const rangeError = dailyRangeError(activeCriteria); if (rangeError) { alert(rangeError); return; } } const selectedCodes = parseItemCodeTokens( [activeCriteria.itemCode, activeCriteria.itemCodePaste].filter(Boolean).join(' '), ); if (selectedCodes.length === 0) { await executeExport(format, activeCriteria); return; } const itemCodesInfo: ItemCodeWithCategory[] = selectedCodes.map((codeTrimmed) => { const categoryInfo = itemCodesWithCategory[codeTrimmed]; return { code: codeTrimmed, category: categoryInfo?.category || 'Unknown', name: categoryInfo?.name || '', }; }); setSelectedItemCodesInfo(itemCodesInfo); setShowConfirmDialog(true); }; const executeExport = async ( format: ExportFormat = exportFormat, activeCriteria: Record = prepareCriteria?.() ?? criteria, ) => { if (inFlightRef.current) return; inFlightRef.current = true; setLoading(true); try { if (format === 'excel-daily') { await generateSemiFGProductionAnalysisReportExcelDaily(activeCriteria, reportTitle); onExportSuccess?.('excel'); } else if (format === 'excel') { await generateSemiFGProductionAnalysisReportExcel(activeCriteria, reportTitle); onExportSuccess?.('excel'); } else { await generateSemiFGProductionAnalysisReport(activeCriteria, reportTitle); onExportSuccess?.('pdf'); } setShowConfirmDialog(false); } catch (error) { console.error('Failed to generate report:', error); const message = error instanceof Error ? error.message.trim() : ''; alert(message && !message.startsWith('HTTP error') ? message : t('generateError')); } finally { setLoading(false); inFlightRef.current = false; } }; const confirmLabel = loading ? exportFormat === 'excel-daily' ? t('semiFgGeneratingDailyExcel') : exportFormat === 'excel' ? t('generatingExcel') : t('generatingPdf') : exportFormat === 'excel-daily' ? t('semiFgConfirmDailyExcel') : exportFormat === 'excel' ? t('confirmDownloadExcel') : t('confirmDownloadPdf'); return ( <>
{/* Confirmation Dialog for 成品/半成品生產分析報告 */} setShowConfirmDialog(false)} maxWidth="md" fullWidth > {t('semiFgConfirmTitle')} {t('semiFgConfirmHint')} {t('semiFgColItem')} {t('semiFgColCategory')} {selectedItemCodesInfo.map((item, index) => { const displayName = item.name ? `${item.code} ${item.name}` : item.code; return ( {displayName} ); })}
); }