From eab8c2b1959f0cb623cad02f3a40bcd4862bf5fd Mon Sep 17 00:00:00 2001 From: FadyGergesRezk <84906847+FadyGergesRezk@users.noreply.github.com> Date: Fri, 3 Jul 2026 06:05:42 +0200 Subject: [PATCH 01/11] chore: add shadcn dialog primitives and server error helper --- web-client/src/components/ui/alert-dialog.tsx | 147 +++++++++++++++ web-client/src/components/ui/dialog.tsx | 167 ++++++++++++++++++ web-client/src/components/ui/input.tsx | 2 +- web-client/src/components/ui/label.tsx | 22 +++ web-client/src/components/ui/textarea.tsx | 18 ++ web-client/src/lib/server-error.ts | 13 ++ 6 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 web-client/src/components/ui/alert-dialog.tsx create mode 100644 web-client/src/components/ui/dialog.tsx create mode 100644 web-client/src/components/ui/label.tsx create mode 100644 web-client/src/components/ui/textarea.tsx create mode 100644 web-client/src/lib/server-error.ts diff --git a/web-client/src/components/ui/alert-dialog.tsx b/web-client/src/components/ui/alert-dialog.tsx new file mode 100644 index 00000000..8e06792b --- /dev/null +++ b/web-client/src/components/ui/alert-dialog.tsx @@ -0,0 +1,147 @@ +"use client" + +import * as React from "react" +import { AlertDialog as AlertDialogPrimitive } from "radix-ui" + +import { buttonVariants } from "@/components/ui/button" +import { cn } from "@/lib/utils" + +function AlertDialog({ + ...props +}: React.ComponentProps) { + return +} + +function AlertDialogTrigger({ + ...props +}: React.ComponentProps) { + return +} + +function AlertDialogPortal({ + ...props +}: React.ComponentProps) { + return +} + +function AlertDialogOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + + + + ) +} + +function AlertDialogHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AlertDialogFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AlertDialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogAction({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogCancel({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/web-client/src/components/ui/dialog.tsx b/web-client/src/components/ui/dialog.tsx new file mode 100644 index 00000000..cc97dc0a --- /dev/null +++ b/web-client/src/components/ui/dialog.tsx @@ -0,0 +1,167 @@ +"use client" + +import * as React from "react" +import { XIcon } from "lucide-react" +import { Dialog as DialogPrimitive } from "radix-ui" + +import { Button } from "@/components/ui/button" +import { cn } from "@/lib/utils" + +function Dialog({ + ...props +}: React.ComponentProps) { + return +} + +function DialogTrigger({ + ...props +}: React.ComponentProps) { + return +} + +function DialogPortal({ + ...props +}: React.ComponentProps) { + return +} + +function DialogClose({ + ...props +}: React.ComponentProps) { + return +} + +function DialogOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DialogContent({ + className, + children, + showCloseButton = true, + ...props +}: React.ComponentProps & { + showCloseButton?: boolean +}) { + return ( + + + + {children} + {showCloseButton && ( + + + + )} + + + ) +} + +function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function DialogFooter({ + className, + showCloseButton = false, + children, + ...props +}: React.ComponentProps<"div"> & { + showCloseButton?: boolean +}) { + return ( +
+ {children} + {showCloseButton && ( + + + + )} +
+ ) +} + +function DialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogOverlay, + DialogPortal, + DialogTitle, + DialogTrigger, +} diff --git a/web-client/src/components/ui/input.tsx b/web-client/src/components/ui/input.tsx index 14021ac4..b959abfe 100644 --- a/web-client/src/components/ui/input.tsx +++ b/web-client/src/components/ui/input.tsx @@ -8,7 +8,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) { type={type} data-slot="input" className={cn( - "h-10 w-full min-w-0 border border-transparent border-b-input bg-transparent px-0 py-1 text-base transition-[color,border-color] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-text-tertiary focus-visible:border-b-ring disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-b-destructive md:text-sm dark:aria-invalid:border-b-destructive/50", + "h-10 w-full min-w-0 border border-input bg-transparent px-3 py-1 text-base transition-[color,border-color] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-text-tertiary focus-visible:border-ring disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive md:text-sm dark:aria-invalid:border-destructive/50", className )} {...props} diff --git a/web-client/src/components/ui/label.tsx b/web-client/src/components/ui/label.tsx new file mode 100644 index 00000000..a4822b14 --- /dev/null +++ b/web-client/src/components/ui/label.tsx @@ -0,0 +1,22 @@ +import * as React from "react" +import { Label as LabelPrimitive } from "radix-ui" + +import { cn } from "@/lib/utils" + +function Label({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Label } diff --git a/web-client/src/components/ui/textarea.tsx b/web-client/src/components/ui/textarea.tsx new file mode 100644 index 00000000..05bd0936 --- /dev/null +++ b/web-client/src/components/ui/textarea.tsx @@ -0,0 +1,18 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { + return ( +