feat: Implement item editing capability

This commit is contained in:
gpt-engineer-app[bot]
2025-09-30 14:06:03 +00:00
parent 9fcf1f5413
commit dc3c210e40
4 changed files with 336 additions and 1 deletions

View File

@@ -0,0 +1,215 @@
import { useState } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { ParkForm } from '@/components/admin/ParkForm';
import { RideForm } from '@/components/admin/RideForm';
import { ManufacturerForm } from '@/components/admin/ManufacturerForm';
import { DesignerForm } from '@/components/admin/DesignerForm';
import { OperatorForm } from '@/components/admin/OperatorForm';
import { PropertyOwnerForm } from '@/components/admin/PropertyOwnerForm';
import { RideModelForm } from '@/components/admin/RideModelForm';
import { PhotoCaptionEditor } from '@/components/upload/PhotoCaptionEditor';
import { useIsMobile } from '@/hooks/use-mobile';
import { editSubmissionItem } from '@/lib/submissionItemsService';
import { useAuth } from '@/hooks/useAuth';
import { toast } from '@/hooks/use-toast';
import type { SubmissionItemWithDeps } from '@/lib/submissionItemsService';
interface ItemEditDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
item: SubmissionItemWithDeps | null;
onEditComplete: () => void;
}
export function ItemEditDialog({ open, onOpenChange, item, onEditComplete }: ItemEditDialogProps) {
const isMobile = useIsMobile();
const { user } = useAuth();
const [isSubmitting, setIsSubmitting] = useState(false);
if (!item) return null;
const handleFormSubmit = async (data: any) => {
if (!user) {
toast({
title: "Authentication Required",
description: "You must be logged in to edit items.",
variant: "destructive"
});
return;
}
setIsSubmitting(true);
try {
await editSubmissionItem(item.id, data, user.id);
toast({
title: "Item Updated",
description: "The submission item has been updated successfully."
});
onOpenChange(false);
onEditComplete();
} catch (error: any) {
toast({
title: "Error",
description: error.message || "Failed to update submission item.",
variant: "destructive"
});
} finally {
setIsSubmitting(false);
}
};
const handleCancel = () => {
if (!isSubmitting) {
onOpenChange(false);
}
};
const renderForm = () => {
const itemData = item.item_data as any;
switch (item.item_type) {
case 'park':
return (
<ParkForm
initialData={itemData}
onSubmit={handleFormSubmit}
onCancel={handleCancel}
isEditing={true}
/>
);
case 'ride':
return (
<RideForm
initialData={itemData}
onSubmit={handleFormSubmit}
onCancel={handleCancel}
isEditing={true}
/>
);
case 'manufacturer':
return (
<ManufacturerForm
initialData={itemData}
onSubmit={handleFormSubmit}
onCancel={handleCancel}
/>
);
case 'designer':
return (
<DesignerForm
initialData={itemData}
onSubmit={handleFormSubmit}
onCancel={handleCancel}
/>
);
case 'operator':
return (
<OperatorForm
initialData={itemData}
onSubmit={handleFormSubmit}
onCancel={handleCancel}
/>
);
case 'property_owner':
return (
<PropertyOwnerForm
initialData={itemData}
onSubmit={handleFormSubmit}
onCancel={handleCancel}
/>
);
case 'ride_model':
return (
<RideModelForm
manufacturerName={itemData.manufacturer_name || 'Unknown'}
manufacturerId={itemData.manufacturer_id}
initialData={itemData}
onSubmit={handleFormSubmit}
onCancel={handleCancel}
/>
);
case 'photo':
return (
<div className="space-y-4 p-4">
<div className="space-y-2">
<Label htmlFor="caption">Caption</Label>
<Input
id="caption"
defaultValue={itemData.caption || ''}
onChange={(e) => {
itemData.caption = e.target.value;
}}
placeholder="Enter photo caption"
/>
</div>
{itemData.image_url && (
<img
src={itemData.image_url}
alt="Preview"
className="w-full rounded-md"
/>
)}
<div className="flex gap-2 justify-end">
<Button variant="outline" onClick={handleCancel}>Cancel</Button>
<Button onClick={() => handleFormSubmit(itemData)}>Save</Button>
</div>
</div>
);
default:
return (
<div className="p-4 text-center text-muted-foreground">
Form not available for item type: {item.item_type}
</div>
);
}
};
const content = (
<>
{isMobile ? (
<SheetHeader>
<SheetTitle>Edit {item.item_type.replace('_', ' ')}</SheetTitle>
</SheetHeader>
) : (
<DialogHeader>
<DialogTitle>Edit {item.item_type.replace('_', ' ')}</DialogTitle>
</DialogHeader>
)}
<div className="mt-4 max-h-[calc(100vh-150px)] overflow-y-auto">
{renderForm()}
</div>
</>
);
if (isMobile) {
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent side="bottom" className="h-[95vh]">
{content}
</SheetContent>
</Sheet>
);
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
{content}
</DialogContent>
</Dialog>
);
}