diff --git a/src/components/NotificationBell.tsx b/src/components/NotificationBell.tsx index 45bf115..3fb435a 100644 --- a/src/components/NotificationBell.tsx +++ b/src/components/NotificationBell.tsx @@ -12,6 +12,7 @@ import { JoinRequestCard } from '@/components/JoinRequestCard'; import { CollectiveJoinRequestCard } from '@/components/CollectiveJoinRequestCard'; import { ActivityNotificationCard } from '@/components/ActivityNotificationCard'; import { ImageWithFallback } from '@/components/ImageWithFallback'; +import { EmptyState as SharedEmptyState } from '@/components/EmptyState'; import { useCrewNotifications, useIsPendingMember } from '@/hooks/useCrewNotifications'; import { useActivityNotifications } from '@/hooks/useActivityNotifications'; import { useNotificationsRead } from '@/hooks/useNotificationsRead'; @@ -180,13 +181,12 @@ function NewsletterItem({ function EmptyState({ label }: { label: string }) { return ( -
-
- -
-

You're all caught up

-

{label}

-
+ ); } diff --git a/src/pages/AmberCallbackPage.tsx b/src/pages/AmberCallbackPage.tsx index 6c2fa9f..a41b488 100644 --- a/src/pages/AmberCallbackPage.tsx +++ b/src/pages/AmberCallbackPage.tsx @@ -11,6 +11,7 @@ import { useEffect, useRef, useState } from 'react'; import { useNavigate, Link } from 'react-router-dom'; +import { useSeoMeta } from '@unhead/react'; import { useLoginActions } from '@/hooks/useLoginActions'; import { useToast } from '@/hooks/useToast'; import { @@ -34,6 +35,11 @@ export default function AmberCallbackPage() { const [status, setStatus] = useState('processing'); const [message, setMessage] = useState('Completing login with Amber...'); + useSeoMeta({ + title: 'Signing in with Amber - SkateSpots', + description: 'Completing your Amber (NIP-55) login.', + }); + useEffect(() => { if (hasProcessed.current) return; hasProcessed.current = true; diff --git a/src/pages/EditTourPage.tsx b/src/pages/EditTourPage.tsx index 29fba52..0978b70 100644 --- a/src/pages/EditTourPage.tsx +++ b/src/pages/EditTourPage.tsx @@ -1,4 +1,5 @@ import { useParams } from 'react-router-dom'; +import { useSeoMeta } from '@unhead/react'; import { Layout } from '@/components/Layout'; import { Card, CardContent } from '@/components/ui/card'; import { Skeleton } from '@/components/ui/skeleton'; @@ -20,6 +21,11 @@ export default function EditTourPage() { const { user } = useCurrentUser(); const { data: tour, isLoading, error } = useTour(identifier || '', pubkey); + useSeoMeta({ + title: tour?.title ? `Edit ${tour.title} - SkateSpots` : 'Edit Tour - SkateSpots', + description: 'Edit your skate tour — update stops, dates and details.', + }); + if (isLoading) { return ( diff --git a/src/pages/LabPage.tsx b/src/pages/LabPage.tsx index e19740e..2bfb28e 100644 --- a/src/pages/LabPage.tsx +++ b/src/pages/LabPage.tsx @@ -71,7 +71,7 @@ import { PersonStanding, ArrowRight, } from 'lucide-react'; -import { cn } from '@/lib/utils'; +import { EmptyState as SharedEmptyState } from '@/components/EmptyState'; import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'; import { ProBadge } from '@/components/ProBadge'; import { LabCrewsStrip } from '@/components/LabCrewsStrip'; @@ -1096,28 +1096,29 @@ function EmptyState({ serviceType, user }: { serviceType: ServiceType; user: boo const Icon = c.icon; return ( -
-
- -
-

{c.title}

-

{c.body}

- {user ? ( - - - - ) : ( -

- Log in to create a profile -

- )} - - Have questions? Check the FAQ → - -
+ + {c.body}{' '} + + Log in + {' '} + to create a profile. + + ) + } + actions={ + user + ? [{ label: c.cta, to: c.to, icon: Plus, className: c.color }] + : [] + } + footer={{ label: 'Have questions? Check the FAQ →', to: '/faq' }} + /> ); } diff --git a/src/pages/NIP19Page.tsx b/src/pages/NIP19Page.tsx index 2c064c0..62defdd 100644 --- a/src/pages/NIP19Page.tsx +++ b/src/pages/NIP19Page.tsx @@ -1,5 +1,6 @@ import { nip19 } from 'nostr-tools'; import { useParams, Link } from 'react-router-dom'; +import { useSeoMeta } from '@unhead/react'; import { Layout } from '@/components/Layout'; import { ImageWithFallback } from '@/components/ImageWithFallback'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; @@ -164,6 +165,11 @@ function ProfilePage({ pubkey }: { pubkey: string }) { const npub = nip19.npubEncode(pubkey); const isOwnProfile = user?.pubkey === pubkey; + useSeoMeta({ + title: `${displayName} - SkateSpots`, + description: about ? about.slice(0, 160) : `${displayName}'s profile on SkateSpots.`, + }); + // At-a-glance skater stats for the summary strip. const { data: riderStats } = useRiderStats(pubkey); const memberSince = profileEventCreatedAt(author.data?.event?.created_at);