added async confirm dialog

This commit is contained in:
biersoeckli
2024-10-31 12:11:27 +00:00
parent bb9428aece
commit f2b5d9ab5d
7 changed files with 107 additions and 3 deletions

BIN
bun.lockb

Binary file not shown.

View File

@@ -59,7 +59,8 @@
"ts-node": "^10.9.2",
"typedi": "^0.10.0",
"vaul": "^1.1.0",
"zod": "^3.23.8"
"zod": "^3.23.8",
"zustand": "^5.0.1"
},
"devDependencies": {
"@types/node": "^22.7.9",

View File

@@ -6,6 +6,7 @@ import "./globals.css";
import { NavBar } from "./nav-bar";
import { Suspense } from "react";
import FullLoadingSpinner from "@/components/ui/full-loading-spinnter";
import { ConfirmDialog } from "@/components/custom/confirm-dialog";
const inter = Inter({
subsets: ["latin"],
@@ -39,6 +40,7 @@ export default function RootLayout({
</div>
</main>
<Toaster />
<ConfirmDialog />
</body>
</html>
);

View File

@@ -8,13 +8,16 @@ import { formatDateTime } from "@/lib/format.utils";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { MoreHorizontal } from "lucide-react";
import { Toast } from "@/lib/toast.utils";
import { App, Project } from "@prisma/client";
import { App } from "@prisma/client";
import { deleteApp } from "./actions";
import { useConfirmDialog } from "@/lib/zustand.states";
export default function AppTable({ data }: { data: App[] }) {
const { openDialog } = useConfirmDialog();
return <>
<SimpleDataTable columns={[
['id', 'ID', false],
@@ -49,7 +52,10 @@ export default function AppTable({ data }: { data: App[] }) {
</DropdownMenuItem>
</Link>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => Toast.fromAction(() => deleteApp(item.id))}>
<DropdownMenuItem onClick={() => openDialog({
title: "Delete App",
description: "Are you sure you want to delete this app?",
}).then((result) => result ? Toast.fromAction(() => deleteApp(item.id)) : undefined)}>
<span className="text-red-500">Delete App</span>
</DropdownMenuItem>
</DropdownMenuContent>

View File

@@ -0,0 +1,37 @@
'use client'
import { Button } from "@/components/ui/button"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
import React from "react";
import { useConfirmDialog } from "@/lib/zustand.states";
export function ConfirmDialog() {
const { isDialogOpen, data, closeDialog } = useConfirmDialog();
if (!data) {
return <></>;
}
return (
<Dialog open={isDialogOpen} onOpenChange={closeDialog}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>{data.title}</DialogTitle>
<DialogDescription>
{data.description}
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button onClick={() => closeDialog(true)}>{data.yesButton ?? 'OK'}</Button>
<Button variant="secondary" onClick={() => closeDialog(false)}>{data.yesButton ?? 'Cancel'}</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)
}

57
src/lib/zustand.states.ts Normal file
View File

@@ -0,0 +1,57 @@
import dataAccess from "@/server/adapter/db.client";
import { create } from "zustand"
interface ZustandDialogProps {
isDialogOpen: boolean;
data: DialogProps | null;
resolvePromise: ((result: boolean) => void) | null;
openDialog: (data: DialogProps) => Promise<boolean>;
closeDialog: (result: boolean) => void;
}
export interface DialogProps {
title: string;
description: string;
yesButton?: string;
noButton?: string;
}
export interface InternDialogProps extends DialogProps {
returnFunc: (dialogResult: boolean) => boolean;
}
export const useConfirmDialog = create<ZustandDialogProps>((set) => ({
isDialogOpen: false,
data: null,
resolvePromise: null,
openDialog: (data) => {
return new Promise((resolve) => {
set({
isDialogOpen: true,
data: data,
resolvePromise: resolve,
});
});
},
closeDialog: (result) => set((state) => {
if (state.resolvePromise) {
state.resolvePromise(result); // Erfülle das Promise mit true oder false
}
return { isDialogOpen: false, userInfo: null, resolvePromise: null };
}),
}));
/*
export async function confirmDialog(props: DialogProps): Promise<boolean> {
const { openDialog } = useConfirmDialog();
return new Promise((resolve) => {
const extendedPropd = {
...props,
returnFunc: (returnVal) => {
resolve(returnVal);
}
} as InternDialogProps;
openDialog(extendedPropd);
});
}*/

View File

@@ -5,6 +5,7 @@ import { CompleteApp, RelatedAppModel } from "./index"
export const AppVolumeModel = z.object({
id: z.string(),
containerMountPath: z.string(),
size: z.number().int(),
appId: z.string(),
createdAt: z.date(),
updatedAt: z.date(),