Files
time_to_leave/apps/mobile/src/components/BikeSection.tsx
T
fegger 44aaa32296 Add edit icon button to event list item
Remove emoji icons from journey display and replace with FontAwesome icons
Add FontAwesome icon imports and styles for new icon usage
Update calendar service to use FontAwesome icons instead of emojis
Remove redundant emoji field from CalendarSourceInfo type
Adjust journey scoring weights to prioritize fewer changes
Remove emoji icons and simplify event metadata display
2026-05-19 00:06:53 +02:00

85 lines
3.5 KiB
TypeScript

import { ActivityIndicator, StyleSheet, Text, View } from 'react-native';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
import { faClock, faRuler, faMap } from '@fortawesome/free-solid-svg-icons';
import { formatDuration, formatDistance } from '@timetoleave/core';
import type { BikeRoute, Station } from '@timetoleave/core';
import type { AppColors } from '../hooks/useColors';
/** Props for the bike route information section shown on event detail. */
interface Props {
bikeRoute: BikeRoute | null;
loading: boolean;
origin: Station | null;
colors: AppColors;
}
/**
* Displays cycling route duration, distance, and a map placeholder for the
* event's origin → destination leg. Shows contextual empty states when no
* origin is set or no route is available.
*/
export function BikeSection({ bikeRoute, loading, origin, colors }: Props) {
return (
<View style={[styles.container, { backgroundColor: colors.background }]}>
<Text style={[styles.sectionTitle, { color: colors.text }]}>Bike route</Text>
{loading ? (
<View style={styles.centered}>
<ActivityIndicator size="small" color={colors.accent} />
<Text style={[styles.hint, { color: colors.subtext }]}>Loading bike route</Text>
</View>
) : bikeRoute ? (
<View style={[styles.card, { backgroundColor: colors.card, borderColor: colors.border }]}>
<View style={styles.row}>
<View style={styles.labelRow}>
<FontAwesomeIcon icon={faClock} size={13} color={colors.text} />
<Text style={[styles.label, { color: colors.text }]}>Dauer</Text>
</View>
<Text style={[styles.value, { color: colors.accent }]}>{formatDuration(bikeRoute.duration)}</Text>
</View>
<View style={styles.row}>
<View style={styles.labelRow}>
<FontAwesomeIcon icon={faRuler} size={13} color={colors.text} />
<Text style={[styles.label, { color: colors.text }]}>Distanz</Text>
</View>
<Text style={[styles.value, { color: colors.accent }]}>{formatDistance(bikeRoute.distance)}</Text>
</View>
<View style={[styles.mapPlaceholder, { backgroundColor: colors.background, borderColor: colors.border }]}>
<View style={styles.mapTextRow}>
<FontAwesomeIcon icon={faMap} size={13} color={colors.subtext} />
<Text style={[styles.mapText, { color: colors.subtext }]}>Map (post-MVP)</Text>
</View>
</View>
</View>
) : (
<Text style={[styles.empty, { color: colors.subtext }]}>
{origin ? 'No bike route available' : 'Set origin station'}
</Text>
)}
</View>
);
}
const styles = StyleSheet.create({
container: { padding: 20 },
sectionTitle: { fontSize: 18, fontWeight: '600', marginBottom: 12 },
centered: { alignItems: 'center', gap: 8 },
hint: { fontSize: 15, marginTop: 12 },
empty: { fontSize: 14 },
card: { borderRadius: 10, padding: 14, borderWidth: 1 },
row: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 6 },
labelRow: { flexDirection: 'row', alignItems: 'center', gap: 6 },
label: { fontSize: 15, fontWeight: '500' },
value: { fontSize: 15, fontWeight: '600' },
mapTextRow: { flexDirection: 'row', alignItems: 'center', gap: 6 },
mapPlaceholder: {
marginTop: 10,
height: 100,
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
},
mapText: { fontSize: 14 },
});