Commit workspace changes

This commit is contained in:
2026-04-05 19:42:33 +02:00
parent 148a3bbe43
commit 08ad757bcb
312 changed files with 35149 additions and 399 deletions

View File

@@ -0,0 +1,109 @@
<?php
declare(strict_types=1);
namespace App\Services;
use App\Models\Group;
use App\Models\GroupRecruitmentProfile;
use App\Models\User;
class GroupRecruitmentService
{
public function __construct(
private readonly GroupHistoryService $history,
private readonly NotificationService $notifications,
) {
}
public function upsert(Group $group, array $attributes, User $actor): GroupRecruitmentProfile
{
$profile = GroupRecruitmentProfile::query()->firstOrNew([
'group_id' => $group->id,
]);
$before = $profile->exists ? $profile->only([
'is_recruiting',
'headline',
'description',
'roles_json',
'skills_json',
'contact_mode',
'visibility',
]) : null;
$profile->fill([
'is_recruiting' => (bool) ($attributes['is_recruiting'] ?? false),
'headline' => $attributes['headline'] ?? null,
'description' => $attributes['description'] ?? null,
'roles_json' => $this->normalizeList($attributes['roles_json'] ?? []),
'skills_json' => $this->normalizeList($attributes['skills_json'] ?? []),
'contact_mode' => $attributes['contact_mode'] ?? null,
'visibility' => (string) ($attributes['visibility'] ?? 'public'),
])->save();
if ($profile->is_recruiting && $profile->visibility === 'public') {
foreach ($group->follows()->with('user.profile')->get() as $follow) {
if ($follow->user) {
$this->notifications->notifyGroupRecruitmentUpdated($follow->user, $actor, $group, $profile);
}
}
}
$this->history->record(
$group,
$actor,
'recruitment_updated',
$profile->is_recruiting ? 'Enabled or updated recruitment profile.' : 'Disabled recruitment profile.',
'group_recruitment_profile',
(int) $profile->id,
$before,
$profile->only([
'is_recruiting',
'headline',
'description',
'roles_json',
'skills_json',
'contact_mode',
'visibility',
]),
);
return $profile->fresh();
}
public function payloadForGroup(Group $group): ?array
{
$profile = $group->relationLoaded('recruitmentProfile')
? $group->recruitmentProfile
: $group->recruitmentProfile()->first();
if (! $profile) {
return null;
}
return [
'id' => (int) $profile->id,
'is_recruiting' => (bool) $profile->is_recruiting,
'headline' => $profile->headline,
'description' => $profile->description,
'roles' => array_values(array_filter($profile->roles_json ?? [])),
'skills' => array_values(array_filter($profile->skills_json ?? [])),
'contact_mode' => $profile->contact_mode,
'visibility' => $profile->visibility,
'updated_at' => $profile->updated_at?->toISOString(),
'roles_options' => config('groups.recruitment.roles', []),
'skills_options' => config('groups.recruitment.skills', []),
];
}
private function normalizeList(array $items): array
{
return collect($items)
->map(fn ($item): string => trim((string) $item))
->filter()
->unique()
->values()
->all();
}
}