--- // 小平市の公園一覧(/kodaira-data/parks/)を表示する。 // データは src/data/kodaira-parks.json(321件、市の公開資料から作成)。 // DOM を抑えるため、設備は1セルにまとめ、アイコンは CSS の擬似要素で描く。 // 絞り込み・並べ替え・カード表示は利用者の端末で実行する。 import parksData from "@/data/kodaira-parks.json"; type Park = Record; const parks = parksData as Park[]; const EMPTY = "—"; // 種別の表示(色付きの丸+区分名。正式名は title / aria-label で補う)。 const TYPE_LABEL: Record = { 街区: "街区公園", 近隣: "近隣公園", 運動: "運動公園", }; const TYPE_CLASS: Record = { 街区: "parks-type--block", 近隣: "parks-type--neighbor", 運動: "parks-type--sports", }; // 設備バッジ(アイコンは CSS の ::before で描く)。 type Badge = { kind: string; label: string; title: string }; function facilityBadges(p: Park): Badge[] { const badges: Badge[] = []; if (p["トイレ"]) { badges.push({ kind: "toilet", label: "トイレ", title: `トイレ: ${p["トイレ"]}` }); } if (p["水飲み場"]) { badges.push({ kind: "water", label: "水飲み場", title: `水飲み場: ${p["水飲み場"]}` }); } if (p["遊具"]) { badges.push({ kind: "toy", label: "遊具", title: `遊具: ${p["遊具"]}` }); } const ball = p["ボール遊び"]; if (ball && ball !== "禁止") { const label = ball.includes("一部") ? "ボール遊び一部可" : "ボール遊び可"; badges.push({ kind: "ball", label, title: `ボール遊び: ${ball}` }); } return badges; } // 設備フィルタ用のトークン(data-fac)。 function facTokens(p: Park): string { const tokens: string[] = []; if (p["トイレ"]) tokens.push("toilet"); if (p["水飲み場"]) tokens.push("water"); if (p["遊具"]) tokens.push("toy"); const ball = p["ボール遊び"]; if (ball && ball !== "禁止") tokens.push("ball"); return tokens.join(" "); } // 設備セルの補足テキスト(バッジで示した項目の詳細と、その他の項目)。 const DETAIL_FIELDS: { key: string; label: string }[] = [ { key: "ベンチ・椅子", label: "ベンチ・椅子" }, { key: "テーブル", label: "テーブル" }, { key: "防災用具", label: "防災用具" }, { key: "遊具", label: "遊具" }, { key: "備考", label: "備考" }, ]; function detailText(p: Park): string { const parts: string[] = []; if (p["南西部指定管理"]) parts.push("南西部指定管理"); for (const { key, label } of DETAIL_FIELDS) { const value = p[key]; if (!value) continue; parts.push(key === "備考" ? value : `${label}: ${value}`); } const ball = p["ボール遊び"]; if (ball && ball !== "禁止" && ball !== "可") parts.push(`ボール遊び: ${ball}`); return parts.join(" / "); } // 面積(数値) function areaNumber(value: string): number { const n = Number(value); return Number.isFinite(n) ? n : 0; } function areaText(value: string): string { const n = areaNumber(value); return n ? n.toLocaleString("ja-JP") : value; } // 面積の目安(小・中・大)。しきい値はページの注記に合わせる。 function sizeLabel(area: number): string { if (area < 1000) return "小"; if (area < 10000) return "中"; return "大"; } function sizeTitle(area: number): string { if (area < 1000) return "目安: 1,000㎡未満(小さめ)"; if (area < 10000) return "目安: 1,000〜10,000㎡(ふつう)"; return "目安: 10,000㎡以上(広め)"; } // 住所ではなく公園名で検索する(地番は地図側で正しく解決されないため)。 // 「小平市」を付けないと別の自治体の同名公園に飛ぶので必ず付ける。 function mapsUrl(name: string): string { const query = encodeURIComponent(`小平市${name}`); return `https://www.google.com/maps/search/?api=1&query=${query}`; } // 検索対象(公園名・住所・町名・種別・設備・備考)。 function searchIndex(p: Park): string { return [ p["公園名"], p["住所"], p["町名"], p["種別"], p["トイレ"], p["水飲み場"], p["ボール遊び"], ...DETAIL_FIELDS.map((f) => p[f.key]), ] .join(" ") .toLowerCase(); } const towns = [...new Set(parks.map((p) => p["町名"]))].sort((a, b) => a.localeCompare(b, "ja"), ); const total = parks.length; ---
設備で絞る
{total}件

設備の情報は市の南西部地域の公園のみです。設備で絞ると、この情報がある公園だけが対象になります。

{parks.map((park) => ( ))}
住所 種別 施設・備考
{park["公園名"]} {park["住所"]} {areaText(park["面積㎡"])}㎡ {park["種別"] ? ( {park["種別"]} ) : ( EMPTY )} {facilityBadges(park).map((b) => ( {b.label} ))} {detailText(park) ? {detailText(park)} : null} {facilityBadges(park).length === 0 && !detailText(park) ? EMPTY : null}