frontend: global km/mi distance-unit toggle across dashboard, activities, routes, records
This commit is contained in:
@@ -4,9 +4,10 @@ import { useQuery } from '@tanstack/react-query'
|
||||
import { format } from 'date-fns'
|
||||
import api from '../utils/api'
|
||||
import {
|
||||
formatDuration, formatDistance, formatPace, formatHeartRate,
|
||||
formatDate, sportIcon, sportColor,
|
||||
formatDuration, formatDistance, formatPace, formatHeartRate, formatElevation,
|
||||
formatDate, sportIcon, sportColor, convertKm, distanceUnitLabel,
|
||||
} from '../utils/format'
|
||||
import { useUnit } from '../hooks/useUnits'
|
||||
|
||||
const SPORTS = ['all', 'running', 'cycling', 'hiking', 'walking']
|
||||
|
||||
@@ -15,6 +16,8 @@ export default function ActivitiesPage() {
|
||||
const navigate = useNavigate()
|
||||
const [sport, setSport] = useState('all')
|
||||
const [page, setPage] = useState(1)
|
||||
const unit = useUnit()
|
||||
const distLabel = distanceUnitLabel(unit)
|
||||
|
||||
const fromParam = searchParams.get('from')
|
||||
const toParam = searchParams.get('to')
|
||||
@@ -56,10 +59,10 @@ export default function ActivitiesPage() {
|
||||
{ytdStats && (
|
||||
<div className="flex flex-wrap gap-x-4 gap-y-1 mb-4 text-sm">
|
||||
{ytdStats.running_km > 0 && (
|
||||
<span className="text-blue-400">🏃 {ytdStats.running_km.toFixed(0)} km this year</span>
|
||||
<span className="text-blue-400">🏃 {convertKm(ytdStats.running_km, unit).toFixed(0)} {distLabel} this year</span>
|
||||
)}
|
||||
{ytdStats.cycling_km > 0 && (
|
||||
<span className="text-orange-400">🚴 {ytdStats.cycling_km.toFixed(0)} km this year</span>
|
||||
<span className="text-orange-400">🚴 {convertKm(ytdStats.cycling_km, unit).toFixed(0)} {distLabel} this year</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
@@ -118,14 +121,14 @@ export default function ActivitiesPage() {
|
||||
<p className="text-xs text-gray-500 mt-0.5">{formatDate(activity.start_time)}</p>
|
||||
{/* Compact metrics line — the full metrics column is hidden below sm */}
|
||||
<p className="sm:hidden text-xs text-gray-400 mt-0.5 truncate">
|
||||
{formatDistance(activity.distance_m)} · {formatDuration(activity.duration_s)} · {formatPace(activity.avg_speed_ms, activity.sport_type)}
|
||||
{formatDistance(activity.distance_m, unit)} · {formatDuration(activity.duration_s)} · {formatPace(activity.avg_speed_ms, activity.sport_type, unit)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Metrics */}
|
||||
<div className="hidden sm:flex items-center gap-6 text-sm">
|
||||
<div className="text-right">
|
||||
<p className="text-gray-200 font-medium">{formatDistance(activity.distance_m)}</p>
|
||||
<p className="text-gray-200 font-medium">{formatDistance(activity.distance_m, unit)}</p>
|
||||
<p className="text-xs text-gray-600">distance</p>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
@@ -133,7 +136,7 @@ export default function ActivitiesPage() {
|
||||
<p className="text-xs text-gray-600">time</p>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="text-gray-200 font-medium">{formatPace(activity.avg_speed_ms, activity.sport_type)}</p>
|
||||
<p className="text-gray-200 font-medium">{formatPace(activity.avg_speed_ms, activity.sport_type, unit)}</p>
|
||||
<p className="text-xs text-gray-600">pace</p>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
@@ -142,7 +145,7 @@ export default function ActivitiesPage() {
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="text-gray-200 font-medium">
|
||||
{activity.elevation_gain_m ? `↑ ${Math.round(activity.elevation_gain_m)}m` : '--'}
|
||||
{activity.elevation_gain_m ? `↑ ${formatElevation(activity.elevation_gain_m, unit)}` : '--'}
|
||||
</p>
|
||||
<p className="text-xs text-gray-600">elev</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user