netgescon-day0/resources/views/filament/pages/supporto/modifiche.blade.php

492 lines
33 KiB
PHP

<div class="fi-page">
<div class="mx-auto max-w-7xl space-y-3 text-xs">
<x-filament.components.page-breadcrumbs
:breadcrumbs="[
['label' => 'Supporto', 'url' => null],
['label' => 'Modifiche', 'url' => null],
]"
/>
<x-filament::section class="!p-4">
<div class="flex flex-wrap items-start justify-between gap-3">
<div class="space-y-1">
<div class="text-base font-semibold">NetGescon - Modifiche e Aggiornamenti</div>
<div class="text-xs text-gray-600">
Versione corrente: <span class="font-mono font-semibold">{{ $this->currentVersion }}</span>
<span class="ml-2 rounded bg-gray-100 px-1.5 py-0.5 text-[10px] uppercase">fonte {{ $this->versionSource }}</span>
</div>
</div>
<div class="space-y-1 text-xs text-gray-600">
<div class="font-medium text-gray-700">Legenda rapida</div>
<div class="flex flex-wrap gap-3">
<span class="inline-flex items-center gap-2"><span class="inline-block h-2.5 w-2.5 rounded-sm bg-success-500"></span>U utenti finali</span>
<span class="inline-flex items-center gap-2"><span class="inline-block h-2.5 w-2.5 rounded-sm bg-primary-500"></span>P assistenza/sviluppo</span>
<span class="inline-flex items-center gap-2"><span class="inline-block h-2.5 w-2.5 rounded-sm bg-warning-500"></span>E non bloccante</span>
<span class="inline-flex items-center gap-2"><span class="inline-block h-2.5 w-2.5 rounded-sm bg-danger-500"></span>E! bloccante</span>
</div>
</div>
</div>
<div class="mt-3 flex flex-wrap gap-2">
<button
type="button"
wire:click="setActiveTab('errori')"
class="inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium {{ $this->activeTab === 'errori' ? 'bg-slate-800 text-white' : 'bg-slate-100 text-slate-700 hover:bg-slate-200' }}"
>
Errori
</button>
<button
type="button"
wire:click="setActiveTab('commit')"
class="inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium {{ $this->activeTab === 'commit' ? 'bg-slate-800 text-white' : 'bg-slate-100 text-slate-700 hover:bg-slate-200' }}"
>
Commit + Note
</button>
<button
type="button"
wire:click="setActiveTab('migliorie')"
class="inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium {{ $this->activeTab === 'migliorie' ? 'bg-slate-800 text-white' : 'bg-slate-100 text-slate-700 hover:bg-slate-200' }}"
>
Migliorie
</button>
</div>
</x-filament::section>
@if($this->activeTab === 'errori')
<x-filament::section class="!p-4">
<div class="grid gap-3 lg:grid-cols-3">
<div class="rounded-lg border bg-gray-50 p-3 lg:col-span-2">
<div class="mb-2 text-xs font-semibold text-gray-700">Aggiornamento da server distribution</div>
<div class="grid gap-2 sm:grid-cols-3">
<label class="block">
<span class="mb-1 block text-[11px] font-medium">Canale</span>
<select wire:model="updateChannel" class="w-full rounded-md border-gray-300 text-xs">
<option value="free">free</option>
<option value="licensed">licensed</option>
</select>
</label>
<label class="inline-flex items-center gap-2 rounded-md border bg-white px-2 py-1.5 text-[11px]">
<input type="checkbox" wire:model="updateDryRun" class="rounded border-gray-300" />
Dry run
</label>
<label class="inline-flex items-center gap-2 rounded-md border bg-white px-2 py-1.5 text-[11px]">
<input type="checkbox" wire:model="updateForce" class="rounded border-gray-300" />
Force
</label>
</div>
<div class="mt-3 flex flex-wrap gap-2">
<x-filament::button size="sm" wire:click="runUpdate" :disabled="!$this->canRunUpdate()">
Lancia aggiornamento
</x-filament::button>
<x-filament::button size="sm" color="warning" wire:click="runUpdateFallback" :disabled="!$this->canRunUpdate()">
Lancia aggiornamento (riserva)
</x-filament::button>
<x-filament::button size="sm" color="info" wire:click="runUpdateConnectivityCheck">
Check connettivita update
</x-filament::button>
<x-filament::button size="sm" color="gray" wire:click="reloadDashboardData">
Aggiorna dati pagina
</x-filament::button>
<x-filament::button size="sm" color="gray" wire:click="runMaintenanceOptimizeClear" :disabled="!$this->canRunUpdate()">
Pulisci cache remoto
</x-filament::button>
<x-filament::button size="sm" color="gray" wire:click="runMaintenanceViewRebuild" :disabled="!$this->canRunUpdate()">
Ricompila view remoto
</x-filament::button>
<x-filament::button size="sm" color="gray" wire:click="refreshUpdateProgress" :disabled="!$this->updateInProgress">
Aggiorna avanzamento
</x-filament::button>
</div>
@if($this->updateInProgress)
<div class="mt-3 rounded-lg border bg-white p-3" wire:poll.2s="refreshUpdateProgress">
@else
<div class="mt-3 rounded-lg border bg-white p-3">
@endif
<div class="mb-1 flex items-center justify-between text-[11px] text-gray-600">
<span class="font-semibold">Avanzamento aggiornamento</span>
<span class="font-mono">{{ (int) $this->updateProgressPercent }}%</span>
</div>
<div class="h-2 w-full overflow-hidden rounded bg-gray-200">
<div class="h-2 {{ $this->updateProgressStatus === 'failed' ? 'bg-rose-500' : 'bg-emerald-500' }}" style="width: {{ max(0, min(100, (int) $this->updateProgressPercent)) }}%"></div>
</div>
<div class="mt-1 text-[11px] text-gray-600">{{ $this->updateProgressMessage }}</div>
<div class="mt-1 text-[10px] text-gray-500">
Job: <span class="font-mono">{{ $this->updateJobId ?? '-' }}</span>
· Stato: <span class="font-semibold">{{ $this->updateProgressStatus }}</span>
@if($this->updateInProgress)
· in esecuzione
@endif
</div>
</div>
@if(! $this->canRunUpdate())
<div class="mt-2 text-[11px] text-amber-700">Permesso update non disponibile per il tuo ruolo.</div>
@endif
</div>
<div class="rounded-lg border bg-white p-3">
<div class="text-xs font-semibold text-gray-700">Esito ultimo update</div>
<div class="mt-2 space-y-1 text-[11px] text-gray-600">
<div>Ultima esecuzione: <span class="font-medium">{{ $this->lastUpdateAt ?? '-' }}</span></div>
<div>
Exit code:
@if($this->lastUpdateExitCode === null)
<span class="font-medium">-</span>
@elseif($this->lastUpdateExitCode === 0)
<span class="rounded bg-emerald-100 px-1.5 py-0.5 font-semibold text-emerald-800">0 OK</span>
@else
<span class="rounded bg-rose-100 px-1.5 py-0.5 font-semibold text-rose-800">{{ $this->lastUpdateExitCode }} ERRORE</span>
@endif
</div>
@if(filled($this->lastPlannedUpdateSummary))
<div class="rounded bg-slate-50 px-2 py-1 text-[10px] text-slate-600">
Piano usato: {{ $this->lastPlannedUpdateSummary }}
</div>
@endif
</div>
</div>
</div>
<div class="mt-3 grid gap-3 lg:grid-cols-2">
<div class="rounded-lg border bg-white p-3">
<div class="text-xs font-semibold text-gray-700">Ultimo backup pronto per update</div>
@if($this->latestBackupSummary)
<div class="mt-2 space-y-1 text-[11px] text-gray-600">
<div>Snapshot: <span class="font-mono">{{ $this->latestBackupSummary['snapshot_id'] }}</span></div>
<div>Creato: <span class="font-medium">{{ $this->latestBackupSummary['created_at'] }}</span></div>
<div>Copia locale: <span class="font-medium {{ $this->latestBackupSummary['zip_exists'] ? 'text-emerald-700' : 'text-rose-700' }}">{{ $this->latestBackupSummary['zip_exists'] ? 'OK' : 'mancante' }}</span></div>
<div>ZIP: <span class="break-all font-mono">{{ $this->latestBackupSummary['zip_path'] ?: '-' }}</span></div>
<div>Dimensione: <span class="font-medium">{{ $this->latestBackupSummary['zip_size_mb'] !== null ? number_format((float) $this->latestBackupSummary['zip_size_mb'], 2, ',', '.') . ' MB' : '-' }}</span></div>
<div>File copiati: <span class="font-medium">{{ (int) $this->latestBackupSummary['copied_files'] }}</span> · Tabelle indicizzate: <span class="font-medium">{{ (int) $this->latestBackupSummary['tables_count'] }}</span></div>
<div>
Copia Google Drive:
@if(is_array($this->latestBackupSummary['drive'] ?? null))
<span class="font-medium text-emerald-700">OK</span>
@if(!empty($this->latestBackupSummary['drive']['webViewLink']))
<a href="{{ $this->latestBackupSummary['drive']['webViewLink'] }}" target="_blank" class="ml-1 text-primary-600 hover:underline">Apri su Drive</a>
@endif
@else
<span class="font-medium text-rose-700">non disponibile</span>
@endif
</div>
</div>
@else
<div class="mt-2 text-[11px] text-gray-500">Nessun backup pre-update registrato.</div>
@endif
</div>
<div class="rounded-lg border bg-white p-3">
<div class="text-xs font-semibold text-gray-700">Anteprima pacchetto in arrivo</div>
@if($this->lastManifestPreview)
<div class="mt-2 space-y-1 text-[11px] text-gray-600">
<div>Versione remota: <span class="font-semibold">{{ $this->lastManifestPreview['version'] }}</span></div>
<div>Migration richieste: <span class="font-medium {{ $this->lastManifestPreview['migrate_required'] ? 'text-amber-700' : 'text-emerald-700' }}">{{ $this->lastManifestPreview['migrate_required'] ? 'si' : 'no' }}</span></div>
<div>Pacchetto: <span class="break-all font-mono">{{ $this->lastManifestPreview['package_url'] }}</span></div>
<div>SHA256: <span class="break-all font-mono">{{ $this->lastManifestPreview['sha256'] }}</span></div>
@if(filled($this->lastManifestPreview['release_notes'] ?? null))
<div class="rounded bg-slate-50 px-2 py-1 text-[10px] text-slate-700">{{ $this->lastManifestPreview['release_notes'] }}</div>
@endif
@if(!empty($this->lastManifestPreview['security']))
<div class="rounded border border-amber-300 bg-amber-50 px-2 py-1 text-[10px] text-amber-900">
Aggiornamenti sicurezza: {{ is_array($this->lastManifestPreview['security']) ? json_encode($this->lastManifestPreview['security'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : $this->lastManifestPreview['security'] }}
</div>
@endif
</div>
@else
<div class="mt-2 text-[11px] text-gray-500">Esegui “Check connettivita update” per leggere manifest e contenuto dell aggiornamento prima del lancio.</div>
@endif
</div>
</div>
<div class="mt-3 rounded-lg border bg-blue-50 p-3">
<div class="mb-1 text-[11px] font-semibold text-blue-900">Aggiornamenti pianificati (prima del lancio)</div>
<ul class="list-disc space-y-1 pl-4 text-[11px] text-blue-900">
@foreach($this->updatePlannedSteps as $step)
<li>{{ $step }}</li>
@endforeach
</ul>
<div class="mt-3 rounded border border-blue-200 bg-white p-2 text-[11px] text-blue-900">
<div class="font-semibold">Ripristino differenziale disponibile</div>
<div class="mt-1">Ripristino singola scrittura:</div>
<pre class="mt-1 overflow-auto whitespace-pre-wrap rounded bg-slate-950 p-2 text-[10px] text-slate-100">php artisan netgescon:restore-record &lt;tabella&gt; &lt;pk&gt; --apply</pre>
<div class="mt-1">Preview senza scrivere:</div>
<pre class="mt-1 overflow-auto whitespace-pre-wrap rounded bg-slate-950 p-2 text-[10px] text-slate-100">php artisan netgescon:restore-record &lt;tabella&gt; &lt;pk&gt;</pre>
</div>
</div>
@if(filled($this->lastUpdateOutput))
<div class="mt-3 rounded-lg border bg-slate-950 p-3">
<div class="mb-1 text-[11px] font-semibold text-slate-200">Output tecnico</div>
<pre class="max-h-64 overflow-auto whitespace-pre-wrap text-[11px] leading-relaxed text-slate-100">{{ $this->lastUpdateOutput }}</pre>
</div>
@endif
@if(filled($this->lastUpdateIssue))
<div class="mt-3 rounded-lg border border-amber-300 bg-amber-50 p-3 text-[11px] text-amber-900">
<div class="font-semibold">Diagnostica automatica ultimo errore</div>
<div class="mt-1">{{ $this->lastUpdateIssue }}</div>
</div>
@endif
@if(filled($this->lastConnectivityCheckOutput))
<div class="mt-3 rounded-lg border bg-slate-100 p-3">
<div class="mb-1 text-[11px] font-semibold text-slate-700">Output check connettivita endpoint update</div>
<pre class="max-h-52 overflow-auto whitespace-pre-wrap text-[11px] text-slate-700">{{ $this->lastConnectivityCheckOutput }}</pre>
</div>
@endif
</x-filament::section>
<x-filament::section class="!p-4">
<div class="mb-2 text-xs font-semibold text-gray-700">Errori runtime, supporto e pregressi (laravel.log)</div>
<div class="mb-2 text-[11px] text-gray-500">Raccolta unificata da: <code>runtime-errors.ndjson</code>, <code>support-events.ndjson</code>, <code>laravel.log</code>, <code>docs/support/online-runtime-errors.ndjson</code> (feed Git da online).</div>
<div class="mb-2 flex flex-wrap items-center gap-2 text-[11px]">
<span class="rounded bg-rose-100 px-2 py-1 font-semibold text-rose-800">Aperti: {{ (int) $this->openBugCount }}</span>
<span class="rounded bg-emerald-100 px-2 py-1 font-semibold text-emerald-800">Risolti: {{ (int) $this->resolvedBugCount }}</span>
<span class="ml-2 text-gray-500">Filtro:</span>
<button type="button" wire:click="setBugFilterStatus('all')" class="rounded px-2 py-1 {{ $this->bugFilterStatus === 'all' ? 'bg-slate-800 text-white' : 'bg-slate-100 text-slate-700' }}">Tutti</button>
<button type="button" wire:click="setBugFilterStatus('open')" class="rounded px-2 py-1 {{ $this->bugFilterStatus === 'open' ? 'bg-slate-800 text-white' : 'bg-slate-100 text-slate-700' }}">Aperti</button>
<button type="button" wire:click="setBugFilterStatus('resolved')" class="rounded px-2 py-1 {{ $this->bugFilterStatus === 'resolved' ? 'bg-slate-800 text-white' : 'bg-slate-100 text-slate-700' }}">Risolti</button>
</div>
<div class="mb-3 grid gap-3 lg:grid-cols-2">
<div class="rounded-lg border bg-gray-50 p-3">
<div class="mb-2 text-[11px] font-semibold text-gray-700">Aggiungi BUG manuale</div>
<label class="mb-2 block">
<span class="mb-1 block text-[11px] font-medium">Titolo</span>
<input type="text" wire:model.defer="manualBugTitle" class="w-full rounded-md border-gray-300 text-xs" placeholder="Es: Duplicati ricerca rubrica universale" />
</label>
<label class="block">
<span class="mb-1 block text-[11px] font-medium">Dettagli</span>
<textarea wire:model.defer="manualBugDetails" rows="3" class="w-full rounded-md border-gray-300 text-xs" placeholder="URL, cosa succede, risultato atteso, eventuale stabile/codice"></textarea>
</label>
<div class="mt-2">
<x-filament::button size="sm" wire:click="createManualBug">Crea BUG manuale</x-filament::button>
</div>
</div>
<div class="rounded-lg border bg-gray-50 p-3">
<div class="mb-2 text-[11px] font-semibold text-gray-700">Nota risoluzione BUG</div>
<div class="mb-2 text-[11px] text-gray-500">
BUG selezionato: <span class="font-mono font-semibold">{{ $this->selectedBugFingerprint ? 'selezionato' : 'nessuno' }}</span>
</div>
<label class="block">
<span class="mb-1 block text-[11px] font-medium">Nota</span>
<textarea wire:model.defer="bugResolutionNote" rows="4" class="w-full rounded-md border-gray-300 text-xs" placeholder="Es: risolto con fix parser X, migration Y, deploy Z"></textarea>
</label>
<div class="mt-2">
<x-filament::button size="sm" color="primary" wire:click="saveBugResolutionNote">Salva nota risoluzione</x-filament::button>
</div>
</div>
</div>
<div class="overflow-x-auto">
<table class="min-w-full border-collapse border text-[11px]">
<thead>
<tr class="bg-slate-100 text-slate-700">
<th class="border px-2 py-1.5 text-left">BUG #</th>
<th class="border px-2 py-1.5 text-left">Stato</th>
<th class="border px-2 py-1.5 text-left">Timestamp</th>
<th class="border px-2 py-1.5 text-left">Origine</th>
<th class="border px-2 py-1.5 text-left">Tipo</th>
<th class="border px-2 py-1.5 text-left">Occorrenze</th>
<th class="border px-2 py-1.5 text-left">Messaggio</th>
<th class="border px-2 py-1.5 text-left">Contesto</th>
<th class="border px-2 py-1.5 text-left">Nota risoluzione</th>
<th class="border px-2 py-1.5 text-left">Azioni</th>
</tr>
</thead>
<tbody>
@forelse($this->runtimeErrors as $row)
<tr class="hover:bg-slate-50">
<td class="border px-2 py-1.5 font-mono font-semibold">{{ $row['bug_code'] }}</td>
<td class="border px-2 py-1.5">
@if(($row['bug_status'] ?? 'open') === 'resolved')
<span class="rounded bg-emerald-100 px-1.5 py-0.5 font-semibold text-emerald-800">risolto</span>
@else
<span class="rounded bg-rose-100 px-1.5 py-0.5 font-semibold text-rose-800">aperto</span>
@endif
</td>
<td class="border px-2 py-1.5 whitespace-nowrap">{{ $row['timestamp'] }}</td>
<td class="border px-2 py-1.5">{{ $row['source'] ?? '-' }}</td>
<td class="border px-2 py-1.5">{{ $row['type'] }}</td>
<td class="border px-2 py-1.5">{{ (int) ($row['occurrences'] ?? 1) }}</td>
<td class="border px-2 py-1.5">{{ $row['message'] }}</td>
<td class="border px-2 py-1.5">
<div class="max-w-[420px] break-words text-[10px] text-gray-700">{{ $row['context'] !== '' ? \Illuminate\Support\Str::limit($row['context'], 220) : '-' }}</div>
</td>
<td class="border px-2 py-1.5">
<div class="max-w-[260px] break-words text-[10px] text-gray-700">{{ $row['resolution_note'] !== '' ? \Illuminate\Support\Str::limit($row['resolution_note'], 160) : '-' }}</div>
@if(($row['bug_status'] ?? 'open') === 'resolved' && filled($row['resolved_at']))
<div class="mt-1 text-[10px] text-emerald-700">risolto: {{ $row['resolved_at'] }}</div>
@endif
</td>
<td class="border px-2 py-1.5">
<x-filament::button size="xs" color="gray" type="button" wire:click="selectBugForResolution('{{ $row['fingerprint'] }}')">Nota</x-filament::button>
@if(($row['bug_status'] ?? 'open') === 'resolved')
<x-filament::button size="xs" color="warning" type="button" wire:click="reopenBug('{{ $row['fingerprint'] }}')">Riapri</x-filament::button>
@else
<x-filament::button size="xs" color="success" type="button" wire:click="markBugResolved('{{ $row['fingerprint'] }}')">Segna risolto</x-filament::button>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="10" class="border px-2 py-3 text-center text-gray-500">Nessun errore registrato negli ultimi eventi.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</x-filament::section>
@endif
@if($this->activeTab === 'commit')
<x-filament::section class="!p-4">
<div class="mb-2 text-xs font-semibold text-gray-700">Ultimi commit (descrizioni)</div>
<div class="mb-3 rounded-lg border bg-gray-50 p-3">
<div class="mb-2 text-[11px] font-semibold text-gray-700">Aggiungi nota operativa a un commit</div>
<div class="grid gap-2 sm:grid-cols-2">
<label class="block">
<span class="mb-1 block text-[11px] font-medium">Commit</span>
<select wire:model="selectedCommitHash" wire:change="onSelectedCommitHashUpdated" class="w-full rounded-md border-gray-300 text-xs">
<option value="">Seleziona commit</option>
@foreach($this->latestCommits as $c)
<option value="{{ $c['hash'] }}">{{ $c['short_hash'] }} - {{ $c['message'] }}</option>
@endforeach
</select>
</label>
<label class="block sm:col-span-2">
<span class="mb-1 block text-[11px] font-medium">Nota aggiuntiva</span>
<textarea wire:model.defer="newCommitNote" rows="3" class="w-full rounded-md border-gray-300 text-xs" placeholder="Es: Fix runtime error page X, aggiunta diagnostica update timeout, ecc."></textarea>
</label>
</div>
<div class="mt-2">
<x-filament::button size="sm" wire:click="saveCommitNote">Salva nota commit</x-filament::button>
</div>
</div>
<div class="overflow-x-auto">
<table class="min-w-full border-collapse border text-[11px]">
<thead>
<tr class="bg-slate-100 text-slate-700">
<th class="border px-2 py-1.5 text-left">Data</th>
<th class="border px-2 py-1.5 text-left">Commit</th>
<th class="border px-2 py-1.5 text-left">Autore</th>
<th class="border px-2 py-1.5 text-left">Descrizione</th>
<th class="border px-2 py-1.5 text-left">Nota aggiuntiva</th>
</tr>
</thead>
<tbody>
@forelse($this->latestCommits as $commit)
<tr class="hover:bg-slate-50">
<td class="border px-2 py-1.5 whitespace-nowrap">{{ $commit['date'] }}</td>
<td class="border px-2 py-1.5 font-mono">{{ $commit['short_hash'] }}</td>
<td class="border px-2 py-1.5">{{ $commit['author'] }}</td>
<td class="border px-2 py-1.5">{{ $commit['message'] }}</td>
<td class="border px-2 py-1.5">
@php
$note = $this->getCommitNote($commit['hash']);
@endphp
<div class="max-w-[380px] break-words text-[11px] {{ $note !== '' ? 'text-slate-800' : 'text-gray-400' }}">{{ $note !== '' ? $note : '-' }}</div>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="border px-2 py-3 text-center text-gray-500">Nessun commit disponibile.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</x-filament::section>
@endif
@php
$path = base_path('docs/NETGESCON-MODIFICHE.md');
$raw = file_exists($path) ? file_get_contents($path) : "# Modifiche\n\nFile non trovato: {$path}\n";
$gitPath = base_path('docs/NETGESCON-GIT-AUTOCHANGELOG.md');
$gitRaw = file_exists($gitPath) ? file_get_contents($gitPath) : "# Git Auto Changelog\n\nFile non trovato: {$gitPath}\nEsegui: `bash scripts/ops/netgescon-sync-git-changelog.sh`\n";
// Mini-render: sostituisce tag tipo [U], [P], [E], [E!] con un quadratino colorato.
$replacements = [
'[E!]' => '<span class="inline-flex items-center gap-2"><span class="inline-block h-3 w-3 rounded-sm bg-danger-500"></span><span class="font-mono">E!</span></span>',
'[U]' => '<span class="inline-flex items-center gap-2"><span class="inline-block h-3 w-3 rounded-sm bg-success-500"></span><span class="font-mono">U</span></span>',
'[P]' => '<span class="inline-flex items-center gap-2"><span class="inline-block h-3 w-3 rounded-sm bg-primary-500"></span><span class="font-mono">P</span></span>',
'[E]' => '<span class="inline-flex items-center gap-2"><span class="inline-block h-3 w-3 rounded-sm bg-warning-500"></span><span class="font-mono">E</span></span>',
];
$rawHtml = \Illuminate\Support\Str::markdown($raw);
$rawHtml = str_replace(array_keys($replacements), array_values($replacements), $rawHtml);
$gitRawHtml = \Illuminate\Support\Str::markdown($gitRaw);
$gitRawHtml = str_replace(array_keys($replacements), array_values($replacements), $gitRawHtml);
@endphp
@if($this->activeTab === 'migliorie')
<x-filament::section class="!p-4">
<div class="mb-2 text-xs font-semibold text-gray-700">Pagine nuove o rese piu funzionali (ultimi commit)</div>
<div class="overflow-x-auto">
<table class="min-w-full border-collapse border text-[11px]">
<thead>
<tr class="bg-slate-100 text-slate-700">
<th class="border px-2 py-1.5 text-left">Pagina</th>
<th class="border px-2 py-1.5 text-left">Percorso</th>
<th class="border px-2 py-1.5 text-left">Commit</th>
<th class="border px-2 py-1.5 text-left">Descrizione</th>
</tr>
</thead>
<tbody>
@forelse($this->recentFilamentPages as $row)
<tr class="hover:bg-slate-50">
<td class="border px-2 py-1.5 font-medium">{{ $row['page'] }}</td>
<td class="border px-2 py-1.5 font-mono text-[10px]">{{ $row['path'] }}</td>
<td class="border px-2 py-1.5 font-mono">{{ $row['commit'] }}</td>
<td class="border px-2 py-1.5">{{ $row['message'] }}</td>
</tr>
@empty
<tr>
<td colspan="4" class="border px-2 py-3 text-center text-gray-500">Nessuna pagina recente rilevata dai commit.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</x-filament::section>
<x-filament::section class="!p-4">
<div class="mb-2 text-xs font-semibold text-gray-700">Migliorie e funzionalita aggiunte (estratte dal registro)</div>
<div class="rounded-lg border bg-gray-50 p-3">
<ul class="list-disc space-y-1 pl-4 text-[11px] text-gray-700">
@forelse($this->functionalHighlights as $item)
<li>{{ $item }}</li>
@empty
<li>Nessuna miglioria rilevata automaticamente nel file modifiche.</li>
@endforelse
</ul>
</div>
</x-filament::section>
<x-filament::section class="!p-4">
<div class="mb-2 text-xs font-semibold text-gray-700">Registro funzionale (manuale)</div>
<div class="prose prose-sm max-w-none text-[11px] leading-relaxed">
{!! $rawHtml !!}
</div>
</x-filament::section>
<x-filament::section class="!p-4">
<div class="mb-2 text-xs font-semibold text-gray-700">Changelog automatico da script</div>
<div class="prose prose-sm max-w-none text-[11px] leading-relaxed">
{!! $gitRawHtml !!}
</div>
</x-filament::section>
@endif
</div>
</div>