schema([ Section::make() ->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 self::alert('Format data tidak valid.', 'warning'); } if (isset($new['__delete_request__']) && $new['__delete_request__'] === true) { return self::deletionView($old); } if (empty($old)) { return self::additionView($new); } return self::updateView($old, $new); }), ]), ]) ->columns(1); } private static function deletionView(array $old): string { $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(), ); } private static function additionView(array $new): string { $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(), ); } private static function updateView(array $old, array $new): string { $changed = collect($new) ->map(function ($newVal, $key) use ($old) { $oldVal = $old[$key] ?? null; if ($oldVal === $newVal) { return null; } return "
".e($key)."
".self::renderValue($oldVal)."
".self::renderValue($newVal).'
'; }) ->filter(); if ($changed->isEmpty()) { return self::alert('Tidak ada perubahan data yang terdeteksi.', 'info'); } $count = $changed->count(); $label = $count === 1 ? '1 field diubah' : "{$count} field diubah"; $diffHeader = "
Sebelum
Sesudah
"; 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(''), ); } private static function card(string $header, string $body): string { return "
{$header}
{$body}
"; } 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 ""; } $paths = is_array($value) ? $value : [$value]; return collect($paths)->map(function ($item) { if (! is_string($item)) { return "".e(json_encode($item)).''; } 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); $ext = strtolower(pathinfo($item, PATHINFO_EXTENSION)); if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'])) { return ""; } if ($ext === 'pdf') { return "
"; } $extUp = $ext ? strtoupper($ext) : 'FILE'; return " Dokumen {$extUp} "; } return "".e($item).''; })->implode('
'); } }