|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- "use client";
-
- import { createPrinter, PrinterInputs, fetchPrinterDescriptions } from "@/app/api/settings/printer/actions";
- import { successDialog } from "@/components/Swal/CustomAlerts";
- import { ArrowBack, Check } from "@mui/icons-material";
- import {
- Autocomplete,
- Box,
- Button,
- FormControl,
- Grid,
- InputLabel,
- MenuItem,
- Select,
- SelectChangeEvent,
- Stack,
- TextField,
- } from "@mui/material";
- import { useRouter } from "next/navigation";
- import { useCallback, useEffect, useState } from "react";
- import { useTranslation } from "react-i18next";
-
- const CreatePrinter: React.FC = () => {
- const { t } = useTranslation("common");
- const router = useRouter();
- const [isSubmitting, setIsSubmitting] = useState(false);
- const [descriptions, setDescriptions] = useState<string[]>([]);
- const [formData, setFormData] = useState<PrinterInputs>({
- name: "",
- ip: "",
- port: undefined,
- type: "A4",
- dpi: undefined,
- description: "",
- });
-
- useEffect(() => {
- const loadDescriptions = async () => {
- try {
- const descs = await fetchPrinterDescriptions();
- setDescriptions(descs);
- } catch (error) {
- console.error("Failed to load descriptions:", error);
- }
- };
- loadDescriptions();
- }, []);
-
- useEffect(() => {
- if (formData.type !== "Label") {
- setFormData((prev) => ({ ...prev, dpi: undefined }));
- }
- }, [formData.type]);
-
- const handleChange = useCallback((field: keyof PrinterInputs) => {
- return (e: React.ChangeEvent<HTMLInputElement>) => {
- const value = e.target.value;
- setFormData((prev) => ({
- ...prev,
- [field]:
- field === "port" || field === "dpi"
- ? value === ""
- ? undefined
- : parseInt(value, 10)
- : value,
- }));
- };
- }, []);
-
- const handleTypeChange = useCallback((e: SelectChangeEvent) => {
- setFormData((prev) => ({
- ...prev,
- type: e.target.value,
- }));
- }, []);
-
- const handleDescriptionChange = useCallback((_e: any, newValue: string | null) => {
- setFormData((prev) => ({
- ...prev,
- description: newValue || "",
- }));
- }, []);
-
- const handleSubmit = useCallback(async () => {
- setIsSubmitting(true);
- try {
- const needDpi = formData.type === "Label";
- const missing: string[] = [];
- if (!formData.ip || formData.ip.trim() === "") missing.push("IP");
- if (formData.port === undefined || formData.port === null || Number.isNaN(formData.port)) missing.push("Port");
- if (!formData.type || formData.type.trim() === "") missing.push(t("Type") || "類型");
- if (needDpi && (formData.dpi === undefined || formData.dpi === null || Number.isNaN(formData.dpi))) missing.push("DPI");
- if (missing.length > 0) {
- alert(`請必須輸入 ${missing.join("、")}`);
- setIsSubmitting(false);
- return;
- }
-
- await createPrinter(formData);
- successDialog(t("Create Printer") || "新增列印機", t);
- router.push("/settings/printer");
- router.refresh();
- } catch (error) {
- const errorMessage =
- error instanceof Error
- ? error.message
- : t("Error saving data") || "儲存失敗";
- alert(errorMessage);
- } finally {
- setIsSubmitting(false);
- }
- }, [formData, router, t]);
-
- return (
- <Box sx={{ mt: 3 }}>
- <Grid container spacing={3}>
- <Grid item xs={12} md={6}>
- <TextField
- fullWidth
- label={t("Name")}
- value={formData.name}
- onChange={handleChange("name")}
- variant="outlined"
- />
- </Grid>
- <Grid item xs={12} md={6}>
- <TextField
- fullWidth
- label="IP"
- value={formData.ip}
- onChange={handleChange("ip")}
- variant="outlined"
- />
- </Grid>
- <Grid item xs={12} md={6}>
- <TextField
- fullWidth
- label="Port"
- type="number"
- value={formData.port ?? ""}
- onChange={handleChange("port")}
- variant="outlined"
- />
- </Grid>
- <Grid item xs={12} md={6}>
- <FormControl fullWidth>
- <InputLabel>{t("Type")}</InputLabel>
- <Select
- label={t("Type")}
- value={formData.type ?? "A4"}
- onChange={handleTypeChange}
- >
- <MenuItem value={"A4"}>A4</MenuItem>
- <MenuItem value={"Label"}>Label</MenuItem>
- </Select>
- </FormControl>
- </Grid>
- <Grid item xs={12} md={6}>
- <TextField
- fullWidth
- label="DPI"
- type="number"
- value={formData.dpi ?? ""}
- onChange={handleChange("dpi")}
- variant="outlined"
- disabled={formData.type !== "Label"}
- />
- </Grid>
- <Grid item xs={12} md={6}>
- <Autocomplete
- freeSolo
- options={descriptions}
- value={formData.description || null}
- onChange={handleDescriptionChange}
- onInputChange={(_e, newInputValue) => {
- setFormData((prev) => ({
- ...prev,
- description: newInputValue,
- }));
- }}
- renderInput={(params) => (
- <TextField
- {...params}
- label={t("Description")}
- variant="outlined"
- fullWidth
- />
- )}
- />
- </Grid>
- <Grid item xs={12}>
- <Stack direction="row" spacing={2}>
- <Button
- variant="outlined"
- startIcon={<ArrowBack />}
- onClick={() => router.push("/settings/printer")}
- >
- {t("Back")}
- </Button>
- <Button
- variant="contained"
- startIcon={<Check />}
- onClick={handleSubmit}
- disabled={isSubmitting}
- >
- {t("Save")}
- </Button>
- </Stack>
- </Grid>
- </Grid>
- </Box>
- );
- };
-
- const CreatePrinterLoading: React.FC = () => {
- return null;
- };
-
- export default Object.assign(CreatePrinter, { Loading: CreatePrinterLoading });
-
|