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

@@ -15,7 +15,8 @@ import {
ChevronDown,
Sliders,
X,
FerrisWheel
FerrisWheel,
Plus
} from 'lucide-react';
import { Park } from '@/types/database';
import { supabase } from '@/integrations/supabase/client';
@@ -26,6 +27,10 @@ import { ParkListView } from '@/components/parks/ParkListView';
import { ParkSearch } from '@/components/parks/ParkSearch';
import { ParkSortOptions } from '@/components/parks/ParkSortOptions';
import { useToast } from '@/hooks/use-toast';
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { ParkForm } from '@/components/admin/ParkForm';
import { useAuth } from '@/hooks/useAuth';
import { useUserRole } from '@/hooks/useUserRole';
export interface FilterState {
search: string;
@@ -70,8 +75,11 @@ export default function Parks() {
const [sort, setSort] = useState<SortState>(initialSort);
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
const [showFilters, setShowFilters] = useState(false);
const [isAddParkModalOpen, setIsAddParkModalOpen] = useState(false);
const navigate = useNavigate();
const { toast } = useToast();
const { user } = useAuth();
const { isModerator } = useUserRole();
useEffect(() => {
fetchParks();
@@ -227,6 +235,80 @@ export default function Parks() {
navigate(`/parks/${park.slug}`);
};
const handleAddParkClick = () => {
if (!user) {
navigate('/auth');
return;
}
setIsAddParkModalOpen(true);
};
const handleParkSubmit = async (parkData: any) => {
if (!user) {
navigate('/auth');
return;
}
try {
if (isModerator()) {
// Moderators can create parks directly
const { error } = await supabase
.from('parks')
.insert({
name: parkData.name,
slug: parkData.slug,
description: parkData.description || null,
park_type: parkData.park_type,
status: parkData.status,
opening_date: parkData.opening_date || null,
closing_date: parkData.closing_date || null,
website_url: parkData.website_url || null,
phone: parkData.phone || null,
email: parkData.email || null,
banner_image_url: parkData.banner_image_url || null,
banner_image_id: parkData.banner_image_id || null,
card_image_url: parkData.card_image_url || null,
card_image_id: parkData.card_image_id || null
});
if (error) throw error;
toast({
title: "Park Created",
description: "The park has been created successfully.",
});
setIsAddParkModalOpen(false);
fetchParks();
} else {
// Regular users submit for moderation
const { error } = await supabase
.from('content_submissions')
.insert({
user_id: user.id,
submission_type: 'park',
status: 'pending',
content: parkData
});
if (error) throw error;
toast({
title: "Submission Sent",
description: "Your park submission has been sent for moderation review.",
});
setIsAddParkModalOpen(false);
}
} catch (error: any) {
toast({
title: "Submission Failed",
description: error.message || "Failed to submit park.",
variant: "destructive"
});
}
};
if (loading) {
return (
<div className="min-h-screen bg-background">
@@ -278,16 +360,26 @@ export default function Parks() {
</Badge>
</div>
{activeFilterCount > 0 && (
<div className="flex items-center gap-2">
<Button
variant="outline"
onClick={clearAllFilters}
className="text-destructive hover:text-destructive"
onClick={handleAddParkClick}
className="gap-2"
>
<X className="w-4 h-4 mr-2" />
Clear all filters
<Plus className="w-4 h-4" />
Add Park
</Button>
)}
{activeFilterCount > 0 && (
<Button
variant="outline"
onClick={clearAllFilters}
className="text-destructive hover:text-destructive"
>
<X className="w-4 h-4 mr-2" />
Clear all filters
</Button>
)}
</div>
</div>
</div>
@@ -374,6 +466,23 @@ export default function Parks() {
</Button>
</div>
)}
{/* Add Park Modal */}
<Dialog open={isAddParkModalOpen} onOpenChange={setIsAddParkModalOpen}>
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>Add New Park</DialogTitle>
<DialogDescription>
Add a new park to the database. {isModerator() ? 'The park will be added immediately.' : 'Your submission will be reviewed before being published.'}
</DialogDescription>
</DialogHeader>
<ParkForm
onSubmit={handleParkSubmit}
onCancel={() => setIsAddParkModalOpen(false)}
isEditing={false}
/>
</DialogContent>
</Dialog>
</main>
</div>
);