gallery fix
This commit is contained in:
183
resources/views/components/artwork-card.blade.php
Normal file
183
resources/views/components/artwork-card.blade.php
Normal file
@@ -0,0 +1,183 @@
|
||||
@props([
|
||||
'art',
|
||||
'loading' => 'lazy',
|
||||
'fetchpriority' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
if (isset($art) && (is_array($art) || $art instanceof Illuminate\Support\Collection || $art instanceof Illuminate\Database\Eloquent\Collection)) {
|
||||
$first = null;
|
||||
if (is_array($art)) {
|
||||
$first = reset($art);
|
||||
} elseif ($art instanceof Illuminate\Support\Collection || $art instanceof Illuminate\Database\Eloquent\Collection) {
|
||||
$first = $art->first();
|
||||
}
|
||||
if ($first) {
|
||||
$art = $first;
|
||||
}
|
||||
}
|
||||
|
||||
$title = trim((string) ($art->name ?? $art->title ?? 'Untitled artwork'));
|
||||
|
||||
$author = trim((string) (
|
||||
$art->uname
|
||||
?? $art->author_name
|
||||
?? $art->author
|
||||
?? ($art->user->name ?? null)
|
||||
?? ($art->user->username ?? null)
|
||||
?? 'Skinbase'
|
||||
));
|
||||
|
||||
$username = trim((string) (
|
||||
$art->username
|
||||
?? ($art->user->username ?? null)
|
||||
?? ''
|
||||
));
|
||||
|
||||
$category = trim((string) ($art->category_name ?? $art->category ?? ''));
|
||||
|
||||
$avatarUserId = $art->user->id ?? $art->user_id ?? null;
|
||||
$avatarHash = $art->user->profile->avatar_hash ?? $art->avatar_hash ?? null;
|
||||
$avatarUrl = \App\Support\AvatarUrl::forUser((int) ($avatarUserId ?? 0), $avatarHash, 40);
|
||||
|
||||
$license = trim((string) ($art->license ?? 'Standard'));
|
||||
$resolution = trim((string) ($art->resolution ?? ((isset($art->width, $art->height) && $art->width && $art->height) ? ($art->width . '×' . $art->height) : '')));
|
||||
|
||||
$safeInt = function ($value, $fallback = 0) {
|
||||
if (is_numeric($value)) {
|
||||
return (int) $value;
|
||||
}
|
||||
if (is_array($value)) {
|
||||
return count($value);
|
||||
}
|
||||
if (is_object($value)) {
|
||||
if (method_exists($value, 'count')) {
|
||||
return (int) $value->count();
|
||||
}
|
||||
if ($value instanceof Countable) {
|
||||
return (int) count($value);
|
||||
}
|
||||
}
|
||||
return (int) $fallback;
|
||||
};
|
||||
|
||||
$likes = $safeInt($art->likes ?? $art->favourites ?? 0);
|
||||
$comments = $safeInt($art->comments_count ?? $art->comment_count ?? $art->comments ?? 0);
|
||||
|
||||
$imgSrc = (string) ($art->thumb ?? $art->thumbnail_url ?? '/images/placeholder.jpg');
|
||||
$imgSrcset = (string) ($art->thumb_srcset ?? $art->thumbnail_srcset ?? $imgSrc);
|
||||
$imgAvifSrcset = (string) ($art->thumb_avif_srcset ?? $imgSrcset);
|
||||
$imgWebpSrcset = (string) ($art->thumb_webp_srcset ?? $imgSrcset);
|
||||
|
||||
$resolveDimension = function ($value, string $field, $fallback) {
|
||||
if (is_numeric($value)) {
|
||||
return (int) $value;
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$current = reset($value);
|
||||
return is_numeric($current) ? (int) $current : (int) $fallback;
|
||||
}
|
||||
if (is_object($value)) {
|
||||
if (method_exists($value, 'first')) {
|
||||
$first = $value->first();
|
||||
if (is_object($first) && isset($first->{$field})) {
|
||||
return (int) ($first->{$field} ?: $fallback);
|
||||
}
|
||||
}
|
||||
if (isset($value->{$field})) {
|
||||
return (int) $value->{$field};
|
||||
}
|
||||
}
|
||||
return (int) $fallback;
|
||||
};
|
||||
|
||||
$imgWidth = max(1, $resolveDimension($art->width ?? null, 'width', 800));
|
||||
$imgHeight = max(1, $resolveDimension($art->height ?? null, 'height', 600));
|
||||
$imgAspectRatio = $imgWidth . ' / ' . $imgHeight;
|
||||
|
||||
$contentUrl = $imgSrc;
|
||||
$cardUrl = (string) ($art->url ?? '');
|
||||
if ($cardUrl === '' || $cardUrl === '#') {
|
||||
if (isset($art->id) && is_numeric($art->id)) {
|
||||
$cardUrl = '/art/' . (int) $art->id . '/' . \Illuminate\Support\Str::slug($title);
|
||||
} else {
|
||||
$cardUrl = '#';
|
||||
}
|
||||
}
|
||||
$authorUrl = $username !== '' ? '/@' . strtolower($username) : null;
|
||||
|
||||
$metaParts = [];
|
||||
if ($resolution !== '') {
|
||||
$metaParts[] = $resolution;
|
||||
}
|
||||
if ($category !== '') {
|
||||
$metaParts[] = $category;
|
||||
}
|
||||
if ($license !== '') {
|
||||
$metaParts[] = $license;
|
||||
}
|
||||
@endphp
|
||||
|
||||
<article class="nova-card gallery-item artwork" itemscope itemtype="https://schema.org/ImageObject">
|
||||
<meta itemprop="name" content="{{ $title }}">
|
||||
<meta itemprop="contentUrl" content="{{ $contentUrl }}">
|
||||
<meta itemprop="creator" content="{{ $author }}">
|
||||
<meta itemprop="license" content="{{ $license }}">
|
||||
|
||||
<a href="{{ $cardUrl }}" itemprop="url" class="group relative block overflow-hidden rounded-2xl ring-1 ring-white/5 bg-black/20 shadow-lg shadow-black/40 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">
|
||||
|
||||
@if($category !== '')
|
||||
<div class="absolute left-3 top-3 z-30 rounded-md bg-black/55 px-2 py-1 text-xs text-white backdrop-blur-sm">{{ $category }}</div>
|
||||
@endif
|
||||
|
||||
<div class="nova-card-media relative overflow-hidden bg-neutral-900" style="aspect-ratio: {{ $imgAspectRatio }};">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-white/10 via-white/5 to-transparent"></div>
|
||||
<picture>
|
||||
<source srcset="{{ $imgAvifSrcset }}" type="image/avif">
|
||||
<source srcset="{{ $imgWebpSrcset }}" type="image/webp">
|
||||
<img
|
||||
src="{{ $imgSrc }}"
|
||||
srcset="{{ $imgSrcset }}"
|
||||
sizes="(max-width: 768px) 50vw, (max-width: 1280px) 33vw, 20vw"
|
||||
loading="{{ $loading }}"
|
||||
decoding="{{ $loading === 'eager' ? 'sync' : 'async' }}"
|
||||
@if($fetchpriority) fetchpriority="{{ $fetchpriority }}" @endif
|
||||
@if($loading !== 'eager') data-blur-preview @endif
|
||||
alt="{{ e($title) }}"
|
||||
width="{{ $imgWidth }}"
|
||||
height="{{ $imgHeight }}"
|
||||
class="h-full w-full object-cover transition-[transform,filter] duration-300 ease-out group-hover:scale-[1.04]"
|
||||
itemprop="thumbnailUrl"
|
||||
/>
|
||||
</picture>
|
||||
|
||||
<div class="absolute right-3 top-3 z-30 flex items-center gap-2 opacity-0 transition-opacity duration-200 group-hover:opacity-100 group-focus-visible:opacity-100">
|
||||
<span class="inline-flex items-center rounded-md bg-black/60 px-2 py-1 text-[11px] font-medium text-white ring-1 ring-white/10">View</span>
|
||||
@if($authorUrl)
|
||||
<span class="inline-flex items-center rounded-md bg-black/60 px-2 py-1 text-[11px] font-medium text-white ring-1 ring-white/10">Profile</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="pointer-events-none absolute inset-x-0 bottom-0 z-20 bg-gradient-to-t from-black/80 via-black/40 to-transparent p-3 backdrop-blur-[2px] opacity-100 transition-opacity duration-200 md:opacity-0 md:group-hover:opacity-100 md:group-focus-visible:opacity-100">
|
||||
<div class="truncate text-sm font-semibold text-white">{{ $title }}</div>
|
||||
<div class="mt-1 flex items-center justify-between gap-3 text-xs text-white/80">
|
||||
<span class="truncate flex items-center gap-2">
|
||||
<img src="{{ $avatarUrl }}" alt="Avatar of {{ e($author) }}" class="w-6 h-6 rounded-full object-cover">
|
||||
<span class="truncate">
|
||||
<span>{{ $author }}</span>
|
||||
@if($username !== '')
|
||||
<span class="text-white/60">{{ '@' . $username }}</span>
|
||||
@endif
|
||||
</span>
|
||||
</span>
|
||||
<span class="shrink-0">❤ {{ $likes }} · 💬 {{ $comments }}</span>
|
||||
</div>
|
||||
@if(!empty($metaParts))
|
||||
<div class="mt-1 text-[11px] text-white/70">{{ implode(' • ', $metaParts) }}</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="sr-only">{{ $title }} by {{ $author }}</span>
|
||||
</a>
|
||||
</article>
|
||||
Reference in New Issue
Block a user