|
- "use client";
-
- import React, { useState } from "react";
- import {
- Box, Grid, Paper, Typography, Button, Dialog, DialogTitle,
- DialogContent, DialogActions, TextField, Stack, Table,
- TableBody, TableCell, TableContainer, TableHead, TableRow,
- Tabs, Tab // ← Added for tabs
- } from "@mui/material";
- import { FileDownload, Print, SettingsEthernet, Lan, Router } from "@mui/icons-material";
- import dayjs from "dayjs";
- import { NEXT_PUBLIC_API_URL } from "@/config/api";
- import { clientAuthFetch } from "@/app/utils/clientAuthFetch";
- import * as XLSX from "xlsx";
-
- // Simple TabPanel component for conditional rendering
- interface TabPanelProps {
- children?: React.ReactNode;
- index: number;
- value: number;
- }
-
- function TabPanel(props: TabPanelProps) {
- const { children, value, index, ...other } = props;
- return (
- <div
- role="tabpanel"
- hidden={value !== index}
- id={`simple-tabpanel-${index}`}
- aria-labelledby={`simple-tab-${index}`}
- {...other}
- >
- {value === index && (
- <Box sx={{ p: 3 }}>
- {children}
- </Box>
- )}
- </div>
- );
- }
-
- export default function TestingPage() {
- // Tab state
- const [tabValue, setTabValue] = useState(0);
-
- const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
- setTabValue(newValue);
- };
-
- // --- 1. TSC Section States ---
- const [tscConfig, setTscConfig] = useState({ ip: '192.168.1.100', port: '9100' });
- const [tscItems, setTscItems] = useState([
- { id: 1, itemCode: 'FG-001', itemName: 'Yellow Curry Sauce', lotNo: 'LOT-TSC-01', expiryDate: '2025-12-01' },
- { id: 2, itemCode: 'FG-002', itemName: 'Red Curry Paste', lotNo: 'LOT-TSC-02', expiryDate: '2025-12-05' },
- ]);
-
- // --- 2. DataFlex Section States ---
- const [dfConfig, setDfConfig] = useState({ ip: '192.168.1.101', port: '9100' });
- const [dfItems, setDfItems] = useState([
- { id: 1, itemCode: 'DF-101', itemName: 'Instant Noodle A', lotNo: 'LOT-DF-01', expiryDate: '2026-01-10' },
- { id: 2, itemCode: 'DF-102', itemName: 'Instant Noodle B', lotNo: 'LOT-DF-02', expiryDate: '2026-01-15' },
- ]);
-
- // --- 3. OnPack Section States ---
- const [isPrinterModalOpen, setIsPrinterModalOpen] = useState(false);
- const [printerFormData, setPrinterFormData] = useState({
- itemCode: '',
- lotNo: '',
- expiryDate: dayjs().format('YYYY-MM-DD'),
- productName: ''
- });
-
- // --- 4. Laser Section States ---
- const [laserConfig, setLaserConfig] = useState({ ip: '192.168.1.102', port: '8080' });
- const [laserItems, setLaserItems] = useState([
- { id: 1, templateId: 'JOB_001', lotNo: 'L-LASER-01', expiryDate: '2025-12-31', power: '50' },
- ]);
-
- // --- 5. HANS600S-M Section States ---
- const [hansConfig, setHansConfig] = useState({ ip: '192.168.76.10', port: '45678' });
- const [hansItems, setHansItems] = useState([
- {
- id: 1,
- textChannel3: 'SN-HANS-001-20260117', // channel 3 (e.g. serial / text1)
- textChannel4: 'BATCH-HK-TEST-OK', // channel 4 (e.g. batch / text2)
- text3ObjectName: 'Text3', // EZCAD object name for channel 3
- text4ObjectName: 'Text4' // EZCAD object name for channel 4
- },
- ]);
-
- // --- 6. GRN Preview (M18) ---
- const [grnPreviewReceiptDate, setGrnPreviewReceiptDate] = useState("2026-03-16");
- // --- 7. M18 PO Sync by Code ---
- const [m18PoCode, setM18PoCode] = useState("");
- const [isSyncingM18Po, setIsSyncingM18Po] = useState(false);
- const [m18PoSyncResult, setM18PoSyncResult] = useState<string>("");
-
- // Generic handler for inline table edits
- const handleItemChange = (setter: any, id: number, field: string, value: string) => {
- setter((prev: any[]) => prev.map(item =>
- item.id === id ? { ...item, [field]: value } : item
- ));
- };
-
- // --- API CALLS ---
-
- // TSC Print (Section 1)
- const handleTscPrint = async (row: any) => {
- const payload = { ...row, printerIp: tscConfig.ip, printerPort: tscConfig.port };
- try {
- const response = await clientAuthFetch(`${NEXT_PUBLIC_API_URL}/plastic/print-tsc`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(payload)
- });
- if (response.status === 401 || response.status === 403) return;
- if (response.ok) alert(`TSC Print Command Sent for ${row.itemCode}!`);
- else alert("TSC Print Failed");
- } catch (e) { console.error("TSC Error:", e); }
- };
-
- // DataFlex Print (Section 2)
- const handleDfPrint = async (row: any) => {
- const payload = { ...row, printerIp: dfConfig.ip, printerPort: dfConfig.port };
- try {
- const response = await clientAuthFetch(`${NEXT_PUBLIC_API_URL}/plastic/print-dataflex`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(payload)
- });
- if (response.status === 401 || response.status === 403) return;
- if (response.ok) alert(`DataFlex Print Command Sent for ${row.itemCode}!`);
- else alert("DataFlex Print Failed");
- } catch (e) { console.error("DataFlex Error:", e); }
- };
-
- // OnPack Zip Download (Section 3)
- const handleDownloadPrintJob = async () => {
- const params = new URLSearchParams(printerFormData);
- try {
- const response = await clientAuthFetch(`${NEXT_PUBLIC_API_URL}/plastic/get-printer6?${params.toString()}`, {
- method: 'GET',
- });
-
- if (response.status === 401 || response.status === 403) return;
- if (!response.ok) throw new Error('Download failed');
-
- const blob = await response.blob();
- const url = window.URL.createObjectURL(blob);
- const link = document.createElement('a');
- link.href = url;
- link.setAttribute('download', `${printerFormData.lotNo || 'OnPack'}.zip`);
- document.body.appendChild(link);
- link.click();
- link.remove();
- window.URL.revokeObjectURL(url);
-
- setIsPrinterModalOpen(false);
- } catch (e) { console.error("OnPack Error:", e); }
- };
-
- // Laser Print (Section 4 - original)
- const handleLaserPrint = async (row: any) => {
- const payload = { ...row, printerIp: laserConfig.ip, printerPort: laserConfig.port };
- try {
- const response = await clientAuthFetch(`${NEXT_PUBLIC_API_URL}/plastic/print-laser`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(payload)
- });
- if (response.status === 401 || response.status === 403) return;
- if (response.ok) alert(`Laser Command Sent: ${row.templateId}`);
- } catch (e) { console.error(e); }
- };
-
- const handleLaserPreview = async (row: any) => {
- const payload = { ...row, printerIp: laserConfig.ip, printerPort: parseInt(laserConfig.port) };
- try {
- const response = await clientAuthFetch(`${NEXT_PUBLIC_API_URL}/plastic/preview-laser`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(payload)
- });
- if (response.status === 401 || response.status === 403) return;
- if (response.ok) alert("Red light preview active!");
- } catch (e) { console.error("Preview Error:", e); }
- };
-
- // HANS600S-M TCP Print (Section 5)
- const handleHansPrint = async (row: any) => {
- const payload = {
- printerIp: hansConfig.ip,
- printerPort: hansConfig.port,
- textChannel3: row.textChannel3,
- textChannel4: row.textChannel4,
- text3ObjectName: row.text3ObjectName,
- text4ObjectName: row.text4ObjectName
- };
- try {
- const response = await clientAuthFetch(`${NEXT_PUBLIC_API_URL}/plastic/print-laser-tcp`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(payload)
- });
- if (response.status === 401 || response.status === 403) return;
- const result = await response.text();
- if (response.ok) {
- alert(`HANS600S-M Mark Success: ${result}`);
- } else {
- alert(`HANS600S-M Failed: ${result}`);
- }
- } catch (e) {
- console.error("HANS600S-M Error:", e);
- alert("HANS600S-M Connection Error");
- }
- };
-
- // GRN Preview CSV Download (Section 6)
- const handleDownloadGrnPreviewXlsx = async () => {
- try {
- const response = await clientAuthFetch(
- `${NEXT_PUBLIC_API_URL}/report/grn-preview-m18?receiptDate=${encodeURIComponent(grnPreviewReceiptDate)}`,
- { method: "GET" },
- );
- if (response.status === 401 || response.status === 403) return;
- if (!response.ok) throw new Error(`Download failed: ${response.status}`);
-
- const data = await response.json();
- const rows = Array.isArray(data?.rows) ? data.rows : [];
-
- const ws = XLSX.utils.json_to_sheet(rows);
- const wb = XLSX.utils.book_new();
- XLSX.utils.book_append_sheet(wb, ws, "GRN Preview");
-
- const xlsxArrayBuffer = XLSX.write(wb, { bookType: "xlsx", type: "array" });
- const blob = new Blob([xlsxArrayBuffer], {
- type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
- });
-
- const url = window.URL.createObjectURL(blob);
- const link = document.createElement("a");
- link.href = url;
- link.setAttribute("download", `grn-preview-m18-${grnPreviewReceiptDate}.xlsx`);
- document.body.appendChild(link);
- link.click();
- link.remove();
- window.URL.revokeObjectURL(url);
- } catch (e) {
- console.error("GRN Preview XLSX Download Error:", e);
- alert("GRN Preview XLSX download failed. Check console/network.");
- }
- };
-
- // M18 PO Sync By Code (Section 7)
- const handleSyncM18PoByCode = async () => {
- if (!m18PoCode.trim()) {
- alert("Please enter PO code.");
- return;
- }
- setIsSyncingM18Po(true);
- setM18PoSyncResult("");
- try {
- const response = await clientAuthFetch(
- `${NEXT_PUBLIC_API_URL}/m18/test/po-by-code?code=${encodeURIComponent(m18PoCode.trim())}`,
- { method: "GET" },
- );
- if (response.status === 401 || response.status === 403) return;
- const text = await response.text();
- setM18PoSyncResult(text);
- if (!response.ok) {
- alert(`Sync failed: ${response.status}`);
- }
- } catch (e) {
- console.error("M18 PO Sync By Code Error:", e);
- alert("M18 PO sync failed. Check console/network.");
- } finally {
- setIsSyncingM18Po(false);
- }
- };
-
- // Layout Helper
- const Section = ({ title, children }: { title: string, children?: React.ReactNode }) => (
- <Paper sx={{ p: 3, minHeight: '450px', display: 'flex', flexDirection: 'column' }}>
- <Typography variant="h5" gutterBottom color="primary" sx={{ borderBottom: '2px solid #f0f0f0', pb: 1, mb: 2 }}>
- {title}
- </Typography>
- {children || <Typography color="textSecondary" sx={{ m: 'auto' }}>Waiting for implementation...</Typography>}
- </Paper>
- );
-
- return (
- <Box sx={{ p: 4 }}>
- <Typography variant="h4" sx={{ mb: 4, fontWeight: 'bold' }}>Printer Testing</Typography>
-
- <Tabs value={tabValue} onChange={handleTabChange} aria-label="printer sections tabs" centered variant="fullWidth">
- <Tab label="1. TSC" />
- <Tab label="2. DataFlex" />
- <Tab label="3. OnPack" />
- <Tab label="4. Laser" />
- <Tab label="5. HANS600S-M" />
- <Tab label="6. GRN Preview" />
- <Tab label="7. M18 PO Sync" />
- </Tabs>
-
- <TabPanel value={tabValue} index={0}>
- <Section title="1. TSC">
- <Stack direction="row" spacing={2} sx={{ mb: 2 }}>
- <TextField size="small" label="Printer IP" value={tscConfig.ip} onChange={e => setTscConfig({...tscConfig, ip: e.target.value})} />
- <TextField size="small" label="Port" value={tscConfig.port} onChange={e => setTscConfig({...tscConfig, port: e.target.value})} />
- <SettingsEthernet color="action" />
- </Stack>
- <TableContainer component={Paper} variant="outlined" sx={{ maxHeight: 300 }}>
- <Table size="small" stickyHeader>
- <TableHead>
- <TableRow>
- <TableCell>Code</TableCell>
- <TableCell>Name</TableCell>
- <TableCell>Lot</TableCell>
- <TableCell>Expiry</TableCell>
- <TableCell align="center">Action</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {tscItems.map(row => (
- <TableRow key={row.id}>
- <TableCell><TextField variant="standard" value={row.itemCode} onChange={e => handleItemChange(setTscItems, row.id, 'itemCode', e.target.value)} /></TableCell>
- <TableCell><TextField variant="standard" value={row.itemName} onChange={e => handleItemChange(setTscItems, row.id, 'itemName', e.target.value)} /></TableCell>
- <TableCell><TextField variant="standard" value={row.lotNo} onChange={e => handleItemChange(setTscItems, row.id, 'lotNo', e.target.value)} /></TableCell>
- <TableCell><TextField variant="standard" type="date" value={row.expiryDate} onChange={e => handleItemChange(setTscItems, row.id, 'expiryDate', e.target.value)} /></TableCell>
- <TableCell align="center"><Button variant="contained" size="small" startIcon={<Print />} onClick={() => handleTscPrint(row)}>Print</Button></TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
- </TableContainer>
- </Section>
- </TabPanel>
-
- <TabPanel value={tabValue} index={1}>
- <Section title="2. DataFlex">
- <Stack direction="row" spacing={2} sx={{ mb: 2 }}>
- <TextField size="small" label="Printer IP" value={dfConfig.ip} onChange={e => setDfConfig({...dfConfig, ip: e.target.value})} />
- <TextField size="small" label="Port" value={dfConfig.port} onChange={e => setDfConfig({...dfConfig, port: e.target.value})} />
- <Lan color="action" />
- </Stack>
- <TableContainer component={Paper} variant="outlined" sx={{ maxHeight: 300 }}>
- <Table size="small" stickyHeader>
- <TableHead>
- <TableRow>
- <TableCell>Code</TableCell>
- <TableCell>Name</TableCell>
- <TableCell>Lot</TableCell>
- <TableCell>Expiry</TableCell>
- <TableCell align="center">Action</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {dfItems.map(row => (
- <TableRow key={row.id}>
- <TableCell><TextField variant="standard" value={row.itemCode} onChange={e => handleItemChange(setDfItems, row.id, 'itemCode', e.target.value)} /></TableCell>
- <TableCell><TextField variant="standard" value={row.itemName} onChange={e => handleItemChange(setDfItems, row.id, 'itemName', e.target.value)} /></TableCell>
- <TableCell><TextField variant="standard" value={row.lotNo} onChange={e => handleItemChange(setDfItems, row.id, 'lotNo', e.target.value)} /></TableCell>
- <TableCell><TextField variant="standard" type="date" value={row.expiryDate} onChange={e => handleItemChange(setDfItems, row.id, 'expiryDate', e.target.value)} /></TableCell>
- <TableCell align="center"><Button variant="contained" color="secondary" size="small" startIcon={<Print />} onClick={() => handleDfPrint(row)}>Print</Button></TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
- </TableContainer>
- </Section>
- </TabPanel>
-
- <TabPanel value={tabValue} index={2}>
- <Section title="3. OnPack">
- <Box sx={{ m: 'auto', textAlign: 'center' }}>
- <Typography variant="body2" color="textSecondary" sx={{ mb: 2 }}>
- Calls /plastic/get-printer6 to generate CoLOS .job bundle.
- </Typography>
- <Button variant="contained" color="success" size="large" startIcon={<FileDownload />} onClick={() => setIsPrinterModalOpen(true)}>
- Generate CoLOS Files
- </Button>
- </Box>
- </Section>
- </TabPanel>
-
- <TabPanel value={tabValue} index={3}>
- <Section title="4. Laser">
- <Stack direction="row" spacing={2} sx={{ mb: 2 }}>
- <TextField size="small" label="Laser IP" value={laserConfig.ip} onChange={e => setLaserConfig({...laserConfig, ip: e.target.value})} />
- <TextField size="small" label="Port" value={laserConfig.port} onChange={e => setLaserConfig({...laserConfig, port: e.target.value})} />
- <Router color="action" />
- </Stack>
-
- <TableContainer component={Paper} variant="outlined" sx={{ maxHeight: 300 }}>
- <Table size="small" stickyHeader>
- <TableHead>
- <TableRow>
- <TableCell>Template</TableCell>
- <TableCell>Lot</TableCell>
- <TableCell>Exp</TableCell>
- <TableCell>Pwr%</TableCell>
- <TableCell align="center">Action</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {laserItems.map(row => (
- <TableRow key={row.id}>
- <TableCell><TextField variant="standard" value={row.templateId} onChange={e => handleItemChange(setLaserItems, row.id, 'templateId', e.target.value)} /></TableCell>
- <TableCell><TextField variant="standard" value={row.lotNo} onChange={e => handleItemChange(setLaserItems, row.id, 'lotNo', e.target.value)} /></TableCell>
- <TableCell><TextField variant="standard" type="date" value={row.expiryDate} onChange={e => handleItemChange(setLaserItems, row.id, 'expiryDate', e.target.value)} /></TableCell>
- <TableCell><TextField variant="standard" value={row.power} sx={{ width: 40 }} onChange={e => handleItemChange(setLaserItems, row.id, 'power', e.target.value)} /></TableCell>
- <TableCell align="center">
- <Stack direction="row" spacing={1} justifyContent="center">
- <Button
- variant="outlined"
- color="info"
- size="small"
- onClick={() => handleLaserPreview(row)}
- >
- Preview
- </Button>
- <Button
- variant="contained"
- color="warning"
- size="small"
- startIcon={<Print />}
- onClick={() => handleLaserPrint(row)}
- >
- Mark
- </Button>
- </Stack>
- </TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
- </TableContainer>
- <Typography variant="caption" sx={{ mt: 2, display: 'block', color: 'text.secondary' }}>
- Note: HANS Laser requires pre-saved templates on the controller.
- </Typography>
- </Section>
- </TabPanel>
-
- <TabPanel value={tabValue} index={4}>
- <Section title="5. HANS600S-M">
- <Stack direction="row" spacing={2} sx={{ mb: 2 }}>
- <TextField
- size="small"
- label="Laser IP"
- value={hansConfig.ip}
- onChange={e => setHansConfig({...hansConfig, ip: e.target.value})}
- />
- <TextField
- size="small"
- label="Port"
- value={hansConfig.port}
- onChange={e => setHansConfig({...hansConfig, port: e.target.value})}
- />
- <Router color="action" sx={{ ml: 'auto' }} />
- </Stack>
-
- <TableContainer component={Paper} variant="outlined" sx={{ maxHeight: 300 }}>
- <Table size="small" stickyHeader>
- <TableHead>
- <TableRow>
- <TableCell>Ch3 Text (SN)</TableCell>
- <TableCell>Ch4 Text (Batch)</TableCell>
- <TableCell>Obj3 Name</TableCell>
- <TableCell>Obj4 Name</TableCell>
- <TableCell align="center">Action</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {hansItems.map(row => (
- <TableRow key={row.id}>
- <TableCell>
- <TextField
- variant="standard"
- value={row.textChannel3}
- onChange={e => handleItemChange(setHansItems, row.id, 'textChannel3', e.target.value)}
- sx={{ minWidth: 180 }}
- />
- </TableCell>
- <TableCell>
- <TextField
- variant="standard"
- value={row.textChannel4}
- onChange={e => handleItemChange(setHansItems, row.id, 'textChannel4', e.target.value)}
- sx={{ minWidth: 140 }}
- />
- </TableCell>
- <TableCell>
- <TextField
- variant="standard"
- value={row.text3ObjectName}
- onChange={e => handleItemChange(setHansItems, row.id, 'text3ObjectName', e.target.value)}
- size="small"
- />
- </TableCell>
- <TableCell>
- <TextField
- variant="standard"
- value={row.text4ObjectName}
- onChange={e => handleItemChange(setHansItems, row.id, 'text4ObjectName', e.target.value)}
- size="small"
- />
- </TableCell>
- <TableCell align="center">
- <Button
- variant="contained"
- color="error"
- size="small"
- startIcon={<Print />}
- onClick={() => handleHansPrint(row)}
- sx={{ minWidth: 80 }}
- >
- TCP Mark
- </Button>
- </TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
- </TableContainer>
- <Typography variant="caption" sx={{ mt: 2, display: 'block', color: 'text.secondary', fontSize: '0.75rem' }}>
- TCP Push to EZCAD3 (Ch3/Ch4 via E3_SetTextObject) | IP:192.168.76.10:45678 | Backend: /print-laser-tcp
- </Typography>
- </Section>
- </TabPanel>
-
- <TabPanel value={tabValue} index={5}>
- <Section title="6. GRN Preview (M18)">
- <Stack direction="row" spacing={2} sx={{ mb: 2, alignItems: "center" }}>
- <TextField
- size="small"
- label="Receipt Date"
- type="date"
- value={grnPreviewReceiptDate}
- onChange={(e) => setGrnPreviewReceiptDate(e.target.value)}
- InputLabelProps={{ shrink: true }}
- />
- <Button
- variant="contained"
- color="success"
- size="medium"
- startIcon={<FileDownload />}
- onClick={handleDownloadGrnPreviewXlsx}
- >
- Download GRN Preview XLSX
- </Button>
- </Stack>
- <Typography variant="body2" color="textSecondary">
- Backend endpoint: <code>/report/grn-preview-m18?receiptDate=YYYY-MM-DD</code>
- </Typography>
- </Section>
- </TabPanel>
-
- <TabPanel value={tabValue} index={6}>
- <Section title="7. M18 PO Sync by Code">
- <Stack direction="row" spacing={2} sx={{ mb: 2, alignItems: "center" }}>
- <TextField
- size="small"
- label="PO Code"
- value={m18PoCode}
- onChange={(e) => setM18PoCode(e.target.value)}
- placeholder="e.g. PFP002PO26030341"
- sx={{ minWidth: 320 }}
- />
- <Button
- variant="contained"
- color="primary"
- onClick={handleSyncM18PoByCode}
- disabled={isSyncingM18Po}
- >
- {isSyncingM18Po ? "Syncing..." : "Sync PO from M18"}
- </Button>
- </Stack>
- <Typography variant="body2" color="textSecondary">
- Backend endpoint: <code>/m18/test/po-by-code?code=YOUR_CODE</code>
- </Typography>
- {m18PoSyncResult ? (
- <TextField
- fullWidth
- multiline
- minRows={4}
- margin="normal"
- label="Sync Result"
- value={m18PoSyncResult}
- InputProps={{ readOnly: true }}
- />
- ) : null}
- </Section>
- </TabPanel>
-
- {/* Dialog for OnPack */}
- <Dialog open={isPrinterModalOpen} onClose={() => setIsPrinterModalOpen(false)} fullWidth maxWidth="sm">
- <DialogTitle sx={{ bgcolor: 'success.main', color: 'white' }}>OnPack Printer Job Details</DialogTitle>
- <DialogContent sx={{ mt: 2 }}>
- <Stack spacing={3}>
- <TextField label="Item Code" fullWidth value={printerFormData.itemCode} onChange={(e) => setPrinterFormData({ ...printerFormData, itemCode: e.target.value })} />
- <TextField label="Lot Number" fullWidth value={printerFormData.lotNo} onChange={(e) => setPrinterFormData({ ...printerFormData, lotNo: e.target.value })} />
- <TextField label="Product Name" fullWidth value={printerFormData.productName} onChange={(e) => setPrinterFormData({ ...printerFormData, productName: e.target.value })} />
- <TextField label="Expiry Date" type="date" fullWidth InputLabelProps={{ shrink: true }} value={printerFormData.expiryDate} onChange={(e) => setPrinterFormData({ ...printerFormData, expiryDate: e.target.value })} />
- </Stack>
- </DialogContent>
- <DialogActions sx={{ p: 3 }}>
- <Button onClick={() => setIsPrinterModalOpen(false)} variant="outlined" color="inherit">Cancel</Button>
- <Button variant="contained" color="success" onClick={handleDownloadPrintJob}>Generate & Download</Button>
- </DialogActions>
- </Dialog>
- </Box>
- );
- }
|