Add Wiener Linien API integration and departures monitoring
This commit is contained in:
+57
-57
@@ -1,75 +1,75 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { Event, Station } from '@/types';
|
||||
import TrainSection from './TrainSection';
|
||||
import BikeSection from './BikeSection';
|
||||
import LeaveByBadge from './LeaveByBadge';
|
||||
import { calculateCountdown } from '@/lib/countdown-utils';
|
||||
import { useDestinationStation } from '@/hooks/useDestinationStation';
|
||||
import { useGeocode } from '@/hooks/useGeocode';
|
||||
import { useJourneys } from '@/hooks/useJourneys';
|
||||
import { useBikeRoute } from '@/hooks/useBikeRoute';
|
||||
import { useGeolocation } from '@/hooks/useGeolocation';
|
||||
import { format } from "date-fns";
|
||||
import { useJourneys } from "@/hooks/useJourneys";
|
||||
import { useBikeRoute } from "@/hooks/useBikeRoute";
|
||||
import { useGeocode } from "@/hooks/useGeocode";
|
||||
import { useClock } from "@/hooks/useClock";
|
||||
import { useWienerLinien } from "@/hooks/useWienerLinien";
|
||||
import type { Event, Station } from "@/types";
|
||||
import TrainSection from "./TrainSection";
|
||||
import BikeSection from "./BikeSection";
|
||||
import WienerLinienSection from "./WienerLinienSection";
|
||||
import CountdownBadge from "@/app/ui/CountdownBadge";
|
||||
|
||||
type EventCardProps = {
|
||||
interface EventCardProps {
|
||||
event: Event;
|
||||
originStation: Station | null;
|
||||
className?: string;
|
||||
};
|
||||
}
|
||||
|
||||
const EventCard: React.FC<EventCardProps> = ({ event, originStation, className = '' }) => {
|
||||
const [refreshKey, setRefreshKey] = useState(0);
|
||||
const handleRefresh = useCallback(() => setRefreshKey((k) => k + 1), []);
|
||||
export default function EventCard({ event, originStation }: EventCardProps) {
|
||||
const {
|
||||
journeys,
|
||||
loading: journeysLoading,
|
||||
error: journeysError,
|
||||
} = useJourneys(originStation?.extId ?? null, null, event.eventTime, 0);
|
||||
|
||||
const { location } = useGeolocation();
|
||||
const { station: destStation } = useDestinationStation(event.destination);
|
||||
const { coords: destCoords } = useGeocode(event.destination);
|
||||
const destCoords = useGeocode(event.destination);
|
||||
|
||||
const { journeys, loading, error } = useJourneys(
|
||||
originStation?.extId ?? null,
|
||||
destStation?.extId ?? null,
|
||||
event.eventTime,
|
||||
refreshKey,
|
||||
);
|
||||
const {
|
||||
bikeRoute,
|
||||
loading: bikeLoading,
|
||||
error: bikeError,
|
||||
} = useBikeRoute(originStation?.lat, originStation?.lng, destCoords.coords?.lat, destCoords.coords?.lng);
|
||||
|
||||
const { bikeRoute, loading: bikeLoading, error: bikeError } = useBikeRoute(
|
||||
location?.coords.latitude,
|
||||
location?.coords.longitude,
|
||||
destCoords?.lat,
|
||||
destCoords?.lng,
|
||||
);
|
||||
const {
|
||||
stops,
|
||||
departures,
|
||||
loading: wlLoading,
|
||||
error: wlError,
|
||||
} = useWienerLinien(destCoords.coords?.lat, destCoords.coords?.lng);
|
||||
|
||||
const { countdown, status } = useClock(event.eventTime);
|
||||
|
||||
return (
|
||||
<div className={`bg-white dark:bg-gray-800 rounded-lg shadow-sm overflow-hidden ${className}`}>
|
||||
<div className="p-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1">
|
||||
<h3 className="font-semibold text-gray-900 dark:text-white">{event.title}</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">{event.destination}</p>
|
||||
</div>
|
||||
<div className="ml-4 flex items-center">
|
||||
<LeaveByBadge countdown={calculateCountdown(event.eventTime)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">{event.title}</h3>
|
||||
<CountdownBadge countdown={countdown} status={status} />
|
||||
</div>
|
||||
<div className="p-4">
|
||||
|
||||
<div className="mb-2 text-sm text-gray-600 dark:text-gray-300">
|
||||
<span className="font-medium">Destination:</span> {event.destination}
|
||||
</div>
|
||||
<div className="mb-4 text-sm text-gray-600 dark:text-gray-300">
|
||||
<span className="font-medium">Time:</span> {format(event.eventTime, "EEE dd MMM yyyy HH:mm")}
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<TrainSection
|
||||
journeys={journeys}
|
||||
eventTime={event.eventTime}
|
||||
destName={destStation?.name ?? event.destination}
|
||||
loading={loading}
|
||||
error={error}
|
||||
onRefresh={handleRefresh}
|
||||
/>
|
||||
<BikeSection
|
||||
bikeRoute={bikeRoute}
|
||||
bikeLoading={bikeLoading}
|
||||
bikeError={bikeError}
|
||||
destName={event.destination}
|
||||
loading={journeysLoading}
|
||||
error={journeysError}
|
||||
/>
|
||||
|
||||
<BikeSection bikeRoute={bikeRoute} bikeLoading={bikeLoading} bikeError={bikeError} />
|
||||
|
||||
{stops.length > 0 && (
|
||||
<WienerLinienSection stops={stops} departures={departures} loading={wlLoading} error={wlError} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EventCard;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user