From 9e836a7de1f76c183362b10fc4d462dfdf4ec070 Mon Sep 17 00:00:00 2001 From: ashprit Date: Sat, 26 Oct 2024 15:47:02 +0100 Subject: [PATCH] committing event form unfinished --- app/page.tsx | 47 +- {app => components}/Home.tsx | 0 {app => components}/TicketListings.tsx | 0 components/custom/EventForm.tsx | 219 + components/custom/TicketButton.tsx | 9 +- components/ui/textarea.tsx | 24 + package-lock.json | 6500 ++++++++++++++++++++++++ package.json | 11 +- 8 files changed, 6800 insertions(+), 10 deletions(-) rename {app => components}/Home.tsx (100%) rename {app => components}/TicketListings.tsx (100%) create mode 100644 components/custom/EventForm.tsx create mode 100644 components/ui/textarea.tsx diff --git a/app/page.tsx b/app/page.tsx index 5146df6..404c8f9 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,10 +1,53 @@ +'use client'; +import React from 'react'; import EventDescription from '@/components/custom/EventDescription'; -import Home from './Home'; +import Home from '../components/Home'; +import EventForm from '@/components/custom/EventForm'; export default function Page() { + // Define the handleSubmit function + const handleSubmit = (data: { + name: string; + description: string; + capacity: number; + ticketPrice: number; + eventDate: Date; + eventStartTime?: string; + eventEndTime?: string; + images?: string[]; + }) => { + try { + // Log the data to the console (you can replace this with an API call or other logic) + console.log('Form Submitted:', data); + + // You can format the eventDate if needed (e.g., to a specific date format) + const formattedDate = new Date(data.eventDate).toISOString(); + console.log('Formatted Event Date:', formattedDate); + + // Example: Post data to an API endpoint + // fetch('/api/events', { + // method: 'POST', + // headers: { + // 'Content-Type': 'application/json', + // }, + // body: JSON.stringify({ ...data, eventDate: formattedDate }), + // }) + // .then((response) => response.json()) + // .then((result) => { + // console.log('Success:', result); + // }) + // .catch((error) => { + // console.error('Error:', error); + // }); + } catch (error) { + console.error('Error submitting form:', error); + } + }; + return ( <> - + {/* */} + handleSubmit(data)} /> ); } diff --git a/app/Home.tsx b/components/Home.tsx similarity index 100% rename from app/Home.tsx rename to components/Home.tsx diff --git a/app/TicketListings.tsx b/components/TicketListings.tsx similarity index 100% rename from app/TicketListings.tsx rename to components/TicketListings.tsx diff --git a/components/custom/EventForm.tsx b/components/custom/EventForm.tsx new file mode 100644 index 0000000..bc87e3f --- /dev/null +++ b/components/custom/EventForm.tsx @@ -0,0 +1,219 @@ +'use client'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Textarea } from '@/components/ui/textarea'; + +// Define the schema using Zod +const eventSchema = z + .object({ + name: z.string().min(1, { message: 'Event name is required' }), + description: z.string().min(1, { message: 'Description is required' }), + capacity: z + .number({ invalid_type_error: 'Capacity must be a number' }) + .min(1, { message: 'Capacity must be at least 1' }) + .refine((val) => Number.isInteger(val), { + message: 'Capacity must be an integer', + }), + ticketPrice: z + .number({ invalid_type_error: 'Ticket price must be a number' }) + .min(0, { message: 'Ticket price must be at least 0' }) + .refine((val) => Number.isInteger(val), { + message: 'Ticket price must be in cents', + }), + eventDate: z.coerce.date({ message: 'Event date is required' }).refine( + (date) => { + const today = new Date(); + today.setHours(0, 0, 0, 0); // Remove time component + return date >= today; + }, + { + message: 'Event date must be today or in the future', + } + ), + eventStartTime: z.string().regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/, { + message: 'Invalid start time format', + }), + eventEndTime: z.string().regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/, { + message: 'Invalid end time format', + }), + images: z + .array( + z + .string() + .url() + .regex( + /https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/, + { message: 'Invalid image URL format' } + ) + ) + .optional(), + }) + .superRefine((d, ctx) => { + // Parse event start time + const startTime = new Date(d.eventDate); + const [startHours, startMinutes] = d.eventStartTime.split(':').map(Number); + startTime.setHours(startHours, startMinutes, 0, 0); + + // Parse event end time + const endTime = new Date(d.eventDate); + const [endHours, endMinutes] = d.eventEndTime.split(':').map(Number); + endTime.setHours(endHours, endMinutes, 0, 0); + + const currentDateTime = new Date(); + + // Check if event start time is in the future + if (startTime <= currentDateTime) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Event start time must be in the future', + path: ['eventStartTime'], + }); + } + + // Check if event end time is after start time + if (endTime <= startTime) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Event end time must be after the start time', + path: ['eventEndTime'], + }); + } + }); + +// Define the TypeScript type based on the Zod schema +type EventFormData = z.infer; + +interface EventFormProps { + onSubmit: (data: EventFormData) => void; +} + +const EventForm = ({ onSubmit }: EventFormProps) => { + const { + register, + handleSubmit, + formState: { errors }, + setValue, + watch, + } = useForm({ + resolver: zodResolver(eventSchema), + mode: 'onChange', + }); + + const handleFileChange = (e: React.ChangeEvent) => { + if (e.target.files) { + const filesArray = Array.from(e.target.files).map((file) => + URL.createObjectURL(file) + ); + setValue('images', filesArray, { shouldValidate: true }); + } + }; + + const images = watch('images') || []; + + return ( +
+
+ + + {errors.name &&

{errors.name.message}

} +
+ +
+ +