mapWithKeys(fn (TenantAnnouncementStatus $status) => [$status->value => $status->label()]) ->all(); $audienceOptions = collect(TenantAnnouncementAudience::cases()) ->mapWithKeys(fn (TenantAnnouncementAudience $audience) => [$audience->value => $audience->label()]) ->all(); $segmentOptions = collect(TenantAnnouncementSegment::cases()) ->mapWithKeys(fn (TenantAnnouncementSegment $segment) => [$segment->value => $segment->label()]) ->all(); return $schema ->schema([ Section::make('Inhalt') ->schema([ TextInput::make('title') ->label('Titel') ->required() ->maxLength(160), Textarea::make('body') ->label('Text') ->rows(6) ->required() ->columnSpanFull(), TextInput::make('cta_label') ->label('CTA-Label') ->maxLength(160), TextInput::make('cta_url') ->label('CTA-Link') ->maxLength(255) ->url() ->nullable(), ]) ->columns(2), Section::make('Zielgruppe') ->schema([ Select::make('audience') ->label('Zielgruppe') ->options($audienceOptions) ->default(TenantAnnouncementAudience::ALL->value) ->live() ->required(), Select::make('tenants') ->label('Mandanten') ->relationship('tenants', 'name') ->multiple() ->preload() ->searchable() ->visible(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::TENANTS->value) ->dehydrated(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::TENANTS->value) ->required(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::TENANTS->value) ->columnSpanFull(), CheckboxList::make('segments') ->label('Segmente') ->options($segmentOptions) ->columns(2) ->default([]) ->visible(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::SEGMENTS->value) ->dehydrated(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::SEGMENTS->value) ->required(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::SEGMENTS->value) ->columnSpanFull(), Toggle::make('email_enabled') ->label('E-Mail versenden') ->default(true), ]) ->columns(2), Section::make('Zeitplan') ->schema([ Select::make('status') ->label('Status') ->options($statusOptions) ->default(TenantAnnouncementStatus::DRAFT->value) ->live() ->required(), DateTimePicker::make('starts_at') ->label('Startet am') ->seconds(false) ->nullable() ->required(fn (Get $get): bool => $get('status') === TenantAnnouncementStatus::SCHEDULED->value), DateTimePicker::make('ends_at') ->label('Endet am') ->seconds(false) ->nullable(), ]) ->columns(2), ]) ->columns(1); } public static function table(Table $table): Table { $statusOptions = collect(TenantAnnouncementStatus::cases()) ->mapWithKeys(fn (TenantAnnouncementStatus $status) => [$status->value => $status->label()]) ->all(); $audienceOptions = collect(TenantAnnouncementAudience::cases()) ->mapWithKeys(fn (TenantAnnouncementAudience $audience) => [$audience->value => $audience->label()]) ->all(); return $table ->columns([ Tables\Columns\TextColumn::make('title') ->label('Titel') ->searchable() ->sortable() ->limit(50), Tables\Columns\TextColumn::make('status') ->label('Status') ->badge() ->formatStateUsing(function ($state): string { if ($state instanceof TenantAnnouncementStatus) { return $state->label(); } return TenantAnnouncementStatus::tryFrom((string) $state)?->label() ?? (string) $state; }) ->sortable(), Tables\Columns\TextColumn::make('audience') ->label('Zielgruppe') ->badge() ->formatStateUsing(function ($state): string { if ($state instanceof TenantAnnouncementAudience) { return $state->label(); } return TenantAnnouncementAudience::tryFrom((string) $state)?->label() ?? (string) $state; }) ->sortable(), Tables\Columns\IconColumn::make('email_enabled') ->label('E-Mail') ->boolean(), Tables\Columns\TextColumn::make('starts_at') ->label('Start') ->dateTime() ->sortable(), Tables\Columns\TextColumn::make('ends_at') ->label('Ende') ->dateTime() ->sortable() ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\TextColumn::make('updated_at') ->label('Aktualisiert') ->since() ->sortable() ->toggleable(isToggledHiddenByDefault: true), ]) ->filters([ Tables\Filters\SelectFilter::make('status') ->label('Status') ->options($statusOptions), Tables\Filters\SelectFilter::make('audience') ->label('Zielgruppe') ->options($audienceOptions), ]) ->actions([ Actions\EditAction::make() ->after(fn (array $data, TenantAnnouncement $record) => app(SuperAdminAuditLogger::class)->recordModelMutation( 'updated', $record, SuperAdminAuditLogger::fieldsMetadata($data), static::class )), ]) ->bulkActions([ Actions\DeleteBulkAction::make() ->after(function (Collection $records): void { $logger = app(SuperAdminAuditLogger::class); foreach ($records as $record) { $logger->recordModelMutation( 'deleted', $record, source: static::class ); } }), ]); } public static function getPages(): array { return [ 'index' => Pages\ListTenantAnnouncements::route('/'), 'create' => Pages\CreateTenantAnnouncement::route('/create'), 'edit' => Pages\EditTenantAnnouncement::route('/{record}/edit'), ]; } public static function mutateFormDataBeforeCreate(array $data): array { if ($userId = Auth::id()) { $data['created_by'] = $userId; $data['updated_by'] = $userId; } return $data; } public static function mutateFormDataBeforeSave(array $data): array { if ($userId = Auth::id()) { $data['updated_by'] = $userId; } return $data; } }