Improve FAQ & video rendering, tighten homepage and CSS

This commit is contained in:
Andras Schmelczer 2026-05-04 22:07:30 +01:00
parent 05a1f316e1
commit c69bb0d614
48 changed files with 4689 additions and 1077 deletions

View file

@ -38,6 +38,8 @@ interface AiFilterInputProps {
onSubmit: (query: string) => void;
isLoggedIn: boolean;
onLoginRequired: () => void;
defaultExpanded?: boolean;
defaultQuery?: string;
}
export default memo(function AiFilterInput({
@ -49,10 +51,12 @@ export default memo(function AiFilterInput({
onSubmit,
isLoggedIn,
onLoginRequired,
defaultExpanded = false,
defaultQuery = '',
}: AiFilterInputProps) {
const { t } = useTranslation();
const [query, setQuery] = useState('');
const [expanded, setExpanded] = useState(false);
const [query, setQuery] = useState(defaultQuery);
const [expanded, setExpanded] = useState(defaultExpanded);
const exampleQueries = useMemo(
() => [t('aiFilter.example1'), t('aiFilter.example2'), t('aiFilter.example3')],
[t]

View file

@ -61,7 +61,7 @@ export default function LocationSearch({
};
document.addEventListener('mousedown', handler);
return () => document.removeEventListener('mousedown', handler);
}, [isMobile, search.close]);
}, [isMobile, search]);
// Focus input when expanding on mobile
useEffect(() => {
@ -112,7 +112,7 @@ export default function LocationSearch({
setLoading(false);
}
},
[onFlyTo, onLocationSearched, isMobile, search]
[onFlyTo, onLocationSearched, isMobile, search, t]
);
const [locating, setLocating] = useState(false);

View file

@ -72,6 +72,7 @@ interface MapPageProps {
isMobile?: boolean;
initialTravelTime?: TravelTimeInitial;
initialPostcode?: string;
shareCode?: string;
user?: { id: string; subscription: string; isAdmin?: boolean } | null;
onLoginClick?: () => void;
onRegisterClick?: () => void;
@ -102,6 +103,7 @@ export default function MapPage({
isMobile = false,
initialTravelTime,
initialPostcode,
shareCode,
user,
onLoginClick,
onRegisterClick,
@ -192,6 +194,7 @@ export default function MapPage({
viewFeature,
activeFeature,
travelTimeEntries: entries,
shareCode,
});
const handleAiFilterSubmit = useCallback(
@ -352,18 +355,28 @@ export default function MapPage({
[handleCurrentLocationSearch, isMobile]
);
// For share-link recipients, "Continue with Demo" snaps back to the shared
// coords (the area their link was meant to show), not the central-London
// free-zone demo. Captured once on mount so a later URL rewrite by
// useUrlSync (which tracks the user's current view) doesn't overwrite it.
const shareReturnViewRef = useRef(shareCode ? initialViewState : null);
const handleZoomToFreeZone = useCallback(() => {
mapFlyToRef.current?.(
INITIAL_VIEW_STATE.latitude,
INITIAL_VIEW_STATE.longitude,
INITIAL_VIEW_STATE.zoom
);
const target = shareReturnViewRef.current ?? INITIAL_VIEW_STATE;
mapFlyToRef.current?.(target.latitude, target.longitude, target.zoom);
}, []);
const pois = usePOIData(mapData.bounds, selectedPOICategories);
const [isAreaGroupExpanded, toggleAreaGroup] = useCollapsibleGroups(true);
useUrlSync(mapData.currentView, filters, features, selectedPOICategories, rightPaneTab, entries);
useUrlSync(
mapData.currentView,
filters,
features,
selectedPOICategories,
rightPaneTab,
entries,
shareCode
);
useEffect(() => {
mapData.setInitialView(initialViewState);
@ -868,6 +881,7 @@ export default function MapPage({
onRegisterClick={onRegisterClick ?? (() => {})}
onStartCheckout={() => license.startCheckout()}
onZoomToFreeZone={handleZoomToFreeZone}
isShareReturn={!!shareReturnViewRef.current}
/>
)}
</div>
@ -996,6 +1010,7 @@ export default function MapPage({
onRegisterClick={onRegisterClick ?? (() => {})}
onStartCheckout={() => license.startCheckout()}
onZoomToFreeZone={handleZoomToFreeZone}
isShareReturn={!!shareReturnViewRef.current}
/>
)}
</div>