Files
ota-admin-portal/src/components/Cars/List/useQuery.js

92 lines
2.1 KiB
JavaScript

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,
}
}