✨ Add skill projects modal with Headless UI (Story 2.5)
- Add GET /skills/{slug}/projects endpoint with level progression
- Install @headlessui/vue for accessible modal
- Create SkillProjectsModal with Dialog component:
- Focus trap and keyboard navigation (automatic)
- Fade + scale transitions with backdrop blur
- prefers-reduced-motion support
- Create ProjectListItem with thumbnail and level display
- Integrate modal in competences.vue page
- Add translations for related projects UI
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,51 @@ class SkillController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function projects(string $slug)
|
||||
{
|
||||
$lang = app()->getLocale();
|
||||
|
||||
$skill = Skill::with('projects')->where('slug', $slug)->first();
|
||||
|
||||
if (!$skill) {
|
||||
return response()->json([
|
||||
'error' => [
|
||||
'code' => 'SKILL_NOT_FOUND',
|
||||
'message' => 'Skill not found',
|
||||
],
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'data' => [
|
||||
'skill' => [
|
||||
'id' => $skill->id,
|
||||
'slug' => $skill->slug,
|
||||
'name' => $skill->getTranslated('name_key'),
|
||||
'description' => $skill->getTranslated('description_key'),
|
||||
'level' => $skill->getCurrentLevel(),
|
||||
'max_level' => $skill->max_level,
|
||||
],
|
||||
'projects' => $skill->projects->map(function ($project) {
|
||||
return [
|
||||
'id' => $project->id,
|
||||
'slug' => $project->slug,
|
||||
'title' => $project->getTranslated('title_key'),
|
||||
'short_description' => $project->getTranslated('short_description_key'),
|
||||
'image' => $project->image,
|
||||
'date_completed' => $project->date_completed?->format('Y-m-d'),
|
||||
'level_before' => $project->pivot->level_before,
|
||||
'level_after' => $project->pivot->level_after,
|
||||
'level_description' => $project->pivot->level_description_key
|
||||
? $project->getTranslated($project->pivot->level_description_key)
|
||||
: null,
|
||||
];
|
||||
}),
|
||||
],
|
||||
'meta' => ['lang' => $lang],
|
||||
]);
|
||||
}
|
||||
|
||||
private function getCategoryLabel(string $category, string $lang): string
|
||||
{
|
||||
$labels = [
|
||||
|
||||
@@ -11,3 +11,4 @@ Route::get('/health', function () {
|
||||
Route::get('/projects', [ProjectController::class, 'index']);
|
||||
Route::get('/projects/{slug}', [ProjectController::class, 'show']);
|
||||
Route::get('/skills', [SkillController::class, 'index']);
|
||||
Route::get('/skills/{slug}/projects', [SkillController::class, 'projects']);
|
||||
|
||||
Reference in New Issue
Block a user