cleaning up api calls and the builder page

This commit is contained in:
2025-12-30 13:53:52 -05:00
parent ee91fa1353
commit e69205e6f8
6 changed files with 82 additions and 1556 deletions
+8 -54
View File
@@ -52,7 +52,7 @@ type GunbuilderProductFromApi = {
platform: string;
partRole: string;
price: number | null;
mainImageUrl: string | null;
imageUrl: string | null;
buyUrl: string | null;
inStock?: boolean | null;
};
@@ -150,7 +150,7 @@ export default function PartsBrowseClient(props: {
const search = new URLSearchParams();
search.set("platform", effectivePlatform);
search.append("partRoles", partRole);
search.append("partRole", partRole);
// server paging (0-based)
search.set("page", String(currentPage - 1));
@@ -162,22 +162,13 @@ export default function PartsBrowseClient(props: {
// sort mapping
switch (sortBy) {
case "price-asc":
search.set("sort", "price,asc");
break;
case "price-desc":
search.set("sort", "price,desc");
break;
case "brand-asc":
search.set("sort", "brand,asc");
break;
case "relevance":
default:
search.set("sort", "updatedAt,desc");
break;
}
const res = await fetch(`${API_BASE_URL}/api/v1/products?${search.toString()}`, {
const res = await fetch(`${API_BASE_URL}/api/v1/catalog/options?${search.toString()}`, {
signal: controller.signal,
});
@@ -194,7 +185,7 @@ export default function PartsBrowseClient(props: {
platform: p.platform,
partRole: p.partRole,
price: p.price ?? 0,
imageUrl: p.mainImageUrl ?? undefined,
imageUrl: p.imageUrl ?? undefined,
buyUrl: p.buyUrl ?? undefined,
inStock: p.inStock ?? true,
}))
@@ -277,44 +268,7 @@ export default function PartsBrowseClient(props: {
});
}, [priceBounds.min, priceBounds.max]);
const filteredParts = useMemo(() => {
let result = [...parts];
if (priceRange.min != null)
result = result.filter((p) => p.price >= priceRange.min!);
if (priceRange.max != null)
result = result.filter((p) => p.price <= priceRange.max!);
if (brandFilter.length)
result = result.filter((p) => brandFilter.includes(p.brand));
if (inStockOnly) result = result.filter((p) => p.inStock ?? true);
const q = searchQuery.toLowerCase().trim();
if (q)
result = result.filter(
(p) =>
p.name.toLowerCase().includes(q) || p.brand.toLowerCase().includes(q)
);
switch (sortBy) {
case "price-asc":
result.sort((a, b) => a.price - b.price);
break;
case "price-desc":
result.sort((a, b) => b.price - a.price);
break;
case "brand-asc":
result.sort((a, b) => a.brand.localeCompare(b.brand));
break;
case "relevance":
default:
break;
}
return result;
}, [parts, brandFilter, sortBy, searchQuery, priceRange, inStockOnly]);
const filteredParts = useMemo(() => parts, [parts]);
const totalPages = Math.max(1, serverTotalPages);
const paginatedParts = filteredParts; // filteredParts should become just parts now (see below)
@@ -338,7 +292,7 @@ export default function PartsBrowseClient(props: {
if (!categoryId) {
alert(
`No CategoryId mapping found for role "${partRole}". Add it to catalogMappings.`
`No Category mapping found for role "${partRole}". Add it to catalogMappings.`
);
return;
}
@@ -453,7 +407,7 @@ export default function PartsBrowseClient(props: {
{!loading && !error && (
<SortBar
visibleRange={visibleRange}
totalCount={filteredParts.length}
totalCount={serverTotalElements}
searchQuery={searchQuery}
setSearchQuery={setSearchQuery}
sortBy={sortBy}
@@ -467,7 +421,7 @@ export default function PartsBrowseClient(props: {
</p>
) : error ? (
<p className="py-8 text-center text-sm text-red-400">{error}</p>
) : filteredParts.length === 0 ? (
) : serverTotalElements === 0 ? (
<p className="py-8 text-center text-sm text-zinc-500">
No parts found for this role yet.
</p>