netgescon-day0/resources/views/filament/pages/condomini/tabelle-millesimali.blade.php

441 lines
28 KiB
PHP
Executable File

<x-filament-panels::page>
<div class="mx-auto max-w-7xl space-y-4">
<div class="flex items-center gap-2 text-lg font-semibold text-gray-900">
<x-filament::icon icon="heroicon-o-table-cells" class="h-5 w-5 text-primary-600" />
<span>Tabelle millesimali</span>
</div>
<div class="flex flex-wrap gap-2">
<button
type="button"
wire:click="$set('tab','archivio')"
class="inline-flex items-center rounded-lg border px-4 py-2 text-sm font-semibold transition
{{ ($tab ?? 'archivio') === 'archivio' ? 'border-primary-300 bg-primary-50 text-primary-700 shadow-sm' : 'border-gray-200 bg-white text-gray-700 hover:bg-gray-50' }}"
>
Archivio
</button>
<button
type="button"
wire:click="$set('tab','prospetto')"
class="inline-flex items-center rounded-lg border px-4 py-2 text-sm font-semibold transition
{{ ($tab ?? 'archivio') === 'prospetto' ? 'border-primary-300 bg-primary-50 text-primary-700 shadow-sm' : 'border-gray-200 bg-white text-gray-700 hover:bg-gray-50' }}"
>
Prospetto
</button>
<button
type="button"
wire:click="$set('tab','voci')"
class="inline-flex items-center rounded-lg border px-4 py-2 text-sm font-semibold transition
{{ ($tab ?? 'archivio') === 'voci' ? 'border-primary-300 bg-primary-50 text-primary-700 shadow-sm' : 'border-gray-200 bg-white text-gray-700 hover:bg-gray-50' }}"
>
Voci di spesa
</button>
</div>
@if(($tab ?? 'archivio') === 'archivio')
<x-filament::section class="p-4!">
<div class="flex items-start justify-between gap-4 flex-wrap">
<div class="space-y-1">
<div class="text-sm font-semibold text-gray-900">Pulizia archivi millesimali</div>
<div class="text-sm text-gray-600">Usa `Sel.` per marcare gli archivi sporchi. La cancellazione elimina solo le tabelle orfane e blocca quelle ancora collegate a dettagli, voci o altri riferimenti attivi.</div>
</div>
<div class="rounded-xl border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-800">
Selezionate: {{ count($selectedArchiveIds ?? []) }}
</div>
</div>
</x-filament::section>
{{ $this->table }}
@elseif(($tab ?? 'archivio') === 'prospetto')
@php
$baseUrl = static::getUrl(panel: 'admin-filament');
$baseProspettoUrl = $baseUrl . '?tab=prospetto';
@endphp
<x-filament::section class="p-4!">
<div class="mt-1 flex items-start justify-between gap-4 flex-wrap">
<div class="space-y-1">
<div class="flex items-center gap-2 text-lg font-semibold text-gray-900">
<x-filament::icon icon="heroicon-o-chart-pie" class="h-5 w-5 text-primary-600" />
<span>Prospetto tabelle</span>
</div>
<div class="text-sm text-gray-700">Seleziona una tabella per vedere i dettagli (unità, millesimi, percentuali).</div>
</div>
</div>
</x-filament::section>
<div class="grid gap-4 lg:grid-cols-3">
<x-filament::section class="lg:col-span-1">
<x-slot name="heading">Elenco tabelle</x-slot>
<x-slot name="description">Stabile attivo</x-slot>
@if(empty($tabelle))
<div class="rounded-xl border border-dashed border-gray-200 bg-white p-6 text-center text-gray-500">Nessuna tabella millesimale.</div>
@else
<div class="space-y-2">
@foreach($tabelle as $t)
@php $selected = (int) $tabellaId === (int) $t['id']; @endphp
<a
href="{{ $baseProspettoUrl }}&tabella_id={{ (int) $t['id'] }}"
class="block rounded-xl border p-3 transition
{{ $selected ? 'border-primary-300 bg-primary-50' : 'border-gray-200 bg-white hover:bg-gray-50' }}"
>
<div class="flex items-start justify-between gap-3">
<div>
<div class="flex flex-wrap items-center gap-2">
<div class="text-sm font-semibold {{ $selected ? 'text-primary-700' : 'text-gray-900' }}">
{{ $t['codice'] }}
</div>
@if(isset($t['nord']) && $t['nord'] !== null)
<span class="inline-flex items-center rounded-full bg-slate-100 px-2 py-0.5 text-[10px] font-semibold text-slate-700">Ord. {{ $t['nord'] }}</span>
@endif
</div>
<div class="text-xs text-gray-600">{{ $t['nome'] }}</div>
<div class="mt-1 text-[11px] font-medium text-primary-600">{{ $t['voci_count'] ?? 0 }} voci collegate</div>
@if(!empty($t['tipo']) || !empty($t['calcolo']))
<div class="mt-1 text-xs text-gray-500">
{{ $t['tipo'] ? ('Tipo: ' . $t['tipo']) : '' }}
{{ $t['tipo'] && $t['calcolo'] ? ' · ' : '' }}
{{ $t['calcolo'] ? ('Calcolo: ' . $t['calcolo']) : '' }}
</div>
@endif
</div>
<div class="text-right">
<div class="text-xs text-gray-500">{{ !empty($t['is_consumo']) ? 'A consumo' : 'Bilanciata' }}</div>
@if(!empty($t['is_consumo']))
<div class="text-sm font-semibold text-emerald-700">SI</div>
@else
<div class="text-sm font-semibold {{ $t['is_bilanciata'] ? 'text-emerald-700' : 'text-amber-700' }}">
{{ $t['is_bilanciata'] ? 'SI' : 'NO' }}
</div>
@endif
</div>
</div>
</a>
@endforeach
</div>
@endif
</x-filament::section>
<x-filament::section class="lg:col-span-2">
<x-slot name="heading">Dettaglio</x-slot>
<x-slot name="description">Unità e millesimi</x-slot>
@if(!$tabellaInfo)
<div class="text-sm text-gray-500">Seleziona una tabella per vedere il dettaglio.</div>
@else
<div class="space-y-3">
<div class="flex items-center justify-end gap-2">
@if(empty($righe))
<button
type="button"
wire:click="inizializzaRighe"
class="fi-btn fi-btn-color-gray fi-btn-size-sm"
>
Inizializza righe
</button>
@endif
<button
type="button"
wire:click="saveRighe"
class="fi-btn fi-btn-color-primary fi-btn-size-sm"
>
Salva
</button>
</div>
<div class="rounded-xl border bg-gray-50 p-3">
<div class="flex items-start justify-between gap-3 flex-wrap">
<div>
<div class="text-sm font-semibold text-gray-900">{{ $tabellaInfo['codice'] }} {{ $tabellaInfo['nome'] }}</div>
<div class="text-xs text-gray-600">
@if(!empty($tabellaInfo['tipo'])) Tipo: {{ $tabellaInfo['tipo'] }} @endif
@if(!empty($tabellaInfo['tipo']) && !empty($tabellaInfo['calcolo'])) · @endif
@if(!empty($tabellaInfo['calcolo'])) Calcolo: {{ $tabellaInfo['calcolo'] }} @endif
</div>
@if(!empty($tabellaInfo['preventivo']) || !empty($tabellaInfo['consuntivo']))
<div class="text-xs text-gray-500">
@if(!empty($tabellaInfo['preventivo'])) Prev: {{ number_format((float) $tabellaInfo['preventivo'], 2, ',', '.') }} @endif
@if(!empty($tabellaInfo['preventivo']) && !empty($tabellaInfo['consuntivo'])) · @endif
@if(!empty($tabellaInfo['consuntivo'])) Cons: {{ number_format((float) $tabellaInfo['consuntivo'], 2, ',', '.') }} @endif
</div>
@endif
</div>
<div class="text-right">
<div class="text-xs text-gray-500">Totale</div>
<div class="text-sm font-semibold text-gray-900">{{ number_format((float) ($tabellaInfo['totale'] ?? 0), 3, ',', '.') }}</div>
@if(!empty($tabellaInfo['is_consumo']))
<div class="text-xs text-emerald-700">A consumo</div>
@else
<div class="text-xs {{ ($tabellaInfo['is_bilanciata'] ?? false) ? 'text-emerald-700' : 'text-amber-700' }}">
{{ ($tabellaInfo['is_bilanciata'] ?? false) ? 'Bilanciata (≈1000)' : 'Non bilanciata' }}
</div>
@endif
</div>
</div>
</div>
@if(empty($righe))
<div class="rounded-xl border border-dashed border-gray-200 bg-white p-6 text-center text-gray-500">Nessun dettaglio millesimi.</div>
@else
<div class="overflow-x-auto">
<table class="min-w-full text-sm">
<thead>
<tr class="border-b text-left text-gray-500">
<th class="py-2">Unità</th>
<th class="py-2">Posizione</th>
<th class="py-2">Ruolo</th>
<th class="py-2 text-right">NORD</th>
<th class="py-2 text-center">Partecipa</th>
<th class="py-2 text-right">Millesimi</th>
<th class="py-2 text-right">%</th>
</tr>
</thead>
<tbody class="divide-y">
@foreach($righe as $r)
@php
$unitaUrl = \App\Filament\Pages\UnitaImmobiliarePage::getUrl(panel: 'admin-filament')
. '?unita_id=' . (int) $r['unita_id']
. '&back=' . urlencode(request()->fullUrl());
@endphp
<tr>
<td class="py-2">
<a href="{{ $unitaUrl }}" class="text-gray-900 font-semibold hover:text-primary-700">
{{ $r['codice_unita_display'] ?? $r['codice_unita'] ?? ('Unità #' . $r['unita_id']) }}
</a>
@if(!empty($r['denominazione']))
<div class="text-xs text-gray-500">{{ $r['denominazione'] }}</div>
@endif
</td>
<td class="py-2 text-gray-700">
Pal. {{ $r['palazzina'] ?? '—' }} · Scala {{ $r['scala'] ?? '—' }} · Piano {{ $r['piano'] ?? '—' }} · Int. {{ $r['interno'] ?? '—' }}
</td>
<td class="py-2">
<select wire:model.defer="righe.{{ $loop->index }}.ruolo_legacy" class="rounded-md border-gray-300 py-1 text-xs block w-24">
<option value="">Nessuno</option>
<option value="C">Condomino (C)</option>
<option value="I">Inquilino (I)</option>
</select>
</td>
<td class="py-2 text-right">
<input
type="number"
class="rounded-md border-gray-300 py-1 text-xs block w-16 text-right ml-auto"
wire:model.defer="righe.{{ $loop->index }}.nord"
/>
</td>
<td class="py-2 text-center">
<input
type="checkbox"
class="fi-checkbox-input"
wire:model.defer="righe.{{ $loop->index }}.partecipa"
/>
</td>
<td class="py-2 text-right">
<input
type="number"
step="0.001"
inputmode="decimal"
class="fi-input block w-28 text-right ml-auto"
wire:model.defer="righe.{{ $loop->index }}.millesimi"
/>
</td>
<td class="py-2 text-right text-gray-900">{{ number_format((float) $r['percentuale'], 2, ',', '.') }}%</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
</div>
@endif
</x-filament::section>
</div>
@else
@php
$baseUrl = static::getUrl(panel: 'admin-filament');
$baseVociUrl = $baseUrl . '?tab=voci';
@endphp
<div class="grid gap-4 lg:grid-cols-3">
<x-filament::section class="lg:col-span-1">
<x-slot name="heading">Elenco tabelle</x-slot>
<x-slot name="description">Stabile attivo</x-slot>
@if(empty($tabelle))
<div class="rounded-xl border border-dashed border-gray-200 bg-white p-6 text-center text-gray-500">Nessuna tabella millesimale.</div>
@else
<div class="space-y-2">
@foreach($tabelle as $t)
@php $selected = (int) $tabellaId === (int) $t['id']; @endphp
<a
href="{{ $baseVociUrl }}&tabella_id={{ (int) $t['id'] }}"
class="block rounded-xl border p-3 transition
{{ $selected ? 'border-primary-300 bg-primary-50' : 'border-gray-200 bg-white hover:bg-gray-50' }}"
>
<div class="flex items-start justify-between gap-3">
<div>
<div class="flex flex-wrap items-center gap-2">
<div class="text-sm font-semibold {{ $selected ? 'text-primary-700' : 'text-gray-900' }}">
{{ $t['codice'] }}
</div>
@if(isset($t['nord']) && $t['nord'] !== null)
<span class="inline-flex items-center rounded-full bg-slate-100 px-2 py-0.5 text-[10px] font-semibold text-slate-700">Ord. {{ $t['nord'] }}</span>
@endif
</div>
<div class="text-xs text-gray-600">{{ $t['nome'] }}</div>
<div class="mt-1 text-[11px] font-medium text-primary-600">{{ $t['voci_count'] ?? 0 }} voci collegate</div>
@if(!empty($t['tipo']) || !empty($t['calcolo']))
<div class="mt-1 text-xs text-gray-500">
{{ $t['tipo'] ? ('Tipo: ' . $t['tipo']) : '' }}
{{ $t['tipo'] && $t['calcolo'] ? ' · ' : '' }}
{{ $t['calcolo'] ? ('Calcolo: ' . $t['calcolo']) : '' }}
</div>
@endif
</div>
</div>
</a>
@endforeach
</div>
@endif
</x-filament::section>
<x-filament::section class="lg:col-span-2">
<x-slot name="heading">Voci di spesa</x-slot>
<x-slot name="description">Collegate alla tabella selezionata</x-slot>
@if(empty($vociSpesa))
<div class="text-sm text-gray-500">Nessuna voce collegata a questa tabella.</div>
@else
<div class="flex items-center justify-between gap-3 mb-2 flex-wrap">
<div class="flex items-center gap-2 flex-wrap">
<label class="text-xs text-gray-500">Preset ripartizione</label>
<select
class="fi-input block text-xs"
wire:model.live="presetRipartizione"
>
<option value="manuale">Manuale</option>
<option value="confedilizia">Confedilizia</option>
<option value="custom">Preset salvato</option>
</select>
@if(($presetRipartizione ?? 'manuale') === 'custom')
<select
class="fi-input block text-xs"
wire:model.live="presetId"
>
<option value="">Seleziona preset…</option>
@foreach($presetOptions as $id => $label)
<option value="{{ $id }}">{{ $label }}</option>
@endforeach
</select>
@endif
<button
type="button"
wire:click="applyPresetRipartizione"
class="fi-btn fi-btn-color-gray fi-btn-size-xs"
>
Applica
</button>
@if(($presetRipartizione ?? 'manuale') === 'custom' && !empty($presetId))
<button
type="button"
wire:click="updatePreset"
class="fi-btn fi-btn-color-gray fi-btn-size-xs"
>
Aggiorna preset
</button>
@endif
</div>
<button
type="button"
wire:click="saveVociSpesa"
class="fi-btn fi-btn-color-primary fi-btn-size-sm"
>
Salva
</button>
</div>
@if(!empty($presetDirty))
<div class="mb-2 text-xs text-amber-600">Preset modificato: aggiorna il preset o salva come nuovo.</div>
@endif
<div class="flex items-center gap-2 mb-2">
<input
type="text"
class="fi-input block text-xs w-60"
placeholder="Nome nuovo preset"
wire:model.defer="presetNome"
/>
<button
type="button"
wire:click="savePresetAsNew"
class="fi-btn fi-btn-color-gray fi-btn-size-xs"
>
Crea preset
</button>
</div>
<div class="overflow-x-auto">
<table class="min-w-full text-xs">
<thead>
<tr class="border-b text-left text-gray-500">
<th class="py-2 w-20">Modifica</th>
<th class="py-2">Codice</th>
<th class="py-2">Descrizione</th>
<th class="py-2">Tipo</th>
<th class="py-2">Categoria</th>
<th class="py-2 text-right">% Cond.</th>
<th class="py-2 text-right">% Inq.</th>
</tr>
</thead>
<tbody class="divide-y">
@foreach($vociSpesa as $row)
<tr>
<td class="py-2">
<label class="inline-flex items-center gap-2 text-xs text-gray-600">
<input
type="checkbox"
class="fi-checkbox-input"
wire:model.live="vociSpesa.{{ $loop->index }}.modifica"
/>
Abilita
</label>
</td>
<td class="py-2 text-gray-700">{{ $row['codice'] ?? '—' }}</td>
<td class="py-2">
<div class="text-xs font-semibold text-gray-900">{{ $row['descrizione'] ?? '—' }}</div>
</td>
<td class="py-2 text-gray-700">{{ $row['tipo_gestione'] ?? '—' }}</td>
<td class="py-2 text-gray-700">{{ $row['categoria'] ?? '—' }}</td>
<td class="py-2 text-right">
<input
type="number"
step="0.01"
inputmode="decimal"
class="fi-input block w-20 text-right"
wire:model.live="vociSpesa.{{ $loop->index }}.percentuale_condomino"
@disabled(empty($row['modifica']))
/>
</td>
<td class="py-2 text-right">
<input
type="number"
step="0.01"
inputmode="decimal"
class="fi-input block w-20 text-right"
wire:model.live="vociSpesa.{{ $loop->index }}.percentuale_inquilino"
@disabled(empty($row['modifica']))
/>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
</x-filament::section>
</div>
@endif
</div>
</x-filament-panels::page>