simedkom/app/Filament/Resources/Manage/DataChanges/Infolists/DataChangeInfolist.php

198 lines
8.2 KiB
PHP

<?php
namespace App\Filament\Resources\Manage\DataChanges\Infolists;
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(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;
}
}