// Page-level components: DoctorsCatalogPage, DoctorDetailPage const { useState: pS, useMemo: pM, useEffect: pE } = React; // ============ BREADCRUMBS ============ const Breadcrumbs = ({ items }) => ( ); // ============ PAGE HERO ============ const PageHero = ({ eyebrow, title, sub, breadcrumbs, action }) => (
{breadcrumbs && }
{eyebrow && {eyebrow}}

{title}

{sub &&

{sub}

}
{action &&
{action}
}
); // ============ DOCTORS CATALOG ============ const DoctorsCatalogPage = ({ onBook }) => { const [query, setQuery] = pS(''); const [selectedDirs, setSelectedDirs] = pS([]); const [degreeOnly, setDegreeOnly] = pS(false); const [minExp, setMinExp] = pS(0); const [sort, setSort] = pS('exp-desc'); const toggleDir = (id) => { setSelectedDirs((cur) => cur.includes(id) ? cur.filter(x => x !== id) : [...cur, id] ); }; const filtered = pM(() => { let arr = DATA.doctors.slice(); if (query.trim()) { const q = query.toLowerCase(); arr = arr.filter(d => d.fullName.toLowerCase().includes(q) || d.specs.some(s => s.toLowerCase().includes(q)) || d.tags.some(t => t.toLowerCase().includes(q)) ); } if (selectedDirs.length) { arr = arr.filter(d => d.directions && d.directions.some(x => selectedDirs.includes(x))); } if (degreeOnly) { arr = arr.filter(d => d.degree); } if (minExp > 0) { arr = arr.filter(d => parseInt(d.experience) >= minExp); } if (sort === 'exp-desc') arr.sort((a, b) => parseInt(b.experience) - parseInt(a.experience)); if (sort === 'exp-asc') arr.sort((a, b) => parseInt(a.experience) - parseInt(b.experience)); if (sort === 'name') arr.sort((a, b) => a.fullName.localeCompare(b.fullName, 'ru')); return arr; }, [query, selectedDirs, degreeOnly, minExp, sort]); const reset = () => { setQuery(''); setSelectedDirs([]); setDegreeOnly(false); setMinExp(0); }; return ( <>
{/* Filters */}
setQuery(e.target.value)} /> {query && ( )}
{/* Direction chips */}
Направление: {DATA.directions.map((d) => ( ))} {(selectedDirs.length > 0 || query || degreeOnly || minExp > 0) && ( )}
{/* Quick options */}
{[0, 5, 10, 15, 20].map((y) => ( ))}
Найдено: {filtered.length} из {DATA.doctors.length}
{/* Results */} {filtered.length === 0 ? ( DATA.doctors.length === 0 ? (

Список врачей пока пуст

Скоро здесь появятся специалисты центра

) : (

Ничего не найдено

Попробуйте сбросить фильтры или изменить запрос

) ) : (
{filtered.map((doc) => ( ))}
)}
); }; // ============ DOCTOR CARD (catalog version) ============ const DoctorCard = ({ doctor, onBook }) => { return (
{doctor.photo ? {doctor.fullName} : } {doctor.degree && {doctor.degree}}

{doctor.fullName}

{doctor.specs.join(', ')}
Стаж {doctor.experience} {doctor.price}
Подробнее
); }; Object.assign(window, { DoctorsCatalogPage, DoctorCard, Breadcrumbs, PageHero });