Files
germanandClaude Opus 4.8 ad35d4e992
Deploy / deploy (push) Failing after 5s
feat(#3): frontend scaffold (Next.js 14 App Router, TS, Tailwind, галерея)
Каркас витрины дизайнера Ники: главная (hero + сетка галереи),
страница работы (детали + место под аукцион), список аукционов,
подписка-заглушка. Клиент к backend /api с graceful-фолбэком на
демо-работы при недоступном API. Standalone-сборка + Dockerfile.
Сборка npm run build и tsc --noEmit проходят.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 19:42:13 +03:00

56 lines
2.0 KiB
TypeScript

import Image from 'next/image';
import Link from 'next/link';
import type { Work } from '@/lib/types';
import { coverOf, formatPrice } from '@/lib/format';
export default function WorkCard({ work }: { work: Work }) {
const href = `/works/${work.slug || work.id}`;
const cover = coverOf(work, 800, 1000);
const onAuction = work.auction_mode !== 'none';
const sold = work.status === 'sold';
return (
<Link href={href} className="group block animate-fade-in">
<figure className="relative overflow-hidden bg-line/40 dark:bg-white/5">
{/* Пропорция портретного холста */}
<div className="relative aspect-[4/5] w-full">
<Image
src={cover}
alt={work.title}
fill
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
className="object-cover transition-transform duration-700 ease-gallery group-hover:scale-[1.03]"
/>
</div>
{(onAuction || sold) && (
<figcaption className="absolute left-3 top-3 flex gap-2">
{sold && (
<span className="rounded-full bg-ink/85 px-3 py-1 text-[11px] uppercase tracking-wide text-paper">
Продано
</span>
)}
{onAuction && !sold && (
<span className="rounded-full bg-accent/90 px-3 py-1 text-[11px] uppercase tracking-wide text-white">
Аукцион
</span>
)}
</figcaption>
)}
</figure>
<div className="mt-4 flex items-baseline justify-between gap-4">
<div className="min-w-0">
<h3 className="truncate font-serif text-xl tracking-tightest">
{work.title}
</h3>
<p className="mt-0.5 text-sm text-muted">
{[work.medium, work.year].filter(Boolean).join(' · ') || 'Работа'}
</p>
</div>
<p className="shrink-0 text-sm text-accent">{formatPrice(work.price)}</p>
</div>
</Link>
);
}