schema([ SchemaTabs::make('translations') ->columnSpanFull() ->tabs([ SchemaTab::make('Deutsch') ->schema([ TextInput::make('name_translations.de') ->label('Name (DE)') ->required() ->maxLength(255), MarkdownEditor::make('description_translations.de') ->label('Beschreibung (DE)') ->required() ->columnSpanFull(), ]), SchemaTab::make('English') ->schema([ TextInput::make('name_translations.en') ->label('Name (EN)') ->required() ->maxLength(255), MarkdownEditor::make('description_translations.en') ->label('Description (EN)') ->required() ->columnSpanFull(), ]), ]), Section::make('Allgemeine Einstellungen') ->columns(3) ->schema([ TextInput::make('slug') ->label('Slug') ->required() ->maxLength(191) ->unique(ignoreRecord: true), Select::make('type') ->label('Paket-Typ') ->options([ 'endcustomer' => 'Endkunde', 'reseller' => 'Reseller', ]) ->required(), TextInput::make('price') ->label('Preis') ->numeric() ->step(0.01) ->prefix('€') ->required(), TextInput::make('max_photos') ->label('Max. Fotos') ->numeric() ->minValue(0) ->nullable(), TextInput::make('max_guests') ->label('Max. Gäste') ->numeric() ->minValue(0) ->nullable(), TextInput::make('gallery_days') ->label('Galeriedauer (Tage)') ->numeric() ->minValue(0) ->nullable(), TextInput::make('max_tasks') ->label('Max. Fotoaufgaben') ->numeric() ->minValue(0) ->nullable(), TextInput::make('max_events_per_year') ->label('Events pro Jahr') ->numeric() ->minValue(0) ->nullable() ->visible(fn ($get) => $get('type') === 'reseller'), Toggle::make('watermark_allowed') ->label('Wasserzeichen erlaubt') ->default(true), Toggle::make('branding_allowed') ->label('Eigenes Branding erlaubt') ->default(false), ]), Section::make('Features & Kennzahlen') ->columns(1) ->schema([ CheckboxList::make('features') ->label('Aktive Features') ->options($featureOptions) ->columns(2) ->default([]), Repeater::make('description_table') ->label('Kenndaten') ->schema([ TextInput::make('title') ->label('Titel') ->maxLength(255), TextInput::make('value') ->label('Wert / Beschreibung') ->maxLength(255), ]) ->addActionLabel('Eintrag hinzufügen') ->reorderable() ->columnSpanFull() ->default([]), ]), ]); } public static function formatFeaturesForDisplay(mixed $features): string { if (is_string($features)) { $decoded = json_decode($features, true); if (json_last_error() === JSON_ERROR_NONE) { $features = $decoded; } } if (! is_array($features)) { return ''; } $labels = static::featureLabelMap(); if (array_is_list($features)) { return collect($features) ->filter(fn ($value) => is_string($value) && $value !== '') ->map(fn ($value) => $labels[$value] ?? $value) ->implode(', '); } return collect($features) ->filter(fn ($value) => (bool) $value) ->keys() ->map(fn ($value) => $labels[$value] ?? $value) ->implode(', '); } public static function table(Table $table): Table { return $table ->columns([ TextColumn::make('name_translations.de') ->label('Name (DE)') ->searchable() ->sortable(), TextColumn::make('name_translations.en') ->label('Name (EN)') ->toggleable(isToggledHiddenByDefault: true), BadgeColumn::make('type') ->label('Typ') ->colors([ 'info' => 'endcustomer', 'warning' => 'reseller', ]), TextColumn::make('price') ->label('Preis') ->money('EUR') ->sortable(), TextColumn::make('max_photos') ->label('Fotos') ->sortable(), TextColumn::make('max_guests') ->label('Gäste') ->sortable() ->toggleable(isToggledHiddenByDefault: true), TextColumn::make('features') ->label('Features') ->wrap() ->formatStateUsing(fn ($state) => static::formatFeaturesForDisplay($state)), ]) ->filters([ Tables\Filters\SelectFilter::make('type') ->label('Typ') ->options([ 'endcustomer' => 'Endkunde', 'reseller' => 'Reseller', ]), ]) ->actions([ ViewAction::make(), EditAction::make(), DeleteAction::make(), ]) ->bulkActions([ BulkActionGroup::make([ DeleteBulkAction::make(), ]), ]); } public static function getPages(): array { return [ 'index' => Pages\ListPackages::route('/'), 'create' => Pages\CreatePackage::route('/create'), 'edit' => Pages\EditPackage::route('/{record}/edit'), ]; } protected static function featureLabelMap(): array { return [ 'basic_uploads' => 'Basis-Uploads', 'limited_sharing' => 'Begrenztes Teilen', 'unlimited_sharing' => 'Unbegrenztes Teilen', 'no_watermark' => 'Kein Wasserzeichen', 'custom_branding' => 'Eigenes Branding', 'custom_tasks' => 'Eigene Aufgaben', 'reseller_dashboard' => 'Reseller-Dashboard', 'advanced_analytics' => 'Erweiterte Analytics', 'advanced_reporting' => 'Erweiterte Reports', 'live_slideshow' => 'Live-Slideshow', 'priority_support' => 'Priorisierter Support', ]; } }