"feat: Added debug server and related components for improved development experience"
This commit is contained in:
169
frontend/src/app/printer/[printerId]/reserve/form.tsx
Normal file
169
frontend/src/app/printer/[printerId]/reserve/form.tsx
Normal file
@@ -0,0 +1,169 @@
|
||||
"use client";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { DialogClose } from "@/components/ui/dialog";
|
||||
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { createPrintJob } from "@/server/actions/printJobs";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { CalendarPlusIcon, XCircleIcon } from "lucide-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { If, Then } from "react-if";
|
||||
import { z } from "zod";
|
||||
|
||||
export const formSchema = z.object({
|
||||
hours: z.coerce.number().int().min(0).max(96, {
|
||||
message: "Die Stunden müssen zwischen 0 und 96 liegen.",
|
||||
}),
|
||||
minutes: z.coerce.number().int().min(0).max(59, {
|
||||
message: "Die Minuten müssen zwischen 0 und 59 liegen.",
|
||||
}),
|
||||
comments: z.string().optional(),
|
||||
});
|
||||
|
||||
interface PrinterReserveFormProps {
|
||||
userId: string;
|
||||
printerId: string;
|
||||
isDialog?: boolean;
|
||||
}
|
||||
|
||||
export function PrinterReserveForm(props: PrinterReserveFormProps) {
|
||||
const { userId, printerId, isDialog } = props;
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
const [isLocked, setLocked] = useState(false);
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
hours: 0,
|
||||
minutes: 0,
|
||||
comments: "",
|
||||
},
|
||||
});
|
||||
|
||||
async function onSubmit(values: z.infer<typeof formSchema>) {
|
||||
if (!isLocked) {
|
||||
setLocked(true);
|
||||
setTimeout(() => {
|
||||
setLocked(false);
|
||||
}, 1000 * 5);
|
||||
} else {
|
||||
toast({
|
||||
description: "Bitte warte ein wenig, bevor du eine weitere Reservierung tätigst...",
|
||||
variant: "default",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (values.hours === 0 && values.minutes === 0) {
|
||||
form.setError("hours", {
|
||||
message: "",
|
||||
});
|
||||
form.setError("minutes", {
|
||||
message: "Die Dauer des Druckauftrags muss mindestens 1 Minute betragen.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const jobId = await createPrintJob({
|
||||
durationInMinutes: values.hours * 60 + values.minutes,
|
||||
comments: values.comments,
|
||||
userId: userId,
|
||||
printerId: printerId,
|
||||
});
|
||||
if (typeof jobId === "object") {
|
||||
toast({
|
||||
description: jobId.error,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
|
||||
router.push(`/job/${jobId}`);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
toast({ variant: "destructive", description: error.message });
|
||||
} else {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
description: "Ein unbekannter Fehler ist aufgetreten.",
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
toast({ description: "Druckauftrag wurde erfolgreich erstellt." });
|
||||
}
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
|
||||
<div className="flex flex-row gap-2">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="hours"
|
||||
render={({ field }) => (
|
||||
<FormItem className="w-1/2">
|
||||
<FormLabel>Stunden</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="0" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="minutes"
|
||||
render={({ field }) => (
|
||||
<FormItem className="w-1/2">
|
||||
<FormLabel>Minuten</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="0" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="comments"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Anmerkungen</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea placeholder="" {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
In dieses Feld kannst du Anmerkungen zu deinem Druckauftrag hinzufügen. Sie können beispielsweise
|
||||
Informationen über das Druckmaterial, die Druckqualität oder die Farbe enthalten.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<div className="flex justify-between items-center">
|
||||
<If condition={isDialog}>
|
||||
<Then>
|
||||
<DialogClose asChild>
|
||||
<Button variant={"secondary"} className="gap-2 flex items-center">
|
||||
<XCircleIcon className="w-4 h-4" />
|
||||
<span>Abbrechen</span>
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</Then>
|
||||
</If>
|
||||
<Button type="submit" className="gap-2 flex items-center" disabled={isLocked}>
|
||||
<CalendarPlusIcon className="w-4 h-4" />
|
||||
<span>Reservieren</span>
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
36
frontend/src/app/printer/[printerId]/reserve/page.tsx
Normal file
36
frontend/src/app/printer/[printerId]/reserve/page.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { PrinterReserveForm } from "@/app/printer/[printerId]/reserve/form";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { validateRequest } from "@/server/auth";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Drucker reservieren",
|
||||
};
|
||||
|
||||
interface PrinterReservePageProps {
|
||||
params: {
|
||||
printerId: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default async function PrinterReservePage(props: PrinterReservePageProps) {
|
||||
const { user } = await validateRequest();
|
||||
const { printerId } = props.params;
|
||||
|
||||
if (!user) {
|
||||
return redirect("/");
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Drucker reservieren</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<PrinterReserveForm userId={user?.id} printerId={printerId} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user