mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:31:12 -05:00
Implement dynamic page titles
This commit is contained in:
@@ -3,12 +3,12 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>thrilltrack-explorer</title>
|
||||
<meta name="description" content="Lovable Generated Project" />
|
||||
<title>ThrillWiki - Theme Park & Roller Coaster Database</title>
|
||||
<meta name="description" content="Explore theme parks and roller coasters worldwide with ThrillWiki - the comprehensive database for enthusiasts" />
|
||||
<meta name="author" content="Lovable" />
|
||||
|
||||
<meta property="og:title" content="thrilltrack-explorer" />
|
||||
<meta property="og:description" content="Lovable Generated Project" />
|
||||
<meta property="og:title" content="ThrillWiki - Theme Park & Roller Coaster Database" />
|
||||
<meta property="og:description" content="Explore theme parks and roller coasters worldwide with ThrillWiki - the comprehensive database for enthusiasts" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
|
||||
|
||||
|
||||
12
src/hooks/useDocumentTitle.ts
Normal file
12
src/hooks/useDocumentTitle.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export function useDocumentTitle(title: string, suffix: string = 'ThrillWiki') {
|
||||
useEffect(() => {
|
||||
const fullTitle = title ? `${title} | ${suffix}` : suffix;
|
||||
document.title = fullTitle;
|
||||
|
||||
return () => {
|
||||
document.title = suffix;
|
||||
};
|
||||
}, [title, suffix]);
|
||||
}
|
||||
@@ -13,8 +13,10 @@ import { UserManagement } from '@/components/admin/UserManagement';
|
||||
import { AdminHeader } from '@/components/layout/AdminHeader';
|
||||
import { useModerationStats } from '@/hooks/useModerationStats';
|
||||
import { useAdminSettings } from '@/hooks/useAdminSettings';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function Admin() {
|
||||
useDocumentTitle('Admin Panel');
|
||||
const isMobile = useIsMobile();
|
||||
const { user, loading: authLoading } = useAuth();
|
||||
const { isModerator, loading: roleLoading } = useUserRole();
|
||||
|
||||
@@ -19,6 +19,7 @@ import { extractCloudflareImageId } from '@/lib/cloudflareImageUtils';
|
||||
import { Edit, Trash2, Eye, Plus } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
interface BlogPost {
|
||||
id: string;
|
||||
@@ -34,6 +35,7 @@ interface BlogPost {
|
||||
}
|
||||
|
||||
export default function AdminBlog() {
|
||||
useDocumentTitle('Blog Management - Admin');
|
||||
const { user } = useAuth();
|
||||
const { isAdmin, loading } = useUserRole();
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -18,8 +18,10 @@ import { supabase } from '@/integrations/supabase/client';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { QueueSkeleton } from '@/components/moderation/QueueSkeleton';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function AdminDashboard() {
|
||||
useDocumentTitle('Dashboard - Admin');
|
||||
const { user, loading: authLoading } = useAuth();
|
||||
const { isModerator, loading: roleLoading } = useUserRole();
|
||||
const { needsEnrollment, loading: mfaLoading } = useRequireMFA();
|
||||
|
||||
@@ -6,8 +6,10 @@ import { ModerationQueue, ModerationQueueRef } from '@/components/moderation/Mod
|
||||
import { QueueSkeleton } from '@/components/moderation/QueueSkeleton';
|
||||
import { useAdminSettings } from '@/hooks/useAdminSettings';
|
||||
import { useModerationStats } from '@/hooks/useModerationStats';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function AdminModeration() {
|
||||
useDocumentTitle('Moderation Queue - Admin');
|
||||
const { isLoading, isAuthorized, needsMFA, user } = useAdminGuard();
|
||||
const moderationQueueRef = useRef<ModerationQueueRef>(null);
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@ import { ReportsQueue, ReportsQueueRef } from '@/components/moderation/ReportsQu
|
||||
import { QueueSkeleton } from '@/components/moderation/QueueSkeleton';
|
||||
import { useAdminSettings } from '@/hooks/useAdminSettings';
|
||||
import { useModerationStats } from '@/hooks/useModerationStats';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function AdminReports() {
|
||||
useDocumentTitle('Reports Queue - Admin');
|
||||
const { isLoading, isAuthorized, needsMFA } = useAdminGuard();
|
||||
const reportsQueueRef = useRef<ReportsQueueRef>(null);
|
||||
|
||||
|
||||
@@ -14,8 +14,10 @@ import { useAdminSettings } from '@/hooks/useAdminSettings';
|
||||
import { NovuMigrationUtility } from '@/components/admin/NovuMigrationUtility';
|
||||
import { TestDataGenerator } from '@/components/admin/TestDataGenerator';
|
||||
import { Loader2, Save, Clock, Users, Bell, Shield, Settings, Trash2, Plug, AlertTriangle, Lock } from 'lucide-react';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function AdminSettings() {
|
||||
useDocumentTitle('Settings - Admin');
|
||||
const { user } = useAuth();
|
||||
const { isSuperuser, loading: roleLoading } = useUserRole();
|
||||
const {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
||||
import { AlertCircle } from 'lucide-react';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
interface ErrorBoundaryProps {
|
||||
children: ReactNode;
|
||||
@@ -48,6 +49,7 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
}
|
||||
|
||||
export default function AdminSystemLog() {
|
||||
useDocumentTitle('System Activity Log - Admin');
|
||||
const { isLoading, isAuthorized } = useAdminGuard(false); // No MFA required for viewing logs
|
||||
|
||||
if (isLoading) {
|
||||
|
||||
@@ -4,8 +4,10 @@ import { AdminLayout } from '@/components/layout/AdminLayout';
|
||||
import { UserManagement } from '@/components/admin/UserManagement';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function AdminUsers() {
|
||||
useDocumentTitle('User Management - Admin');
|
||||
const { isLoading, isAuthorized, needsMFA } = useAdminGuard();
|
||||
|
||||
if (isLoading) {
|
||||
|
||||
@@ -19,8 +19,10 @@ import { StorageWarning } from '@/components/auth/StorageWarning';
|
||||
import { MFAChallenge } from '@/components/auth/MFAChallenge';
|
||||
import { verifyMfaUpgrade } from '@/lib/authService';
|
||||
import { setAuthMethod } from '@/lib/sessionFlags';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function Auth() {
|
||||
useDocumentTitle('Sign In');
|
||||
const [searchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
|
||||
@@ -13,8 +13,10 @@ import { Input } from '@/components/ui/input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { MFAStepUpModal } from '@/components/auth/MFAStepUpModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function AuthCallback() {
|
||||
useDocumentTitle('Sign In - Processing');
|
||||
const navigate = useNavigate();
|
||||
const { toast } = useToast();
|
||||
const [status, setStatus] = useState<'processing' | 'success' | 'error' | 'mfa_required'>('processing');
|
||||
|
||||
@@ -8,10 +8,12 @@ import { Search, ChevronLeft, ChevronRight } from 'lucide-react';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { Footer } from '@/components/layout/Footer';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
const POSTS_PER_PAGE = 9;
|
||||
|
||||
export default function BlogIndex() {
|
||||
useDocumentTitle('Blog');
|
||||
const [page, setPage] = useState(1);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { getCloudflareImageUrl } from '@/lib/cloudflareImageUtils';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { Footer } from '@/components/layout/Footer';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function BlogPost() {
|
||||
const { slug } = useParams<{ slug: string }>();
|
||||
@@ -32,6 +33,9 @@ export default function BlogPost() {
|
||||
enabled: !!slug,
|
||||
});
|
||||
|
||||
// Update document title when post changes
|
||||
useDocumentTitle(post?.title || 'Blog Post');
|
||||
|
||||
useEffect(() => {
|
||||
if (slug) {
|
||||
supabase.rpc('increment_blog_view_count', { post_slug: slug });
|
||||
|
||||
@@ -5,8 +5,10 @@ import { ContactFAQ } from '@/components/contact/ContactFAQ';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function Contact() {
|
||||
useDocumentTitle('Contact Us');
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
|
||||
@@ -24,6 +24,7 @@ import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||
import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs';
|
||||
import { trackPageView } from '@/lib/viewTracking';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function DesignerDetail() {
|
||||
const { slug } = useParams<{ slug: string }>();
|
||||
@@ -38,6 +39,9 @@ export default function DesignerDetail() {
|
||||
const { isModerator } = useUserRole();
|
||||
const { requireAuth } = useAuthModal();
|
||||
|
||||
// Update document title when designer changes
|
||||
useDocumentTitle(designer?.name || 'Designer Details');
|
||||
|
||||
useEffect(() => {
|
||||
if (slug) {
|
||||
fetchDesignerData();
|
||||
|
||||
@@ -15,6 +15,7 @@ import { AutocompleteSearch } from '@/components/search/AutocompleteSearch';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { toast } from '@/hooks/use-toast';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function DesignerRides() {
|
||||
const { designerSlug } = useParams<{ designerSlug: string }>();
|
||||
@@ -28,6 +29,9 @@ export default function DesignerRides() {
|
||||
const [sortBy, setSortBy] = useState('name');
|
||||
const [filterCategory, setFilterCategory] = useState('all');
|
||||
const [filterStatus, setFilterStatus] = useState('all');
|
||||
|
||||
// Update document title when designer changes
|
||||
useDocumentTitle(designer ? `${designer.name} - Rides` : 'Designer Rides');
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
|
||||
@@ -23,8 +23,10 @@ import { toast } from '@/hooks/use-toast';
|
||||
import { submitCompanyCreation } from '@/lib/companyHelpers';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function Designers() {
|
||||
useDocumentTitle('Designers');
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuth();
|
||||
const { isModerator } = useUserRole();
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { supabase } from "@/integrations/supabase/client";
|
||||
import { authStorage } from "@/lib/authStorage";
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
/**
|
||||
* ForceLogout - Hidden endpoint for completely clearing auth session
|
||||
@@ -9,6 +10,7 @@ import { authStorage } from "@/lib/authStorage";
|
||||
* Not linked anywhere in the UI - for manual navigation only
|
||||
*/
|
||||
const ForceLogout = () => {
|
||||
useDocumentTitle('Signing Out');
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { SimpleHeroSearch } from '@/components/homepage/SimpleHeroSearch';
|
||||
import { ContentTabs } from '@/components/homepage/ContentTabs';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
const Index = () => {
|
||||
useDocumentTitle('Home');
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
|
||||
@@ -24,6 +24,7 @@ import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||
import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function ManufacturerDetail() {
|
||||
const { slug } = useParams<{ slug: string }>();
|
||||
@@ -39,6 +40,9 @@ export default function ManufacturerDetail() {
|
||||
const { isModerator } = useUserRole();
|
||||
const { requireAuth } = useAuthModal();
|
||||
|
||||
// Update document title when manufacturer changes
|
||||
useDocumentTitle(manufacturer?.name || 'Manufacturer Details');
|
||||
|
||||
useEffect(() => {
|
||||
if (slug) {
|
||||
fetchManufacturerData();
|
||||
|
||||
@@ -15,6 +15,7 @@ import { AutocompleteSearch } from '@/components/search/AutocompleteSearch';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { toast } from '@/hooks/use-toast';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
interface RideModelWithCount extends RideModel {
|
||||
ride_count: number;
|
||||
@@ -28,6 +29,9 @@ export default function ManufacturerModels() {
|
||||
const [manufacturer, setManufacturer] = useState<Company | null>(null);
|
||||
const [models, setModels] = useState<RideModelWithCount[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
// Update document title when manufacturer changes
|
||||
useDocumentTitle(manufacturer ? `${manufacturer.name} - Models` : 'Manufacturer Models');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [sortBy, setSortBy] = useState('name');
|
||||
const [filterCategory, setFilterCategory] = useState('all');
|
||||
|
||||
@@ -15,6 +15,7 @@ import { AutocompleteSearch } from '@/components/search/AutocompleteSearch';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { toast } from '@/hooks/use-toast';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function ManufacturerRides() {
|
||||
const { manufacturerSlug } = useParams<{ manufacturerSlug: string }>();
|
||||
@@ -28,6 +29,9 @@ export default function ManufacturerRides() {
|
||||
const [sortBy, setSortBy] = useState('name');
|
||||
const [filterCategory, setFilterCategory] = useState('all');
|
||||
const [filterStatus, setFilterStatus] = useState('all');
|
||||
|
||||
// Update document title when manufacturer changes
|
||||
useDocumentTitle(manufacturer ? `${manufacturer.name} - Rides` : 'Manufacturer Rides');
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
|
||||
@@ -23,8 +23,10 @@ import { toast } from '@/hooks/use-toast';
|
||||
import { submitCompanyCreation } from '@/lib/companyHelpers';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function Manufacturers() {
|
||||
useDocumentTitle('Manufacturers');
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuth();
|
||||
const { isModerator } = useUserRole();
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useEffect } from "react";
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
const NotFound = () => {
|
||||
useDocumentTitle('404 - Page Not Found');
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -25,6 +25,7 @@ import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||
import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function OperatorDetail() {
|
||||
const { slug } = useParams<{ slug: string }>();
|
||||
@@ -42,6 +43,9 @@ export default function OperatorDetail() {
|
||||
const { isModerator } = useUserRole();
|
||||
const { requireAuth } = useAuthModal();
|
||||
|
||||
// Update document title when operator changes
|
||||
useDocumentTitle(operator?.name || 'Operator Details');
|
||||
|
||||
useEffect(() => {
|
||||
if (slug) {
|
||||
fetchOperatorData();
|
||||
|
||||
@@ -15,6 +15,7 @@ import { ParkFilters } from '@/components/parks/ParkFilters';
|
||||
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Grid3X3, List } from 'lucide-react';
|
||||
import { FilterState, SortState } from './Parks';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
const initialFilters: FilterState = {
|
||||
search: '',
|
||||
@@ -45,6 +46,9 @@ export default function OperatorParks() {
|
||||
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
|
||||
const [showFilters, setShowFilters] = useState(false);
|
||||
|
||||
// Update document title when operator changes
|
||||
useDocumentTitle(operator ? `${operator.name} - Parks` : 'Operator Parks');
|
||||
|
||||
useEffect(() => {
|
||||
if (operatorSlug) {
|
||||
fetchData();
|
||||
|
||||
@@ -24,8 +24,10 @@ import { toast } from '@/hooks/use-toast';
|
||||
import { submitCompanyCreation } from '@/lib/companyHelpers';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
const Operators = () => {
|
||||
useDocumentTitle('Operators');
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuth();
|
||||
const { isModerator } = useUserRole();
|
||||
|
||||
@@ -15,6 +15,7 @@ import { ParkFilters } from '@/components/parks/ParkFilters';
|
||||
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Grid3X3, List } from 'lucide-react';
|
||||
import { FilterState, SortState } from './Parks';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
const initialFilters: FilterState = {
|
||||
search: '',
|
||||
@@ -45,6 +46,9 @@ export default function OwnerParks() {
|
||||
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
|
||||
const [showFilters, setShowFilters] = useState(false);
|
||||
|
||||
// Update document title when owner changes
|
||||
useDocumentTitle(owner ? `${owner.name} - Parks` : 'Owner Parks');
|
||||
|
||||
useEffect(() => {
|
||||
if (ownerSlug) {
|
||||
fetchData();
|
||||
|
||||
@@ -29,6 +29,7 @@ import { Edit } from 'lucide-react';
|
||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||
import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function ParkDetail() {
|
||||
const {
|
||||
@@ -47,6 +48,10 @@ export default function ParkDetail() {
|
||||
const [photoCount, setPhotoCount] = useState<number>(0);
|
||||
const [statsLoading, setStatsLoading] = useState(true);
|
||||
const { isModerator } = useUserRole();
|
||||
|
||||
// Update document title when park changes
|
||||
useDocumentTitle(park?.name || 'Park Details');
|
||||
|
||||
const fetchPhotoCount = useCallback(async (parkId: string) => {
|
||||
try {
|
||||
const { count, error } = await supabase
|
||||
|
||||
@@ -18,8 +18,10 @@ import { toast } from '@/hooks/use-toast';
|
||||
import { submitCompanyCreation } from '@/lib/companyHelpers';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
const ParkOwners = () => {
|
||||
useDocumentTitle('Property Owners');
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuth();
|
||||
const { isModerator } = useUserRole();
|
||||
|
||||
@@ -16,6 +16,7 @@ import { useAuth } from '@/hooks/useAuth';
|
||||
import { toast } from '@/hooks/use-toast';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function ParkRides() {
|
||||
const { parkSlug } = useParams<{ parkSlug: string }>();
|
||||
@@ -28,6 +29,9 @@ export default function ParkRides() {
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [sortBy, setSortBy] = useState('name');
|
||||
const [filterCategory, setFilterCategory] = useState('all');
|
||||
|
||||
// Update document title when park changes
|
||||
useDocumentTitle(park ? `${park.name} - Rides` : 'Park Rides');
|
||||
const [filterStatus, setFilterStatus] = useState('all');
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function Privacy() {
|
||||
useDocumentTitle('Privacy Policy');
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
|
||||
@@ -30,6 +30,7 @@ import { LocationDisplay } from '@/components/profile/LocationDisplay';
|
||||
import { UserBlockButton } from '@/components/profile/UserBlockButton';
|
||||
import { PersonalLocationDisplay } from '@/components/profile/PersonalLocationDisplay';
|
||||
import { useUserRole } from '@/hooks/useUserRole';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
// Activity type definitions
|
||||
interface SubmissionActivity {
|
||||
@@ -156,6 +157,9 @@ export default function Profile() {
|
||||
// User role checking
|
||||
const { isModerator, loading: rolesLoading } = useUserRole();
|
||||
|
||||
// Update document title when profile changes
|
||||
useDocumentTitle(profile?.username ? `${profile.username}'s Profile` : 'Profile');
|
||||
|
||||
// Username validation
|
||||
const usernameValidation = useUsernameValidation(editForm.username, profile?.username);
|
||||
useEffect(() => {
|
||||
|
||||
@@ -25,6 +25,7 @@ import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||
import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function PropertyOwnerDetail() {
|
||||
const { slug } = useParams<{ slug: string }>();
|
||||
@@ -42,6 +43,9 @@ export default function PropertyOwnerDetail() {
|
||||
const { isModerator } = useUserRole();
|
||||
const { requireAuth } = useAuthModal();
|
||||
|
||||
// Update document title when owner changes
|
||||
useDocumentTitle(owner?.name || 'Property Owner Details');
|
||||
|
||||
useEffect(() => {
|
||||
if (slug) {
|
||||
fetchOwnerData();
|
||||
|
||||
@@ -52,6 +52,7 @@ import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||
import { EntityHistoryTabs } from '@/components/history/EntityHistoryTabs';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
// Extended Ride type with additional properties for easier access
|
||||
interface RideWithParkId extends Ride {
|
||||
@@ -71,6 +72,9 @@ export default function RideDetail() {
|
||||
const [photoCount, setPhotoCount] = useState<number>(0);
|
||||
const [statsLoading, setStatsLoading] = useState(true);
|
||||
|
||||
// Update document title when ride changes
|
||||
useDocumentTitle(ride?.name || 'Ride Details');
|
||||
|
||||
useEffect(() => {
|
||||
if (parkSlug && rideSlug) {
|
||||
fetchRideData();
|
||||
|
||||
@@ -22,6 +22,7 @@ import { ManufacturerPhotoGallery } from '@/components/companies/ManufacturerPho
|
||||
const RideModelForm = lazy(() => import('@/components/admin/RideModelForm').then(m => ({ default: m.RideModelForm })));
|
||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||
import { EntityVersionHistory } from '@/components/versioning/EntityVersionHistory';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function RideModelDetail() {
|
||||
const { manufacturerSlug, modelSlug } = useParams<{ manufacturerSlug: string; modelSlug: string }>();
|
||||
@@ -33,6 +34,9 @@ export default function RideModelDetail() {
|
||||
const [rides, setRides] = useState<Ride[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||
|
||||
// Update document title when model changes
|
||||
useDocumentTitle(model?.name || 'Ride Model Details');
|
||||
const [statistics, setStatistics] = useState({ rideCount: 0, photoCount: 0 });
|
||||
|
||||
// Fetch technical specifications from relational table
|
||||
|
||||
@@ -16,6 +16,7 @@ import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { toast } from '@/hooks/use-toast';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import type { Ride, Company, RideModel } from "@/types/database";
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function RideModelRides() {
|
||||
const { manufacturerSlug, modelSlug } = useParams<{ manufacturerSlug: string; modelSlug: string }>();
|
||||
@@ -28,6 +29,9 @@ export default function RideModelRides() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [sortBy, setSortBy] = useState('name');
|
||||
|
||||
// Update document title when model changes
|
||||
useDocumentTitle(model ? `${model.name} - Rides` : 'Model Rides');
|
||||
const [filterCategory, setFilterCategory] = useState('all');
|
||||
const [filterStatus, setFilterStatus] = useState('all');
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
|
||||
@@ -22,8 +22,10 @@ import { useUserRole } from '@/hooks/useUserRole';
|
||||
import { toast } from '@/hooks/use-toast';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { useAuthModal } from '@/hooks/useAuthModal';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function Rides() {
|
||||
useDocumentTitle('Rides & Attractions');
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuth();
|
||||
const { isModerator } = useUserRole();
|
||||
|
||||
@@ -2,8 +2,10 @@ import { Header } from '@/components/layout/Header';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { CheckCircle, AlertTriangle, Camera, Star, MapPin, Settings, Building2, Globe } from 'lucide-react';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function SubmissionGuidelines() {
|
||||
useDocumentTitle('Submission Guidelines');
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Header } from '@/components/layout/Header';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function Terms() {
|
||||
useDocumentTitle('Terms of Service');
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<Header />
|
||||
|
||||
@@ -131,6 +131,7 @@ interface EmailThread {
|
||||
}
|
||||
|
||||
export default function AdminContact() {
|
||||
useDocumentTitle('Contact Submissions - Admin');
|
||||
const queryClient = useQueryClient();
|
||||
const { theme } = useTheme();
|
||||
const { isAdmin, loading: rolesLoading } = useUserRole();
|
||||
|
||||
@@ -16,8 +16,10 @@ import { AdminLayout } from '@/components/layout/AdminLayout';
|
||||
import { useUserRole } from '@/hooks/useUserRole';
|
||||
import { handleError, handleSuccess } from '@/lib/errorHandler';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { useDocumentTitle } from '@/hooks/useDocumentTitle';
|
||||
|
||||
export default function AdminEmailSettings() {
|
||||
useDocumentTitle('Email Settings - Admin');
|
||||
const queryClient = useQueryClient();
|
||||
const { isSuperuser, loading: rolesLoading } = useUserRole();
|
||||
const [signature, setSignature] = useState('');
|
||||
|
||||
Reference in New Issue
Block a user