diff --git a/app/Enums/Channel.php b/app/Enums/Channel.php new file mode 100644 index 0000000..f40b771 --- /dev/null +++ b/app/Enums/Channel.php @@ -0,0 +1,26 @@ + $status->value, self::cases()), + array_map(fn ($status) => $status->value, self::cases()) + ); + } +} diff --git a/app/Filament/Resources/Monitoring/MediaMonitorings/MediaMonitoringResource.php b/app/Filament/Resources/Monitoring/MediaMonitorings/MediaMonitoringResource.php new file mode 100644 index 0000000..76f8869 --- /dev/null +++ b/app/Filament/Resources/Monitoring/MediaMonitorings/MediaMonitoringResource.php @@ -0,0 +1,69 @@ + ListMediaMonitorings::route('/'), + 'create' => CreateMediaMonitoring::route('/create'), + 'edit' => EditMediaMonitoring::route('/{record}/edit'), + ]; + } + + public static function getRecordRouteBindingEloquentQuery(): Builder + { + return parent::getRecordRouteBindingEloquentQuery() + ->withoutGlobalScopes([ + SoftDeletingScope::class, + ]); + } +} diff --git a/app/Filament/Resources/Monitoring/MediaMonitorings/Pages/CreateMediaMonitoring.php b/app/Filament/Resources/Monitoring/MediaMonitorings/Pages/CreateMediaMonitoring.php new file mode 100644 index 0000000..4f415fb --- /dev/null +++ b/app/Filament/Resources/Monitoring/MediaMonitorings/Pages/CreateMediaMonitoring.php @@ -0,0 +1,46 @@ +getResource()::getUrl('index'); + } + + protected function getHeaderActions(): array + { + return [ + Action::make('back') + ->label('Kembali') + ->url(fn (): string => route('filament.dashboard.resources.monitoring.media-monitorings.index')) + ->outlined() + ->color('secondary'), + ]; + } + + protected function mutateFormDataBeforeCreate(array $data): array + { + $latestCode = MediaMonitoring::max('code'); + + $lastNumber = $latestCode + ? intval(substr($latestCode, 3)) + : 0; + + $newNumber = str_pad($lastNumber + 1, 6, '0', STR_PAD_LEFT); + + $data['code'] = 'ADN'.$newNumber; + + return $data; + } +} diff --git a/app/Filament/Resources/Monitoring/MediaMonitorings/Pages/EditMediaMonitoring.php b/app/Filament/Resources/Monitoring/MediaMonitorings/Pages/EditMediaMonitoring.php new file mode 100644 index 0000000..7581be5 --- /dev/null +++ b/app/Filament/Resources/Monitoring/MediaMonitorings/Pages/EditMediaMonitoring.php @@ -0,0 +1,28 @@ +label('Kembali') + ->url(fn (): string => route('filament.dashboard.resources.monitoring.media-monitorings.index')) + ->outlined() + ->color('secondary'), + ]; + } + + protected function getRedirectUrl(): string + { + return $this->getResource()::getUrl('index'); + } +} diff --git a/app/Filament/Resources/Monitoring/MediaMonitorings/Pages/ListMediaMonitorings.php b/app/Filament/Resources/Monitoring/MediaMonitorings/Pages/ListMediaMonitorings.php new file mode 100644 index 0000000..da62822 --- /dev/null +++ b/app/Filament/Resources/Monitoring/MediaMonitorings/Pages/ListMediaMonitorings.php @@ -0,0 +1,22 @@ +label('Tambah'), + ]; + } +} diff --git a/app/Filament/Resources/Monitoring/MediaMonitorings/Schemas/MediaMonitoringForm.php b/app/Filament/Resources/Monitoring/MediaMonitorings/Schemas/MediaMonitoringForm.php new file mode 100644 index 0000000..219b086 --- /dev/null +++ b/app/Filament/Resources/Monitoring/MediaMonitorings/Schemas/MediaMonitoringForm.php @@ -0,0 +1,122 @@ +components([ + Section::make([ + TextInput::make('media_name') + ->label('Nama Media') + ->placeholder('PWK News') + ->autocomplete(false) + ->autofocus() + ->required() + ->maxLength(50), + + TextInput::make('title') + ->label('Judul') + ->placeholder('Berita Purwakarta Hari Ini') + ->autocomplete(false) + ->required() + ->maxLength(255), + + Grid::make(2) + ->schema([ + TextInput::make('writter') + ->label('Penulis') + ->placeholder('John Doe') + ->autocomplete(false) + ->required() + ->maxLength(50), + + TextInput::make('news_page') + ->label('Halaman Berita') + ->placeholder('Halaman 1 s/d 10') + ->autocomplete(false) + ->nullable() + ->maxLength(20), + ]), + + TextInput::make('link') + ->label('Tautan') + ->placeholder('https://www.pwknews.com') + ->autocomplete(false) + ->nullable() + ->maxLength(50) + ->url(), + + RichEditor::make('quote') + ->label('Kutipan') + ->placeholder('....') + ->nullable(), + + RichEditor::make('content') + ->label('Konten') + ->placeholder('....') + ->required(), + ])->columnSpan(2), + + Section::make([ + Select::make('channel') + ->label('Kanal') + ->options(Channel::options()) + ->native(false) + ->required() + ->in(implode(',', array_column(Channel::cases(), 'value'))), + + Select::make('themes') + ->label('Tema') + ->relationship('themes', 'name') + ->native(false) + ->multiple() + ->preload() + ->required(), + + DatePicker::make('release_date') + ->label('Tanggal Rilis') + ->placeholder(fn () => now()->format('Y-m-d')) + ->native(false) + ->displayFormat('l, d F Y') + ->required(), + + TextInput::make('influencer') + ->label('Influencer') + ->placeholder('Sekretariat Daerah') + ->autocomplete(false) + ->nullable() + ->maxLength(50), + + TextInput::make('keyword') + ->label('Kata Kunci') + ->placeholder('Purwakarta, Berita Terbaru, Hari Ini') + ->autocomplete(false) + ->required() + ->maxLength(100), + + SpatieMediaLibraryFileUpload::make('image') + ->label('Gambar') + ->disk(config('filesystems.default')) + ->acceptedFileTypes(['images/*']) + ->maxSize(1024 * 3) + ->collection('media-monitorings') + ->image() + ->required(), + ]), + ]) + ->columns(3); + } +} diff --git a/app/Filament/Resources/Monitoring/MediaMonitorings/Tables/MediaMonitoringsTable.php b/app/Filament/Resources/Monitoring/MediaMonitorings/Tables/MediaMonitoringsTable.php new file mode 100644 index 0000000..ccb2660 --- /dev/null +++ b/app/Filament/Resources/Monitoring/MediaMonitorings/Tables/MediaMonitoringsTable.php @@ -0,0 +1,104 @@ +columns([ + TextColumn::make('code') + ->label('Kode') + ->searchable() + ->sortable(), + + TextColumn::make('media_name') + ->label('Nama media') + ->searchable() + ->sortable(), + + TextColumn::make('title') + ->label('Judul') + ->searchable() + ->sortable() + ->wrap(), + + TextColumn::make('channel') + ->label('Kanal') + ->searchable() + ->sortable(), + + TextColumn::make('writter') + ->label('Penulis') + ->searchable() + ->sortable(), + + TextColumn::make('link') + ->label('Tautan') + ->searchable() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + + TextColumn::make('news_page') + ->label('Halaman Berita') + ->searchable() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + + TextColumn::make('influencer') + ->searchable() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + + TextColumn::make('keyword') + ->searchable() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + + TextColumn::make('themes.name') + ->label('Tema') + ->searchable() + ->sortable() + ->wrap() + ->badge(), + + TextColumn::make('release_date') + ->label('Tgl Rilis') + ->searchable() + ->sortable() + ->date('l, d F Y'), + + ...TimestampColumns::make(), + ]) + ->filters([ + TrashedFilter::make()->native(false), + ]) + ->recordActions([ + EditAction::make(), + DeleteAction::make(), + ForceDeleteAction::make(), + RestoreAction::make(), + ]) + ->toolbarActions([ + BulkActionGroup::make([ + ...DefaultBulkActions::make('Monitoring Media'), + ]), + ]) + ->emptyStateIcon('heroicon-o-bookmark') + ->emptyStateDescription('Setelah Anda membubat data pertama, maka akan muncul disini.') + ->defaultSort('created_at', 'desc') + ->deferFilters(false); + } +} diff --git a/app/Models/MediaMonitoring.php b/app/Models/MediaMonitoring.php new file mode 100644 index 0000000..a45d51e --- /dev/null +++ b/app/Models/MediaMonitoring.php @@ -0,0 +1,21 @@ +belongsToMany(Theme::class); + } +} diff --git a/app/Models/MediaMonitoringTheme.php b/app/Models/MediaMonitoringTheme.php new file mode 100644 index 0000000..b340916 --- /dev/null +++ b/app/Models/MediaMonitoringTheme.php @@ -0,0 +1,12 @@ + 'integer', ]; } + + public function mediaMonitorings(): BelongsToMany + { + return $this->belongsToMany(MediaMonitoring::class); + } } diff --git a/database/migrations/2025_12_05_095022_create_media_monitorings_table.php b/database/migrations/2025_12_05_095022_create_media_monitorings_table.php new file mode 100644 index 0000000..004efb1 --- /dev/null +++ b/database/migrations/2025_12_05_095022_create_media_monitorings_table.php @@ -0,0 +1,41 @@ +id(); + $table->string('code', 10); + $table->string('media_name', 50); + $table->text('title', 255); + $table->string('channel', 20); + $table->string('writter', 50); + $table->text('link', 50)->nullable(); + $table->string('news_page', 20)->nullable(); + $table->text('quote')->nullable(); + $table->text('content'); + $table->string('influencer', 50)->nullable(); + $table->string('keyword', 100); + $table->date('release_date'); + $table->timestamp('created_at')->useCurrent(); + $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('media_monitorings'); + } +}; diff --git a/database/migrations/2025_12_05_100045_create_media_monitoring_theme_table.php b/database/migrations/2025_12_05_100045_create_media_monitoring_theme_table.php new file mode 100644 index 0000000..5542bc9 --- /dev/null +++ b/database/migrations/2025_12_05_100045_create_media_monitoring_theme_table.php @@ -0,0 +1,32 @@ +id(); + $table->foreignIdFor(MediaMonitoring::class); + $table->foreignIdFor(Theme::class); + $table->timestamp('created_at')->useCurrent(); + $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('media_monitoring_theme'); + } +};