productSlug fixes
CI / test (push) Successful in 7s

This commit is contained in:
2026-01-26 07:10:37 -05:00
parent b09ccc542e
commit fb2effca47
2 changed files with 44 additions and 11 deletions
+9 -3
View File
@@ -295,7 +295,7 @@ function buildAssemblyRows(params: {
rows.push({
key: `${groupLabel}-${paths.complete}`,
kind: "category",
label: "Complete Assembly (Fastest)",
label: "Completed Lower (Fastest)",
categoryId: paths.complete,
indent: 0,
pill: mode === "complete" ? "Selected" : undefined,
@@ -1625,9 +1625,15 @@ function GunbuilderPageContent() {
</div>
{selectedPart ? (
<div className="text-[0.7rem] text-zinc-500 line-clamp-1">
<Link
href={`/parts/p/${canonicalPlatform}/${category.id}/${selectedPart.id}-${selectedPart.name
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/(^-|-$)/g, "")}`}
className="text-[0.7rem] text-zinc-500 hover:text-amber-300 hover:underline line-clamp-1 transition-colors"
>
{selectedPart.name}
</div>
</Link>
) : (
<div className="text-[0.7rem] text-zinc-600">
No part selected
@@ -18,6 +18,7 @@ type OfferFromApi = {
price?: number | null;
originalPrice?: number | null;
buyUrl?: string | null;
buyShortUrl?: string | null;
inStock?: boolean | null;
lastUpdated?: string | null;
};
@@ -29,6 +30,7 @@ type GunbuilderProductFromApi = {
platform: string;
partRole: string;
price: number | null;
caliber?: string | null;
// Optional (legacy fallback label if product.offers is missing)
merchantName?: string | null;
@@ -37,6 +39,7 @@ type GunbuilderProductFromApi = {
mainImageUrl?: string | null;
buyUrl?: string | null;
buyShortUrl?: string | null;
inStock?: boolean | null;
shortDescription?: string | null;
@@ -249,6 +252,12 @@ export default function ProductDetailsPage() {
}
const data: GunbuilderProductFromApi = await res.json();
console.log('[DEBUG] Product from API:', {
id: data.id,
name: data.name,
buyUrl: data.buyUrl,
buyShortUrl: data.buyShortUrl
});
setProduct(data);
} catch (err: any) {
if (err?.name === "AbortError") return;
@@ -286,6 +295,7 @@ export default function ProductDetailsPage() {
}
const data: OfferFromApi[] = await res.json();
console.log('[DEBUG] Offers from API:', data);
setOffersFromApi(Array.isArray(data) ? data : []);
} catch (err: any) {
if (err?.name === "AbortError") return;
@@ -336,14 +346,23 @@ export default function ProductDetailsPage() {
* - Fallback to legacy single-offer derived from product if needed
*/
const offers = useMemo(() => {
if (offersFromApi.length > 0) return sortOffers(offersFromApi);
if (offersFromApi.length > 0) {
console.log('[DEBUG] Using offers from API, first offer:', offersFromApi[0]);
const fallbackShortUrl = product?.buyShortUrl ?? null;
const normalized = offersFromApi.map((offer) => ({
...offer,
buyShortUrl: offer.buyShortUrl || fallbackShortUrl,
}));
return sortOffers(normalized);
}
if (product?.buyUrl) {
if (product?.buyUrl || product?.buyShortUrl) {
console.log('[DEBUG] Using fallback from product, buyShortUrl:', product.buyShortUrl, 'buyUrl:', product.buyUrl);
return sortOffers([
{
merchantName: product.merchantName ?? "Retailer",
price: product.price,
buyUrl: product.buyUrl,
buyUrl: product.buyShortUrl || product.buyUrl,
inStock: product.inStock ?? true,
},
]);
@@ -565,6 +584,14 @@ export default function ProductDetailsPage() {
{product.platform || platform}
</span>
</span>
{product.caliber && (
<span className="rounded border border-zinc-800 bg-zinc-900/60 px-2 py-1 text-zinc-300">
Caliber:{" "}
<span className="font-semibold text-zinc-100">
{product.caliber}
</span>
</span>
)}
<span className="rounded border border-zinc-800 bg-zinc-900/60 px-2 py-1 text-zinc-300">
Role:{" "}
<span className="font-semibold text-zinc-100">
@@ -666,9 +693,9 @@ export default function ProductDetailsPage() {
{o.price != null ? `$${o.price.toFixed(2)}` : "—"}
</td>
<td className="px-3 py-2 text-right">
{o.buyUrl ? (
{(o.buyShortUrl || o.buyUrl) ? (
<a
href={o.buyUrl}
href={o.buyShortUrl || o.buyUrl}
target="_blank"
rel="noreferrer"
className="inline-flex items-center justify-center rounded-md bg-amber-400 px-3 py-1.5 text-xs font-semibold text-black hover:bg-amber-300"
@@ -692,10 +719,10 @@ export default function ProductDetailsPage() {
)}
{/* Best Offer CTA */}
{bestOffer?.buyUrl ? (
{(bestOffer?.buyShortUrl || bestOffer?.buyUrl) ? (
<div className="mt-3 flex justify-end">
<a
href={bestOffer.buyUrl}
href={bestOffer.buyShortUrl || bestOffer.buyUrl}
target="_blank"
rel="noreferrer"
className="rounded-md border border-zinc-700 bg-zinc-900/70 px-4 py-2 text-sm font-semibold text-zinc-200 hover:bg-zinc-800"
@@ -753,4 +780,4 @@ export default function ProductDetailsPage() {
</div>
</main>
);
}
}