diff --git a/app/Filament/Resources/Manage/Journalists/JournalistResource.php b/app/Filament/Resources/Manage/Journalists/JournalistResource.php
index 3934a6f..e8cb190 100644
--- a/app/Filament/Resources/Manage/Journalists/JournalistResource.php
+++ b/app/Filament/Resources/Manage/Journalists/JournalistResource.php
@@ -3,32 +3,14 @@
namespace App\Filament\Resources\Manage\Journalists;
use App\Enums\RoleEnum;
-use App\Enums\VerificationStatus;
-use App\Filament\Actions\Cheerful\ForceDeleteAction;
-use App\Filament\Actions\Cheerful\RestoreAction;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Columns\TimestampColumns;
-use App\Filament\Pages\Media;
-use App\Filament\Resources\Manage\Journalists\Actions\DeleteJournalistAction;
-use App\Filament\Resources\Manage\Journalists\Actions\EditJournalistAction;
use App\Filament\Resources\Manage\Journalists\Pages\ManageJournalists;
-use App\Filament\Support\CheerfulNotification;
+use App\Filament\Resources\Manage\Journalists\Schemas\JournalistForm;
+use App\Filament\Resources\Manage\Journalists\Tables\JournalistTable;
use App\Models\Journalist;
-use Asmit\FilamentUpload\Forms\Components\AdvancedFileUpload;
use BackedEnum;
-use Filament\Actions\Action;
-use Filament\Actions\BulkActionGroup;
-use Filament\Actions\DeleteBulkAction;
-use Filament\Actions\ForceDeleteBulkAction;
-use Filament\Actions\RestoreBulkAction;
-use Filament\Forms\Components\Group;
-use Filament\Forms\Components\Textarea;
-use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
@@ -52,180 +34,12 @@ class JournalistResource extends Resource
public static function form(Schema $schema): Schema
{
- $documents = [
- [
- 'title' => 'Dokumen Pers',
- 'text_name' => 'press_card',
- 'placeholder' => '*****',
- 'max' => 100,
- 'max_size' => 1024 * 10,
- 'file_name' => 'press_card_docs',
- 'accept' => ['application/pdf'],
- 'folder' => 'press-card/',
- ],
- [
- 'title' => 'Sertifikat UKW',
- 'text_name' => 'ukw_certificate',
- 'placeholder' => '*****',
- 'max' => 100,
- 'max_size' => 1024 * 10,
- 'file_name' => 'ukw_certificate_docs',
- 'accept' => ['application/pdf'],
- 'folder' => 'ukw-certificate/',
- ],
- ];
-
- return $schema
- ->components([
- TextInput::make('name')
- ->label('Nama Lengkap')
- ->placeholder('John Doe')
- ->autocomplete(false)
- ->autofocus()
- ->required()
- ->maxLength(100),
-
- TextInput::make('email')
- ->label('Alamat Surel')
- ->placeholder('johndoe@example.com')
- ->autocomplete(false)
- ->required()
- ->maxLength(254)
- ->email()
- ->prefixIcon('heroicon-o-envelope'),
-
- TextInput::make('phone_number')
- ->label('Nomor Telepon')
- ->placeholder('08xx xxxx xxxx')
- ->autocomplete(false)
- ->required()
- ->maxLength(20)
- ->tel()
- ->prefixIcon('heroicon-o-phone'),
-
- Group::make()
- ->schema(
- collect($documents)
- ->map(function (array $doc): array {
- return [
- TextInput::make($doc['text_name'])
- ->label('Nomor Identitas ('.$doc['title'].')')
- ->placeholder($doc['placeholder'])
- ->autocomplete(false)
- ->required()
- ->maxLength($doc['max']),
-
- AdvancedFileUpload::make($doc['file_name'])
- ->label('File Pendukung ('.$doc['title'].') (PDF)')
- ->disk(config('filesystems.default'))
- ->acceptedFileTypes($doc['accept'])
- ->directory(fn (): string => 'journalists/'.$doc['folder'].now()->toDateString())
- ->maxSize($doc['max_size'])
- ->helperText('Format yang diterima: '.implode(', ', array_map(fn ($t) => strtoupper(str_replace('application/', '', $t)), $doc['accept'])).'. Ukuran maksimum: '.($doc['max_size'] / 1024).' MB.')
- ->required(),
- ];
- })
- ->flatten()
- ->toArray()
- ),
-
- Textarea::make('change_reason')
- ->label('Alasan Perubahan')
- ->placeholder('Jelaskan alasan perubahan data ini...')
- ->rows(3)
- ->required()
- ->visible(fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED && auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
- ])
- ->columns(1);
+ return JournalistForm::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('name')
- ->label('Nama')
- ->searchable()
- ->sortable(),
-
- TextColumn::make('email')
- ->label('Alamat Surel')
- ->searchable()
- ->sortable(),
-
- TextColumn::make('phone_number')
- ->label('Nomor Telepon')
- ->searchable()
- ->sortable(),
-
- TextColumn::make('press_card')
- ->label('Dokumen Pers')
- ->searchable()
- ->sortable()
- ->wrap(),
-
- TextColumn::make('ukw_certificate')
- ->label('Sertifikat UKW')
- ->searchable()
- ->sortable()
- ->wrap(),
-
- ...TimestampColumns::make(),
- ])
- ->filters([
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->checkIfRecordIsSelectableUsing(
- fn () => ! (
- in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) ||
- auth()->user()->company?->verificationRequest()->pending()->exists()
- )
- )
- ->recordActions([
- EditJournalistAction::make('edit')
- ->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
-
- DeleteJournalistAction::make('delete')
- ->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
-
- ForceDeleteAction::make()
- ->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
-
- RestoreAction::make()
- ->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- DeleteBulkAction::make(),
-
- ForceDeleteBulkAction::make(),
-
- RestoreBulkAction::make(),
- ])->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
- ])
- ->emptyStateIcon(Heroicon::OutlinedIdentification)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('journalist.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('journalist.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading()
- ->when(fn () => auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value) && ! auth()->user()->company?->partnerMedia, function (Table $table): Table {
- return $table
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('access.restricted'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('access.complete_media_data'))
- ->emptyStateIcon(Heroicon::OutlinedLockClosed)
- ->emptyStateActions([
- Action::make('complete_media')
- ->label('Lengkapi Data Media')
- ->url(Media::getUrl())
- ->button(),
- ]);
- });
+ return JournalistTable::configure($table);
}
public static function getPages(): array
diff --git a/app/Filament/Resources/Manage/Journalists/Schemas/JournalistForm.php b/app/Filament/Resources/Manage/Journalists/Schemas/JournalistForm.php
new file mode 100644
index 0000000..2c4cdef
--- /dev/null
+++ b/app/Filament/Resources/Manage/Journalists/Schemas/JournalistForm.php
@@ -0,0 +1,103 @@
+ 'Dokumen Pers',
+ 'text_name' => 'press_card',
+ 'placeholder' => '*****',
+ 'max' => 100,
+ 'max_size' => 1024 * 10,
+ 'file_name' => 'press_card_docs',
+ 'accept' => ['application/pdf'],
+ 'folder' => 'press-card/',
+ ],
+ [
+ 'title' => 'Sertifikat UKW',
+ 'text_name' => 'ukw_certificate',
+ 'placeholder' => '*****',
+ 'max' => 100,
+ 'max_size' => 1024 * 10,
+ 'file_name' => 'ukw_certificate_docs',
+ 'accept' => ['application/pdf'],
+ 'folder' => 'ukw-certificate/',
+ ],
+ ];
+
+ return $schema
+ ->components([
+ TextInput::make('name')
+ ->label('Nama Lengkap')
+ ->placeholder('John Doe')
+ ->autocomplete(false)
+ ->autofocus()
+ ->required()
+ ->maxLength(100),
+
+ TextInput::make('email')
+ ->label('Alamat Surel')
+ ->placeholder('johndoe@example.com')
+ ->autocomplete(false)
+ ->required()
+ ->maxLength(254)
+ ->email()
+ ->prefixIcon('heroicon-o-envelope'),
+
+ TextInput::make('phone_number')
+ ->label('Nomor Telepon')
+ ->placeholder('08xx xxxx xxxx')
+ ->autocomplete(false)
+ ->required()
+ ->maxLength(20)
+ ->tel()
+ ->prefixIcon('heroicon-o-phone'),
+
+ Group::make()
+ ->schema(
+ collect($documents)
+ ->map(function (array $doc): array {
+ return [
+ TextInput::make($doc['text_name'])
+ ->label('Nomor Identitas ('.$doc['title'].')')
+ ->placeholder($doc['placeholder'])
+ ->autocomplete(false)
+ ->required()
+ ->maxLength($doc['max']),
+
+ AdvancedFileUpload::make($doc['file_name'])
+ ->label('File Pendukung ('.$doc['title'].') (PDF)')
+ ->disk(config('filesystems.default'))
+ ->acceptedFileTypes($doc['accept'])
+ ->directory(fn (): string => 'journalists/'.$doc['folder'].now()->toDateString())
+ ->maxSize($doc['max_size'])
+ ->helperText('Format yang diterima: '.implode(', ', array_map(fn ($t) => strtoupper(str_replace('application/', '', $t)), $doc['accept'])).'. Ukuran maksimum: '.($doc['max_size'] / 1024).' MB.')
+ ->required(),
+ ];
+ })
+ ->flatten()
+ ->toArray()
+ ),
+
+ Textarea::make('change_reason')
+ ->label('Alasan Perubahan')
+ ->placeholder('Jelaskan alasan perubahan data ini...')
+ ->rows(3)
+ ->required()
+ ->visible(fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED && auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Manage/Journalists/Tables/JournalistTable.php b/app/Filament/Resources/Manage/Journalists/Tables/JournalistTable.php
new file mode 100644
index 0000000..401c7ed
--- /dev/null
+++ b/app/Filament/Resources/Manage/Journalists/Tables/JournalistTable.php
@@ -0,0 +1,115 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('name')
+ ->label('Nama')
+ ->searchable()
+ ->sortable(),
+
+ TextColumn::make('email')
+ ->label('Alamat Surel')
+ ->searchable()
+ ->sortable(),
+
+ TextColumn::make('phone_number')
+ ->label('Nomor Telepon')
+ ->searchable()
+ ->sortable(),
+
+ TextColumn::make('press_card')
+ ->label('Dokumen Pers')
+ ->searchable()
+ ->sortable()
+ ->wrap(),
+
+ TextColumn::make('ukw_certificate')
+ ->label('Sertifikat UKW')
+ ->searchable()
+ ->sortable()
+ ->wrap(),
+
+ ...TimestampColumns::make(),
+ ])
+ ->filters([
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->checkIfRecordIsSelectableUsing(
+ fn () => ! (
+ in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) ||
+ auth()->user()->company?->verificationRequest()->pending()->exists()
+ )
+ )
+ ->recordActions([
+ EditJournalistAction::make('edit')
+ ->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
+
+ DeleteJournalistAction::make('delete')
+ ->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
+
+ ForceDeleteAction::make()
+ ->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
+
+ RestoreAction::make()
+ ->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ DeleteBulkAction::make(),
+
+ ForceDeleteBulkAction::make(),
+
+ RestoreBulkAction::make(),
+ ])->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedIdentification)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('journalist.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('journalist.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading()
+ ->when(fn () => auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value) && ! auth()->user()->company?->partnerMedia, function (Table $table): Table {
+ return $table
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('access.restricted'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('access.complete_media_data'))
+ ->emptyStateIcon(Heroicon::OutlinedLockClosed)
+ ->emptyStateActions([
+ Action::make('complete_media')
+ ->label('Lengkapi Data Media')
+ ->url(Media::getUrl())
+ ->button(),
+ ]);
+ });
+ }
+}
diff --git a/app/Filament/Resources/Manage/Partners/Infolists/PartnerInfolist.php b/app/Filament/Resources/Manage/Partners/Infolists/PartnerInfolist.php
new file mode 100644
index 0000000..5042e08
--- /dev/null
+++ b/app/Filament/Resources/Manage/Partners/Infolists/PartnerInfolist.php
@@ -0,0 +1,306 @@
+schema([
+ Section::make(fn () => CheerfulNotification::getByKey('company.account_title'))
+ ->description(fn () => CheerfulNotification::getByKey('company.account_desc'))
+ ->schema([
+ Grid::make(3)
+ ->schema([
+ TextEntry::make('name')
+ ->label('Nama'),
+
+ TextEntry::make('email')
+ ->label('Email'),
+
+ TextEntry::make('username')
+ ->label('Nama Pengguna'),
+
+ TextEntry::make('is_active')
+ ->label('Status')
+ ->badge(),
+
+ TextEntry::make('email_verified_at')
+ ->label('Email Verifikasi')
+ ->placeholder('Akun Belum Diverifikasi')
+ ->dateTime('l, d F Y H:i'),
+ ]),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.company_title'))
+ ->description(fn () => CheerfulNotification::getByKey('company.company_desc'))
+ ->schema([
+ Grid::make(3)
+ ->schema([
+ TextEntry::make('company.name')
+ ->label('Nama'),
+
+ TextEntry::make('company.email')
+ ->label('Email'),
+
+ TextEntry::make('company.phone_number')
+ ->label('Nomor Telepon'),
+
+ TextEntry::make('company.address')
+ ->label('Alamat'),
+
+ TextEntry::make('company.phone_number')
+ ->label('No. Telepon'),
+
+ TextEntry::make('company.director_name')
+ ->label('Nama Direktur'),
+
+ TextEntry::make('company.verificationRequest.created_at')
+ ->label('Tanggal Pengajuan Verifikasi')
+ ->dateTime('d F Y H:i'),
+
+ TextEntry::make('company.verificationRequest.latestReview.decision')
+ ->label('Status Verifikasi')
+ ->badge(),
+
+ TextEntry::make('company.verificationRequest.latestReview.created_at')
+ ->label('Tanggal Verifikasi')
+ ->dateTime('d F Y H:i')
+ ->visible(fn (User $record): ?string => $record->company?->verificationRequest?->latestReview),
+
+ TextEntry::make('company.verificationRequest.latestReview.note')
+ ->label('Alasan Penolakan')
+ ->visible(fn (User $record): ?string => $record->company?->verificationRequest?->latestReview?->decision === DecisionAdmin::REJECTED),
+ ]),
+
+ Grid::make(3)
+ ->schema([
+ Section::make(fn () => CheerfulNotification::getByKey('company.director_nik'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-user' : null)
+ ->schema([
+ TextEntry::make('company.director_nik')
+ ->hiddenLabel(),
+
+ TextEntry::make('company.director_nik_docs')
+ ->hiddenLabel()
+ ->html()
+ ->getStateUsing(function (User $record): string {
+ $media = $record->company
+ ?->getMedia('companies')
+ ->where('custom_properties.doc_type', 'director-nik')
+ ->sortByDesc('created_at')
+ ->first();
+
+ if (! $media) {
+ return '';
+ }
+
+ $url = $media->getUrl();
+ $mime = $media->mime_type;
+
+ if (str_contains($mime, 'image')) {
+ return '
';
+ }
+
+ if (str_contains($mime, 'pdf')) {
+ return '';
+ }
+
+ return 'Unduh Dokumen';
+ }),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.establishment_deed'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
+ ->schema([
+ TextEntry::make('company.deed_incorporation')
+ ->hiddenLabel(),
+
+ self::fileEntry('company.deed_incorporation'),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.siup_nib'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
+ ->schema([
+ TextEntry::make('company.trade_license')
+ ->hiddenLabel(),
+
+ self::fileEntry('company.trade_license'),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.npwp'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
+ ->schema([
+ TextEntry::make('company.tax_id_number')
+ ->hiddenLabel(),
+
+ self::fileEntry('company.tax_id_number'),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.pkp'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
+ ->schema([
+ TextEntry::make('company.taxable_enterprise')
+ ->hiddenLabel(),
+
+ self::fileEntry('company.taxable_enterprise'),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.annual_tax'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
+ ->schema([
+ TextEntry::make('company.annual_tax_return')
+ ->hiddenLabel(),
+
+ self::fileEntry('company.annual_tax_return'),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.domicile'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
+ ->schema([
+ TextEntry::make('company.domicile_certificate')
+ ->hiddenLabel(),
+
+ self::fileEntry('company.domicile_certificate'),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.company_profile'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
+ ->schema([
+ TextEntry::make('company.profile')
+ ->hiddenLabel(),
+
+ self::fileEntry('company.profile'),
+ ]),
+ ]),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.media_title'))
+ ->description(fn () => CheerfulNotification::getByKey('company.media_desc'))
+ ->schema([
+ Grid::make(4)
+ ->schema([
+ TextEntry::make('company.partnerMedia.name')
+ ->label('Nama'),
+
+ TextEntry::make('company.partnerMedia.link')
+ ->label('Tautan')
+ ->url(fn (User $record): ?string => $record->company?->partnerMedia?->link, true),
+
+ TextEntry::make('company.partnerMedia.type')
+ ->label('Jenis')
+ ->badge(),
+
+ TextEntry::make('company.partnerMedia.classification')
+ ->label('Klasifikasi')
+ ->badge(),
+
+ TextEntry::make('company.partnerMedia.address')
+ ->label('Alamat')
+ ->columnSpanFull(),
+ ]),
+
+ Grid::make(2)
+ ->schema([
+ Section::make(fn () => CheerfulNotification::getByKey('company.journalism_org_cert'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
+ ->schema([
+ TextEntry::make('company.partnerMedia.journalism_organization')
+ ->hiddenLabel(),
+
+ self::fileEntry('company.partnerMedia.journalism_organization', 'company.partnerMedia', 'partnerMedia'),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.press_council_cert'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
+ ->schema([
+ TextEntry::make('company.partnerMedia.press_council_certificate')
+ ->hiddenLabel(),
+
+ self::fileEntry('company.partnerMedia.press_council_certificate', 'company.partnerMedia', 'partnerMedia'),
+ ]),
+ ]),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.journalist_title'))
+ ->description(fn () => CheerfulNotification::getByKey('company.journalist_desc'))
+ ->schema([
+ RepeatableEntry::make('company.partnerMedia.journalists')
+ ->hiddenLabel()
+ ->schema([
+ Grid::make(3)
+ ->schema([
+ TextEntry::make('name')
+ ->label('Nama'),
+
+ TextEntry::make('email')
+ ->label('Email'),
+
+ TextEntry::make('phone_number')
+ ->label('No. Telepon'),
+ ]),
+ Grid::make(2)
+ ->schema([
+ Section::make(fn () => CheerfulNotification::getByKey('company.press_card'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-identification' : null)
+ ->schema([
+ TextEntry::make('press_card')
+ ->hiddenLabel(),
+
+ self::fileEntry('press_card', null, 'journalists'),
+ ]),
+
+ Section::make(fn () => CheerfulNotification::getByKey('company.ukw_cert'))
+ ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
+ ->schema([
+ TextEntry::make('ukw_certificate')
+ ->hiddenLabel(),
+
+ self::fileEntry('ukw_certificate', null, 'journalists'),
+ ]),
+ ]),
+ ]),
+ ]),
+ ])
+ ->columns(1);
+ }
+
+ private static function fileEntry(
+ string $name,
+ ?string $mediaOwner = 'company',
+ string $collection = 'companies'
+ ): PdfViewerEntry {
+ return PdfViewerEntry::make($name)
+ ->hiddenLabel()
+ ->getStateUsing(function (Model $record) use ($name, $mediaOwner, $collection): ?string {
+ $owner = $mediaOwner ? data_get($record, $mediaOwner) : $record;
+
+ if (! $owner) {
+ return null;
+ }
+
+ $docType = str($name)
+ ->afterLast('.')
+ ->slug('-');
+
+ return $owner->getMedia($collection)
+ ->where('custom_properties.doc_type', (string) $docType)
+ ->sortByDesc('created_at')
+ ->first()
+ ?->getUrl();
+ });
+ }
+}
diff --git a/app/Filament/Resources/Manage/Partners/PartnerResource.php b/app/Filament/Resources/Manage/Partners/PartnerResource.php
index 11cf693..32cfc93 100644
--- a/app/Filament/Resources/Manage/Partners/PartnerResource.php
+++ b/app/Filament/Resources/Manage/Partners/PartnerResource.php
@@ -2,36 +2,17 @@
namespace App\Filament\Resources\Manage\Partners;
-use App\Enums\DecisionAdmin;
-use App\Enums\MediaClassification;
-use App\Enums\MediaType;
-use App\Enums\NotifStyle;
-use App\Enums\RoleEnum;
-use App\Enums\VerificationStatus;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
+use App\Filament\Resources\Manage\Partners\Infolists\PartnerInfolist;
use App\Filament\Resources\Manage\Partners\Pages\ManagePartners;
use App\Filament\Resources\Manage\Partners\Pages\ViewPartner;
-use App\Filament\Support\CheerfulNotification;
+use App\Filament\Resources\Manage\Partners\Tables\PartnerTable;
use App\Models\User;
use BackedEnum;
-use Filament\Actions\BulkActionGroup;
-use Filament\Actions\ViewAction;
-use Filament\Infolists\Components\RepeatableEntry;
-use Filament\Infolists\Components\TextEntry;
use Filament\Resources\Resource;
-use Filament\Schemas\Components\Grid;
-use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Filters\SelectFilter;
-use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
-use Illuminate\Database\Eloquent\Model;
-use Illuminate\Support\HtmlString;
-use Joaopaulolndev\FilamentPdfViewer\Infolists\Components\PdfViewerEntry;
use UnitEnum;
class PartnerResource extends Resource
@@ -52,375 +33,12 @@ class PartnerResource extends Resource
public static function infolist(Schema $schema): Schema
{
- return $schema
- ->schema([
- Section::make(fn () => CheerfulNotification::getByKey('company.account_title'))
- ->description(fn () => CheerfulNotification::getByKey('company.account_desc'))
- ->schema([
- Grid::make(3)
- ->schema([
- TextEntry::make('name')
- ->label('Nama'),
-
- TextEntry::make('email')
- ->label('Email'),
-
- TextEntry::make('username')
- ->label('Nama Pengguna'),
-
- TextEntry::make('is_active')
- ->label('Status')
- ->badge(),
-
- TextEntry::make('email_verified_at')
- ->label('Email Verifikasi')
- ->placeholder('Akun Belum Diverifikasi')
- ->dateTime('l, d F Y H:i'),
- ]),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.company_title'))
- ->description(fn () => CheerfulNotification::getByKey('company.company_desc'))
- ->schema([
- Grid::make(3)
- ->schema([
- TextEntry::make('company.name')
- ->label('Nama'),
-
- TextEntry::make('company.email')
- ->label('Email'),
-
- TextEntry::make('company.phone_number')
- ->label('Nomor Telepon'),
-
- TextEntry::make('company.address')
- ->label('Alamat'),
-
- TextEntry::make('company.phone_number')
- ->label('No. Telepon'),
-
- TextEntry::make('company.director_name')
- ->label('Nama Direktur'),
-
- TextEntry::make('company.verificationRequest.created_at')
- ->label('Tanggal Pengajuan Verifikasi')
- ->dateTime('d F Y H:i'),
-
- TextEntry::make('company.verificationRequest.latestReview.decision')
- ->label('Status Verifikasi')
- ->badge(),
-
- TextEntry::make('company.verificationRequest.latestReview.created_at')
- ->label('Tanggal Verifikasi')
- ->dateTime('d F Y H:i')
- ->visible(fn (User $record): ?string => $record->company?->verificationRequest?->latestReview),
-
- TextEntry::make('company.verificationRequest.latestReview.note')
- ->label('Alasan Penolakan')
- ->visible(fn (User $record): ?string => $record->company?->verificationRequest?->latestReview?->decision === DecisionAdmin::REJECTED),
- ]),
-
- Grid::make(3)
- ->schema([
- Section::make(fn () => CheerfulNotification::getByKey('company.director_nik'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-user' : null)
- ->schema([
- TextEntry::make('company.director_nik')
- ->hiddenLabel(),
-
- TextEntry::make('company.director_nik_docs')
- ->hiddenLabel()
- ->html()
- ->getStateUsing(function (User $record): string {
- $media = $record->company
- ?->getMedia('companies')
- ->where('custom_properties.doc_type', 'director-nik')
- ->sortByDesc('created_at')
- ->first();
-
- if (! $media) {
- return '';
- }
-
- $url = $media->getUrl();
- $mime = $media->mime_type;
-
- if (str_contains($mime, 'image')) {
- return '
';
- }
-
- if (str_contains($mime, 'pdf')) {
- return '';
- }
-
- return 'Unduh Dokumen';
- }),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.establishment_deed'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
- ->schema([
- TextEntry::make('company.deed_incorporation')
- ->hiddenLabel(),
-
- self::fileEntry('company.deed_incorporation'),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.siup_nib'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
- ->schema([
- TextEntry::make('company.trade_license')
- ->hiddenLabel(),
-
- self::fileEntry('company.trade_license'),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.npwp'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
- ->schema([
- TextEntry::make('company.tax_id_number')
- ->hiddenLabel(),
-
- self::fileEntry('company.tax_id_number'),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.pkp'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
- ->schema([
- TextEntry::make('company.taxable_enterprise')
- ->hiddenLabel(),
-
- self::fileEntry('company.taxable_enterprise'),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.annual_tax'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
- ->schema([
- TextEntry::make('company.annual_tax_return')
- ->hiddenLabel(),
-
- self::fileEntry('company.annual_tax_return'),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.domicile'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
- ->schema([
- TextEntry::make('company.domicile_certificate')
- ->hiddenLabel(),
-
- self::fileEntry('company.domicile_certificate'),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.company_profile'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
- ->schema([
- TextEntry::make('company.profile')
- ->hiddenLabel(),
-
- self::fileEntry('company.profile'),
- ]),
- ]),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.media_title'))
- ->description(fn () => CheerfulNotification::getByKey('company.media_desc'))
- ->schema([
- Grid::make(4)
- ->schema([
- TextEntry::make('company.partnerMedia.name')
- ->label('Nama'),
-
- TextEntry::make('company.partnerMedia.link')
- ->label('Tautan')
- ->url(fn (User $record): ?string => $record->company?->partnerMedia?->link, true),
-
- TextEntry::make('company.partnerMedia.type')
- ->label('Jenis')
- ->badge(),
-
- TextEntry::make('company.partnerMedia.classification')
- ->label('Klasifikasi')
- ->badge(),
-
- TextEntry::make('company.partnerMedia.address')
- ->label('Alamat')
- ->columnSpanFull(),
- ]),
-
- Grid::make(2)
- ->schema([
- Section::make(fn () => CheerfulNotification::getByKey('company.journalism_org_cert'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
- ->schema([
- TextEntry::make('company.partnerMedia.journalism_organization')
- ->hiddenLabel(),
-
- self::fileEntry('company.partnerMedia.journalism_organization', 'company.partnerMedia', 'partnerMedia'),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.press_council_cert'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
- ->schema([
- TextEntry::make('company.partnerMedia.press_council_certificate')
- ->hiddenLabel(),
-
- self::fileEntry('company.partnerMedia.press_council_certificate', 'company.partnerMedia', 'partnerMedia'),
- ]),
- ]),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.journalist_title'))
- ->description(fn () => CheerfulNotification::getByKey('company.journalist_desc'))
- ->schema([
- RepeatableEntry::make('company.partnerMedia.journalists')
- ->hiddenLabel()
- ->schema([
- Grid::make(3)
- ->schema([
- TextEntry::make('name')
- ->label('Nama'),
-
- TextEntry::make('email')
- ->label('Email'),
-
- TextEntry::make('phone_number')
- ->label('No. Telepon'),
- ]),
- Grid::make(2)
- ->schema([
- Section::make(fn () => CheerfulNotification::getByKey('company.press_card'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-identification' : null)
- ->schema([
- TextEntry::make('press_card')
- ->hiddenLabel(),
-
- self::fileEntry('press_card', null, 'journalists'),
- ]),
-
- Section::make(fn () => CheerfulNotification::getByKey('company.ukw_cert'))
- ->icon(fn () => CheerfulNotification::getNotifStyle() === NotifStyle::CHEERFUL ? 'heroicon-o-document-text' : null)
- ->schema([
- TextEntry::make('ukw_certificate')
- ->hiddenLabel(),
-
- self::fileEntry('ukw_certificate', null, 'journalists'),
- ]),
- ]),
- ]),
- ]),
- ])
- ->columns(1);
+ return PartnerInfolist::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('company.name')
- ->label('Perusahaan')
- ->searchable(query: function ($query, $search) {
- $query->whereHas('company', function ($q) use ($search) {
- $q->where('companies.name', 'like', "%{$search}%")
- ->orWhere('companies.director_name', 'like', "%{$search}%");
- });
- })
- ->sortable()
- ->description(
- fn (User $record) => new HtmlString(
- 'Akun: '.$record->name.
- '
Direktur: '.$record->company?->director_name
- )
- ),
-
- TextColumn::make('company.partnerMedia.name')
- ->label('Media')
- ->searchable(query: function ($query, $search) {
- $query->whereHas('company.partnerMedia', function ($q) use ($search) {
- $q->where('partner_media.name', 'like', "%{$search}%");
- });
- })
- ->sortable(),
-
- TextColumn::make('company.journalists.name')
- ->label('Jurnalis')
- ->searchable(query: function ($query, $search) {
- $query->whereHas('company.journalists', function ($q) use ($search) {
- $q->where('journalists.name', 'like', "%{$search}%");
- });
- })
- ->sortable()
- ->badge(),
-
- TextColumn::make('status')
- ->label('Status')
- ->badge()
- ->getStateUsing(function ($record) {
- return $record->company->verificationRequest
- ? $record->company->verificationRequest->status->getLabel()
- : 'Belum Mengajukan';
- })
- ->color(function ($record) {
- return $record->company->verificationRequest
- ? $record->company->verificationRequest->status->getColor()
- : 'gray';
- }),
-
- TextColumn::make('created_at')
- ->label('Tgl Daftar')
- ->date()
- ->sortable()
- ->dateTime('l, d F Y H:i:s')
- ->wrap(),
- ])
- ->filters([
- SelectFilter::make('media_type')
- ->label('Jenis Media')
- ->options(MediaType::class)
- ->query(fn (Builder $query, array $data) => $query->when(
- $data['value'],
- fn (Builder $query, $value) => $query->whereHas('company.partnerMedia', fn ($q) => $q->where('type', $value))
- ))
- ->native(false),
-
- SelectFilter::make('media_classification')
- ->label('Klasifikasi Media')
- ->options(MediaClassification::class)
- ->query(fn (Builder $query, array $data) => $query->when(
- $data['value'],
- fn (Builder $query, $value) => $query->whereHas('company.partnerMedia', fn ($q) => $q->where('classification', $value))
- ))
- ->native(false),
-
- SelectFilter::make('verification_status')
- ->label('Status Verifikasi')
- ->options(VerificationStatus::class)
- ->query(fn (Builder $query, array $data) => $query->when(
- $data['value'],
- fn (Builder $query, $value) => $query->whereHas('company.verificationRequest', fn ($q) => $q->where('status', $value))
- ))
- ->native(false),
-
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- ViewAction::make(),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('rekanan'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedBuildingOffice2)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('company.partner_empty_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('company.partner_empty'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading();
+ return PartnerTable::configure($table);
}
public static function getEloquentQuery(): Builder
@@ -437,30 +55,4 @@ public static function getPages(): array
'view' => ViewPartner::route('/{record}'),
];
}
-
- private static function fileEntry(
- string $name,
- ?string $mediaOwner = 'company',
- string $collection = 'companies'
- ): PdfViewerEntry {
- return PdfViewerEntry::make($name)
- ->hiddenLabel()
- ->getStateUsing(function (Model $record) use ($name, $mediaOwner, $collection): ?string {
- $owner = data_get($record, $mediaOwner);
-
- if (! $owner) {
- return null;
- }
-
- $docType = str($name)
- ->afterLast('.')
- ->slug('-');
-
- return $owner->getMedia($collection)
- ->where('custom_properties.doc_type', (string) $docType)
- ->sortByDesc('created_at')
- ->first()
- ?->getUrl();
- });
- }
}
diff --git a/app/Filament/Resources/Manage/Partners/Tables/PartnerTable.php b/app/Filament/Resources/Manage/Partners/Tables/PartnerTable.php
new file mode 100644
index 0000000..e9549d4
--- /dev/null
+++ b/app/Filament/Resources/Manage/Partners/Tables/PartnerTable.php
@@ -0,0 +1,135 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('company.name')
+ ->label('Perusahaan')
+ ->searchable(query: function ($query, $search) {
+ $query->whereHas('company', function ($q) use ($search) {
+ $q->where('companies.name', 'like', "%{$search}%")
+ ->orWhere('companies.director_name', 'like', "%{$search}%");
+ });
+ })
+ ->sortable()
+ ->description(
+ fn (User $record) => new HtmlString(
+ 'Akun: '.$record->name.
+ '
Direktur: '.$record->company?->director_name
+ )
+ ),
+
+ TextColumn::make('company.partnerMedia.name')
+ ->label('Media')
+ ->searchable(query: function ($query, $search) {
+ $query->whereHas('company.partnerMedia', function ($q) use ($search) {
+ $q->where('partner_media.name', 'like', "%{$search}%");
+ });
+ })
+ ->sortable(),
+
+ TextColumn::make('company.journalists.name')
+ ->label('Jurnalis')
+ ->searchable(query: function ($query, $search) {
+ $query->whereHas('company.journalists', function ($q) use ($search) {
+ $q->where('journalists.name', 'like', "%{$search}%");
+ });
+ })
+ ->sortable()
+ ->badge(),
+
+ TextColumn::make('status')
+ ->label('Status')
+ ->badge()
+ ->getStateUsing(function ($record) {
+ return $record->company->verificationRequest
+ ? $record->company->verificationRequest->status->getLabel()
+ : 'Belum Mengajukan';
+ })
+ ->color(function ($record) {
+ return $record->company->verificationRequest
+ ? $record->company->verificationRequest->status->getColor()
+ : 'gray';
+ }),
+
+ TextColumn::make('created_at')
+ ->label('Tgl Daftar')
+ ->date()
+ ->sortable()
+ ->dateTime('l, d F Y H:i:s')
+ ->wrap(),
+ ])
+ ->filters([
+ SelectFilter::make('media_type')
+ ->label('Jenis Media')
+ ->options(MediaType::class)
+ ->query(fn (Builder $query, array $data) => $query->when(
+ $data['value'],
+ fn (Builder $query, $value) => $query->whereHas('company.partnerMedia', fn ($q) => $q->where('type', $value))
+ ))
+ ->native(false),
+
+ SelectFilter::make('media_classification')
+ ->label('Klasifikasi Media')
+ ->options(MediaClassification::class)
+ ->query(fn (Builder $query, array $data) => $query->when(
+ $data['value'],
+ fn (Builder $query, $value) => $query->whereHas('company.partnerMedia', fn ($q) => $q->where('classification', $value))
+ ))
+ ->native(false),
+
+ SelectFilter::make('verification_status')
+ ->label('Status Verifikasi')
+ ->options(VerificationStatus::class)
+ ->query(fn (Builder $query, array $data) => $query->when(
+ $data['value'],
+ fn (Builder $query, $value) => $query->whereHas('company.verificationRequest', fn ($q) => $q->where('status', $value))
+ ))
+ ->native(false),
+
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ ViewAction::make(),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('rekanan'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedBuildingOffice2)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('company.partner_empty_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('company.partner_empty'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading();
+ }
+}
diff --git a/app/Filament/Resources/Master/Categories/CategoryResource.php b/app/Filament/Resources/Master/Categories/CategoryResource.php
index 2e566ae..c43bfdd 100644
--- a/app/Filament/Resources/Master/Categories/CategoryResource.php
+++ b/app/Filament/Resources/Master/Categories/CategoryResource.php
@@ -2,29 +2,14 @@
namespace App\Filament\Resources\Master\Categories;
-use App\Enums\IsActive;
-use App\Enums\RoleEnum;
-use App\Filament\Actions\Cheerful\DeleteAction;
-use App\Filament\Actions\Cheerful\EditAction;
-use App\Filament\Actions\Cheerful\ForceDeleteAction;
-use App\Filament\Actions\Cheerful\RestoreAction;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Columns\TimestampColumns;
use App\Filament\Resources\Master\Categories\Pages\ManageCategories;
-use App\Filament\Support\CheerfulNotification;
+use App\Filament\Resources\Master\Categories\Schemas\CategoryForm;
+use App\Filament\Resources\Master\Categories\Tables\CategoryTable;
use App\Models\Category;
use BackedEnum;
-use Filament\Actions\BulkActionGroup;
-use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
-use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Columns\ToggleColumn;
-use Filament\Tables\Filters\SelectFilter;
-use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
@@ -48,75 +33,12 @@ class CategoryResource extends Resource
public static function form(Schema $schema): Schema
{
- return $schema
- ->components([
- TextInput::make('name')
- ->label('Nama Kategori')
- ->placeholder('Ekonomi')
- ->autocomplete(false)
- ->autofocus()
- ->required()
- ->maxLength(50),
- ])
- ->columns(1);
+ return CategoryForm::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('name')
- ->label('Nama')
- ->searchable()
- ->sortable(),
-
- ToggleColumn::make('is_active')
- ->label('Aktif?')
- ->sortable()
- ->getStateUsing(fn (Category $record): bool => $record->is_active === IsActive::ACTIVE)
- ->updateStateUsing(function (Category $record, bool $state): void {
- $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
- $record->save();
-
- CheerfulNotification::statusUpdated()->send();
- }),
-
- ...TimestampColumns::make(),
- ])
- ->filters([
- SelectFilter::make('is_active')
- ->label('Status')
- ->options(IsActive::class)
- ->native(false),
-
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- EditAction::make()
- ->modalWidth(Width::Large),
-
- DeleteAction::make(),
-
- ForceDeleteAction::make(),
-
- RestoreAction::make(),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('kategori'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedListBullet)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('category.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('category.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading();
+ return CategoryTable::configure($table);
}
public static function getPages(): array
diff --git a/app/Filament/Resources/Master/Categories/Schemas/CategoryForm.php b/app/Filament/Resources/Master/Categories/Schemas/CategoryForm.php
new file mode 100644
index 0000000..094f900
--- /dev/null
+++ b/app/Filament/Resources/Master/Categories/Schemas/CategoryForm.php
@@ -0,0 +1,24 @@
+components([
+ TextInput::make('name')
+ ->label('Nama Kategori')
+ ->placeholder('Ekonomi')
+ ->autocomplete(false)
+ ->autofocus()
+ ->required()
+ ->maxLength(50),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Master/Categories/Tables/CategoryTable.php b/app/Filament/Resources/Master/Categories/Tables/CategoryTable.php
new file mode 100644
index 0000000..7bc287b
--- /dev/null
+++ b/app/Filament/Resources/Master/Categories/Tables/CategoryTable.php
@@ -0,0 +1,84 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('name')
+ ->label('Nama')
+ ->searchable()
+ ->sortable(),
+
+ ToggleColumn::make('is_active')
+ ->label('Aktif?')
+ ->sortable()
+ ->getStateUsing(fn (Category $record): bool => $record->is_active === IsActive::ACTIVE)
+ ->updateStateUsing(function (Category $record, bool $state): void {
+ $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
+ $record->save();
+
+ CheerfulNotification::statusUpdated()->send();
+ }),
+
+ ...TimestampColumns::make(),
+ ])
+ ->filters([
+ SelectFilter::make('is_active')
+ ->label('Status')
+ ->options(IsActive::class)
+ ->native(false),
+
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ EditAction::make()
+ ->modalWidth(Width::Large),
+
+ DeleteAction::make(),
+
+ ForceDeleteAction::make(),
+
+ RestoreAction::make(),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('kategori'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedListBullet)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('category.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('category.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading();
+ }
+}
diff --git a/app/Filament/Resources/Master/Classifications/ClassificationResource.php b/app/Filament/Resources/Master/Classifications/ClassificationResource.php
index 4b420ea..db0631d 100644
--- a/app/Filament/Resources/Master/Classifications/ClassificationResource.php
+++ b/app/Filament/Resources/Master/Classifications/ClassificationResource.php
@@ -2,29 +2,14 @@
namespace App\Filament\Resources\Master\Classifications;
-use App\Enums\IsActive;
-use App\Enums\RoleEnum;
-use App\Filament\Actions\Cheerful\DeleteAction;
-use App\Filament\Actions\Cheerful\EditAction;
-use App\Filament\Actions\Cheerful\ForceDeleteAction;
-use App\Filament\Actions\Cheerful\RestoreAction;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Columns\TimestampColumns;
use App\Filament\Resources\Master\Classifications\Pages\ManageClassifications;
-use App\Filament\Support\CheerfulNotification;
+use App\Filament\Resources\Master\Classifications\Schemas\ClassificationForm;
+use App\Filament\Resources\Master\Classifications\Tables\ClassificationTable;
use App\Models\Classification;
use BackedEnum;
-use Filament\Actions\BulkActionGroup;
-use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
-use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Columns\ToggleColumn;
-use Filament\Tables\Filters\SelectFilter;
-use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
@@ -48,75 +33,12 @@ class ClassificationResource extends Resource
public static function form(Schema $schema): Schema
{
- return $schema
- ->components([
- TextInput::make('name')
- ->label('Nama Klasifikasi')
- ->placeholder('Pelaporan')
- ->autocomplete(false)
- ->autofocus()
- ->required()
- ->maxLength(50),
- ])
- ->columns(1);
+ return ClassificationForm::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('name')
- ->label('Nama')
- ->searchable()
- ->sortable(),
-
- ToggleColumn::make('is_active')
- ->label('Aktif?')
- ->sortable()
- ->getStateUsing(fn (Classification $record): bool => $record->is_active === IsActive::ACTIVE)
- ->updateStateUsing(function (Classification $record, bool $state): void {
- $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
- $record->save();
-
- CheerfulNotification::statusUpdated()->send();
- }),
-
- ...TimestampColumns::make(),
- ])
- ->filters([
- SelectFilter::make('is_active')
- ->label('Status')
- ->options(IsActive::class)
- ->native(false),
-
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- EditAction::make()
- ->modalWidth(Width::Large),
-
- DeleteAction::make(),
-
- ForceDeleteAction::make(),
-
- RestoreAction::make(),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('klasifikasi'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedBookOpen)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('classification.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('classification.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading();
+ return ClassificationTable::configure($table);
}
public static function getPages(): array
diff --git a/app/Filament/Resources/Master/Classifications/Schemas/ClassificationForm.php b/app/Filament/Resources/Master/Classifications/Schemas/ClassificationForm.php
new file mode 100644
index 0000000..8937f7a
--- /dev/null
+++ b/app/Filament/Resources/Master/Classifications/Schemas/ClassificationForm.php
@@ -0,0 +1,24 @@
+components([
+ TextInput::make('name')
+ ->label('Nama Klasifikasi')
+ ->placeholder('Pelaporan')
+ ->autocomplete(false)
+ ->autofocus()
+ ->required()
+ ->maxLength(50),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Master/Classifications/Tables/ClassificationTable.php b/app/Filament/Resources/Master/Classifications/Tables/ClassificationTable.php
new file mode 100644
index 0000000..0a73ca3
--- /dev/null
+++ b/app/Filament/Resources/Master/Classifications/Tables/ClassificationTable.php
@@ -0,0 +1,84 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('name')
+ ->label('Nama')
+ ->searchable()
+ ->sortable(),
+
+ ToggleColumn::make('is_active')
+ ->label('Aktif?')
+ ->sortable()
+ ->getStateUsing(fn (Classification $record): bool => $record->is_active === IsActive::ACTIVE)
+ ->updateStateUsing(function (Classification $record, bool $state): void {
+ $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
+ $record->save();
+
+ CheerfulNotification::statusUpdated()->send();
+ }),
+
+ ...TimestampColumns::make(),
+ ])
+ ->filters([
+ SelectFilter::make('is_active')
+ ->label('Status')
+ ->options(IsActive::class)
+ ->native(false),
+
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ EditAction::make()
+ ->modalWidth(Width::Large),
+
+ DeleteAction::make(),
+
+ ForceDeleteAction::make(),
+
+ RestoreAction::make(),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('klasifikasi'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedBookOpen)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('classification.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('classification.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading();
+ }
+}
diff --git a/app/Filament/Resources/Master/Departments/DepartmentResource.php b/app/Filament/Resources/Master/Departments/DepartmentResource.php
index 3b28c42..32851a3 100644
--- a/app/Filament/Resources/Master/Departments/DepartmentResource.php
+++ b/app/Filament/Resources/Master/Departments/DepartmentResource.php
@@ -2,29 +2,14 @@
namespace App\Filament\Resources\Master\Departments;
-use App\Enums\IsActive;
-use App\Enums\RoleEnum;
-use App\Filament\Actions\Cheerful\DeleteAction;
-use App\Filament\Actions\Cheerful\EditAction;
-use App\Filament\Actions\Cheerful\ForceDeleteAction;
-use App\Filament\Actions\Cheerful\RestoreAction;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Columns\TimestampColumns;
use App\Filament\Resources\Master\Departments\Pages\ManageDepartments;
-use App\Filament\Support\CheerfulNotification;
+use App\Filament\Resources\Master\Departments\Schemas\DepartmentForm;
+use App\Filament\Resources\Master\Departments\Tables\DepartmentTable;
use App\Models\Department;
use BackedEnum;
-use Filament\Actions\BulkActionGroup;
-use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
-use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Columns\ToggleColumn;
-use Filament\Tables\Filters\SelectFilter;
-use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
@@ -48,86 +33,12 @@ class DepartmentResource extends Resource
public static function form(Schema $schema): Schema
{
- return $schema
- ->components([
- TextInput::make('name')
- ->label('Nama OPD')
- ->placeholder('Dinas Komunikasi dan Informatika')
- ->autocomplete(false)
- ->autofocus()
- ->required()
- ->maxLength(100),
-
- TextInput::make('alias')
- ->label('Alias')
- ->placeholder('Diskominfo')
- ->autocomplete(false)
- ->required()
- ->maxLength(20),
- ])
- ->columns(1);
+ return DepartmentForm::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('name')
- ->label('Nama')
- ->searchable()
- ->sortable(),
-
- TextColumn::make('alias')
- ->searchable()
- ->sortable(),
-
- ToggleColumn::make('is_active')
- ->label('Aktif?')
- ->sortable()
- ->getStateUsing(fn (Department $record): bool => $record->is_active === IsActive::ACTIVE)
- ->updateStateUsing(function (Department $record, bool $state): void {
- $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
- $record->save();
-
- CheerfulNotification::statusUpdated()->send();
- }),
-
- ...TimestampColumns::make(),
- ])
- ->filters([
- SelectFilter::make('is_active')
- ->label('Status')
- ->options(IsActive::class)
- ->native(false),
-
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- EditAction::make()
- ->modalWidth(Width::Large),
-
- DeleteAction::make(),
-
- ForceDeleteAction::make(),
-
- RestoreAction::make(),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('OPD'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedBuildingLibrary)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('opd.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('opd.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading();
+ return DepartmentTable::configure($table);
}
public static function getPages(): array
diff --git a/app/Filament/Resources/Master/Departments/Schemas/DepartmentForm.php b/app/Filament/Resources/Master/Departments/Schemas/DepartmentForm.php
new file mode 100644
index 0000000..0608441
--- /dev/null
+++ b/app/Filament/Resources/Master/Departments/Schemas/DepartmentForm.php
@@ -0,0 +1,31 @@
+components([
+ TextInput::make('name')
+ ->label('Nama OPD')
+ ->placeholder('Dinas Komunikasi dan Informatika')
+ ->autocomplete(false)
+ ->autofocus()
+ ->required()
+ ->maxLength(100),
+
+ TextInput::make('alias')
+ ->label('Alias')
+ ->placeholder('Diskominfo')
+ ->autocomplete(false)
+ ->required()
+ ->maxLength(20),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Master/Departments/Tables/DepartmentTable.php b/app/Filament/Resources/Master/Departments/Tables/DepartmentTable.php
new file mode 100644
index 0000000..e23723d
--- /dev/null
+++ b/app/Filament/Resources/Master/Departments/Tables/DepartmentTable.php
@@ -0,0 +1,88 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('name')
+ ->label('Nama')
+ ->searchable()
+ ->sortable(),
+
+ TextColumn::make('alias')
+ ->searchable()
+ ->sortable(),
+
+ ToggleColumn::make('is_active')
+ ->label('Aktif?')
+ ->sortable()
+ ->getStateUsing(fn (Department $record): bool => $record->is_active === IsActive::ACTIVE)
+ ->updateStateUsing(function (Department $record, bool $state): void {
+ $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
+ $record->save();
+
+ CheerfulNotification::statusUpdated()->send();
+ }),
+
+ ...TimestampColumns::make(),
+ ])
+ ->filters([
+ SelectFilter::make('is_active')
+ ->label('Status')
+ ->options(IsActive::class)
+ ->native(false),
+
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ EditAction::make()
+ ->modalWidth(Width::Large),
+
+ DeleteAction::make(),
+
+ ForceDeleteAction::make(),
+
+ RestoreAction::make(),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('OPD'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedBuildingLibrary)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('opd.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('opd.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading();
+ }
+}
diff --git a/app/Filament/Resources/Master/Locations/LocationResource.php b/app/Filament/Resources/Master/Locations/LocationResource.php
index c38ac21..d32abe5 100644
--- a/app/Filament/Resources/Master/Locations/LocationResource.php
+++ b/app/Filament/Resources/Master/Locations/LocationResource.php
@@ -2,29 +2,14 @@
namespace App\Filament\Resources\Master\Locations;
-use App\Enums\IsActive;
-use App\Enums\RoleEnum;
-use App\Filament\Actions\Cheerful\DeleteAction;
-use App\Filament\Actions\Cheerful\EditAction;
-use App\Filament\Actions\Cheerful\ForceDeleteAction;
-use App\Filament\Actions\Cheerful\RestoreAction;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Columns\TimestampColumns;
use App\Filament\Resources\Master\Locations\Pages\ManageLocations;
-use App\Filament\Support\CheerfulNotification;
+use App\Filament\Resources\Master\Locations\Schemas\LocationForm;
+use App\Filament\Resources\Master\Locations\Tables\LocationTable;
use App\Models\Location;
use BackedEnum;
-use Filament\Actions\BulkActionGroup;
-use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
-use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Columns\ToggleColumn;
-use Filament\Tables\Filters\SelectFilter;
-use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
@@ -48,75 +33,12 @@ class LocationResource extends Resource
public static function form(Schema $schema): Schema
{
- return $schema
- ->components([
- TextInput::make('name')
- ->label('Nama Lokus')
- ->placeholder('Purwakarta')
- ->autocomplete(false)
- ->autofocus()
- ->required()
- ->maxLength(50),
- ])
- ->columns(1);
+ return LocationForm::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('name')
- ->label('Nama')
- ->searchable()
- ->sortable(),
-
- ToggleColumn::make('is_active')
- ->label('Aktif?')
- ->sortable()
- ->getStateUsing(fn (Location $record): bool => $record->is_active === IsActive::ACTIVE)
- ->updateStateUsing(function (Location $record, bool $state): void {
- $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
- $record->save();
-
- CheerfulNotification::statusUpdated()->send();
- }),
-
- ...TimestampColumns::make(),
- ])
- ->filters([
- SelectFilter::make('is_active')
- ->label('Status')
- ->options(IsActive::class)
- ->native(false),
-
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- EditAction::make()
- ->modalWidth(Width::Large),
-
- DeleteAction::make(),
-
- ForceDeleteAction::make(),
-
- RestoreAction::make(),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('Lokus'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedMapPin)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('locus.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('locus.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading();
+ return LocationTable::configure($table);
}
public static function getPages(): array
diff --git a/app/Filament/Resources/Master/Locations/Schemas/LocationForm.php b/app/Filament/Resources/Master/Locations/Schemas/LocationForm.php
new file mode 100644
index 0000000..707cb04
--- /dev/null
+++ b/app/Filament/Resources/Master/Locations/Schemas/LocationForm.php
@@ -0,0 +1,24 @@
+components([
+ TextInput::make('name')
+ ->label('Nama Lokus')
+ ->placeholder('Purwakarta')
+ ->autocomplete(false)
+ ->autofocus()
+ ->required()
+ ->maxLength(50),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Master/Locations/Tables/LocationTable.php b/app/Filament/Resources/Master/Locations/Tables/LocationTable.php
new file mode 100644
index 0000000..f250d6f
--- /dev/null
+++ b/app/Filament/Resources/Master/Locations/Tables/LocationTable.php
@@ -0,0 +1,84 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('name')
+ ->label('Nama')
+ ->searchable()
+ ->sortable(),
+
+ ToggleColumn::make('is_active')
+ ->label('Aktif?')
+ ->sortable()
+ ->getStateUsing(fn (Location $record): bool => $record->is_active === IsActive::ACTIVE)
+ ->updateStateUsing(function (Location $record, bool $state): void {
+ $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
+ $record->save();
+
+ CheerfulNotification::statusUpdated()->send();
+ }),
+
+ ...TimestampColumns::make(),
+ ])
+ ->filters([
+ SelectFilter::make('is_active')
+ ->label('Status')
+ ->options(IsActive::class)
+ ->native(false),
+
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ EditAction::make()
+ ->modalWidth(Width::Large),
+
+ DeleteAction::make(),
+
+ ForceDeleteAction::make(),
+
+ RestoreAction::make(),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('Lokus'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedMapPin)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('locus.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('locus.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading();
+ }
+}
diff --git a/app/Filament/Resources/Master/SubClassifications/Schemas/SubClassificationForm.php b/app/Filament/Resources/Master/SubClassifications/Schemas/SubClassificationForm.php
new file mode 100644
index 0000000..675ad54
--- /dev/null
+++ b/app/Filament/Resources/Master/SubClassifications/Schemas/SubClassificationForm.php
@@ -0,0 +1,34 @@
+components([
+ Select::make('classification_id')
+ ->label('Klasifikasi Utama')
+ ->options(Classification::query()->active()->pluck('name', 'id'))
+ ->searchable()
+ ->native(false)
+ ->required()
+ ->rules(['exists:classifications,id'])
+ ->autofocus(),
+
+ TextInput::make('name')
+ ->label('Nama Subklasifikasi')
+ ->placeholder('Korupsi')
+ ->autocomplete(false)
+ ->required()
+ ->maxLength(50),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Master/SubClassifications/SubClassificationResource.php b/app/Filament/Resources/Master/SubClassifications/SubClassificationResource.php
index 1b0e9ad..0fff8a6 100644
--- a/app/Filament/Resources/Master/SubClassifications/SubClassificationResource.php
+++ b/app/Filament/Resources/Master/SubClassifications/SubClassificationResource.php
@@ -2,32 +2,14 @@
namespace App\Filament\Resources\Master\SubClassifications;
-use App\Enums\IsActive;
-use App\Enums\RoleEnum;
-use App\Filament\Actions\Cheerful\DeleteAction;
-use App\Filament\Actions\Cheerful\EditAction;
-use App\Filament\Actions\Cheerful\ForceDeleteAction;
-use App\Filament\Actions\Cheerful\RestoreAction;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Columns\TimestampColumns;
use App\Filament\Resources\Master\SubClassifications\Pages\ManageSubClassifications;
-use App\Filament\Support\CheerfulNotification;
-use App\Models\Classification;
+use App\Filament\Resources\Master\SubClassifications\Schemas\SubClassificationForm;
+use App\Filament\Resources\Master\SubClassifications\Tables\SubClassificationTable;
use App\Models\SubClassification;
use BackedEnum;
-use Filament\Actions\BulkActionGroup;
-use Filament\Forms\Components\Select;
-use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
-use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Columns\ToggleColumn;
-use Filament\Tables\Filters\SelectFilter;
-use Filament\Tables\Filters\TrashedFilter;
-use Filament\Tables\Grouping\Group;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
@@ -51,99 +33,12 @@ class SubClassificationResource extends Resource
public static function form(Schema $schema): Schema
{
- return $schema
- ->components([
- Select::make('classification_id')
- ->label('Klasifikasi Utama')
- ->options(Classification::query()->active()->pluck('name', 'id'))
- ->searchable()
- ->native(false)
- ->required()
- ->rules(['exists:classifications,id'])
- ->autofocus(),
-
- TextInput::make('name')
- ->label('Nama Subklasifikasi')
- ->placeholder('Korupsi')
- ->autocomplete(false)
- ->required()
- ->maxLength(50),
- ])
- ->columns(1);
+ return SubClassificationForm::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('name')
- ->label('Nama')
- ->searchable()
- ->sortable(),
-
- ToggleColumn::make('is_active')
- ->label('Aktif?')
- ->sortable()
- ->getStateUsing(fn (SubClassification $record): bool => $record->is_active === IsActive::ACTIVE)
- ->updateStateUsing(function (SubClassification $record, bool $state): void {
- $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
- $record->save();
-
- CheerfulNotification::success(
- CheerfulNotification::getByKey('status.updated'),
- CheerfulNotification::getByKey('status.update_success')
- )->send();
- }),
-
- ...TimestampColumns::make(),
- ])
- ->filters([
- SelectFilter::make('is_active')
- ->label('Status')
- ->options(IsActive::class)
- ->native(false),
-
- SelectFilter::make('classification')
- ->label('Klasifikasi')
- ->relationship('classification', 'name')
- ->searchable()
- ->preload()
- ->native(false),
-
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- EditAction::make()
- ->modalWidth(Width::Large),
-
- DeleteAction::make(),
-
- ForceDeleteAction::make(),
-
- RestoreAction::make(),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('Subklasifikasi'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedQueueList)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('classification.sub.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('classification.sub.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading()
- ->groups([
- Group::make('classification.name')
- ->label('Klasifikasi')
- ->collapsible(),
- ])
- ->defaultGroup('classification.name');
+ return SubClassificationTable::configure($table);
}
public static function getPages(): array
diff --git a/app/Filament/Resources/Master/SubClassifications/Tables/SubClassificationTable.php b/app/Filament/Resources/Master/SubClassifications/Tables/SubClassificationTable.php
new file mode 100644
index 0000000..6bafdbd
--- /dev/null
+++ b/app/Filament/Resources/Master/SubClassifications/Tables/SubClassificationTable.php
@@ -0,0 +1,101 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('name')
+ ->label('Nama')
+ ->searchable()
+ ->sortable(),
+
+ ToggleColumn::make('is_active')
+ ->label('Aktif?')
+ ->sortable()
+ ->getStateUsing(fn (SubClassification $record): bool => $record->is_active === IsActive::ACTIVE)
+ ->updateStateUsing(function (SubClassification $record, bool $state): void {
+ $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
+ $record->save();
+
+ CheerfulNotification::success(
+ CheerfulNotification::getByKey('status.updated'),
+ CheerfulNotification::getByKey('status.update_success')
+ )->send();
+ }),
+
+ ...TimestampColumns::make(),
+ ])
+ ->filters([
+ SelectFilter::make('is_active')
+ ->label('Status')
+ ->options(IsActive::class)
+ ->native(false),
+
+ SelectFilter::make('classification')
+ ->label('Klasifikasi')
+ ->relationship('classification', 'name')
+ ->searchable()
+ ->preload()
+ ->native(false),
+
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ EditAction::make()
+ ->modalWidth(Width::Large),
+
+ DeleteAction::make(),
+
+ ForceDeleteAction::make(),
+
+ RestoreAction::make(),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('Subklasifikasi'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedQueueList)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('classification.sub.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('classification.sub.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading()
+ ->groups([
+ Group::make('classification.name')
+ ->label('Klasifikasi')
+ ->collapsible(),
+ ])
+ ->defaultGroup('classification.name');
+ }
+}
diff --git a/app/Filament/Resources/Master/SubLocations/Schemas/SubLocationForm.php b/app/Filament/Resources/Master/SubLocations/Schemas/SubLocationForm.php
new file mode 100644
index 0000000..0123014
--- /dev/null
+++ b/app/Filament/Resources/Master/SubLocations/Schemas/SubLocationForm.php
@@ -0,0 +1,34 @@
+components([
+ Select::make('location_id')
+ ->label('Lokus Utama')
+ ->options(Location::query()->pluck('name', 'id'))
+ ->searchable()
+ ->native(false)
+ ->required()
+ ->rules(['exists:locations,id'])
+ ->autofocus(),
+
+ TextInput::make('name')
+ ->label('Nama Sublokus')
+ ->placeholder('Kecamatan Purwakarta')
+ ->autocomplete(false)
+ ->required()
+ ->maxLength(50),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Master/SubLocations/SubLocationResource.php b/app/Filament/Resources/Master/SubLocations/SubLocationResource.php
index d8c41fb..21cf6e6 100644
--- a/app/Filament/Resources/Master/SubLocations/SubLocationResource.php
+++ b/app/Filament/Resources/Master/SubLocations/SubLocationResource.php
@@ -2,32 +2,14 @@
namespace App\Filament\Resources\Master\SubLocations;
-use App\Enums\IsActive;
-use App\Enums\RoleEnum;
-use App\Filament\Actions\Cheerful\DeleteAction;
-use App\Filament\Actions\Cheerful\EditAction;
-use App\Filament\Actions\Cheerful\ForceDeleteAction;
-use App\Filament\Actions\Cheerful\RestoreAction;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Columns\TimestampColumns;
use App\Filament\Resources\Master\SubLocations\Pages\ManageSubLocations;
-use App\Filament\Support\CheerfulNotification;
-use App\Models\Location;
+use App\Filament\Resources\Master\SubLocations\Schemas\SubLocationForm;
+use App\Filament\Resources\Master\SubLocations\Tables\SubLocationTable;
use App\Models\SubLocation;
use BackedEnum;
-use Filament\Actions\BulkActionGroup;
-use Filament\Forms\Components\Select;
-use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
-use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Columns\ToggleColumn;
-use Filament\Tables\Filters\SelectFilter;
-use Filament\Tables\Filters\TrashedFilter;
-use Filament\Tables\Grouping\Group;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
@@ -51,96 +33,12 @@ class SubLocationResource extends Resource
public static function form(Schema $schema): Schema
{
- return $schema
- ->components([
- Select::make('location_id')
- ->label('Lokus Utama')
- ->options(Location::query()->pluck('name', 'id'))
- ->searchable()
- ->native(false)
- ->required()
- ->rules(['exists:locations,id'])
- ->autofocus(),
-
- TextInput::make('name')
- ->label('Nama Sublokus')
- ->placeholder('Kecamatan Purwakarta')
- ->autocomplete(false)
- ->required()
- ->maxLength(50),
- ])
- ->columns(1);
+ return SubLocationForm::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('name')
- ->label('Nama')
- ->searchable()
- ->sortable(),
-
- ToggleColumn::make('is_active')
- ->label('Aktif?')
- ->sortable()
- ->getStateUsing(fn (SubLocation $record): bool => $record->is_active === IsActive::ACTIVE)
- ->updateStateUsing(function (SubLocation $record, bool $state): void {
- $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
- $record->save();
-
- CheerfulNotification::statusUpdated()->send();
- }),
-
- ...TimestampColumns::make(),
- ])
- ->filters([
- SelectFilter::make('is_active')
- ->label('Status')
- ->options(IsActive::class)
- ->native(false),
-
- SelectFilter::make('location')
- ->label('Lokus')
- ->relationship('location', 'name')
- ->searchable()
- ->preload()
- ->native(false),
-
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- EditAction::make()
- ->modalWidth(Width::Large),
-
- DeleteAction::make(),
-
- ForceDeleteAction::make(),
-
- RestoreAction::make(),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('Sublokus'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedNumberedList)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('locus.sub.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('locus.sub.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading()
- ->groups([
- Group::make('location.name')
- ->label('Lokus')
- ->collapsible(),
- ])
- ->defaultGroup('location.name');
+ return SubLocationTable::configure($table);
}
public static function getPages(): array
diff --git a/app/Filament/Resources/Master/SubLocations/Tables/SubLocationTable.php b/app/Filament/Resources/Master/SubLocations/Tables/SubLocationTable.php
new file mode 100644
index 0000000..482afe2
--- /dev/null
+++ b/app/Filament/Resources/Master/SubLocations/Tables/SubLocationTable.php
@@ -0,0 +1,98 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('name')
+ ->label('Nama')
+ ->searchable()
+ ->sortable(),
+
+ ToggleColumn::make('is_active')
+ ->label('Aktif?')
+ ->sortable()
+ ->getStateUsing(fn (SubLocation $record): bool => $record->is_active === IsActive::ACTIVE)
+ ->updateStateUsing(function (SubLocation $record, bool $state): void {
+ $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
+ $record->save();
+
+ CheerfulNotification::statusUpdated()->send();
+ }),
+
+ ...TimestampColumns::make(),
+ ])
+ ->filters([
+ SelectFilter::make('is_active')
+ ->label('Status')
+ ->options(IsActive::class)
+ ->native(false),
+
+ SelectFilter::make('location')
+ ->label('Lokus')
+ ->relationship('location', 'name')
+ ->searchable()
+ ->preload()
+ ->native(false),
+
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ EditAction::make()
+ ->modalWidth(Width::Large),
+
+ DeleteAction::make(),
+
+ ForceDeleteAction::make(),
+
+ RestoreAction::make(),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('Sublokus'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedNumberedList)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('locus.sub.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('locus.sub.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading()
+ ->groups([
+ Group::make('location.name')
+ ->label('Lokus')
+ ->collapsible(),
+ ])
+ ->defaultGroup('location.name');
+ }
+}
diff --git a/app/Filament/Resources/Master/Themes/Schemas/ThemeForm.php b/app/Filament/Resources/Master/Themes/Schemas/ThemeForm.php
new file mode 100644
index 0000000..e771c04
--- /dev/null
+++ b/app/Filament/Resources/Master/Themes/Schemas/ThemeForm.php
@@ -0,0 +1,24 @@
+components([
+ TextInput::make('name')
+ ->label('Nama Tema')
+ ->placeholder('Pendidikan')
+ ->autocomplete(false)
+ ->autofocus()
+ ->required()
+ ->maxLength(50),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Master/Themes/Tables/ThemeTable.php b/app/Filament/Resources/Master/Themes/Tables/ThemeTable.php
new file mode 100644
index 0000000..64cd5c6
--- /dev/null
+++ b/app/Filament/Resources/Master/Themes/Tables/ThemeTable.php
@@ -0,0 +1,78 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('name')
+ ->label('Nama')
+ ->searchable()
+ ->sortable(),
+
+ ToggleColumn::make('is_active')
+ ->label('Aktif?')
+ ->sortable()
+ ->getStateUsing(fn (Theme $record): bool => $record->is_active === IsActive::ACTIVE)
+ ->updateStateUsing(function (Theme $record, bool $state): void {
+ $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
+ $record->save();
+
+ CheerfulNotification::statusUpdated()->send();
+ }),
+
+ ...TimestampColumns::make(),
+ ])
+ ->filters([
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ EditAction::make()
+ ->modalWidth(Width::Large),
+
+ DeleteAction::make(),
+
+ ForceDeleteAction::make(),
+
+ RestoreAction::make(),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('Tema'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedPuzzlePiece)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('theme.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('theme.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading();
+ }
+}
diff --git a/app/Filament/Resources/Master/Themes/ThemeResource.php b/app/Filament/Resources/Master/Themes/ThemeResource.php
index b3c5b09..7afccfb 100644
--- a/app/Filament/Resources/Master/Themes/ThemeResource.php
+++ b/app/Filament/Resources/Master/Themes/ThemeResource.php
@@ -2,28 +2,14 @@
namespace App\Filament\Resources\Master\Themes;
-use App\Enums\IsActive;
-use App\Enums\RoleEnum;
-use App\Filament\Actions\Cheerful\DeleteAction;
-use App\Filament\Actions\Cheerful\EditAction;
-use App\Filament\Actions\Cheerful\ForceDeleteAction;
-use App\Filament\Actions\Cheerful\RestoreAction;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Columns\TimestampColumns;
use App\Filament\Resources\Master\Themes\Pages\ManageThemes;
-use App\Filament\Support\CheerfulNotification;
+use App\Filament\Resources\Master\Themes\Schemas\ThemeForm;
+use App\Filament\Resources\Master\Themes\Tables\ThemeTable;
use App\Models\Theme;
use BackedEnum;
-use Filament\Actions\BulkActionGroup;
-use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
-use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Columns\ToggleColumn;
-use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
@@ -47,70 +33,12 @@ class ThemeResource extends Resource
public static function form(Schema $schema): Schema
{
- return $schema
- ->components([
- TextInput::make('name')
- ->label('Nama Tema')
- ->placeholder('Pendidikan')
- ->autocomplete(false)
- ->autofocus()
- ->required()
- ->maxLength(50),
- ])
- ->columns(1);
+ return ThemeForm::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('name')
- ->label('Nama')
- ->searchable()
- ->sortable(),
-
- ToggleColumn::make('is_active')
- ->label('Aktif?')
- ->sortable()
- ->getStateUsing(fn (Theme $record): bool => $record->is_active === IsActive::ACTIVE)
- ->updateStateUsing(function (Theme $record, bool $state): void {
- $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
- $record->save();
-
- CheerfulNotification::statusUpdated()->send();
- }),
-
- ...TimestampColumns::make(),
- ])
- ->filters([
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- EditAction::make()
- ->modalWidth(Width::Large),
-
- DeleteAction::make(),
-
- ForceDeleteAction::make(),
-
- RestoreAction::make(),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('Tema'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedPuzzlePiece)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('theme.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('theme.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading();
+ return ThemeTable::configure($table);
}
public static function getPages(): array
diff --git a/app/Filament/Resources/Master/Users/Schemas/UserForm.php b/app/Filament/Resources/Master/Users/Schemas/UserForm.php
new file mode 100644
index 0000000..7201484
--- /dev/null
+++ b/app/Filament/Resources/Master/Users/Schemas/UserForm.php
@@ -0,0 +1,67 @@
+components([
+ TextInput::make('name')
+ ->label('Nama Lengkap')
+ ->placeholder('John Doe')
+ ->autocomplete(false)
+ ->autofocus()
+ ->required()
+ ->maxLength(100),
+
+ Grid::make(1)
+ ->schema([
+ TextInput::make('email')
+ ->label('Alamat Surel')
+ ->placeholder('johndoe@example.com')
+ ->autocomplete(false)
+ ->required()
+ ->maxLength(254)
+ ->email()
+ ->unique(ignoreRecord: true)
+ ->prefixIcon('heroicon-o-envelope'),
+
+ TextInput::make('username')
+ ->label('Nama Pengguna')
+ ->placeholder('johndoe')
+ ->autocomplete(false)
+ ->required()
+ ->minLength(5)
+ ->maxLength(20)
+ ->regex('/^[a-zA-Z0-9_.-]+$/')
+ ->unique(ignoreRecord: true)
+ ->prefixIcon('heroicon-o-at-symbol'),
+
+ Select::make('roles')
+ ->label('Peran')
+ ->required()
+ ->relationship('roles', 'name', function (Builder $query): Builder {
+ return $query->whereNotIn('name', [RoleEnum::DEVELOPER, RoleEnum::PERUSAHAAN]);
+ })
+ ->multiple()
+ ->preload()
+ ->searchable(),
+
+ Hidden::make('password')
+ ->default(fn (): string => config('auth.password_default'))
+ ->visibleOn('create'),
+ ]),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Master/Users/Tables/UserTable.php b/app/Filament/Resources/Master/Users/Tables/UserTable.php
new file mode 100644
index 0000000..ee46664
--- /dev/null
+++ b/app/Filament/Resources/Master/Users/Tables/UserTable.php
@@ -0,0 +1,125 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('name')
+ ->label('Nama')
+ ->searchable()
+ ->sortable(),
+
+ TextColumn::make('email')
+ ->label('Alamat Surel')
+ ->searchable()
+ ->sortable(),
+
+ TextColumn::make('username')
+ ->label('Nama Pengguna')
+ ->searchable()
+ ->sortable(),
+
+ ToggleColumn::make('is_active')
+ ->label('Status')
+ ->sortable()
+ ->getStateUsing(fn (User $record): bool => $record->is_active === IsActive::ACTIVE)
+ ->updateStateUsing(function (User $record, bool $state): void {
+ $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
+ $record->save();
+
+ if ($record->is_active === IsActive::INACTIVE) {
+ DB::table('sessions')
+ ->where('user_id', $record->id)
+ ->delete();
+ }
+
+ CheerfulNotification::success(
+ $state ? CheerfulNotification::getByKey('user.activated') : CheerfulNotification::getByKey('user.deactivated'),
+ $state ? CheerfulNotification::getByKey('user.status_activated_success') : CheerfulNotification::getByKey('user.status_activated_success')
+ )->send();
+ })
+ ->disabled(fn (User $record): bool => $record->hasRole(RoleEnum::PERUSAHAAN->value)),
+
+ TextColumn::make('roles.name')
+ ->label('Peran')
+ ->searchable()
+ ->badge()
+ ->getStateUsing(fn (User $record): array => $record->roles->pluck('name', 'id')->toArray()),
+
+ ...TimestampColumns::make(),
+ ])
+ ->filters([
+ SelectFilter::make('is_active')
+ ->label('Status')
+ ->options(IsActive::class)
+ ->native(false),
+
+ SelectFilter::make('roles')
+ ->label('Peran')
+ ->relationship('roles', 'name', function (Builder $query): Builder {
+ return $query->whereNotIn('name', [RoleEnum::DEVELOPER, RoleEnum::PERUSAHAAN]);
+ })
+ ->multiple()
+ ->preload()
+ ->searchable()
+ ->native(false),
+
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ EditAction::make()
+ ->modalWidth(Width::Large),
+
+ DeleteAction::make(),
+
+ ForceDeleteAction::make(),
+
+ RestoreAction::make(),
+
+ ChangePasswordAction::make('changePassword'),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('Pengguna'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedUserGroup)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('user.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('user.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading();
+ }
+}
diff --git a/app/Filament/Resources/Master/Users/UserResource.php b/app/Filament/Resources/Master/Users/UserResource.php
index 38ae072..2fb7de2 100644
--- a/app/Filament/Resources/Master/Users/UserResource.php
+++ b/app/Filament/Resources/Master/Users/UserResource.php
@@ -2,37 +2,17 @@
namespace App\Filament\Resources\Master\Users;
-use App\Enums\IsActive;
-use App\Enums\RoleEnum;
-use App\Filament\Actions\Cheerful\DeleteAction;
-use App\Filament\Actions\Cheerful\EditAction;
-use App\Filament\Actions\Cheerful\ForceDeleteAction;
-use App\Filament\Actions\Cheerful\RestoreAction;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Columns\TimestampColumns;
-use App\Filament\Resources\Master\Users\Actions\ChangePasswordAction;
use App\Filament\Resources\Master\Users\Pages\ManageUsers;
-use App\Filament\Support\CheerfulNotification;
+use App\Filament\Resources\Master\Users\Schemas\UserForm;
+use App\Filament\Resources\Master\Users\Tables\UserTable;
use App\Models\User;
use BackedEnum;
-use Filament\Actions\BulkActionGroup;
-use Filament\Forms\Components\Hidden;
-use Filament\Forms\Components\Select;
-use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
-use Filament\Schemas\Components\Grid;
use Filament\Schemas\Schema;
-use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Columns\ToggleColumn;
-use Filament\Tables\Filters\SelectFilter;
-use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
-use Illuminate\Support\Facades\DB;
use UnitEnum;
class UserResource extends Resource
@@ -53,151 +33,12 @@ class UserResource extends Resource
public static function form(Schema $schema): Schema
{
- return $schema
- ->components([
- TextInput::make('name')
- ->label('Nama Lengkap')
- ->placeholder('John Doe')
- ->autocomplete(false)
- ->autofocus()
- ->required()
- ->maxLength(100),
-
- Grid::make(1)
- ->schema([
- TextInput::make('email')
- ->label('Alamat Surel')
- ->placeholder('johndoe@example.com')
- ->autocomplete(false)
- ->required()
- ->maxLength(254)
- ->email()
- ->unique(ignoreRecord: true)
- ->prefixIcon('heroicon-o-envelope'),
-
- TextInput::make('username')
- ->label('Nama Pengguna')
- ->placeholder('johndoe')
- ->autocomplete(false)
- ->required()
- ->minLength(5)
- ->maxLength(20)
- ->regex('/^[a-zA-Z0-9_.-]+$/')
- ->unique(ignoreRecord: true)
- ->prefixIcon('heroicon-o-at-symbol'),
-
- Select::make('roles')
- ->label('Peran')
- ->required()
- ->relationship('roles', 'name', function (Builder $query): Builder {
- return $query->whereNotIn('name', [RoleEnum::DEVELOPER, RoleEnum::PERUSAHAAN]);
- })
- ->multiple()
- ->preload()
- ->searchable(),
-
- Hidden::make('password')
- ->default(fn (): string => config('auth.password_default'))
- ->visibleOn('create'),
- ]),
- ])
- ->columns(1);
+ return UserForm::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('name')
- ->label('Nama')
- ->searchable()
- ->sortable(),
-
- TextColumn::make('email')
- ->label('Alamat Surel')
- ->searchable()
- ->sortable(),
-
- TextColumn::make('username')
- ->label('Nama Pengguna')
- ->searchable()
- ->sortable(),
-
- ToggleColumn::make('is_active')
- ->label('Status')
- ->sortable()
- ->getStateUsing(fn (User $record): bool => $record->is_active === IsActive::ACTIVE)
- ->updateStateUsing(function (User $record, bool $state): void {
- $record->is_active = $state ? IsActive::ACTIVE : IsActive::INACTIVE;
- $record->save();
-
- if ($record->is_active === IsActive::INACTIVE) {
- DB::table('sessions')
- ->where('user_id', $record->id)
- ->delete();
- }
-
- CheerfulNotification::success(
- $state ? CheerfulNotification::getByKey('user.activated') : CheerfulNotification::getByKey('user.deactivated'),
- $state ? CheerfulNotification::getByKey('user.status_activated_success') : CheerfulNotification::getByKey('user.status_activated_success')
- )->send();
- })
- ->disabled(fn (User $record): bool => $record->hasRole(RoleEnum::PERUSAHAAN->value)),
-
- TextColumn::make('roles.name')
- ->label('Peran')
- ->searchable()
- ->badge()
- ->getStateUsing(fn (User $record): array => $record->roles->pluck('name', 'id')->toArray()),
-
- ...TimestampColumns::make(),
- ])
- ->filters([
- SelectFilter::make('is_active')
- ->label('Status')
- ->options(IsActive::class)
- ->native(false),
-
- SelectFilter::make('roles')
- ->label('Peran')
- ->relationship('roles', 'name', function (Builder $query): Builder {
- return $query->whereNotIn('name', [RoleEnum::DEVELOPER, RoleEnum::PERUSAHAAN]);
- })
- ->multiple()
- ->preload()
- ->searchable()
- ->native(false),
-
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- EditAction::make()
- ->modalWidth(Width::Large),
-
- DeleteAction::make(),
-
- ForceDeleteAction::make(),
-
- RestoreAction::make(),
-
- ChangePasswordAction::make('changePassword'),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('Pengguna'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedUserGroup)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('user.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('user.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading();
+ return UserTable::configure($table);
}
public static function getPages(): array
diff --git a/app/Filament/Resources/Publication/Announcements/AnnouncementResource.php b/app/Filament/Resources/Publication/Announcements/AnnouncementResource.php
index 125495c..e296b4a 100644
--- a/app/Filament/Resources/Publication/Announcements/AnnouncementResource.php
+++ b/app/Filament/Resources/Publication/Announcements/AnnouncementResource.php
@@ -2,33 +2,14 @@
namespace App\Filament\Resources\Publication\Announcements;
-use App\Enums\AnnouncementType;
-use App\Enums\RoleEnum;
-use App\Filament\Actions\Cheerful\DeleteAction;
-use App\Filament\Actions\Cheerful\EditAction;
-use App\Filament\Actions\Cheerful\ForceDeleteAction;
-use App\Filament\Actions\Cheerful\RestoreAction;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Columns\TimestampColumns;
use App\Filament\Resources\Publication\Announcements\Pages\ManageAnnouncements;
-use App\Filament\Support\CheerfulNotification;
+use App\Filament\Resources\Publication\Announcements\Schemas\AnnouncementForm;
+use App\Filament\Resources\Publication\Announcements\Tables\AnnouncementTable;
use App\Models\Announcement;
use BackedEnum;
-use Filament\Actions\Action;
-use Filament\Actions\BulkActionGroup;
-use Filament\Forms\Components\CheckboxList;
-use Filament\Forms\Components\Radio;
-use Filament\Forms\Components\RichEditor;
-use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
-use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Schema;
-use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
-use Filament\Tables\Columns\TextColumn;
-use Filament\Tables\Filters\SelectFilter;
-use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
@@ -52,122 +33,12 @@ class AnnouncementResource extends Resource
public static function form(Schema $schema): Schema
{
- return $schema
- ->components([
- TextInput::make('title')
- ->label('Judul Pengumuman')
- ->placeholder('Pencairan Dana Kerja Sama Media')
- ->autocomplete(false)
- ->autofocus()
- ->required()
- ->columnSpanFull(),
-
- RichEditor::make('content')
- ->label('Isi Pengumuman')
- ->placeholder('Tuliskan detail pengumuman di sini...')
- ->required()
- ->columnSpanFull(),
-
- Radio::make('type')
- ->label('Tipe Pengumuman')
- ->options(AnnouncementType::class)
- ->required()
- ->default(AnnouncementType::PUBLIC->value)
- ->live()
- ->inline(),
-
- CheckboxList::make('partnerMedia')
- ->label('Penerima Khusus')
- ->relationship('partnerMedia', 'name', fn (Builder $query): Builder => $query->verified())
- ->visible(fn (Get $get): bool => in_array($get('type'), [AnnouncementType::COMPANY, AnnouncementType::COMPANY->value]))
- ->required(fn (Get $get): bool => in_array($get('type'), [AnnouncementType::COMPANY, AnnouncementType::COMPANY->value]))
- ->searchable()
- ->noSearchResultsMessage('Tidak ada media yang ditemukan.')
- ->helperText('Pilih media yang akan menerima pengumuman ini.')
- ->columnSpanFull()
- ->bulkToggleable()
- ->selectAllAction(
- fn (Action $action): Action => $action->label('Pilih Semua Media'),
- )
- ->dehydrated(),
- ])
- ->columns(1);
+ return AnnouncementForm::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('title')
- ->label('Judul')
- ->searchable()
- ->sortable()
- ->wrap(),
-
- TextColumn::make('content')
- ->label('Konten')
- ->searchable()
- ->sortable()
- ->wrap()
- ->limit(100)
- ->html()
- ->toggleable(isToggledHiddenByDefault: true),
-
- TextColumn::make('type')
- ->label('Tipe')
- ->badge()
- ->sortable(),
-
- TextColumn::make('partnerMedia')
- ->label('Penerima')
- ->getStateUsing(
- fn ($record) => $record->partnerMedia->pluck('name')->toArray()
- )
- ->listWithLineBreaks()
- ->limitList(3)
- ->expandableLimitedList()
- ->badge()
- ->placeholder(
- fn (Announcement $record) => $record->type === AnnouncementType::PUBLIC ? 'Publik' : 'Tidak ada penerima'
- ),
-
- ...TimestampColumns::make(),
- ])
- ->filters([
- SelectFilter::make('type')
- ->label('Tipe')
- ->options(AnnouncementType::class)
- ->native(false),
-
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- EditAction::make()
- ->modalWidth(Width::FiveExtraLarge)
- ->visible(fn (Announcement $record): bool => $record->type === AnnouncementType::PUBLIC),
-
- DeleteAction::make(),
-
- ForceDeleteAction::make(),
-
- RestoreAction::make(),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('Pengumuman'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedMegaphone)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('announcement.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('announcement.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading();
+ return AnnouncementTable::configure($table);
}
public static function getPages(): array
diff --git a/app/Filament/Resources/Publication/Announcements/Schemas/AnnouncementForm.php b/app/Filament/Resources/Publication/Announcements/Schemas/AnnouncementForm.php
new file mode 100644
index 0000000..28ca82e
--- /dev/null
+++ b/app/Filament/Resources/Publication/Announcements/Schemas/AnnouncementForm.php
@@ -0,0 +1,60 @@
+components([
+ TextInput::make('title')
+ ->label('Judul Pengumuman')
+ ->placeholder('Pencairan Dana Kerja Sama Media')
+ ->autocomplete(false)
+ ->autofocus()
+ ->required()
+ ->columnSpanFull(),
+
+ RichEditor::make('content')
+ ->label('Isi Pengumuman')
+ ->placeholder('Tuliskan detail pengumuman di sini...')
+ ->required()
+ ->columnSpanFull(),
+
+ Radio::make('type')
+ ->label('Tipe Pengumuman')
+ ->options(AnnouncementType::class)
+ ->required()
+ ->default(AnnouncementType::PUBLIC->value)
+ ->live()
+ ->inline(),
+
+ CheckboxList::make('partnerMedia')
+ ->label('Penerima Khusus')
+ ->relationship('partnerMedia', 'name', fn (Builder $query): Builder => $query->verified())
+ ->visible(fn (Get $get): bool => in_array($get('type'), [AnnouncementType::COMPANY, AnnouncementType::COMPANY->value]))
+ ->required(fn (Get $get): bool => in_array($get('type'), [AnnouncementType::COMPANY, AnnouncementType::COMPANY->value]))
+ ->searchable()
+ ->noSearchResultsMessage('Tidak ada media yang ditemukan.')
+ ->helperText('Pilih media yang akan menerima pengumuman ini.')
+ ->columnSpanFull()
+ ->bulkToggleable()
+ ->selectAllAction(
+ fn (Action $action): Action => $action->label('Pilih Semua Media'),
+ )
+ ->dehydrated(),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Publication/Announcements/Tables/AnnouncementTable.php b/app/Filament/Resources/Publication/Announcements/Tables/AnnouncementTable.php
new file mode 100644
index 0000000..da75526
--- /dev/null
+++ b/app/Filament/Resources/Publication/Announcements/Tables/AnnouncementTable.php
@@ -0,0 +1,101 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('title')
+ ->label('Judul')
+ ->searchable()
+ ->sortable()
+ ->wrap(),
+
+ TextColumn::make('content')
+ ->label('Konten')
+ ->searchable()
+ ->sortable()
+ ->wrap()
+ ->limit(100)
+ ->html()
+ ->toggleable(isToggledHiddenByDefault: true),
+
+ TextColumn::make('type')
+ ->label('Tipe')
+ ->badge()
+ ->sortable(),
+
+ TextColumn::make('partnerMedia')
+ ->label('Penerima')
+ ->getStateUsing(
+ fn ($record) => $record->partnerMedia->pluck('name')->toArray()
+ )
+ ->listWithLineBreaks()
+ ->limitList(3)
+ ->expandableLimitedList()
+ ->badge()
+ ->placeholder(
+ fn (Announcement $record) => $record->type === AnnouncementType::PUBLIC ? 'Publik' : 'Tidak ada penerima'
+ ),
+
+ ...TimestampColumns::make(),
+ ])
+ ->filters([
+ SelectFilter::make('type')
+ ->label('Tipe')
+ ->options(AnnouncementType::class)
+ ->native(false),
+
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ EditAction::make()
+ ->modalWidth(Width::FiveExtraLarge)
+ ->visible(fn (Announcement $record): bool => $record->type === AnnouncementType::PUBLIC),
+
+ DeleteAction::make(),
+
+ ForceDeleteAction::make(),
+
+ RestoreAction::make(),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('Pengumuman'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedMegaphone)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('announcement.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('announcement.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading();
+ }
+}