✨ Add project detail page with prev/next navigation (Story 2.3)
- 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>
This commit is contained in:
@@ -5,6 +5,7 @@ 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
|
||||
{
|
||||
@@ -18,9 +19,39 @@ class ProjectController extends Controller
|
||||
|
||||
public function show(string $slug)
|
||||
{
|
||||
$project = Project::with('skills')->where('slug', $slug)->firstOrFail();
|
||||
$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' => app()->getLocale()]]);
|
||||
->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,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user