From fb79565e27bbf1c5f0c7318da3007f4dfc8f012a Mon Sep 17 00:00:00 2001 From: redglow Date: Sun, 21 Jun 2026 14:17:03 +0200 Subject: [PATCH] chore: delete confirmation --- src/client/components/use-boolean.ts | 19 +++++ src/client/routes/index.tsx | 110 ++++++++++++++++++++------- 2 files changed, 103 insertions(+), 26 deletions(-) create mode 100644 src/client/components/use-boolean.ts diff --git a/src/client/components/use-boolean.ts b/src/client/components/use-boolean.ts new file mode 100644 index 0000000..7c236ce --- /dev/null +++ b/src/client/components/use-boolean.ts @@ -0,0 +1,19 @@ +import { useCallback, useState } from "react"; + +export interface UsetBooleanResultOperators { + setTrue(): void; + setFalse(): void; + toggle(): void; +} + +export type UseBooleanResult = [boolean, UsetBooleanResultOperators]; + +export function useBoolean(initialValue: boolean = false): UseBooleanResult { + const [value, setValue] = useState(initialValue); + + const toggle = useCallback(() => setValue((x) => !x), []); + const setTrue = useCallback(() => setValue(true), []); + const setFalse = useCallback(() => setValue(false), []); + + return [value, { setTrue, setFalse, toggle }]; +} diff --git a/src/client/routes/index.tsx b/src/client/routes/index.tsx index 3cd0633..d9bb51b 100644 --- a/src/client/routes/index.tsx +++ b/src/client/routes/index.tsx @@ -1,7 +1,15 @@ +import DeleteIcon from "@mui/icons-material/Delete"; import { Alert, Box, + Button, CircularProgress, + Dialog, + DialogActions, + DialogContent, + DialogContentText, + DialogTitle, + IconButton, Table, TableBody, TableCell, @@ -12,9 +20,10 @@ import { } from "@mui/material"; import { useQuery } from "@tanstack/react-query"; import { createFileRoute } from "@tanstack/react-router"; -import { useEffect } from "react"; +import { useCallback, useEffect, useState } from "react"; import z from "zod"; import { RouterButton } from "../components/RouterButton"; +import { useBoolean } from "../components/use-boolean"; const Announcements = z.array( z.object({ @@ -26,6 +35,8 @@ const Announcements = z.array( }), ); +type Announcement = z.infer[0]; + export const Route = createFileRoute("/")({ component: RouteComponent, }); @@ -51,6 +62,27 @@ function RouteComponent() { } }, [announcementsQuery.error]); + // delete confirmation dialog status + const [ + isDeleteConfirmationOpen, + { + setTrue: openDeleteConfirmationDialog, + setFalse: closeDeleteConfirmation, + }, + ] = useBoolean(); + + const [ + announcementForLatestDeleteAttempt, + setAnnouncementForLatestDeleteAttempt, + ] = useState(undefined); + const openDeleteConfirmation = useCallback( + (a: Announcement) => { + openDeleteConfirmationDialog(); + setAnnouncementForLatestDeleteAttempt(a); + }, + [openDeleteConfirmationDialog], + ); + // handle loading / error / show values return ( @@ -67,32 +99,58 @@ function RouteComponent() { ) : announcementsQuery.status === "error" ? ( Error (see console) ) : ( - //
{JSON.stringify(announcementsQuery.data, null, 2)}
- - - - - - Title - Text - Publication Date - - - - {announcementsQuery.data.map((a) => ( - - {a.id} - {a.title} - - {a.text.substring(0, 50) + - (a.text.length > 50 ? "..." : "")} - - {a.publication_date.toString()} + <> + +
+ + + + Title + Text + Publication Date + - ))} - -
-
+ + + {announcementsQuery.data.map((a) => ( + + {a.id} + {a.title} + + {a.text.substring(0, 50) + + (a.text.length > 50 ? "..." : "")} + + {a.publication_date.toString()} + + openDeleteConfirmation(a)}> + + + + + ))} + + + + + Delete announcement + + + Do you want to delete the announcement{" "} + {announcementForLatestDeleteAttempt?.title}? + + + + + + + + )}
);