FPSMS-frontend
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 

207 行
6.6 KiB

  1. "use client";
  2. import React, { useState, useEffect } from 'react';
  3. import {
  4. Dialog,
  5. DialogTitle,
  6. DialogContent,
  7. DialogActions,
  8. Button,
  9. Table,
  10. TableBody,
  11. TableCell,
  12. TableContainer,
  13. TableHead,
  14. TableRow,
  15. Paper,
  16. Chip,
  17. Typography,
  18. } from '@mui/material';
  19. import DownloadIcon from '@mui/icons-material/Download';
  20. import {
  21. fetchSemiFGItemCodes,
  22. fetchSemiFGItemCodesWithCategory,
  23. generateSemiFGProductionAnalysisReport,
  24. generateSemiFGProductionAnalysisReportExcel,
  25. ItemCodeWithCategory,
  26. } from './semiFGProductionAnalysisApi';
  27. interface SemiFGProductionAnalysisReportProps {
  28. criteria: Record<string, string>;
  29. requiredFieldLabels: string[];
  30. loading: boolean;
  31. setLoading: (loading: boolean) => void;
  32. reportTitle?: string;
  33. }
  34. export default function SemiFGProductionAnalysisReport({
  35. criteria,
  36. requiredFieldLabels,
  37. loading,
  38. setLoading,
  39. reportTitle = '成品/半成品生產分析報告',
  40. }: SemiFGProductionAnalysisReportProps) {
  41. const [showConfirmDialog, setShowConfirmDialog] = useState(false);
  42. const [selectedItemCodesInfo, setSelectedItemCodesInfo] = useState<ItemCodeWithCategory[]>([]);
  43. const [itemCodesWithCategory, setItemCodesWithCategory] = useState<Record<string, ItemCodeWithCategory>>({});
  44. const [exportFormat, setExportFormat] = useState<'pdf' | 'excel'>('pdf');
  45. // Fetch item codes with category when stockCategory changes
  46. useEffect(() => {
  47. const stockCategory = criteria.stockCategory || '';
  48. if (stockCategory) {
  49. fetchSemiFGItemCodesWithCategory(stockCategory)
  50. .then((items) => {
  51. const categoryMap: Record<string, ItemCodeWithCategory> = {};
  52. items.forEach((item) => {
  53. categoryMap[item.code] = item;
  54. });
  55. setItemCodesWithCategory((prev) => ({ ...prev, ...categoryMap }));
  56. })
  57. .catch((error) => {
  58. console.error('Failed to fetch item codes with category:', error);
  59. });
  60. }
  61. }, [criteria.stockCategory]);
  62. const handleExportClick = async (format: 'pdf' | 'excel') => {
  63. setExportFormat(format);
  64. // Validate required fields
  65. if (requiredFieldLabels.length > 0) {
  66. alert(`缺少必填條件:\n- ${requiredFieldLabels.join('\n- ')}`);
  67. return;
  68. }
  69. // If no itemCode is selected, export directly without confirmation
  70. if (!criteria.itemCode) {
  71. await executeExport(format);
  72. return;
  73. }
  74. // If itemCode is selected, show confirmation dialog
  75. const selectedCodes = criteria.itemCode.split(',').filter((code) => code.trim());
  76. const itemCodesInfo: ItemCodeWithCategory[] = selectedCodes.map((code) => {
  77. const codeTrimmed = code.trim();
  78. const categoryInfo = itemCodesWithCategory[codeTrimmed];
  79. return {
  80. code: codeTrimmed,
  81. category: categoryInfo?.category || 'Unknown',
  82. name: categoryInfo?.name || '',
  83. };
  84. });
  85. setSelectedItemCodesInfo(itemCodesInfo);
  86. setShowConfirmDialog(true);
  87. };
  88. const executeExport = async (format: 'pdf' | 'excel' = exportFormat) => {
  89. setLoading(true);
  90. try {
  91. if (format === 'excel') {
  92. await generateSemiFGProductionAnalysisReportExcel(criteria, reportTitle);
  93. } else {
  94. await generateSemiFGProductionAnalysisReport(criteria, reportTitle);
  95. }
  96. setShowConfirmDialog(false);
  97. } catch (error) {
  98. console.error('Failed to generate report:', error);
  99. alert('An error occurred while generating the report. Please try again.');
  100. } finally {
  101. setLoading(false);
  102. }
  103. };
  104. return (
  105. <>
  106. <div style={{ display: 'flex', gap: 16 }}>
  107. <Button
  108. variant="contained"
  109. size="large"
  110. startIcon={<DownloadIcon />}
  111. onClick={() => handleExportClick('pdf')}
  112. disabled={loading}
  113. sx={{ px: 4 }}
  114. >
  115. {loading ? '生成 PDF...' : '下載報告 (PDF)'}
  116. </Button>
  117. <Button
  118. variant="outlined"
  119. size="large"
  120. startIcon={<DownloadIcon />}
  121. onClick={() => handleExportClick('excel')}
  122. disabled={loading}
  123. sx={{ px: 4 }}
  124. >
  125. {loading ? '生成 Excel...' : '下載報告 (Excel)'}
  126. </Button>
  127. </div>
  128. {/* Confirmation Dialog for 成品/半成品生產分析報告 */}
  129. <Dialog
  130. open={showConfirmDialog}
  131. onClose={() => setShowConfirmDialog(false)}
  132. maxWidth="md"
  133. fullWidth
  134. >
  135. <DialogTitle>
  136. <Typography variant="h6" fontWeight="bold">
  137. 已選擇的物料編號以及列印成品/半成品生產分析報告
  138. </Typography>
  139. </DialogTitle>
  140. <DialogContent>
  141. <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
  142. 請確認以下已選擇的物料編號及其類別:
  143. </Typography>
  144. <TableContainer component={Paper} variant="outlined">
  145. <Table>
  146. <TableHead>
  147. <TableRow>
  148. <TableCell>
  149. <strong>物料編號及名稱</strong>
  150. </TableCell>
  151. <TableCell>
  152. <strong>類別</strong>
  153. </TableCell>
  154. </TableRow>
  155. </TableHead>
  156. <TableBody>
  157. {selectedItemCodesInfo.map((item, index) => {
  158. const displayName = item.name ? `${item.code} ${item.name}` : item.code;
  159. return (
  160. <TableRow key={index}>
  161. <TableCell>{displayName}</TableCell>
  162. <TableCell>
  163. <Chip
  164. label={item.category || 'Unknown'}
  165. color={item.category === 'FG' ? 'primary' : item.category === 'WIP' ? 'secondary' : 'default'}
  166. size="small"
  167. />
  168. </TableCell>
  169. </TableRow>
  170. );
  171. })}
  172. </TableBody>
  173. </Table>
  174. </TableContainer>
  175. </DialogContent>
  176. <DialogActions sx={{ p: 2 }}>
  177. <Button onClick={() => setShowConfirmDialog(false)}>取消</Button>
  178. <Button
  179. variant="contained"
  180. onClick={() => executeExport()}
  181. disabled={loading}
  182. startIcon={<DownloadIcon />}
  183. >
  184. {loading
  185. ? exportFormat === 'excel'
  186. ? '生成 Excel...'
  187. : '生成 PDF...'
  188. : exportFormat === 'excel'
  189. ? '確認下載 Excel'
  190. : '確認下載 PDF'}
  191. </Button>
  192. </DialogActions>
  193. </Dialog>
  194. </>
  195. );
  196. }