mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 01:51:13 -05:00
Add edit ride modal
This commit is contained in:
@@ -6,6 +6,7 @@ import { Badge } from '@/components/ui/badge';
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||||
import {
|
import {
|
||||||
MapPin,
|
MapPin,
|
||||||
Star,
|
Star,
|
||||||
@@ -24,7 +25,8 @@ import {
|
|||||||
FerrisWheel,
|
FerrisWheel,
|
||||||
Waves,
|
Waves,
|
||||||
Theater,
|
Theater,
|
||||||
Train
|
Train,
|
||||||
|
Edit
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { ReviewsSection } from '@/components/reviews/ReviewsSection';
|
import { ReviewsSection } from '@/components/reviews/ReviewsSection';
|
||||||
import { MeasurementDisplay } from '@/components/ui/measurement-display';
|
import { MeasurementDisplay } from '@/components/ui/measurement-display';
|
||||||
@@ -37,6 +39,10 @@ import { RecentPhotosPreview } from '@/components/rides/RecentPhotosPreview';
|
|||||||
import { ParkLocationMap } from '@/components/maps/ParkLocationMap';
|
import { ParkLocationMap } from '@/components/maps/ParkLocationMap';
|
||||||
import { Ride } from '@/types/database';
|
import { Ride } from '@/types/database';
|
||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
|
import { RideForm } from '@/components/admin/RideForm';
|
||||||
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
|
import { useUserRole } from '@/hooks/useUserRole';
|
||||||
|
import { toast } from '@/hooks/use-toast';
|
||||||
|
|
||||||
export default function RideDetail() {
|
export default function RideDetail() {
|
||||||
const { parkSlug, rideSlug } = useParams<{ parkSlug: string; rideSlug: string }>();
|
const { parkSlug, rideSlug } = useParams<{ parkSlug: string; rideSlug: string }>();
|
||||||
@@ -44,6 +50,9 @@ export default function RideDetail() {
|
|||||||
const [ride, setRide] = useState<Ride | null>(null);
|
const [ride, setRide] = useState<Ride | null>(null);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [activeTab, setActiveTab] = useState("overview");
|
const [activeTab, setActiveTab] = useState("overview");
|
||||||
|
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||||
|
const { user } = useAuth();
|
||||||
|
const { isModerator } = useUserRole();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (parkSlug && rideSlug) {
|
if (parkSlug && rideSlug) {
|
||||||
@@ -115,6 +124,85 @@ export default function RideDetail() {
|
|||||||
).join(' ');
|
).join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEditSubmit = async (data: any) => {
|
||||||
|
try {
|
||||||
|
if (isModerator) {
|
||||||
|
// Moderators can edit directly
|
||||||
|
const { error } = await supabase
|
||||||
|
.from('rides')
|
||||||
|
.update({
|
||||||
|
name: data.name,
|
||||||
|
slug: data.slug,
|
||||||
|
description: data.description,
|
||||||
|
category: data.category,
|
||||||
|
ride_sub_type: data.ride_sub_type,
|
||||||
|
status: data.status,
|
||||||
|
opening_date: data.opening_date,
|
||||||
|
closing_date: data.closing_date,
|
||||||
|
height_requirement: data.height_requirement,
|
||||||
|
age_requirement: data.age_requirement,
|
||||||
|
capacity_per_hour: data.capacity_per_hour,
|
||||||
|
duration_seconds: data.duration_seconds,
|
||||||
|
max_speed_kmh: data.max_speed_kmh,
|
||||||
|
max_height_meters: data.max_height_meters,
|
||||||
|
length_meters: data.length_meters,
|
||||||
|
inversions: data.inversions,
|
||||||
|
coaster_type: data.coaster_type,
|
||||||
|
seating_type: data.seating_type,
|
||||||
|
intensity_level: data.intensity_level,
|
||||||
|
drop_height_meters: data.drop_height_meters,
|
||||||
|
max_g_force: data.max_g_force,
|
||||||
|
banner_image_url: data.banner_image_url,
|
||||||
|
banner_image_id: data.banner_image_id,
|
||||||
|
card_image_url: data.card_image_url,
|
||||||
|
card_image_id: data.card_image_id,
|
||||||
|
manufacturer_id: data.manufacturer_id,
|
||||||
|
ride_model_id: data.ride_model_id,
|
||||||
|
updated_at: new Date().toISOString()
|
||||||
|
})
|
||||||
|
.eq('id', ride?.id);
|
||||||
|
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: "Ride Updated",
|
||||||
|
description: "The ride has been updated successfully."
|
||||||
|
});
|
||||||
|
|
||||||
|
setIsEditModalOpen(false);
|
||||||
|
fetchRideData(); // Refresh the ride data
|
||||||
|
} else {
|
||||||
|
// Regular users submit for moderation
|
||||||
|
const { error } = await supabase
|
||||||
|
.from('content_submissions')
|
||||||
|
.insert({
|
||||||
|
user_id: user?.id,
|
||||||
|
submission_type: 'ride_edit',
|
||||||
|
content: {
|
||||||
|
ride_id: ride?.id,
|
||||||
|
...data
|
||||||
|
},
|
||||||
|
status: 'pending'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: "Edit Submitted",
|
||||||
|
description: "Your edit has been submitted for review."
|
||||||
|
});
|
||||||
|
|
||||||
|
setIsEditModalOpen(false);
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
toast({
|
||||||
|
title: "Error",
|
||||||
|
description: error.message || "Failed to submit edit.",
|
||||||
|
variant: "destructive"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
@@ -155,15 +243,26 @@ export default function RideDetail() {
|
|||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
<main className="container mx-auto px-4 py-8">
|
<main className="container mx-auto px-4 py-8">
|
||||||
{/* Back Button */}
|
{/* Back Button and Edit Button */}
|
||||||
<Button
|
<div className="flex items-center justify-between mb-6">
|
||||||
variant="ghost"
|
<Button
|
||||||
onClick={() => navigate(`/parks/${ride.park?.slug}`)}
|
variant="ghost"
|
||||||
className="mb-6"
|
onClick={() => navigate(`/parks/${ride.park?.slug}`)}
|
||||||
>
|
>
|
||||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||||
Back to {ride.park?.name}
|
Back to {ride.park?.name}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
{user && (
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setIsEditModalOpen(true)}
|
||||||
|
>
|
||||||
|
<Edit className="w-4 h-4 mr-2" />
|
||||||
|
Edit Ride
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<div className="relative mb-8">
|
<div className="relative mb-8">
|
||||||
@@ -631,6 +730,56 @@ export default function RideDetail() {
|
|||||||
/>
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
{/* Edit Ride Modal */}
|
||||||
|
<Dialog open={isEditModalOpen} onOpenChange={setIsEditModalOpen}>
|
||||||
|
<DialogContent className="max-w-5xl max-h-[90vh] overflow-y-auto">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Edit Ride</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
{isModerator
|
||||||
|
? "Make changes to this ride. Changes will be applied immediately."
|
||||||
|
: "Submit changes to this ride for review. A moderator will review your submission."}
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
{ride && (
|
||||||
|
<RideForm
|
||||||
|
initialData={{
|
||||||
|
name: ride.name,
|
||||||
|
slug: ride.slug,
|
||||||
|
description: ride.description,
|
||||||
|
category: ride.category,
|
||||||
|
ride_sub_type: ride.ride_sub_type,
|
||||||
|
status: ride.status,
|
||||||
|
opening_date: ride.opening_date,
|
||||||
|
closing_date: ride.closing_date,
|
||||||
|
height_requirement: ride.height_requirement,
|
||||||
|
age_requirement: ride.age_requirement,
|
||||||
|
capacity_per_hour: ride.capacity_per_hour,
|
||||||
|
duration_seconds: ride.duration_seconds,
|
||||||
|
max_speed_kmh: ride.max_speed_kmh,
|
||||||
|
max_height_meters: ride.max_height_meters,
|
||||||
|
length_meters: ride.length_meters,
|
||||||
|
inversions: ride.inversions,
|
||||||
|
coaster_type: ride.coaster_type,
|
||||||
|
seating_type: ride.seating_type,
|
||||||
|
intensity_level: ride.intensity_level,
|
||||||
|
drop_height_meters: ride.drop_height_meters,
|
||||||
|
max_g_force: ride.max_g_force,
|
||||||
|
banner_image_url: ride.banner_image_url,
|
||||||
|
banner_image_id: ride.banner_image_id,
|
||||||
|
card_image_url: ride.card_image_url,
|
||||||
|
card_image_id: ride.card_image_id,
|
||||||
|
manufacturer_id: ride.manufacturer?.id,
|
||||||
|
ride_model_id: ride.ride_model?.id
|
||||||
|
}}
|
||||||
|
onSubmit={handleEditSubmit}
|
||||||
|
onCancel={() => setIsEditModalOpen(false)}
|
||||||
|
isEditing={true}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user