90 lines
3.0 KiB
TypeScript
90 lines
3.0 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import { BikeRoute } from "@timetoleave/core";
|
|
import LoadingSpinner from "@/app/ui/LoadingSpinner";
|
|
import Button from "@/app/ui/Button";
|
|
|
|
type BikeSectionProps = {
|
|
bikeRoute: BikeRoute | null | undefined;
|
|
bikeLoading: boolean;
|
|
bikeError: string | null | undefined;
|
|
onRefresh?: () => void;
|
|
className?: string;
|
|
forceVisible?: boolean;
|
|
};
|
|
|
|
const BikeSection: React.FC<BikeSectionProps> = ({
|
|
bikeRoute,
|
|
bikeLoading,
|
|
bikeError,
|
|
onRefresh,
|
|
className = "",
|
|
forceVisible = false,
|
|
}) => {
|
|
if (!forceVisible && !bikeRoute && !bikeLoading && !bikeError) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div className={`mt-4 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">Bicycle Route</h3>
|
|
<p className="text-sm text-[#F4F1EA]/60">Door-to-door route to the event</p>
|
|
</div>
|
|
{onRefresh && (
|
|
<Button variant="secondary" size="sm" onClick={onRefresh}>
|
|
Refresh
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div className="p-4">
|
|
{bikeLoading ? (
|
|
<div className="text-center py-4">
|
|
<LoadingSpinner size="md" />
|
|
</div>
|
|
) : bikeError ? (
|
|
<div className="text-center py-4 text-[#FF2D8D]">Error: {bikeError}</div>
|
|
) : bikeRoute ? (
|
|
<div className="space-y-2">
|
|
<div className="flex justify-between">
|
|
<span className="text-[#F4F1EA]/66">Distance</span>
|
|
<span className="font-medium text-white">
|
|
{Math.round(bikeRoute.distance / 1000)} km ({Math.round(bikeRoute.distance)} m)
|
|
</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-[#F4F1EA]/66">Duration</span>
|
|
<span className="font-medium text-white">
|
|
{Math.floor(bikeRoute.duration / 60)} min {bikeRoute.duration % 60} s
|
|
</span>
|
|
</div>
|
|
{bikeRoute.steps && bikeRoute.steps.length > 0 && (
|
|
<div className="mt-4">
|
|
<h4 className="mb-2 font-medium text-[#F4F1EA]">Steps</h4>
|
|
<ul className="space-y-2">
|
|
{bikeRoute.steps.map((step, index) => (
|
|
<li key={index} className="text-sm">
|
|
<span className="font-medium text-[#D946EF]">{step.name}</span>
|
|
<span className="ml-2 text-[#F4F1EA]/70">{step.instruction}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : (
|
|
<div className="py-4 text-center text-sm text-[#F4F1EA]/58">
|
|
Add origin and destination coordinates to calculate a bike route.
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default BikeSection;
|