Files
2025-11-08 13:42:43 +01:00

294 lines
13 KiB
TypeScript

"use Client";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Separator } from "@/components/ui/separator";
import { Plus } from "lucide-react";
import { useFieldArray } from "react-hook-form";
import { alterVorlage } from "./action";
import { useState } from "react";
type TableData = {
id: number;
product_type: string;
height: number;
width: number;
printer: string;
coordinates: { x: number; y: number; rotation: number }[];
};
type AlterDialogProps = {
onNewEntry: () => void;
data: TableData;
};
export default function AlterDialog({ onNewEntry, data }: AlterDialogProps) {
const [open, setOpen] = useState(false)
const formSchema = z.object({
Drucker: z.string().min(1, {
message: "Druckername muss mindestens 2 Zeichen lang sein.",
}),
Artikeltyp: z.string().min(1, {
message: "Artikeltyp muss mindestens 2 Zeichen lang sein.",
}),
Höhe: z.preprocess(
(value) => (typeof value === "string" ? parseFloat(value) : value),
z.number({
invalid_type_error: "Höhe muss eine gültige Zahl sein. Bspw. 1.5 .",
}).min(1, {
message: "Höhe muss mindestens 1 sein.",
})
),
Breite: z.preprocess(
(value) => (typeof value === "string" ? parseFloat(value) : value),
z.number({
invalid_type_error: "Breite muss eine gültige Zahl sein. Bspw. 1.5 .",
}).min(1, {
message: "Breite muss mindestens 1 sein.",
})
),
Koordinaten: z.array(
z.object({
x: z.preprocess(
(value) => (typeof value === "string" ? parseFloat(value) : value),
z.number().min(0, {
message: "X-Koordinate muss mindestens 0 sein.",
})
),
y: z.preprocess(
(value) => (typeof value === "string" ? parseFloat(value) : value),
z.number().min(0, {
message: "Y-Koordinate muss mindestens 0 sein.",
})
),
rotation: z.preprocess(
(value) => (typeof value === "string" ? parseFloat(value) : value),
z.number().min(0, {
message: "Rotation muss mindestens 0 sein.",
})
),
})
).min(1, {
message: "Es muss mindestens eine Koordinate angegeben werden.",
}),
});
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
Drucker: data.printer,
Artikeltyp: data.product_type,
Höhe: data.height,
Breite: data.width,
Koordinaten: data.coordinates.map((coord) => ({
x: coord.x,
y: coord.y,
rotation: coord.rotation,
})),
},
});
const { fields, append, remove } = useFieldArray({
control: form.control,
name: "Koordinaten",
});
async function onSubmit(values: z.infer<typeof formSchema>) {
const formData = new FormData();
formData.append("id", data.id.toString());
formData.append("printer", values.Drucker);
formData.append("product_type", values.Artikeltyp);
formData.append("height", values.Höhe.toString());
formData.append("width", values.Breite.toString());
formData.append("coordinates", JSON.stringify(values.Koordinaten));
try {
await alterVorlage(formData);
setOpen(false);
form.reset();
onNewEntry();
}
catch (error) {
console.error("Error submitting form:", error);
throw new Error("An error occurred while submitting the form.");
}
}
return (
<div>
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button variant="ghost" className="font-normal pl-2">
Vorlage bearbeiten
</Button>
</DialogTrigger>
<DialogContent className="max-w-screen-lg max-h-screen overflow-y-auto">
<DialogHeader>
<DialogTitle className="mb-8">Vorlage bearbeiten</DialogTitle>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="Drucker"
render={({ field }) => (
<FormItem>
<FormLabel>Drucker Name</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<DialogDescription>
Der Name des Druckers, auf dem die Vorlage gedruckt wird.
</DialogDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="Artikeltyp"
render={({ field }) => (
<FormItem>
<FormLabel>Artikel Typ</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<DialogDescription>
Der Name des Artikels, der auf der Vorlage gedruckt wird.
</DialogDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="Höhe"
render={({ field }) => (
<FormItem>
<FormLabel>Höhe</FormLabel>
<FormControl>
<Input type="number" step="any" {...field} />
</FormControl>
<FormDescription>
Die Höhe der Vorlage in Millimeter.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="Breite"
render={({ field }) => (
<FormItem>
<FormLabel>Breite</FormLabel>
<FormControl>
<Input type="number" step="any" {...field} />
</FormControl>
<FormDescription>
Die Breite der Vorlage in Millimeter.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<div className="max-h-64 overflow-y-auto">
<FormLabel className="mb-4">Koordinaten:</FormLabel>
<Separator />
{fields.map((field, index) => (
<div key={field.id} className="space-y-4">
<FormField
control={form.control}
name={`Koordinaten.${index}.x`}
render={({ field }) => (
<FormItem className="mt-4">
<FormLabel>X-Koordinate</FormLabel>
<FormControl>
<Input type="number" step="any" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name={`Koordinaten.${index}.y`}
render={({ field }) => (
<FormItem>
<FormLabel>Y-Koordinate</FormLabel>
<FormControl>
<Input type="number" step="any" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name={`Koordinaten.${index}.rotation`}
render={({ field }) => (
<FormItem>
<FormLabel>Rotation</FormLabel>
<FormControl>
<Input type="number" step="any" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="button"
variant="destructive"
onClick={() => remove(index)}
>
Entfernen
</Button>
<Separator className="mt-4" />
</div>
))}
<Button
type="button"
variant="outline"
onClick={() => append({ x: 0, y: 0, rotation: 0 })}
className="mt-4"
>
<Plus />
</Button>
</div>
<Button type="submit">
Änderungen speichern
</Button>
</form>
</Form>
</DialogHeader>
</DialogContent>
</Dialog>
</div>
);
}