diff --git a/app/Filament/Resources/Manage/DataChanges/Actions/AcceptAction.php b/app/Filament/Resources/Manage/DataChanges/Actions/AcceptAction.php index ffb24f9..e385ccf 100644 --- a/app/Filament/Resources/Manage/DataChanges/Actions/AcceptAction.php +++ b/app/Filament/Resources/Manage/DataChanges/Actions/AcceptAction.php @@ -35,7 +35,7 @@ protected function setUp(): void $entity = $record->entity; $newData = $record->new_data; - if (isset($newData['__delete_request__']) && $newData['__delete_request__'] === true) { + if (empty($newData)) { $entity->delete(); $record->update(['status' => DataChangeStatus::APPROVED]); diff --git a/app/Filament/Resources/Manage/DataChanges/Infolists/DataChangeInfolist.php b/app/Filament/Resources/Manage/DataChanges/Infolists/DataChangeInfolist.php index 71e2449..054f3dc 100644 --- a/app/Filament/Resources/Manage/DataChanges/Infolists/DataChangeInfolist.php +++ b/app/Filament/Resources/Manage/DataChanges/Infolists/DataChangeInfolist.php @@ -4,229 +4,194 @@ use App\Filament\Support\CheerfulNotification; use App\Models\DataChangeRequest; +use Filament\Infolists\Components\ImageEntry; use Filament\Infolists\Components\TextEntry; +use Filament\Schemas\Components\Grid; use Filament\Schemas\Components\Section; use Filament\Schemas\Schema; use Illuminate\Support\Facades\Storage; +use Joaopaulolndev\FilamentPdfViewer\Infolists\Components\PdfViewerEntry; class DataChangeInfolist { public static function configure(Schema $schema): Schema { return $schema - ->schema([ - Section::make() - ->schema([ - TextEntry::make('comparison') + ->schema(function (DataChangeRequest $record): array { + $old = $record->old_data ?? []; + $new = $record->new_data ?? []; + + if (! is_array($old) || ! is_array($new)) { + return [ + TextEntry::make('error') ->hiddenLabel() - ->html() - ->state(function (DataChangeRequest $record): string { - $old = $record->old_data ?? []; - $new = $record->new_data ?? []; + ->state('Format data tidak valid.') + ->badge() + ->color('danger'), + ]; + } - if (! is_array($old) || ! is_array($new)) { - return self::alert('Format data tidak valid.', 'warning'); - } + if (empty($new)) { + return self::buildDeletionView($old); + } - if (isset($new['__delete_request__']) && $new['__delete_request__'] === true) { - return self::deletionView($old); - } + if (empty($old)) { + return self::buildAdditionView($new); + } - if (empty($old)) { - return self::additionView($new); - } - - return self::updateView($old, $new); - }), - ]), - ]) + return self::buildUpdateView($old, $new); + }) ->columns(1); } - private static function deletionView(array $old): string + private static function buildDeletionView(array $old): array { $title = CheerfulNotification::getByKey('data_change.deletion_request_title'); $desc = CheerfulNotification::getByKey('data_change.deletion_request_desc'); - $rows = collect($old) - ->map(fn ($v, $k) => self::row($k, self::renderValue($v))) - ->implode(''); - - return self::card( - header: self::header('del', $title, $desc, self::badge('Penghapusan', 'del')), - body: $rows ?: self::emptyRow(), - ); + return [ + Section::make($title) + ->description($desc) + ->icon('heroicon-o-trash') + ->schema([ + TextEntry::make('badge')->hiddenLabel()->state('Penghapusan')->badge()->color('danger'), + ...collect($old)->map(fn ($v, $k) => self::fieldEntry($k, $v, showLabel: true))->flatten()->toArray(), + ]), + ]; } - private static function additionView(array $new): string + private static function buildAdditionView(array $new): array { $title = CheerfulNotification::getByKey('data_change.addition_request_title'); $desc = CheerfulNotification::getByKey('data_change.addition_request_desc'); - $rows = collect($new) - ->map(fn ($v, $k) => self::row($k, self::renderValue($v))) - ->implode(''); - - return self::card( - header: self::header('add', $title, $desc, self::badge('Penambahan Baru', 'add')), - body: $rows ?: self::emptyRow(), - ); + return [ + Section::make($title) + ->description($desc) + ->icon('heroicon-o-plus-circle') + ->schema([ + TextEntry::make('badge')->hiddenLabel()->state('Penambahan Baru')->badge()->color('success'), + ...collect($new)->map(fn ($v, $k) => self::fieldEntry($k, $v, showLabel: true))->flatten()->toArray(), + ]), + ]; } - private static function updateView(array $old, array $new): string + private static function buildUpdateView(array $old, array $new): array { - $changed = collect($new) - ->map(function ($newVal, $key) use ($old) { - $oldVal = $old[$key] ?? null; + $title = CheerfulNotification::getByKey('data_change.comparison_title'); + $desc = CheerfulNotification::getByKey('data_change.comparison_desc'); - if ($oldVal === $newVal) { - return null; - } + $changedFields = collect($new) + ->filter(fn ($newVal, $key) => ($old[$key] ?? null) !== $newVal); - return " -
-
".e($key)."
-
-
".self::renderValue($oldVal)."
-
".self::renderValue($newVal).'
-
-
'; - }) - ->filter(); - - if ($changed->isEmpty()) { - return self::alert('Tidak ada perubahan data yang terdeteksi.', 'info'); + if ($changedFields->isEmpty()) { + return [ + TextEntry::make('info')->hiddenLabel()->state('Tidak ada perubahan data terdeteksi.')->badge()->color('info'), + ]; } - $count = $changed->count(); - $label = $count === 1 ? '1 field diubah' : "{$count} field diubah"; + $fieldCount = $changedFields->count(); + $label = $fieldCount === 1 ? '1 field diubah' : "{$fieldCount} field diubah"; - $diffHeader = " -
-
-
-
Sebelum
-
Sesudah
-
-
"; + return [ + Section::make($title) + ->description($desc) + ->icon('heroicon-o-pencil-square') + ->schema([ + TextEntry::make('badge')->hiddenLabel()->state($label)->badge()->color('primary'), + Grid::make(1) + ->schema( + $changedFields->map(function ($newVal, $key) use ($old) { + $oldVal = $old[$key] ?? null; - return self::card( - header: self::header('edit', CheerfulNotification::getByKey('data_change.comparison_title'), CheerfulNotification::getByKey('data_change.comparison_desc'), self::badge($label, 'default')), - body: $diffHeader.$changed->implode(''), - ); + return [ + Section::make($key) + ->columnSpanFull() + ->compact() + ->schema([ + Grid::make(2) + ->schema([ + Grid::make(1) + ->schema([ + TextEntry::make("{$key}_old_label") + ->hiddenLabel() + ->state('SEBELUM') + ->weight('bold') + ->size('xs') + ->color('danger'), + ...self::fieldEntry("{$key}_old", $oldVal, showLabel: false), + ])->columnSpan(1), + + Grid::make(1) + ->schema([ + TextEntry::make("{$key}_new_label") + ->hiddenLabel() + ->state('SESUDAH') + ->weight('bold') + ->size('xs') + ->color('success'), + ...self::fieldEntry("{$key}_new", $newVal, showLabel: false), + ])->columnSpan(1), + ]), + ]), + ]; + })->flatten()->toArray() + ), + ]), + ]; } - private static function card(string $header, string $body): string + private static function fieldEntry(string $label, mixed $value, bool $showLabel = true): array { - return " -
- {$header} -
{$body}
-
"; - } + $id = str($label)->slug('_')->toString(); - private static function header(string $type, string $title, string $desc, string $badge): string - { - $icon = self::icon($type); - - return " -
- {$icon} -
-
{$title}
-
{$desc}
-
- {$badge} -
"; - } - - private static function row(string $key, string $value): string - { - return " -
-
".e($key)."
-
{$value}
-
"; - } - - private static function emptyRow(): string - { - return "
Tidak ada data tersedia.
"; - } - - private static function badge(string $label, string $variant): string - { - [$bg, $color, $border] = match ($variant) { - 'del' => ['var(--dcr-badge-del-bg)', 'var(--dcr-badge-del-color)', 'var(--dcr-badge-del-border)'], - 'add' => ['var(--dcr-badge-add-bg)', 'var(--dcr-badge-add-color)', 'var(--dcr-badge-add-border)'], - default => ['var(--dcr-badge-bg)', 'var(--dcr-badge-color)', 'var(--dcr-badge-border)'], - }; - - return "{$label}"; - } - - private static function alert(string $message, string $type = 'info'): string - { - $icon = $type === 'warning' ? '⚠' : 'ℹ'; - - return " -
- {$icon} - {$message} -
"; - } - - private static function icon(string $type): string - { - return match ($type) { - 'del' => "", - 'add' => "", - 'edit' => "", - default => '', - }; - } - - private static function renderValue(mixed $value): string - { if ($value === null || $value === '' || (is_array($value) && empty($value))) { - return ""; + return [ + TextEntry::make($id) + ->label($label) + ->hiddenLabel(! $showLabel) + ->state('—') + ->color('gray'), + ]; } $paths = is_array($value) ? $value : [$value]; + $components = []; - return collect($paths)->map(function ($item) { - if (! is_string($item)) { - return "".e(json_encode($item)).''; - } + foreach ($paths as $index => $item) { + $uniqueId = "{$id}_{$index}"; - if (preg_match('/^https?:\/\//i', $item)) { - return "".e($item).''; - } - - if ((str_contains($item, '/') || str_contains($item, '\\')) && ! str_contains($item, ' ')) { - $url = Storage::disk(config('filesystems.default'))->url($item); + if (is_string($item) && (str_contains($item, '/') || str_contains($item, '\\'))) { $ext = strtolower(pathinfo($item, PATHINFO_EXTENSION)); if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'])) { - return ""; + $components[] = ImageEntry::make($uniqueId) + ->label($index === 0 ? $label : '') + ->hiddenLabel(! ($showLabel && $index === 0)) + ->disk(config('filesystems.default')) + ->state($item) + ->extraImgAttributes(['style' => 'max-height: 200px; width: auto; border-radius: 0.5rem;']); + + continue; } if ($ext === 'pdf') { - return " -
- -
"; + $components[] = PdfViewerEntry::make($uniqueId) + ->label($index === 0 ? $label : '') + ->hiddenLabel(! ($showLabel && $index === 0)) + ->minHeight('500px') + ->state(Storage::disk(config('filesystems.default'))->url($item)); + + continue; } - - $extUp = $ext ? strtoupper($ext) : 'FILE'; - - return " - - Dokumen {$extUp} - "; } - return "".e($item).''; - })->implode('
'); + $components[] = TextEntry::make($uniqueId) + ->label($index === 0 ? $label : '') + ->hiddenLabel(! ($showLabel && $index === 0)) + ->state(is_scalar($item) ? $item : json_encode($item)); + } + + return $components; } } diff --git a/app/Filament/Resources/Manage/Journalists/Actions/DeleteJournalistAction.php b/app/Filament/Resources/Manage/Journalists/Actions/DeleteJournalistAction.php index 26e3f20..9558538 100644 --- a/app/Filament/Resources/Manage/Journalists/Actions/DeleteJournalistAction.php +++ b/app/Filament/Resources/Manage/Journalists/Actions/DeleteJournalistAction.php @@ -28,9 +28,10 @@ protected function setUp(): void $this->successNotification(null); - $this->modalHeading(fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED - ? CheerfulNotification::getByKey('journalist.request_deletion_title') - : CheerfulNotification::getByKey('journalist.delete_title') + $this->modalHeading( + fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED + ? CheerfulNotification::getByKey('journalist.request_deletion_title') + : CheerfulNotification::getByKey('journalist.delete_title') ); $this->schema(fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED ? [ @@ -58,12 +59,42 @@ protected function setUp(): void return; } + $fieldLabels = Journalist::dataChangeEntryLabels(); + $oldFields = []; + + // Standard fields + foreach (['name', 'email', 'phone_number', 'press_card', 'ukw_certificate'] as $f) { + $label = $fieldLabels[$f] ?? $f; + $val = $record->{$f}; + + // Resolve enums if necessary + if ($val instanceof \BackedEnum) { + $val = $val->value; + } + + $oldFields[$label] = $val ?? '-'; + } + + // Document fields + $mediaItems = $record->getMedia('journalists'); + foreach (['press_card_docs', 'ukw_certificate_docs'] as $df) { + $label = $fieldLabels[$df] ?? $df; + $docType = str($df)->replace('_docs', '')->slug('-'); + + $currentMedia = $mediaItems + ->where('custom_properties.doc_type', $docType) + ->sortByDesc('created_at') + ->first(); + + $oldFields[$label] = $currentMedia ? [$currentMedia->getPathRelativeToRoot()] : []; + } + $dataChangeRequest = DataChangeRequest::create([ 'user_id' => $user->id, 'entity_type' => Journalist::class, 'entity_id' => $record->id, - 'old_data' => $record->toArray(), - 'new_data' => ['__delete_request__' => true], + 'old_data' => $oldFields, + 'new_data' => [], 'change_reason' => $data['deletion_reason'] ?? 'Penghapusan jurnalis', ]); diff --git a/lang/id/notif.php b/lang/id/notif.php index 6b058a4..7f537ea 100644 --- a/lang/id/notif.php +++ b/lang/id/notif.php @@ -708,6 +708,14 @@ 'cheerful' => 'Maaf ya, pengajuan perubahan data kamu terpaksa ditolak untuk saat ini. Tetap semangat! 💪', 'formal' => 'Pengajuan perubahan data Anda tidak dapat disetujui.', ], + 'deletion_approved' => [ + 'cheerful' => 'Hapus Berhasil! 🗑️🚀', + 'formal' => 'Penghapusan Disetujui', + ], + 'deletion_success_desc' => [ + 'cheerful' => 'Sip! Data tersebut sudah berhasil dihapus secara permanen dari sistem sebagaimana permintaanmu. ✨🚮', + 'formal' => 'Data tersebut telah berhasil dihapus dari sistem sesuai permohonan.', + ], ], 'visitor' => [ 'empty_state' => [