netgescon-day0/resources/views/filament/pages/fornitore/rubrica-clienti.blade.php

249 lines
23 KiB
PHP
Executable File

<x-filament-panels::page>
<div class="space-y-4">
<div class="rounded-xl border bg-white p-4">
<div class="flex flex-wrap items-center justify-between gap-3">
<div>
<div class="text-lg font-semibold">Rubrica clienti fornitore</div>
<div class="text-sm text-gray-600">
@if($this->fornitoreLabel)
Rubrica unificata: contatti aggregati da <strong>TecnoRepair (TClienti)</strong>, <strong>Contabilità MySQL (Target Cross arc_nehr)</strong> e <strong>Ticket NetGescon</strong>.
@else
Seleziona un fornitore per aprire la rubrica clienti.
@endif
</div>
</div>
<div class="flex flex-wrap items-center gap-2">
<button type="button" wire:click="sincronizzaRubrica" wire:loading.attr="disabled" class="inline-flex items-center gap-1 rounded-md bg-emerald-700 px-3 py-1.5 text-xs font-bold text-white hover:bg-emerald-600 shadow-xs">
<span wire:loading.remove wire:target="sincronizzaRubrica"> Sincronizza Rubrica</span>
<span wire:loading wire:target="sincronizzaRubrica">Sincronizzazione in corso...</span>
</button>
<a href="/admin-filament/fornitore/pratiche?fornitore={{ $this->fornitoreId }}" class="inline-flex items-center rounded-md bg-sky-700 px-3 py-1.5 text-xs font-bold text-white hover:bg-sky-600 shadow-xs">💻 Pratiche TecnoRepair</a>
<a href="{{ $this->getLavorazioniUrl() }}" class="inline-flex items-center rounded-md bg-gray-800 px-3 py-1.5 text-xs font-medium text-white hover:bg-gray-700">Lavorazioni</a>
<a href="/admin-filament/fornitore/tickets?fornitore={{ $this->fornitoreId }}" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50">Ticket Operativi</a>
</div>
</div>
</div>
@if($this->missingAdminContext)
<div class="rounded-xl border border-amber-300 bg-amber-50 p-4 text-sm text-amber-800">
Questa vista richiede un fornitore selezionato.
</div>
@else
<div class="rounded-xl border bg-white p-4">
<div class="grid gap-3 xl:grid-cols-[1.2fr,0.8fr]">
<div class="flex flex-wrap items-center gap-2">
<button type="button" wire:click="selectTab('elenco')" class="inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium {{ $activeTab === 'elenco' ? 'bg-slate-800 text-white' : 'bg-white text-slate-700 ring-1 ring-inset ring-slate-300 hover:bg-slate-50' }}">Elenco compatto</button>
<button type="button" wire:click="selectTab('scheda')" class="inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium {{ $activeTab === 'scheda' ? 'bg-slate-800 text-white' : 'bg-white text-slate-700 ring-1 ring-inset ring-slate-300 hover:bg-slate-50' }}">Scheda cliente</button>
</div>
<div class="grid grid-cols-2 gap-2 xl:grid-cols-4">
<div class="rounded-lg border bg-slate-50 px-3 py-2 text-xs">Totali <span class="font-semibold">{{ $counters['totali'] ?? 0 }}</span></div>
<div class="rounded-lg border bg-emerald-50 px-3 py-2 text-xs text-emerald-800">Collegati <span class="font-semibold">{{ $counters['collegati'] ?? 0 }}</span></div>
<div class="rounded-lg border bg-sky-50 px-3 py-2 text-xs text-sky-800">Con email <span class="font-semibold">{{ $counters['con_email'] ?? 0 }}</span></div>
<div class="rounded-lg border bg-amber-50 px-3 py-2 text-xs text-amber-800">Con cellulare <span class="font-semibold">{{ $counters['con_cellulare'] ?? 0 }}</span></div>
</div>
</div>
<div class="mt-4 grid gap-4 xl:grid-cols-[1.4fr,0.6fr]">
<div>
@if($activeTab === 'elenco')
<div class="flex flex-wrap items-center gap-3">
<label class="block flex-1 text-sm min-w-[240px]">
<span class="mb-1 block font-medium text-xs text-slate-600">Cerca cliente (nome, telefono, CF/PIVA, città)</span>
<input type="text" wire:model.live.debounce.300ms="search" class="w-full rounded-lg border-gray-300 text-sm" placeholder="Es. Rossi, 3391234567, RM, Casaregola..." />
</label>
<label class="block text-sm min-w-[180px]">
<span class="mb-1 block font-medium text-xs text-slate-600">Filtra per Sorgente</span>
<select wire:model.live="filterSource" class="w-full rounded-lg border-gray-300 text-sm">
<option value="all">Tutte le sorgenti</option>
<option value="tecnorepair">TecnoRepair (TClienti)</option>
<option value="contabilita">Contabilità (Target Cross)</option>
<option value="tickets">Ticket NetGescon</option>
</select>
</label>
</div>
<div class="mt-4 overflow-x-auto">
<table class="min-w-full border-collapse border text-xs">
<thead>
<tr class="bg-slate-100 text-slate-700">
<th class="border px-2 py-2 text-left">Cliente</th>
<th class="border px-2 py-2 text-left">Sorgente</th>
<th class="border px-2 py-2 text-left">Recapiti</th>
<th class="border px-2 py-2 text-left">Zona</th>
<th class="border px-2 py-2 text-left">Schede</th>
<th class="border px-2 py-2 text-left">Rubrica</th>
<th class="border px-2 py-2 text-left">Azioni</th>
</tr>
</thead>
<tbody>
@forelse($rows as $row)
<tr class="{{ ($selectedClienteId ?? 0) === (int) ($row['id'] ?? 0) && (int) ($row['id'] ?? 0) > 0 ? 'bg-sky-50' : 'bg-white hover:bg-slate-50' }}">
<td class="border px-2 py-2 align-top">
<div class="font-medium text-slate-900">{{ $row['display_name'] }}</div>
@if(!empty($row['codice_fiscale']) || !empty($row['partita_iva']))
<div class="text-[10px] text-slate-500 font-mono">{{ $row['codice_fiscale'] ?: $row['partita_iva'] }}</div>
@endif
</td>
<td class="border px-2 py-2 align-top">
@if(($row['source'] ?? '') === 'tecnorepair_tclienti')
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-semibold bg-sky-100 text-sky-800">TecnoRepair</span>
@elseif(($row['source'] ?? '') === 'contabilita_mysql')
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-semibold bg-purple-100 text-purple-800">Contabilità</span>
@elseif(($row['source'] ?? '') === 'netgescon_ticket')
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-semibold bg-emerald-100 text-emerald-800">Ticket</span>
@else
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-semibold bg-slate-100 text-slate-700">{{ $row['source'] }}</span>
@endif
</td>
<td class="border px-2 py-2 align-top">
<div>{{ $row['phone'] !== '' ? $row['phone'] : '-' }}</div>
<div class="text-[11px] text-slate-500">{{ $row['phone_alt'] !== '' ? $row['phone_alt'] : ($row['email'] !== '' ? $row['email'] : 'nessun recapito') }}</div>
</td>
<td class="border px-2 py-2 align-top">
<div>{{ $row['citta'] !== '' ? $row['citta'] : '-' }}</div>
<div class="text-[11px] text-slate-500">{{ $row['indirizzo'] !== '' ? $row['indirizzo'] : '' }}</div>
</td>
<td class="border px-2 py-2 align-top">
<div class="font-medium">{{ $row['totale_schede'] ?? 0 }}</div>
<div class="text-[11px] text-slate-500">Ultima {{ $row['ultima_data'] ?? '-' }}</div>
</td>
<td class="border px-2 py-2 align-top">
@if($row['rubrica_url'])
<a href="{{ $row['rubrica_url'] }}" class="inline-flex items-center rounded-md bg-white px-2 py-1 text-[11px] font-medium text-indigo-700 ring-1 ring-inset ring-indigo-300 hover:bg-indigo-50">Vai al cliente</a>
@else
<span class="text-[11px] text-amber-700">Non collegato</span>
@endif
</td>
<td class="border px-2 py-2 align-top">
@if((int) ($row['id'] ?? 0) > 0)
<button type="button" wire:click="selectCliente({{ (int) $row['id'] }})" class="inline-flex items-center rounded-md bg-slate-800 px-2 py-1 text-[11px] font-medium text-white hover:bg-slate-700">Apri</button>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="7" class="border px-2 py-6 text-center text-sm text-slate-500">Nessun contatto trovato. Clicca su "⚡ Sincronizza Rubrica" per importare da TecnoRepair, Contabilità e Ticket.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@else
@php
$selected = $this->selectedCliente;
@endphp
@if(! $selected)
<div class="rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm text-amber-800">
Seleziona un cliente dall'elenco compatto per aprire la scheda fornitore limitata.
</div>
@else
<div class="grid gap-4 xl:grid-cols-[1.1fr,0.9fr]">
<div class="space-y-4">
<div class="rounded-xl border bg-slate-50 p-4">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Scheda cliente</div>
<div class="mt-2 text-lg font-semibold text-slate-900">{{ $selected->display_name ?: 'Cliente TecnoRepair' }}</div>
<div class="mt-1 text-xs text-slate-500">Legacy cliente ID {{ $selected->legacy_cliente_id ?: '-' }} · aggiornato {{ optional($selected->updated_at)->format('d/m/Y H:i') ?: '-' }}</div>
<div class="mt-4 grid gap-3 sm:grid-cols-2">
<div class="rounded-lg border bg-white px-3 py-2 text-sm">
<div class="text-[11px] font-semibold uppercase tracking-wide text-slate-500">Cellulare</div>
<div class="mt-1">{{ $selected->phone ?: '-' }}</div>
</div>
<div class="rounded-lg border bg-white px-3 py-2 text-sm">
<div class="text-[11px] font-semibold uppercase tracking-wide text-slate-500">Fisso / email</div>
<div class="mt-1">{{ $selected->phone_alt ?: ($selected->email ?: '-') }}</div>
</div>
<div class="rounded-lg border bg-white px-3 py-2 text-sm sm:col-span-2">
<div class="text-[11px] font-semibold uppercase tracking-wide text-slate-500">Indirizzo</div>
<div class="mt-1">{{ trim(implode(', ', array_filter([$selected->indirizzo, $selected->cap, $selected->citta, $selected->provincia]))) !== '' ? trim(implode(', ', array_filter([$selected->indirizzo, $selected->cap, $selected->citta, $selected->provincia]))) : '-' }}</div>
</div>
<div class="rounded-lg border bg-white px-3 py-2 text-sm">
<div class="text-[11px] font-semibold uppercase tracking-wide text-slate-500">Codice fiscale</div>
<div class="mt-1">{{ $selected->codice_fiscale ?: '-' }}</div>
</div>
<div class="rounded-lg border bg-white px-3 py-2 text-sm">
<div class="text-[11px] font-semibold uppercase tracking-wide text-slate-500">P. IVA</div>
<div class="mt-1">{{ $selected->partita_iva ?: '-' }}</div>
</div>
</div>
@if($selected->rubrica_id && $selected->rubrica_url)
<div class="mt-4">
<a href="{{ $selected->rubrica_url }}" class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-indigo-500">Apri vista cliente collegata</a>
</div>
@endif
</div>
<div class="rounded-xl border bg-white p-4">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Storico apparecchi / seriali</div>
<div class="mt-3 overflow-x-auto">
<table class="min-w-full border-collapse border text-xs">
<thead>
<tr class="bg-slate-100 text-slate-700">
<th class="border px-2 py-2 text-left">Scheda</th>
<th class="border px-2 py-2 text-left">Prodotto</th>
<th class="border px-2 py-2 text-left">Seriali</th>
<th class="border px-2 py-2 text-left">Stato</th>
</tr>
</thead>
<tbody>
@forelse($this->selectedClienteSchede as $scheda)
<tr class="bg-white hover:bg-slate-50">
<td class="border px-2 py-2 align-top">
<div class="font-medium">{{ $scheda['numero'] }}</div>
<div class="text-[11px] text-slate-500">{{ $scheda['ingresso'] }}</div>
</td>
<td class="border px-2 py-2 align-top">
<div>{{ $scheda['prodotto'] }}</div>
<div class="text-[11px] text-slate-500">{{ $scheda['codice'] !== '' ? $scheda['codice'] : 'senza codice' }}</div>
</td>
<td class="border px-2 py-2 align-top">{{ $scheda['seriali'] }}</td>
<td class="border px-2 py-2 align-top"><span class="inline-flex rounded-full border px-2 py-1 text-[11px] font-medium {{ $scheda['status_badge'] }}">{{ $scheda['stato'] }}</span></td>
</tr>
@empty
<tr>
<td colspan="4" class="border px-2 py-4 text-center text-slate-500">Nessuna scheda legacy collegata a questo cliente.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
<div class="space-y-4">
<div class="rounded-xl border bg-white p-4">
<div class="text-sm font-semibold">Google workspace fornitore</div>
@if($googleWorkspaceStatus)
<div class="mt-3 space-y-2 text-sm">
<div><span class="font-medium">Stato:</span> {{ $googleWorkspaceStatus['connected'] ? 'Collegato' : 'Non collegato' }}</div>
<div><span class="font-medium">Account:</span> {{ $googleWorkspaceStatus['email'] !== '' ? $googleWorkspaceStatus['email'] : '-' }}</div>
<div><span class="font-medium">Nome:</span> {{ $googleWorkspaceStatus['name'] !== '' ? $googleWorkspaceStatus['name'] : '-' }}</div>
<div><span class="font-medium">Ultimo collegamento:</span> {{ $googleWorkspaceStatus['connected_at'] !== '' ? $googleWorkspaceStatus['connected_at'] : '-' }}</div>
</div>
<div class="mt-3 flex flex-wrap gap-2">
<a href="{{ $this->getGoogleConnectUrl() }}" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50">Collega / aggiorna Google</a>
@if($googleWorkspaceStatus['connected'])
<form method="POST" action="{{ $this->getGoogleDisconnectUrl() }}">
@csrf
<button type="submit" class="inline-flex items-center rounded-md bg-rose-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-rose-500">Scollega</button>
</form>
@endif
</div>
@else
<div class="mt-3 text-sm text-gray-500">Stato Google del fornitore non disponibile.</div>
@endif
</div>
<div class="rounded-xl border bg-slate-50 p-4 text-sm text-slate-700">
Il modello dati prodotti e seriali è già separato: un prodotto unico può avere più seriali collegati. Nella fase successiva si può rifinire la UI della scheda intervento in stile TecnoRepair e riusare la pipeline FE lato fornitore senza auto-import.
</div>
</div>
</div>
@endif
</div>
@endif
</div>
</div>
@endif
</div>
</x-filament-panels::page>