import { useMemo, useState } from 'react'; import { useI18n, type Key } from '../lib/i18n'; import { VERDICT_ORDER } from '../lib/assess'; import { DEMO_PLACES } from '../lib/demo'; import { fold } from '../lib/text'; import type { Assessment, Place, PlaceCategory, Profile } from '../lib/types'; import { Icon, VerdictTag } from './ui'; export interface Filters { query: string; cat: PlaceCategory | 'all'; onlyFit: boolean } export const DEFAULT_FILTERS: Filters = { query: '', cat: 'all', onlyFit: false }; const CATS: (PlaceCategory | 'all')[] = ['all', 'food', 'culture', 'shop', 'stay', 'health', 'services']; const PAGE = 40; export function filterPlaces(places: Place[], assessments: Map, f: Filters): Place[] { const q = fold(f.query.trim()); return places .filter((p) => { if (f.cat !== 'all' && p.cat !== f.cat) return false; const v = assessments.get(p.id)?.verdict; if (f.onlyFit && v !== 'match' && v !== 'partial') return false; if (!q) return true; return fold(`${p.name ?? ''} ${p.tags['addr:street'] ?? ''} ${p.tags['addr:housenumber'] ?? ''}`).includes(q); }) .sort((a, b) => { const va = VERDICT_ORDER[assessments.get(a.id)?.verdict ?? 'incomplete']; const vb = VERDICT_ORDER[assessments.get(b.id)?.verdict ?? 'incomplete']; return va - vb || Number(!!a.demo) - Number(!!b.demo) || (a.name ?? '').localeCompare(b.name ?? '', 'pl'); }); } interface Props { profile: Profile; filters: Filters; onFilters: (f: Filters) => void; results: Place[]; assessments: Map; onSelect: (id: string) => void; } export function PlacesView({ profile, filters, onFilters, results, assessments, onSelect }: Props) { const { t } = useI18n(); const [shown, setShown] = useState(PAGE); const visible = useMemo(() => results.slice(0, shown), [results, shown]); const set = (patch: Partial) => { setShown(PAGE); onFilters({ ...filters, ...patch }); }; return (

{t('places.title')}

{t('places.hint', { profile: t(`profile.${profile.kind}`).toLowerCase() })}

set({ query: e.target.value })} />
set({ onlyFit: e.target.checked })} />

{t('places.count', { n: results.length })}

{results.length === 0 ? (

{t('places.empty')}

) : (
    {visible.map((p) => { const a = assessments.get(p.id); const isDemo = DEMO_PLACES.some((d) => d.id === p.id); return (
  • ); })}
)} {results.length > shown && ( )}
); }