@php
$palazzine = $stabile->palazzine()
->with(['unitaImmobiliari' => function ($q) {
$q->with('soggetti')->orderBy('scala')->orderBy('piano')->orderBy('interno');
}])
->orderBy('codice_palazzina')
->get();
$unitaAll = $stabile->unitaImmobiliari()->with('soggetti')->get();
$fallbackGroups = collect();
if ($palazzine->isEmpty() && $unitaAll->isNotEmpty()) {
$fallbackGroups = $unitaAll->groupBy(fn($u) => strtoupper(trim($u->palazzina ?? '')))->sortKeys();
}
$unitaByPalCode = $unitaAll->groupBy(fn($u) => strtoupper(trim($u->palazzina ?? '')));
$formatSoggettoNome = static function ($soggetto) {
$nome = trim(($soggetto->nome ?? '') . ' ' . ($soggetto->cognome ?? ''));
return $nome !== '' ? $nome : ($soggetto->ragione_sociale ?? '—');
};
$ruoliProprietario = ['proprieta','proprietario','piena_proprieta','comproprietario','comproprieta','nudo_proprietario','nuda_proprieta','usufruttuario','usufrutto','diritto_abitazione','diritto_di_abitazione'];
$ruoliInquilino = ['locazione','inquilino','conduttore','locatario'];
$rolePriority = ['proprietario' => 0, 'inquilino' => 1, 'altro' => 2];
$badgePalette = [
'proprietario' => ['bg' => 'bg-emerald-50', 'text' => 'text-emerald-700', 'border' => 'border-emerald-200', 'icon' => 'fa-user-tie'],
'inquilino' => ['bg' => 'bg-sky-50', 'text' => 'text-sky-700', 'border' => 'border-sky-200', 'icon' => 'fa-user'],
'altro' => ['bg' => 'bg-slate-50', 'text' => 'text-slate-600', 'border' => 'border-slate-200', 'icon' => 'fa-user-circle'],
];
$categoriaColor = [
'A' => ['bg' => 'bg-emerald-50', 'text' => 'text-emerald-700', 'border' => 'border-emerald-200', 'icon' => 'fa-building'],
'B' => ['bg' => 'bg-sky-50', 'text' => 'text-sky-700', 'border' => 'border-sky-200', 'icon' => 'fa-warehouse'],
'C' => ['bg' => 'bg-amber-50', 'text' => 'text-amber-700', 'border' => 'border-amber-200', 'icon' => 'fa-store'],
'D' => ['bg' => 'bg-fuchsia-50', 'text' => 'text-fuchsia-700', 'border' => 'border-fuchsia-200', 'icon' => 'fa-industry'],
'E' => ['bg' => 'bg-rose-50', 'text' => 'text-rose-700', 'border' => 'border-rose-200', 'icon' => 'fa-landmark'],
'F' => ['bg' => 'bg-purple-50', 'text' => 'text-purple-700', 'border' => 'border-purple-200', 'icon' => 'fa-drafting-compass'],
'G' => ['bg' => 'bg-lime-50', 'text' => 'text-lime-700', 'border' => 'border-lime-200', 'icon' => 'fa-sitemap'],
'S' => ['bg' => 'bg-stone-50', 'text' => 'text-stone-600', 'border' => 'border-stone-200', 'icon' => 'fa-tree'],
];
$categoriaLegenda = [
'A' => ['label' => 'Gruppo A', 'descrizione' => 'Uso abitativo'],
'B' => ['label' => 'Gruppo B', 'descrizione' => 'Servizi collettivi'],
'C' => ['label' => 'Gruppo C', 'descrizione' => 'Depositi, box, negozi'],
'D' => ['label' => 'Gruppo D', 'descrizione' => 'Immobili a uso speciale'],
'E' => ['label' => 'Gruppo E', 'descrizione' => 'Immobili a destinazione particolare'],
'F' => ['label' => 'Gruppo F', 'descrizione' => 'Entità urbane particolari'],
'G' => ['label' => 'Gruppo G', 'descrizione' => 'Opere speciali e servizi'],
'S' => ['label' => 'Terreni', 'descrizione' => 'Terreni e aree scoperte'],
];
$legacyTipologie = [
'A' => 'Appartamento',
'B' => 'Autorimessa / Box',
'C' => 'Cantina / Deposito',
'D' => 'Locale commerciale',
'M' => 'Magazzino',
'S' => 'Soffitta / Sottotetto',
'L' => 'Locale tecnico',
];
$labelPiano = static function (int $piano): string {
return match ($piano) {
9 => 'Soffitte (+1)',
8 => 'Piano 8',
7 => 'Piano 7',
6 => 'Piano 6',
5 => 'Piano 5',
4 => 'Piano 4',
3 => 'Piano 3',
2 => 'Piano 2',
1 => 'Piano 1',
0 => 'Piano Terra',
-1 => 'Cantina (-1)',
default => 'Piano '.$piano,
};
};
$highlightPalazzinaId = isset($highlightPalazzina) ? (string) $highlightPalazzina : '';
$highlightPalazzinaCode = isset($highlightPalazzinaCode) ? strtoupper((string) $highlightPalazzinaCode) : '';
$highlightScala = isset($highlightScala) ? strtoupper((string) $highlightScala) : '';
$highlightUnita = isset($highlightUnita) ? (string) $highlightUnita : '';
$highlightInterno = isset($highlightInterno) ? strtoupper((string) $highlightInterno) : '';
@endphp
Palazzine
{{ $palazzine->isNotEmpty() ? $palazzine->count() : $fallbackGroups->count() }}
Unità immobiliari
{{ $palazzine->isNotEmpty() ? $palazzine->flatMap->unitaImmobiliari->count() : $unitaAll->count() }}
Unità con soggetti
@php $withSubjectsKpi = $palazzine->isNotEmpty()
? $palazzine->flatMap->unitaImmobiliari->filter(fn($u) => $u->soggetti->isNotEmpty())->count()
: $unitaAll->filter(fn($u) => $u->soggetti->isNotEmpty())->count(); @endphp
{{ $withSubjectsKpi }}
Locali tecnici
@php $localiTecniciKpi = ($palazzine->isNotEmpty() ? $palazzine->flatMap->unitaImmobiliari : $unitaAll)
->filter(fn($u) => in_array($u->tipo_unita, ['locale_tecnico','centrale_termica','autorimessa','cantina','box','solaio']))
->count(); @endphp
{{ $localiTecniciKpi }}
Palazzine/Scale
@if($palazzine->isNotEmpty())
@foreach($palazzine as $pal)
@php
$pid = 'pal_'.$pal->id;
$label = $pal->denominazione ?: ($pal->codice_palazzina ?: '—');
$scalaCode = strtoupper(trim($pal->codice_palazzina ?? ''));
$unitaPal = $pal->unitaImmobiliari;
if ($unitaPal->isEmpty() && $scalaCode !== '') {
$unitaPal = $unitaByPalCode[$scalaCode] ?? collect();
}
$cnt = $unitaPal->count();
$isFirst = $loop->first;
@endphp
@endforeach
@elseif($fallbackGroups->isNotEmpty())
@foreach($fallbackGroups as $codicePalazzina => $group)
@php $pid = 'fb_'.str_replace(' ','_', $codicePalazzina ?: 'ND'); @endphp
@endforeach
@else
@endif
@if($palazzine->isNotEmpty())
@foreach($palazzine as $pal)
@php
$pid = 'pal_'.$pal->id;
$panelClasses = 'palazzina-panel ' . ($loop->first ? '' : 'hidden');
$unitaPal = $pal->unitaImmobiliari;
if ($unitaPal->isEmpty()) {
$code = strtoupper(trim($pal->codice_palazzina ?? ''));
$unitaPal = $code !== '' ? ($unitaByPalCode[$code] ?? collect()) : collect();
}
$unitCount = $unitaPal->count();
$withSubjectsCount = $unitaPal->filter(fn($u) => $u->soggetti->isNotEmpty())->count();
$localiTecniciPalCount = $unitaPal->filter(fn($u) => in_array($u->tipo_unita, ['locale_tecnico','centrale_termica','autorimessa','cantina','box','solaio']))->count();
$libereCount = $unitaPal->where('stato_occupazione', 'libera')->count();
$occupateProp = $unitaPal->where('stato_occupazione', 'occupata_proprietario')->count();
$occupateInq = $unitaPal->where('stato_occupazione', 'occupata_inquilino')->count();
@endphp
@php $perScala = $unitaPal->groupBy('scala'); @endphp
@foreach($perScala as $scala => $unitaScala)
@php $pianiGrouped = $unitaScala->groupBy(fn($u) => (int) ($u->piano ?? 0))->sortKeysDesc(); @endphp
Scala {{ $scala ?? '-' }}
@foreach($pianiGrouped as $piano => $unitaPiano)
{{ $labelPiano((int) $piano) }}
@if($unitaPiano->isNotEmpty())
@else
Nessuna unità su questo piano.
@endif
@endforeach
@endforeach
@endforeach
@elseif($fallbackGroups->isNotEmpty())
@foreach($fallbackGroups as $codicePalazzina => $group)
@php
$pid = 'fb_'.str_replace(' ','_', $codicePalazzina ?: 'ND');
$unitCount = $group->count();
$withSubjectsCount = $group->filter(fn($u) => $u->soggetti->isNotEmpty())->count();
$localiTecniciPalCount = $group->filter(fn($u) => in_array($u->tipo_unita, ['locale_tecnico','centrale_termica','autorimessa','cantina','box','solaio']))->count();
$libereCount = $group->where('stato_occupazione', 'libera')->count();
$occupateProp = $group->where('stato_occupazione', 'occupata_proprietario')->count();
$occupateInq = $group->where('stato_occupazione', 'occupata_inquilino')->count();
@endphp
Palazzina {{ $codicePalazzina ?: '—' }} (fallback)
{{ $unitCount }} unità
{{ $withSubjectsCount }} con soggetti
{{ $localiTecniciPalCount }} locali tecnici
{{ $occupateProp }} proprietario
{{ $occupateInq }} inquilino
{{ $libereCount }} libere
@php $perScala = $group->groupBy('scala'); @endphp
@foreach($perScala as $scala => $unitaScala)
@php $pianiGrouped = $unitaScala->groupBy(fn($u) => (int) ($u->piano ?? 0))->sortKeysDesc(); @endphp
Scala {{ $scala ?? '-' }}
@foreach($pianiGrouped as $piano => $unitaPiano)
{{ $labelPiano((int) $piano) }}
@if($unitaPiano->isNotEmpty())
@else
Nessuna unità su questo piano.
@endif
@endforeach
@endforeach
@endforeach
@elseif($fallbackGroups->isNotEmpty())
@foreach($fallbackGroups as $codicePalazzina => $group)
@php
$pid = 'fb_'.str_replace(' ','_', $codicePalazzina ?: 'ND');
$unitCount = $group->count();
$withSubjectsCount = $group->filter(fn($u) => $u->soggetti->isNotEmpty())->count();
$localiTecniciPalCount = $group->filter(fn($u) => in_array($u->tipo_unita, ['locale_tecnico','centrale_termica','autorimessa','cantina','box','solaio']))->count();
$libereCount = $group->where('stato_occupazione', 'libera')->count();
$occupateProp = $group->where('stato_occupazione', 'occupata_proprietario')->count();
$occupateInq = $group->where('stato_occupazione', 'occupata_inquilino')->count();
@endphp
Palazzina {{ $codicePalazzina ?: '—' }} (fallback)
{{ $unitCount }} unità
{{ $withSubjectsCount }} con soggetti
{{ $localiTecniciPalCount }} locali tecnici
{{ $occupateProp }} proprietario
{{ $occupateInq }} inquilino
{{ $libereCount }} libere
@php $perScala = $group->groupBy('scala'); @endphp
@foreach($perScala as $scala => $unitaScala)
@php $pianiGrouped = $unitaScala->groupBy(fn($u) => (int) ($u->piano ?? 0))->sortKeysDesc(); @endphp
Scala {{ $scala ?? '-' }}
@foreach($pianiGrouped as $piano => $unitaPiano)
{{ $labelPiano((int) $piano) }}
@if($unitaPiano->isNotEmpty())
@foreach($unitaPiano->sortBy(fn ($u) => \App\Support\InternoSort::key($u->interno !== null ? (string) $u->interno : null)) as $u)
@php
$categoriaCompleta = strtoupper(trim($u->categoria_catastale ?? ''));
$categoriaGruppo = $categoriaCompleta !== '' ? substr($categoriaCompleta, 0, 1) : null;
$categoriaStyle = $categoriaColor[$categoriaGruppo] ?? ['bg' => 'bg-slate-50', 'text' => 'text-slate-600', 'border' => 'border-slate-200', 'icon' => 'fa-tags'];
$categoriaDescrizione = $categoriaLegenda[$categoriaGruppo]['descrizione'] ?? null;
$tipoUnitaLabel = $legacyTipologie[strtoupper(substr($u->tipo_unita ?? '', 0, 1))] ?? ucfirst(str_replace('_', ' ', $u->tipo_unita ?? 'ND'));
$utilizzo = $u->utilizzo_attuale ? ucfirst($u->utilizzo_attuale) : null;
$consistenza = $u->consistenza ? number_format((float) $u->consistenza, 2, ',', '.') : null;
$rendita = $u->rendita_catastale ? number_format((float) $u->rendita_catastale, 2, ',', '.') : null;
$occupanti = $u->soggetti->map(function ($soggetto) use ($formatSoggettoNome, $ruoliProprietario, $ruoliInquilino, $badgePalette, $rolePriority) {
$tipoPivot = strtolower(trim($soggetto->pivot?->tipo_diritto ?? ''));
$ruoloKey = in_array($tipoPivot, $ruoliProprietario, true)
? 'proprietario'
: (in_array($tipoPivot, $ruoliInquilino, true) ? 'inquilino' : 'altro');
$palette = $badgePalette[$ruoloKey] ?? $badgePalette['altro'];
return [
'nome' => $formatSoggettoNome($soggetto),
'ruolo_label' => $tipoPivot !== '' ? ucfirst(str_replace('_', ' ', $tipoPivot)) : ($ruoloKey === 'altro' ? 'Altro' : ucfirst($ruoloKey)),
'ruolo_key' => $ruoloKey,
'palette' => $palette,
'percentuale' => $soggetto->pivot?->percentuale_possesso,
'inizio' => optional(\Illuminate\Support\Carbon::make($soggetto->pivot?->data_inizio))?->format('d/m/Y'),
'fine' => optional(\Illuminate\Support\Carbon::make($soggetto->pivot?->data_fine))?->format('d/m/Y'),
];
})->sortBy(fn($item) => $rolePriority[$item['ruolo_key']] ?? 99)->values();
$statoLabel = match($u->stato_occupazione) {
'occupata_proprietario' => 'Proprietà',
'occupata_inquilino' => 'Locata',
'libera' => 'Libera',
default => ucfirst(str_replace('_', ' ', $u->stato_occupazione ?? 'Sconosciuta')),
};
$statoColor = match($u->stato_occupazione) {
'occupata_proprietario' => 'bg-emerald-100 text-emerald-700 border-emerald-200',
'occupata_inquilino' => 'bg-sky-100 text-sky-700 border-sky-200',
'libera' => 'bg-stone-100 text-stone-600 border-stone-200',
default => 'bg-slate-100 text-slate-600 border-slate-200',
};
@endphp
{{ $u->interno ?: '—' }}
{{ $u->codice_unita ?: 'Unità '.$u->id }}
Scala {{ $scala ?? '—' }}
{{ $labelPiano((int) ($u->piano ?? 0)) }}
{{ $categoriaCompleta ?: 'Cat. ND' }}
{{ $tipoUnitaLabel }}
@if($utilizzo)
{{ $utilizzo }}
@endif
{{ $statoLabel }}
@if($u->subalterno)
Subalterno: {{ $u->subalterno }}
@endif
@if($consistenza)
Consistenza: {{ $consistenza }}
@endif
@if($rendita)
Rendita: € {{ $rendita }}
@endif
@if($u->millesimi_generali)
Millesimi Proprietà: {{ number_format((float) $u->millesimi_generali, 3, ',', '.') }}
@endif
@if($u->millesimi_riscaldamento)
Millesimi Riscaldamento: {{ number_format((float) $u->millesimi_riscaldamento, 3, ',', '.') }}
@endif
@if($u->millesimi_acqua)
Millesimi Acqua: {{ number_format((float) $u->millesimi_acqua, 3, ',', '.') }}
@endif
@if($occupanti->isNotEmpty())
@foreach($occupanti as $occupante)
{{ \Illuminate\Support\Str::limit($occupante['nome'], 60) }}
{{ $occupante['ruolo_label'] }}
@if(!is_null($occupante['percentuale']))
Quota {{ rtrim(rtrim(number_format((float) $occupante['percentuale'], 4, ',', '.'), '0'), ',') }}%
@endif
@if($occupante['inizio'] || $occupante['fine'])
@if($occupante['inizio'] && $occupante['fine'])
{{ $occupante['inizio'] }} → {{ $occupante['fine'] }}
@elseif($occupante['inizio'])
dal {{ $occupante['inizio'] }}
@else
fino al {{ $occupante['fine'] }}
@endif
@endif
@endforeach
@else
Nessun soggetto associato a questa unità.
@endif
@endforeach
@else
Nessuna unità su questo piano.
@endif
@endforeach
@endforeach
@endforeach
@else
Nessuna palazzina o unità disponibili.
@endif