/* ============================================================= 全国ページ — フィルタ / 検索 / ソート / 3つの表示モード ============================================================= */ const { useState, useMemo, useEffect } = React; const YEARS = [ { key: "y2023_range", label: "2023" }, { key: "y2024_range", label: "2024" }, { key: "y2025_range", label: "2025" } ]; /* セグメント型トグル */ function Segmented({ options, value, onChange, label }) { return (
{options.map(o => ( ))}
); } /* レンジ絞り込みチップ */ function RangeChips({ selected, onToggle }) { return (
{window.RANGES.map(r => { const on = selected.includes(r); return ( ); })}
); } /* ---- 1行=1施設(テーブル行 / カード / レンジ重視) ---- */ function YearProgression({ row }) { return (
{YEARS.map((y, i) => (
{y.label}
{i < YEARS.length - 1 && }
))}
); } function FacilityCard({ row, prefHref }) { return (

{row.facility}

{row.address &&

{row.address}

}
{row.pref}
{row.note &&

{row.note}

} {row.pref}のページへ
); } /* 地図セクションの表示切替(false で非表示) */ const SHOW_MAP = false; function App() { const data = window.SURVEY_DATA; const prefsWithData = useMemo(() => { const s = new Set(data.map(d => d.pref_slug)); return window.PREF_LIST.filter(p => s.has(p.slug)); }, []); const [q, setQ] = useState(""); const [pref, setPref] = useState("all"); const [type, setType] = useState("all"); const [hasOnly, setHasOnly] = useState(false); // 有のみ const [rangeYear, setRangeYear] = useState("y2025_range"); const [ranges, setRanges] = useState([]); // 空=すべて const [sort, setSort] = useState("name"); // name | range const [view, setView] = useState("table"); // table | card | trend const toggleRange = (r) => setRanges(s => s.includes(r) ? s.filter(x => x !== r) : [...s, r]); const results = useMemo(() => { let rows = data.filter(d => { if (q && !d.facility.toLowerCase().includes(q.trim().toLowerCase())) return false; if (pref !== "all" && d.pref_slug !== pref) return false; if (type !== "all" && d.type !== type) return false; if (hasOnly && d.has_surgery !== "有") return false; if (ranges.length && !ranges.includes(d[rangeYear])) return false; return true; }); if (sort === "name") { rows = [...rows].sort((a, b) => a.facility.localeCompare(b.facility, "ja")); } else { rows = [...rows].sort((a, b) => { const diff = (window.RANGE_ORDER[b.y2025_range] ?? -2) - (window.RANGE_ORDER[a.y2025_range] ?? -2); return diff !== 0 ? diff : a.facility.localeCompare(b.facility, "ja"); }); } return rows; }, [q, pref, type, hasOnly, ranges, rangeYear, sort]); const prefHref = (slug) => `都道府県別ページ.html?pref=${slug}`; const activeFilters = (pref !== "all") + (type !== "all") + (hasOnly ? 1 : 0) + (ranges.length ? 1 : 0) + (q ? 1 : 0); const resetAll = () => { setQ(""); setPref("all"); setType("all"); setHasOnly(false); setRanges([]); setSort("name"); }; const pickFromMap = (slug) => { setPref(slug); const f = document.getElementById("finder"); if (f) f.scrollIntoView({ behavior: "smooth", block: "start" }); }; return ( {/* HERO */}

斜視手術件数 全国調査(2023–2025)|回答施設を都道府県から探す

斜視手術件数 全国調査(2023–2025)。日本地図と医療機関、眼鏡をかけた子どもと家族のイラスト。回答施設内集計。

締切までに回答のあった医療機関を、都道府県・種別・実施有無・件数レンジで絞り込めます。
優劣の比較を目的とするものではありません。

{/* MAP + FINDER */}
{SHOW_MAP && }

回答施設をさがす

該当 {results.length} 件 / 全 {data.length} 件(回答施設)
e.preventDefault()} aria-label="絞り込み"> {/* 検索 */}
setQ(e.target.value)} placeholder="施設名でフリーワード検索" aria-label="施設名でフリーワード検索" /> {q && }
実施有無 setHasOnly(v === "only")} options={[{ value: "both", label: "有無両方" }, { value: "only", label: "実施有のみ" }]} />
{/* レンジ絞り込み */}
件数レンジで絞り込み
対象年 ({ value: y.key, label: y.label }))} />
{/* ツールバー:ソート・表示・リセット */}
並び替え
表示
{activeFilters > 0 && }
{sort === "range" &&

「2025レンジ順」は便宜的な区分の並びです(500件以上>300–499>150–299>60–149>30–59>10–29>0–9>未回答)。ランキングや優劣を示すものではありません。

} {/* 結果 */} {results.length === 0 ? (

条件に一致する回答施設が見つかりませんでした。

) : view === "table" ? (
{results.map((r, i) => ( ))}
都道府県施設名種別 実施有無202320242025 リンク
{r.pref} {r.facility} {r.address && {r.address}} {r.note && {r.note}}
) : view === "card" ? (
{results.map((r, i) => )}
) : (
{results.map((r, i) => (
{r.facility} {r.address &&

{r.address}

}
))}
)} {/* 都道府県ショートカット */}
回答のある都道府県:
); } ReactDOM.createRoot(document.getElementById("root")).render();