'use client';
import React from 'react';
import Link from 'next/link';
import { useParams, useSearchParams } from 'next/navigation';
import { ClubUpcomingRide, UserPortalPermissions } from './types';
import { EmptyState } from './empty-state';
interface UpcomingRidesSectionProps {
rides: ClubUpcomingRide[];
permissions: UserPortalPermissions;
clubId?: string;
onPlanRide?: () => void;
onManageRide?: (rideId: string) => void;
onViewRoster?: (rideId: string) => void;
onViewRoute?: (routeId?: string) => void;
}
export function ClubRideCard({
ride,
permissions,
clubId,
onManageRide,
onViewRoster,
onViewRoute,
}: {
ride: ClubUpcomingRide;
permissions: UserPortalPermissions;
clubId?: string;
onManageRide?: (rideId: string) => void;
onViewRoster?: (rideId: string) => void;
onViewRoute?: (routeId?: string) => void;
}) {
const params = useParams();
const targetClubId = clubId || (typeof params?.clubId === 'string' ? params.clubId : '');
const capacityPercent = ride.capacity ? Math.min(100, Math.round((ride.confirmedCount / ride.capacity) * 100)) : 75;
return (
{/* Top Metadata Row */}
{ride.scheduledStartAt}
•
Ride ID: {ride.rideIdentifier}
{ride.title}
{ride.paceClassification}
{/* Attributes Row */}
Straight-line distance
{ride.distanceMiles ? `${ride.distanceMiles} mi` : '--'}
Duration
{ride.durationString ?? '--'}
Pace Classification
{ride.paceClassification}
{/* Roster & Road Captain Details */}
Riders: {ride.confirmedCount} going
{ride.pendingCount > 0 ? (
{ride.pendingCount} requests pending
) : ride.capacity ? (
{Math.max(0, ride.capacity - ride.confirmedCount)} open spots
) : null}
0 ? 'bg-amber-400' : 'bg-brand-cyan'
}`}
style={{ width: `${capacityPercent}%` }}
/>
Road Captain:
{ride.roadCaptainName}
{ride.roadCaptainMotorcycle && (
({ride.roadCaptainMotorcycle})
)}
{ride.sweepStatus === 'needs_assignment' ? (
Sweep: Needs Assignment
) : ride.briefingTime ? (
Briefing: {ride.briefingTime}
) : null}
{/* Section 15: Verbatim Live Location Privacy Policy Notice */}
info
Live location is shared only with eligible ride participants while sharing is enabled. Club membership alone never grants access to rider location.
{/* Actions: Disabled until backend club-ride management ships */}
{permissions.canPlanRides ? (
Manage Ride
) : (
View Ride
)}
View Roster ({ride.confirmedCount})
map
View Route
);
}
export function UpcomingRidesSection({
rides,
permissions,
clubId,
onPlanRide,
onManageRide,
onViewRoster,
onViewRoute,
}: UpcomingRidesSectionProps) {
const params = useParams();
const searchParams = useSearchParams();
const isDemo = searchParams?.get('preview') === 'demo';
const queryParam = isDemo ? '?preview=demo' : '';
const targetClubId = clubId || (typeof params?.clubId === 'string' ? params.clubId : '');
return (
Upcoming Club Rides
Scheduled Club Rides, routes, participants, and ride assignments.
{rides.length > 0 && (
Full Ride Schedule
arrow_forward
)}
{rides.length === 0 ? (
) : (
{rides.map((ride) => (
))}
)}
);
}