TCA-Admin-Frontend/components/gallery/CreateEventGalleryForm.tsx

158 lines
5.8 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 { buildApiUrl } from '@/utils/BaseUrl.utils';
interface FormErrors {
[key: string]: string;
}
interface EditEventFormProps {
eventId: string | null;
}
const CreateEventGalleryForm: React.FC<EditEventFormProps> = ({ eventId }) => {
const router = useRouter();
const [linkInput, setLinkInput] = useState('');
const [loading, setLoading] = useState(false);
const [errors, setErrors] = useState<FormErrors>({});
const parsedLinks = React.useMemo(() => {
return linkInput.split(/[\n,]+/).map(l => l.trim()).filter(l => l !== '').map(link => {
if (link.includes("drive.google.com")) {
const match = link.match(/\/d\/([a-zA-Z0-9_-]+)/) || link.match(/id=([a-zA-Z0-9_-]+)/);
if (match && match[1]) {
return `https://drive.google.com/thumbnail?id=${match[1]}&sz=w1000-h1000`;
}
}
return link;
});
}, [linkInput]);
const handleLinkInputChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
setLinkInput(e.target.value);
if (parsedLinks.length > 20) {
setErrors({ images: 'You can only add up to 20 images at a time' });
} else {
setErrors(prev => ({ ...prev, images: '' }));
}
};
const handleImageDelete = (index: number) => {
const lines = linkInput.split(/[\n,]+/).map(l => l.trim()).filter(l => l !== '');
lines.splice(index, 1);
setLinkInput(lines.join('\n'));
};
const validateForm = (): boolean => {
const newErrors: FormErrors = {};
if (parsedLinks.length === 0) {
newErrors.images = 'Please provide at least one image link';
} else if (parsedLinks.length > 20) {
newErrors.images = 'Only 20 images can be added at a time';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
if (!validateForm()) return;
setLoading(true);
try {
// Step 1: Prepare body for bulk save
const body = {
eventid: Number(eventId),
imageurl: parsedLinks
};
console.log("Sending body:", body);
// Step 3: Call bulk API
const token = localStorage.getItem('token');
await axios.post(
buildApiUrl('event-images/bulk'),
body,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
router.push(`/event-gallery?eventid=${eventId}`);
} catch (error: any) {
console.error('Upload failed:', error);
const message = error.response?.data?.message || 'Failed to upload images. Please try again.';
setErrors({ submit: message });
alert(message);
} finally {
setLoading(false);
}
};
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">Upload Gallery Images</h2>
{/* Link Input */}
<div className="mb-4">
<label htmlFor="gallery" className="block font-medium mb-1">Image Links (Google Drive etc.)</label>
<textarea
id="gallery"
rows={5}
placeholder="Paste your Google Drive links here, one per line..."
value={linkInput}
onChange={handleLinkInputChange}
className="w-full border rounded px-3 py-2"
/>
{errors.images && <p className="text-red-500 text-sm">{errors.images}</p>}
<p className="text-gray-500 text-xs mt-1">You can add up to 20 images.</p>
</div>
{/* Previews */}
{parsedLinks.length > 0 && (
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
{parsedLinks.map((url, index) => (
<div key={index} className="relative border rounded shadow overflow-hidden">
<img
src={url}
alt={`Preview ${index + 1}`}
className="w-full h-40 object-cover"
onError={(e) => {
(e.target as HTMLImageElement).src = "https://placehold.co/150x150?text=Invalid+Image+Link";
}}
/>
<button
type="button"
onClick={() => handleImageDelete(index)}
className="absolute top-1 right-1 bg-red-600 text-white rounded-full p-1 hover:bg-red-700"
>
<IconTrashLines className="w-4 h-4" />
</button>
</div>
))}
</div>
)}
{/* Submit */}
<div className="mt-6">
<button
type="submit"
disabled={loading}
className={`bg-blue-600 text-white px-6 py-2 rounded hover:bg-blue-700 ${loading ? 'opacity-50 cursor-not-allowed' : ''}`}
>
{loading ? 'Uploading...' : 'Submit'}
</button>
</div>
</form>
);
};
export default CreateEventGalleryForm;