components([ // Döntéstámogató panel: megszakadt végrehajtás után a felhasználónak a // Folytatás és a Visszavonás között kell választania. Enélkül vakon // döntene - itt látja, mi történt már meg az importból. Section::make('Megszakadt végrehajtás') ->description('A végrehajtás nem fejeződött be. Az árlista nem élesedett, tehát a felhasználók felé nem került ki ár. Döntsd el, folytatod-e, vagy visszavonod a már végrehajtott részt.') ->icon('heroicon-o-exclamation-triangle') ->columnSpanFull() ->maxWidth(Width::Full) ->visible(fn ($record) => $record->needsExecutionDecision()) ->schema([ TextEntry::make('execution_error') ->label('Hiba') ->color('danger') ->weight(FontWeight::Bold) ->columnSpanFull() ->getStateUsing(fn ($record) => $record->isExecutionStuck() ? 'A végrehajtás ' . PricelistFile::STUCK_AFTER_MINUTES . ' percnél régebben nem jelzett haladást (elakadt folyamat).' : ($record->processing_current_step ?: 'Ismeretlen hiba.')), Grid::make(4)->schema([ TextEntry::make('created_products') ->label('Létrehozott termék') ->icon('heroicon-o-plus-circle') ->getStateUsing(fn ($record) => $record->executionSummary()['created_products']), TextEntry::make('updated_products') ->label('Frissített termék') ->icon('heroicon-o-pencil-square') ->getStateUsing(fn ($record) => $record->executionSummary()['updated_products']), TextEntry::make('priced_lines') ->label('Rögzített ár') ->icon('heroicon-o-currency-dollar') ->getStateUsing(fn ($record) => $record->executionSummary()['priced_lines']), TextEntry::make('pending_lines') ->label('Hátralévő sor') ->icon('heroicon-o-clock') ->getStateUsing(fn ($record) => $record->executionSummary()['pending_lines']), ]), TextEntry::make('revert_error') ->label('Utolsó visszaállítási kísérlet hibája') ->color('danger') ->columnSpanFull() ->visible(fn ($record) => ($record->file_meta['revert']['last_status'] ?? null) === 'failed') ->getStateUsing(fn ($record) => $record->file_meta['revert']['last_error'] ?? null), ]), // A jóváhagyás gombjai némán tűnnének el, ha ugyanahhoz a beszállítóhoz // egy másik fájl végrehajtása van nyitva - ez megmondja, miért. Section::make('Blokkolt beszállító') ->icon('heroicon-o-no-symbol') ->columnSpanFull() ->maxWidth(Width::Full) ->visible(fn ($record) => $record->status === PricelistFileStatusEnum::waiting_for_approval && app(PricelistGuard::class)->isBlocked($record->supplier_id, $record->id)) ->schema([ TextEntry::make('blocking_file') ->hiddenLabel() ->color('danger') ->columnSpanFull() ->getStateUsing(function ($record) { $guard = app(PricelistGuard::class); $blockingFile = $guard->blockingFileFor($record->supplier_id, $record->id); return $blockingFile ? $guard->blockingMessage($blockingFile) : null; }), ]), Section::make(null) ->poll('5s') ->columnSpanFull() ->maxWidth(Width::Full) ->schema([ Grid::make(2) ->columnSpanFull() ->maxWidth(Width::Full) ->schema([ // BAL OSZLOP Grid::make(1) ->columnSpan(1) ->schema([ Section::make('Fájl információk') ->schema([ Grid::make(3) ->schema([ TextEntry::make('filename') ->label('Fájlnév') ->icon('heroicon-o-document-text') ->color('primary'), TextEntry::make('supplier.name') ->label('Beszállító') ->icon('heroicon-o-user'), TextEntry::make('status') ->label('Státusz') ->badge() ->formatStateUsing(fn (PricelistFileStatusEnum $state): string => $state->label()) ->color(fn (PricelistFileStatusEnum $state): string => $state->color()), ]), Grid::make(3) ->schema([ TextEntry::make('available_date') ->label('Életbelépés') ->date('Y.m.d'), TextEntry::make('created_at') ->label('Feltöltés') ->dateTime('Y.m.d H:i'), ]), // SÁRGA NÉGYZET JAVÍTÁSA: Teljes szélességben alul, csak hiba esetén TextEntry::make('processing_current_step') ->label('Validációs hiba') ->weight('bold') ->color('danger') ->columnSpanFull() ->visible(fn ($record) => $record->status === PricelistFileStatusEnum::fail) ->formatStateUsing(fn ($state, $record) => str_contains((string)$state, 'hibás') ? $state : "Hiba történt a folyamat során: $state"), // Folyamatban lévő állapot kijelzése (nem hiba, de hasznos) TextEntry::make('processing_current_step_inprogress') ->label('Aktuális folyamat') ->getStateUsing(fn ($record) => $record->processing_current_step) ->weight('bold') ->color('info') ->columnSpanFull() ->visible(fn ($record) => $record->status === PricelistFileStatusEnum::inprogress) ->formatStateUsing(fn ($state, $record) => "$state ({$record->processing_current_step_percentage}%)"), TextEntry::make('note') ->label('Megjegyzés') ->placeholder('Nincs megjegyzés') ->columnSpanFull(), ]), ]), // JOBB OSZLOP Grid::make(1) ->columnSpan(1) ->schema([ Section::make('Fájl statisztika') // KÉK NÉGYZETEK JAVÍTÁSA: Összevont szekció ->schema([ Grid::make(5)->schema([ TextEntry::make('lines_count') ->label('Sorok') ->icon('heroicon-o-list-bullet') ->getStateUsing(fn ($record) => $record->lines()->count()), TextEntry::make('error_lines_count') ->label('Hibás') ->icon('heroicon-o-x-circle') ->color('danger') ->getStateUsing(fn ($record) => $record->lines()->where('status', 'error')->count()), TextEntry::make('warning_lines_count') ->label('Figyelm.') ->icon('heroicon-o-exclamation-triangle') ->color('warning') ->getStateUsing(fn ($record) => $record->lines()->where('status', 'warning')->count()), TextEntry::make('new_lines_count') ->label('Új') ->icon('heroicon-o-sparkles') ->color('info') ->getStateUsing(fn ($record) => $record->lines()->where('status', 'new_product')->count()), TextEntry::make('updated_lines_count') ->label('Módosult') ->icon('heroicon-o-pencil-square') ->color('primary') ->getStateUsing(fn ($record) => $record->lines()->where('status', 'updated')->count()), ]), Grid::make(4)->schema([ TextEntry::make('file_meta.preprocess.statistics.data_rows') ->label('Adatsorok') ->icon('heroicon-o-table-cells'), TextEntry::make('file_meta.preprocess.statistics.column_count') ->label('Oszlopok'), TextEntry::make('file_meta.preprocess.file_info.file_size_human') ->label('Fájlméret'), TextEntry::make('file_meta.preprocess.duration_seconds') ->label('Idő') ->suffix(' mp'), ]) ->extraAttributes(['class' => 'mt-4 border-t pt-4']), ]) ->visible(fn ($record) => $record->lines()->exists() || !empty($record->file_meta['preprocess'] ?? [])), Section::make('Feldolgozási folyamat (Workflow)') ->collapsible() ->collapsed(fn ($record) => $record->status !== PricelistFileStatusEnum::inprogress) ->schema([ RepeatableEntry::make('workflow_steps') ->label(false) ->schema([ TextEntry::make('label') ->label('Lépés') ->weight('bold') ->inlineLabel(), TextEntry::make('status') ->label('Állapot') ->badge() ->inlineLabel() ->formatStateUsing(fn (string $state): string => match ($state) { 'pending' => 'várakozik', 'inprogress' => 'folyamatban', 'completed' => 'kész', 'failed' => 'hiba', default => $state, }) ->color(fn (string $state): string => match ($state) { 'pending' => 'gray', 'inprogress' => 'info', 'completed' => 'success', 'failed' => 'danger', default => 'gray', }) ->icon(fn (string $state): string => match ($state) { 'pending' => 'heroicon-o-clock', 'inprogress' => 'heroicon-o-arrow-path', 'completed' => 'heroicon-o-check-circle', 'failed' => 'heroicon-o-x-circle', default => 'heroicon-o-question-mark-circle', }), ]) ->columns(2) ->columnSpanFull(), ]), RepeatableEntry::make('file_meta.preprocess.warnings') ->label('Előfeldolgozási figyelmeztetések') ->schema([ TextEntry::make('message')->label('Leírás')->color('warning'), TextEntry::make('severity')->label('Súlyosság')->badge()->color('warning'), ]) ->visible(fn ($record) => !empty($record->file_meta['preprocess']['warnings'] ?? [])), RepeatableEntry::make('file_meta.preprocess.errors') ->label('Előfeldolgozási hibák') ->schema([ TextEntry::make('message')->label('Leírás')->color('danger'), TextEntry::make('severity')->label('Súlyosság')->badge()->color('danger'), ]) ->visible(fn ($record) => !empty($record->file_meta['preprocess']['errors'] ?? [])), ]), ]), ]), ]); } }