- Enhance ProjectController show() with prev/next navigation data - Create useFetchProject composable with ProjectNavigation type - Implement [slug].vue with full project details: - Hero image, title with featured badge, formatted date - Description, external links (site/GitHub) - Skills grid with level progression (before → after) - Prev/next navigation with project titles - 404 state with spider narrator - Add dynamic SEO meta tags with og:image from project - Responsive design: stacked mobile, grid desktop Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
58 lines
1.8 KiB
PHP
58 lines
1.8 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Resources\ProjectResource;
|
|
use App\Models\Project;
|
|
use App\Models\Translation;
|
|
|
|
class ProjectController extends Controller
|
|
{
|
|
public function index()
|
|
{
|
|
$projects = Project::with('skills')->ordered()->get();
|
|
|
|
return ProjectResource::collection($projects)
|
|
->additional(['meta' => ['lang' => app()->getLocale()]]);
|
|
}
|
|
|
|
public function show(string $slug)
|
|
{
|
|
$project = Project::with('skills')->where('slug', $slug)->first();
|
|
|
|
if (!$project) {
|
|
return response()->json([
|
|
'error' => [
|
|
'code' => 'PROJECT_NOT_FOUND',
|
|
'message' => 'Project not found',
|
|
],
|
|
], 404);
|
|
}
|
|
|
|
$lang = app()->getLocale();
|
|
|
|
// Get all projects in order for navigation
|
|
$allProjects = Project::ordered()->get(['id', 'slug', 'title_key']);
|
|
$currentIndex = $allProjects->search(fn ($p) => $p->slug === $slug);
|
|
|
|
$prev = $currentIndex > 0 ? $allProjects[$currentIndex - 1] : null;
|
|
$next = $currentIndex < $allProjects->count() - 1 ? $allProjects[$currentIndex + 1] : null;
|
|
|
|
return (new ProjectResource($project))
|
|
->additional([
|
|
'meta' => ['lang' => $lang],
|
|
'navigation' => [
|
|
'prev' => $prev ? [
|
|
'slug' => $prev->slug,
|
|
'title' => Translation::getTranslation($prev->title_key, $lang),
|
|
] : null,
|
|
'next' => $next ? [
|
|
'slug' => $next->slug,
|
|
'title' => Translation::getTranslation($next->title_key, $lang),
|
|
] : null,
|
|
],
|
|
]);
|
|
}
|
|
}
|