From 6061e4c4dddbb11b5eccff66396e592ad0814918 Mon Sep 17 00:00:00 2001 From: Thorsten Bus Date: Sun, 31 May 2026 00:01:24 +0200 Subject: [PATCH] feat(service): add image columns and overrides Enable storage-backed key visuals and background images plus service-specific moderator and preacher name overrides. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- app/Models/Service.php | 14 +++++ ...900_add_image_fields_to_services_table.php | 30 +++++++++++ tests/Feature/ServiceImageColumnsTest.php | 52 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 database/migrations/2026_05_10_115900_add_image_fields_to_services_table.php create mode 100644 tests/Feature/ServiceImageColumnsTest.php diff --git a/app/Models/Service.php b/app/Models/Service.php index b47ed7e..63c4fc2 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -17,7 +17,11 @@ class Service extends Model 'title', 'date', 'preacher_name', + 'preacher_name_override', 'beamer_tech_name', + 'key_visual_filename', + 'background_filename', + 'moderator_name', 'finalized_at', 'last_synced_at', 'cts_data', @@ -45,6 +49,16 @@ public function slides(): HasMany return $this->hasMany(Slide::class); } + protected function keyVisualUrl(): Attribute + { + return Attribute::get(fn () => $this->key_visual_filename ? '/storage/'.$this->key_visual_filename : null); + } + + protected function backgroundUrl(): Attribute + { + return Attribute::get(fn () => $this->background_filename ? '/storage/'.$this->background_filename : null); + } + public function agendaItems(): HasMany { return $this->hasMany(ServiceAgendaItem::class)->orderBy('sort_order'); diff --git a/database/migrations/2026_05_10_115900_add_image_fields_to_services_table.php b/database/migrations/2026_05_10_115900_add_image_fields_to_services_table.php new file mode 100644 index 0000000..dd4fa89 --- /dev/null +++ b/database/migrations/2026_05_10_115900_add_image_fields_to_services_table.php @@ -0,0 +1,30 @@ +string('key_visual_filename')->nullable()->after('beamer_tech_name'); + $table->string('background_filename')->nullable()->after('key_visual_filename'); + $table->string('moderator_name')->nullable()->after('background_filename'); + $table->string('preacher_name_override')->nullable()->after('moderator_name'); + }); + } + + public function down(): void + { + Schema::table('services', function (Blueprint $table) { + $table->dropColumn([ + 'key_visual_filename', + 'background_filename', + 'moderator_name', + 'preacher_name_override', + ]); + }); + } +}; diff --git a/tests/Feature/ServiceImageColumnsTest.php b/tests/Feature/ServiceImageColumnsTest.php new file mode 100644 index 0000000..aa7aa52 --- /dev/null +++ b/tests/Feature/ServiceImageColumnsTest.php @@ -0,0 +1,52 @@ +create([ + 'key_visual_filename' => 'slides/a.jpg', + ]); + + expect($service->keyVisualUrl)->toBe('/storage/slides/a.jpg'); +}); + +test('key visual url returns null when filename is missing', function () { + $service = Service::factory()->create([ + 'key_visual_filename' => null, + ]); + + expect($service->keyVisualUrl)->toBeNull(); +}); + +test('service fillable persists image and name override columns', function () { + $service = Service::factory()->create(); + + $service->fill([ + 'key_visual_filename' => 'slides/key.jpg', + 'background_filename' => 'slides/background.jpg', + 'moderator_name' => 'Max Mustermann', + 'preacher_name_override' => 'Lisa Beispiel', + ]); + + $service->save(); + + $fresh = $service->fresh(); + + expect($fresh->key_visual_filename)->toBe('slides/key.jpg') + ->and($fresh->background_filename)->toBe('slides/background.jpg') + ->and($fresh->moderator_name)->toBe('Max Mustermann') + ->and($fresh->preacher_name_override)->toBe('Lisa Beispiel') + ->and($fresh->backgroundUrl)->toBe('/storage/slides/background.jpg'); +}); + +test('services table has the new image and override columns', function () { + expect(Schema::hasColumn('services', 'key_visual_filename'))->toBeTrue() + ->and(Schema::hasColumn('services', 'background_filename'))->toBeTrue() + ->and(Schema::hasColumn('services', 'moderator_name'))->toBeTrue() + ->and(Schema::hasColumn('services', 'preacher_name_override'))->toBeTrue(); +});