112 lines
7.3 KiB
PHP
112 lines
7.3 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));
|
|
@endphp
|
|
|
|
<article class="{{ ($layout ?? 'grid') === 'rail' ? 'min-w-[72%] snap-start sm:min-w-[44%] lg:min-w-0' : 'min-w-0' }}">
|
|
<div class="group 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-within:ring-2 focus-within:ring-sky-300/70">
|
|
<a href="{{ $artworkUrl }}" class="relative block overflow-hidden">
|
|
<div class="relative aspect-video 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>
|
|
|
|
<div class="flex items-start justify-between gap-3 border-t border-white/5 bg-slate-950/40 px-3 py-3">
|
|
<div class="min-w-0">
|
|
<a href="{{ $artworkUrl }}" class="block truncate text-sm font-semibold text-white transition hover:text-sky-100">{{ $titleText }}</a>
|
|
<div class="mt-1 flex items-center gap-2 text-xs text-soft">
|
|
@if ($authorUrl)
|
|
<a href="{{ $authorUrl }}" class="truncate text-nova-200 transition hover:text-white">{{ $authorName }}</a>
|
|
@else
|
|
<span class="truncate">{{ $authorName }}</span>
|
|
@endif
|
|
@if (!empty($artwork['category_name']))
|
|
<span class="shrink-0 text-white/35">•</span>
|
|
<span class="truncate">{{ $artwork['category_name'] }}</span>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
<a href="{{ $artworkUrl }}" class="shrink-0 rounded-full border border-white/10 bg-white/[0.04] px-3 py-1.5 text-[11px] font-semibold uppercase tracking-[0.14em] text-white/80 transition hover:border-white/20 hover:bg-white/[0.08] hover:text-white">
|
|
View
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</article> |