schema([ TextInput::make('name') ->label('Event-Name') ->required(), TextInput::make('title') ->label('Galerie Titel') ->required(), TextInput::make('images_path') ->label('Upload-Pfad') ->helperText('Relativ zu public/storage, z.B. uploads/event-xyz') ->default(fn () => 'uploads/'.Str::slug('event-'.Str::random(4))) ->required() ->rule('regex:/^[A-Za-z0-9._\\/-]+$/') ->unique(table: Gallery::class, column: 'images_path') ->dehydrateStateUsing(fn (string $state): string => trim($state, '/')), Toggle::make('allow_print') ->label('Drucken erlauben') ->default(true), Toggle::make('allow_ai_styles') ->label('AI-Stile erlauben') ->default(true), Toggle::make('upload_enabled') ->label('Uploads aktivieren') ->default(true), TextInput::make('sparkbooth_username') ->label('Photobooth Benutzername') ->helperText('Wird im Photobooth Uploader unter „Benutzername“ eingetragen. Erlaubt sind Buchstaben, Zahlen sowie ._-') ->default(fn (): string => 'spark-'.Str::lower(Str::random(6))) ->required() ->maxLength(64) ->rule('regex:/^[A-Za-z0-9._-]+$/') ->unique(table: Gallery::class, column: 'sparkbooth_username'), Select::make('sparkbooth_response_format') ->label('Standard-Antwortformat') ->helperText('Der Photobooth Uploader kann JSON oder XML erwarten. JSON ist empfohlen.') ->options([ 'json' => 'JSON', 'xml' => 'XML', ]) ->default('json') ->required(), ]) ->statePath('data'); } public function save(): void { $data = $this->form->getState(); $sparkboothUsername = $this->normalizeUsername($data['sparkbooth_username'] ?? ''); $sparkboothPassword = Str::random(24); $gallery = new Gallery([ 'name' => $data['name'], 'title' => $data['title'], 'images_path' => trim($data['images_path'], '/'), 'is_public' => true, 'allow_ai_styles' => (bool) $data['allow_ai_styles'], 'allow_print' => (bool) $data['allow_print'], 'upload_enabled' => (bool) $data['upload_enabled'], 'sparkbooth_username' => $sparkboothUsername, 'sparkbooth_password' => $sparkboothPassword, 'sparkbooth_response_format' => $data['sparkbooth_response_format'] ?? 'json', ]); $gallery->slug = Str::uuid()->toString(); $plainToken = Str::random(40); $gallery->setUploadToken($plainToken); $gallery->save(); $this->result = [ 'gallery' => $gallery->only(['id', 'name', 'slug', 'images_path']), 'upload_token' => $plainToken, 'upload_url' => route('api.photobooth.upload'), 'gallery_url' => route('gallery.show', $gallery), 'sparkbooth_username' => $sparkboothUsername, 'sparkbooth_password' => $sparkboothPassword, 'response_format' => $gallery->sparkbooth_response_format, ]; Notification::make() ->title('Galerie erstellt und Upload-Token generiert.') ->success() ->send(); } protected function getFormActions(): array { return [ \Filament\Actions\Action::make('save') ->label('Speichern') ->icon('heroicon-m-check') ->color('primary') ->submit('save'), \Filament\Actions\Action::make('cancel') ->label('Abbrechen') ->icon('heroicon-m-x-mark') ->color('gray') ->url(route('filament.admin.pages.dashboard')), ]; } protected function normalizeUsername(string $value): string { $clean = preg_replace('/[^A-Za-z0-9._-]/', '', $value) ?? ''; return Str::of($clean)->lower()->trim()->value(); } }