aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/components/FacilitiesTable.astro
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/FacilitiesTable.astro')
-rw-r--r--src/components/FacilitiesTable.astro186
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>