import { useState, useEffect } from "react"; import { useLocalStorage } from "../../useLocalStorage"; const TYPE_VIN = "vin"; /** * Match VIN with RegEx * @param {string} vin - potential VIN * @returns {[boolean, string]} */ function parseVin(vin = "") { const prefix = new RegExp(`^${TYPE_VIN}:`); if (vin.match(prefix)) { return [true, vin.replace(prefix, "")]; } vin = vin.replace(/[^\p{L}\d]/gu, ''); var re = new RegExp("^[A-HJ-NPR-Z0-9]{8}[0-9X][A-HJ-NPR-Z0-9]{2}[0-9]{6}$"); return [vin.match(re), vin]; } /** * 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"; const [isVin, vin] = parseVin(part) if (isVin) { type = TYPE_VIN; part = vin; } return [type, part]; } export default function useQuery() { const [query, setQuery] = useLocalStorage("VEHICLE_SEARCH", ""); const [parts, setParts] = useState([]); const [payload, setPayload] = useState({}); const [loading, setLoading] = useState(true); useEffect(() => { setLoading(true); let vins = []; let search = ""; const parts = query.replaceAll(" ", ",").split(",").map(parseQueryPart); setParts(parts); parts.forEach(([type, value]) => { if (type === "vin") { vins.push(value); } if (type === "search") { search = `${search} ${value}`.trim(); } }); setQuery(() => parts.map(([type, part]) => { if (type !== "search") { return `${type}:${part}`; } return part; }).join(" ").replace(/\s{2,}/g, ' ').trim()); setPayload({ search, vins: vins.join(","), }) }, [query, setPayload, setQuery]); useEffect(() => { setLoading(false); }, [payload, setLoading]) return { parts, payload, query, setQuery, loading, } }