Implement Park Form and Edit/Add Functionality

This commit is contained in:
gpt-engineer-app[bot]
2025-09-29 23:45:35 +00:00
parent 97c7a4226d
commit 0ddae7493c
6 changed files with 311 additions and 29 deletions

View File

@@ -7,7 +7,7 @@ import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Label } from '@/components/ui/label';
import { PhotoUpload } from '@/components/upload/PhotoUpload';
import { UppyPhotoUpload } from '@/components/upload/UppyPhotoUpload';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { DatePicker } from '@/components/ui/date-picker';
import { toast } from '@/hooks/use-toast';
@@ -29,9 +29,9 @@ const parkSchema = z.object({
type ParkFormData = z.infer<typeof parkSchema>;
interface ParkFormProps {
onSubmit: (data: ParkFormData & { banner_image_url?: string; card_image_url?: string }) => Promise<void>;
onSubmit: (data: ParkFormData & { banner_image_url?: string; card_image_url?: string; banner_image_id?: string; card_image_id?: string }) => Promise<void>;
onCancel?: () => void;
initialData?: Partial<ParkFormData & { banner_image_url?: string; card_image_url?: string }>;
initialData?: Partial<ParkFormData & { banner_image_url?: string; card_image_url?: string; banner_image_id?: string; card_image_id?: string }>;
isEditing?: boolean;
}
@@ -59,6 +59,14 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
const [submitting, setSubmitting] = useState(false);
const [bannerImage, setBannerImage] = useState<string>(initialData?.banner_image_url || '');
const [cardImage, setCardImage] = useState<string>(initialData?.card_image_url || '');
const [bannerImageId, setBannerImageId] = useState<string>(initialData?.banner_image_id || '');
const [cardImageId, setCardImageId] = useState<string>(initialData?.card_image_id || '');
// Extract Cloudflare image ID from URL
const extractImageId = (url: string): string => {
const match = url.match(/\/([a-f0-9-]{36})\//);
return match ? match[1] : '';
};
const {
register,
@@ -103,7 +111,9 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
await onSubmit({
...data,
banner_image_url: bannerImage || undefined,
card_image_url: cardImage || undefined
card_image_url: cardImage || undefined,
banner_image_id: bannerImageId || undefined,
card_image_id: cardImageId || undefined
});
toast({
@@ -283,15 +293,28 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
<div className="space-y-6">
<div className="space-y-2">
<Label>Banner Image</Label>
<PhotoUpload
{bannerImage && (
<div className="mb-2">
<img src={bannerImage} alt="Current banner" className="h-32 w-full object-cover rounded-md" />
</div>
)}
<UppyPhotoUpload
maxFiles={1}
variant="default"
existingPhotos={bannerImage ? [bannerImage] : []}
onUploadComplete={(urls) => setBannerImage(urls[0] || '')}
onError={(error) => {
variant="public"
onUploadComplete={(urls) => {
const url = urls[0];
if (url) {
setBannerImage(url);
const imageId = extractImageId(url);
if (imageId) {
setBannerImageId(imageId);
}
}
}}
onUploadError={(error) => {
toast({
title: "Upload Error",
description: error,
description: error.message,
variant: "destructive"
});
}}
@@ -303,15 +326,28 @@ export function ParkForm({ onSubmit, onCancel, initialData, isEditing = false }:
<div className="space-y-2">
<Label>Card Image</Label>
<PhotoUpload
{cardImage && (
<div className="mb-2">
<img src={cardImage} alt="Current card" className="h-32 w-full object-cover rounded-md" />
</div>
)}
<UppyPhotoUpload
maxFiles={1}
variant="default"
existingPhotos={cardImage ? [cardImage] : []}
onUploadComplete={(urls) => setCardImage(urls[0] || '')}
onError={(error) => {
variant="public"
onUploadComplete={(urls) => {
const url = urls[0];
if (url) {
setCardImage(url);
const imageId = extractImageId(url);
if (imageId) {
setCardImageId(imageId);
}
}
}}
onUploadError={(error) => {
toast({
title: "Upload Error",
description: error,
description: error.message,
variant: "destructive"
});
}}