175 lines
7.7 KiB
PHP
175 lines
7.7 KiB
PHP
@extends('layouts.nova')
|
|
|
|
@section('content')
|
|
@php
|
|
$currentCategory = (string) (request()->route('category') ?? request()->query('category', ''));
|
|
$storyTabs = [
|
|
['label' => '🔥 Trending', 'href' => '#trending'],
|
|
['label' => '🚀 New & Hot', 'href' => '#featured'],
|
|
['label' => '⭐ Best', 'href' => '#latest'],
|
|
['label' => '🕐 Latest', 'href' => '#latest'],
|
|
];
|
|
@endphp
|
|
|
|
<x-nova-page-header
|
|
section="Stories"
|
|
title="Browse Stories"
|
|
icon="fa-newspaper"
|
|
:breadcrumbs="$breadcrumbs ?? collect()"
|
|
description="List of all published stories across tutorials, creator journals, interviews, and project breakdowns."
|
|
contentClass="max-w-3xl"
|
|
actionsClass="lg:pt-8"
|
|
>
|
|
<x-slot name="actions">
|
|
<a href="{{ route('creator.stories.create') }}"
|
|
class="inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium border border-white/[0.08] bg-white/[0.04] text-white/70 hover:bg-white/[0.08] hover:text-white transition-colors">
|
|
<i class="fa-solid fa-pen-nib text-xs"></i>
|
|
Write Story
|
|
</a>
|
|
</x-slot>
|
|
</x-nova-page-header>
|
|
|
|
<div class="border-b border-white/10 bg-nova-900/90 backdrop-blur-md">
|
|
<div class="px-6 md:px-10">
|
|
<nav data-stories-tabs class="flex items-center gap-0 -mb-px nb-scrollbar-none overflow-x-auto" role="tablist" aria-label="Stories sections">
|
|
@foreach($storyTabs as $index => $tab)
|
|
<a href="{{ $tab['href'] }}"
|
|
data-stories-tab
|
|
data-target="{{ ltrim($tab['href'], '#') }}"
|
|
role="tab"
|
|
aria-selected="{{ $index === 0 ? 'true' : 'false' }}"
|
|
class="relative whitespace-nowrap px-5 py-4 text-sm font-medium {{ $index === 0 ? 'text-white' : 'text-neutral-400 hover:text-white' }}">
|
|
{{ $tab['label'] }}
|
|
<span data-tab-indicator class="absolute bottom-0 left-0 right-0 h-0.5 {{ $index === 0 ? 'bg-accent scale-x-100' : 'bg-transparent scale-x-0' }} transition-transform duration-300 origin-left rounded-full"></span>
|
|
</a>
|
|
@endforeach
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="border-b border-white/10 bg-nova-900/70">
|
|
<div class="px-6 md:px-10 py-6">
|
|
<div class="flex gap-3 overflow-x-auto nb-scrollbar-none pb-1">
|
|
<a href="{{ route('stories.index') }}" class="whitespace-nowrap rounded-full px-3 py-1.5 text-sm font-semibold transition-colors {{ $currentCategory === '' ? 'bg-orange-500 text-white' : 'border border-white/10 bg-white/[0.05] text-white/70 hover:bg-white/[0.1] hover:text-white' }}">All</a>
|
|
@foreach($categories as $category)
|
|
<a href="{{ route('stories.category', $category['slug']) }}" class="whitespace-nowrap rounded-full px-3 py-1.5 text-sm transition-colors {{ $currentCategory === $category['slug'] ? 'bg-orange-500 text-white font-semibold' : 'border border-white/10 bg-white/[0.05] text-white/70 hover:bg-white/[0.1] hover:text-white' }}">
|
|
{{ $category['name'] }}
|
|
</a>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="px-6 pb-16 md:px-10">
|
|
<div class="space-y-10">
|
|
@if($featured)
|
|
<section id="featured" class="overflow-hidden rounded-xl border border-gray-700 bg-gray-800/70 shadow-lg">
|
|
<a href="{{ route('stories.show', $featured->slug) }}" class="grid gap-0 lg:grid-cols-2">
|
|
<div class="aspect-video overflow-hidden bg-gray-900">
|
|
@if($featured->cover_url)
|
|
<img src="{{ $featured->cover_url }}" alt="{{ $featured->title }}" class="h-full w-full object-cover transition-transform duration-300 group-hover:scale-105" />
|
|
@endif
|
|
</div>
|
|
<div class="flex flex-col justify-center space-y-4 p-6">
|
|
<span class="inline-flex w-fit rounded-full border border-sky-400/30 bg-sky-500/10 px-3 py-1 text-xs font-semibold text-sky-300">Featured Story</span>
|
|
<h2 class="text-2xl font-bold text-white">{{ $featured->title }}</h2>
|
|
<p class="text-gray-300">{{ $featured->excerpt }}</p>
|
|
<p class="text-sm text-gray-400">by @{{ $featured->creator?->username ?? 'unknown' }} • {{ $featured->reading_time }} min read • {{ number_format((int) $featured->views) }} views</p>
|
|
</div>
|
|
</a>
|
|
</section>
|
|
@endif
|
|
|
|
<section id="trending">
|
|
<div class="mb-5 flex items-center justify-between">
|
|
<h3 class="text-2xl font-semibold tracking-tight text-white">Trending Stories</h3>
|
|
</div>
|
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
|
|
@foreach($trendingStories as $story)
|
|
<x-story-card :story="$story" />
|
|
@endforeach
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h3 class="mb-5 text-2xl font-semibold tracking-tight text-white">Categories</h3>
|
|
<div class="flex flex-wrap gap-2">
|
|
@foreach($categories as $category)
|
|
<a href="{{ route('stories.category', $category['slug']) }}" class="rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 transition-colors hover:border-sky-500/40 hover:text-white">
|
|
{{ $category['name'] }}
|
|
</a>
|
|
@endforeach
|
|
</div>
|
|
</section>
|
|
|
|
<section id="latest">
|
|
<h3 class="mb-5 text-2xl font-semibold tracking-tight text-white">Latest Stories</h3>
|
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
|
|
@foreach($latestStories as $story)
|
|
<x-story-card :story="$story" />
|
|
@endforeach
|
|
</div>
|
|
<div class="mt-8">
|
|
{{ $latestStories->links() }}
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
var tabLinks = Array.from(document.querySelectorAll('[data-stories-tab]'));
|
|
if (!tabLinks.length) return;
|
|
|
|
function setActiveTab(targetId) {
|
|
tabLinks.forEach(function (link) {
|
|
var isActive = link.getAttribute('data-target') === targetId;
|
|
link.setAttribute('aria-selected', isActive ? 'true' : 'false');
|
|
link.classList.toggle('text-white', isActive);
|
|
link.classList.toggle('text-neutral-400', !isActive);
|
|
|
|
var indicator = link.querySelector('[data-tab-indicator]');
|
|
if (!indicator) return;
|
|
indicator.classList.toggle('bg-accent', isActive);
|
|
indicator.classList.toggle('bg-transparent', !isActive);
|
|
indicator.classList.toggle('scale-x-100', isActive);
|
|
indicator.classList.toggle('scale-x-0', !isActive);
|
|
});
|
|
}
|
|
|
|
tabLinks.forEach(function (link) {
|
|
link.addEventListener('click', function () {
|
|
var targetId = link.getAttribute('data-target');
|
|
if (targetId) setActiveTab(targetId);
|
|
});
|
|
});
|
|
|
|
var sectionIds = Array.from(new Set(tabLinks.map(function (link) {
|
|
return link.getAttribute('data-target');
|
|
}).filter(Boolean)));
|
|
|
|
var sections = sectionIds
|
|
.map(function (id) { return document.getElementById(id); })
|
|
.filter(Boolean);
|
|
|
|
if (!sections.length) return;
|
|
|
|
var observer = new IntersectionObserver(function (entries) {
|
|
entries.forEach(function (entry) {
|
|
if (entry.isIntersecting) {
|
|
setActiveTab(entry.target.id);
|
|
}
|
|
});
|
|
}, {
|
|
root: null,
|
|
rootMargin: '-35% 0px -55% 0px',
|
|
threshold: 0.01
|
|
});
|
|
|
|
sections.forEach(function (section) { observer.observe(section); });
|
|
});
|
|
</script>
|
|
@endpush
|