331 lines
23 KiB
PHP
331 lines
23 KiB
PHP
<x-filament-panels::page wire:poll.8s="refreshLiveCallBanner">
|
|
<div class="space-y-4">
|
|
@if($liveIncomingCall)
|
|
@php($rubricaUrl = $this->getLiveRubricaUrl())
|
|
@php($estrattoUrl = $this->getLiveEstrattoContoUrl())
|
|
<div class="rounded-xl border border-emerald-300 bg-emerald-50 p-4">
|
|
<div class="flex flex-wrap items-start justify-between gap-3">
|
|
<div>
|
|
<div class="text-sm font-semibold text-emerald-900">Chiamata in arrivo in tempo reale</div>
|
|
<div class="mt-1 text-xs text-emerald-800">
|
|
Numero: <span class="font-semibold">{{ $liveIncomingCall['phone'] ?? '-' }}</span>
|
|
@if(!empty($liveIncomingCall['target_extension']))
|
|
· Interno: {{ $liveIncomingCall['target_extension'] }}
|
|
@endif
|
|
@if(!empty($liveIncomingCall['received_at']))
|
|
· Ricevuta: {{ $liveIncomingCall['received_at'] }}
|
|
@endif
|
|
</div>
|
|
@if(!empty($liveIncomingCall['rubrica_nome']))
|
|
<div class="mt-1 text-xs text-emerald-800">Contatto riconosciuto: {{ $liveIncomingCall['rubrica_nome'] }}</div>
|
|
@endif
|
|
@if(!empty($liveIncomingCall['line']))
|
|
<div class="mt-1 text-[11px] text-emerald-700">{{ $this->excerpt((string) $liveIncomingCall['line'], 180) }}</div>
|
|
@endif
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
<x-filament::button size="sm" color="success" wire:click="creaPostItDaChiamataInIngresso">
|
|
Crea Post-it (prima valutazione)
|
|
</x-filament::button>
|
|
|
|
<x-filament::button size="sm" color="gray" wire:click="usaChiamataInIngresso">
|
|
Precompila ticket (opzionale)
|
|
</x-filament::button>
|
|
|
|
@if($liveCallCanClickToCall)
|
|
<x-filament::button size="sm" color="warning" wire:click="richiediClickToCallDaInterno">
|
|
Chiama da interno assegnato
|
|
</x-filament::button>
|
|
@endif
|
|
|
|
@if($rubricaUrl)
|
|
<a href="{{ $rubricaUrl }}" class="inline-flex items-center rounded-md bg-indigo-700 px-3 py-1.5 text-xs font-medium text-white hover:bg-indigo-600">
|
|
Apri scheda rubrica
|
|
</a>
|
|
@endif
|
|
|
|
@if($estrattoUrl)
|
|
<a href="{{ $estrattoUrl }}" class="inline-flex items-center rounded-md bg-slate-800 px-3 py-1.5 text-xs font-medium text-white hover:bg-slate-700" target="_blank" rel="noopener noreferrer">
|
|
Apri estratto conto
|
|
</a>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="rounded-xl border bg-white p-4">
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<a href="{{ $this->getDashboardFilamentUrl() }}" class="inline-flex items-center rounded-md bg-gray-900 px-3 py-1.5 text-xs font-medium text-white hover:bg-gray-700">Dashboard Filament</a>
|
|
<a href="{{ $this->getRubricaFilamentUrl() }}" class="inline-flex items-center rounded-md bg-primary-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-primary-500">Rubrica Unica Filament</a>
|
|
<a href="{{ $this->getAdminMobileHubUrl() }}" class="inline-flex items-center rounded-md bg-emerald-700 px-3 py-1.5 text-xs font-medium text-white hover:bg-emerald-600">Hub Cellulare / WebApp</a>
|
|
<a href="{{ $this->getCondominoMobileTicketUrl() }}" class="inline-flex items-center rounded-md bg-amber-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-amber-500" target="_blank" rel="noopener noreferrer">WebApp Ticket Condomino</a>
|
|
<a href="{{ $this->getTicketArchivioUrl() }}" 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">Archivio Ticket Completo</a>
|
|
</div>
|
|
<div class="mt-3 grid grid-cols-2 gap-2 sm:grid-cols-4">
|
|
<div class="rounded-lg border bg-gray-50 px-3 py-2 text-xs">Aperti: <span class="font-semibold">{{ $ticketCounters['open'] ?? 0 }}</span></div>
|
|
<div class="rounded-lg border bg-gray-50 px-3 py-2 text-xs">Urgenti: <span class="font-semibold">{{ $ticketCounters['urgent'] ?? 0 }}</span></div>
|
|
<div class="rounded-lg border bg-gray-50 px-3 py-2 text-xs">Chiusi: <span class="font-semibold">{{ $ticketCounters['closed'] ?? 0 }}</span></div>
|
|
<div class="rounded-lg border bg-gray-50 px-3 py-2 text-xs">Totali: <span class="font-semibold">{{ $ticketCounters['all'] ?? 0 }}</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="rounded-xl border bg-white p-4">
|
|
<div class="text-sm font-semibold">Ricerca chiamante</div>
|
|
<div class="mt-2 text-xs text-gray-500">Ricerca per telefono, nome, cognome, ragione sociale o email e seleziona il contatto con un click.</div>
|
|
<input type="text" wire:model.live.debounce.300ms="callerSearch" placeholder="Es. +39 333 1234567 oppure Mario Rossi" class="mt-3 w-full rounded-lg border-gray-300 text-sm" />
|
|
|
|
@if($selectedCallerId)
|
|
<div class="mt-2 text-xs text-emerald-700">Contatto selezionato: #{{ $selectedCallerId }}</div>
|
|
@endif
|
|
|
|
@if($callerMatches->count() > 0)
|
|
<div class="mt-3 space-y-2">
|
|
@foreach($callerMatches as $match)
|
|
@php($stabileLabel = $this->getCallerStabileLabel((int) $match->id))
|
|
<button type="button" wire:click="selezionaCaller({{ (int) $match->id }})" class="w-full rounded-lg border p-3 text-left {{ (int) $selectedCallerId === (int) $match->id ? 'border-emerald-400 bg-emerald-50 ring-1 ring-emerald-200' : 'bg-white hover:bg-gray-50' }}">
|
|
<div class="text-sm font-medium">{{ $match->nome_completo ?: ($match->ragione_sociale ?: 'Contatto') }}</div>
|
|
<div class="text-xs text-gray-600">{{ $match->categoria ?: 'altro' }} @if($match->email) · {{ $match->email }} @endif</div>
|
|
@if(($match->duplicate_count ?? 1) > 1)
|
|
<div class="mt-1 text-xs text-amber-700">
|
|
Raggruppati {{ $match->duplicate_count }} record equivalenti
|
|
@if(!empty($match->duplicate_categories))
|
|
· categorie: {{ implode(', ', $match->duplicate_categories) }}
|
|
@endif
|
|
</div>
|
|
@endif
|
|
@if($match->tipo_utenza_call)
|
|
<div class="text-xs text-indigo-700">Profilo: {{ $match->tipo_utenza_call }}</div>
|
|
@endif
|
|
@if($match->riferimento_stabile)
|
|
<div class="text-xs text-indigo-700">Rif. stabile: {{ $match->riferimento_stabile }}</div>
|
|
@endif
|
|
@if($match->riferimento_unita)
|
|
<div class="text-xs text-indigo-700">Rif. unità: {{ $match->riferimento_unita }}</div>
|
|
@endif
|
|
@if($stabileLabel)
|
|
<div class="text-xs text-emerald-700">Stabile: {{ $stabileLabel }}</div>
|
|
@endif
|
|
<div class="mt-1 text-xs text-gray-700">
|
|
{{ $match->telefono_cellulare ?: $match->telefono_ufficio ?: $match->telefono_casa ?: 'Telefono non valorizzato' }}
|
|
</div>
|
|
@if($match->note_segreteria)
|
|
<div class="mt-1 text-xs text-gray-500">{{ $match->note_segreteria }}</div>
|
|
@endif
|
|
</button>
|
|
@endforeach
|
|
</div>
|
|
@elseif(filled($callerSearch))
|
|
<div class="mt-3 text-xs text-gray-500">Nessun contatto trovato con questa ricerca.</div>
|
|
@endif
|
|
|
|
<div class="mt-4 rounded-lg border border-dashed p-3">
|
|
<div class="text-sm font-semibold">Nuovo ticket rapido</div>
|
|
<div class="mt-1 text-xs text-gray-500">Dopo aver selezionato il chiamante, compila e crea il ticket.</div>
|
|
@if($errors->any())
|
|
<div class="mt-3 rounded-lg border border-rose-200 bg-rose-50 px-3 py-2 text-xs text-rose-800">
|
|
<div class="font-semibold">Il ticket non e stato inviato.</div>
|
|
<ul class="mt-1 list-disc ps-4">
|
|
@foreach($errors->all() as $error)
|
|
<li>{{ $error }}</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
@endif
|
|
@php($ticketCallContext = $this->ticketCallContext)
|
|
@if(!empty($ticketCallContext['phone']) || !empty($ticketCallContext['caller_name']) || !empty($ticketCallContext['target_extension']))
|
|
<div class="mt-3 rounded-lg border border-emerald-200 bg-emerald-50 p-3 text-xs text-emerald-900">
|
|
<div class="font-semibold uppercase tracking-wide">Contesto chiamata</div>
|
|
<div class="mt-2 grid gap-2 md:grid-cols-2">
|
|
@if(!empty($ticketCallContext['phone']))
|
|
<div>
|
|
<div class="text-[11px] uppercase tracking-wide text-emerald-700">Numero chiamante</div>
|
|
<div class="text-sm font-semibold">{{ $ticketCallContext['phone'] }}</div>
|
|
</div>
|
|
@endif
|
|
@if(!empty($ticketCallContext['target_extension']))
|
|
<div>
|
|
<div class="text-[11px] uppercase tracking-wide text-emerald-700">Interno o gruppo chiamato</div>
|
|
<div class="text-sm font-semibold">{{ $ticketCallContext['target_extension'] }}</div>
|
|
</div>
|
|
@endif
|
|
@if(!empty($ticketCallContext['received_at']))
|
|
<div>
|
|
<div class="text-[11px] uppercase tracking-wide text-emerald-700">Ricevuta alle</div>
|
|
<div>{{ $ticketCallContext['received_at'] }}</div>
|
|
</div>
|
|
@endif
|
|
@if(!empty($ticketCallContext['caller_name']))
|
|
<div>
|
|
<div class="text-[11px] uppercase tracking-wide text-emerald-700">Contatto associato</div>
|
|
<div>{{ $ticketCallContext['caller_name'] }}</div>
|
|
</div>
|
|
@endif
|
|
@if(!empty($ticketCallContext['caller_profile']))
|
|
<div>
|
|
<div class="text-[11px] uppercase tracking-wide text-emerald-700">Profilo</div>
|
|
<div>{{ $ticketCallContext['caller_profile'] }}</div>
|
|
</div>
|
|
@endif
|
|
@if(!empty($ticketCallContext['riferimento_stabile']))
|
|
<div>
|
|
<div class="text-[11px] uppercase tracking-wide text-emerald-700">Riferimento stabile</div>
|
|
<div>{{ $ticketCallContext['riferimento_stabile'] }}</div>
|
|
</div>
|
|
@endif
|
|
@if(!empty($ticketCallContext['riferimento_unita']))
|
|
<div>
|
|
<div class="text-[11px] uppercase tracking-wide text-emerald-700">Riferimento unità</div>
|
|
<div>{{ $ticketCallContext['riferimento_unita'] }}</div>
|
|
</div>
|
|
@endif
|
|
@if(!empty($ticketCallContext['stabile_label']))
|
|
<div>
|
|
<div class="text-[11px] uppercase tracking-wide text-emerald-700">Stabile collegato</div>
|
|
<div>{{ $ticketCallContext['stabile_label'] }}</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@if(!empty($ticketCallContext['call_note']))
|
|
<div class="mt-2 rounded-md bg-white/70 px-3 py-2 text-[11px] text-emerald-800">
|
|
<div class="font-semibold">Nota operativa importata</div>
|
|
<div class="mt-1 whitespace-pre-wrap">{{ $ticketCallContext['call_note'] }}</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
<div class="mt-3 grid gap-3 md:grid-cols-2">
|
|
<label class="block text-sm md:col-span-2">
|
|
<span class="mb-1 block font-medium">Titolo operativo</span>
|
|
<input type="text" wire:model.defer="newTicketTitolo" class="w-full rounded-lg border-gray-300" placeholder="Es. Guasto ascensore scala B" />
|
|
</label>
|
|
|
|
<label class="block text-sm">
|
|
<span class="mb-1 block font-medium">Priorita</span>
|
|
<select wire:model.defer="newTicketPriorita" class="w-full rounded-lg border-gray-300">
|
|
<option value="Bassa">Bassa</option>
|
|
<option value="Media">Media</option>
|
|
<option value="Alta">Alta</option>
|
|
<option value="Urgente">Urgente</option>
|
|
</select>
|
|
</label>
|
|
|
|
<label class="block text-sm">
|
|
<span class="mb-1 block font-medium">Categoria ticket</span>
|
|
<select wire:model.defer="newTicketCategoriaId" class="w-full rounded-lg border-gray-300">
|
|
<option value="">Seleziona categoria</option>
|
|
@foreach($categorieTicketOptions as $cat)
|
|
<option value="{{ (int) $cat['id'] }}">{{ $cat['nome'] }}</option>
|
|
@endforeach
|
|
</select>
|
|
</label>
|
|
|
|
<label class="block text-sm md:col-span-2">
|
|
<span class="mb-1 block font-medium">Tipo intervento preimpostato</span>
|
|
<select wire:model.defer="newTicketTipoIntervento" class="w-full rounded-lg border-gray-300">
|
|
@foreach($interventiPreimpostati as $code => $label)
|
|
<option value="{{ $code }}">{{ $label }}</option>
|
|
@endforeach
|
|
</select>
|
|
</label>
|
|
|
|
<label class="block text-sm">
|
|
<span class="mb-1 block font-medium">Luogo intervento</span>
|
|
<input type="text" wire:model.defer="newTicketLuogo" class="w-full rounded-lg border-gray-300" placeholder="Es. Scala B - Piano 2" />
|
|
</label>
|
|
|
|
<label class="block text-sm md:col-span-2">
|
|
<span class="mb-1 block font-medium">Descrizione</span>
|
|
<textarea rows="3" wire:model.defer="newTicketDescrizione" class="w-full rounded-lg border-gray-300" placeholder="Descrivi il problema senza ripetere i dati tecnici della chiamata..." ></textarea>
|
|
</label>
|
|
|
|
<label class="block text-sm md:col-span-2">
|
|
<span class="mb-1 block font-medium">Nota generale foto/documentazione (opzionale)</span>
|
|
<textarea rows="2" wire:model.defer="newTicketFotoNote" class="w-full rounded-lg border-gray-300" placeholder="Es. perdita visibile sotto il lavello, foto allegata" ></textarea>
|
|
</label>
|
|
|
|
<label class="block text-sm md:col-span-2">
|
|
<span class="mb-2 block font-medium">Acquisizione foto e allegati</span>
|
|
@if(count($this->selectedUploads) > 0)
|
|
<div class="mb-2 inline-flex items-center rounded-full bg-emerald-100 px-3 py-1 text-[11px] font-semibold text-emerald-800">
|
|
{{ count($this->selectedUploads) }} file gi\u00e0 in coda per questo ticket
|
|
</div>
|
|
@endif
|
|
<div class="flex flex-wrap gap-2">
|
|
<label class="inline-flex cursor-pointer items-center rounded-md bg-emerald-600 px-3 py-2 text-xs font-medium text-white hover:bg-emerald-500">
|
|
Scatta foto
|
|
<input type="file" wire:model="pendingTicketCameraShots" multiple accept="image/*" capture="environment" class="hidden" />
|
|
</label>
|
|
|
|
<label class="inline-flex cursor-pointer items-center rounded-md bg-indigo-600 px-3 py-2 text-xs font-medium text-white hover:bg-indigo-500">
|
|
Aggiungi allegati
|
|
<input type="file" wire:model="pendingTicketAttachments" multiple accept=".pdf,.doc,.docx,.xls,.xlsx,.txt,image/*" class="hidden" />
|
|
</label>
|
|
</div>
|
|
<div class="mt-1 text-xs text-gray-500">Puoi caricare fino a 10 file totali. Ogni nuovo scatto viene accodato senza sostituire i precedenti.</div>
|
|
<div class="mt-1 text-xs text-gray-500">Bozza protocollo corrente: <span class="font-semibold">{{ $newTicketDraftProtocol }}</span></div>
|
|
<div class="mt-1 text-xs text-gray-500">iPhone: su "Aggiungi allegati" scegli "Sfoglia" per aprire l'app File (iCloud Drive/On My iPhone).</div>
|
|
<div wire:loading wire:target="pendingTicketCameraShots,pendingTicketAttachments" class="mt-2 text-xs font-medium text-amber-700">Caricamento in corso: sto accodando foto e allegati alla bozza ticket.</div>
|
|
</label>
|
|
|
|
@if(count($this->selectedUploads) > 0)
|
|
<div class="md:col-span-2">
|
|
<div class="mb-2 text-xs font-semibold text-gray-700">Coda allegati pronta per il ticket</div>
|
|
<div class="grid gap-3 sm:grid-cols-2">
|
|
@foreach($this->selectedUploads as $upload)
|
|
<div class="rounded-xl border bg-white p-3 text-xs shadow-sm">
|
|
<div class="aspect-[4/3] rounded-lg border bg-gray-50 p-2">
|
|
@if($upload['is_image'] && !empty($upload['preview_url']))
|
|
<img src="{{ $upload['preview_url'] }}" alt="{{ $upload['name'] }}" class="h-full w-full rounded object-cover" />
|
|
@else
|
|
<div class="flex h-full items-center justify-center text-center text-gray-500">
|
|
<div>
|
|
<div class="text-sm font-semibold">{{ strtoupper(pathinfo($upload['name'], PATHINFO_EXTENSION) ?: 'FILE') }}</div>
|
|
<div class="mt-1 text-[11px]">{{ $upload['name'] }}</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="mt-2 font-medium">{{ $upload['name'] }}</div>
|
|
<div class="mt-1 text-[11px] text-emerald-700">Protocollo bozza: {{ $upload['protocol'] }}</div>
|
|
@if($upload['original_name'] !== $upload['name'])
|
|
<div class="mt-1 text-[11px] text-gray-500">File origine: {{ $upload['original_name'] }}</div>
|
|
@endif
|
|
<label class="mt-2 block">
|
|
<span class="mb-1 block text-[11px] font-medium">Descrizione foto/allegato</span>
|
|
<input type="text" wire:model.defer="newTicketAttachmentDescriptions.{{ $upload['index'] }}" class="w-full rounded-lg border-gray-300" placeholder="Es. perdita in cucina lato sifone" />
|
|
</label>
|
|
|
|
<button type="button" wire:click="removeNewTicketFile({{ (int) $upload['index'] }})" class="mt-2 inline-flex items-center rounded-md bg-rose-600 px-2 py-1 text-[11px] font-medium text-white hover:bg-rose-500">Rimuovi</button>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
<div class="mt-3">
|
|
<x-filament::button wire:click="creaTicketRapido" wire:loading.attr="disabled" wire:target="creaTicketRapido,pendingTicketCameraShots,pendingTicketAttachments">
|
|
<span wire:loading.remove wire:target="creaTicketRapido">Crea ticket</span>
|
|
<span wire:loading wire:target="creaTicketRapido">Invio ticket...</span>
|
|
</x-filament::button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="rounded-xl border bg-white p-4">
|
|
<div class="text-sm font-semibold">Gestione operativa separata</div>
|
|
<div class="mt-1 text-xs text-gray-500">Per lavorazione, presa in carico, risoluzione e chiusura usa la pagina dedicata.</div>
|
|
<div class="mt-3 flex flex-wrap gap-2">
|
|
<a href="{{ \App\Filament\Pages\Supporto\TicketGestione::getUrl(panel: 'admin-filament') }}" class="inline-flex items-center rounded-md bg-indigo-700 px-3 py-1.5 text-xs font-medium text-white hover:bg-indigo-600">Vai a Gestione Ticket</a>
|
|
<a href="{{ $this->getHelpUrl() }}" 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">Apri Help Ticket Mobile</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-xs text-gray-500">
|
|
Suggerimento: aggiungi questa pagina ai preferiti del browser sul telefono per usarla come webapp rapida.
|
|
</div>
|
|
</div>
|
|
|
|
</x-filament-panels::page>
|