BlogController was an empty stub with no view, so /blog 500'd on every visit. Adds a real Post model, public listing/detail pages, and an admin CRUD screen mirroring the existing Exercise admin pattern (image upload or URL, auto-slug, publish toggle). Seeds 5 real posts so it's not empty on launch. Also fixes two things that were silently broken: phpunit.xml pointed DB_DATABASE at a non-existent "testing" file with no DB_CONNECTION set, and the stock ExampleTest had RefreshDatabase commented out - both meant the test suite never actually ran successfully. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
44 lines
3.1 KiB
PHP
44 lines
3.1 KiB
PHP
<x-app-layout>
|
|
<section class="bg-white dark:bg-gray-900 border-b border-gray-100 dark:border-gray-800">
|
|
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-8">
|
|
<div>
|
|
<h1 class="text-2xl sm:text-3xl font-extrabold tracking-tight text-gray-900 dark:text-white">{{ __('app.nav.blog') }}</h1>
|
|
<p class="mt-2 text-gray-600 dark:text-gray-300">Tips, guides, and news from the FitAtlas team.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-6">
|
|
<form action="{{ route('blog.index') }}" method="GET" class="mb-6 flex items-end gap-3 bg-white dark:bg-gray-800 rounded-2xl p-4 ring-1 ring-gray-200 dark:ring-gray-700">
|
|
<div class="w-full sm:w-80">
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Search</label>
|
|
<input type="text" name="q" value="{{ $filters['q'] ?? '' }}" placeholder="Search posts" class="mt-1 w-full rounded-xl border-gray-300 dark:border-gray-700 bg-white/80 dark:bg-gray-900 text-gray-900 dark:text-gray-100 placeholder-gray-400 focus:border-indigo-500 focus:ring-indigo-500 px-3 py-2">
|
|
</div>
|
|
<button type="submit" class="inline-flex items-center rounded-xl bg-gradient-to-r from-fuchsia-600 to-indigo-600 px-4 py-2 text-sm font-semibold text-white shadow hover:from-fuchsia-500 hover:to-indigo-500">Search</button>
|
|
</form>
|
|
|
|
@if($posts->count() === 0)
|
|
<div class="rounded-2xl border border-dashed border-gray-300 dark:border-gray-700 p-8 text-center text-gray-600 dark:text-gray-300">No posts yet. Check back soon.</div>
|
|
@else
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
@foreach($posts as $post)
|
|
<a href="{{ route('blog.show', $post->slug) }}" class="group rounded-3xl overflow-hidden bg-white dark:bg-gray-800 ring-1 ring-gray-200 dark:ring-gray-700 shadow-sm hover:shadow-xl transition flex flex-col">
|
|
<div class="relative aspect-[16/9] overflow-hidden">
|
|
<img src="{{ $post->cover_url ?: 'https://images.unsplash.com/photo-1517836357463-d25dfeac3438?q=80&w=1200&auto=format&fit=crop' }}" alt="{{ $post->title }}" class="h-full w-full object-cover transition-transform duration-500 group-hover:scale-105">
|
|
</div>
|
|
<div class="p-5 flex flex-col flex-1">
|
|
<div class="text-xs text-gray-500">{{ $post->published_at?->format('M j, Y') }}@if($post->author) · {{ $post->author->name }} @endif</div>
|
|
<h2 class="mt-2 text-lg font-bold text-gray-900 dark:text-white">{{ $post->title }}</h2>
|
|
@if($post->excerpt)
|
|
<p class="mt-2 text-sm text-gray-600 dark:text-gray-300 line-clamp-3">{{ $post->excerpt }}</p>
|
|
@endif
|
|
</div>
|
|
</a>
|
|
@endforeach
|
|
</div>
|
|
|
|
<div class="mt-6">{{ $posts->links() }}</div>
|
|
@endif
|
|
</section>
|
|
</x-app-layout>
|