feat: add optional event date and expiration settings

Add global settings to make event_date and expiration optional when
creating galleries. This supports non-event use cases like portraits,
corporate shoots, etc.

New features:
- Settings toggles in Settings → Event Creation tab
- "Require event date" checkbox with warning about random URL identifiers
- "Require expiration date" checkbox with warning about manual archiving
- Galleries without date use random hex suffix in slug (e.g. portrait-smith-a1b2c3)
- Galleries without expiration never expire (stay active until archived)

Backend changes:
- New migration for settings and nullable columns
- Conditional validation based on settings
- Updated slug generation with random suffix fallback
- Updated expiration checker to skip null expires_at
- Updated gallery access control for null expiration

Frontend changes:
- New checkboxes in EventsTab with warnings
- Conditional event date field (shows optional label)
- No Expiration message when expiration disabled
- Updated types for nullable event_date and expires_at

Closes #118
This commit is contained in:
Paul Nothaft
2026-01-16 09:39:32 +01:00
parent 3e69579f5a
commit 2151147f2d
13 changed files with 226 additions and 61 deletions
+6 -6
View File
@@ -4,7 +4,7 @@ export interface Event {
slug: string;
event_type: string;
event_name: string;
event_date: string;
event_date: string | null;
customer_name?: string;
customer_email: string;
admin_email: string;
@@ -12,7 +12,7 @@ export interface Event {
color_theme?: string;
share_link: string;
created_at: string;
expires_at: string;
expires_at: string | null;
is_active: boolean;
is_archived: boolean;
archive_path?: string;
@@ -46,8 +46,8 @@ export interface Event {
export interface GalleryInfo {
event_name: string;
event_type: string;
event_date: string;
expires_at: string;
event_date: string | null;
expires_at: string | null;
is_active: boolean;
is_expired: boolean;
requires_password?: boolean;
@@ -97,10 +97,10 @@ export interface GalleryData {
id: number;
event_name: string;
event_type: string;
event_date: string;
event_date: string | null;
welcome_message?: string;
color_theme?: string;
expires_at: string;
expires_at: string | null;
allow_user_uploads?: boolean;
upload_category_id?: number | null;
hero_photo_id?: number | null;