has issues
This commit is contained in:
parent
2e112d7398
commit
c645b0f1d4
96 changed files with 2147083 additions and 5787 deletions
|
|
@ -11,7 +11,12 @@ import { EyeIcon } from '../ui/icons/EyeIcon';
|
|||
import { InfoIcon } from '../ui/icons/InfoIcon';
|
||||
import { formatFilterValue, formatNumber } from '../../lib/format';
|
||||
import { useTravelDestinations } from '../../hooks/useTravelDestinations';
|
||||
import { MODE_ICONS, useTranslatedModes, type TransportMode } from '../../hooks/useTravelTime';
|
||||
import {
|
||||
MAX_TRAVEL_MINUTES,
|
||||
MODE_ICONS,
|
||||
useTranslatedModes,
|
||||
type TransportMode,
|
||||
} from '../../hooks/useTravelTime';
|
||||
|
||||
interface TravelTimeCardProps {
|
||||
mode: TransportMode;
|
||||
|
|
@ -19,6 +24,8 @@ interface TravelTimeCardProps {
|
|||
label: string;
|
||||
timeRange: [number, number] | null;
|
||||
useBest: boolean;
|
||||
noChange: boolean;
|
||||
noBuses: boolean;
|
||||
isPinned: boolean;
|
||||
isActive: boolean;
|
||||
dragValue: [number, number] | null;
|
||||
|
|
@ -29,6 +36,8 @@ interface TravelTimeCardProps {
|
|||
onDragChange: (value: [number, number]) => void;
|
||||
onDragEnd: () => void;
|
||||
onToggleBest: () => void;
|
||||
onToggleNoChange: () => void;
|
||||
onToggleNoBuses: () => void;
|
||||
onRemove: () => void;
|
||||
filterImpact?: number;
|
||||
destinationDropdownPortal?: boolean;
|
||||
|
|
@ -40,6 +49,8 @@ export function TravelTimeCard({
|
|||
label,
|
||||
timeRange,
|
||||
useBest,
|
||||
noChange,
|
||||
noBuses,
|
||||
isPinned,
|
||||
isActive,
|
||||
dragValue,
|
||||
|
|
@ -50,6 +61,8 @@ export function TravelTimeCard({
|
|||
onDragChange,
|
||||
onDragEnd,
|
||||
onToggleBest,
|
||||
onToggleNoChange,
|
||||
onToggleNoBuses,
|
||||
onRemove,
|
||||
filterImpact,
|
||||
destinationDropdownPortal = true,
|
||||
|
|
@ -59,6 +72,8 @@ export function TravelTimeCard({
|
|||
const { destinations, loading: destinationsLoading } = useTravelDestinations(mode);
|
||||
const [showInfo, setShowInfo] = useState(false);
|
||||
const [showBestInfo, setShowBestInfo] = useState(false);
|
||||
const [showNoChangeInfo, setShowNoChangeInfo] = useState(false);
|
||||
const [showNoBusesInfo, setShowNoBusesInfo] = useState(false);
|
||||
|
||||
const handleDestinationSelect = useCallback(
|
||||
(selectedSlug: string, selectedLabel: string, lat: number, lon: number) => {
|
||||
|
|
@ -68,7 +83,7 @@ export function TravelTimeCard({
|
|||
);
|
||||
|
||||
const sliderMin = 0;
|
||||
const sliderMax = 120;
|
||||
const sliderMax = MAX_TRAVEL_MINUTES;
|
||||
const displayRange = isActive && dragValue ? dragValue : (timeRange ?? [sliderMin, sliderMax]);
|
||||
|
||||
const ModeIcon = MODE_ICONS[mode];
|
||||
|
|
@ -116,18 +131,42 @@ export function TravelTimeCard({
|
|||
portal={destinationDropdownPortal}
|
||||
/>
|
||||
|
||||
{/* Best-case toggle — transit only, shown when destination is set */}
|
||||
{/* Transit-only toggles — shown when destination is set */}
|
||||
{slug && mode === 'transit' && (
|
||||
<div className="flex items-center gap-1.5">
|
||||
<PillToggle
|
||||
label={t('travel.bestCase')}
|
||||
active={useBest}
|
||||
onClick={onToggleBest}
|
||||
size="xs"
|
||||
/>
|
||||
<IconButton onClick={() => setShowBestInfo(true)} title={t('travel.bestCaseTitle')}>
|
||||
<InfoIcon className="w-3 h-3" />
|
||||
</IconButton>
|
||||
<div className="flex flex-wrap items-center gap-x-3 gap-y-1.5">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<PillToggle
|
||||
label={t('travel.bestCase')}
|
||||
active={useBest}
|
||||
onClick={onToggleBest}
|
||||
size="xs"
|
||||
/>
|
||||
<IconButton onClick={() => setShowBestInfo(true)} title={t('travel.bestCaseTitle')}>
|
||||
<InfoIcon className="w-3 h-3" />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<PillToggle
|
||||
label={t('travel.noChange')}
|
||||
active={noChange}
|
||||
onClick={onToggleNoChange}
|
||||
size="xs"
|
||||
/>
|
||||
<IconButton onClick={() => setShowNoChangeInfo(true)} title={t('travel.noChangeTitle')}>
|
||||
<InfoIcon className="w-3 h-3" />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<PillToggle
|
||||
label={t('travel.noBuses')}
|
||||
active={noBuses}
|
||||
onClick={onToggleNoBuses}
|
||||
size="xs"
|
||||
/>
|
||||
<IconButton onClick={() => setShowNoBusesInfo(true)} title={t('travel.noBusesTitle')}>
|
||||
<InfoIcon className="w-3 h-3" />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -141,6 +180,22 @@ export function TravelTimeCard({
|
|||
</InfoPopup>
|
||||
)}
|
||||
|
||||
{showNoChangeInfo && (
|
||||
<InfoPopup title={t('travel.noChangeTitle')} onClose={() => setShowNoChangeInfo(false)}>
|
||||
<p className="text-sm text-warm-700 dark:text-warm-300 leading-relaxed">
|
||||
<Trans i18nKey="travel.noChangeDesc" components={{ strong: <strong /> }} />
|
||||
</p>
|
||||
</InfoPopup>
|
||||
)}
|
||||
|
||||
{showNoBusesInfo && (
|
||||
<InfoPopup title={t('travel.noBusesTitle')} onClose={() => setShowNoBusesInfo(false)}>
|
||||
<p className="text-sm text-warm-700 dark:text-warm-300 leading-relaxed">
|
||||
<Trans i18nKey="travel.noBusesDesc" components={{ strong: <strong /> }} />
|
||||
</p>
|
||||
</InfoPopup>
|
||||
)}
|
||||
|
||||
{/* Time range slider — only show when we have data */}
|
||||
{slug && (
|
||||
<div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue