diff --git a/app/Filament/Resources/Manage/DataChanges/DataChangesResource.php b/app/Filament/Resources/Manage/DataChanges/DataChangesResource.php
index e7ca80d..da694ff 100644
--- a/app/Filament/Resources/Manage/DataChanges/DataChangesResource.php
+++ b/app/Filament/Resources/Manage/DataChanges/DataChangesResource.php
@@ -2,32 +2,19 @@
namespace App\Filament\Resources\Manage\DataChanges;
-use App\Enums\DataChangeStatus;
use App\Enums\RoleEnum;
-use App\Filament\Actions\DefaultBulkActions;
-use App\Filament\Columns\RowIndexColumn;
-use App\Filament\Resources\Manage\DataChanges\Actions\DataChangeRequest\AcceptAction;
-use App\Filament\Resources\Manage\DataChanges\Actions\DataChangeRequest\RejectAction;
+use App\Filament\Resources\Manage\DataChanges\Infolists\DataChangeInfolist;
use App\Filament\Resources\Manage\DataChanges\Pages\ManageDataChanges;
use App\Filament\Resources\Manage\DataChanges\Pages\ViewDataChange;
-use App\Filament\Support\CheerfulNotification;
-use App\Models\Company;
+use App\Filament\Resources\Manage\DataChanges\Tables\DataChangeTable;
use App\Models\DataChangeRequest;
-use App\Models\Journalist;
-use App\Models\PartnerMedia;
use BackedEnum;
-use Filament\Actions\BulkActionGroup;
-use Filament\Actions\ViewAction;
-use Filament\Infolists\Components\TextEntry;
use Filament\Resources\Resource;
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\Support\Facades\Storage;
+use Illuminate\Support\Facades\Auth;
use UnitEnum;
class DataChangesResource extends Resource
@@ -46,7 +33,7 @@ class DataChangesResource extends Resource
public static function getNavigationBadge(): ?string
{
- if (auth()->user()->hasRole(RoleEnum::PERUSAHAAN)) {
+ if (Auth::user()?->hasRole(RoleEnum::PERUSAHAAN)) {
return null;
}
@@ -55,230 +42,19 @@ public static function getNavigationBadge(): ?string
public static function infolist(Schema $schema): Schema
{
- return $schema
- ->schema([
- TextEntry::make('comparison')
- ->hiddenLabel()
- ->html()
- ->state(function (DataChangeRequest $record): string {
- $old = $record->old_data ?? [];
- $new = $record->new_data ?? [];
-
- if (! is_array($old) || ! is_array($new)) {
- return 'Format data tidak valid.';
- }
-
- $renderValue = function ($value) {
- if (empty($value)) {
- return 'Kosong';
- }
-
- $paths = is_array($value) ? $value : [$value];
- $isProbablyPath = false;
-
- foreach ($paths as $path) {
- if (is_string($path) && (str_contains($path, '/') || str_contains($path, '\\'))) {
- $isProbablyPath = true;
- break;
- }
- }
-
- if ($isProbablyPath) {
- return collect($paths)
- ->map(function ($path) {
- if (! is_string($path)) {
- return e(json_encode($path));
- }
-
- $url = Storage::disk(config('filesystems.default'))->url($path);
- $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
-
- if (in_array($extension, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'])) {
- return "
";
- }
-
- if ($extension === 'pdf') {
- return "
-
- ";
- }
-
- return "📎 Buka Dokumen (".strtoupper($extension).')';
- })
- ->implode('
');
- }
-
- return e(is_scalar($value) ? $value : json_encode($value));
- };
-
- // 1. Deletion Request
- if (isset($new['__delete_request__']) && $new['__delete_request__'] === true) {
- return "
-
-
".CheerfulNotification::getByKey('data_change.deletion_request_title')."
-
".CheerfulNotification::getByKey('data_change.deletion_request_desc').'
-
- ';
- }
-
- // 2. New Addition Request
- if (empty($old)) {
- $rows = collect($new)
- ->map(function ($value, $key) use ($renderValue) {
- return sprintf(
- "",
- e($key),
- $renderValue($value)
- );
- })
- ->implode('');
-
- return "
-
-
".CheerfulNotification::getByKey('data_change.addition_request_title')."
-
".CheerfulNotification::getByKey('data_change.addition_request_desc')."
-
- {$rows}
- ";
- }
-
- // 3. Standard Comparison (Update)
- return collect($new)
- ->map(function ($newValue, $key) use ($old, $renderValue) {
- $oldValue = $old[$key] ?? null;
-
- if ($oldValue === $newValue) {
- return null;
- }
-
- return sprintf(
- "",
- e($key),
- $renderValue($oldValue),
- $renderValue($newValue)
- );
- })
- ->filter()
- ->implode('');
- })
- ->columnSpanFull(),
- ])
- ->columns(1);
+ return DataChangeInfolist::configure($schema);
}
public static function table(Table $table): Table
{
- return $table
- ->columns([
- ...RowIndexColumn::make(),
-
- TextColumn::make('user.name')
- ->label('Pemohon')
- ->searchable()
- ->sortable()
- ->description(fn (DataChangeRequest $record): ?string => $record?->entity?->name)
- ->visible(! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
-
- TextColumn::make('entity_type')
- ->label('Jenis Data')
- ->searchable()
- ->sortable()
- ->description(fn (DataChangeRequest $record): ?string => match (true) {
- isset($record->new_data['__delete_request__']) => CheerfulNotification::getByKey('data_change.deletion'),
- empty($record->old_data) => CheerfulNotification::getByKey('data_change.addition'),
- default => CheerfulNotification::getByKey('data_change.change'),
- })
- ->formatStateUsing(fn (DataChangeRequest $record): ?string => match ($record->entity_type) {
- Company::class => 'Perusahaan',
- PartnerMedia::class => 'Media',
- Journalist::class => 'Jurnalis',
- default => 'Lainnya',
- })
- ->color(fn (DataChangeRequest $record): ?string => match ($record->entity_type) {
- Company::class => 'success',
- PartnerMedia::class => 'info',
- Journalist::class => 'warning',
- default => 'secondary',
- })
- ->badge(),
-
- TextColumn::make('status')
- ->label('Status')
- ->searchable()
- ->sortable()
- ->badge()
- ->formatStateUsing(fn (DataChangeStatus $state): string => $state->getLabel())
- ->color(fn (DataChangeStatus $state): string => $state->getColor())
- ->description(fn (DataChangeRequest $record): ?string => $record?->review ? 'Oleh: '.$record->review?->reviewer?->name : ''),
-
- TextColumn::make('change_reason')
- ->label('Alasan Perubahan')
- ->limit(50),
-
- TextColumn::make('review.note')
- ->label('Alasan Penolakan')
- ->limit(50),
-
- TextColumn::make('created_at')
- ->label('Tgl Permohonan')
- ->date()
- ->sortable()
- ->dateTime('l, d F Y H:i:s')
- ->wrap(),
- ])
- ->filters([
- SelectFilter::make('status')
- ->label('Status')
- ->options(DataChangeStatus::class)
- ->native(false),
-
- TrashedFilter::make()
- ->native(false)
- ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
- ])
- ->recordActions([
- ViewAction::make(),
- AcceptAction::make('accept'),
- RejectAction::make('reject'),
- ])
- ->toolbarActions([
- BulkActionGroup::make([
- ...DefaultBulkActions::make('permohonan perubahan data'),
- ]),
- ])
- ->emptyStateIcon(Heroicon::OutlinedDocumentText)
- ->emptyStateHeading(fn () => CheerfulNotification::getByKey('data_change.empty_state_heading'))
- ->emptyStateDescription(fn () => CheerfulNotification::getByKey('data_change.empty_state'))
- ->defaultSort('created_at', 'desc')
- ->deferFilters(false)
- ->paginated([25, 50, 100, 'all'])
- ->deferLoading();
+ return DataChangeTable::configure($table);
}
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
- ->when(auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value), function (Builder $q): Builder {
- return $q->where('user_id', auth()->id());
+ ->when(Auth::user()?->hasRole(RoleEnum::PERUSAHAAN->value), function (Builder $q): Builder {
+ return $q->where('user_id', Auth::id());
});
}
diff --git a/app/Filament/Resources/Manage/DataChanges/Infolists/DataChangeInfolist.php b/app/Filament/Resources/Manage/DataChanges/Infolists/DataChangeInfolist.php
new file mode 100644
index 0000000..1c2eb31
--- /dev/null
+++ b/app/Filament/Resources/Manage/DataChanges/Infolists/DataChangeInfolist.php
@@ -0,0 +1,144 @@
+schema([
+ TextEntry::make('comparison')
+ ->hiddenLabel()
+ ->html()
+ ->state(function (DataChangeRequest $record): string {
+ $old = $record->old_data ?? [];
+ $new = $record->new_data ?? [];
+
+ if (! is_array($old) || ! is_array($new)) {
+ return 'Format data tidak valid.';
+ }
+
+ $renderValue = function ($value) {
+ if (empty($value)) {
+ return 'Kosong';
+ }
+
+ $paths = is_array($value) ? $value : [$value];
+ $isProbablyPath = false;
+
+ foreach ($paths as $path) {
+ if (is_string($path) && (str_contains($path, '/') || str_contains($path, '\\'))) {
+ $isProbablyPath = true;
+ break;
+ }
+ }
+
+ if ($isProbablyPath) {
+ return collect($paths)
+ ->map(function ($path) {
+ if (! is_string($path)) {
+ return e(json_encode($path));
+ }
+
+ $url = Storage::disk(config('filesystems.default'))->url($path);
+ $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
+
+ if (in_array($extension, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'])) {
+ return "
";
+ }
+
+ if ($extension === 'pdf') {
+ return "
+
+ ";
+ }
+
+ return "📎 Buka Dokumen (".strtoupper($extension).')';
+ })
+ ->implode('
');
+ }
+
+ return e(is_scalar($value) ? $value : json_encode($value));
+ };
+
+ // 1. Deletion Request
+ if (isset($new['__delete_request__']) && $new['__delete_request__'] === true) {
+ return "
+
+
".CheerfulNotification::getByKey('data_change.deletion_request_title')."
+
".CheerfulNotification::getByKey('data_change.deletion_request_desc').'
+
+ ';
+ }
+
+ // 2. New Addition Request
+ if (empty($old)) {
+ $rows = collect($new)
+ ->map(function ($value, $key) use ($renderValue) {
+ return sprintf(
+ "",
+ e($key),
+ $renderValue($value)
+ );
+ })
+ ->implode('');
+
+ return "
+
+
".CheerfulNotification::getByKey('data_change.addition_request_title')."
+
".CheerfulNotification::getByKey('data_change.addition_request_desc')."
+
+ {$rows}
+ ";
+ }
+
+ // 3. Standard Comparison (Update)
+ return collect($new)
+ ->map(function ($newValue, $key) use ($old, $renderValue) {
+ $oldValue = $old[$key] ?? null;
+
+ if ($oldValue === $newValue) {
+ return null;
+ }
+
+ return sprintf(
+ "",
+ e($key),
+ $renderValue($oldValue),
+ $renderValue($newValue)
+ );
+ })
+ ->filter()
+ ->implode('');
+ })
+ ->columnSpanFull(),
+ ])
+ ->columns(1);
+ }
+}
diff --git a/app/Filament/Resources/Manage/DataChanges/Tables/DataChangeTable.php b/app/Filament/Resources/Manage/DataChanges/Tables/DataChangeTable.php
new file mode 100644
index 0000000..a0b35d2
--- /dev/null
+++ b/app/Filament/Resources/Manage/DataChanges/Tables/DataChangeTable.php
@@ -0,0 +1,114 @@
+columns([
+ ...RowIndexColumn::make(),
+
+ TextColumn::make('user.name')
+ ->label('Pemohon')
+ ->searchable()
+ ->sortable()
+ ->description(fn (DataChangeRequest $record): ?string => $record?->entity?->name)
+ ->visible(! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
+
+ TextColumn::make('entity_type')
+ ->label('Jenis Data')
+ ->searchable()
+ ->sortable()
+ ->description(fn (DataChangeRequest $record): ?string => match (true) {
+ isset($record->new_data['__delete_request__']) => CheerfulNotification::getByKey('data_change.deletion'),
+ empty($record->old_data) => CheerfulNotification::getByKey('data_change.addition'),
+ default => CheerfulNotification::getByKey('data_change.change'),
+ })
+ ->formatStateUsing(fn (DataChangeRequest $record): ?string => match ($record->entity_type) {
+ Company::class => 'Perusahaan',
+ PartnerMedia::class => 'Media',
+ Journalist::class => 'Jurnalis',
+ default => 'Lainnya',
+ })
+ ->color(fn (DataChangeRequest $record): ?string => match ($record->entity_type) {
+ Company::class => 'success',
+ PartnerMedia::class => 'info',
+ Journalist::class => 'warning',
+ default => 'secondary',
+ })
+ ->badge(),
+
+ TextColumn::make('status')
+ ->label('Status')
+ ->searchable()
+ ->sortable()
+ ->badge()
+ ->formatStateUsing(fn (DataChangeStatus $state): string => $state->getLabel())
+ ->color(fn (DataChangeStatus $state): string => $state->getColor())
+ ->description(fn (DataChangeRequest $record): ?string => $record?->review ? 'Oleh: '.$record->review?->reviewer?->name : ''),
+
+ TextColumn::make('change_reason')
+ ->label('Alasan Perubahan')
+ ->limit(50),
+
+ TextColumn::make('review.note')
+ ->label('Alasan Penolakan')
+ ->limit(50),
+
+ TextColumn::make('created_at')
+ ->label('Tgl Permohonan')
+ ->date()
+ ->sortable()
+ ->dateTime('l, d F Y H:i:s')
+ ->wrap(),
+ ])
+ ->filters([
+ SelectFilter::make('status')
+ ->label('Status')
+ ->options(DataChangeStatus::class)
+ ->native(false),
+
+ TrashedFilter::make()
+ ->native(false)
+ ->visible(fn () => auth()->user()?->hasRole(RoleEnum::DEVELOPER->value)),
+ ])
+ ->recordActions([
+ ViewAction::make(),
+ AcceptAction::make('accept'),
+ RejectAction::make('reject'),
+ ])
+ ->toolbarActions([
+ BulkActionGroup::make([
+ ...DefaultBulkActions::make('permohonan perubahan data'),
+ ]),
+ ])
+ ->emptyStateIcon(Heroicon::OutlinedDocumentText)
+ ->emptyStateHeading(fn () => CheerfulNotification::getByKey('data_change.empty_state_heading'))
+ ->emptyStateDescription(fn () => CheerfulNotification::getByKey('data_change.empty_state'))
+ ->defaultSort('created_at', 'desc')
+ ->deferFilters(false)
+ ->paginated([25, 50, 100, 'all'])
+ ->deferLoading();
+ }
+}