84 lines
3.0 KiB
TypeScript
84 lines
3.0 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import { WalkRoute } from "@timetoleave/core";
|
|
import LoadingSpinner from "@/app/ui/LoadingSpinner";
|
|
import Button from "@/app/ui/Button";
|
|
|
|
/**
|
|
* Renders the walking route from the arrival station to the event destination.
|
|
*
|
|
* This is the "last mile" leg computed via OSRM walking profile.
|
|
* Hidden when no route data, no loading, and no error are present.
|
|
*/
|
|
type WalkingOptionProps = {
|
|
walkRoute: WalkRoute | null | undefined;
|
|
walkLoading?: boolean;
|
|
walkError?: string | null | undefined;
|
|
onRefresh?: () => void;
|
|
className?: string;
|
|
};
|
|
|
|
const WalkingOption: React.FC<WalkingOptionProps> = ({ walkRoute, walkLoading, walkError, onRefresh, className = "" }) => {
|
|
if (!walkRoute && !walkLoading && !walkError) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div className={`overflow-hidden rounded-xl border border-white/10 bg-black/16 ${className}`}>
|
|
<div className="border-b border-white/10 p-4">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h3 className="text-lg font-semibold text-white">Final Walk</h3>
|
|
<p className="text-sm text-brand-light/60">From arrival station to destination</p>
|
|
</div>
|
|
{onRefresh && (
|
|
<Button variant="secondary" size="sm" onClick={onRefresh}>
|
|
Refresh
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div className="p-4">
|
|
{walkLoading ? (
|
|
<div className="py-4 text-center">
|
|
<LoadingSpinner size="md" />
|
|
</div>
|
|
) : walkError ? (
|
|
<div className="py-4 text-center text-brand-pink">Error: {walkError}</div>
|
|
) : walkRoute ? (
|
|
<div className="space-y-2">
|
|
<div className="flex justify-between">
|
|
<span className="text-brand-light/66">Distance</span>
|
|
<span className="font-medium text-white">
|
|
{Math.round(walkRoute.distance / 1000)} km ({Math.round(walkRoute.distance)} m)
|
|
</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-brand-light/66">Duration</span>
|
|
<span className="font-medium text-white">
|
|
{Math.floor(walkRoute.duration / 60)} min {walkRoute.duration % 60} s
|
|
</span>
|
|
</div>
|
|
{walkRoute.steps && walkRoute.steps.length > 0 && (
|
|
<div className="mt-4">
|
|
<h4 className="mb-2 font-medium text-brand-light">Steps</h4>
|
|
<ul className="space-y-2">
|
|
{walkRoute.steps.map((step: { name: string; instruction: string }, index: number) => (
|
|
<li key={index} className="text-sm">
|
|
<span className="font-medium text-brand-fuchsia">{step.name}</span>
|
|
<span className="ml-2 text-brand-light/70">{step.instruction}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default WalkingOption;
|