mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 06:11:11 -05:00
Enhance loading skeletons and breadcrumbs
- Add content-m matching loading skeletons for ParkDetail, RideDetail, CompanyDetail, etc., replacing generic spinners to preserve layout during load - Remove redundant Back to Parent Entity buttons in detail pages in favor of breadcrumb navigation - Prepare groundwork for breadcrumbs across detail pages to improve cohesion and navigation
This commit is contained in:
98
src/components/loading/CompanyDetailSkeleton.tsx
Normal file
98
src/components/loading/CompanyDetailSkeleton.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
||||
|
||||
export function CompanyDetailSkeleton() {
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8 max-w-7xl animate-pulse">
|
||||
{/* Breadcrumb */}
|
||||
<div className="h-4 bg-muted rounded w-56 mb-4" />
|
||||
|
||||
{/* Edit Button Area */}
|
||||
<div className="flex justify-end mb-6">
|
||||
<div className="h-10 bg-muted rounded w-32" />
|
||||
</div>
|
||||
|
||||
{/* Hero Banner */}
|
||||
<div className="aspect-[21/9] bg-muted rounded-lg mb-8" />
|
||||
|
||||
{/* Stats Cards */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-12 max-w-6xl mx-auto">
|
||||
{[1, 2, 3, 4].map((i) => (
|
||||
<Card key={i} className="border-0 bg-gradient-to-br from-muted/50 to-muted/30">
|
||||
<CardContent className="p-4 text-center">
|
||||
<div className="h-8 bg-muted rounded w-16 mx-auto mb-2" />
|
||||
<div className="h-3 bg-muted rounded w-20 mx-auto" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Tabs */}
|
||||
<div className="flex gap-2 border-b mb-6">
|
||||
{['Overview', 'Rides', 'Models', 'Photos'].map((tab) => (
|
||||
<div key={tab} className="h-10 bg-muted rounded w-20" />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Content Grid */}
|
||||
<div className="grid lg:grid-cols-3 gap-6">
|
||||
{/* Main Content */}
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
{/* Description Card */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="h-6 bg-muted rounded w-48" />
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<div className="h-4 bg-muted rounded w-full" />
|
||||
<div className="h-4 bg-muted rounded w-full" />
|
||||
<div className="h-4 bg-muted rounded w-4/5" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Products Grid */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="h-6 bg-muted rounded w-40" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{[1, 2, 3, 4, 5, 6].map((i) => (
|
||||
<div key={i} className="space-y-2">
|
||||
<div className="aspect-square bg-muted rounded-lg" />
|
||||
<div className="h-4 bg-muted rounded w-full" />
|
||||
<div className="h-3 bg-muted rounded w-2/3" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
<div className="space-y-6">
|
||||
{/* Company Info Card */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="h-6 bg-muted rounded w-40" />
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{/* Logo */}
|
||||
<div className="w-32 h-32 bg-muted rounded mx-auto mb-4" />
|
||||
|
||||
{/* Info Items */}
|
||||
{[1, 2, 3].map((i) => (
|
||||
<div key={i} className="flex items-center gap-3">
|
||||
<div className="w-4 h-4 bg-muted rounded" />
|
||||
<div className="flex-1">
|
||||
<div className="h-4 bg-muted rounded w-24 mb-1" />
|
||||
<div className="h-3 bg-muted rounded w-32" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
101
src/components/loading/ParkDetailSkeleton.tsx
Normal file
101
src/components/loading/ParkDetailSkeleton.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
||||
|
||||
export function ParkDetailSkeleton() {
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8 max-w-7xl animate-pulse">
|
||||
{/* Breadcrumb */}
|
||||
<div className="h-4 bg-muted rounded w-48 mb-4" />
|
||||
|
||||
{/* Edit Button Area */}
|
||||
<div className="flex justify-end mb-6">
|
||||
<div className="h-10 bg-muted rounded w-32" />
|
||||
</div>
|
||||
|
||||
{/* Hero Banner */}
|
||||
<div className="aspect-[21/9] bg-muted rounded-lg mb-8" />
|
||||
|
||||
{/* Stats Cards */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-12 max-w-6xl mx-auto">
|
||||
{[1, 2, 3, 4].map((i) => (
|
||||
<Card key={i} className="border-0 bg-gradient-to-br from-muted/50 to-muted/30">
|
||||
<CardContent className="p-4 text-center">
|
||||
<div className="h-8 bg-muted rounded w-16 mx-auto mb-2" />
|
||||
<div className="h-3 bg-muted rounded w-20 mx-auto" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Tabs */}
|
||||
<div className="flex gap-2 border-b mb-6">
|
||||
{['Overview', 'Rides', 'Reviews', 'Photos', 'History'].map((tab) => (
|
||||
<div key={tab} className="h-10 bg-muted rounded w-24" />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Content Grid */}
|
||||
<div className="grid lg:grid-cols-3 gap-6">
|
||||
{/* Main Content */}
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
{/* Description Card */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="h-6 bg-muted rounded w-48" />
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<div className="h-4 bg-muted rounded w-full" />
|
||||
<div className="h-4 bg-muted rounded w-full" />
|
||||
<div className="h-4 bg-muted rounded w-3/4" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Featured Rides Card */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="h-6 bg-muted rounded w-40" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
{[1, 2, 3, 4].map((i) => (
|
||||
<div key={i} className="space-y-2">
|
||||
<div className="aspect-square bg-muted rounded-lg" />
|
||||
<div className="h-4 bg-muted rounded w-full" />
|
||||
<div className="h-3 bg-muted rounded w-3/4" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
<div className="space-y-6">
|
||||
{/* Info Card */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="h-6 bg-muted rounded w-40" />
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{[1, 2, 3, 4].map((i) => (
|
||||
<div key={i} className="flex items-center gap-3">
|
||||
<div className="w-4 h-4 bg-muted rounded" />
|
||||
<div className="flex-1">
|
||||
<div className="h-4 bg-muted rounded w-24 mb-1" />
|
||||
<div className="h-3 bg-muted rounded w-32" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Map Card */}
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<div className="aspect-square bg-muted rounded-lg" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
106
src/components/loading/RideDetailSkeleton.tsx
Normal file
106
src/components/loading/RideDetailSkeleton.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
|
||||
export function RideDetailSkeleton() {
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8 max-w-7xl animate-pulse">
|
||||
{/* Breadcrumb */}
|
||||
<div className="h-4 bg-muted rounded w-64 mb-4" />
|
||||
|
||||
{/* Edit Button Area */}
|
||||
<div className="flex justify-end mb-6">
|
||||
<div className="h-10 bg-muted rounded w-32" />
|
||||
</div>
|
||||
|
||||
{/* Hero Banner */}
|
||||
<div className="aspect-[21/9] bg-muted rounded-lg mb-8" />
|
||||
|
||||
{/* Stats Grid */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4 mb-12">
|
||||
{[1, 2, 3, 4, 5, 6].map((i) => (
|
||||
<Card key={i} className="border-0 bg-gradient-to-br from-muted/50 to-muted/30">
|
||||
<CardContent className="p-4 text-center">
|
||||
<div className="w-6 h-6 bg-muted rounded mx-auto mb-2" />
|
||||
<div className="h-8 bg-muted rounded w-16 mx-auto mb-1" />
|
||||
<div className="h-3 bg-muted rounded w-12 mx-auto" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Tabs */}
|
||||
<div className="flex gap-2 border-b mb-6">
|
||||
{['Overview', 'Reviews', 'Photos', 'History'].map((tab) => (
|
||||
<div key={tab} className="h-10 bg-muted rounded w-24" />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Content Grid */}
|
||||
<div className="grid lg:grid-cols-3 gap-6">
|
||||
{/* Main Content */}
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
{/* Description Card */}
|
||||
<Card>
|
||||
<CardContent className="p-6 space-y-3">
|
||||
<div className="h-6 bg-muted rounded w-48 mb-4" />
|
||||
<div className="h-4 bg-muted rounded w-full" />
|
||||
<div className="h-4 bg-muted rounded w-full" />
|
||||
<div className="h-4 bg-muted rounded w-5/6" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Technical Specs */}
|
||||
<Card>
|
||||
<CardContent className="p-6 space-y-4">
|
||||
<div className="h-6 bg-muted rounded w-56 mb-4" />
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{[1, 2, 3, 4, 5, 6].map((i) => (
|
||||
<div key={i} className="space-y-2">
|
||||
<div className="h-3 bg-muted rounded w-24" />
|
||||
<div className="h-5 bg-muted rounded w-32" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Sidebar */}
|
||||
<div className="space-y-6">
|
||||
{/* Ride Info Card */}
|
||||
<Card>
|
||||
<CardContent className="p-6 space-y-4">
|
||||
<div className="h-6 bg-muted rounded w-40 mb-4" />
|
||||
{[1, 2, 3, 4, 5].map((i) => (
|
||||
<div key={i} className="flex items-center gap-3">
|
||||
<div className="w-4 h-4 bg-muted rounded" />
|
||||
<div className="flex-1">
|
||||
<div className="h-4 bg-muted rounded w-20 mb-1" />
|
||||
<div className="h-3 bg-muted rounded w-28" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Similar Rides */}
|
||||
<Card>
|
||||
<CardContent className="p-6">
|
||||
<div className="h-6 bg-muted rounded w-32 mb-4" />
|
||||
<div className="space-y-3">
|
||||
{[1, 2, 3].map((i) => (
|
||||
<div key={i} className="flex gap-3">
|
||||
<div className="w-16 h-16 bg-muted rounded" />
|
||||
<div className="flex-1 space-y-2">
|
||||
<div className="h-4 bg-muted rounded w-full" />
|
||||
<div className="h-3 bg-muted rounded w-3/4" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, lazy, Suspense } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { EntityBreadcrumb } from '@/components/navigation/EntityBreadcrumb';
|
||||
import { CompanyDetailSkeleton } from '@/components/loading/CompanyDetailSkeleton';
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { getBannerUrls } from '@/lib/cloudflareImageUtils';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -150,12 +151,7 @@ export default function DesignerDetail() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="animate-pulse space-y-6">
|
||||
<div className="h-64 bg-muted rounded-lg"></div>
|
||||
<div className="h-8 bg-muted rounded w-1/2"></div>
|
||||
</div>
|
||||
</div>
|
||||
<CompanyDetailSkeleton />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -191,13 +187,8 @@ export default function DesignerDetail() {
|
||||
className="mb-4"
|
||||
/>
|
||||
|
||||
{/* Back Button and Edit Button */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<Button variant="ghost" onClick={() => navigate('/designers')}>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
Back to Designers
|
||||
</Button>
|
||||
|
||||
{/* Edit Button */}
|
||||
<div className="flex justify-end mb-6">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => requireAuth(() => setIsEditModalOpen(true), "Sign in to edit this designer")}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, lazy, Suspense } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { EntityBreadcrumb } from '@/components/navigation/EntityBreadcrumb';
|
||||
import { CompanyDetailSkeleton } from '@/components/loading/CompanyDetailSkeleton';
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { trackPageView } from '@/lib/viewTracking';
|
||||
import { getBannerUrls } from '@/lib/cloudflareImageUtils';
|
||||
@@ -160,12 +161,7 @@ export default function ManufacturerDetail() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="animate-pulse space-y-6">
|
||||
<div className="h-64 bg-muted rounded-lg"></div>
|
||||
<div className="h-8 bg-muted rounded w-1/2"></div>
|
||||
</div>
|
||||
</div>
|
||||
<CompanyDetailSkeleton />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -201,14 +197,8 @@ export default function ManufacturerDetail() {
|
||||
className="mb-4"
|
||||
/>
|
||||
|
||||
{/* Back Button and Edit Button */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<Button variant="ghost" onClick={() => navigate('/manufacturers')}>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
<span className="md:hidden">Back</span>
|
||||
<span className="hidden md:inline">Back to Manufacturers</span>
|
||||
</Button>
|
||||
|
||||
{/* Edit Button */}
|
||||
<div className="flex justify-end mb-6">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => requireAuth(() => setIsEditModalOpen(true), "Sign in to edit this manufacturer")}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect, lazy, Suspense } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { EntityBreadcrumb } from '@/components/navigation/EntityBreadcrumb';
|
||||
import { CompanyDetailSkeleton } from '@/components/loading/CompanyDetailSkeleton';
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { trackPageView } from '@/lib/viewTracking';
|
||||
import { getBannerUrls } from '@/lib/cloudflareImageUtils';
|
||||
@@ -189,12 +190,7 @@ export default function OperatorDetail() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="animate-pulse space-y-6">
|
||||
<div className="h-64 bg-muted rounded-lg"></div>
|
||||
<div className="h-8 bg-muted rounded w-1/2"></div>
|
||||
</div>
|
||||
</div>
|
||||
<CompanyDetailSkeleton />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -230,13 +226,8 @@ export default function OperatorDetail() {
|
||||
className="mb-4"
|
||||
/>
|
||||
|
||||
{/* Back Button and Edit Button */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<Button variant="ghost" onClick={() => navigate('/operators')}>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
Back to Operators
|
||||
</Button>
|
||||
|
||||
{/* Edit Button */}
|
||||
<div className="flex justify-end mb-6">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => requireAuth(() => setIsEditModalOpen(true), "Sign in to edit this operator")}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useParams, useNavigate, Link } from 'react-router-dom';
|
||||
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card';
|
||||
import { CompanyPreviewCard } from '@/components/preview/CompanyPreviewCard';
|
||||
import { EntityBreadcrumb } from '@/components/navigation/EntityBreadcrumb';
|
||||
import { ParkDetailSkeleton } from '@/components/loading/ParkDetailSkeleton';
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { getBannerUrls } from '@/lib/cloudflareImageUtils';
|
||||
import { trackPageView } from '@/lib/viewTracking';
|
||||
@@ -164,13 +165,7 @@ export default function ParkDetail() {
|
||||
if (loading) {
|
||||
return <div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="animate-pulse space-y-6">
|
||||
<div className="h-64 bg-muted rounded-lg"></div>
|
||||
<div className="h-8 bg-muted rounded w-1/2"></div>
|
||||
<div className="h-4 bg-muted rounded w-1/3"></div>
|
||||
</div>
|
||||
</div>
|
||||
<ParkDetailSkeleton />
|
||||
</div>;
|
||||
}
|
||||
if (!park) {
|
||||
@@ -203,13 +198,8 @@ export default function ParkDetail() {
|
||||
className="mb-4"
|
||||
/>
|
||||
|
||||
{/* Back Button and Edit Button */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<Button variant="ghost" onClick={() => navigate('/parks')}>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
Back to Parks
|
||||
</Button>
|
||||
|
||||
{/* Edit Button */}
|
||||
<div className="flex justify-end mb-6">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => requireAuth(() => setIsEditParkModalOpen(true), "Sign in to edit this park")}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useState, useEffect, lazy, Suspense } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { EntityBreadcrumb } from '@/components/navigation/EntityBreadcrumb';
|
||||
import { CompanyDetailSkeleton } from '@/components/loading/CompanyDetailSkeleton';
|
||||
import { trackPageView } from '@/lib/viewTracking';
|
||||
import { getBannerUrls } from '@/lib/cloudflareImageUtils';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -188,12 +190,7 @@ export default function PropertyOwnerDetail() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="animate-pulse space-y-6">
|
||||
<div className="h-64 bg-muted rounded-lg"></div>
|
||||
<div className="h-8 bg-muted rounded w-1/2"></div>
|
||||
</div>
|
||||
</div>
|
||||
<CompanyDetailSkeleton />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -220,13 +217,17 @@ export default function PropertyOwnerDetail() {
|
||||
<Header />
|
||||
|
||||
<main className="container mx-auto px-4 py-8 max-w-7xl">
|
||||
{/* Back Button and Edit Button */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<Button variant="ghost" onClick={() => navigate('/owners')}>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
Back to Property Owners
|
||||
</Button>
|
||||
|
||||
{/* Breadcrumb Navigation */}
|
||||
<EntityBreadcrumb
|
||||
segments={[
|
||||
{ label: 'Property Owners', href: '/owners' },
|
||||
{ label: owner.name }
|
||||
]}
|
||||
className="mb-4"
|
||||
/>
|
||||
|
||||
{/* Edit Button */}
|
||||
<div className="flex justify-end mb-6">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => requireAuth(() => setIsEditModalOpen(true), "Sign in to edit this property owner")}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/h
|
||||
import { CompanyPreviewCard } from '@/components/preview/CompanyPreviewCard';
|
||||
import { ParkPreviewCard } from '@/components/preview/ParkPreviewCard';
|
||||
import { EntityBreadcrumb } from '@/components/navigation/EntityBreadcrumb';
|
||||
import { RideDetailSkeleton } from '@/components/loading/RideDetailSkeleton';
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { getBannerUrls } from '@/lib/cloudflareImageUtils';
|
||||
import { trackPageView } from '@/lib/viewTracking';
|
||||
@@ -164,13 +165,7 @@ export default function RideDetail() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="animate-pulse space-y-6">
|
||||
<div className="h-64 bg-muted rounded-lg"></div>
|
||||
<div className="h-8 bg-muted rounded w-1/2"></div>
|
||||
<div className="h-4 bg-muted rounded w-1/3"></div>
|
||||
</div>
|
||||
</div>
|
||||
<RideDetailSkeleton />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -217,16 +212,8 @@ export default function RideDetail() {
|
||||
className="mb-4"
|
||||
/>
|
||||
|
||||
{/* Back Button and Edit Button */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => navigate(`/parks/${ride.park?.slug}`)}
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
Back to {ride.park?.name}
|
||||
</Button>
|
||||
|
||||
{/* Edit Button */}
|
||||
<div className="flex justify-end mb-6">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => requireAuth(() => setIsEditModalOpen(true), "Sign in to edit this ride")}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useState, useEffect, useCallback, lazy, Suspense } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { EntityBreadcrumb } from '@/components/navigation/EntityBreadcrumb';
|
||||
import { CompanyDetailSkeleton } from '@/components/loading/CompanyDetailSkeleton';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
@@ -167,17 +169,7 @@ export default function RideModelDetail() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="animate-pulse space-y-6">
|
||||
<div className="h-12 bg-muted rounded w-1/3"></div>
|
||||
<div className="h-64 bg-muted rounded"></div>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{[...Array(6)].map((_, i) => (
|
||||
<div key={i} className="h-48 bg-muted rounded-lg"></div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CompanyDetailSkeleton />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -204,12 +196,25 @@ export default function RideModelDetail() {
|
||||
<Header />
|
||||
|
||||
<main className="container mx-auto px-4 py-8">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<Button variant="ghost" onClick={() => navigate(`/manufacturers/${manufacturerSlug}/models`)}>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
Back to {manufacturer.name} Models
|
||||
</Button>
|
||||
|
||||
{/* Breadcrumb Navigation */}
|
||||
<EntityBreadcrumb
|
||||
segments={[
|
||||
{ label: 'Manufacturers', href: '/manufacturers' },
|
||||
{
|
||||
label: manufacturer.name,
|
||||
href: `/manufacturers/${manufacturerSlug}`,
|
||||
showPreview: true,
|
||||
previewType: 'company',
|
||||
previewSlug: manufacturerSlug || ''
|
||||
},
|
||||
{ label: 'Models', href: `/manufacturers/${manufacturerSlug}/models` },
|
||||
{ label: model.name }
|
||||
]}
|
||||
className="mb-4"
|
||||
/>
|
||||
|
||||
{/* Edit Button */}
|
||||
<div className="flex justify-end mb-6">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => requireAuth(() => setIsEditModalOpen(true), "Sign in to edit this ride model")}
|
||||
|
||||
Reference in New Issue
Block a user