diff --git a/app/Http/Controllers/ServiceController.php b/app/Http/Controllers/ServiceController.php index 3725fd2..4d489a9 100644 --- a/app/Http/Controllers/ServiceController.php +++ b/app/Http/Controllers/ServiceController.php @@ -3,8 +3,10 @@ namespace App\Http\Controllers; use App\Models\Service; +use App\Models\Setting; use App\Models\Slide; use App\Models\Song; +use App\Services\AgendaMatcherService; use App\Services\ProBundleExportService; use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; @@ -94,6 +96,11 @@ public function edit(Service $service): Response 'serviceSongs.song.arrangements.arrangementGroups.group', 'serviceSongs.arrangement', 'slides', + 'agendaItems' => fn ($q) => $q->orderBy('sort_order'), + 'agendaItems.slides', + 'agendaItems.serviceSong.song.groups.slides', + 'agendaItems.serviceSong.song.arrangements.arrangementGroups.group', + 'agendaItems.serviceSong.arrangement.arrangementGroups.group', ]); $songsCatalog = Song::query() @@ -148,6 +155,41 @@ public function edit(Service $service): Response ->orderBy('date') ->first(['id', 'title', 'date']); + // Load agenda settings + $agendaSettings = [ + 'start_title' => Setting::get('agenda_start_title'), + 'end_title' => Setting::get('agenda_end_title'), + 'announcement_position' => Setting::get('agenda_announcement_position'), + 'sermon_matching' => Setting::get('agenda_sermon_matching'), + ]; + + // Filter agenda items (exclude before-event, apply boundary filtering) + $matcher = app(AgendaMatcherService::class); + $agendaItemsArray = $service->agendaItems + ->filter(fn ($i) => ! $i->is_before_event) + ->values() + ->all(); + $filteredItems = $matcher->filterBetween( + $agendaItemsArray, + $agendaSettings['start_title'], + $agendaSettings['end_title'] + ); + + // Add computed flags to each agenda item + $announcementPatterns = $agendaSettings['announcement_position']; + $sermonPatterns = $agendaSettings['sermon_matching']; + $agendaItemsMapped = array_map(function ($item) use ($matcher, $announcementPatterns, $sermonPatterns) { + $arr = $item->toArray(); + $arr['is_announcement_position'] = $announcementPatterns + ? $matcher->matchesAny($item->title, array_map('trim', explode(',', $announcementPatterns))) + : false; + $arr['is_sermon'] = $sermonPatterns + ? $matcher->matchesAny($item->title, array_map('trim', explode(',', $sermonPatterns))) + : false; + + return $arr; + }, $filteredItems); + return Inertia::render('Services/Edit', [ 'service' => [ 'id' => $service->id, @@ -210,6 +252,8 @@ public function edit(Service $service): Response 'moderationSlides' => $moderationSlides, 'sermonSlides' => $sermonSlides, 'songsCatalog' => $songsCatalog, + 'agendaItems' => $agendaItemsMapped, + 'agendaSettings' => $agendaSettings, 'prevService' => $prevService ? [ 'id' => $prevService->id, 'title' => $prevService->title, diff --git a/tests/Feature/ServiceControllerTest.php b/tests/Feature/ServiceControllerTest.php index c1d5f63..f26c0f9 100644 --- a/tests/Feature/ServiceControllerTest.php +++ b/tests/Feature/ServiceControllerTest.php @@ -3,7 +3,9 @@ namespace Tests\Feature; use App\Models\Service; +use App\Models\ServiceAgendaItem; use App\Models\ServiceSong; +use App\Models\Setting; use App\Models\Slide; use App\Models\Song; use App\Models\SongArrangement; @@ -351,4 +353,198 @@ public function test_services_index_zeigt_vergangene_services_mit_archived_param ->where('archived', true) ); } + + public function test_edit_seite_liefert_leere_agenda_items_und_settings(): void + { + Carbon::setTestNow('2026-03-01 10:00:00'); + $this->withoutVite(); + + $user = User::factory()->create(); + $service = Service::factory()->create([ + 'date' => Carbon::today()->addDays(7), + ]); + + $response = $this->actingAs($user)->get(route('services.edit', $service)); + + $response->assertOk(); + $response->assertInertia( + fn ($page) => $page + ->component('Services/Edit') + ->has('agendaItems', 0) + ->has('agendaSettings') + ->where('agendaSettings.start_title', null) + ->where('agendaSettings.end_title', null) + ->where('agendaSettings.announcement_position', null) + ->where('agendaSettings.sermon_matching', null) + ); + } + + public function test_edit_seite_liefert_agenda_items_mit_computed_flags(): void + { + Carbon::setTestNow('2026-03-01 10:00:00'); + $this->withoutVite(); + + $user = User::factory()->create(); + $service = Service::factory()->create([ + 'date' => Carbon::today()->addDays(7), + ]); + + Setting::set('agenda_announcement_position', 'Hinweis*,Information*'); + Setting::set('agenda_sermon_matching', 'Predigt*'); + + ServiceAgendaItem::factory()->create([ + 'service_id' => $service->id, + 'title' => 'Lobpreis', + 'sort_order' => 1, + 'is_before_event' => false, + ]); + + ServiceAgendaItem::factory()->create([ + 'service_id' => $service->id, + 'title' => 'Hinweise und Infos', + 'sort_order' => 2, + 'is_before_event' => false, + ]); + + ServiceAgendaItem::factory()->create([ + 'service_id' => $service->id, + 'title' => 'Predigt: Thema', + 'sort_order' => 3, + 'is_before_event' => false, + ]); + + $response = $this->actingAs($user)->get(route('services.edit', $service)); + + $response->assertOk(); + $response->assertInertia( + fn ($page) => $page + ->component('Services/Edit') + ->has('agendaItems', 3) + ->where('agendaItems.0.title', 'Lobpreis') + ->where('agendaItems.0.is_announcement_position', false) + ->where('agendaItems.0.is_sermon', false) + ->where('agendaItems.1.title', 'Hinweise und Infos') + ->where('agendaItems.1.is_announcement_position', true) + ->where('agendaItems.1.is_sermon', false) + ->where('agendaItems.2.title', 'Predigt: Thema') + ->where('agendaItems.2.is_announcement_position', false) + ->where('agendaItems.2.is_sermon', true) + ); + } + + public function test_edit_seite_filtert_agenda_items_mit_start_end_grenzen(): void + { + Carbon::setTestNow('2026-03-01 10:00:00'); + $this->withoutVite(); + + $user = User::factory()->create(); + $service = Service::factory()->create([ + 'date' => Carbon::today()->addDays(7), + ]); + + Setting::set('agenda_start_title', 'Beginn*'); + Setting::set('agenda_end_title', 'Segen*'); + + ServiceAgendaItem::factory()->create([ + 'service_id' => $service->id, + 'title' => 'Beginn Gottesdienst', + 'sort_order' => 1, + 'is_before_event' => false, + ]); + + ServiceAgendaItem::factory()->create([ + 'service_id' => $service->id, + 'title' => 'Lobpreis', + 'sort_order' => 2, + 'is_before_event' => false, + ]); + + ServiceAgendaItem::factory()->create([ + 'service_id' => $service->id, + 'title' => 'Predigt', + 'sort_order' => 3, + 'is_before_event' => false, + ]); + + ServiceAgendaItem::factory()->create([ + 'service_id' => $service->id, + 'title' => 'Segen und Sendung', + 'sort_order' => 4, + 'is_before_event' => false, + ]); + + $response = $this->actingAs($user)->get(route('services.edit', $service)); + + $response->assertOk(); + $response->assertInertia( + fn ($page) => $page + ->component('Services/Edit') + ->has('agendaItems', 2) + ->where('agendaItems.0.title', 'Lobpreis') + ->where('agendaItems.1.title', 'Predigt') + ); + } + + public function test_edit_seite_schliesst_before_event_items_aus(): void + { + Carbon::setTestNow('2026-03-01 10:00:00'); + $this->withoutVite(); + + $user = User::factory()->create(); + $service = Service::factory()->create([ + 'date' => Carbon::today()->addDays(7), + ]); + + ServiceAgendaItem::factory()->create([ + 'service_id' => $service->id, + 'title' => 'Technik Check', + 'sort_order' => 1, + 'is_before_event' => true, + ]); + + ServiceAgendaItem::factory()->create([ + 'service_id' => $service->id, + 'title' => 'Lobpreis', + 'sort_order' => 2, + 'is_before_event' => false, + ]); + + $response = $this->actingAs($user)->get(route('services.edit', $service)); + + $response->assertOk(); + $response->assertInertia( + fn ($page) => $page + ->component('Services/Edit') + ->has('agendaItems', 1) + ->where('agendaItems.0.title', 'Lobpreis') + ); + } + + public function test_edit_seite_liefert_agenda_settings_mit_allen_vier_keys(): void + { + Carbon::setTestNow('2026-03-01 10:00:00'); + $this->withoutVite(); + + $user = User::factory()->create(); + $service = Service::factory()->create([ + 'date' => Carbon::today()->addDays(7), + ]); + + Setting::set('agenda_start_title', 'Beginn*'); + Setting::set('agenda_end_title', 'Segen*'); + Setting::set('agenda_announcement_position', 'Hinweis*'); + Setting::set('agenda_sermon_matching', 'Predigt*'); + + $response = $this->actingAs($user)->get(route('services.edit', $service)); + + $response->assertOk(); + $response->assertInertia( + fn ($page) => $page + ->component('Services/Edit') + ->where('agendaSettings.start_title', 'Beginn*') + ->where('agendaSettings.end_title', 'Segen*') + ->where('agendaSettings.announcement_position', 'Hinweis*') + ->where('agendaSettings.sermon_matching', 'Predigt*') + ); + } } diff --git a/tests/Feature/SettingsControllerAgendaKeysTest.php b/tests/Feature/SettingsControllerAgendaKeysTest.php index ea51e3e..943e825 100644 --- a/tests/Feature/SettingsControllerAgendaKeysTest.php +++ b/tests/Feature/SettingsControllerAgendaKeysTest.php @@ -14,11 +14,11 @@ $response->assertInertia( fn ($page) => $page - ->component('Settings') - ->has('settings.agenda_start_title') - ->has('settings.agenda_end_title') - ->has('settings.agenda_announcement_position') - ->has('settings.agenda_sermon_matching') + ->component('Settings') + ->has('settings.agenda_start_title') + ->has('settings.agenda_end_title') + ->has('settings.agenda_announcement_position') + ->has('settings.agenda_sermon_matching') ); });