feat: person tags system - org-level skills with self-reported and organiser-assigned sources

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-10 11:15:43 +02:00
parent 5dbe7a254e
commit d37a45b028
21 changed files with 1375 additions and 1 deletions

View File

@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace App\Http\Requests\Api\V1;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
final class StorePersonTagRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => [
'required',
'string',
'max:50',
Rule::unique('person_tags')->where('organisation_id', $this->route('organisation')->id),
],
'category' => ['nullable', 'string', 'max:50'],
'icon' => ['nullable', 'string', 'max:50'],
'color' => ['nullable', 'string', 'max:7'],
'is_active' => ['sometimes', 'boolean'],
'sort_order' => ['sometimes', 'integer'],
];
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace App\Http\Requests\Api\V1;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
final class StoreUserOrganisationTagRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
$organisationId = $this->route('organisation')->id;
return [
'person_tag_id' => [
'required',
'ulid',
Rule::exists('person_tags', 'id')->where('organisation_id', $organisationId),
],
'source' => ['required', 'in:self_reported,organiser_assigned'],
'proficiency' => ['nullable', 'in:beginner,experienced,expert'],
'notes' => ['nullable', 'string', 'max:500'],
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\Http\Requests\Api\V1;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
final class SyncUserOrganisationTagsRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
$organisationId = $this->route('organisation')->id;
return [
'tag_ids' => ['required', 'array'],
'tag_ids.*' => [
'ulid',
Rule::exists('person_tags', 'id')->where('organisation_id', $organisationId),
],
'source' => ['required', 'in:self_reported,organiser_assigned'],
];
}
}

View File

@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace App\Http\Requests\Api\V1;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
final class UpdatePersonTagRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => [
'sometimes',
'string',
'max:50',
Rule::unique('person_tags')
->where('organisation_id', $this->route('organisation')->id)
->ignore($this->route('person_tag')),
],
'category' => ['nullable', 'string', 'max:50'],
'icon' => ['nullable', 'string', 'max:50'],
'color' => ['nullable', 'string', 'max:7'],
'is_active' => ['sometimes', 'boolean'],
'sort_order' => ['sometimes', 'integer'],
];
}
}