feat(25-02): add attribution display on catalog detail page
- GlobalItem interface extended with sourceUrl, imageCredit, imageSourceUrl fields - Attribution block below image: Photo credit and source link when present - Product page link (sourceUrl) at bottom of detail page - Image div mb-6 moved to attribution paragraph for consistent spacing
This commit is contained in:
@@ -10,6 +10,9 @@ interface GlobalItem {
|
|||||||
priceCents: number | null;
|
priceCents: number | null;
|
||||||
imageUrl: string | null;
|
imageUrl: string | null;
|
||||||
description: string | null;
|
description: string | null;
|
||||||
|
sourceUrl: string | null;
|
||||||
|
imageCredit: string | null;
|
||||||
|
imageSourceUrl: string | null;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ function GlobalItemDetail() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Image */}
|
{/* Image */}
|
||||||
<div className="aspect-[16/9] bg-gray-50 rounded-xl overflow-hidden mb-6">
|
<div className="aspect-[16/9] bg-gray-50 rounded-xl overflow-hidden">
|
||||||
{item.imageUrl ? (
|
{item.imageUrl ? (
|
||||||
<img
|
<img
|
||||||
src={item.imageUrl}
|
src={item.imageUrl}
|
||||||
@@ -84,6 +84,25 @@ function GlobalItemDetail() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Attribution */}
|
||||||
|
{(item.imageCredit || item.imageSourceUrl) && (
|
||||||
|
<p className="text-xs text-gray-400 mt-1 mb-6">
|
||||||
|
{item.imageCredit && <span>Photo: {item.imageCredit}</span>}
|
||||||
|
{item.imageCredit && item.imageSourceUrl && <span> · </span>}
|
||||||
|
{item.imageSourceUrl && (
|
||||||
|
<a
|
||||||
|
href={item.imageSourceUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="underline hover:text-gray-600 transition-colors"
|
||||||
|
>
|
||||||
|
Source
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{!(item.imageCredit || item.imageSourceUrl) && <div className="mb-6" />}
|
||||||
|
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<p className="text-xs font-medium text-gray-400 uppercase tracking-wide mb-1">
|
<p className="text-xs font-medium text-gray-400 uppercase tracking-wide mb-1">
|
||||||
@@ -169,6 +188,20 @@ function GlobalItemDetail() {
|
|||||||
<p className="text-gray-600 leading-relaxed">{item.description}</p>
|
<p className="text-gray-600 leading-relaxed">{item.description}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Product page link */}
|
||||||
|
{item.sourceUrl && (
|
||||||
|
<div className="mt-4">
|
||||||
|
<a
|
||||||
|
href={item.sourceUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-sm text-blue-500 hover:text-blue-600 underline transition-colors"
|
||||||
|
>
|
||||||
|
View product page →
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user