diff options
| author | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-24 12:29:24 +0900 |
|---|---|---|
| committer | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-24 12:29:24 +0900 |
| commit | a71727538f65ab4f10f5239550be82590f9d47d1 (patch) | |
| tree | 4608d37faead4f253c3311982a400a8fb88fba9e /src/components/FacilitiesTable.astro | |
| parent | c7efe674b34a2949b76d62bb71a972427965af92 (diff) | |
parks: 公園一覧と地図、公共施設の情報を更新
- 近隣公園のクリックを市内公園と同じ挙動にし、Googleマップを公園名で開く
- 公共施設のトイレを○にし、ルネこだいらを追加
- 未取得だった施設の座標を追加し、再ジオコーディング時の上書きを防止
- 手入力ポリゴン、近隣公園、PWA、ライセンス表示を追加
Diffstat (limited to 'src/components/FacilitiesTable.astro')
| -rw-r--r-- | src/components/FacilitiesTable.astro | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/components/FacilitiesTable.astro b/src/components/FacilitiesTable.astro new file mode 100644 index 0000000..2974581 --- /dev/null +++ b/src/components/FacilitiesTable.astro @@ -0,0 +1,186 @@ +--- +// 地域センター・公民館・図書館・市役所支所・文化施設の一覧。 +// トイレは市の公共施設として基本的に利用できる。給水は公式ページに明記が少ないため「未確認」が多い。 +import facilitiesData from "@/data/kodaira-facilities.json"; + +type Facility = { + name: string; + type: string; + address: string; + hours: string; + closed: string; + toilet: string; + water: string; + note: string; + source: string; +}; + +const facilities = facilitiesData as Facility[]; +const types = ["地域センター", "公民館", "図書館", "市役所支所", "文化施設"]; +const mapsUrl = (name: string) => + `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(`小平市${name}`)}`; +--- + +<div class="facilities" data-fac-root> + <div class="fac-controls"> + <label> + 種別 + <select data-fac-type> + <option value="">すべて</option> + {types.map((type) => <option value={type}>{type}</option>)} + </select> + </label> + <label> + キーワード + <input type="search" data-fac-search placeholder="施設名・住所・備考" /> + </label> + <label><input type="checkbox" data-fac-toilet /> トイレ○</label> + <label><input type="checkbox" data-fac-water /> 給水○</label> + <span class="fac-count" data-fac-count>{facilities.length}件</span> + </div> + + <div class="fac-table-wrap"> + <table> + <thead> + <tr> + <th scope="col">施設名</th> + <th scope="col">種別</th> + <th scope="col">住所</th> + <th scope="col">開館時間</th> + <th scope="col">休館日</th> + <th scope="col">トイレ</th> + <th scope="col">給水</th> + <th scope="col">備考</th> + </tr> + </thead> + <tbody> + {facilities.map((f) => ( + <tr + data-fac-row + data-type={f.type} + data-toilet={f.toilet || ""} + data-water={f.water || ""} + data-search={`${f.name} ${f.type} ${f.address} ${f.note}`.toLowerCase()} + > + <td> + {f.source ? ( + <a href={f.source} target="_blank" rel="noopener">{f.name}</a> + ) : ( + f.name + )} + </td> + <td>{f.type}</td> + <td> + <a href={mapsUrl(f.name)} target="_blank" rel="noopener"> + {f.address || "—"} + </a> + </td> + <td>{f.hours || "未確認"}</td> + <td>{f.closed || "未確認"}</td> + <td + class:list={[ + "fac-status", + f.toilet === "○" ? "is-yes" : f.toilet === "×" ? "is-no" : "", + ]} + >{f.toilet || "未確認"}</td> + <td + class:list={[ + "fac-status", + f.water === "○" ? "is-yes" : f.water === "×" ? "is-no" : "", + ]} + >{f.water || "未確認"}</td> + <td>{f.note}</td> + </tr> + ))} + </tbody> + </table> + </div> + + <p class="fac-note"> + トイレは市の公共施設として基本的に利用できます(○)。給水は公式ページに明記が少ないため「未確認」が多いです。最新の情報は各施設の公式ページで確認してください。地図の位置は住所・名称からの概略です。 + </p> +</div> + +<script> + const root = document.querySelector<HTMLElement>("[data-fac-root]"); + if (root) { + const rows = Array.from(root.querySelectorAll<HTMLTableRowElement>("[data-fac-row]")); + const search = root.querySelector<HTMLInputElement>("[data-fac-search]"); + const type = root.querySelector<HTMLSelectElement>("[data-fac-type]"); + const toilet = root.querySelector<HTMLInputElement>("[data-fac-toilet]"); + const water = root.querySelector<HTMLInputElement>("[data-fac-water]"); + const count = root.querySelector<HTMLElement>("[data-fac-count]"); + const apply = () => { + const q = (search?.value || "").trim().toLowerCase(); + const t = type?.value || ""; + const needToilet = Boolean(toilet?.checked); + const needWater = Boolean(water?.checked); + let shown = 0; + rows.forEach((row) => { + const okType = !t || row.dataset.type === t; + const okText = !q || (row.dataset.search || "").includes(q); + const okToilet = !needToilet || row.dataset.toilet === "○"; + const okWater = !needWater || row.dataset.water === "○"; + const ok = okType && okText && okToilet && okWater; + row.hidden = !ok; + if (ok) shown += 1; + }); + if (count) count.textContent = `${shown} / ${rows.length}件`; + }; + search?.addEventListener("input", apply); + type?.addEventListener("change", apply); + toilet?.addEventListener("change", apply); + water?.addEventListener("change", apply); + apply(); + } +</script> + +<style> + .fac-controls { + display: flex; + flex-wrap: wrap; + gap: 0.75rem; + align-items: center; + margin: 0.75rem 0; + font-size: 0.9em; + } + .fac-controls label { + display: flex; + gap: 0.35rem; + align-items: center; + } + .fac-controls input, + .fac-controls select { + padding: 0.3rem 0.5rem; + border: 1px solid var(--sl-color-gray-5); + border-radius: 4px; + background: var(--sl-color-bg); + color: var(--sl-color-text); + } + .fac-count { + color: var(--sl-color-gray-2); + font-size: 0.85em; + } + .fac-table-wrap { + overflow-x: auto; + } + .fac-table-wrap table { + font-size: 0.85em; + } + .fac-status { + text-align: center; + white-space: nowrap; + } + .fac-status.is-yes { + color: #1b5e20; + font-weight: 700; + } + .fac-status.is-no { + color: #b71c1c; + } + .fac-note { + margin-top: 0.5rem; + color: var(--sl-color-gray-2); + font-size: 0.82em; + } +</style> |
