fix error handling

This commit is contained in:
Torben Haack 2024-10-11 12:10:51 +02:00
parent 87606b9b9b
commit 555166db6c
11 changed files with 194 additions and 79 deletions

Binary file not shown.

View File

@ -29,7 +29,13 @@ export function DeletePrinterDialog(props: DeletePrinterDialogProps) {
description: "Drucker wird gelöscht...",
});
try {
await deletePrinter(printerId);
const result = await deletePrinter(printerId);
if (result?.error) {
toast({
description: result.error,
variant: "destructive",
});
}
toast({
description: "Drucker wurde gelöscht.",
});

View File

@ -57,11 +57,17 @@ export function PrinterForm(props: PrinterFormProps) {
// Update
try {
await updatePrinter(printer.id, {
const result = await updatePrinter(printer.id, {
description: values.description,
name: values.name,
status: values.status,
});
if (result?.error) {
toast({
description: result.error,
variant: "destructive",
});
}
setOpen(false);
@ -90,11 +96,17 @@ export function PrinterForm(props: PrinterFormProps) {
// Create
try {
await createPrinter({
const result = await createPrinter({
description: values.description,
name: values.name,
status: values.status,
});
if (result?.error) {
toast({
description: result.error,
variant: "destructive",
});
}
setOpen(false);

View File

@ -52,7 +52,13 @@ export function CancelForm(props: CancelFormProps) {
description: "Druckauftrag wird abgebrochen...",
});
try {
await abortPrintJob(jobId, values.abortReason);
const result = await abortPrintJob(jobId, values.abortReason);
if (result?.error) {
toast({
description: result.error,
variant: "destructive",
});
}
setOpen(false);
toast({
description: "Druckauftrag wurde abgebrochen.",

View File

@ -17,7 +17,13 @@ export function EditComments(props: EditCommentsProps) {
const debounced = useDebouncedCallback(async (value) => {
try {
await updatePrintComments(jobId, value);
const result = await updatePrintComments(jobId, value);
if (result?.error) {
toast({
description: result.error,
variant: "destructive",
});
}
toast({
description: "Anmerkungen wurden gespeichert.",
});

View File

@ -53,7 +53,14 @@ export function ExtendForm(props: ExtendFormProps) {
description: "Druckauftrag wird verlängert...",
});
try {
await extendPrintJob(jobId, values.minutes, values.hours);
const result = await extendPrintJob(jobId, values.minutes, values.hours);
if (result?.error) {
toast({
description: result.error,
variant: "destructive",
});
}
setOpen(false);
form.reset();

View File

@ -27,7 +27,13 @@ export function FinishForm(props: FinishFormProps) {
description: "Druckauftrag wird abgeschlossen...",
});
try {
await earlyFinishPrintJob(jobId);
const result = await earlyFinishPrintJob(jobId);
if (result?.error) {
toast({
description: result.error,
variant: "destructive",
});
}
toast({
description: "Druckauftrag wurde abgeschlossen.",
});

View File

@ -1,15 +1,7 @@
"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 { 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";
@ -17,6 +9,7 @@ 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";
@ -41,6 +34,7 @@ export function PrinterReserveForm(props: PrinterReserveFormProps) {
const { userId, printerId, isDialog } = props;
const router = useRouter();
const { toast } = useToast();
const [lock, setLocked] = useState(false);
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
@ -52,13 +46,22 @@ export function PrinterReserveForm(props: PrinterReserveFormProps) {
});
async function onSubmit(values: z.infer<typeof formSchema>) {
if (!lock) {
setLocked(true);
} 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.",
message: "Die Dauer des Druckauftrags muss mindestens 1 Minute betragen.",
});
return;
}
@ -70,6 +73,12 @@ export function PrinterReserveForm(props: PrinterReserveFormProps) {
userId: userId,
printerId: printerId,
});
if (typeof jobId === "object") {
toast({
description: jobId.error,
variant: "destructive",
});
}
router.push(`/job/${jobId}`);
} catch (error) {
@ -128,9 +137,8 @@ export function PrinterReserveForm(props: PrinterReserveFormProps) {
<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.
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>
@ -140,17 +148,14 @@ export function PrinterReserveForm(props: PrinterReserveFormProps) {
<If condition={isDialog}>
<Then>
<DialogClose asChild>
<Button
variant={"secondary"}
className="gap-2 flex items-center"
>
<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">
<Button type="submit" className="gap-2 flex items-center" disabled={lock}>
<CalendarPlusIcon className="w-4 h-4" />
<span>Reservieren</span>
</Button>

View File

@ -4,8 +4,8 @@ import { validateRequest } from "@/server/auth";
import { UserRole } from "@/server/auth/permissions";
import { db } from "@/server/db";
import { printJobs, users } from "@/server/db/schema";
import { PermissionError } from "@/utils/errors";
import { IS, guard } from "@/utils/guard";
import strings from "@/utils/strings";
import { type InferInsertModel, eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
@ -13,7 +13,9 @@ export async function createPrintJob(printJob: InferInsertModel<typeof printJobs
const { user } = await validateRequest();
if (guard(user, IS, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const dbUser = await db.query.users.findFirst({
@ -22,7 +24,9 @@ export async function createPrintJob(printJob: InferInsertModel<typeof printJobs
});
if (guard(dbUser, IS, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
try {
@ -32,7 +36,9 @@ export async function createPrintJob(printJob: InferInsertModel<typeof printJobs
return result[0].jobId;
} catch (error) {
throw new Error("Druckauftrag konnte nicht hinzugefügt werden.");
return {
error: "Druckauftrag konnte nicht hinzugefügt werden.",
};
}
}
@ -40,7 +46,9 @@ export async function createPrintJob(printJob: InferInsertModel<typeof printJobs
const { user } = await validateRequest();
if (guard(user, is, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION
}
}
const dbUser = await db.query.users.findFirst({
@ -49,7 +57,9 @@ export async function createPrintJob(printJob: InferInsertModel<typeof printJobs
});
if (guard(dbUser, is, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION
}
}
await db.update(printJobs).set(printJob).where(eq(printJobs.id, jobId));
@ -59,7 +69,9 @@ export async function abortPrintJob(jobId: string, reason: string) {
const { user } = await validateRequest();
if (guard(user, IS, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const dbUser = await db.query.users.findFirst({
@ -68,7 +80,9 @@ export async function abortPrintJob(jobId: string, reason: string) {
});
if (guard(dbUser, IS, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
// Get the print job
@ -77,22 +91,26 @@ export async function abortPrintJob(jobId: string, reason: string) {
});
if (!printJob) {
throw new Error("Druckauftrag nicht gefunden");
return {
error: "Druckauftrag nicht gefunden",
};
}
// Check if the print job is already aborted or completed
if (printJob.aborted) {
throw new Error("Druckauftrag wurde bereits abgebrochen");
return { error: "Druckauftrag wurde bereits abgebrochen" };
}
if (new Date(printJob.startAt).getTime() + printJob.durationInMinutes * 60 * 1000 < Date.now()) {
throw new Error("Druckauftrag ist bereits abgeschlossen");
return { error: "Druckauftrag ist bereits abgeschlossen" };
}
// Check if user is the owner of the print job
// biome-ignore lint/style/noNonNullAssertion: guard already checks against null
if (printJob.userId !== dbUser!.id && dbUser!.role !== UserRole.ADMIN) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
// Get duration in minutes since startAt
@ -115,7 +133,9 @@ export async function earlyFinishPrintJob(jobId: string) {
const { user } = await validateRequest();
if (guard(user, IS, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const dbUser = await db.query.users.findFirst({
@ -124,7 +144,9 @@ export async function earlyFinishPrintJob(jobId: string) {
});
if (guard(dbUser, IS, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
// Get the print job
@ -133,22 +155,24 @@ export async function earlyFinishPrintJob(jobId: string) {
});
if (!printJob) {
throw new Error("Druckauftrag nicht gefunden");
return { error: "Druckauftrag nicht gefunden" };
}
// Check if the print job is already aborted or completed
if (printJob.aborted) {
throw new Error("Druckauftrag wurde bereits abgebrochen");
return { error: "Druckauftrag wurde bereits abgebrochen" };
}
if (new Date(printJob.startAt).getTime() + printJob.durationInMinutes * 60 * 1000 < Date.now()) {
throw new Error("Druckauftrag ist bereits abgeschlossen");
return { error: "Druckauftrag ist bereits abgeschlossen" };
}
// Check if user is the owner of the print job
// biome-ignore lint/style/noNonNullAssertion: guard already checks against null
if (printJob.userId !== dbUser!.id && dbUser!.role !== UserRole.ADMIN) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
// Get duration in minutes since startAt
@ -169,7 +193,9 @@ export async function extendPrintJob(jobId: string, minutes: number, hours: numb
const { user } = await validateRequest();
if (guard(user, IS, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const dbUser = await db.query.users.findFirst({
@ -178,7 +204,9 @@ export async function extendPrintJob(jobId: string, minutes: number, hours: numb
});
if (guard(dbUser, IS, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
// Get the print job
@ -187,22 +215,24 @@ export async function extendPrintJob(jobId: string, minutes: number, hours: numb
});
if (!printJob) {
throw new Error("Druckauftrag nicht gefunden");
return { error: "Druckauftrag nicht gefunden" };
}
// Check if the print job is already aborted or completed
if (printJob.aborted) {
throw new Error("Druckauftrag wurde bereits abgebrochen");
return { error: "Druckauftrag wurde bereits abgebrochen" };
}
if (new Date(printJob.startAt).getTime() + printJob.durationInMinutes * 60 * 1000 < Date.now()) {
throw new Error("Druckauftrag ist bereits abgeschlossen");
return { error: "Druckauftrag ist bereits abgeschlossen" };
}
// Check if user is the owner of the print job
// biome-ignore lint/style/noNonNullAssertion: guard already checks against null
if (printJob.userId !== dbUser!.id && dbUser!.role !== UserRole.ADMIN) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const duration = minutes + hours * 60;
@ -222,7 +252,9 @@ export async function updatePrintComments(jobId: string, comments: string) {
const { user } = await validateRequest();
if (guard(user, IS, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const dbUser = await db.query.users.findFirst({
@ -231,7 +263,9 @@ export async function updatePrintComments(jobId: string, comments: string) {
});
if (guard(dbUser, IS, UserRole.GUEST)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
// Get the print job
@ -240,22 +274,24 @@ export async function updatePrintComments(jobId: string, comments: string) {
});
if (!printJob) {
throw new Error("Druckauftrag nicht gefunden");
return { error: "Druckauftrag nicht gefunden" };
}
// Check if the print job is already aborted or completed
if (printJob.aborted) {
throw new Error("Druckauftrag wurde bereits abgebrochen");
return { error: "Druckauftrag wurde bereits abgebrochen" };
}
if (new Date(printJob.startAt).getTime() + printJob.durationInMinutes * 60 * 1000 < Date.now()) {
throw new Error("Druckauftrag ist bereits abgeschlossen");
return { error: "Druckauftrag ist bereits abgeschlossen" };
}
// Check if user is the owner of the print job
// biome-ignore lint/style/noNonNullAssertion: guard already checks against null
if (printJob.userId !== dbUser!.id && dbUser!.role !== UserRole.ADMIN) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
await db

View File

@ -1,11 +1,10 @@
"use server";
import { validateRequest } from "@/server/auth";
import { UserRole } from "@/server/auth/permissions";
import { db } from "@/server/db";
import { printers, users } from "@/server/db/schema";
import { PermissionError } from "@/utils/errors";
import { IS_NOT, guard } from "@/utils/guard";
import strings from "@/utils/strings";
import { type InferInsertModel, eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
@ -13,7 +12,9 @@ export async function createPrinter(printer: InferInsertModel<typeof printers>)
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const dbUser = await db.query.users.findFirst({
@ -22,17 +23,23 @@ export async function createPrinter(printer: InferInsertModel<typeof printers>)
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
if (!printer) {
throw new Error("Druckerdaten sind erforderlich.");
return {
error: "Druckerdaten sind erforderlich.",
};
}
try {
await db.insert(printers).values(printer);
} catch (error) {
throw new Error("Drucker konnte nicht hinzugefügt werden.");
return {
error: "Drucker konnte nicht hinzugefügt werden.",
};
}
revalidatePath("/");
@ -42,7 +49,9 @@ export async function updatePrinter(id: string, data: InferInsertModel<typeof pr
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const dbUser = await db.query.users.findFirst({
@ -51,17 +60,23 @@ export async function updatePrinter(id: string, data: InferInsertModel<typeof pr
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
if (!data) {
throw new Error("Druckerdaten sind erforderlich.");
return {
error: "Druckerdaten sind erforderlich.",
};
}
try {
await db.update(printers).set(data).where(eq(printers.id, id));
} catch (error) {
throw new Error("Drucker konnte nicht aktualisiert werden.");
return {
error: "Druckerdaten sind erforderlich.",
};
}
revalidatePath("/");
@ -71,7 +86,9 @@ export async function deletePrinter(id: string) {
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const dbUser = await db.query.users.findFirst({
@ -80,16 +97,22 @@ export async function deletePrinter(id: string) {
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
try {
await db.delete(printers).where(eq(printers.id, id));
} catch (error) {
if (error instanceof Error) {
throw new Error(error.message);
return {
error: error.message,
};
}
throw new Error("Ein unbekannter Fehler ist aufgetreten.");
return {
error: "Ein unbekannter Fehler ist aufgetreten.",
};
}
revalidatePath("/");

View File

@ -5,8 +5,8 @@ import { validateRequest } from "@/server/auth";
import { UserRole } from "@/server/auth/permissions";
import { db } from "@/server/db";
import { users } from "@/server/db/schema";
import { PermissionError } from "@/utils/errors";
import { IS, IS_NOT, guard } from "@/utils/guard";
import strings from "@/utils/strings";
import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import type { z } from "zod";
@ -18,7 +18,9 @@ export async function updateUser(userId: string, data: z.infer<typeof formSchema
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const dbUser = await db.query.users.findFirst({
@ -27,7 +29,9 @@ export async function updateUser(userId: string, data: z.infer<typeof formSchema
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
await db.update(users).set(data).where(eq(users.id, userId));
@ -42,7 +46,9 @@ export async function deleteUser(userId: string) {
const { user } = await validateRequest();
if (guard(user, IS_NOT, UserRole.ADMIN)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const dbUser = await db.query.users.findFirst({
@ -51,7 +57,9 @@ export async function deleteUser(userId: string) {
});
if (guard(dbUser, IS_NOT, UserRole.ADMIN)) {
throw new PermissionError();
return {
error: strings.ERROR.PERMISSION,
};
}
const targetUser = await db.query.users.findFirst({
@ -59,11 +67,11 @@ export async function deleteUser(userId: string) {
});
if (!targetUser) {
throw new Error("Benutzer nicht gefunden");
return { error: "Benutzer nicht gefunden" };
}
if (guard(targetUser, IS, UserRole.ADMIN)) {
throw new Error("Kann keinen Admin löschen");
return { error: "Kann keinen Admin löschen" };
}
await db.delete(users).where(eq(users.id, userId));