makearmy-app/components/buying-guide/BuyingGuideProduct.tsx

96 lines
3.4 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { dxGet } from "./dx";
type EntryDetail = {
submission_id: string | number;
title?: string | null;
brand?: string | null;
model?: string | null;
body?: string | null;
specs?: any;
gallery?: { directus_files_id: { id: string; filename_disk?: string } }[];
thumb?: { id: string };
};
function assetUrl(id?: string) {
if (!id) return "";
return `/api/dx/assets/${id}`;
}
export default function BuyingGuideProduct({ id }: { id: string | number }) {
const [rec, setRec] = useState<EntryDetail | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
(async () => {
setLoading(true);
try {
const data = await dxGet<EntryDetail[]>("items/bg_entries", {
filter: JSON.stringify({ submission_id: { _eq: id } }),
fields: [
"submission_id",
"title",
"brand",
"model",
"body",
"specs",
"thumb.id",
"gallery.directus_files_id.id",
].join(","),
limit: 1,
});
setRec(data?.[0] || null);
} finally {
setLoading(false);
}
})();
}, [id]);
if (loading) return <div className="text-sm text-zinc-400">Loading</div>;
if (!rec) return <div className="text-sm text-zinc-400">Not found.</div>;
const title = rec.model || rec.title || "Product";
const images = [
rec.thumb?.id,
...(rec.gallery?.map(g => g.directus_files_id?.id).filter(Boolean) as string[]),
].filter(Boolean);
return (
<div className="space-y-4">
<div className="flex flex-wrap items-end justify-between gap-2">
<h2 className="text-xl font-semibold">
{rec.brand ? `${rec.brand} ` : ""}{title}
</h2>
<a
href={`/buying-guide/${rec.submission_id}`}
className="text-sm underline"
target="_blank"
rel="noopener noreferrer"
>
Open full page
</a>
</div>
{images.length > 0 && (
<div className="grid gap-2 grid-cols-2 sm:grid-cols-3 md:grid-cols-4">
{images.map((id) => (
// eslint-disable-next-line @next/next/no-img-element
<img key={id} src={assetUrl(id)} alt="" className="rounded-md border object-cover w-full aspect-[4/3]" />
))}
</div>
)}
{rec.body && (
<div className="prose prose-invert max-w-none" dangerouslySetInnerHTML={{ __html: rec.body }} />
)}
{rec.specs && (
<pre className="rounded-md border bg-muted/40 p-3 overflow-auto text-xs">
{JSON.stringify(rec.specs, null, 2)}
</pre>
)}
</div>
);
}