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() ->state('Format data tidak valid.') ->badge() ->color('danger'), ]; } if (empty($new)) { return self::buildDeletionView($old); } if (empty($old)) { return self::buildAdditionView($new); } return self::buildUpdateView($old, $new); }) ->columns(1); } private static function buildDeletionView(array $old): array { $title = CheerfulNotification::getByKey('data_change.deletion_request_title'); $desc = CheerfulNotification::getByKey('data_change.deletion_request_desc'); 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 buildAdditionView(array $new): array { $title = CheerfulNotification::getByKey('data_change.addition_request_title'); $desc = CheerfulNotification::getByKey('data_change.addition_request_desc'); 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 buildUpdateView(array $old, array $new): array { $title = CheerfulNotification::getByKey('data_change.comparison_title'); $desc = CheerfulNotification::getByKey('data_change.comparison_desc'); $changedFields = collect($new) ->filter(fn ($newVal, $key) => ($old[$key] ?? null) !== $newVal); if ($changedFields->isEmpty()) { return [ TextEntry::make('info')->hiddenLabel()->state('Tidak ada perubahan data terdeteksi.')->badge()->color('info'), ]; } $fieldCount = $changedFields->count(); $label = $fieldCount === 1 ? '1 field diubah' : "{$fieldCount} field diubah"; 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 [ 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 fieldEntry(string $label, mixed $value, bool $showLabel = true): array { $id = str($label)->slug('_')->toString(); if ($value === null || $value === '' || (is_array($value) && empty($value))) { return [ TextEntry::make($id) ->label($label) ->hiddenLabel(! $showLabel) ->state('—') ->color('gray'), ]; } $paths = is_array($value) ? $value : [$value]; $components = []; foreach ($paths as $index => $item) { $uniqueId = "{$id}_{$index}"; 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'])) { $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') { $components[] = PdfViewerEntry::make($uniqueId) ->label($index === 0 ? $label : '') ->hiddenLabel(! ($showLabel && $index === 0)) ->minHeight('500px') ->state(Storage::disk(config('filesystems.default'))->url($item)); continue; } } $components[] = TextEntry::make($uniqueId) ->label($index === 0 ? $label : '') ->hiddenLabel(! ($showLabel && $index === 0)) ->state(is_scalar($item) ? $item : json_encode($item)); } return $components; } }