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 = "
";
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 "
";
}
private static function header(string $type, string $title, string $desc, string $badge): string
{
$icon = self::icon($type);
return "
";
}
private static function row(string $key, string $value): string
{
return "
";
}
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(' ');
}
}