import { useState, useEffect } from "react"; import { useLocalStorage } from "../../useLocalStorage"; const TYPE_VIN = "vin"; /** * Match VIN with RegEx * @param {string} vin - potential VIN * @returns {boolean} */ function isVIN(vin) { var re = new RegExp("^[A-HJ-NPR-Z\\d]{8}[\\dX][A-HJ-NPR-Z\\d]{2}\\d{6}$"); return vin.match(re) } /** * Convert a string into a QueryPart tuple. * @typedef {"search" | "vin"} Type - the type of value represented * @typedef {string} Value - the value * @typedef {[Type, Value]} QueryPart - a tuple representing a substring of a query * @param {string} part - substring of a query to turn into a QueryPart * @returns {QueryPart} */ function parseQueryPart(part) { let type = "search"; if (isVIN(part)) { type = TYPE_VIN; part = `${part}`; } return [type, part]; } export default function useQuery() { const [query, setQuery] = useLocalStorage("VEHICLE_SEARCH", ""); const [parts, setParts] = useState([]); const [search, setSearch] = useState(null); const [vins, setVins] = useState(""); const [loading, setLoading] = useState(true); function reset() { setSearch(""); setVins([]); } useEffect(() => { reset(); const parts = query.replaceAll(" ", ",").split(",").map(parseQueryPart); setParts(parts); parts.forEach(([type, value]) => { if (type === "vin") { setVins(vins => { if (vins.length) { return `${vins},${value}`; } return value; }); } if (type === "search") { setSearch(search => `${search} ${value}`.trim()); } }); setLoading(false); }, [query]); return { parts, search, vins, query, setQuery, loading, } }