netgescon-day0/resources/views/admin/rubrica/index.blade.php

583 lines
30 KiB
PHP
Executable File

@extends('admin.layouts.netgescon')
@section('page-title', 'Rubrica Unica NetGescon')
@push('head')
<meta name="csrf-token" content="{{ csrf_token() }}">
@endpush
@section('content')
@php
$records = null;
if (isset($persone) && $persone instanceof \Illuminate\Contracts\Pagination\LengthAwarePaginator) {
$records = $persone;
} elseif (isset($soggetti) && $soggetti instanceof \Illuminate\Contracts\Pagination\LengthAwarePaginator) {
$records = $soggetti;
}
if (!$records) {
$records = new \Illuminate\Pagination\LengthAwarePaginator([], 0, 20, 1, [
'path' => request()->url(),
'query' => request()->query(),
]);
}
// Deduplica client-side per display: prefer CF, poi email, poi telefono, poi nome+telefono
$displayRecords = $records->getCollection()
->unique(function ($item) {
$cf = $item->codice_fiscale ?? null;
$email = $item->email ?? $item->email_principale ?? null;
$tel = $item->telefono_ufficio ?? $item->telefono_cellulare ?? $item->telefono_principale ?? null;
$name = ($item->nome ?? '') . '|' . ($item->cognome ?? '') . '|' . ($item->ragione_sociale ?? '');
return $cf ?: $email ?: ($tel ? $name . '|' . $tel : $name);
})
->values();
$duplicateHidden = max(0, $records->count() - $displayRecords->count());
$statistiche = is_array($statistiche ?? null) ? $statistiche : [
'totale_persone' => 0,
'persone_fisiche' => 0,
'persone_giuridiche' => 0,
'con_relazioni_attive' => 0,
'senza_relazioni' => 0,
];
$categorieDisponibili = collect($categorieDisponibili ?? [])->filter()->values();
@endphp
<div class="space-y-8 netgescon-fade-in">
<!-- Header -->
<div class="netgescon-card">
<div class="flex items-center justify-between">
<div>
<h2 class="netgescon-title">
<i class="fas fa-address-book text-purple-500 mr-3"></i>
Rubrica Unica NetGescon
</h2>
<p class="netgescon-text mt-2">
Sistema centralizzato per gestione anagrafica di tutto lo studio
</p>
</div>
<div class="hidden md:block">
<a href="{{ route('admin.rubrica.create') }}" class="netgescon-btn netgescon-btn-primary">
<i class="fas fa-user-plus mr-2"></i>
Nuova Persona
</a>
</div>
</div>
</div>
<!-- Statistiche principali -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-6">
<!-- Totale Persone -->
<div class="netgescon-card">
<div class="flex items-center">
<div class="flex-1">
<p class="text-sm font-medium text-gray-600">Totale Persone</p>
<p class="text-3xl font-bold netgescon-text">{{ $statistiche['totale_persone'] ?? 0 }}</p>
</div>
<div class="p-3 bg-purple-100 rounded-full">
<i class="fas fa-users text-purple-600 text-xl"></i>
</div>
</div>
</div>
<!-- Persone Fisiche -->
<div class="netgescon-card">
<div class="flex items-center">
<div class="flex-1">
<p class="text-sm font-medium text-gray-600">Persone Fisiche</p>
<p class="text-3xl font-bold netgescon-text">{{ $statistiche['persone_fisiche'] ?? 0 }}</p>
</div>
<div class="p-3 bg-blue-100 rounded-full">
<i class="fas fa-user text-blue-600 text-xl"></i>
</div>
</div>
</div>
<!-- Persone Giuridiche -->
<div class="netgescon-card">
<div class="flex items-center">
<div class="flex-1">
<p class="text-sm font-medium text-gray-600">Persone Giuridiche</p>
<p class="text-3xl font-bold netgescon-text">{{ $statistiche['persone_giuridiche'] ?? 0 }}</p>
</div>
<div class="p-3 bg-green-100 rounded-full">
<i class="fas fa-building text-green-600 text-xl"></i>
</div>
</div>
</div>
<!-- Con Relazioni -->
<div class="netgescon-card">
<div class="flex items-center">
<div class="flex-1">
<p class="text-sm font-medium text-gray-600">Con Relazioni</p>
<p class="text-3xl font-bold netgescon-text">{{ $statistiche['con_relazioni_attive'] ?? 0 }}</p>
<p class="text-sm text-green-600">Collegate a unità</p>
</div>
<div class="p-3 bg-green-100 rounded-full">
<i class="fas fa-link text-green-600 text-xl"></i>
</div>
</div>
</div>
<!-- Senza Relazioni -->
<div class="netgescon-card">
<div class="flex items-center">
<div class="flex-1">
<p class="text-sm font-medium text-gray-600">Senza Relazioni</p>
<p class="text-3xl font-bold netgescon-text">{{ $statistiche['senza_relazioni'] ?? 0 }}</p>
<p class="text-sm text-orange-600">Da collegare</p>
</div>
<div class="p-3 bg-orange-100 rounded-full">
<i class="fas fa-unlink text-orange-600 text-xl"></i>
</div>
</div>
</div>
</div>
<!-- Ricerca e filtri -->
<div class="netgescon-card">
<form method="GET" action="{{ route('admin.rubrica.index') }}" class="flex flex-col xl:flex-row gap-4">
<div class="flex-1">
<input type="text"
name="search"
value="{{ request('search') }}"
placeholder="Cerca per nome, cognome, ragione sociale, email..."
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent">
</div>
@if($categorieDisponibili->isNotEmpty())
<div class="w-full xl:w-60">
<select name="categoria" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent">
<option value="">Tutte le categorie</option>
@foreach($categorieDisponibili as $categoria)
<option value="{{ $categoria }}" @selected(request('categoria') === $categoria)>
{{ ucfirst($categoria) }}
</option>
@endforeach
</select>
</div>
@endif
<div class="flex gap-2">
<button type="submit" class="netgescon-btn netgescon-btn-primary">
<i class="fas fa-search mr-2"></i>
Cerca
</button>
@if(request('search'))
<a href="{{ route('admin.rubrica.index') }}" class="netgescon-btn netgescon-btn-secondary">
<i class="fas fa-times mr-2"></i>
Reset
</a>
@endif
</div>
</form>
<!-- Tabella soggetti -->
<div class="netgescon-card">
<div class="netgescon-card-header">
<h3 class="netgescon-card-title">
<i class="fas fa-users mr-2"></i>
Elenco Soggetti
@if(request('search'))
<span class="text-sm font-normal text-gray-500 ml-2">
({{ $displayRecords->count() }} risultati unici per "{{ request('search') }}" @if($duplicateHidden>0) / {{ $duplicateHidden }} duplicati nascosti @endif)
@else
<span class="text-sm font-normal text-gray-500 ml-2">
({{ $displayRecords->count() }} soggetti unici @if($duplicateHidden>0) / {{ $duplicateHidden }} duplicati nascosti @endif)
@endif
</span>
</h3>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Soggetto
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Tipo
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Contatti
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Unità Immobiliari
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Azioni
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@forelse($displayRecords as $soggetto)
@php
$tipoRaw = strtolower((string) ($soggetto->tipologia ?? $soggetto->tipo ?? 'f'));
$isFisica = in_array($tipoRaw, ['f', 'fisica', 'persona_fisica'], true);
$nomeCompleto = $soggetto->nome_completo
?? ($isFisica
? trim(($soggetto->nome ?? '') . ' ' . ($soggetto->cognome ?? ''))
: ($soggetto->ragione_sociale
?? trim(($soggetto->nome ?? '') . ' ' . ($soggetto->cognome ?? ''))));
$codiceFiscale = $soggetto->codice_fiscale ?? $soggetto->codice_fiscale_societa ?? null;
$partitaIva = $soggetto->partita_iva ?? $soggetto->partita_iva_societa ?? null;
$emailPrincipale = $soggetto->email_principale ?? $soggetto->email ?? null;
$pecPrincipale = $soggetto->email_pec ?? $soggetto->pec ?? null;
$telefonoPrincipale = $soggetto->telefono_principale ?? $soggetto->telefono ?? null;
$relazioniUnita = collect();
if (method_exists($soggetto, 'relationLoaded') && $soggetto->relationLoaded('relazioniUnitaAttive')) {
$relazioniUnita = $soggetto->relazioniUnitaAttive->map(function ($relazione) {
$unita = $relazione->unitaImmobiliare;
return [
'stabile' => $unita->stabile->denominazione ?? 'N/D',
'scala' => $unita->scala ?? null,
'interno' => $unita->interno ?? null,
'ruolo' => $relazione->tipo_relazione ?? null,
'quota' => $relazione->quota_relazione ?? null,
];
});
} elseif (method_exists($soggetto, 'relationLoaded') && $soggetto->relationLoaded('unitaImmobiliari')) {
$relazioniUnita = $soggetto->unitaImmobiliari->map(function ($unita) {
return [
'stabile' => $unita->stabile->denominazione ?? 'N/D',
'scala' => $unita->scala ?? null,
'interno' => $unita->interno ?? null,
'ruolo' => $unita->pivot->tipo_diritto ?? null,
'quota' => $unita->pivot->percentuale_possesso ?? null,
];
});
} elseif (method_exists($soggetto, 'relationLoaded') && $soggetto->relationLoaded('ruoli')) {
$relazioniUnita = $soggetto->ruoli->map(function ($ruolo) {
$stabile = $ruolo->stabile;
$unita = $ruolo->unitaImmobiliare;
return [
'stabile' => $stabile->denominazione ?? ($ruolo->meta['stabile_label'] ?? 'N/D'),
'scala' => $unita->scala ?? null,
'interno' => $unita->interno ?? null,
'ruolo' => $ruolo->ruolo_custom ?? $ruolo->ruolo_standard,
'quota' => null,
];
});
}
@endphp
<tr class="hover:bg-gray-50">
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<div class="h-10 w-10 rounded-full bg-purple-100 flex items-center justify-center">
@if($soggetto->tipo == 'F')
<i class="fas fa-user text-purple-600"></i>
@else
<i class="fas fa-building text-purple-600"></i>
@endif
</div>
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">
{{ $nomeCompleto ?: '—' }}
</div>
<div class="text-sm text-gray-500">
@if($codiceFiscale)
CF: {{ $codiceFiscale }}
@endif
@if($partitaIva)
| P.IVA: {{ $partitaIva }}
@endif
</div>
<div class="flex flex-wrap gap-2 mt-2">
@if(!empty($soggetto->categoria))
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] uppercase tracking-wide bg-purple-100 text-purple-700">
{{ ucfirst($soggetto->categoria) }}
</span>
@endif
@if(method_exists($soggetto, 'relationLoaded') && $soggetto->relationLoaded('ruoli') && $soggetto->ruoli->count())
@foreach($soggetto->ruoli->take(3) as $ruolo)
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] bg-slate-100 text-slate-700">
{{ strtoupper($ruolo->ruolo_custom ?? $ruolo->ruolo_standard) }}
@if($ruolo->stabile)
<span class="ml-1 text-[9px] text-slate-500">· {{ \Illuminate\Support\Str::limit($ruolo->stabile->denominazione, 20) }}</span>
@endif
</span>
@endforeach
@if($soggetto->ruoli->count() > 3)
<span class="text-[10px] text-slate-500">+{{ $soggetto->ruoli->count() - 3 }}</span>
@endif
@endif
</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
@if($isFisica)
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
<i class="fas fa-user mr-1"></i>
Persona Fisica
</span>
@else
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
<i class="fas fa-building mr-1"></i>
Persona Giuridica
</span>
@endif
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
@if($emailPrincipale)
<div class="flex items-center mb-1">
<i class="fas fa-envelope text-gray-400 mr-2"></i>
<a href="mailto:{{ $emailPrincipale }}" class="text-purple-600 hover:text-purple-900">
{{ $emailPrincipale }}
</a>
</div>
@endif
@if($pecPrincipale)
<div class="flex items-center mb-1">
<i class="fas fa-inbox text-gray-400 mr-2"></i>
<a href="mailto:{{ $pecPrincipale }}" class="text-purple-600 hover:text-purple-900">
{{ $pecPrincipale }}
</a>
<span class="ml-2 text-[10px] uppercase text-orange-500">PEC</span>
</div>
@endif
@if($telefonoPrincipale)
<div class="flex items-center">
<i class="fas fa-phone text-gray-400 mr-2"></i>
<a href="tel:{{ $telefonoPrincipale }}" class="text-purple-600 hover:text-purple-900">
{{ $telefonoPrincipale }}
</a>
</div>
@endif
@if(!$emailPrincipale && !$telefonoPrincipale)
<span class="text-gray-400 italic">Nessun contatto</span>
@endif
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
@if($relazioniUnita->count() > 0)
<div class="space-y-1">
@foreach($relazioniUnita->take(2) as $unita)
<div class="flex items-center text-xs">
<i class="fas fa-home text-blue-500 mr-2"></i>
<span class="font-medium">{{ $unita['stabile'] ?? 'N/D' }}</span>
@if(!empty($unita['scala']) || !empty($unita['interno']))
<span class="text-gray-500 ml-1">
- Scala {{ $unita['scala'] ?? '-' }} Int. {{ $unita['interno'] ?? '-' }}
</span>
@endif
</div>
@if(!empty($unita['ruolo']) || !empty($unita['quota']))
<div class="text-xs text-gray-500 ml-5">
{{ ucfirst($unita['ruolo'] ?? 'ruolo') }}
@if(!empty($unita['quota']))
({{ $unita['quota'] }})
@endif
</div>
@endif
@endforeach
@if($relazioniUnita->count() > 2)
<div class="text-xs text-gray-500 mt-1">
... e altre {{ $relazioniUnita->count() - 2 }} unità
</div>
@endif
</div>
@else
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-orange-100 text-orange-800">
<i class="fas fa-unlink mr-1"></i>
Nessuna unità
</span>
@endif
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<div class="flex items-center space-x-2">
<a href="{{ route('admin.rubrica.show', $soggetto) }}"
class="text-purple-600 hover:text-purple-900"
title="Visualizza dettagli">
<i class="fas fa-eye"></i>
</a>
<a href="{{ route('admin.rubrica.edit', $soggetto) }}"
class="text-blue-600 hover:text-blue-900"
title="Modifica">
<i class="fas fa-edit"></i>
</a>
@if($records->count() > 0)
<button onclick="collegaUnita({{ $soggetto->id }})"
class="text-green-600 hover:text-green-900"
title="Collega a unità immobiliare">
<i class="fas fa-link"></i>
</button>
@endif
</div>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="px-6 py-12 text-center">
<div class="text-gray-500">
<i class="fas fa-users text-4xl mb-4 opacity-50"></i>
<p class="text-lg font-medium">Nessun soggetto trovato</p>
@if(request('search'))
<p class="text-sm mt-2">Prova a modificare i criteri di ricerca</p>
@else
<p class="text-sm mt-2">Aggiungi il primo soggetto alla rubrica</p>
@endif
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<!-- Paginazione -->
@if($records->hasPages())
<div class="px-6 py-4 border-t border-gray-200">
{{ $records->appends(request()->query())->links() }}
</div>
@endif
</div>
</div>
<!-- Modal per collegare unità immobiliare -->
<div id="collegaUnitaModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full hidden">
<div class="relative top-20 mx-auto p-5 border w-11/12 md:w-1/2 shadow-lg rounded-md bg-white">
<div class="mt-3">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-medium text-gray-900">Collega Unità Immobiliare</h3>
<button onclick="chiudiModal()" class="text-gray-400 hover:text-gray-600">
<i class="fas fa-times"></i>
</button>
</div>
<form id="collegaUnitaForm" method="POST">
@csrf
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700">Tipo di Diritto</label>
<select name="tipo_diritto" class="mt-1 block w-full border-gray-300 rounded-md shadow-sm">
<option value="proprieta">Proprietà</option>
<option value="usufrutto">Usufrutto</option>
<option value="nuda_proprieta">Nuda Proprietà</option>
<option value="locazione">Locazione</option>
<option value="altro">Altro</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Percentuale Possesso (%)</label>
<input type="number" name="percentuale_possesso" min="0" max="100" step="0.01"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm">
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Unità Immobiliare</label>
<select name="unita_immobiliare_id" class="mt-1 block w-full border-gray-300 rounded-md shadow-sm" required>
<option value="">Seleziona un'unità immobiliare...</option>
<!-- Le opzioni verranno caricate via AJAX -->
</select>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700">Data Inizio</label>
<input type="date" name="data_inizio"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm">
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Data Fine</label>
<input type="date" name="data_fine"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm">
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Note</label>
<textarea name="note" rows="3"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm"></textarea>
</div>
</div>
<div class="flex justify-end space-x-2 mt-6">
<button type="button" onclick="chiudiModal()"
class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-200 rounded-md hover:bg-gray-300">
Annulla
</button>
<button type="submit"
class="px-4 py-2 text-sm font-medium text-white bg-purple-600 rounded-md hover:bg-purple-700">
Collega Unità
</button>
</div>
</form>
</div>
</div>
</div>
<script>
let soggettoSelezionato = null;
function collegaUnita(soggettoId) {
soggettoSelezionato = soggettoId;
document.getElementById('collegaUnitaModal').classList.remove('hidden');
// Carica le unità immobiliari disponibili
fetch(`/admin/rubrica/unita-disponibili`)
.then(response => response.json())
.then(data => {
const select = document.querySelector('select[name="unita_immobiliare_id"]');
select.innerHTML = '<option value="">Seleziona un\'unità immobiliare...</option>';
data.forEach(unita => {
const option = document.createElement('option');
option.value = unita.id;
option.textContent = `${unita.stabile_nome} - Scala ${unita.scala || '-'} Int. ${unita.interno || '-'}`;
select.appendChild(option);
});
})
.catch(error => {
console.error('Errore nel caricamento delle unità:', error);
});
// Imposta l'action del form
document.getElementById('collegaUnitaForm').action = `/admin/rubrica/${soggettoId}/collega-unita`;
}
function chiudiModal() {
document.getElementById('collegaUnitaModal').classList.add('hidden');
soggettoSelezionato = null;
}
// Gestione submit del form
document.getElementById('collegaUnitaForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
fetch(this.action, {
method: 'POST',
body: formData,
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
chiudiModal();
location.reload(); // Ricarica la pagina per mostrare i cambiamenti
} else {
alert('Errore nel collegamento: ' + (data.message || 'Errore sconosciuto'));
}
})
.catch(error => {
console.error('Errore:', error);
alert('Errore nel collegamento dell\'unità immobiliare');
});
});
// Chiudi modal cliccando fuori
document.getElementById('collegaUnitaModal').addEventListener('click', function(e) {
if (e.target === this) {
chiudiModal();
}
});
</script>
@endsection