src/components/ZoneSearchPanel.js
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import React, { useState, useRef, useLayoutEffect } from "react"
import { zonesForSearch, zonePath } from "../models/information"
import { labelColor } from "../styles"
import { Link } from "gatsby"
import { faSearch } from "@fortawesome/free-solid-svg-icons"
import Fuse from "fuse.js"
import { trackEvent } from "../util/analytics"
const fuse = new Fuse(zonesForSearch, {
keys: ["inclusionAreas", "province.name"],
})
const postcodeRegex = /^[0-9]{1,5}$/
export function postcodeSearch(postcode) {
return zonesForSearch.filter(zone => {
for (let code of zone.postcode) {
if (code.toString().indexOf(postcode) === 0) {
return true
}
}
return false
})
}
export function search(keyword) {
if (postcodeRegex.test(keyword)) {
return postcodeSearch(keyword)
} else {
return fuse.search(keyword)
}
}
let searchUsed = false
export function ZoneSearchPanel({ autoFocus, onSearchCompleted }) {
const [state, setState] = useState({
isSearchOpen: false,
zoneQuery: null,
})
const inputRef = useRef(/** @type {HTMLInputElement} */ (null))
useLayoutEffect(() => {
if (autoFocus && inputRef.current) {
inputRef.current.focus()
}
}, [autoFocus])
return (
<div css={{ position: "relative" }}>
<input
ref={inputRef}
css={{
border: `1px solid ${labelColor}`,
width: "100%",
boxSizing: "border-box",
padding: 10,
fontSize: 16,
marginTop: 20,
}}
placeholder="ค้นหาจาก รหัสไปรษณีย์ ชื่อ ตำบล อำเภอ หรือ จังหวัด"
onChange={v => {
const query = v.target.value
const isSearchOpen = query.length > 2 || postcodeRegex.test(query)
if (isSearchOpen && !searchUsed) {
searchUsed = true
trackEvent("Search for zone")
}
setState({ zoneQuery: query, isSearchOpen })
}}
value={state.zoneQuery}
/>
<div
css={{
top: 30,
position: "absolute",
right: 10,
color: labelColor,
}}
>
<FontAwesomeIcon icon={faSearch} />
</div>
{state.isSearchOpen && (
<ul css={{ listStyle: "none", padding: 0 }}>
{search(state.zoneQuery).map(z => {
return (
<li
key={`${z.zone.provinceId}-${z.zone.no}`}
css={{
padding: "12px 0px",
borderBottom: "1px solid gray",
position: "relative",
}}
>
<Link
to={zonePath(z.zone)}
onClick={() => {
trackEvent("View zone", { via: "Search" })
if (onSearchCompleted) onSearchCompleted()
}}
css={{
width: "calc(100% - 24px)",
display: "block",
color: "inherit",
textDecoration: "none",
}}
>
<div css={{ fontSize: 16 }}>
<b>
{z.province.name} เขตเลือกตั้งที่ {z.zone.no}
</b>
</div>
<div
css={{
color: "gray",
}}
>
{z.zone.details}
</div>
</Link>
<div
css={{
position: "absolute",
right: "4px",
top: "calc(50% - 3px)",
border: "solid #212121",
borderWidth: "0 2px 2px 0",
// display: 'inline-block',
padding: "4px",
transform: "rotate(-45deg)",
}}
/>
</li>
)
})}
</ul>
)}
</div>
)
}