import { useLocalSearchParams, useRouter } from 'expo-router';
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { useActivity } from '@/db/queries';
export default function ActivityScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
const router = useRouter();
const row = useActivity(id);
if (!row) {
return (
Activity not found
);
}
const detail = JSON.parse(row.detail_json);
const km = detail.distance_m != null
? (detail.distance_m / 1000).toFixed(2)
: null;
const elev = detail.elevation_gain_m != null
? Math.round(detail.elevation_gain_m)
: null;
const elevLoss = detail.elevation_loss_m != null
? Math.round(Math.abs(detail.elevation_loss_m))
: null;
const movingTime = detail.moving_time_s != null
? formatDuration(detail.moving_time_s)
: null;
const speed = detail.avg_speed_kmh != null
? detail.avg_speed_kmh.toFixed(1)
: null;
const hr = detail.avg_hr_bpm != null
? Math.round(detail.avg_hr_bpm)
: null;
const power = detail.avg_power_w != null
? Math.round(detail.avg_power_w)
: null;
const date = new Date(detail.started_at).toLocaleDateString(undefined, {
weekday: 'long', day: 'numeric', month: 'long', year: 'numeric',
});
return (
router.back()}>
← Back
{detail.sport ?? 'Activity'}
{detail.title}
{date}
{/* Map placeholder — Phase 1 */}
Map · Phase 1
{/* Stats grid */}
{km && }
{movingTime && }
{elev != null && }
{elevLoss != null && }
{speed && }
{hr && }
{power && }
{/* Elevation chart placeholder — Phase 1 */}
{row.timeseries_json && (
Elevation chart · Phase 1
)}
);
}
function StatCell({ label, value, unit }: { label: string; value: string; unit: string }) {
return (
{value}
{unit ? {unit} : null}
{label}
);
}
function MetaRow({ label, value }: { label: string; value: string }) {
return (
{label}
{value}
);
}
function formatDuration(seconds: number): string {
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = seconds % 60;
if (h > 0) return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
return `${m}:${String(s).padStart(2, '0')}`;
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#09090b' },
content: { paddingBottom: 40 },
center: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: '#09090b' },
notFound: { color: '#71717a', fontSize: 16 },
backButton: { paddingHorizontal: 16, paddingTop: 60, paddingBottom: 12 },
backText: { color: '#60a5fa', fontSize: 15 },
sport: { color: '#71717a', fontSize: 12, fontWeight: '600', letterSpacing: 0.8, paddingHorizontal: 16, marginBottom: 4 },
title: { color: '#f4f4f5', fontSize: 22, fontWeight: '700', paddingHorizontal: 16, marginBottom: 4 },
date: { color: '#71717a', fontSize: 13, paddingHorizontal: 16, marginBottom: 16 },
mapPlaceholder: {
height: 200, backgroundColor: '#18181b',
alignItems: 'center', justifyContent: 'center',
borderTopWidth: 1, borderBottomWidth: 1, borderColor: '#27272a',
marginBottom: 16,
},
chartPlaceholder: {
height: 120, backgroundColor: '#18181b',
alignItems: 'center', justifyContent: 'center',
borderTopWidth: 1, borderBottomWidth: 1, borderColor: '#27272a',
marginBottom: 16,
},
mapPlaceholderText: { color: '#3f3f46', fontSize: 13 },
grid: {
flexDirection: 'row', flexWrap: 'wrap',
paddingHorizontal: 12, gap: 8, marginBottom: 16,
},
statCell: {
backgroundColor: '#18181b', borderRadius: 10,
borderWidth: 1, borderColor: '#27272a',
padding: 14, width: '47%',
},
statValueRow: { flexDirection: 'row', alignItems: 'baseline', gap: 4, marginBottom: 4 },
statValue: { color: '#f4f4f5', fontSize: 24, fontWeight: '700' },
statUnit: { color: '#71717a', fontSize: 13 },
statLabel: { color: '#71717a', fontSize: 12 },
meta: {
marginHorizontal: 16, backgroundColor: '#18181b',
borderRadius: 10, borderWidth: 1, borderColor: '#27272a',
},
metaRow: {
flexDirection: 'row', justifyContent: 'space-between',
paddingHorizontal: 14, paddingVertical: 10,
borderBottomWidth: 1, borderBottomColor: '#27272a',
},
metaLabel: { color: '#71717a', fontSize: 13 },
metaValue: { color: '#a1a1aa', fontSize: 13 },
});