$this->getTabsContentComponent()->container($this->makeSchema())->toHtml(),
scopes: static::class,
);
}
public function content(Schema $schema): Schema
{
return $schema
->components([
RenderHook::make(PanelsRenderHook::RESOURCE_RELATION_MANAGER_BEFORE),
EmbeddedTable::make(),
RenderHook::make(PanelsRenderHook::RESOURCE_RELATION_MANAGER_AFTER),
]);
}
public function getTabs(): array
{
$ownerRecord = $this->getOwnerRecord();
$counts = $ownerRecord->lines()
->selectRaw('status, count(*) as count')
->groupBy('status')
->pluck('count', 'status');
return [
'all' => Tab::make('Mind')
->badge($counts->sum()),
'hibas' => Tab::make('Hibás')
->icon(PricelistFileLineStatusEnum::error->icon())
->badgeColor(PricelistFileLineStatusEnum::error->color())
->badge($counts->get(PricelistFileLineStatusEnum::error->value, 0))
->modifyQueryUsing(fn (Builder $query) => $query->where('status', PricelistFileLineStatusEnum::error)),
'warning' => Tab::make('Figyelmeztetések')
->icon(PricelistFileLineStatusEnum::warning->icon())
->badgeColor(PricelistFileLineStatusEnum::warning->color())
->badge($counts->get(PricelistFileLineStatusEnum::warning->value, 0))
->modifyQueryUsing(fn (Builder $query) => $query->where('status', PricelistFileLineStatusEnum::warning)),
'uj' => Tab::make('Új')
->icon(PricelistFileLineStatusEnum::new_product->icon())
->badgeColor(PricelistFileLineStatusEnum::new_product->color())
->badge($counts->get(PricelistFileLineStatusEnum::new_product->value, 0))
->modifyQueryUsing(fn (Builder $query) => $query->where('status', PricelistFileLineStatusEnum::new_product)),
'modosult' => Tab::make('Módosult')
->icon(PricelistFileLineStatusEnum::updated->icon())
->badgeColor(PricelistFileLineStatusEnum::updated->color())
->badge($counts->get(PricelistFileLineStatusEnum::updated->value, 0))
->modifyQueryUsing(fn (Builder $query) => $query->where('status', PricelistFileLineStatusEnum::updated)),
];
}
public function form(Schema $schema): Schema
{
return $schema
->components([
Grid::make(1)
->schema([
Section::make('Módosulások')
->schema([
Text::make(fn ($record) => new HtmlString(
'
' .
collect($record->diff ?? [])->map(function ($d, $field) {
$old = $d['old_label'] ?? $d['old'] ?? 'N/A';
$new = $d['new_label'] ?? $d['new'] ?? 'N/A';
$label = $d['label'] ?? $field;
if ($old === '' || $old === null) $old = '
(üres)';
if ($new === '' || $new === null) $new = '
(üres)';
// Ár formázása ha árról van szó
if ($field === 'price') {
$old = number_format((float)($d['old'] ?? 0), 2, ',', ' ') . ' Ft';
$new = number_format((float)($d['new'] ?? 0), 2, ',', ' ') . ' Ft';
}
return "
";
})->join('') .
'
'
)),
])
->visible(fn ($record) => !empty($record->diff)),
Section::make('Validációs üzenetek')
->schema([
Text::make(fn ($record) => new HtmlString(
'' .
collect($record->validation_messages ?? [])->map(fn ($msg) => "- $msg
")->join('') .
'
'
)),
])
->visible(fn ($record) => !empty($record->validation_messages)),
])
->columnSpan(1)
->visible(fn ($record) => !empty($record->diff) || !empty($record->validation_messages)),
Section::make('Adatok')
->schema([
Text::make(fn ($record) => new HtmlString(
'
| Oszlop |
Érték |
' . collect($record->payload ?? [])->map(function ($value, $key) {
$valStr = is_array($value) ? json_encode($value) : (string)$value;
return '
| ' . e($key) . ' |
' . e($valStr) . ' |
';
})->join('') . '
'
)),
])
->columnSpan(fn ($record) => (empty($record->diff) && empty($record->validation_messages)) ? 2 : 1),
]);
}
public function table(Table $table): Table
{
return $table
->recordTitleAttribute('id')
->columns([
TextColumn::make('row_number')
->label('#')
->sortable()
->width('50px'),
TextColumn::make('status')
->label('Státusz')
->badge()
->color(fn (PricelistFileLineStatusEnum $state) => $state->color())
->formatStateUsing(fn (PricelistFileLineStatusEnum $state) => $state->label())
->icon(fn (PricelistFileLineStatusEnum $state) => $state->icon())
->sortable(),
TextColumn::make('product_info')
->label('Termék')
->description(fn ($record) => $record->payload[PriceListService::EXPECTED_HEADERS[4]] ?? '')
->getStateUsing(fn ($record) => $record->payload[PriceListService::EXPECTED_HEADERS[0]] ?? 'N/A')
->color(fn ($record) => !empty($record->diff) ? 'info' : null)
->wrap()
->searchable(query: function ($query, string $search) {
$sku = PriceListService::EXPECTED_HEADERS[0];
$name = PriceListService::EXPECTED_HEADERS[4];
$query->where("payload->$sku", 'like', "%{$search}%")
->orWhere("payload->$name", 'like', "%{$search}%");
}),
TextColumn::make('price_diff')
->label('Árváltozás')
->html()
->getStateUsing(function ($record) {
// Biztonságos elérés data_get-tel, mert a diff lehet null
$oldPrice = data_get($record->diff, 'price.old');
// Az új árat a diff-ből vesszük (már float), vagy a payload-ból (string lehet)
$newPriceRaw = data_get($record->diff, 'price.new') ?? data_get($record->payload, PriceListService::EXPECTED_HEADERS[14]);
// Normalizálás: szóközök eltávolítása és tizedesvessző cseréje
$newPrice = is_string($newPriceRaw)
? (float) str_replace([' ', ','], ['', '.'], $newPriceRaw)
: (float) $newPriceRaw;
// Ha nincs régi ár, vagy az nulla, akkor nincs százalékos számítás
if (empty($oldPrice) || (float)$oldPrice === 0.0) {
return number_format($newPrice, 2, ',', ' ') . ' Ft';
}
$oldPrice = (float) $oldPrice;
$diffPercent = (($newPrice / $oldPrice) - 1) * 100;
$colorClass = $diffPercent > 0 ? 'text-danger-600' : ($diffPercent < 0 ? 'text-success-600' : 'text-gray-600');
$icon = $diffPercent > 0 ? '↑' : ($diffPercent < 0 ? '↓' : '');
return sprintf(
'
%s Ft
%s Ft %s %s%%
',
number_format($oldPrice, 2, ',', ' '),
number_format($newPrice, 2, ',', ' '),
$colorClass,
$icon,
number_format(abs($diffPercent), 1, ',', ' ')
);
})
->visible(fn ($livewire) => $livewire->getOwnerRecord()->status !== PricelistFileStatusEnum::todo),
TextColumn::make('validation_messages')
->label('Megjegyzés')
->listWithLineBreaks()
->bulleted()
->wrap()
->color(fn ($state) => collect($state)->contains(fn ($msg) => str_contains($msg, 'Hiányzó') || str_contains($msg, 'Ismeretlen') || str_contains($msg, 'Érvénytelen')) ? 'danger' : 'info')
->getStateUsing(function ($record) {
$messages = collect($record->validation_messages ?? [])->values();
$diffMessages = collect($record->diff ?? [])->map(function ($d, $field) {
$label = $d['label'] ?? $field;
$old = $d['old_label'] ?? $d['old'] ?? 'N/A';
$new = $d['new_label'] ?? $d['new'] ?? 'N/A';
if ($field === 'price') {
$old = number_format((float)($d['old'] ?? 0), 0, ',', ' ') . ' Ft';
$new = number_format((float)($d['new'] ?? 0), 0, ',', ' ') . ' Ft';
}
return "Módosult $label: $old -> $new";
})->values();
return $messages->merge($diffMessages)->toArray();
}),
])
->filters([
//
])
->headerActions([
//
])
->actions([
ViewAction::make()
->slideOver()
->modalWidth(Width::FourExtraLarge)
->iconButton()
->modalHeading(fn ($record) => "Sor száma: #{$record->row_number}")
->modalDescription(fn ($record) => "Státusz: " . $record->status->label()),
])
->bulkActions([
//
])
->defaultSort('row_number', 'asc')
->striped()
->poll('5s');
}
}