diff --git a/apps/mobile/src/__tests__/screens.test.tsx b/apps/mobile/src/__tests__/screens.test.tsx index f8dcdc3..9a8f923 100644 --- a/apps/mobile/src/__tests__/screens.test.tsx +++ b/apps/mobile/src/__tests__/screens.test.tsx @@ -197,7 +197,7 @@ describe('EventListScreen', () => { expect(getByText('Test Destination')).toBeTruthy(); }); await waitFor(() => { - expect(getByText('Losgehen')).toBeTruthy(); + expect(getByText('Losgehen in')).toBeTruthy(); expect(getByText('S1 -> Wien')).toBeTruthy(); expect(getByText('Inkl. Fußweg zur Station: 10 min')).toBeTruthy(); }); diff --git a/apps/mobile/src/components/EventHeader.tsx b/apps/mobile/src/components/EventHeader.tsx index 01cc925..7afc267 100644 --- a/apps/mobile/src/components/EventHeader.tsx +++ b/apps/mobile/src/components/EventHeader.tsx @@ -1,6 +1,4 @@ -import { useEffect, useState } from 'react'; import { StyleSheet, Text, View } from 'react-native'; -import { calculateCountdown } from '@timetoleave/core'; import type { Event } from '@timetoleave/core'; import type { AppColors } from '../hooks/useColors'; @@ -13,34 +11,20 @@ interface Props { } /** - * Renders the event title, destination, leave countdown, data source, and a + * Renders the event title, destination, leave-by time, data source, and a * three-column grid with leave-by time, arrive-by time, and buffer. */ export function EventHeader({ event, leaveByTime, arrivalBufferMinutes, colors }: Props) { - const [, setTick] = useState(0); const arriveByTime = new Date(event.eventTime.getTime() - arrivalBufferMinutes * 60_000); - const leaveCountdown = leaveByTime ? calculateCountdown(leaveByTime) : null; - - useEffect(() => { - const interval = setInterval(() => setTick((tick) => tick + 1), 30_000); - return () => clearInterval(interval); - }, []); return ( {event.title} {event.destination} - - {leaveCountdown - ? leaveCountdown.label === 'Now' - ? 'Jetzt losgehen' - : `Noch ${leaveCountdown.label} bis Losgehen` - : 'Countdown wird berechnet'} + + {leaveByTime + ? `Losgehen um ${leaveByTime.toLocaleTimeString('de-AT', { hour: '2-digit', minute: '2-digit' })}` + : 'Losgehzeit wird berechnet'} Quelle: {event.source} @@ -72,7 +56,7 @@ const styles = StyleSheet.create({ container: { padding: 20, marginBottom: 12 }, title: { fontSize: 22, fontWeight: '700' }, destination: { fontSize: 16, marginTop: 4 }, - countdown: { fontSize: 18, fontWeight: '700', marginTop: 10 }, + leaveTime: { fontSize: 18, fontWeight: '700', marginTop: 10 }, source: { fontSize: 12, marginTop: 4 }, infoGrid: { flexDirection: 'row', diff --git a/apps/mobile/src/screens/EventListScreen.tsx b/apps/mobile/src/screens/EventListScreen.tsx index 88ed91c..ca1ad56 100644 --- a/apps/mobile/src/screens/EventListScreen.tsx +++ b/apps/mobile/src/screens/EventListScreen.tsx @@ -28,9 +28,9 @@ type ScreenProps = { }; /** - * Home screen showing a scrollable list of upcoming events with countdown - * badges. Pull-to-refresh reloads events from storage. Reloads automatically - * when the screen gains focus (so edits on other screens are reflected). + * Home screen showing a scrollable list of upcoming events with leave-time + * countdowns. Pull-to-refresh reloads events from storage. Reloads + * automatically when the screen gains focus so edits are reflected. */ export function EventListScreen({ navigation }: ScreenProps) { const colors = useColors(); @@ -173,13 +173,18 @@ export function EventListScreen({ navigation }: ScreenProps) { ]); const renderItem = ({ item }: { item: CalendarEvent }) => { - const countdown = calculateCountdown(item.eventTime); const leaveBy = departureInfo.departureTime; + const leaveCountdown = leaveBy ? calculateCountdown(leaveBy) : null; + const leaveCountdownLabel = leaveCountdown?.label === 'Now' ? 'Jetzt' : leaveCountdown?.label; + const leaveByLabel = leaveBy ? formatTime(leaveBy) : null; const trainLabel = selectedJourney?.trains.length ? selectedJourney.trains.join(', ') : 'Zugverbindung wird gesucht'; - - // Derive a simple status — journeys aren't loaded on the list screen for MVP - // so we show countdown-based status instead - const status = countdown.urgent ? 'Bald!' : countdown.label; + const status = leaveCountdown + ? leaveCountdown.label === 'Now' + ? 'Jetzt losgehen' + : `Losgehen in ${leaveCountdown.label}` + : journeysLoading || destStation.loading + ? 'Losgehzeit wird berechnet' + : 'Keine Verbindung'; return ( @@ -190,16 +195,25 @@ export function EventListScreen({ navigation }: ScreenProps) { > - + {item.title} - - {countdown.label} + + {leaveByLabel ?? '--:--'} {item.destination} - Losgehen - - {leaveBy ? formatTime(leaveBy) : journeysLoading || destStation.loading ? '--:--' : 'Keine Verbindung'} + Losgehen in + + {leaveCountdownLabel + ? leaveCountdownLabel + : journeysLoading || destStation.loading + ? '--' + : 'Keine Verbindung'} @@ -233,7 +247,7 @@ export function EventListScreen({ navigation }: ScreenProps) { minute: '2-digit', })} - {status} + {status}