'use client'; import { collection, getDocs, addDoc, deleteDoc, doc, updateDoc, writeBatch, } from 'firebase/firestore'; import { onAuthStateChanged, User } from 'firebase/auth'; import Link from 'next/link'; import React, { useEffect, useState, useRef } from 'react'; import { firebaseAuth, firestore } from '../lib/firebase-client'; import { WebTelemetryReplayModal } from './web-telemetry-replay-modal'; import { generateRideGpx, generateRideCsv, downloadFile, resolveRideTelemetryPoints, TelemetryPoint, } from '../lib/telemetry-export'; export type Motorcycle = { id: string; nickname: string; makeName: string; modelName: string; variantName: string; year: number; description: string; isDefault: boolean; imageUrl?: string; vin?: string; }; export type Ride = { id: string; startedAt: Date | null; endedAt: Date | null; distanceMiles: number; topSpeedMph: number; averageSpeed: number; maxLeanLeft: number; maxLeanRight: number; maxAccelG: number; maxBrakingG: number; movingTime: number; // in seconds elevationGain: number; qualityScore: number; motorcycle: string; startLat?: number; startLon?: number; endLat?: number; endLon?: number; points?: TelemetryPoint[]; gpxContent?: string; csvContent?: string; telemetryBundlePath?: string; }; function text(value: unknown): string { return typeof value === 'string' ? value.trim() : ''; } function number(value: unknown): number { return typeof value === 'number' && Number.isFinite(value) ? value : 0; } function formatDuration(seconds: number): string { if (!seconds || seconds <= 0) return '0m'; const mins = Math.floor(seconds / 60); const hrs = Math.floor(mins / 60); const remainingMins = mins % 60; if (hrs > 0) { return `${hrs}h ${remainingMins}m`; } return `${mins}m`; } // Sleek high-tech stock sportbike vector illustration function StockMotorcycleGraphic({ className = 'w-full h-40' }: { className?: string }) { return (
Synced bikes, ECU links, and motorcycle profiles
VIN: {bike.vin}
)}Add your bike to bind CAN-bus telemetry, IMU orientation, and lean angles.
High-fidelity 20Hz GNSS, lean angles, and speed telemetry logs
Record a ride using the MotorSignal mobile app. Rides are automatically uploaded to Cloudflare R2 and Firestore upon completion.
Register a bike in your cloud garage