263 lines
9.6 KiB
TypeScript
263 lines
9.6 KiB
TypeScript
'use client';
|
|
import React, { useState, useEffect, ChangeEvent, FormEvent } from 'react';
|
|
import IconTrashLines from '../icon/icon-trash-lines';
|
|
import axios from 'axios';
|
|
import { useRouter } from 'next/navigation';
|
|
|
|
interface FormValues {
|
|
year: string;
|
|
eventdate: string;
|
|
eventtitle: string;
|
|
eventimageurl: File | null;
|
|
eventdescription: string;
|
|
}
|
|
|
|
interface FormErrors {
|
|
[key: string]: string;
|
|
}
|
|
|
|
interface EditEventFormProps {
|
|
eventId: string | null;
|
|
}
|
|
|
|
const EditEventForm: React.FC<EditEventFormProps> = ({ eventId }) => {
|
|
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 [existingImageUrl, setExistingImageUrl] = useState<string | null>(null); // Used if no new file uploaded
|
|
|
|
useEffect(() => {
|
|
if (eventId) {
|
|
getEvent();
|
|
}
|
|
}, [eventId]);
|
|
|
|
const getEvent = async () => {
|
|
try {
|
|
const res = await axios.get(`https://api.tamilculturewaterloo.org/api/events/${eventId}`);
|
|
const data = res?.data?.data;
|
|
|
|
setFormData({
|
|
year: data.year || '',
|
|
eventdate: data.eventdate || '',
|
|
eventtitle: data.eventtitle || '',
|
|
eventimageurl: null, // File only used for uploads
|
|
eventdescription: data.eventdescription || '',
|
|
});
|
|
|
|
if (data.eventimageurl) {
|
|
setPreviewUrl(data.eventimageurl);
|
|
setExistingImageUrl(data.eventimageurl);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading event:', error);
|
|
}
|
|
};
|
|
|
|
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(existingImageUrl);
|
|
}
|
|
};
|
|
|
|
const handleImageDelete = () => {
|
|
setFormData(prev => ({
|
|
...prev,
|
|
eventimageurl: null,
|
|
}));
|
|
setPreviewUrl(null);
|
|
setExistingImageUrl(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.eventdescription.trim()) newErrors.eventdescription = 'Description is required';
|
|
|
|
// If no preview or no file selected, show error
|
|
if (!previewUrl) {
|
|
newErrors.eventimageurl = 'Please upload an image';
|
|
}
|
|
|
|
setErrors(newErrors);
|
|
return Object.keys(newErrors).length === 0;
|
|
};
|
|
|
|
const handleSubmit = async (e: FormEvent) => {
|
|
e.preventDefault();
|
|
if (!validateForm()) return;
|
|
|
|
try {
|
|
let imageUrl = existingImageUrl;
|
|
|
|
if (formData.eventimageurl && formData.eventimageurl.type.startsWith('image/')) {
|
|
const imgFormData = new FormData();
|
|
imgFormData.append('file', formData.eventimageurl);
|
|
|
|
const uploadRes = await axios.post(
|
|
'https://api.tamilculturewaterloo.org/api/upload/single',
|
|
imgFormData,
|
|
{ headers: { 'Content-Type': 'multipart/form-data' } }
|
|
);
|
|
|
|
imageUrl = uploadRes?.data?.data?.fullUrl;
|
|
}
|
|
|
|
const updatedData = {
|
|
year: formData.year,
|
|
eventdate: formData.eventdate,
|
|
eventtitle: formData.eventtitle,
|
|
eventdescription: formData.eventdescription,
|
|
eventimageurl: imageUrl,
|
|
};
|
|
|
|
const res = await axios.put(`https://api.tamilculturewaterloo.org/api/events/${eventId}`, updatedData, );
|
|
|
|
console.log('Event updated:', res.data);
|
|
router.push('/');
|
|
} catch (error) {
|
|
console.error('Error submitting form:', error);
|
|
}
|
|
};
|
|
|
|
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">{eventId ? 'Edit Event' : '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 EditEventForm;
|