FPSMS-frontend
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

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