schema([ Forms\Components\TextInput::make('sender_name') ->label('Sender') ->afterStateHydrated(function ($component, $state, $record) { if ($record) { if ($record->is_system) { $component->state('System'); } elseif ($record->sender) { $profile = \Paymenter\Extensions\Others\SocialBase\Models\UserProfile::where('user_id', $record->sender_id)->first(); $component->state($profile?->display_name ?? $record->sender->name); } else { $component->state('—'); } } }) ->disabled(), Forms\Components\TextInput::make('sender_email') ->label('Sender Email') ->afterStateHydrated(function ($component, $state, $record) { if ($record) { $component->state($record->sender ? $record->sender->email : '—'); } }) ->disabled(), Forms\Components\Textarea::make('recipients') ->label('Recipients') ->afterStateHydrated(function ($component, $state, $record) { if ($record && $record->conversation) { $recipients = $record->conversation->participants() ->where('user_id', '!=', $record->sender_id) ->get() ->map(fn($p) => $p->name) ->join(', '); $component->state($recipients ?: '—'); } else { $component->state('—'); } }) ->disabled() ->rows(2), Forms\Components\Textarea::make('content') ->label('Message Content') ->disabled() ->rows(4), Forms\Components\Select::make('moderation_status') ->label('Moderation Status') ->options([ 'pending' => 'Pending', 'flagged' => 'Flagged', 'approved' => 'Approved', 'deleted' => 'Deleted', ]) ->required(), Forms\Components\Textarea::make('moderation_reason') ->label('Moderation Reason') ->rows(3) ->placeholder('Enter reason for moderation...'), Forms\Components\TextInput::make('conversation_id') ->label('Conversation ID') ->disabled(), Forms\Components\Toggle::make('is_system') ->label('System Message') ->disabled(), Forms\Components\TextInput::make('system_type') ->label('System Type') ->disabled() ->visible(fn($record) => $record && $record->is_system), Forms\Components\TextInput::make('moderator_name') ->label('Moderated By') ->afterStateHydrated(function ($component, $state, $record) { if ($record) { $component->state($record->moderator ? $record->moderator->name : 'Not moderated'); } }) ->disabled(), Forms\Components\DateTimePicker::make('moderated_at') ->label('Moderated At') ->disabled(), Forms\Components\DateTimePicker::make('created_at') ->label('Created At') ->disabled(), Forms\Components\Textarea::make('report_summary') ->label('User Reports') ->afterStateHydrated(function ($component, $state, $record) { if ($record) { $reports = $record->reports()->with('reporter')->get(); if ($reports->isEmpty()) { $component->state('No reports'); } else { $summary = $reports->map(function($report) { return "[{$report->created_at->format('Y-m-d H:i')}] {$report->reporter->name}: {$report->reason}" . ($report->description ? " - {$report->description}" : ""); })->join("\n\n"); $component->state($summary); } } }) ->disabled() ->rows(4) ->helperText('Messages with 3+ reports are auto-flagged'), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('id') ->label('ID') ->sortable(), Tables\Columns\TextColumn::make('conversation.id') ->label('Conversation ID') ->sortable() ->searchable(), Tables\Columns\TextColumn::make('sender_display_name') ->label('Sender') ->getStateUsing(function ($record) { if ($record->is_system) { return 'System'; } if ($record->sender) { $profile = \Paymenter\Extensions\Others\SocialBase\Models\UserProfile::where('user_id', $record->sender_id)->first(); return $profile?->display_name ?? $record->sender->name; } return '—'; }) ->sortable() ->searchable(), Tables\Columns\TextColumn::make('content') ->label('Content') ->limit(50) ->searchable(), Tables\Columns\BadgeColumn::make('moderation_status') ->label('Status') ->colors([ 'warning' => 'flagged', 'success' => 'approved', 'danger' => 'deleted', ]), Tables\Columns\IconColumn::make('is_system') ->label('System') ->boolean(), Tables\Columns\TextColumn::make('created_at') ->label('Sent At') ->dateTime() ->sortable(), Tables\Columns\TextColumn::make('moderator.name') ->label('Moderated By') ->default('—'), ]) ->filters([ Tables\Filters\SelectFilter::make('moderation_status') ->options([ 'flagged' => 'Flagged', 'approved' => 'Approved', 'deleted' => 'Deleted', ]) ->default('flagged'), Tables\Filters\SelectFilter::make('conversation_id') ->label('Conversation') ->options(function () { return \Paymenter\Extensions\Others\SocialBase\Models\Conversation::query() ->orderBy('id') ->pluck('id', 'id') ->mapWithKeys(fn($id) => [$id => "Conversation #{$id}"]) ->toArray(); }) ->searchable() ->preload() ->query(function (Builder $query, array $data): Builder { if (isset($data['value']) && filled($data['value'])) { return $query->where('conversation_id', $data['value']); } return $query; }), Tables\Filters\Filter::make('is_system') ->label('System Messages Only') ->query(fn(Builder $query) => $query->where('is_system', true)), ]) ->defaultSort('created_at', 'desc') ->actions([ Actions\ViewAction::make(), Actions\EditAction::make(), Actions\Action::make('approve') ->label('Approve') ->icon('heroicon-o-check') ->color('success') ->visible(fn($record) => $record->moderation_status === 'flagged') ->requiresConfirmation() ->action(function ($record) { $record->update([ 'moderation_status' => 'approved', 'moderator_id' => Auth::id(), 'moderated_at' => now(), ]); Notification::make() ->title('Message approved') ->success() ->send(); }), Actions\Action::make('delete_message') ->label('Delete') ->icon('heroicon-o-trash') ->color('danger') ->visible(fn($record) => $record->moderation_status !== 'deleted') ->requiresConfirmation() ->action(function ($record) { $record->update([ 'moderation_status' => 'deleted', 'moderator_id' => Auth::id(), 'moderated_at' => now(), ]); Notification::make() ->title('Message deleted') ->success() ->send(); }), Actions\Action::make('view_conversation') ->label('View Conversation') ->icon('heroicon-o-chat') ->color('info') ->url(fn($record) => \Paymenter\Extensions\Others\SocialBase\Admin\Resources\ConversationResource::getUrl('view', ['record' => $record->conversation_id])) ->openUrlInNewTab(), Actions\DeleteAction::make() ->successNotificationTitle('Message deleted'), ]) ->bulkActions([ Actions\BulkAction::make('approve') ->label('Approve Selected') ->icon('heroicon-o-check') ->color('success') ->requiresConfirmation() ->action(function ($records) { $records->each->update([ 'moderation_status' => 'approved', 'moderator_id' => Auth::id(), 'moderated_at' => now(), ]); Notification::make() ->title('Messages approved') ->success() ->send(); }), Actions\BulkAction::make('delete') ->label('Delete Selected') ->icon('heroicon-o-trash') ->color('danger') ->requiresConfirmation() ->action(function ($records) { $records->each->update([ 'moderation_status' => 'deleted', 'moderator_id' => Auth::id(), 'moderated_at' => now(), ]); Notification::make() ->title('Messages deleted') ->success() ->send(); }), Actions\DeleteBulkAction::make() ->successNotificationTitle('Messages deleted'), ]); } public static function getPages(): array { return [ 'index' => \Paymenter\Extensions\Others\SocialBase\Admin\Resources\MessageModerationResource\Pages\ListMessageModerations::route('/'), 'view' => \Paymenter\Extensions\Others\SocialBase\Admin\Resources\MessageModerationResource\Pages\ViewMessageModeration::route('/{record}'), 'edit' => \Paymenter\Extensions\Others\SocialBase\Admin\Resources\MessageModerationResource\Pages\EditMessageModeration::route('/{record}/edit'), ]; } public static function getEloquentQuery(): Builder { return parent::getEloquentQuery()->with(['sender', 'conversation', 'moderator']); } public static function getNavigationBadge(): ?string { $count = static::getModel()::where('moderation_status', 'flagged')->count(); return $count > 0 ? (string)$count : null; } public static function getNavigationBadgeColor(): ?string { $count = static::getModel()::where('moderation_status', 'flagged')->count(); return $count > 5 ? 'danger' : ($count > 0 ? 'warning' : null); } public static function canViewAny(): bool { $user = Auth::user(); return $user && $user->hasPermission('socialbase.messages.view'); } }