mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-24 04:51:13 -05:00
Add unit preferences to user settings
This commit is contained in:
@@ -11,8 +11,9 @@ import { Separator } from '@/components/ui/separator';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import { useUnitPreferences } from '@/hooks/useUnitPreferences';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import { MapPin, Calendar, Globe, Accessibility } from 'lucide-react';
|
||||
import { MapPin, Calendar, Globe, Accessibility, Ruler } from 'lucide-react';
|
||||
const locationSchema = z.object({
|
||||
preferred_pronouns: z.string().max(20).optional(),
|
||||
timezone: z.string(),
|
||||
@@ -35,6 +36,7 @@ export function LocationTab() {
|
||||
const {
|
||||
toast
|
||||
} = useToast();
|
||||
const { preferences: unitPreferences, updatePreferences: updateUnitPreferences } = useUnitPreferences();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [parks, setParks] = useState<any[]>([]);
|
||||
const [accessibility, setAccessibility] = useState<AccessibilityOptions>({
|
||||
@@ -115,10 +117,13 @@ export function LocationTab() {
|
||||
|
||||
if (accessibilityError) throw accessibilityError;
|
||||
|
||||
// Save unit preferences
|
||||
await updateUnitPreferences(unitPreferences);
|
||||
|
||||
await refreshProfile();
|
||||
toast({
|
||||
title: 'Settings saved',
|
||||
description: 'Your location, personal information, and accessibility settings have been updated.'
|
||||
description: 'Your location, personal information, accessibility, and unit preferences have been updated.'
|
||||
});
|
||||
} catch (error: any) {
|
||||
toast({
|
||||
@@ -243,6 +248,58 @@ export function LocationTab() {
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Unit Preferences */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Ruler className="w-5 h-5" />
|
||||
<h3 className="text-lg font-medium">Units & Measurements</h3>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardDescription>
|
||||
Choose your preferred measurement system for displaying distances, speeds, and other measurements.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
<div className="space-y-3">
|
||||
<Label>Measurement System</Label>
|
||||
<Select
|
||||
value={unitPreferences.measurement_system}
|
||||
onValueChange={(value: 'metric' | 'imperial') =>
|
||||
updateUnitPreferences({ measurement_system: value })
|
||||
}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="metric">Metric (km/h, meters, cm)</SelectItem>
|
||||
<SelectItem value="imperial">Imperial (mph, feet, inches)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-1">
|
||||
<Label>Auto-detect from location</Label>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Automatically set measurement system based on your location when you first visit
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
checked={unitPreferences.auto_detect}
|
||||
onCheckedChange={(checked) =>
|
||||
updateUnitPreferences({ auto_detect: checked })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
{/* Accessibility Options */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
100
src/components/ui/measurement-display.tsx
Normal file
100
src/components/ui/measurement-display.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
import {
|
||||
convertSpeed,
|
||||
convertDistance,
|
||||
convertHeight,
|
||||
getSpeedUnit,
|
||||
getDistanceUnit,
|
||||
getHeightUnit,
|
||||
getShortDistanceUnit,
|
||||
type MeasurementSystem,
|
||||
type UnitPreferences
|
||||
} from '@/lib/units';
|
||||
|
||||
interface MeasurementDisplayProps {
|
||||
value: number;
|
||||
type: 'speed' | 'distance' | 'height' | 'short_distance';
|
||||
showBothUnits?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function MeasurementDisplay({
|
||||
value,
|
||||
type,
|
||||
showBothUnits = false,
|
||||
className = ""
|
||||
}: MeasurementDisplayProps) {
|
||||
const { profile } = useAuth();
|
||||
|
||||
const unitPreferences = useMemo(() => {
|
||||
// Get unit preferences from user profile or default to metric
|
||||
const defaultPrefs: UnitPreferences = {
|
||||
measurement_system: 'metric',
|
||||
temperature: 'celsius',
|
||||
auto_detect: true
|
||||
};
|
||||
|
||||
// If no profile or no preferences, use default
|
||||
if (!profile) return defaultPrefs;
|
||||
|
||||
// Try to get preferences from profile (this will be populated from user_preferences)
|
||||
const storedPrefs = (profile as any)?.unit_preferences;
|
||||
if (storedPrefs && typeof storedPrefs === 'object') {
|
||||
return { ...defaultPrefs, ...storedPrefs };
|
||||
}
|
||||
|
||||
return defaultPrefs;
|
||||
}, [profile]);
|
||||
|
||||
const { displayValue, unit, alternateDisplay } = useMemo(() => {
|
||||
const system = unitPreferences.measurement_system;
|
||||
|
||||
let displayValue: number;
|
||||
let unit: string;
|
||||
let alternateValue: number;
|
||||
let alternateUnit: string;
|
||||
|
||||
switch (type) {
|
||||
case 'speed':
|
||||
displayValue = convertSpeed(value, system);
|
||||
unit = getSpeedUnit(system);
|
||||
alternateValue = convertSpeed(value, system === 'metric' ? 'imperial' : 'metric');
|
||||
alternateUnit = getSpeedUnit(system === 'metric' ? 'imperial' : 'metric');
|
||||
break;
|
||||
case 'distance':
|
||||
displayValue = convertDistance(value, system);
|
||||
unit = getDistanceUnit(system);
|
||||
alternateValue = convertDistance(value, system === 'metric' ? 'imperial' : 'metric');
|
||||
alternateUnit = getDistanceUnit(system === 'metric' ? 'imperial' : 'metric');
|
||||
break;
|
||||
case 'height':
|
||||
displayValue = convertHeight(value, system);
|
||||
unit = getHeightUnit(system);
|
||||
alternateValue = convertHeight(value, system === 'metric' ? 'imperial' : 'metric');
|
||||
alternateUnit = getHeightUnit(system === 'metric' ? 'imperial' : 'metric');
|
||||
break;
|
||||
case 'short_distance':
|
||||
displayValue = convertDistance(value, system);
|
||||
unit = getShortDistanceUnit(system);
|
||||
alternateValue = convertDistance(value, system === 'metric' ? 'imperial' : 'metric');
|
||||
alternateUnit = getShortDistanceUnit(system === 'metric' ? 'imperial' : 'metric');
|
||||
break;
|
||||
default:
|
||||
displayValue = value;
|
||||
unit = '';
|
||||
alternateValue = value;
|
||||
alternateUnit = '';
|
||||
}
|
||||
|
||||
const alternateDisplay = showBothUnits ? ` (${alternateValue} ${alternateUnit})` : '';
|
||||
|
||||
return { displayValue, unit, alternateDisplay };
|
||||
}, [value, type, unitPreferences.measurement_system, showBothUnits]);
|
||||
|
||||
return (
|
||||
<span className={className} title={showBothUnits ? undefined : alternateDisplay ? `${alternateValue} ${alternateUnit}` : undefined}>
|
||||
{displayValue} {unit}{alternateDisplay}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user