import { Plus, Trash2 } from "lucide-react"; import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { Card } from "@/components/ui/card"; import { useUnitPreferences } from "@/hooks/useUnitPreferences"; import { toast } from "sonner"; import { convertValueToMetric, convertValueFromMetric, detectUnitType, getMetricUnit, getDisplayUnit } from "@/lib/units"; import { validateMetricUnit } from "@/lib/unitValidation"; import { getErrorMessage } from "@/lib/errorHandler"; interface CoasterStat { stat_name: string; stat_value: number; unit?: string; category?: string; description?: string; display_order: number; } interface CoasterStatsEditorProps { stats: CoasterStat[]; onChange: (stats: CoasterStat[]) => void; categories?: string[]; } const DEFAULT_CATEGORIES = ['Speed', 'Height', 'Length', 'Forces', 'Capacity', 'Duration', 'Other']; const COMMON_STATS = [ { name: 'Max Speed', unit: 'km/h', category: 'Speed' }, { name: 'Max Height', unit: 'm', category: 'Height' }, { name: 'Drop Height', unit: 'm', category: 'Height' }, { name: 'Track Length', unit: 'm', category: 'Length' }, { name: 'Max G-Force', unit: 'G', category: 'Forces' }, { name: 'Max Negative G-Force', unit: 'G', category: 'Forces' }, { name: 'Ride Duration', unit: 'seconds', category: 'Duration' }, { name: 'Inversions', unit: 'count', category: 'Other' }, ]; export function CoasterStatsEditor({ stats, onChange, categories = DEFAULT_CATEGORIES }: CoasterStatsEditorProps) { const { preferences } = useUnitPreferences(); const [unitErrors, setUnitErrors] = useState>({}); const addStat = () => { onChange([ ...stats, { stat_name: '', stat_value: 0, unit: '', category: categories[0], description: '', display_order: stats.length } ]); }; const addCommonStat = (commonStat: typeof COMMON_STATS[0]) => { onChange([ ...stats, { stat_name: commonStat.name, stat_value: 0, unit: commonStat.unit, category: commonStat.category, description: '', display_order: stats.length } ]); }; const removeStat = (index: number) => { const newStats = stats.filter((_, i) => i !== index); onChange(newStats.map((stat, i) => ({ ...stat, display_order: i }))); }; const updateStat = (index: number, field: keyof CoasterStat, value: string | number | boolean | null | undefined) => { const newStats = [...stats]; // Ensure unit is metric when updating unit field if (field === 'unit' && value && typeof value === 'string') { try { validateMetricUnit(value, 'Unit'); newStats[index] = { ...newStats[index], unit: value }; // Clear error for this index setUnitErrors(prev => { const updated = { ...prev }; delete updated[index]; return updated; }); } catch (error: unknown) { const message = getErrorMessage(error); toast.error(message); // Store error for visual feedback setUnitErrors(prev => ({ ...prev, [index]: message })); return; } } else { newStats[index] = { ...newStats[index], [field]: value }; } onChange(newStats); }; // Get display value (convert from metric to user's preferred units) const getDisplayValue = (stat: CoasterStat): string => { if (!stat.stat_value || !stat.unit) return String(stat.stat_value || ''); const numValue = Number(stat.stat_value); if (isNaN(numValue)) return String(stat.stat_value); const unitType = detectUnitType(stat.unit); if (unitType === 'unknown') return String(stat.stat_value); // stat.unit is the metric unit (e.g., "km/h") // Get the display unit based on user preference (e.g., "mph" for imperial) const displayUnit = getDisplayUnit(stat.unit, preferences.measurement_system); // Convert from metric to display unit const displayValue = convertValueFromMetric(numValue, displayUnit, stat.unit); return String(displayValue); }; return (
{stats.length === 0 ? ( No statistics added yet. Add a common stat or create a custom one. ) : (
{stats.map((stat, index) => (
updateStat(index, 'stat_name', e.target.value)} placeholder="e.g., Max Speed" />
{ const inputValue = e.target.value; const numValue = parseFloat(inputValue); if (!isNaN(numValue) && stat.unit) { // Determine what unit the user is entering (based on their preference) const displayUnit = getDisplayUnit(stat.unit, preferences.measurement_system); // Convert from user's input unit to metric for storage const metricValue = convertValueToMetric(numValue, displayUnit); updateStat(index, 'stat_value', metricValue); } else { updateStat(index, 'stat_value', numValue || 0); } }} placeholder="0" /> {stat.unit && detectUnitType(stat.unit) !== 'unknown' && (

Enter in {getDisplayUnit(stat.unit, preferences.measurement_system)}

)}
updateStat(index, 'unit', e.target.value)} placeholder="km/h, m, G..." className={unitErrors[index] ? 'border-destructive' : ''} /> {unitErrors[index] && (

{unitErrors[index]}

)}

⚠️ Use metric units only: km/h, m, cm, kg, G, celsius