From 42e1b69720e8ef7345d5e705d6bf9034b6a0809e Mon Sep 17 00:00:00 2001 From: Micha Date: Thu, 26 Jun 2025 12:56:53 +0200 Subject: [PATCH] feat(events): add deletion button and style toaster for light mode --- .../{ => (main)}/events/[eventID]/page.tsx | 89 ++++++++++++++++--- .../events/edit/[eventID]/page.tsx | 2 - src/app/{ => (main)}/events/new/page.tsx | 0 src/app/{ => (main)}/events/page.tsx | 5 -- src/app/globals.css | 42 +++++++-- src/components/misc/toast-inner.tsx | 20 +++-- src/components/ui/button.tsx | 2 + 7 files changed, 128 insertions(+), 32 deletions(-) rename src/app/{ => (main)}/events/[eventID]/page.tsx (66%) rename src/app/{ => (main)}/events/edit/[eventID]/page.tsx (84%) rename src/app/{ => (main)}/events/new/page.tsx (100%) rename src/app/{ => (main)}/events/page.tsx (92%) diff --git a/src/app/events/[eventID]/page.tsx b/src/app/(main)/events/[eventID]/page.tsx similarity index 66% rename from src/app/events/[eventID]/page.tsx rename to src/app/(main)/events/[eventID]/page.tsx index c366130..bfc390d 100644 --- a/src/app/events/[eventID]/page.tsx +++ b/src/app/(main)/events/[eventID]/page.tsx @@ -1,25 +1,42 @@ 'use client'; -import React from 'react'; +import React, { useState } from 'react'; import Logo from '@/components/misc/logo'; -import { ThemePicker } from '@/components/misc/theme-picker'; import { Card, CardContent, CardHeader } from '@/components/ui/card'; import { Label } from '@/components/ui/label'; -import { useGetApiEventEventID } from '@/generated/api/event/event'; +import { + useDeleteApiEventEventID, + useGetApiEventEventID, +} from '@/generated/api/event/event'; import { useGetApiUserMe } from '@/generated/api/user/user'; import { RedirectButton } from '@/components/buttons/redirect-button'; import { useSession } from 'next-auth/react'; import ParticipantListEntry from '@/components/custom-ui/participant-list-entry'; -import { useParams } from 'next/navigation'; +import { useParams, useRouter } from 'next/navigation'; +import { Button } from '@/components/ui/button'; +import { ToastInner } from '@/components/misc/toast-inner'; +import { toast } from 'sonner'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@/components/ui/dialog'; export default function ShowEvent() { const session = useSession(); + const router = useRouter(); + const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); - const { eventId } = useParams<{ eventId: string }>(); + const { eventID: eventID } = useParams<{ eventID: string }>(); // Fetch event data - const { data: eventData, isLoading, error } = useGetApiEventEventID(eventId); + const { data: eventData, isLoading, error } = useGetApiEventEventID(eventID); const { data: userData, isLoading: userLoading } = useGetApiUserMe(); + const deleteEvent = useDeleteApiEventEventID(); if (isLoading || userLoading) { return ( @@ -54,9 +71,6 @@ export default function ShowEvent() { return (
-
- -
@@ -150,10 +164,65 @@ export default function ShowEvent() {
+
+ {session.data?.user?.id === event.organizer.id ? ( + + + + + + + Delete Event + + Are you sure you want to delete the event “ + {event.title}”? This action cannot be undone. + + + + + + + + + ) : null} +
{session.data?.user?.id === event.organizer.id ? ( diff --git a/src/app/events/edit/[eventID]/page.tsx b/src/app/(main)/events/edit/[eventID]/page.tsx similarity index 84% rename from src/app/events/edit/[eventID]/page.tsx rename to src/app/(main)/events/edit/[eventID]/page.tsx index 712ba05..42c6e8b 100644 --- a/src/app/events/edit/[eventID]/page.tsx +++ b/src/app/(main)/events/edit/[eventID]/page.tsx @@ -1,4 +1,3 @@ -import { ThemePicker } from '@/components/misc/theme-picker'; import { Card, CardContent, CardHeader } from '@/components/ui/card'; import EventForm from '@/components/forms/event-form'; import { Suspense } from 'react'; @@ -11,7 +10,6 @@ export default async function Page({ const eventID = (await params).eventID; return (
-
{}
diff --git a/src/app/events/new/page.tsx b/src/app/(main)/events/new/page.tsx similarity index 100% rename from src/app/events/new/page.tsx rename to src/app/(main)/events/new/page.tsx diff --git a/src/app/events/page.tsx b/src/app/(main)/events/page.tsx similarity index 92% rename from src/app/events/page.tsx rename to src/app/(main)/events/page.tsx index b5c295d..f0391dd 100644 --- a/src/app/events/page.tsx +++ b/src/app/(main)/events/page.tsx @@ -2,7 +2,6 @@ import { RedirectButton } from '@/components/buttons/redirect-button'; import EventListEntry from '@/components/custom-ui/event-list-entry'; -import { ThemePicker } from '@/components/misc/theme-picker'; import { Label } from '@/components/ui/label'; import { useGetApiEvent } from '@/generated/api/event/event'; @@ -19,10 +18,6 @@ export default function Events() { return (
-
- -
- {/* Heading */}

My Events diff --git a/src/app/globals.css b/src/app/globals.css index 1707398..bc18178 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -50,11 +50,23 @@ --active-secondary: oklch(0.4254 0.133 272.15); --disabled-secondary: oklch(0.4937 0.1697 271.26 / 0.5); + --destructive: oklch(60.699% 0.20755 25.945); + --hover-destructive: oklch(60.699% 0.20755 25.945 / 0.8); + --active-destructive: oklch(50.329% 0.17084 25.842); + --disabled-destructive: oklch(60.699% 0.20755 25.945 / 0.4); + --muted: var(--color-neutral-700); --hover-muted: var(--color-neutral-600); --active-muted: var(--color-neutral-400); --disabled-muted: var(--color-neutral-400); + --toaster-default-bg: var(--color-neutral-150); + --toaster-success-bg: oklch(54.147% 0.09184 144.208); + --toaster-error-bg: oklch(52.841% 0.10236 27.274); + --toaster-info-bg: oklch(44.298% 0.05515 259.369); + --toaster-warning-bg: oklch(61.891% 0.07539 102.943); + --toaster-notification-bg: var(--color-neutral-150); + --card: var(--neutral-800); --sidebar-width-icon: 32px; @@ -81,8 +93,6 @@ --accent-foreground: oklch(0.21 0.034 264.665); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.928 0.006 264.531); --input: oklch(0.928 0.006 264.531); @@ -232,11 +242,23 @@ p { --color-active-secondary: var(--active-secondary); --color-disabled-secondary: var(--disabled-secondary); + --color-destructive: var(--destructive); + --color-hover-destructive: var(--hover-destructive); + --color-active-destructive: var(--active-destructive); + --color-disabled-destructive: var(--disabled-destructive); + --color-muted: var(--muted); --color-hover-muted: var(--hover-muted); --color-active-muted: var(--active-muted); --color-disabled-muted: var(--disabled-muted); + --color-toaster-default-bg: var(--toaster-default-bg); + --color-toaster-success-bg: var(--toaster-success-bg); + --color-toaster-error-bg: var(--toaster-error-bg); + --color-toaster-info-bg: var(--toaster-info-bg); + --color-toaster-warning-bg: var(--toaster-warning-bg); + --color-toaster-notification-bg: var(--toaster-notification-bg); + /* Custom values */ --radius-sm: calc(var(--radius) - 4px); @@ -277,8 +299,6 @@ p { --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-border: var(--border); --color-input: var(--input); @@ -354,11 +374,23 @@ p { --active-secondary: oklch(0.4471 0.15 271.61); --disabled-secondary: oklch(0.6065 0.213 271.11 / 0.4); + --destructive: oklch(0.58 0.2149 27.13); + --hover-destructive: oklch(0.58 0.2149 27.13 / 0.8); + --active-destructive: oklch(45.872% 0.16648 26.855); + --disabled-destructive: oklch(0.58 0.2149 27.13 / 0.4); + --muted: var(--color-neutral-650); --hover-muted: var(--color-neutral-500); --active-muted: var(--color-neutral-400); --disabled-muted: var(--color-neutral-400); + --toaster-default-bg: var(--color-neutral-150); + --toaster-success-bg: var(--color-green-200); + --toaster-error-bg: var(--color-red-200); + --toaster-info-bg: var(--color-blue-200); + --toaster-warning-bg: var(--color-yellow-200); + --toaster-notification-bg: var(--color-neutral-150); + --card: var(--neutral-750); /* ------------------- */ @@ -383,8 +415,6 @@ p { --accent-foreground: oklch(0.985 0.002 247.839); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); --input: oklch(1 0 0 / 15%); diff --git a/src/components/misc/toast-inner.tsx b/src/components/misc/toast-inner.tsx index 9617b75..c3f8134 100644 --- a/src/components/misc/toast-inner.tsx +++ b/src/components/misc/toast-inner.tsx @@ -65,27 +65,27 @@ interface ToastInnerProps { const variantConfig = { default: { - bgColor: 'bg-neutral-150', + bgColor: 'bg-toaster-default-bg', defaultIcon: 'Info', }, success: { - bgColor: 'bg-green-200', + bgColor: 'bg-toaster-success-bg', defaultIcon: 'CheckCircle', }, error: { - bgColor: 'bg-red-200', + bgColor: 'bg-toaster-error-bg', defaultIcon: 'XCircle', }, info: { - bgColor: 'bg-blue-200', + bgColor: 'bg-toaster-info-bg', defaultIcon: 'Info', }, warning: { - bgColor: 'bg-yellow-200', + bgColor: 'bg-toaster-warning-bg', defaultIcon: 'AlertTriangle', }, notification: { - bgColor: 'bg-neutral-150', + bgColor: 'bg-toaster-notification-bg', defaultIcon: 'BellRing', }, }; @@ -127,14 +127,16 @@ export const ToastInner: React.FC = ({ > {variant !== 'default' && (
- +
)} {/* Text Content */}
-
{title}
- {description && } +
{title}
+ {description && ( + + )}
{/* Action Button */} diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 8daf206..a5eec23 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -26,6 +26,8 @@ const buttonVariants = cva( 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 w-32 justify-between font-normal', ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', + destructive: + 'bg-destructive text-text shadow-xs hover:bg-hover-destructive active:bg-active-destructive disabled:bg-disabled-destructive', }, size: { default: 'h-9 px-4 py-2 has-[>svg]:px-3',