feat(settings): add add_countdown_slide toggle

New key/value setting in the Export-Dateien submenu, seeded to '0' and
allowlisted in SettingsController. Controls whether a countdown standby
slide is prepended to playlist exports.
This commit is contained in:
Thorsten Bus 2026-08-03 08:59:43 +02:00
parent 94170857b6
commit 4a2fa0b753
4 changed files with 88 additions and 6 deletions

View file

@ -31,6 +31,7 @@ class SettingsController extends Controller
'namenseinblender_macro_id',
'song_prefix_label_id',
'song_postfix_label_id',
'add_countdown_slide',
];
public function index(): Response

View file

@ -13,5 +13,10 @@ public function run(): void
['key' => 'default_translation_language'],
['value' => 'DE'],
);
Setting::firstOrCreate(
['key' => 'add_countdown_slide'],
['value' => '0'],
);
}
}

View file

@ -289,12 +289,30 @@ watch(songPostfixLabelId, (value) => {
</div>
<!-- Task 7: Export-Dateien submenu -->
<ExportProFiles
v-if="activeSubmenu === 'export-files'"
:prefix-files="export_pro_files.prefix"
:postfix-files="export_pro_files.postfix"
:keyword-files="export_pro_files.keyword"
/>
<div v-if="activeSubmenu === 'export-files'" class="space-y-8">
<!-- Countdown-Folie Toggle -->
<label class="flex cursor-pointer items-start gap-3 rounded-lg border border-gray-200 p-4">
<input
type="checkbox"
class="mt-0.5 h-4 w-4 shrink-0 rounded border-gray-300 text-amber-600 focus:ring-amber-500"
data-testid="setting-add-countdown-slide"
:checked="settings.add_countdown_slide === '1'"
@change="updateSetting('add_countdown_slide', $event.target.checked ? '1' : '0')"
/>
<span class="min-w-0">
<span class="block text-sm font-semibold text-gray-900">Countdown-Folie hinzufügen</span>
<span class="mt-1 block text-xs text-gray-500">
Fügt am Anfang eine Folie mit Keyvisual und Uhrzeit-Timer (hh:mm) oben links hinzu.
</span>
</span>
</label>
<ExportProFiles
:prefix-files="export_pro_files.prefix"
:postfix-files="export_pro_files.postfix"
:keyword-files="export_pro_files.keyword"
/>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,58 @@
<?php
use App\Models\Setting;
use App\Models\User;
beforeEach(function () {
$this->user = User::factory()->create();
});
test('settings index includes add_countdown_slide in props', function () {
$response = $this->actingAs($this->user)
->withoutVite()
->get(route('settings.index'));
$response->assertInertia(
fn ($page) => $page
->component('Settings')
->has('settings.add_countdown_slide')
);
});
test('patch add_countdown_slide to 1 persists', function () {
$response = $this->actingAs($this->user)
->patchJson(route('settings.update'), [
'key' => 'add_countdown_slide',
'value' => '1',
]);
$response->assertOk()
->assertJson(['success' => true]);
expect(Setting::get('add_countdown_slide'))->toBe('1');
});
test('patch add_countdown_slide to 0 persists', function () {
Setting::set('add_countdown_slide', '1');
$response = $this->actingAs($this->user)
->patchJson(route('settings.update'), [
'key' => 'add_countdown_slide',
'value' => '0',
]);
$response->assertOk()
->assertJson(['success' => true]);
expect(Setting::get('add_countdown_slide'))->toBe('0');
});
test('patch with unknown key returns 422', function () {
$response = $this->actingAs($this->user)
->patchJson(route('settings.update'), [
'key' => 'unknown_setting_key',
'value' => 'some value',
]);
$response->assertUnprocessable();
});