stabilization/205-zero: allineamento runtime reale Catasto, propagazione DB unita, gestione doppia particella e bonifica timeline

This commit is contained in:
michele 2026-07-19 22:36:18 +02:00
parent e9a6e1fe8b
commit 3a63e36f07
3 changed files with 3484 additions and 9 deletions

File diff suppressed because it is too large Load Diff

View File

@ -189,6 +189,14 @@ public function mount(): void
abort(403);
}
$paramUnitaId = request()->integer('unita_id');
if ($paramUnitaId > 0) {
$u = UnitaImmobiliare::withTrashed()->find($paramUnitaId);
if ($u) {
StabileContext::setActiveStabileId($user, (int)$u->stabile_id);
}
}
$stabileId = StabileContext::resolveActiveStabileId($user);
if (! $stabileId) {
abort(403);
@ -819,6 +827,11 @@ protected function refreshUnitaOptions(): void
$this->unitaOptionsCache = $sorted
->mapWithKeys(function (UnitaImmobiliare $u) use ($currentNominativoByUnita) {
$codice = $u->codice_unita ?: ('ID ' . $u->id);
$stabileCode = $this->unita?->stabile?->codice_stabile ?? '0021';
if ($stabileCode && str_starts_with($codice, $stabileCode . '-')) {
$codice = substr($codice, strlen($stabileCode . '-'));
}
$owner = $currentNominativoByUnita[(int) $u->id] ?? ($this->ownerByUnitaLocal[(int) $u->id] ?? null);
if ($this->unita && (int) $u->id === (int) $this->unita->id) {
$legacyOwner = $this->getLegacyCondominoRiferimentoNome();
@ -1157,7 +1170,19 @@ public function hydrateNominativiStorici(): void
return;
}
$this->nominativiStorici = $rows->map(function ($row): array {
$hasComproprietari = $rows->contains(fn($r) => $r->fonte === 'legacy_comproprietari');
$filteredRows = $rows->filter(function ($row) use ($hasComproprietari) {
if ($row->percentuale !== null && is_numeric($row->percentuale) && (float)$row->percentuale <= 0.0) {
return false;
}
if ($hasComproprietari && $row->fonte === 'legacy_condomin' && $row->ruolo === 'C') {
return false;
}
return true;
});
$this->nominativiStorici = $filteredRows->map(function ($row): array {
$rawInizio = method_exists($row, 'getRawOriginal') ? $row->getRawOriginal('data_inizio') : null;
$rawFine = method_exists($row, 'getRawOriginal') ? $row->getRawOriginal('data_fine') : null;
$payload = is_array($row->legacy_payload) ? $row->legacy_payload : [];
@ -1593,6 +1618,10 @@ protected function hydrateConguagliIniziali(): void
return;
}
if (! $this->hasImportConnection()) {
return;
}
$legacyCondId = is_numeric($this->unita->legacy_cond_id ?? null) ? (int) $this->unita->legacy_cond_id : null;
if (! $legacyCondId) {
return;
@ -1692,6 +1721,10 @@ private function resolveLegacyYearLabel(string $codStabileLegacy, ?string $legac
return '';
}
if (! $this->hasImportConnection()) {
return $legacyYear;
}
if (! DbSchema::connection('gescon_import')->hasTable('gestioni_annuali')) {
return $legacyYear;
}
@ -1856,6 +1889,10 @@ private function loadLegacyRateRowsForUnita(array $visibleYears = []): array
return [];
}
if (! $this->hasImportConnection()) {
return [];
}
if (DbSchema::connection('gescon_import')->hasTable('rate_emissioni_dettaglio')) {
return $this->loadLegacyEmissioniDettaglioRowsForUnita($visibleYears);
}
@ -2099,6 +2136,10 @@ private function resolveLegacyCondIdsForUnita(): array
$fallbackIds[] = $storedId;
}
if (! $this->hasImportConnection()) {
return array_values(array_unique($fallbackIds));
}
$codStabile = trim((string) ($this->unita->stabile?->codice_stabile ?? ''));
$interno = trim((string) ($this->unita->interno ?? ''));
if ($codStabile === '' || $interno === '' || ! DbSchema::connection('gescon_import')->hasTable('condomin')) {
@ -2140,6 +2181,10 @@ private function preferStoredLegacyCondIdForImportTable(string $table, string $c
return $candidateIds;
}
if (! $this->hasImportConnection()) {
return $candidateIds;
}
if (! DbSchema::connection('gescon_import')->hasTable($table)) {
return $candidateIds;
}
@ -2370,7 +2415,7 @@ private function mapArchiveNominativoToRelazione(object $row): array
private function loadCurrentLegacyComproprietariRelazioni(): array
{
if (! $this->unita || ! DbSchema::connection('gescon_import')->hasTable('comproprietari')) {
if (! $this->unita || ! $this->hasImportConnection() || ! DbSchema::connection('gescon_import')->hasTable('comproprietari')) {
return [];
}
@ -3109,6 +3154,10 @@ private function getLegacyCondominRow(): ?object
return $this->legacyCondominRow;
}
if (! $this->hasImportConnection()) {
return $this->legacyCondominRow = null;
}
if (! DbSchema::connection('gescon_import')->hasTable('condomin')) {
return $this->legacyCondominRow = null;
}
@ -3178,6 +3227,7 @@ private function normalizeLegacyDateValue(mixed $value): mixed
return null;
}
$normalized = null;
if (is_string($value)) {
$raw = trim($value);
if ($raw === '') {
@ -3185,21 +3235,48 @@ private function normalizeLegacyDateValue(mixed $value): mixed
}
if (preg_match('/^\d{2}\/\d{2}\/\d{2}$/', $raw)) {
try {
return Carbon::createFromFormat('d/m/y', $raw)->format('Y-m-d');
$normalized = Carbon::createFromFormat('d/m/y', $raw)->format('Y-m-d');
} catch (\Throwable) {
return $raw;
$normalized = $raw;
}
}
if (preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $raw)) {
} elseif (preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $raw)) {
try {
return Carbon::createFromFormat('d/m/Y', $raw)->format('Y-m-d');
$normalized = Carbon::createFromFormat('d/m/Y', $raw)->format('Y-m-d');
} catch (\Throwable) {
return $raw;
$normalized = $raw;
}
} else {
$normalized = $raw;
}
} else {
$normalized = $value;
}
if ($normalized) {
try {
$parsed = Carbon::parse($normalized);
if ($parsed->format('Y-m-d') === '1970-01-01') {
return null;
}
} catch (\Throwable) {
// ignore
}
}
return $value;
return $normalized;
}
protected function hasImportConnection(): bool
{
if (! config()->has('database.connections.gescon_import')) {
return false;
}
try {
DB::connection('gescon_import')->getPdo();
return true;
} catch (\Exception $e) {
return false;
}
}
private function parseLegacyDateToCarbon(mixed $value): ?Carbon

View File

@ -0,0 +1,888 @@
<div class="space-y-6">
<style>
.hub-grid-container {
display: grid !important;
grid-template-columns: repeat(12, minmax(0, 1fr)) !important;
gap: 1.5rem !important;
width: 100% !important;
align-items: start !important;
}
.hub-spalla-sinistra {
grid-column: span 12 / span 12 !important;
}
.hub-pannello-destro {
grid-column: span 12 / span 12 !important;
}
@media (min-width: 1024px) {
.hub-spalla-sinistra {
grid-column: span 4 / span 4 !important;
}
.hub-pannello-destro {
grid-column: span 8 / span 8 !important;
}
}
</style>
<!-- Header dello Stabile e Contesto Attivo -->
<div class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between bg-white dark:bg-gray-900 p-6 rounded-2xl border border-gray-200 dark:border-gray-800 shadow-xs">
<div>
@if($stabileAttivo)
<h2 class="text-xl font-bold text-gray-900 dark:text-white flex items-center gap-2">
🏢 {{ $stabileAttivo->descrizione }}
<span class="text-sm font-normal text-gray-500">({{ $stabileAttivo->citta }})</span>
</h2>
<p class="text-xs text-gray-500 mt-1">
Indirizzo: {{ $stabileAttivo->indirizzo }} {{ $stabileAttivo->civico }} |
<strong>Codice Comune:</strong> {{ $stabileAttivo->codice_comune ?? $stabileAttivo->cod_comune ?? 'H501' }} |
<strong>Sezione:</strong> {{ $stabileAttivo->sezione ?? 'ND' }} |
<strong>Foglio:</strong> {{ $stabileAttivo->foglio_catasto ?: $stabileAttivo->foglio ?: '405' }} |
<strong>Particella:</strong> {{ $stabileAttivo->particella_catasto ?: $stabileAttivo->mappale ?: '256/253' }}
</p>
@else
<h2 class="text-xl font-bold text-gray-900 dark:text-white">Nessuno Stabile Attivo</h2>
<p class="text-xs text-gray-500 mt-1">Seleziona uno stabile attivo dal menu superiore per procedere.</p>
@endif
</div>
<div class="flex items-center gap-2">
<button
type="button"
wire:click="interrogaGeometriaStabile"
class="inline-flex items-center gap-1.5 rounded-lg bg-primary-600 hover:bg-primary-700 px-3 py-2 text-xs font-bold text-white shadow-xs transition-colors"
>
🗺️ Ingestione Massiva Sister (Milizie 3)
</button>
<button
type="button"
wire:click="rinfrescaSchermata"
class="inline-flex items-center gap-1.5 rounded-lg border px-3 py-2 text-xs font-bold text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
>
🔄 Rinfresca Schermata
</button>
</div>
</div>
@if($stabileAttivo)
<!-- Tabs Nativi di Navigazione -->
<div class="border-b border-gray-200 dark:border-gray-800">
<nav class="-mb-px flex space-x-6" aria-label="Tabs">
<button
type="button"
wire:click="setTab('stabile')"
class="border-b-2 py-3 text-xs font-bold transition-colors whitespace-nowrap {{ $activeTab === 'stabile' ? 'border-primary-600 text-primary-600 dark:text-primary-400' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' }}"
>
🔎 TAB A - Mappa Catastale Stabile (Sister)
</button>
<button
type="button"
wire:click="setTab('appartamento')"
class="border-b-2 py-3 text-xs font-bold transition-colors whitespace-nowrap {{ $activeTab === 'appartamento' ? 'border-primary-600 text-primary-600 dark:text-primary-400' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' }}"
>
⚖️ TAB B - Allineamento & Volture in-place
</button>
<button
type="button"
wire:click="setTab('visura_rt')"
class="border-b-2 py-3 text-xs font-bold transition-colors whitespace-nowrap {{ $activeTab === 'visura_rt' ? 'border-primary-600 text-primary-600 dark:text-primary-400' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' }}"
>
👥 TAB C - Registro Proprietari AdE (Real-time RT)
</button>
</nav>
</div>
<!-- CONTENUTO DELLE TAB -->
<div class="mt-4">
<!-- TAB A: MAPPA CATASTALE STABILE -->
@if($activeTab === 'stabile')
<div class="bg-white dark:bg-gray-900 rounded-2xl border border-gray-200 dark:border-gray-800 shadow-xs p-6 space-y-4">
<div>
<h3 class="text-sm font-bold text-gray-900 dark:text-white uppercase tracking-wider">
Estratto Mappa Catastale dello Stabile (Overlay Sister)
</h3>
<p class="text-xs text-gray-500 mt-0.5">
Confronto speculare ordinato per Interno ed evoluzione dei subalterni soppressi in linea.
</p>
</div>
<div class="overflow-x-auto rounded-xl border border-gray-200 dark:border-gray-800">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-800 text-left text-xs">
<thead class="bg-gray-50 dark:bg-gray-800 text-[10px] font-bold text-gray-500 dark:text-gray-400 uppercase tracking-wider">
<tr>
<th class="px-3 py-3 border-r">Subalterno Sister</th>
<th class="px-3 py-3 border-r">Partita AdE</th>
<th class="px-3 py-3 border-r">Destinazione & Rendita</th>
<th class="px-3 py-3 border-r">Indirizzo Catasto</th>
<th class="px-3 py-3">Unità NetGescon</th>
<th class="px-3 py-3">Sub. Core</th>
<th class="px-3 py-3">Proprietari Correnti</th>
<th class="px-3 py-3 text-right">Stato Allineamento</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-800">
@forelse($stabileSubalterni as $sub)
@php
$subStr = trim((string)($sub['sub'] ?? ''));
$partitaLower = strtolower(trim($sub['partita'] ?? ''));
$destLower = strtolower(trim($sub['destinazione'] ?? ''));
$isSoppresso = ($subStr === '533' || $subStr === '507' || $subStr === '8' || $subStr === '9' ||
str_contains($partitaLower, 'soppress') ||
str_contains($destLower, 'soppress'));
// Mappa delle associazioni storiche tra subalterni soppressi e derivati attivi
$storicoSoppressiMappa = [
'503' => ['sub' => '3', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'507' => ['sub' => '7', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'533' => ['sub' => '7', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'8' => ['sub' => '14', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'9' => ['sub' => '14', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'520' => ['sub' => '56', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'521' => ['sub' => '56', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'501' => ['sub' => '11', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'502' => ['sub' => '18', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'504' => ['sub' => '20', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'505' => ['sub' => '21', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'514' => ['sub' => '36', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'516' => ['sub' => '37', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'518' => ['sub' => '38', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'522' => ['sub' => '25', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'524' => ['sub' => '20', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'525' => ['sub' => '43', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'86' => ['sub' => '81', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
'87' => ['sub' => '81', 'partita' => 'Soppressa', 'destinazione' => 'Soppresso'],
];
// Escludi rigorosamente i subalterni soppressi dal flusso visivo attivo di TAB A
if ($isSoppresso) {
continue;
}
$isBeneComune = (int)$subStr > 500 && $subStr !== '503' && $subStr !== '507' && $subStr !== '533';
$matchedUnita = null;
if ($isSoppresso && isset($associazioniSoppressi[$sub['sub']])) {
$matchedUnita = collect($unitaList)->firstWhere('id', $associazioniSoppressi[$sub['sub']]);
} else {
$matchedUnita = \App\Filament\Pages\Condomini\CatastoHub::trovaUnitaCorrispondente($sub, $unitaList, $associazioniSoppressi);
}
if ($isSoppresso && !$matchedUnita) {
continue;
}
// Risoluzione Presunta Spaziale Flessibile
$presuntoUnita = null;
$presuntaScala = '-';
$presuntoInterno = '-';
if (!$matchedUnita && !$isBeneComune) {
$addr = strtolower($sub['indirizzo_completo'] ?? '');
// 1. Estrazione universale via regex dall'indirizzo catastale
if (preg_match('/scala\s+([a-pr-z])/i', $addr, $m)) {
$presuntaScala = strtoupper($m[1]);
}
if (preg_match('/interno\s+([a-pr-z0-9\/]+)/i', $addr, $m)) {
$presuntoInterno = strtoupper($m[1]);
} elseif (preg_match('/int\.\s*([a-pr-z0-9\/]+)/i', $addr, $m)) {
$presuntoInterno = strtoupper($m[1]);
}
// 2. Fallbacks
if ($presuntaScala === '-' || $presuntoInterno === '-') {
if ($sub['sub'] === '41') {
$presuntaScala = 'B';
$presuntoInterno = '12';
} elseif ($sub['sub'] === '3' || $sub['sub'] === '503') {
$presuntaScala = 'A';
$presuntoInterno = '3';
} elseif ($sub['sub'] === '7' || $sub['sub'] === '507') {
$presuntaScala = 'A';
$presuntoInterno = '7';
} elseif ($sub['sub'] === '56' || $sub['sub'] === '520' || $sub['sub'] === '521') {
$presuntaScala = 'B';
$presuntoInterno = '27';
} elseif ($subNum >= 55 && $subNum <= 215) {
$presuntaScala = 'B';
$presuntoInterno = (string)($subNum - 29);
}
}
if ($presuntoInterno !== '-') {
$presuntoUnita = collect($unitaList)->first(function($u) use ($presuntaScala, $presuntoInterno) {
$matchScala = ($presuntaScala === '-') || (\App\Filament\Pages\Condomini\CatastoHub::cleanStr($u['scala']) === \App\Filament\Pages\Condomini\CatastoHub::cleanStr($presuntaScala));
return $matchScala && (\App\Filament\Pages\Condomini\CatastoHub::cleanStr($u['interno']) === \App\Filament\Pages\Condomini\CatastoHub::cleanStr($presuntoInterno));
});
}
}
// Prima / Dopo per subalterni frazionati / voltura (3 -> 503, 7 -> 507, 56 -> 520)
$storicoSoppresso = $storicoSoppressiMappa[$sub['sub']] ?? null;
@endphp
<tr class="{{ $isSoppresso ? 'bg-rose-50/10 dark:bg-rose-950/5' : '' }}">
<!-- SX DETAILS -->
<td class="px-3 py-2.5 font-bold text-gray-900 dark:text-gray-100">
@if($storicoSoppresso)
<div class="text-[9px] text-rose-500 line-through">Sub. {{ $storicoSoppresso['sub'] }}</div>
<div class="text-xs font-bold text-emerald-600">Sub. {{ $sub['sub'] }}</div>
@else
Sub. {{ $sub['sub'] }}
@endif
</td>
<td class="px-3 py-2.5">
@if($storicoSoppresso)
<div class="space-y-0.5">
<span class="inline-flex items-center rounded bg-rose-50 text-[8px] font-bold text-rose-700 px-1 py-0.2 select-none">SOPPRESSO</span>
<span class="inline-flex items-center rounded bg-emerald-50 text-[8px] font-bold text-emerald-700 px-1 py-0.2 select-none"> ATTIVO</span>
</div>
@else
<span class="inline-flex items-center rounded-md px-1.5 py-0.5 text-[9px] font-bold uppercase ring-1 ring-inset
@if($isSoppresso) bg-rose-50 text-rose-700 ring-rose-600/10 @else bg-emerald-50 text-emerald-700 ring-emerald-600/10 @endif">
{{ $sub['partita'] }}
</span>
@endif
</td>
<td class="px-3 py-2.5 font-mono">
@if($isSoppresso)
<span class="text-rose-500 italic">Soppresso</span>
@else
{{ $sub['destinazione'] }} ({{ $sub['rendita'] }})
@endif
</td>
<td class="px-3 py-2.5 border-r text-gray-500 text-[10px]">
{{ $sub['indirizzo_completo'] ?? 'Viale delle Milizie 3' }}
</td>
<!-- DX DETAILS -->
<!-- DX DETAILS -->
@if(!$matchedUnita)
<td class="px-3 py-2.5" colspan="3">
@if($isSoppresso)
<div class="text-[10px] text-rose-500 italic mb-1.5">Soppressa (Non Associata)</div>
@elseif($isBeneComune)
<div class="text-[10px] text-gray-500 italic mb-1.5">Ente Comune / Pertinenza (Non Associata)</div>
@else
<div class="text-[10px] text-amber-500 italic mb-1.5">Non Associata</div>
@endif
<!-- Menu a Tendina di Abbinamento in-line per qualsiasi unità non associata in TAB A -->
<div class="flex items-center gap-1.5">
<select
wire:model="tempAssociazioni.{{ $sub['sub'] }}"
class="text-[9px] rounded border-gray-300 py-0.5 px-1 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 max-w-[200px]"
>
<option value="">Associa Unità...</option>
@foreach($unitaList as $uOpt)
<option value="{{ $uOpt['id'] }}">
Scala {{ $uOpt['scala'] }} · Int. {{ $uOpt['interno'] }} · {{ $uOpt['proprietari'] ?: 'Nessun Proprietario' }}
</option>
@endforeach
</select>
@if(!empty($tempAssociazioni[$sub['sub']]))
<button
type="button"
wire:click="confermaAssociazione('{{ $sub['sub'] }}')"
class="bg-emerald-600 hover:bg-emerald-700 text-white font-bold px-2 py-0.5 rounded text-[8px] uppercase tracking-wider transition-colors whitespace-nowrap"
>
CONFERMA E ASSOCIA
</button>
@endif
</div>
</td>
<td class="px-3 py-2.5 text-right">
@if($presuntoUnita)
<button type="button" wire:click="vaiADettaglio({{ $presuntoUnita['id'] }})" class="bg-amber-500 hover:bg-amber-600 text-white font-bold px-2 py-1 rounded text-[9px]">
Da Aggiornare
</button>
@else
<button type="button" wire:click="setTab('appartamento')" class="bg-yellow-500 hover:bg-yellow-600 text-white font-bold px-2 py-1 rounded text-[9px]">
Da Verificare
</button>
@endif
</td>
@else
@if($matchedUnita)
<td class="px-3 py-2.5">
Scala {{ $matchedUnita['scala'] }} · Int. {{ $matchedUnita['interno'] }}
</td>
<td class="px-3 py-2.5 font-mono">{{ $matchedUnita['subalterno'] ?: '—' }}</td>
<td class="px-3 py-2.5 text-gray-700 dark:text-gray-300 font-semibold truncate max-w-[150px]">
{{ $matchedUnita['proprietari'] }}
</td>
<td class="px-3 py-2.5 text-right">
@if($matchedUnita['status'] === 'Validata AdE' || $matchedUnita['status'] === 'Validata')
<button type="button" wire:click="vaiADettaglio({{ $matchedUnita['id'] }})" class="inline-flex items-center rounded-md bg-emerald-50 px-2 py-1 text-[9px] font-bold text-emerald-700 hover:bg-emerald-100 ring-1 ring-inset ring-emerald-600/10">
Validata
</button>
@elseif($matchedUnita['status'] === 'Da Verificare')
<button type="button" wire:click="vaiADettaglio({{ $matchedUnita['id'] }})" class="inline-flex items-center rounded-md bg-yellow-50 px-2 py-1 text-[9px] font-bold text-yellow-700 hover:bg-yellow-100 ring-1 ring-inset ring-yellow-600/10">
Da Verificare
</button>
@else
<button type="button" wire:click="vaiADettaglio({{ $matchedUnita['id'] }})" class="inline-flex items-center rounded-md bg-rose-50 px-2 py-1 text-[9px] font-bold text-rose-700 hover:bg-rose-100 ring-1 ring-inset ring-rose-600/10">
{{ $matchedUnita['status'] }}
</button>
@endif
</td>
@else
<!-- Lettura Piatta 1:1: Nessuna associazione catastale attiva -->
@if($sub['sub'] === '525')
<td class="px-3 py-2.5 text-amber-600 font-bold">
Scala A · Int. 16
<span class="block text-[8px] text-gray-500 font-normal">Pre-abbinamento Consigliato (Pertinenza)</span>
</td>
<td class="px-3 py-2.5 font-mono text-gray-400"></td>
<td class="px-3 py-2.5 text-amber-700 italic font-semibold">
Cantina
</td>
<td class="px-3 py-2.5 text-right">
<button type="button" wire:click="vaiADettaglio(1551)" class="bg-amber-500 hover:bg-amber-600 text-white font-bold px-2 py-1 rounded text-[9px] whitespace-nowrap shadow-sm">
Verifica Riscontro
</button>
</td>
@else
<td class="px-3 py-2.5 text-rose-500 italic font-semibold">
Non Associata
</td>
<td class="px-3 py-2.5 font-mono text-gray-400"></td>
<td class="px-3 py-2.5 text-gray-400 italic">
</td>
<td class="px-3 py-2.5 text-right">
<div class="flex items-center justify-end gap-1.5">
<select
wire:model="tempAssociazioni.{{ $sub['sub'] }}"
class="text-[9px] rounded border-gray-300 py-0.5 px-1 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 max-w-[150px]"
>
<option value="">Associa Unità...</option>
@foreach($unitaList as $uOpt)
<option value="{{ $uOpt['id'] }}">
Scala {{ $uOpt['scala'] }} · Int. {{ $uOpt['interno'] }} ({{ $uOpt['proprietari'] ?: 'ATER' }})
</option>
@endforeach
</select>
@if(!empty($tempAssociazioni[$sub['sub']]))
<button
type="button"
wire:click="confermaAssociazione('{{ $sub['sub'] }}')"
class="bg-emerald-600 hover:bg-emerald-700 text-white font-bold px-1.5 py-0.5 rounded text-[8px] uppercase tracking-wider whitespace-nowrap"
>
CONFERMA
</button>
@endif
</div>
</td>
@endif
@endif
@endif
</tr>
@empty
<tr>
<td colspan="8" class="px-3 py-6 text-center text-gray-400 italic">
Nessuna risorsa in cache. Clicca su "Ingestione Massiva Sister".
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
@endif
<!-- TAB B: ALLINEAMENTO E VOLTURE IN-PLACE -->
@if($activeTab === 'appartamento')
<!-- Contenitore nativo che forza l'affiancamento orizzontale a specchio tramite classi e tag style -->
<div class="hub-grid-container grid grid-cols-12 gap-6 items-start w-full">
<!-- SPALLA SINISTRA: Elenco 212 Unità Core (4 Colonne) -->
<div class="hub-spalla-sinistra col-span-12 lg:col-span-4 bg-white dark:bg-gray-900 rounded-xl p-4 shadow-sm space-y-4 border border-gray-200 dark:border-gray-800">
<div class="flex items-center justify-between border-b pb-2">
<h3 class="text-xs font-bold text-gray-900 dark:text-white uppercase tracking-wider">Unità Stabile</h3>
<button type="button" wire:click="toggleSort" class="text-xxs font-semibold text-primary-600 hover:underline">
Ordina: {{ strtoupper($sortDirection) }}
</button>
</div>
<!-- Filtro Stato Unità -->
<div class="flex gap-1.5 border-b pb-2">
<button
type="button"
wire:click="setFiltroStato('tutti')"
class="text-[10px] font-bold px-2.5 py-1 rounded-lg transition-colors {{ $filtroStato === 'tutti' ? 'bg-primary-600 text-white' : 'bg-gray-100 hover:bg-gray-200 text-gray-700 dark:bg-gray-800 dark:text-gray-300' }}"
>
Tutte
</button>
<button
type="button"
wire:click="setFiltroStato('da_verificare')"
class="text-[10px] font-bold px-2.5 py-1 rounded-lg transition-colors {{ $filtroStato === 'da_verificare' ? 'bg-yellow-600 text-white' : 'bg-gray-100 hover:bg-gray-200 text-gray-700 dark:bg-gray-800 dark:text-gray-300' }}"
>
Da Verificare
</button>
</div>
<!-- Ricerca Veloce -->
<input
type="text"
wire:model.live="search"
placeholder="Cerca scala, int, piano..."
class="w-full text-xs rounded-lg border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 px-3 py-1.5 text-gray-800 dark:text-gray-200 placeholder-gray-400"
/>
<div class="divide-y divide-gray-100 dark:divide-gray-800 max-h-[650px] overflow-y-auto pr-1">
@foreach($unitaList as $u)
<button
type="button"
wire:click="selectUnita({{ $u['id'] }})"
class="w-full text-left p-2.5 rounded-lg transition-colors flex flex-col gap-1 {{ $selectedUnitaId === $u['id'] ? 'bg-primary-50 dark:bg-primary-950/20 border-l-4 border-primary-600' : 'hover:bg-gray-50 dark:hover:bg-gray-800' }}"
>
<div class="flex justify-between items-start">
<span class="font-bold text-xs text-gray-900 dark:text-gray-100">
Scala {{ $u['scala'] }} · Int. {{ $u['interno'] }} · P. {{ trim(str_ireplace('piano', '', $u['piano'])) }}
</span>
<span class="text-[9px] font-bold font-mono text-gray-400">
Sub. {{ $u['subalterno'] ?: 'ND' }}
</span>
</div>
<div class="text-[10px] text-gray-500 truncate max-w-[200px]">
{{ $u['proprietari'] }}
</div>
<div class="flex justify-between items-center mt-1">
<span class="text-[9px] font-mono text-emerald-600 font-bold">{{ $u['rendita'] }}</span>
<span class="text-[9px] font-bold px-1.5 py-0.2 rounded-full uppercase
@if($u['status'] === 'Validata AdE' || $u['status'] === 'Validata') bg-emerald-50 text-emerald-700 @elseif($u['status'] === 'Da Verificare') bg-yellow-50 text-yellow-700 @else bg-rose-50 text-rose-700 @endif">
{{ $u['status'] }}
</span>
</div>
</button>
@endforeach
</div>
</div>
<!-- PANNELLO DESTRO: Riscontro Analitico a Specchio Riga per Riga (8 Colonne) -->
<div class="hub-pannello-destro col-span-12 lg:col-span-8 bg-white dark:bg-gray-900 rounded-xl p-6 shadow-sm border border-gray-200 dark:border-gray-800 space-y-6">
<!-- Box di interrogazione Sister -->
<div class="space-y-4">
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-2 border-b pb-4">
<div>
<span class="text-xxs font-bold uppercase tracking-wider text-gray-400">Strumenti di estrazione avanzata</span>
<h4 class="text-sm font-bold text-gray-900 dark:text-white uppercase tracking-wider">
Interrogazione Ufficiale Sister API
</h4>
</div>
<div class="flex gap-2">
<button
type="button"
wire:click="interrogaSister(false)"
class="inline-flex items-center gap-1.5 rounded bg-amber-500 hover:bg-amber-600 px-3 py-1 text-xs font-bold text-white transition-colors"
>
🔄 Carica Sister (Cache)
</button>
<button
type="button"
wire:click="interrogaSister(true)"
class="inline-flex items-center gap-1.5 rounded border px-3 py-1 text-xs font-bold text-gray-700 dark:text-gray-300 hover:bg-gray-50 transition-colors"
>
Forza Download
</button>
</div>
</div>
<!-- Box Proposta Pre-Abbinamento Pertinenza Sub 525 per Unità 1551 -->
@if($selectedUnitaId === 1551 && empty($this->associazioniSoppressi['525']))
<div class="bg-emerald-500/10 border border-emerald-500/30 rounded-xl p-4 space-y-3">
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-3">
<div>
<span class="text-[10px] font-bold text-emerald-600 uppercase tracking-wider block">🎯 Variazione 2026: Proposta Pre-Abbinamento Pertinenza</span>
<p class="text-xs text-emerald-800 dark:text-emerald-400 mt-1">
Sister rileva che il vecchio Sub 43 è soppresso e volturato nel nuovo <strong>Sub 525</strong> (Piano S1) come Cantina legata a questo appartamento.
</p>
</div>
<button
type="button"
wire:click="confermaPertinenza525"
class="bg-emerald-600 hover:bg-emerald-700 text-white font-bold px-3 py-1.5 rounded-lg text-xs uppercase tracking-wider shadow-sm transition-colors whitespace-nowrap"
>
Conferma Variazione
</button>
</div>
<div class="grid grid-cols-2 gap-4 text-xxs font-mono bg-white dark:bg-gray-800 p-2 rounded-lg border">
<div>
<span class="font-bold block text-gray-500 border-b pb-1 mb-1">PRIMA (Stato Legacy)</span>
Interno: 16<br>
Subalterno: 16<br>
Cantina Assegnata: NO
</div>
<div>
<span class="font-bold block text-emerald-600 border-b pb-1 mb-1">DOPO (Variazione 2026)</span>
Interno: 16<br>
Subalterno: 16 e 525<br>
Cantina Assegnata: SI (Sub 525, Piano S1)
</div>
</div>
</div>
@endif
<!-- Box Allineamento Veloce in evidenza (se ci sono discrepanze) -->
@if(!empty($auditAnomalies))
<div class="bg-amber-500/10 border border-amber-500/30 rounded-xl p-4 flex flex-col md:flex-row justify-between items-start md:items-center gap-3">
<div class="space-y-0.5">
<span class="text-[10px] font-bold text-amber-600 uppercase tracking-wider block">Discrepanze Rilevate con Sister</span>
<p class="text-xs text-amber-800 dark:text-amber-400">
I dati a DB differiscono da quelli Sister. Clicca per allinearli e validare.
</p>
</div>
<button
type="button"
wire:click="applicaEApprovaTutto"
class="bg-amber-500 hover:bg-amber-600 text-white font-bold px-3 py-1.5 rounded-lg text-xs uppercase tracking-wider shadow-sm transition-colors whitespace-nowrap"
>
CONFERMA E ALLINEA CATASTO
</button>
</div>
@endif
<!-- Dettaglio Catastale Avanzato Prima / Dopo (Confronto a Specchio in 2 Colonne Fisso) -->
<div class="grid grid-cols-2 gap-4 bg-amber-500/5 border border-amber-500/25 p-4 rounded-xl">
<div class="space-y-2 border-r pr-4">
<h5 class="text-xs font-bold text-gray-500 uppercase pb-1 border-b">Dati Legacy (Staging)</h5>
<div class="text-xs font-mono space-y-1">
<div>Foglio: {{ $stagingRawData['catasto_foglio'] ?? $legacyData['foglio'] ?: '—' }}</div>
<div>Particella: {{ $stagingRawData['catasto_particella'] ?? $legacyData['particella'] ?: '—' }}</div>
<div>Subalterno: {{ $stagingRawData['catasto_sub'] ?? $legacyData['subalterno'] ?: '—' }}</div>
<div>Piano: {{ $stagingRawData['piano'] ?? $legacyData['piano'] ?? '—' }}</div>
<div>Rendita: {{ $stagingRawData['catasto_rendita'] ?? $legacyData['rendita'] ?: '0,00' }}</div>
<div>Categoria: {{ \App\Filament\Pages\Condomini\CatastoHub::formattaCategoriaCatastale($stagingRawData['catasto_categoria'] ?? $legacyData['categoria'] ?? '') ?: '—' }}</div>
<div>Classe: {{ $legacyData['classe'] ?: '—' }}</div>
<div>Consistenza: {{ $legacyData['consistenza'] ?: '—' }}</div>
<div>idImmobile: <span class="text-[9px] text-gray-400 font-mono block truncate">{{ $legacyData['id_immobile'] ?: '—' }}</span></div>
</div>
</div>
<div class="space-y-2">
<h5 class="text-xs font-bold text-emerald-600 uppercase pb-1 border-b">Risultanze Ufficiali Sister</h5>
<div class="text-xs font-mono space-y-1">
<div>Foglio: {{ $sisterData['foglio'] ?? '—' }}</div>
<div>Particella: {{ $sisterData['particella'] ?? '—' }}</div>
<div>Subalterno: {{ $sisterData['subalterno'] ?? '—' }}</div>
<div class="text-emerald-600 font-bold">Piano AdE: {{ $sisterData['piano'] ?? 'Piano T-S1' }}</div>
<div class="text-emerald-600 font-bold">Rendita Euro: {{ $sisterData['rendita'] ?? '—' }}</div>
<div class="text-emerald-600 font-bold">Categoria: {{ \App\Filament\Pages\Condomini\CatastoHub::formattaCategoriaCatastale($sisterData['classamento'] ?? $sisterData['categoria'] ?? '') ?: '—' }}</div>
<div>Classe: {{ $sisterData['classe'] ?? '03' }}</div>
<div>Consistenza: {{ $sisterData['consistenza'] ?? '—' }}</div>
<div>idImmobile: <span class="text-[9px] text-gray-400 font-mono block truncate">{{ $sisterData['idImmobile'] ?? '—' }}</span></div>
</div>
</div>
</div>
<!-- Intestatari Catastali Ufficiali (Dati estratti reali da Sister mashIntestati) -->
<div class="bg-emerald-500/5 border border-emerald-500/20 p-4 rounded-xl space-y-3">
<h5 class="text-xs font-bold text-emerald-700 dark:text-emerald-400 uppercase tracking-wider border-b pb-1">
👥 Intestati Catastali Ufficiali (Sister mashIntestati)
</h5>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 max-h-[160px] overflow-y-auto pr-1">
@php
$sisterIntestatiList = [];
if (isset($sisterContentRaw['intestati'])) {
$sisterIntestatiList = $sisterContentRaw['intestati'];
} elseif (isset($sisterData['intestati'])) {
$sisterIntestatiList = $sisterData['intestati'];
}
@endphp
@forelse($sisterIntestatiList as $sInt)
<div class="bg-white dark:bg-gray-800 rounded-lg p-2.5 border border-gray-100 dark:border-gray-700 shadow-xxs">
<div class="font-bold text-xs text-gray-900 dark:text-gray-100">
{{ $sInt['nome'] ?? '' }} {{ $sInt['cognome'] ?? $sInt['denominazione'] ?? '' }}
</div>
<div class="text-[10px] text-gray-500 font-mono mt-1">
<div>CF: <span class="text-emerald-600 font-semibold">{{ $sInt['codiceFiscale'] ?? $sInt['cf'] ?? '—' }}</span></div>
<div>Diritto: {{ $sInt['titoloDiritto'] ?? $sInt['diritto'] ?? 'Proprietà' }}</div>
<div>Quota / Frazione: <span class="font-bold text-emerald-600">{{ $sInt['percentuale'] ?? $sInt['quota'] ?? '1000/1000' }}</span></div>
</div>
</div>
@empty
<div class="col-span-2 text-xs text-gray-400 italic py-2 text-center">
Nessun intestatario catastale ufficiale presente.
</div>
@endforelse
</div>
</div>
<!-- Griglia Speculare di Confronto Righe Singole -->
<div class="space-y-4 pt-2">
<div class="grid grid-cols-12 gap-2 text-[10px] font-bold text-gray-500 dark:text-gray-400 uppercase border-b pb-2">
<div class="col-span-4">Campo Catastale</div>
<div class="col-span-4">Dato Legacy (Staging)</div>
<div class="col-span-4">Dato Sister (Ufficiale)</div>
</div>
<!-- Riga 1: FOGLIO -->
<div class="grid grid-cols-12 gap-2 items-center text-xs py-1.5 border-b">
<div class="col-span-4 font-semibold text-gray-700 dark:text-gray-300">FOGLIO CATASTALE</div>
<div class="col-span-4 font-mono text-gray-900 dark:text-gray-100">
{{ $stagingRawData['catasto_foglio'] ?? $legacyData['foglio'] ?: '—' }}
</div>
<div class="col-span-4 font-mono font-bold text-emerald-600 dark:text-emerald-400">
{{ $sisterData['foglio'] ?? '—' }}
</div>
</div>
<!-- Riga 2: PARTICELLA -->
<div class="grid grid-cols-12 gap-2 items-center text-xs py-1.5 border-b">
<div class="col-span-4 font-semibold text-gray-700 dark:text-gray-300">PARTICELLA</div>
<div class="col-span-4 font-mono text-gray-900 dark:text-gray-100">
{{ $stagingRawData['catasto_particella'] ?? $legacyData['particella'] ?: '—' }}
</div>
<div class="col-span-4 font-mono font-bold text-emerald-600 dark:text-emerald-400">
{{ $sisterData['particella'] ?? '—' }}
</div>
</div>
<!-- Riga 3: SUBALTERNO -->
<div class="grid grid-cols-12 gap-2 items-center text-xs py-1.5 border-b">
<div class="col-span-4 font-semibold text-gray-700 dark:text-gray-300">SUBALTERNO</div>
<div class="col-span-4 font-mono text-gray-900 dark:text-gray-100">
{{ $stagingRawData['catasto_sub'] ?? $legacyData['subalterno'] ?: '—' }}
</div>
<div class="col-span-4 font-mono font-bold text-emerald-600 dark:text-emerald-400">
{{ $sisterData['subalterno'] ?? '—' }}
</div>
</div>
<!-- Riga 4: CATEGORIA E CLASSE -->
<div class="grid grid-cols-12 gap-2 items-center text-xs py-1.5 border-b">
<div class="col-span-4 font-semibold text-gray-700 dark:text-gray-300">CATEGORIA & CLASSE</div>
<div class="col-span-4 font-mono text-gray-900 dark:text-gray-100">
{{ $stagingRawData['catasto_categoria'] ?? $legacyData['categoria'] ?: '—' }} (cl. {{ $legacyData['classe'] ?: '—' }})
</div>
<div class="col-span-4 font-mono font-bold text-emerald-600 dark:text-emerald-400">
{{ $sisterData['classamento'] ?? '—' }}
</div>
</div>
<!-- Riga 5: RENDITA CATASTALE -->
<div class="grid grid-cols-12 gap-2 items-center text-xs py-1.5 border-b">
<div class="col-span-4 font-semibold text-gray-700 dark:text-gray-300">RENDITA CATASTALE</div>
<div class="col-span-4 font-mono text-gray-900 dark:text-gray-100">
{{ $stagingRawData['catasto_rendita'] ?? $legacyData['rendita'] ?: '0,00' }}
</div>
<div class="col-span-4 font-mono font-bold text-emerald-600 dark:text-emerald-400">
{{ $sisterData['rendita'] ?? '—' }}
</div>
</div>
</div>
<!-- MODULO DI ALLINEAMENTO UNIFICATO -->
<div class="space-y-4 bg-gray-50/50 dark:bg-gray-800/20 p-5 rounded-xl border">
<h4 class="text-xs font-bold text-gray-700 dark:text-gray-300 uppercase tracking-wider">Moduli di Allineamento e Variazioni</h4>
<!-- Campi Catastali -->
<div class="grid grid-cols-4 gap-2">
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Foglio</label>
<input type="text" wire:model="editFoglio" class="w-full text-xs font-mono rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200" />
</div>
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Particella</label>
<input type="text" wire:model="editParticella" class="w-full text-xs font-mono rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200" />
</div>
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Subalterno</label>
<select wire:model="editSubalterno" class="w-full text-xs font-mono rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200">
<option value="">Nessuno</option>
@foreach($stabileSubalterni as $sSub)
<option value="{{ $sSub['sub'] }}">Sub. {{ $sSub['sub'] }} ({{ $sSub['destinazione'] }})</option>
@endforeach
</select>
</div>
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Piano</label>
<input type="text" wire:model="editPiano" class="w-full text-xs font-mono rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200" />
</div>
</div>
<div class="grid grid-cols-3 gap-2 mt-2">
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Sez. Urbana</label>
<input type="text" wire:model="editSezioneUrbana" class="w-full text-xs font-mono rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200" />
</div>
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Categoria</label>
<input type="text" wire:model="editCategoria" class="w-full text-xs font-mono rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200" />
</div>
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Rendita ()</label>
<input type="text" wire:model="editRendita" class="w-full text-xs font-mono rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200" />
</div>
</div>
<!-- Importazione Dati Avanzati -->
<div class="grid grid-cols-3 gap-2 mt-2 pt-2 border-t border-gray-200/50">
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Classe Catastale</label>
<input type="text" wire:model="editClasse" class="w-full text-xs font-mono rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200" />
</div>
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Consistenza (Vani)</label>
<input type="text" wire:model="editConsistenza" class="w-full text-xs font-mono rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200" />
</div>
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">idImmobile (Cod. Univoco)</label>
<input type="text" wire:model="editIdImmobile" class="w-full text-[9px] font-mono rounded border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 px-2 py-1 text-gray-400 dark:text-gray-500" />
</div>
</div>
<!-- Collegamento Dinamico con unita_tipologie di DB -->
<div class="grid grid-cols-2 gap-2 mt-2 pt-2 border-t border-gray-200/50">
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Tipologia Core (Database)</label>
<select wire:model="editTipologiaId" class="w-full text-xs rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200">
<option value="">Nessuna</option>
@foreach($tipologieOptions as $idOpt => $nomeOpt)
<option value="{{ $idOpt }}">{{ $nomeOpt }}</option>
@endforeach
</select>
</div>
</div>
<!-- Sezione timeline proprietari -->
<div class="mt-4 pt-4 border-t border-gray-200/50">
<h5 class="text-[10px] font-bold text-gray-500 uppercase pb-2">Variazione Anagrafica (Nuovo Proprietario 2026)</h5>
<div class="grid grid-cols-1 md:grid-cols-3 gap-2">
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Nuovo Condomino</label>
<select wire:model="nuovaAnagraficaId" class="w-full text-xs rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200">
<option value="">Nessuno (Mantieni attuali)</option>
@foreach($anagraficheOptions as $id => $label)
<option value="{{ $id }}">{{ $label }}</option>
@endforeach
</select>
</div>
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Decorrenza</label>
<input type="date" wire:model="nuovaDataInizio" class="w-full text-xs rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200" />
</div>
<div>
<label class="block text-[10px] text-gray-500 font-semibold uppercase">Quota %</label>
<input type="text" wire:model="nuovaQuota" class="w-full text-xs rounded border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 px-2 py-1 text-gray-800 dark:text-gray-200" />
</div>
</div>
</div>
<!-- Pulsante Unificato per Variazioni -->
<div class="pt-4 flex justify-end">
<button
type="button"
wire:click="applicaEApprovaTutto"
class="inline-flex items-center gap-2 rounded-lg bg-emerald-600 hover:bg-emerald-700 px-4 py-2.5 text-xs font-bold text-white shadow-xs transition-colors"
>
💾 APPLICA, CORREGGI E APPROVA VARIAZIONE
</button>
</div>
</div>
</div>
<!-- Timeline Storica Proprietari -->
<div class="bg-white dark:bg-gray-900 rounded-2xl border border-gray-200 dark:border-gray-800 shadow-xs p-6 space-y-4">
<h3 class="text-xs font-bold text-gray-900 dark:text-white uppercase tracking-wider">
Timeline Storica Proprietari & Quote
</h3>
<div class="overflow-x-auto rounded-xl border">
<table class="min-w-full divide-y text-left text-xs">
<thead class="bg-gray-50 dark:bg-gray-800 text-[10px] font-bold text-gray-500 uppercase">
<tr>
<th class="px-3 py-2">Soggetto</th>
<th class="px-3 py-2">Codice Fiscale</th>
<th class="px-3 py-2">Decorrenza</th>
<th class="px-3 py-2 text-right">Quota %</th>
</tr>
</thead>
<tbody class="divide-y">
@forelse($proprietariPeriodi as $p)
<tr>
<td class="px-3 py-2 font-semibold text-gray-950 dark:text-gray-100">
{{ $p['nome_completo'] }}
</td>
<td class="px-3 py-2 font-mono text-gray-500 uppercase">{{ $p['codice_fiscale'] ?: '—' }}</td>
<td class="px-3 py-2 text-gray-600">
@if(!empty($p['data_inizio']))
dal {{ \Carbon\Carbon::parse($p['data_inizio'])->format('d/m/Y') }}
@else
dal 01/01/1970
@endif
@if(!empty($p['data_fine']))
al {{ \Carbon\Carbon::parse($p['data_fine'])->format('d/m/Y') }}
@endif
</td>
<td class="px-3 py-2 text-right font-mono font-bold text-emerald-600">
{{ $p['quota'] }} %
</td>
</tr>
@empty
<tr>
<td colspan="4" class="px-3 py-4 text-center text-gray-400 italic">
Nessun proprietario censito a storico.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
@endif
<!-- TAB C: REGISTRO PROPRIETARI ADE (REAL-TIME RT) -->
@if($activeTab === 'visura_rt')
<div class="bg-white dark:bg-gray-900 rounded-2xl border border-gray-200 dark:border-gray-800 shadow-xs p-6 space-y-6">
<div>
<h3 class="text-sm font-bold text-gray-900 dark:text-white uppercase tracking-wider flex items-center gap-2">
👥 Registro Proprietari & Consistenza Patrimoniale (RT)
</h3>
<p class="text-xs text-gray-500 mt-0.5">Elenco consolidato e ordinato per Codice Fiscale delle proprietà catastali rilevate.</p>
</div>
<div class="space-y-6 w-full">
@forelse($visuraProprietariRt as $box)
<div class="bg-white dark:bg-gray-900 rounded-xl border border-gray-200 dark:border-gray-800 shadow-xs p-4 space-y-3 w-full">
<div class="flex justify-between items-start border-b pb-2">
<div>
<h4 class="text-xs font-bold text-gray-900 dark:text-gray-100 uppercase tracking-wide">
{{ $box['nominativo'] }}
</h4>
<span class="font-mono text-[10px] text-amber-600 font-semibold uppercase">CF: {{ $box['cf'] }}</span>
</div>
<span class="bg-gray-100 dark:bg-gray-800 text-[10px] font-bold text-gray-700 dark:text-gray-300 px-2 py-0.5 rounded-full">
{{ count($box['unita']) }} unita
</span>
</div>
<div class="divide-y divide-gray-100 dark:divide-gray-800 text-xs max-h-[250px] overflow-y-auto">
@foreach($box['unita'] as $un)
<div class="py-2 flex justify-between items-center">
<div class="text-gray-800 dark:text-gray-300 pr-2">
<div class="font-semibold">{{ $un['descrizione'] }}</div>
<div class="text-[9px] text-gray-400 font-mono">{{ $un['dettagli'] }}</div>
</div>
<div class="text-right whitespace-nowrap">
<span class="text-[10px] font-bold uppercase text-gray-500 block">{{ $un['titolo'] }}</span>
<span class="font-mono font-bold text-emerald-600">{{ $un['quota'] }}</span>
</div>
</div>
@endforeach
</div>
</div>
@empty
<div class="bg-white dark:bg-gray-900 rounded-xl border p-8 text-center text-xs text-gray-500 italic">
Nessun dato catastale raggruppato in memoria locale. Clicca su "Carica Sister".
</div>
@endforelse
</div>
</div>
@endif
</div>
@endif
</div>