deckhearth/components/DashboardCardSpotlight.js
varutasu b9e840ff3a
Realign dashboard home nav and wire honest ownership stats (#164)
Flatten authenticated sidebar IA, move admin to the profile menu, right-align TopSearchBar actions, and replace placeholder dashboard panels with data from /api/user/stats and /api/user-cards.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-15 16:47:59 -05:00

154 lines
4.4 KiB
JavaScript

import Link from 'next/link';
import { VOCAB } from '../lib/collection-vocabulary.js';
/**
* Last-added card spotlight on /dashboard — real ownership data only.
* Market charts and watchlist ship in a follow-up convoy.
*/
export default function DashboardCardSpotlight({ card = null, loading = false }) {
if (loading) {
return (
<aside className="glass-panel rounded-2xl p-5 sm:p-6">
<div
className="aspect-[2.5/3.5] rounded-lg motion-essential animate-pulse mb-4"
style={{ backgroundColor: 'var(--bg-tertiary)' }}
aria-hidden="true"
/>
<div
className="h-4 rounded motion-essential animate-pulse mb-2"
style={{ backgroundColor: 'var(--bg-tertiary)' }}
/>
<div
className="h-4 rounded motion-essential animate-pulse w-2/3"
style={{ backgroundColor: 'var(--bg-tertiary)' }}
/>
</aside>
);
}
if (!card) {
return (
<aside className="glass-panel rounded-2xl p-5 sm:p-6">
<h2
className="text-lg font-bold mb-3"
style={{ color: 'var(--text-primary)' }}
>
Latest card
</h2>
<p className="text-sm mb-4" style={{ color: 'var(--text-secondary)' }}>
Add cards to {VOCAB.MY_COLLECTION} to see details here.
</p>
<Link href="/scanner">
<span
className="text-sm font-medium hover:underline"
style={{ color: 'var(--accent-ember)' }}
>
Open scanner
</span>
</Link>
</aside>
);
}
const cardId = card.card_id ?? card.id;
const marketPrice = card.market_price ?? card.marketPrice;
const priceLabel =
marketPrice != null && !Number.isNaN(Number(marketPrice))
? `$${Number(marketPrice).toFixed(2)}`
: '—';
return (
<aside className="glass-panel rounded-2xl p-5 sm:p-6 space-y-4">
<header>
<h2
className="text-lg font-bold"
style={{ color: 'var(--text-primary)' }}
>
Latest card
</h2>
</header>
<Link
href={`/card/${cardId}`}
className="card-grid-outer-glow aspect-[2.5/3.5] rounded-lg overflow-hidden block focus:outline-none focus:ring-2"
style={{
backgroundColor: 'var(--bg-tertiary)',
'--tw-ring-color': 'var(--accent-ember)',
}}
>
{card.image_url ? (
// eslint-disable-next-line @next/next/no-img-element
<img
src={card.image_url}
alt={card.name ?? 'Card'}
className="w-full h-full object-cover"
/>
) : (
<div
className="w-full h-full flex items-center justify-center p-4 text-center text-sm"
style={{ color: 'var(--text-secondary)' }}
>
{card.name ?? 'Card'}
</div>
)}
</Link>
<div>
<div
className="text-lg font-bold"
style={{ color: 'var(--text-primary)' }}
>
{card.name}
</div>
{card.set_name && (
<div className="text-sm" style={{ color: 'var(--text-secondary)' }}>
{card.set_name}
</div>
)}
</div>
<dl className="grid grid-cols-2 gap-x-4 gap-y-2 text-sm">
{card.rarity && (
<>
<dt style={{ color: 'var(--text-secondary)' }}>Rarity</dt>
<dd
className="font-semibold text-right"
style={{ color: 'var(--accent-ember)' }}
>
{card.rarity}
</dd>
</>
)}
{card.game && (
<>
<dt style={{ color: 'var(--text-secondary)' }}>Game</dt>
<dd
className="font-medium text-right"
style={{ color: 'var(--text-primary)' }}
>
{card.game}
</dd>
</>
)}
{card.quantity != null && (
<>
<dt style={{ color: 'var(--text-secondary)' }}>Owned</dt>
<dd
className="font-medium text-right"
style={{ color: 'var(--text-primary)' }}
>
{card.quantity}
</dd>
</>
)}
<dt style={{ color: 'var(--text-secondary)' }}>Market</dt>
<dd
className="font-semibold text-right"
style={{ color: 'var(--text-primary)' }}
>
{priceLabel}
</dd>
</dl>
</aside>
);
}