From 1a3f0610a36d337ee7dca8827acd00d533ddf1fa Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Fri, 9 Jan 2026 10:43:16 +0700 Subject: [PATCH] feat: Add notification system with BroadcastNotification class and database migration for notifications table --- .../Announcements/AnnouncementResource.php | 16 +++++---- .../Pages/ManageAnnouncements.php | 26 ++++++++++++++- app/Notifications/BroadcastNotification.php | 31 +++++++++++++++++ .../Filament/DashboardPanelProvider.php | 4 ++- ...1_08_145246_create_notifications_table.php | 33 +++++++++++++++++++ 5 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 app/Notifications/BroadcastNotification.php create mode 100644 database/migrations/2026_01_08_145246_create_notifications_table.php diff --git a/app/Filament/Resources/Publication/Announcements/AnnouncementResource.php b/app/Filament/Resources/Publication/Announcements/AnnouncementResource.php index caf3b93..68a439f 100644 --- a/app/Filament/Resources/Publication/Announcements/AnnouncementResource.php +++ b/app/Filament/Resources/Publication/Announcements/AnnouncementResource.php @@ -15,8 +15,8 @@ use Filament\Actions\ForceDeleteAction; use Filament\Actions\RestoreAction; use Filament\Forms\Components\CheckboxList; +use Filament\Forms\Components\Radio; use Filament\Forms\Components\RichEditor; -use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Resources\Resource; use Filament\Schemas\Schema; @@ -64,13 +64,13 @@ public static function form(Schema $schema): Schema ->required() ->columnSpanFull(), - Select::make('type') - ->label('Tipe Pengumuman') + Radio::make('type') + ->label('Tipe') ->options(AnnouncementType::class) ->required() - ->native(false) ->default(AnnouncementType::PUBLIC->value) - ->live(), + ->live() + ->inline(), CheckboxList::make('partnerMedia') ->label('Kirim Kepada') @@ -84,7 +84,8 @@ public static function form(Schema $schema): Schema ->bulkToggleable() ->selectAllAction( fn (Action $action) => $action->label('Pilih Semua Media'), - ), + ) + ->dehydrated(), ]) ->columns(1); @@ -129,7 +130,8 @@ public static function table(Table $table): Table ]) ->recordActions([ EditAction::make() - ->modalWidth(Width::TwoExtraLarge), + ->modalWidth(Width::TwoExtraLarge) + ->visible(fn ($record) => $record->type === AnnouncementType::PUBLIC), DeleteAction::make(), diff --git a/app/Filament/Resources/Publication/Announcements/Pages/ManageAnnouncements.php b/app/Filament/Resources/Publication/Announcements/Pages/ManageAnnouncements.php index 53b9143..3be17a0 100644 --- a/app/Filament/Resources/Publication/Announcements/Pages/ManageAnnouncements.php +++ b/app/Filament/Resources/Publication/Announcements/Pages/ManageAnnouncements.php @@ -2,7 +2,12 @@ namespace App\Filament\Resources\Publication\Announcements\Pages; +use App\Enums\AnnouncementType; use App\Filament\Resources\Publication\Announcements\AnnouncementResource; +use App\Models\Company; +use App\Models\PartnerMedia; +use App\Models\User; +use App\Notifications\BroadcastNotification; use Filament\Actions\CreateAction; use Filament\Resources\Pages\ManageRecords; use Filament\Support\Enums\Width; @@ -25,7 +30,26 @@ protected function getHeaderActions(): array $action->makeModalSubmitAction('createAnother', arguments: ['another' => true]) ->label('Simpan dan Tambah Lagi'), ]) - ->modalWidth(Width::TwoExtraLarge), + ->modalWidth(Width::TwoExtraLarge) + ->after(function (array $data) { + if ($data['type'] === AnnouncementType::PUBLIC) { + return; + } + + $payload = [ + 'title' => $data['title'], + 'body' => $data['content'], + ]; + + $userIds = Company::whereIn( + 'id', + PartnerMedia::whereIn('id', $data['partnerMedia'])->pluck('company_id') + )->pluck('user_id'); + + User::whereIn('id', $userIds)->each(function ($user) use ($payload) { + $user->notify(new BroadcastNotification($payload)); + }); + }), ]; } } diff --git a/app/Notifications/BroadcastNotification.php b/app/Notifications/BroadcastNotification.php new file mode 100644 index 0000000..2045a76 --- /dev/null +++ b/app/Notifications/BroadcastNotification.php @@ -0,0 +1,31 @@ +payload = $payload; + } + + public function via($notifiable): array + { + return ['database']; + } + + public function toDatabase($notifiable): array + { + return FilamentNotification::make() + ->title($this->payload['title']) + ->body($this->payload['body']) + ->getDatabaseMessage(); + } +} diff --git a/app/Providers/Filament/DashboardPanelProvider.php b/app/Providers/Filament/DashboardPanelProvider.php index bcaf7c5..6a3fe84 100644 --- a/app/Providers/Filament/DashboardPanelProvider.php +++ b/app/Providers/Filament/DashboardPanelProvider.php @@ -99,6 +99,8 @@ public function panel(Panel $panel): Panel 'Publikasi', 'Pengaturan', 'Pelindung', - ]); + ]) + ->databaseNotifications() + ->databaseNotificationsPolling('30s'); } } diff --git a/database/migrations/2026_01_08_145246_create_notifications_table.php b/database/migrations/2026_01_08_145246_create_notifications_table.php new file mode 100644 index 0000000..a66f815 --- /dev/null +++ b/database/migrations/2026_01_08_145246_create_notifications_table.php @@ -0,0 +1,33 @@ +uuid('id')->primary(); + $table->string('type'); + $table->morphs('notifiable'); + $table->text('data'); + $table->timestamp('read_at')->nullable(); + $table->timestamp('created_at')->useCurrent(); + $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('notifications'); + } +};