Files
SkinbaseNova/resources/views/web/home/sections/artwork-card.blade.php

93 lines
5.9 KiB
PHP

@php
$artFallback = 'https://files.skinbase.org/default/missing_md.webp';
$avatarFallback = 'https://files.skinbase.org/default/avatar_default.webp';
$artwork = is_array($item ?? null) ? $item : [];
$titleText = (string) ($artwork['title'] ?? $artwork['name'] ?? 'Untitled');
$artworkUrl = (string) ($artwork['url'] ?? '#');
$thumbUrl = (string) ($artwork['thumb'] ?? $artwork['thumb_url'] ?? $artFallback);
$authorName = (string) ($artwork['author'] ?? 'Artist');
$authorUsername = (string) ($artwork['author_username'] ?? $artwork['username'] ?? '');
$authorAvatar = (string) ($artwork['author_avatar'] ?? $artwork['avatar_url'] ?? $avatarFallback);
$authorUrl = !empty($artwork['publisher']['profile_url'] ?? null)
? (string) $artwork['publisher']['profile_url']
: ($authorUsername !== '' ? route('profile.show', ['username' => strtolower($authorUsername)]) : null);
$metricBadge = is_array($artwork['metric_badge'] ?? null) ? $artwork['metric_badge'] : null;
$maturity = is_array($artwork['maturity'] ?? null) ? $artwork['maturity'] : [];
$shouldBlur = (bool) ($maturity['should_blur'] ?? false);
$cardImageId = ($idPrefix ?? 'artwork') . '-image-' . ($index ?? 0);
$medalScore = (int) data_get($artwork, 'medals.score_30d', data_get($artwork, 'medals.score', 0));
$cardFrameClass = ($layout ?? 'grid') === 'rail'
? 'aspect-video'
: 'aspect-[4/5] sm:aspect-[5/4] lg:aspect-video';
@endphp
<article class="{{ ($layout ?? 'grid') === 'rail' ? 'min-w-[72%] snap-start sm:min-w-[44%] lg:min-w-0' : 'min-w-0' }}">
<a href="{{ $artworkUrl }}" class="group relative block overflow-hidden rounded-2xl bg-black/20 shadow-lg shadow-black/40 ring-1 ring-white/5 transition-all duration-200 ease-out hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-300/70">
<div class="relative {{ $cardFrameClass }} overflow-hidden bg-neutral-900">
<div class="pointer-events-none absolute inset-0 z-10 bg-gradient-to-br from-white/10 via-white/5 to-transparent"></div>
<img
id="{{ $cardImageId }}"
src="{{ $thumbUrl }}"
@if (!empty($artwork['thumb_srcset']))
srcset="{{ $artwork['thumb_srcset'] }}"
sizes="{{ $sizes ?? '100vw' }}"
@endif
alt="{{ $titleText }}"
width="{{ max(1, (int) ($artwork['width'] ?? 1600)) }}"
height="{{ max(1, (int) ($artwork['height'] ?? 900)) }}"
class="h-full w-full object-cover transition-[transform,filter] duration-300 ease-out group-hover:scale-[1.04] {{ $shouldBlur ? 'blur-2xl scale-[1.03]' : '' }}"
loading="lazy"
decoding="async"
>
@if (!empty($badge))
<div class="absolute left-3 top-3 z-30">
<span class="inline-flex items-center rounded-md px-2 py-1 text-[11px] font-bold ring-1 ring-white/10 backdrop-blur-sm {{ $badgeClass ?? 'bg-sky-500/80 text-white' }}">
{{ $badge }}
</span>
</div>
@elseif ($metricBadge && !empty($metricBadge['label']))
<div class="absolute left-3 top-3 z-30">
<span class="inline-flex items-center rounded-full border border-sky-300/30 bg-sky-500/14 px-2.5 py-1 text-[11px] font-semibold text-sky-100 ring-1 ring-sky-300/20 backdrop-blur-sm">
{{ $metricBadge['label'] }}
</span>
</div>
@endif
@if ($medalScore > 0)
<div class="absolute right-3 top-3 z-30">
<span class="inline-flex items-center rounded-full border border-amber-300/20 bg-amber-300/12 px-2.5 py-1 text-[11px] font-semibold text-amber-100 ring-1 ring-amber-300/20 backdrop-blur-sm">
Medal {{ number_format($medalScore) }}
</span>
</div>
@endif
@if ($shouldBlur)
<div class="absolute inset-0 z-20 flex items-center justify-center bg-slate-950/55 p-4" data-home-mature-overlay>
<div class="rounded-2xl border border-white/10 bg-black/45 px-4 py-4 text-center shadow-2xl backdrop-blur-md">
<p class="text-xs font-semibold uppercase tracking-[0.18em] text-white/70">Mature content</p>
<p class="mt-2 max-w-[16rem] text-sm text-white/90">This artwork may contain mature material.</p>
<button
type="button"
data-home-mature-toggle="{{ $cardImageId }}"
class="mt-4 inline-flex items-center rounded-full border border-white/15 bg-white/10 px-4 py-2 text-xs font-semibold uppercase tracking-[0.16em] text-white transition hover:bg-white/20"
>
Reveal image
</button>
</div>
</div>
@endif
<div class="pointer-events-none absolute inset-x-0 bottom-0 z-20 bg-gradient-to-t from-black/85 via-black/45 to-transparent p-3 backdrop-blur-[2px] opacity-100 transition-opacity duration-200 md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100">
<div class="truncate text-sm font-semibold text-white">{{ $titleText }}</div>
<div class="mt-1 flex items-center gap-2 text-xs text-white/80">
<img src="{{ $authorAvatar }}" alt="{{ $authorName }}" class="h-6 w-6 shrink-0 rounded-full object-cover" loading="lazy" decoding="async">
<span class="truncate">{{ $authorName }}</span>
@if ($authorUsername !== '')
<span class="shrink-0 text-white/50">{{ $authorUsername }}</span>
@endif
</div>
</div>
</div>
</a>
</article>