535 lines
31 KiB
TypeScript
535 lines
31 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import Link from 'next/link';
|
|
import { INITIAL_GROUP_RIDES } from './fixtures';
|
|
import { GroupRideSummary } from './types';
|
|
import { LivePackRadar } from './live-pack-radar';
|
|
|
|
interface GroupRidesShowcaseProps {
|
|
isLoggedIn?: boolean;
|
|
userEmail?: string | null;
|
|
onGoToManagement?: () => void;
|
|
}
|
|
|
|
export function GroupRidesShowcase({
|
|
isLoggedIn = false,
|
|
userEmail,
|
|
onGoToManagement,
|
|
}: GroupRidesShowcaseProps) {
|
|
const [selectedFilter, setSelectedFilter] = useState<'all' | 'brisk' | 'track' | 'tour'>('all');
|
|
const [sampleRides] = useState<GroupRideSummary[]>(INITIAL_GROUP_RIDES);
|
|
|
|
const filteredRides = sampleRides.filter((ride) => {
|
|
if (selectedFilter === 'brisk') return ride.paceClassification === 'Brisk Pace';
|
|
if (selectedFilter === 'track') return ride.paceClassification === 'Track Pace';
|
|
if (selectedFilter === 'tour')
|
|
return (
|
|
ride.paceClassification === 'Weekend Tours' ||
|
|
ride.paceClassification === 'Endurance / Chill'
|
|
);
|
|
return true;
|
|
});
|
|
|
|
return (
|
|
<div className="flagship-page text-on-surface bg-surface min-h-screen">
|
|
<div className="flex flex-col w-full">
|
|
{/* Dynamic Atmospheric Glow Background Layers */}
|
|
<div className="relative w-full overflow-hidden">
|
|
<div className="absolute top-0 left-1/4 w-96 h-96 bg-primary-container/10 rounded-full blur-[120px] pointer-events-none -z-10"></div>
|
|
<div className="absolute top-64 right-10 w-[500px] h-[500px] bg-secondary-fixed/5 rounded-full blur-[140px] pointer-events-none -z-10"></div>
|
|
|
|
{/* Authenticated Rider Quick Notice (if logged-in user visits showcase) */}
|
|
{isLoggedIn && (
|
|
<div className="bg-primary-container/15 border-b border-primary-container/30 py-2.5 px-4">
|
|
<div className="max-w-container-max mx-auto flex items-center justify-between text-xs font-semibold">
|
|
<div className="flex items-center gap-2 text-primary-container">
|
|
<span className="material-symbols-outlined text-[18px]">verified_user</span>
|
|
<span>
|
|
Viewing Public Showcase {userEmail ? `as ${userEmail}` : '(Signed In)'}
|
|
</span>
|
|
</div>
|
|
{onGoToManagement ? (
|
|
<button
|
|
type="button"
|
|
onClick={onGoToManagement}
|
|
className="inline-flex items-center gap-1.5 px-3 py-1 rounded-lg bg-primary-container text-on-primary-container font-bold hover:shadow-[0_0_12px_rgba(0,242,254,0.4)] transition cursor-pointer"
|
|
>
|
|
<span>Go to Group Rides Console</span>
|
|
<span className="material-symbols-outlined text-[14px]">arrow_forward</span>
|
|
</button>
|
|
) : (
|
|
<Link
|
|
href="/group-rides?view=manage"
|
|
className="inline-flex items-center gap-1.5 px-3 py-1 rounded-lg bg-primary-container text-on-primary-container font-bold hover:shadow-[0_0_12px_rgba(0,242,254,0.4)] transition"
|
|
>
|
|
<span>Go to Group Rides Console</span>
|
|
<span className="material-symbols-outlined text-[14px]">arrow_forward</span>
|
|
</Link>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Hero Section */}
|
|
<section className="max-w-container-max mx-auto px-gutter-desktop pt-space-2xl pb-space-3xl">
|
|
<div className="flex flex-col items-start max-w-4xl">
|
|
{/* Eyebrow Badge */}
|
|
<div className="inline-flex items-center gap-space-xs px-space-sm py-1.5 rounded-full bg-surface-container-high border-0 shadow-sm mb-space-md">
|
|
<span className="relative flex h-2.5 w-2.5">
|
|
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-secondary-fixed opacity-75"></span>
|
|
<span className="relative inline-flex rounded-full h-2.5 w-2.5 bg-secondary-fixed-dim"></span>
|
|
</span>
|
|
<span className="font-label-caps text-label-caps text-secondary-fixed tracking-wide">
|
|
Formation Telemetry Showcase
|
|
</span>
|
|
</div>
|
|
|
|
{/* Headline */}
|
|
<h1 className="font-display-hero text-display-hero text-on-surface tracking-tight mb-space-sm">
|
|
Ride in pack formation. <br />
|
|
<span className="bg-gradient-to-r from-primary-container via-primary-fixed to-secondary-fixed text-transparent bg-clip-text">
|
|
Never lose a wingman.
|
|
</span>
|
|
</h1>
|
|
|
|
{/* Subheading */}
|
|
<p className="font-body-lg text-body-lg text-on-surface-variant max-w-2xl mb-space-xl">
|
|
Real-time rider radar, staggered formation spacing alerts, instant incident broadcast, and
|
|
automated regroup checkpoints calibrated for fast canyon runs and transcontinental tours.
|
|
</p>
|
|
|
|
{/* Showcase Action CTAs */}
|
|
<div className="flex flex-wrap items-center gap-space-md w-full">
|
|
{isLoggedIn ? (
|
|
<>
|
|
{onGoToManagement ? (
|
|
<button
|
|
type="button"
|
|
onClick={onGoToManagement}
|
|
className="inline-flex items-center justify-center gap-space-xs px-space-xl py-3.5 rounded-xl bg-gradient-to-r from-primary-container to-primary-fixed text-on-primary-container font-headline-sm text-headline-sm shadow-xl hover:shadow-[0_0_24px_rgba(0,242,254,0.4)] transition-all cursor-pointer"
|
|
>
|
|
<span className="material-symbols-outlined text-[20px]">dashboard</span>
|
|
Manage My Group Rides
|
|
</button>
|
|
) : (
|
|
<Link
|
|
href="/group-rides?view=manage"
|
|
className="inline-flex items-center justify-center gap-space-xs px-space-xl py-3.5 rounded-xl bg-gradient-to-r from-primary-container to-primary-fixed text-on-primary-container font-headline-sm text-headline-sm shadow-xl hover:shadow-[0_0_24px_rgba(0,242,254,0.4)] transition-all"
|
|
>
|
|
<span className="material-symbols-outlined text-[20px]">dashboard</span>
|
|
Manage My Group Rides
|
|
</Link>
|
|
)}
|
|
<a
|
|
href="#radar-cockpit"
|
|
className="inline-flex items-center justify-center gap-space-xs px-space-lg py-3.5 rounded-xl bg-surface-container-high hover:bg-surface-container-highest text-on-surface font-headline-sm text-headline-sm transition-all cursor-pointer border border-outline-variant/30"
|
|
>
|
|
<span className="material-symbols-outlined text-primary-fixed-dim text-[20px]">
|
|
radar
|
|
</span>
|
|
Explore Radar Simulation
|
|
</a>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Link
|
|
href="/register"
|
|
className="inline-flex items-center justify-center gap-space-xs px-space-xl py-3.5 rounded-xl bg-gradient-to-r from-primary-container to-primary-fixed text-on-primary-container font-headline-sm text-headline-sm shadow-xl hover:shadow-[0_0_24px_rgba(0,242,254,0.4)] transition-all"
|
|
>
|
|
<span className="material-symbols-outlined text-[20px]">how_to_reg</span>
|
|
Get Started Free
|
|
</Link>
|
|
<Link
|
|
href="/login?redirect=/group-rides"
|
|
className="inline-flex items-center justify-center gap-space-xs px-space-lg py-3.5 rounded-xl bg-surface-container-high hover:bg-surface-container-highest text-on-surface font-headline-sm text-headline-sm transition-all border border-outline-variant/30"
|
|
>
|
|
<span className="material-symbols-outlined text-primary-fixed-dim text-[20px]">
|
|
login
|
|
</span>
|
|
Sign In to Join Runs
|
|
</Link>
|
|
<a
|
|
href="#radar-cockpit"
|
|
className="inline-flex items-center justify-center gap-space-xs px-space-md py-3.5 rounded-xl text-on-surface-variant hover:text-on-surface font-label-md text-label-md transition-colors"
|
|
>
|
|
<span className="material-symbols-outlined text-[18px]">expand_more</span>
|
|
Live Radar Demo
|
|
</a>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Interactive Live Pack Radar Cockpit */}
|
|
<section id="radar-cockpit" className="max-w-container-max mx-auto px-gutter-desktop mb-space-4xl scroll-mt-24">
|
|
<LivePackRadar initialMode="tactical" />
|
|
</section>
|
|
|
|
{/* Group Ride Features Grid (6 Core Subsystems) */}
|
|
<section className="max-w-container-max mx-auto px-gutter-desktop mb-space-4xl">
|
|
<div className="flex flex-col mb-space-2xl">
|
|
<span className="font-label-caps text-label-caps text-primary-container tracking-wide mb-1">
|
|
Formation Architecture
|
|
</span>
|
|
<h2 className="font-headline-xl text-headline-xl text-on-surface tracking-tight">
|
|
Engineered for Squadron Cohesion
|
|
</h2>
|
|
<p className="font-body-md text-body-md text-on-surface-variant max-w-2xl">
|
|
High-frequency mesh communications keep the entire formation synchronized through blind
|
|
apexes, mountain passes, and dense urban corridors.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-space-lg">
|
|
{/* Feature 1: Paceline Audit */}
|
|
<div className="bg-surface-container-low p-space-xl rounded-2xl flex flex-col justify-between hover:bg-surface-container transition-all shadow-md border border-outline-variant/20">
|
|
<div>
|
|
<div className="w-12 h-12 rounded-xl bg-surface-container-high flex items-center justify-center text-primary-container mb-space-lg">
|
|
<span className="material-symbols-outlined text-[26px]">spatial_audio_off</span>
|
|
</div>
|
|
<span className="font-code-mono text-code-mono text-primary-fixed-dim block mb-1">
|
|
01 / Paceline Spacing
|
|
</span>
|
|
<h3 className="font-headline-md text-headline-md text-on-surface mb-space-sm">
|
|
Staggered Paceline Warnings
|
|
</h3>
|
|
<p className="font-body-sm text-body-sm text-on-surface-variant leading-relaxed">
|
|
Spatial audio HUD chimes dynamically sound whenever rider follow distance or lane
|
|
positioning falls beneath calculated emergency stopping thresholds.
|
|
</p>
|
|
</div>
|
|
<div className="pt-space-lg mt-space-lg flex items-center justify-between font-code-mono text-code-mono text-primary-container border-t border-outline-variant/20">
|
|
<span>Latency: <12ms</span>
|
|
<span className="material-symbols-outlined text-[16px]">arrow_forward</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Feature 2: Crash & Separation Alerts */}
|
|
<div className="bg-surface-container-low p-space-xl rounded-2xl flex flex-col justify-between hover:bg-surface-container transition-all shadow-md border border-outline-variant/20">
|
|
<div>
|
|
<div className="w-12 h-12 rounded-xl bg-surface-container-high flex items-center justify-center text-error mb-space-lg">
|
|
<span className="material-symbols-outlined text-[26px]">fmd_bad</span>
|
|
</div>
|
|
<span className="font-code-mono text-code-mono text-error block mb-1">
|
|
02 / Swarm Broadcast
|
|
</span>
|
|
<h3 className="font-headline-md text-headline-md text-on-surface mb-space-sm">
|
|
Crash & Separation Alerts
|
|
</h3>
|
|
<p className="font-body-sm text-body-sm text-on-surface-variant leading-relaxed">
|
|
Autonomous 6-axis IMU impact detection pings the entire pack instantly. Visual yellow and
|
|
red telemetry flags highlight coordinates for immediate regrouping.
|
|
</p>
|
|
</div>
|
|
<div className="pt-space-lg mt-space-lg flex items-center justify-between font-code-mono text-code-mono text-error border-t border-outline-variant/20">
|
|
<span>IMU Sensing: 6-Axis</span>
|
|
<span className="material-symbols-outlined text-[16px]">arrow_forward</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Feature 3: P2P Mesh */}
|
|
<div className="bg-surface-container-low p-space-xl rounded-2xl flex flex-col justify-between hover:bg-surface-container transition-all shadow-md border border-outline-variant/20">
|
|
<div>
|
|
<div className="w-12 h-12 rounded-xl bg-surface-container-high flex items-center justify-center text-secondary-fixed mb-space-lg">
|
|
<span className="material-symbols-outlined text-[26px]">hub</span>
|
|
</div>
|
|
<span className="font-code-mono text-code-mono text-secondary-fixed block mb-1">
|
|
03 / Offline Link
|
|
</span>
|
|
<h3 className="font-headline-md text-headline-md text-on-surface mb-space-sm">
|
|
Peer-to-Peer Mesh Sync
|
|
</h3>
|
|
<p className="font-body-sm text-body-sm text-on-surface-variant leading-relaxed">
|
|
Never rely on cellular towers in deep canyons. Ad-hoc Bluetooth and Wi-Fi Direct
|
|
protocols daisy-chain vital bike metrics from road lead to sweep.
|
|
</p>
|
|
</div>
|
|
<div className="pt-space-lg mt-space-lg flex items-center justify-between font-code-mono text-code-mono text-secondary-fixed border-t border-outline-variant/20">
|
|
<span>Zero-cell Ready</span>
|
|
<span className="material-symbols-outlined text-[16px]">arrow_forward</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Feature 4: Mission Debrief */}
|
|
<div className="bg-surface-container-low p-space-xl rounded-2xl flex flex-col justify-between hover:bg-surface-container transition-all shadow-md border border-outline-variant/20">
|
|
<div>
|
|
<div className="w-12 h-12 rounded-xl bg-surface-container-high flex items-center justify-center text-primary-fixed mb-space-lg">
|
|
<span className="material-symbols-outlined text-[26px]">history_toggle_off</span>
|
|
</div>
|
|
<span className="font-code-mono text-code-mono text-primary-fixed block mb-1">
|
|
04 / Mission Debrief
|
|
</span>
|
|
<h3 className="font-headline-md text-headline-md text-on-surface mb-space-sm">
|
|
3D Multi-Bike Replay
|
|
</h3>
|
|
<p className="font-body-sm text-body-sm text-on-surface-variant leading-relaxed">
|
|
Relive the run with synced multi-bike timelines. Compare apex entries, sector speeds,
|
|
and individual lean angles across the entire squad simultaneously.
|
|
</p>
|
|
</div>
|
|
<div className="pt-space-lg mt-space-lg flex items-center justify-between font-code-mono text-code-mono text-primary-fixed border-t border-outline-variant/20">
|
|
<span>3D Replay Engine</span>
|
|
<span className="material-symbols-outlined text-[16px]">arrow_forward</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Feature 5: Multi-Band GNSS Formation Lock */}
|
|
<div className="bg-surface-container-low p-space-xl rounded-2xl flex flex-col justify-between hover:bg-surface-container transition-all shadow-md border border-outline-variant/20">
|
|
<div>
|
|
<div className="w-12 h-12 rounded-xl bg-surface-container-high flex items-center justify-center text-secondary-fixed-dim mb-space-lg">
|
|
<span className="material-symbols-outlined text-[26px]">satellite_alt</span>
|
|
</div>
|
|
<span className="font-code-mono text-code-mono text-secondary-fixed block mb-1">
|
|
05 / Precision Mesh
|
|
</span>
|
|
<h3 className="font-headline-md text-headline-md text-on-surface mb-space-sm">
|
|
Multi-Band GNSS Lock
|
|
</h3>
|
|
<p className="font-body-sm text-body-sm text-on-surface-variant leading-relaxed">
|
|
Dual-frequency L1+L5 satellite tracking ensures accurate relative positioning even in
|
|
dense canyon canopy where consumer navigation drifts.
|
|
</p>
|
|
</div>
|
|
<div className="pt-space-lg mt-space-lg flex items-center justify-between font-code-mono text-code-mono text-secondary-fixed-dim border-t border-outline-variant/20">
|
|
<span>Sub-Meter Precision</span>
|
|
<span className="material-symbols-outlined text-[16px]">arrow_forward</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Feature 6: Dynamic Checkpoint Auto-Regroup */}
|
|
<div className="bg-surface-container-low p-space-xl rounded-2xl flex flex-col justify-between hover:bg-surface-container transition-all shadow-md border border-outline-variant/20">
|
|
<div>
|
|
<div className="w-12 h-12 rounded-xl bg-surface-container-high flex items-center justify-center text-primary-container mb-space-lg">
|
|
<span className="material-symbols-outlined text-[26px]">pin_drop</span>
|
|
</div>
|
|
<span className="font-code-mono text-code-mono text-primary-container block mb-1">
|
|
06 / Intelligent Checkpoints
|
|
</span>
|
|
<h3 className="font-headline-md text-headline-md text-on-surface mb-space-sm">
|
|
Auto-Regroup Checkpoints
|
|
</h3>
|
|
<p className="font-body-sm text-body-sm text-on-surface-variant leading-relaxed">
|
|
Automatic rally waypoints notify lead marshals when the pack spreads beyond safety
|
|
parameters, ensuring no rider is left behind at remote turnouts.
|
|
</p>
|
|
</div>
|
|
<div className="pt-space-lg mt-space-lg flex items-center justify-between font-code-mono text-code-mono text-primary-container border-t border-outline-variant/20">
|
|
<span>Smart Geofencing</span>
|
|
<span className="material-symbols-outlined text-[16px]">arrow_forward</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Hardware & Intercom Strip */}
|
|
<section className="max-w-container-max mx-auto px-gutter-desktop mb-space-4xl">
|
|
<div className="relative bg-surface-container-low rounded-2xl overflow-hidden shadow-2xl p-space-2xl border border-outline-variant/20">
|
|
<div className="absolute -right-16 -bottom-16 w-80 h-80 bg-primary-container/10 rounded-full blur-3xl pointer-events-none"></div>
|
|
<div className="relative z-10 flex flex-col lg:flex-row items-center justify-between gap-space-xl">
|
|
<div className="flex flex-col gap-space-xs max-w-xl">
|
|
<span className="font-label-caps text-label-caps text-secondary-fixed">
|
|
Hardware Compatibility
|
|
</span>
|
|
<h3 className="font-headline-lg text-headline-lg text-on-surface tracking-tight">
|
|
Sync directly with your helmet comms & bike dash
|
|
</h3>
|
|
<p className="font-body-md text-body-md text-on-surface-variant">
|
|
Integrates seamlessly with Cardo, Sena, Apple Watch, and OBD-II CAN bus links for live
|
|
peg-to-peg telemetry cues without taking your eyes off the corner exit.
|
|
</p>
|
|
</div>
|
|
<div className="flex flex-wrap items-center gap-space-md">
|
|
<div className="flex items-center gap-space-sm px-space-md py-3 rounded-xl bg-surface-container-high border border-outline-variant/20">
|
|
<span className="material-symbols-outlined text-secondary-fixed">headset_mic</span>
|
|
<span className="font-code-mono text-code-mono text-on-surface">Cardo / Sena Audio</span>
|
|
</div>
|
|
<div className="flex items-center gap-space-sm px-space-md py-3 rounded-xl bg-surface-container-high border border-outline-variant/20">
|
|
<span className="material-symbols-outlined text-primary-container">watch</span>
|
|
<span className="font-code-mono text-code-mono text-on-surface">Haptic Alerts</span>
|
|
</div>
|
|
<div className="flex items-center gap-space-sm px-space-md py-3 rounded-xl bg-surface-container-high border border-outline-variant/20">
|
|
<span className="material-symbols-outlined text-secondary-fixed-dim">sensors</span>
|
|
<span className="font-code-mono text-code-mono text-on-surface">CAN-Link Telemetry</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Sample Community Runs Preview */}
|
|
<section className="max-w-container-max mx-auto px-gutter-desktop mb-space-4xl">
|
|
<div className="flex flex-col md:flex-row md:items-end justify-between mb-space-xl gap-space-md">
|
|
<div>
|
|
<span className="font-label-caps text-label-caps text-primary-fixed-dim tracking-wide block mb-1">
|
|
Community Network Preview
|
|
</span>
|
|
<h2 className="font-headline-xl text-headline-xl text-on-surface tracking-tight">
|
|
Sample Pack Formations
|
|
</h2>
|
|
<p className="font-body-sm text-on-surface-variant mt-1">
|
|
Preview public squadron runs organized by regional riders across North America.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Filter Toggles */}
|
|
<div className="flex flex-wrap items-center gap-space-xs bg-surface-container-low p-1 rounded-xl border border-outline-variant/20">
|
|
<button
|
|
type="button"
|
|
onClick={() => setSelectedFilter('all')}
|
|
className={`px-space-md py-1.5 rounded-lg font-label-md text-label-md transition-all ${
|
|
selectedFilter === 'all'
|
|
? 'bg-surface-container-highest text-on-surface font-bold shadow-sm'
|
|
: 'text-on-surface-variant hover:text-on-surface'
|
|
}`}
|
|
>
|
|
All ({sampleRides.length})
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => setSelectedFilter('brisk')}
|
|
className={`px-space-md py-1.5 rounded-lg font-label-md text-label-md transition-all ${
|
|
selectedFilter === 'brisk'
|
|
? 'bg-surface-container-highest text-on-surface font-bold shadow-sm'
|
|
: 'text-on-surface-variant hover:text-on-surface'
|
|
}`}
|
|
>
|
|
Brisk Pace
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => setSelectedFilter('track')}
|
|
className={`px-space-md py-1.5 rounded-lg font-label-md text-label-md transition-all ${
|
|
selectedFilter === 'track'
|
|
? 'bg-surface-container-highest text-on-surface font-bold shadow-sm'
|
|
: 'text-on-surface-variant hover:text-on-surface'
|
|
}`}
|
|
>
|
|
Track Pace
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => setSelectedFilter('tour')}
|
|
className={`px-space-md py-1.5 rounded-lg font-label-md text-label-md transition-all ${
|
|
selectedFilter === 'tour'
|
|
? 'bg-surface-container-highest text-on-surface font-bold shadow-sm'
|
|
: 'text-on-surface-variant hover:text-on-surface'
|
|
}`}
|
|
>
|
|
Tours
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Showcase Cards Grid */}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-space-lg">
|
|
{filteredRides.map((ride) => (
|
|
<div
|
|
key={ride.id}
|
|
className="bg-surface-container-low rounded-2xl border border-outline-variant/30 overflow-hidden shadow-md hover:shadow-xl transition-all flex flex-col justify-between"
|
|
>
|
|
<div className="p-space-lg">
|
|
{/* Header Badges */}
|
|
<div className="flex items-center justify-between gap-2 mb-space-sm">
|
|
<span className="font-mono text-[10px] uppercase px-2 py-0.5 rounded bg-surface-container-high text-primary-container border border-outline-variant/30 font-semibold">
|
|
{ride.paceClassification}
|
|
</span>
|
|
<span className="font-mono text-xs text-on-surface-variant flex items-center gap-1">
|
|
<span className="material-symbols-outlined text-[14px]">calendar_today</span>
|
|
{ride.scheduledDate} • {ride.scheduledTime}
|
|
</span>
|
|
</div>
|
|
|
|
<h3 className="font-headline-md text-lg text-on-surface font-bold mb-1">
|
|
{ride.title}
|
|
</h3>
|
|
<p className="font-body-sm text-xs text-on-surface-variant line-clamp-2 mb-3">
|
|
{ride.description}
|
|
</p>
|
|
|
|
<div className="text-xs font-mono text-on-surface-variant space-y-1 mb-3">
|
|
<div className="flex items-center gap-1.5 truncate">
|
|
<span className="material-symbols-outlined text-[14px] text-secondary-fixed">
|
|
location_on
|
|
</span>
|
|
<span className="truncate">{ride.region}</span>
|
|
</div>
|
|
<div className="flex items-center gap-1.5 truncate">
|
|
<span className="material-symbols-outlined text-[14px] text-primary-container">
|
|
flag
|
|
</span>
|
|
<span className="truncate">Rally: {ride.meetingPoint}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between pt-2 border-t border-outline-variant/20 text-xs font-mono text-on-surface-variant">
|
|
<span>Lead: {ride.leadHandle}</span>
|
|
<span className="text-secondary-fixed">
|
|
{ride.participantCount} / {ride.participantLimit} Riders
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="p-space-lg pt-0">
|
|
{isLoggedIn ? (
|
|
<Link
|
|
href="/group-rides?view=manage"
|
|
className="w-full py-2.5 rounded-xl bg-surface-container-high hover:bg-primary-container hover:text-on-primary-container text-on-surface font-headline-sm text-xs font-bold transition flex items-center justify-center gap-1.5"
|
|
>
|
|
<span className="material-symbols-outlined text-[16px]">add_circle</span>
|
|
<span>View in Management Console</span>
|
|
</Link>
|
|
) : (
|
|
<Link
|
|
href="/login?redirect=/group-rides"
|
|
className="w-full py-2.5 rounded-xl bg-surface-container-high hover:bg-primary-container hover:text-on-primary-container text-on-surface font-headline-sm text-xs font-bold transition flex items-center justify-center gap-1.5"
|
|
>
|
|
<span className="material-symbols-outlined text-[16px]">lock</span>
|
|
<span>Sign In to Join Pack</span>
|
|
</Link>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
{/* Bottom Conversion Section */}
|
|
<section className="max-w-container-max mx-auto px-gutter-desktop mb-space-4xl">
|
|
<div className="relative rounded-3xl bg-gradient-to-r from-surface-container-low via-surface-container to-surface-container-high border border-outline-variant/30 p-8 sm:p-12 text-center overflow-hidden shadow-2xl">
|
|
<div className="absolute top-0 right-1/4 w-72 h-72 bg-primary-container/10 rounded-full blur-3xl pointer-events-none"></div>
|
|
<div className="relative z-10 max-w-2xl mx-auto space-y-4">
|
|
<span className="font-label-caps text-label-caps text-secondary-fixed">
|
|
Ready to Lead Formation?
|
|
</span>
|
|
<h2 className="font-display-hero text-2xl sm:text-3xl font-extrabold text-on-surface tracking-tight">
|
|
Organize, coordinate, and debrief group rides with precision telemetry.
|
|
</h2>
|
|
<p className="font-body-md text-sm sm:text-base text-on-surface-variant">
|
|
Join thousands of sport riders and touring groups who keep their squad in formation with
|
|
MotorSignal. Create your account in under 60 seconds.
|
|
</p>
|
|
<div className="flex flex-wrap items-center justify-center gap-4 pt-2">
|
|
<Link
|
|
href="/register"
|
|
className="px-6 py-3 rounded-xl bg-gradient-to-r from-primary-container to-primary-fixed text-on-primary-container font-headline-sm text-sm font-bold shadow-lg hover:shadow-[0_0_24px_rgba(0,242,254,0.45)] transition"
|
|
>
|
|
Create Free Account
|
|
</Link>
|
|
<Link
|
|
href="/login?redirect=/group-rides"
|
|
className="px-6 py-3 rounded-xl bg-surface-container-highest hover:bg-surface-container-lowest text-on-surface font-headline-sm text-sm font-semibold border border-outline-variant/40 transition"
|
|
>
|
|
Sign In
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|