diff --git a/app/page.tsx b/app/page.tsx index 404c8f9..98589e3 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -11,9 +11,8 @@ export default function Page() { description: string; capacity: number; ticketPrice: number; - eventDate: Date; - eventStartTime?: string; - eventEndTime?: string; + eventStartTime: Date; // event day + eventEndTime?: Date; images?: string[]; }) => { try { @@ -21,7 +20,7 @@ export default function Page() { 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(); + const formattedDate = new Date(data.eventStartTime).toISOString(); console.log('Formatted Event Date:', formattedDate); // Example: Post data to an API endpoint diff --git a/components/PreviousTickets.tsx b/components/PreviousTickets.tsx new file mode 100644 index 0000000..941f952 --- /dev/null +++ b/components/PreviousTickets.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +// interface props{ +// previousTickets: previousTicket[]; +// } + +const PreviousTickets = () => { + return
PreviousTicket
; +}; + +export default PreviousTickets; diff --git a/components/custom/EventForm.tsx b/components/custom/EventForm.tsx index bc87e3f..9273dd0 100644 --- a/components/custom/EventForm.tsx +++ b/components/custom/EventForm.tsx @@ -2,6 +2,7 @@ import { useForm } from 'react-hook-form'; import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; +import { useState } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; @@ -15,69 +16,41 @@ const eventSchema = z 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', - }), + .refine(Number.isInteger, { 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', - } + .refine(Number.isInteger, { message: 'Ticket price must be in cents' }), + location: z.string().min(1, { message: 'Location is required' }), + eventStartTime: z.preprocess( + (val) => + typeof val === 'string' && val !== '' ? new Date(val) : undefined, + z + .date({ required_error: 'Event start time is required' }) + .min(new Date(), { message: 'Event start time must be in the future' }) + ), + eventEndTime: z.preprocess( + (val) => + typeof val === 'string' && val !== '' ? new Date(val) : undefined, + z.date().optional() + ), + images: z.preprocess( + (val) => { + if (Array.isArray(val)) { + // Filter out empty strings + return val.filter((v) => v !== ''); + } + return []; + }, + z + .array(z.string().url({ message: 'Invalid image URL format' })) + .optional() ), - 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) { + .superRefine((data, ctx) => { + if (data.eventEndTime && data.eventEndTime <= data.eventStartTime) { 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, + code: 'custom', message: 'Event end time must be after the start time', path: ['eventEndTime'], }); @@ -92,6 +65,8 @@ interface EventFormProps { } const EventForm = ({ onSubmit }: EventFormProps) => { + const [imageFields, setImageFields] = useState(['']); + const { register, handleSubmit, @@ -101,27 +76,35 @@ const EventForm = ({ onSubmit }: EventFormProps) => { } = useForm({ resolver: zodResolver(eventSchema), mode: 'onChange', + defaultValues: { + images: [''], + }, }); - 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') || []; + const handleAddImageField = () => { + setImageFields((prev) => [...prev, '']); + }; + + const handleRemoveImageField = (index: number) => { + const updatedImages = [...imageFields]; + updatedImages.splice(index, 1); + setImageFields(updatedImages); + // Also update the form values + setValue('images', updatedImages); + }; + return (
+ {/* Name Field */}
{errors.name &&

{errors.name.message}

}
+ {/* Description Field */}