Files
SkinbaseNova/resources/views/artworks/show.blade.php

267 lines
13 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@extends('layouts.nova')
@php
use App\Banner;
use App\Models\Category;
use Illuminate\Pagination\LengthAwarePaginator;
// Determine a sensible category/context for this artwork so the
// legacy layout (sidebar + hero) can be rendered similarly to
// category listing pages.
$category = $artwork->categories->first() ?? null;
$contentType = $category ? $category->contentType : null;
if ($contentType) {
$rootCategories = Category::where('content_type_id', $contentType->id)
->whereNull('parent_id')
->orderBy('sort_order')
->get();
} else {
$rootCategories = collect();
}
$subcategories = $category ? $category->children()->orderBy('sort_order')->get() : collect();
// Provide an empty paginator to satisfy any shared pagination partials
$artworks = new LengthAwarePaginator([], 0, 24, 1, ['path' => request()->url()]);
@endphp
@section('content')
<div class="container-fluid legacy-page">
@php Banner::ShowResponsiveAd(); @endphp
<div class="pt-0">
<div class="mx-auto w-full">
<div class="flex min-h-[calc(100vh-64px)]">
<!-- SIDEBAR -->
<aside id="sidebar" class="hidden md:block w-72 shrink-0 border-r border-neutral-800 bg-nova-900/60 backdrop-blur-sm">
<div class="p-4">
<button class="w-full h-12 rounded-xl bg-white/5 hover:bg-white/7 border border-white/5 flex items-center gap-3 px-4">
<span class="w-8 h-8 rounded-lg bg-white/5 inline-flex items-center justify-center">
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h16"/></svg>
</span>
<span class="text-sm text-white/90">Menu</span>
</button>
<div class="mt-6 text-sm text-neutral-400">
<div class="font-semibold text-white/80 mb-2">Main Categories:</div>
<ul class="space-y-2">
@foreach($rootCategories as $root)
<li>
<a class="flex items-center gap-2 hover:text-white" href="{{ $root->url }}"><span class="opacity-70">📁</span> {{ $root->name }}</a>
</li>
@endforeach
</ul>
<div class="mt-6 font-semibold text-white/80 mb-2">Browse Subcategories:</div>
<ul class="space-y-2 pr-2">
@foreach($subcategories as $sub)
<li><a class="hover:text-white {{ $category && $sub->id === $category->id ? 'font-semibold text-white' : 'text-neutral-400' }}" href="{{ $sub->url }}">{{ $sub->name }}</a></li>
@endforeach
</ul>
</div>
</div>
</aside>
<!-- MAIN -->
<main class="flex-1">
<div class="relative overflow-hidden nb-hero-radial">
<div class="absolute inset-0 opacity-35"></div>
<div class="relative px-6 py-8 md:px-10 md:py-10">
<div class="text-sm text-neutral-400">
@if($contentType)
<a class="hover:text-white" href="/{{ $contentType->slug }}">{{ $contentType->name }}</a>
@endif
@if($category)
@foreach ($category->breadcrumbs as $crumb)
<span class="opacity-50"></span> <a class="hover:text-white" href="{{ $crumb->url }}">{{ $crumb->name }}</a>
@endforeach
@endif
</div>
@php
$breadcrumbs = $category ? (is_array($category->breadcrumbs) ? $category->breadcrumbs : [$category]) : [];
$headerCategory = !empty($breadcrumbs) ? end($breadcrumbs) : ($category ?? null);
@endphp
<h1 class="mt-2 text-3xl md:text-4xl font-semibold tracking-tight text-white/95">{{ $headerCategory->name ?? $artwork->title }}</h1>
<section class="mt-5 bg-white/5 border border-white/10 rounded-2xl shadow-lg">
<div class="p-5 md:p-6">
<div class="text-lg font-semibold text-white/90">{{ $artwork->title }}</div>
<p class="mt-2 text-sm leading-6 text-neutral-400">{!! $artwork->description ?? ($headerCategory->description ?? ($contentType->name ?? 'Artwork')) !!}</p>
</div>
</section>
<div class="absolute left-0 right-0 bottom-0 h-36 nb-hero-fade pointer-events-none" aria-hidden="true"></div>
</div>
</div>
<!-- Artwork detail -->
<section class="px-6 pb-10 md:px-10">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="col-span-2">
<div class="rounded-2xl overflow-hidden bg-black/20 border border-white/10 shadow-lg">
<img src="{{ $artwork->thumbnail_url ?? '/images/placeholder.jpg' }}" alt="{{ $artwork->title }}" class="w-full h-auto object-contain" />
</div>
</div>
<aside class="p-4 bg-white/3 rounded-2xl border border-white/6">
<h3 class="font-semibold text-white">{{ $artwork->title }}</h3>
<p class="text-sm text-neutral-400 mt-2">{!! $artwork->description ?? 'No description provided.' !!}</p>
<div class="mt-4">
<a href="{{ $artwork->file_path ?? '#' }}" class="inline-block px-4 py-2 bg-indigo-600 text-white rounded">Download</a>
</div>
</aside>
</div>
@if(isset($similarItems) && $similarItems->isNotEmpty())
<section class="mt-8" data-similar-analytics data-algo-version="{{ $similarAlgoVersion ?? '' }}" data-artwork-id="{{ $artwork->id }}">
<div class="mb-3 flex items-center justify-between">
<h2 class="text-lg md:text-xl font-semibold text-white/95">Similar artworks</h2>
</div>
<div class="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4">
@foreach($similarItems as $item)
<article class="rounded-2xl overflow-hidden border border-white/10 bg-black/20 shadow-lg">
<a
href="{{ $item['url'] }}"
class="group block"
data-similar-click
data-similar-id="{{ $item['id'] }}"
data-similar-title="{{ e($item['title']) }}"
>
<div class="aspect-[16/10] bg-neutral-900">
<img
src="{{ $item['thumb'] }}"
@if(!empty($item['thumb_srcset'])) srcset="{{ $item['thumb_srcset'] }}" @endif
loading="lazy"
decoding="async"
alt="{{ $item['title'] }}"
class="h-full w-full object-cover transition group-hover:scale-[1.02]"
/>
</div>
<div class="p-3">
<div class="truncate text-sm font-medium text-white/90">{{ $item['title'] }}</div>
@if(!empty($item['author']))
<div class="mt-1 truncate text-xs text-neutral-400">by {{ $item['author'] }}</div>
@endif
</div>
</a>
</article>
@endforeach
</div>
</section>
@endif
</section>
</main>
</div>
</div>
</div>
</div> <!-- end .legacy-page -->
@php
$jsonLdType = str_starts_with((string) ($artwork->mime_type ?? ''), 'image/') ? 'ImageObject' : 'CreativeWork';
$keywords = $artwork->tags()->pluck('name')->values()->all();
$jsonLd = [
'@context' => 'https://schema.org',
'@type' => $jsonLdType,
'name' => (string) $artwork->title,
'description' => trim(strip_tags((string) ($artwork->description ?? ''))),
'author' => [
'@type' => 'Person',
'name' => (string) optional($artwork->user)->name,
],
'datePublished' => optional($artwork->published_at)->toAtomString(),
'url' => request()->url(),
'image' => (string) ($artwork->thumbnail_url ?? ''),
'keywords' => $keywords,
];
@endphp
<script type="application/ld+json">{!! json_encode($jsonLd, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) !!}</script>
@if(isset($similarItems) && $similarItems->isNotEmpty())
<script>
(function () {
var section = document.querySelector('[data-similar-analytics]');
if (!section) return;
var algoVersion = section.getAttribute('data-algo-version') || '';
var sourceArtworkId = section.getAttribute('data-artwork-id') || '';
var anchors = section.querySelectorAll('[data-similar-click]');
var impressionPayload = {
event: 'similar_artworks_impression',
source_artwork_id: sourceArtworkId,
algo_version: algoVersion,
item_ids: Array.prototype.map.call(anchors, function (anchor) {
return anchor.getAttribute('data-similar-id');
})
};
window.dataLayer = window.dataLayer || [];
function sendAnalytics(payload) {
var endpoint = '/api/analytics/similar-artworks';
var body = JSON.stringify(payload);
if (navigator.sendBeacon) {
var blob = new Blob([body], { type: 'application/json' });
navigator.sendBeacon(endpoint, blob);
return;
}
fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: body,
keepalive: true
}).catch(function () {
// ignore analytics transport errors
});
}
window.dataLayer.push(impressionPayload);
anchors.forEach(function (anchor, index) {
sendAnalytics({
event_type: 'impression',
source_artwork_id: Number(sourceArtworkId),
similar_artwork_id: Number(anchor.getAttribute('data-similar-id')),
algo_version: algoVersion,
position: index + 1,
items_count: anchors.length
});
});
anchors.forEach(function (anchor, index) {
anchor.addEventListener('click', function () {
window.dataLayer.push({
event: 'similar_artworks_click',
source_artwork_id: sourceArtworkId,
algo_version: algoVersion,
similar_artwork_id: anchor.getAttribute('data-similar-id'),
similar_artwork_title: anchor.getAttribute('data-similar-title') || '',
position: index + 1
});
sendAnalytics({
event_type: 'click',
source_artwork_id: Number(sourceArtworkId),
similar_artwork_id: Number(anchor.getAttribute('data-similar-id')),
algo_version: algoVersion,
position: index + 1
});
});
});
})();
</script>
@endif
@endsection
@push('styles')
<style>
.nb-hero-fade {
background: linear-gradient(180deg, rgba(17,24,39,0) 0%, rgba(7,10,15,0.9) 60%, rgba(7,10,15,1) 100%);
}
</style>
@endpush