$query->where('user_id', auth()->id()))->count(); return $unreadCount > 0 ? (string) $unreadCount : null; } public static function getPagePermission(): string { return 'View:Changelog'; } #[Computed] public function techStack(): array { $latestUpdate = Changelog::latest('release_date')->first(); return [ 'name' => config('app.name'), 'version' => $latestUpdate?->version ?? 'v1.0.0', 'stack' => [ 'PHP' => PHP_VERSION, 'Laravel' => app()->version(), 'Filament' => 'v5.x', 'Database' => config('database.default'), ], ]; } #[Computed] public function changelogs(): Collection { return Changelog::with([ 'users' => fn ($query) => $query->where('user_id', auth()->id()), ]) ->orderBy('version', 'desc') ->get() ->sortBy([ fn ($a, $b) => $a->is_read <=> $b->is_read, ]) ->values(); } protected function getHeaderActions(): array { return [ CreateChangelogAction::make() ->visible(fn () => auth()->user()?->can('Create:Changelog')), ]; } public function editChangelogAction(): Action { return EditChangelogAction::make() ->visible(fn () => auth()->user()?->can('Update:Changelog')); } public function deleteChangelogAction(): Action { return DeleteChangelogAction::make() ->visible(fn () => auth()->user()?->can('Delete:Changelog')); } public function markAsReadAction(): Action { return MarkAsReadAction::make(); } public function viewReadersAction(): Action { return Action::make('viewReaders') ->label('Lihat') ->icon('heroicon-o-eye') ->color('info') ->link() ->tooltip('Daftar Mahasiswa') ->modalHeading('Daftar Mahasiswa yang Melihat') ->modalWidth(Width::TwoExtraLarge) ->modalSubmitAction(false) ->modalCancelActionLabel('Tutup') ->visible(fn () => auth()->user()?->can('Update:Changelog')) ->modalContent(function (array $arguments) { $record = Changelog::find($arguments['record'] ?? null); if (! $record) { return null; } $students = Student::with('user')->get(); $readUsersMap = $record->users()->withPivot('read_at')->get()->keyBy('id'); $records = $students->map(fn ($student) => (object) [ 'student' => $student, 'is_read' => $readUsersMap->has($student->user_id), 'read_at' => $readUsersMap->get($student->user_id)?->pivot?->read_at ? Carbon::parse($readUsersMap->get($student->user_id)->pivot->read_at)->translatedFormat('d F Y H:i') : null, ]); return view('filament.pages.system.changelog.view-readers', [ 'records' => $records, 'readCount' => $readUsersMap->count(), ]); }); } #[Computed] public function emptyHeading(): string { return SystemNotification::getByKey('labels.empty_changelog.title'); } #[Computed] public function emptyDescription(): string { return SystemNotification::getByKey('labels.empty_changelog.description'); } public function changelogFormSchema(): array { return [ Grid::make(3) ->schema([ TextInput::make('version') ->label('Versi') ->placeholder('v1.0.0') ->required() ->unique(ignoreRecord: true) ->autocomplete(false), DatePicker::make('release_date') ->label('Tanggal Rilis') ->required() ->native(false) ->default(now()) ->displayFormat('d F Y'), Select::make('type') ->label('Tipe Update') ->options(ChangelogType::class) ->required() ->native(false), ]), TextInput::make('title') ->label('Judul Update') ->placeholder('Sistem Notifikasi & Estetika Baru') ->required() ->maxLength(100) ->autocomplete(false), TagsInput::make('changes') ->label('Daftar Perubahan') ->placeholder('Tambah perubahan...') ->required(), RichEditor::make('description') ->label('Deskripsi') ->placeholder('...') ->required(), ]; } }