tca-admin/components/gallery/CreateEventForm.tsx
2025-08-12 10:25:18 +05:30

234 lines
8.7 KiB
TypeScript

'use client';
import React, { useState, ChangeEvent, FormEvent } from 'react';
import IconTrashLines from '../icon/icon-trash-lines';
import axios from 'axios';
import { useRouter } from 'next/navigation';
import { showMessage } from '@/utils/CommonFunction.utils';
interface FormValues {
year: string;
eventdate: string;
eventtitle: string;
eventimageurl: File | null;
eventdescription: string;
}
interface FormErrors {
[key: string]: string;
}
const CreateEventForm: React.FC = () => {
const router = useRouter()
const [formData, setFormData] = useState<FormValues>({
year: '',
eventdate: '',
eventtitle: '',
eventimageurl: null,
eventdescription: '',
});
const [errors, setErrors] = useState<FormErrors>({});
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
const handleChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value,
}));
};
const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0] || null;
setFormData(prev => ({
...prev,
eventimageurl: file,
}));
if (file) {
const url = URL.createObjectURL(file);
setPreviewUrl(url);
} else {
setPreviewUrl(null);
}
};
const validateForm = (): boolean => {
const newErrors: FormErrors = {};
if (!formData.year.trim()) newErrors.year = 'Year is required';
if (!formData.eventdate.trim()) newErrors.eventdate = 'Event date is required';
if (!formData.eventtitle.trim()) newErrors.eventtitle = 'Event title is required';
if (!formData.eventimageurl) {
newErrors.eventimageurl = 'Please upload an image';
} else if (!formData.eventimageurl.type.startsWith('image/')) {
newErrors.eventimageurl = 'Only image files are allowed';
}
if (!formData.eventdescription.trim()) newErrors.eventdescription = 'Description is required';
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
if (!validateForm()) return;
console.log("formData", formData)
const data = new FormData();
if (formData.eventimageurl && formData.eventimageurl.type.startsWith("image/")) {
data.append("file", formData.eventimageurl); // ✅ Use correct field name
}
try {
const ImageUpload = await axios.post(`https://api.tamilculturewaterloo.org/api/upload/single`, data, {
headers: {
"Content-Type": "multipart/form-data", // important for file upload
},
})
console.log("ImageUpload", ImageUpload)
const createData = {
year: formData.year,
eventdate: formData.eventdate,
eventtitle: formData.eventtitle,
eventdescription: formData.eventdescription,
eventimageurl: ImageUpload?.data?.data?.fullUrl
}
const res = await axios.post(`https://api.tamilculturewaterloo.org/api/events`, createData)
console.log("res", res)
showMessage("Event Created Successfully", "success")
router?.push(`/`)
} catch (error: any) {
showMessage(`${error?.response?.data?.message ? error?.response?.data?.message : "error"}`)
}
};
const handleImageDelete = () => {
setFormData(prev => ({
...prev,
eventimageurl: null,
}));
setPreviewUrl(null);
};
return (
<form onSubmit={handleSubmit} className="max-w-4xl mx-auto p-6 bg-white rounded shadow-md">
<h2 className="text-xl font-bold mb-4">Create Event</h2>
<div className="grid grid-cols-1 xl:grid-cols-2 gap-6">
<div className="space-y-4">
{/* Year */}
<div>
<label htmlFor="year" className="block font-medium">Year</label>
<input
type="text"
name="year"
id="year"
value={formData.year}
onChange={handleChange}
className="w-full border rounded px-3 py-2"
/>
{errors.year && <p className="text-red-500 text-sm">{errors.year}</p>}
</div>
{/* Event Date */}
<div>
<label htmlFor="eventdate" className="block font-medium">Event Date</label>
<input
type="date"
name="eventdate"
id="eventdate"
value={formData.eventdate}
onChange={handleChange}
className="w-full border rounded px-3 py-2"
/>
{errors.eventdate && <p className="text-red-500 text-sm">{errors.eventdate}</p>}
</div>
{/* Event Title */}
<div>
<label htmlFor="eventtitle" className="block font-medium">Event Title</label>
<input
type="text"
name="eventtitle"
id="eventtitle"
value={formData.eventtitle}
onChange={handleChange}
className="w-full border rounded px-3 py-2"
/>
{errors.eventtitle && <p className="text-red-500 text-sm">{errors.eventtitle}</p>}
</div>
{/* Event Description */}
<div>
<label htmlFor="eventdescription" className="block font-medium">Event Description</label>
<textarea
name="eventdescription"
id="eventdescription"
rows={4}
value={formData.eventdescription}
onChange={handleChange}
className="w-full border rounded px-3 py-2"
/>
{errors.eventdescription && <p className="text-red-500 text-sm">{errors.eventdescription}</p>}
</div>
{/* Image Upload */}
<div>
<label htmlFor="eventimageurl" className="block font-medium">Event Image</label>
<input
type="file"
name="eventimageurl"
id="eventimageurl"
onChange={handleFileChange}
accept="image/*"
className="w-full border rounded px-3 py-2"
/>
{errors.eventimageurl && <p className="text-red-500 text-sm">{errors.eventimageurl}</p>}
</div>
</div>
{/* Image Preview */}
<div className="flex items-center justify-center border rounded p-4 bg-gray-50">
{previewUrl ? (
<div className="relative">
<img
src={previewUrl}
alt="Preview"
className="max-w-xs max-h-64 border rounded shadow"
/>
<button
type="button"
onClick={handleImageDelete}
className="absolute top-0 right-0 mt-2 mr-2 bg-red-600 text-white text-xs px-2 py-1 rounded"
>
<IconTrashLines className="shrink-0 " />
</button>
</div>
) : (
<p className="text-gray-500">No image selected</p>
)}
</div>
</div>
{/* Submit */}
<div className="mt-6">
<button type="submit" className="bg-blue-600 text-white px-6 py-2 rounded hover:bg-blue-700">
Submit
</button>
</div>
</form>
);
};
export default CreateEventForm;