import { useState, useEffect, useCallback } from 'react'; import { eq, desc, and, inArray } from 'drizzle-orm'; import { useDatabase } from './useDatabase'; import { rides } from '../db/schema'; // ─── Types ───────────────────────────────────────────────────────────────────── type RideStatus = 'searching' | 'matched' | 'in_progress' | 'completed' | 'cancelled'; interface RideData { id: string; userId: string; originAddress: string; originLatitude: number; originLongitude: number; destinationAddress: string; destinationLatitude: number; destinationLongitude: number; routePolyline: string | null; scheduledTime: string | null; status: RideStatus; seatPrice: number | null; totalDistance: number | null; estimatedDuration: number | null; createdAt: string | null; updatedAt: string | null; } interface NewRide { id: string; userId: string; originAddress: string; originLatitude: number; originLongitude: number; destinationAddress: string; destinationLatitude: number; destinationLongitude: number; routePolyline?: string; scheduledTime?: string; seatPrice?: number; totalDistance?: number; estimatedDuration?: number; } interface UseRidesReturn { rides: RideData[]; activeRide: RideData | null; loading: boolean; createRide: (data: NewRide) => Promise; updateRideStatus: (rideId: string, status: RideStatus) => Promise; getRideById: (rideId: string) => Promise; refresh: () => Promise; } // ─── Hook ────────────────────────────────────────────────────────────────────── export function useRides(statusFilter?: RideStatus[]): UseRidesReturn { const { db } = useDatabase(); const [ridesList, setRidesList] = useState([]); const [loading, setLoading] = useState(true); // ── Load rides ─────────────────────────────────────────────────────────────── const loadRides = useCallback(async () => { try { setLoading(true); const activeStatuses: RideStatus[] = ['searching', 'matched', 'in_progress']; // Always load active rides const allRides = await db .select() .from(rides) .orderBy(desc(rides.createdAt)) .all(); let filtered: typeof allRides = allRides; if (statusFilter && statusFilter.length > 0) { filtered = allRides.filter((r) => statusFilter.includes(r.status as RideStatus)); } setRidesList(filtered as RideData[]); } catch (error) { console.error('[useRides] Failed to load rides:', error); setRidesList([]); } finally { setLoading(false); } }, [db, statusFilter]); useEffect(() => { loadRides(); }, [loadRides]); // ── Active ride (first non-completed, non-cancelled) ───────────────────────── const activeRide = ridesList.find( (r) => r.status === 'searching' || r.status === 'matched' || r.status === 'in_progress', ) ?? null; // ── Create ride ────────────────────────────────────────────────────────────── const createRide = useCallback( async (data: NewRide): Promise => { try { await db.insert(rides).values({ id: data.id, userId: data.userId, originAddress: data.originAddress, originLatitude: data.originLatitude, originLongitude: data.originLongitude, destinationAddress: data.destinationAddress, destinationLatitude: data.destinationLatitude, destinationLongitude: data.destinationLongitude, routePolyline: data.routePolyline ?? null, scheduledTime: data.scheduledTime ?? null, seatPrice: data.seatPrice ?? null, totalDistance: data.totalDistance ?? null, estimatedDuration: data.estimatedDuration ?? null, }).run(); await loadRides(); const created = ridesList.find((r) => r.id === data.id); return (created as RideData) ?? null; } catch (error) { console.error('[useRides] Failed to create ride:', error); return null; } }, [db, loadRides, ridesList], ); // ── Update ride status ─────────────────────────────────────────────────────── const updateRideStatus = useCallback( async (rideId: string, status: RideStatus) => { try { await db .update(rides) .set({ status, updatedAt: new Date().toISOString() }) .where(eq(rides.id, rideId)) .run(); await loadRides(); } catch (error) { console.error('[useRides] Failed to update ride status:', error); } }, [db, loadRides], ); // ── Get ride by ID ─────────────────────────────────────────────────────────── const getRideById = useCallback( async (rideId: string): Promise => { try { const results = await db .select() .from(rides) .where(eq(rides.id, rideId)) .all(); return (results[0] as RideData) ?? null; } catch (error) { console.error('[useRides] Failed to get ride:', error); return null; } }, [db], ); return { rides: ridesList, activeRide, loading, createRide, updateRideStatus, getRideById, refresh: loadRides, }; }