From 193e9fa4d2a6f3ab558b94f294ae5fb55e2499b0 Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Date: Wed, 12 Mar 2025 09:48:50 +0100 Subject: [PATCH] Refactor event creation form with improved UI and validation Replaced basic HTML form with styled components for better UI consistency. Added fields for start/end time and location URL, along with live slug validation to prevent reserved slugs. Enhanced layout and structure for improved usability and responsiveness. --- .../app/(main)/dashboard/events/new/page.tsx | 267 +++++++++++------- 1 file changed, 167 insertions(+), 100 deletions(-) diff --git a/frontend/src/app/(main)/dashboard/events/new/page.tsx b/frontend/src/app/(main)/dashboard/events/new/page.tsx index a96f3ff..aba17f1 100644 --- a/frontend/src/app/(main)/dashboard/events/new/page.tsx +++ b/frontend/src/app/(main)/dashboard/events/new/page.tsx @@ -3,41 +3,73 @@ import React, { useState } from "react"; import { useRouter } from "next/navigation"; import { useEvents } from "@/context/event-context"; -import { EventCreate } from "@/client/types.gen"; +import { EventCreate } from "@/client"; import Navbar from "@/components/layout/navbar"; import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Label } from "@/components/ui/label"; +import { Switch } from "@/components/ui/switch"; +import { RESERVED_SLUGS } from "@/constants"; -const CreateEventPage: React.FC = () => { +export default function CreateEventPage() { const router = useRouter(); const { createEvent, isCreating } = useEvents(); + const [slugError, setSlugError] = useState(null); const [formData, setFormData] = useState({ title: "", description: "", location_name: "", location_address: "", + location_url: "", event_date: "", + event_start_time: "", + event_end_time: "", timezone: "UTC", slug: "", is_public: false, + rsvp_enabled: true, }); const onChange = ( - e: React.ChangeEvent< - HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement - >, + e: React.ChangeEvent, ) => { const { name, value, type } = e.target; + const checked = type === "checkbox" ? (e.target as HTMLInputElement).checked : undefined; - setFormData({ - ...formData, + + setFormData((prev) => ({ + ...prev, [name]: type === "checkbox" ? checked : value, - }); + })); + + // live validation for slug + if (name === "slug") { + if (RESERVED_SLUGS.includes(value)) { + setSlugError(`The slug "${value}" is reserved.`); + } else { + setSlugError(null); + } + } + }; + + const onTogglePublic = (checked: boolean) => { + setFormData((prev) => ({ ...prev, is_public: checked })); }; const onSubmit = async (e: React.FormEvent) => { e.preventDefault(); + + if (RESERVED_SLUGS.includes(formData.slug)) { + alert( + `The slug "${formData.slug}" is reserved and cannot be used. Please choose another slug.`, + ); + return; + } + try { const event = await createEvent(formData); router.push(`/dashboard/events/${event.slug}`); @@ -50,105 +82,140 @@ const CreateEventPage: React.FC = () => { return ( <> -
-

Create New Event

+
+ + + Create New Event + + +
+
+ + +
- - +
+ +