netgescon-day0/resources/views/filament/pages/gescon/fornitore-scheda.blade.php

807 lines
53 KiB
PHP

<x-filament-panels::page>
@php
$tabs = [
'profilo' => 'Dati condivisi',
'accessi' => 'Dipendenti e accessi',
'assistenza' => 'Assistenza interna',
'catalogo' => 'Catalogo e prodotti',
'contabilita' => 'Contabilita',
];
$catalogoActions = [
['action' => 'nuovo_prodotto', 'label' => 'Nuovo prodotto', 'color' => 'gray'],
['action' => 'estrai_prodotti_fe', 'label' => 'Estrai da FE', 'color' => 'primary'],
['action' => 'importa_listino_csv', 'label' => 'Importa listino CSV', 'color' => 'success'],
['action' => 'scarica_asset_catalogo', 'label' => 'Internalizza asset', 'color' => 'warning'],
['action' => 'genera_referral_amazon', 'label' => 'Prepara link Amazon', 'color' => 'gray'],
];
$assistenzaActions = [
['action' => 'impostazioni_fe', 'label' => 'Impostazioni FE', 'color' => 'gray'],
['action' => 'acqua_config', 'label' => 'Configura acqua', 'color' => 'gray'],
['action' => 'acqua_scan', 'label' => 'Scansiona FE acqua', 'color' => 'primary'],
];
@endphp
<div class="space-y-6 overflow-x-hidden" x-data="{ tab: @js($this->sectionTab) }">
<div class="rounded-xl border bg-white p-4">
<div class="flex flex-wrap items-start justify-between gap-4">
<div>
<div class="text-lg font-semibold">Scheda fornitore</div>
<div class="mt-1 text-sm text-slate-600">La scheda e divisa in tab operative per separare dati condivisi, accessi, assistenza, catalogo e contabilita senza perdere il contesto del fornitore.</div>
</div>
<div class="rounded-lg bg-slate-900 px-3 py-2 text-right text-white">
<div class="text-[10px] uppercase tracking-[0.18em] text-slate-300">Fornitore</div>
<div class="text-sm font-semibold">{{ $fornitore->ragione_sociale ?? trim(($fornitore->nome ?? '') . ' ' . ($fornitore->cognome ?? '')) ?: ('Fornitore #' . $fornitore->id) }}</div>
</div>
</div>
<div class="mt-4 flex flex-wrap gap-2">
@foreach($tabs as $tabKey => $tabLabel)
<button
type="button"
wire:click="setSectionTab('{{ $tabKey }}')"
x-on:click="tab = '{{ $tabKey }}'"
class="inline-flex items-center rounded-full px-4 py-2 text-sm font-medium"
x-bind:class="tab === '{{ $tabKey }}' ? 'bg-slate-900 text-white shadow-sm' : 'bg-slate-100 text-slate-700 hover:bg-slate-200'"
>
{{ $tabLabel }}
</button>
@endforeach
</div>
</div>
<div class="rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-700" x-show="tab === 'catalogo'" x-cloak>
Qui restano visibili modulo fornitore e catalogo operativo. Il magazzino e la gestione completa del prodotto possono essere spostati in menu dedicati mantenendo qui il quadro sintetico e i collegamenti rapidi.
</div>
<div class="rounded-xl border border-slate-200 bg-white p-4" x-show="tab === 'catalogo' || tab === 'assistenza'" x-cloak>
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<div class="text-sm font-semibold text-slate-900" x-show="tab === 'catalogo'">Azioni catalogo</div>
<div class="text-sm font-semibold text-slate-900" x-show="tab === 'assistenza'">Azioni automazioni</div>
<div class="mt-1 text-xs text-slate-500" x-show="tab === 'catalogo'">Un solo punto per le azioni operative del catalogo, senza duplicarle in più riquadri.</div>
<div class="mt-1 text-xs text-slate-500" x-show="tab === 'assistenza'">FE e acqua raccolte in una toolbar compatta, così la colonna destra non spinge più il layout.</div>
</div>
<div class="flex max-w-full flex-wrap justify-end gap-2">
@foreach($catalogoActions as $action)
<x-filament::button
x-show="tab === 'catalogo'"
size="sm"
:color="$action['color']"
type="button"
wire:click="mountAction('{{ $action['action'] }}')"
>{{ $action['label'] }}</x-filament::button>
@endforeach
@foreach($assistenzaActions as $action)
<x-filament::button
x-show="tab === 'assistenza'"
size="sm"
:color="$action['color']"
type="button"
wire:click="mountAction('{{ $action['action'] }}')"
>{{ $action['label'] }}</x-filament::button>
@endforeach
</div>
</div>
</div>
<div class="rounded-xl border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-900" x-show="tab === 'assistenza'" x-cloak>
Questa tab concentra TecnoRepair, seriali e automazioni collegate al fornitore. I ticket operativi e il protocollo comunicazioni possono poi evolvere come viste dedicate, senza ricadere in una scheda unica confusa.
</div>
<div class="rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900" x-show="tab === 'contabilita'" x-cloak>
Qui si prepara il perimetro economico del fornitore: pagamenti, fatture, anteprime contabili e ritenute. Preventivi, ordini e fatturazione completa possono innestarsi in questa area senza mischiarsi con catalogo o assistenza.
</div>
<div class="grid min-w-0 grid-cols-1 gap-6 lg:grid-cols-3">
<div class="min-w-0 space-y-6 lg:col-span-2">
<div class="rounded-lg border p-4" x-show="tab === 'profilo'" x-cloak>
<div class="text-lg font-semibold">Fornitore</div>
<div class="mt-2 grid grid-cols-1 gap-2 md:grid-cols-2">
<div><span class="font-medium">Codice:</span> {{ $fornitore->codice_univoco ?? '-' }}</div>
<div><span class="font-medium">Ragione sociale:</span> {{ $fornitore->ragione_sociale ?? '-' }}</div>
<div><span class="font-medium">Nome:</span> {{ trim(($fornitore->nome ?? '') . ' ' . ($fornitore->cognome ?? '')) ?: '-' }}</div>
<div><span class="font-medium">Sito:</span> {{ $fornitore->sito_web ?? '-' }}</div>
<div><span class="font-medium">P.IVA:</span> {{ $fornitore->partita_iva ?? '-' }}</div>
<div><span class="font-medium">CF:</span> {{ $fornitore->codice_fiscale ?? '-' }}</div>
<div class="md:col-span-2"><span class="font-medium">Indirizzo:</span> {{ $fornitore->indirizzo_completo ?? '-' }}</div>
<div class="md:col-span-2"><span class="font-medium">Note:</span> {{ $this->cleanDisplayValue($fornitore->note) }}</div>
</div>
</div>
<div class="rounded-lg border p-4" x-show="tab === 'profilo'" x-cloak>
<div class="text-lg font-semibold">Contatti</div>
<div class="mt-3 grid grid-cols-1 gap-4 md:grid-cols-2">
<div class="space-y-1">
<div class="text-sm font-medium text-gray-700">Fornitore</div>
<div><span class="font-medium">Email:</span> {{ $this->cleanDisplayValue($fornitore->email) }}</div>
<div><span class="font-medium">PEC:</span> {{ $this->cleanDisplayValue($fornitore->pec) }}</div>
<div><span class="font-medium">Telefono:</span> {{ $fornitore->telefono ?? '-' }}</div>
<div><span class="font-medium">Cellulare:</span> {{ $fornitore->cellulare ?? '-' }}</div>
</div>
<div class="space-y-1">
<div class="text-sm font-medium text-gray-700">Rubrica</div>
@if($fornitore->rubrica)
<div><span class="font-medium">Email:</span> {{ $fornitore->rubrica->email ?? '-' }}</div>
<div><span class="font-medium">PEC:</span> {{ $fornitore->rubrica->pec ?? '-' }}</div>
<div><span class="font-medium">Tel. ufficio:</span> {{ $fornitore->rubrica->telefono_ufficio ?? '-' }}</div>
<div><span class="font-medium">Tel. cellulare:</span> {{ $fornitore->rubrica->telefono_cellulare ?? '-' }}</div>
<div><span class="font-medium">Tel. casa:</span> {{ $fornitore->rubrica->telefono_casa ?? '-' }}</div>
<div><span class="font-medium">Fax:</span> {{ $fornitore->rubrica->fax ?? '-' }}</div>
@else
<div class="text-sm text-gray-600">Nessun collegamento presente.</div>
@endif
</div>
</div>
</div>
<div class="rounded-lg border p-4" x-show="tab === 'accessi'" x-cloak>
<div class="text-lg font-semibold">Dipendenti e accessi fornitore</div>
<div class="mt-1 text-xs text-gray-500">La gestione accessi dei dipendenti fornitore e centralizzata qui.</div>
@if(filled($lastGeneratedPassword ?? null))
<div class="mt-3 rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-xs text-amber-900">
Ultima password temporanea generata: <span class="font-mono font-semibold">{{ $lastGeneratedPassword }}</span>
</div>
@endif
<div class="mt-4 rounded-xl border border-slate-200 bg-slate-50 p-3">
<label class="block text-sm">
<span class="mb-1 block font-medium">Ricerca nominativo in anagrafica unica</span>
<input type="text" wire:model.live.debounce.250ms="dipendenteRubricaSearch" class="w-full rounded-lg border-gray-300" placeholder="Ricerca per telefono, nome, cognome, ragione sociale o email e seleziona il contatto con un click. Es. +39 333 1234567 oppure Mario Rossi" />
</label>
<div class="mt-2 text-xs text-gray-500">Usa lo stesso lookup operativo del ticket per agganciare un nominativo già presente nella rubrica unica.</div>
@if($dipendenteRubricaId)
<div class="mt-3 rounded-lg border border-emerald-200 bg-emerald-50 p-3 text-xs text-emerald-800">
Nominativo selezionato: <span class="font-semibold">{{ $dipendenteRubricaSearch }}</span>
<button type="button" wire:click="resetDipendenteRubricaSelection" class="ml-2 inline-flex items-center rounded-md bg-white px-2 py-1 text-[11px] font-medium text-emerald-700 ring-1 ring-inset ring-emerald-300 hover:bg-emerald-100">Cambia</button>
</div>
@endif
@if(count($dipendenteRubricaMatches) > 0)
<div class="mt-3 space-y-2">
@foreach($dipendenteRubricaMatches as $match)
<button type="button" wire:click="selezionaDipendenteRubrica({{ (int) $match['id'] }})" class="w-full rounded-lg border p-3 text-left {{ (int) $dipendenteRubricaId === (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['label'] }}</div>
<div class="mt-1 text-xs text-gray-600">
{{ $match['phone'] ?: 'Telefono non valorizzato' }}
@if($match['email'])
· {{ $match['email'] }}
@endif
@if($match['cf'])
· CF {{ $match['cf'] }}
@endif
</div>
@if($match['category'])
<div class="mt-1 text-xs text-indigo-700">Categoria: {{ $match['category'] }}</div>
@endif
@if($match['note'])
<div class="mt-1 text-xs text-gray-500">{{ $match['note'] }}</div>
@endif
</button>
@endforeach
</div>
@elseif(filled($dipendenteRubricaSearch) && ! $dipendenteRubricaId)
<div class="mt-3 text-xs text-gray-500">Nessun nominativo trovato con questa ricerca.</div>
@endif
<div class="mt-3">
<x-filament::button size="sm" color="primary" type="button" wire:click="collegaDipendenteDaRubrica">Collega nominativo selezionato</x-filament::button>
</div>
</div>
<div class="mt-3 grid grid-cols-1 gap-2 md:grid-cols-4">
<input type="text" wire:model.defer="nuovoDipendenteNome" class="rounded-md border-gray-300 text-xs" placeholder="Nome" />
<input type="text" wire:model.defer="nuovoDipendenteCognome" class="rounded-md border-gray-300 text-xs" placeholder="Cognome" />
<input type="email" wire:model.defer="nuovoDipendenteEmail" class="rounded-md border-gray-300 text-xs" placeholder="Email" />
<input type="text" wire:model.defer="nuovoDipendenteTelefono" class="rounded-md border-gray-300 text-xs" placeholder="Telefono" />
</div>
<div class="mt-2">
<x-filament::button size="sm" color="primary" type="button" wire:click="creaDipendenteFornitore">Aggiungi dipendente</x-filament::button>
</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-1.5 text-left">Dipendente</th>
<th class="border px-2 py-1.5 text-left">Email</th>
<th class="border px-2 py-1.5 text-left">Telefono</th>
<th class="border px-2 py-1.5 text-left">Utente collegato</th>
<th class="border px-2 py-1.5 text-left">Stato</th>
<th class="border px-2 py-1.5 text-left">Azioni</th>
</tr>
</thead>
<tbody>
@forelse($dipendentiRows as $row)
<tr class="hover:bg-slate-50">
<td class="border px-2 py-1.5">{{ $row['nome'] }}</td>
<td class="border px-2 py-1.5">{{ $row['email'] !== '' ? $row['email'] : '-' }}</td>
<td class="border px-2 py-1.5">{{ $row['telefono'] !== '' ? $row['telefono'] : '-' }}</td>
<td class="border px-2 py-1.5">
@if((int) ($row['user_id'] ?? 0) > 0)
{{ $row['user_label'] }} (ID {{ (int) $row['user_id'] }})
@if((int) ($row['rubrica_id'] ?? 0) > 0)
<div class="mt-1 text-[11px] text-slate-500">Rubrica: {{ $row['rubrica'] ?: ('#' . (int) $row['rubrica_id']) }}</div>
@endif
@else
@if((int) ($row['rubrica_id'] ?? 0) > 0)
<div>{{ $row['rubrica'] ?: ('Rubrica #' . (int) $row['rubrica_id']) }}</div>
@else
-
@endif
@endif
</td>
<td class="border px-2 py-1.5">
@if($row['attivo'])
<span class="rounded bg-emerald-100 px-1.5 py-0.5 text-[10px] font-semibold text-emerald-800">attivo</span>
@else
<span class="rounded bg-rose-100 px-1.5 py-0.5 text-[10px] font-semibold text-rose-800">non attivo</span>
@endif
</td>
<td class="border px-2 py-1.5">
<div class="flex flex-wrap gap-1">
<x-filament::button size="xs" color="primary" type="button" wire:click="abilitaAccessoDipendente({{ (int) $row['id'] }})">Abilita accesso</x-filament::button>
@if((int) ($row['user_id'] ?? 0) > 0)
<x-filament::button size="xs" color="warning" type="button" wire:click="resetPasswordDipendenteUser({{ (int) $row['user_id'] }})">Reset password</x-filament::button>
@endif
<x-filament::button size="xs" color="gray" type="button" wire:click="toggleDipendenteAttivo({{ (int) $row['id'] }})">Toggle attivo</x-filament::button>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="border px-2 py-3 text-center text-gray-500">Nessun dipendente registrato per questo fornitore.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
<div class="rounded-lg border p-4" x-show="tab === 'catalogo'" x-cloak>
<div class="flex items-start justify-between gap-4">
<div>
<div class="text-lg font-semibold">Modulo fornitore separato</div>
<div class="mt-1 text-xs text-gray-500">Catalogo isolato per questo fornitore tramite codice univoco, con riferimenti pubblici interni e sorgenti esterne archiviate solo nel gestionale.</div>
</div>
<div class="rounded-md bg-slate-900 px-3 py-2 text-right text-white">
<div class="text-[10px] uppercase tracking-[0.18em] text-slate-300">Scope</div>
<div class="font-mono text-sm font-semibold">{{ $box['catalogo_modulo']['scope_code'] ?? ($fornitore->codice_univoco ?? ('FORN-' . $fornitore->id)) }}</div>
</div>
</div>
<div class="mt-4 grid grid-cols-2 gap-3 md:grid-cols-7">
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Da FE</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['catalogo_modulo']['fe_products'] ?? 0) }}</div>
</div>
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Da CSV</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['catalogo_modulo']['csv_products'] ?? 0) }}</div>
</div>
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Manuali</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['catalogo_modulo']['manual_products'] ?? 0) }}</div>
</div>
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Solo interni</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['catalogo_modulo']['internal_only'] ?? 0) }}</div>
</div>
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Link sorgente</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['catalogo_modulo']['private_links'] ?? 0) }}</div>
</div>
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Offerte</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['catalogo_modulo']['offers'] ?? 0) }}</div>
</div>
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Amazon link</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['catalogo_modulo']['amazon_links'] ?? 0) }}</div>
</div>
</div>
</div>
<div class="rounded-lg border p-4" x-show="tab === 'catalogo'" x-cloak>
<div class="flex items-start justify-between gap-4">
<div>
<div class="text-lg font-semibold">Catalogo operativo interno</div>
<div class="mt-1 text-xs text-gray-500">Anagrafica prodotti/servizi del fornitore. I riferimenti esterni importati restano interni al gestionale e la pubblicazione usa il codice interno del catalogo.</div>
</div>
<div class="rounded-md bg-slate-100 px-3 py-2 text-xs text-slate-600">Le azioni operative sono state raccolte sopra.</div>
</div>
<div class="mt-4 grid grid-cols-2 gap-3 md:grid-cols-4">
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Prodotti</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['prodotti']['count'] ?? 0) }}</div>
</div>
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Serializzati</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['prodotti']['serializzati'] ?? 0) }}</div>
</div>
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Codici agganciati</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['prodotti']['identifiers'] ?? 0) }}</div>
</div>
<div class="rounded-md bg-slate-50 p-3">
<div class="text-[11px] uppercase tracking-wide text-slate-500">Media</div>
<div class="mt-1 text-xl font-semibold text-slate-900">{{ (int) ($box['prodotti']['with_media'] ?? 0) }}</div>
</div>
</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-1.5 text-left">Codice</th>
<th class="border px-2 py-1.5 text-left">Prodotto</th>
<th class="border px-2 py-1.5 text-left">Marca / modello</th>
<th class="border px-2 py-1.5 text-left">Origine</th>
<th class="border px-2 py-1.5 text-left">Rif. interno</th>
<th class="border px-2 py-1.5 text-left">Codici</th>
<th class="border px-2 py-1.5 text-left">Seriali</th>
<th class="border px-2 py-1.5 text-left">Offerte</th>
<th class="border px-2 py-1.5 text-left">Catalogo</th>
</tr>
</thead>
<tbody>
@forelse($catalogoProdottiRows as $row)
<tr class="hover:bg-slate-50">
<td class="border px-2 py-1.5 font-medium">{{ $row['internal_code'] !== '' ? $row['internal_code'] : '-' }}</td>
<td class="border px-2 py-1.5">
<div>{{ $row['name'] !== '' ? $row['name'] : '-' }}</div>
@if($row['color_label'] !== '')
<div class="text-[11px] text-slate-500">Colore: {{ $row['color_label'] }}</div>
@endif
</td>
<td class="border px-2 py-1.5">{{ trim(($row['brand'] ?? '') . ' ' . ($row['model'] ?? '')) ?: '-' }}</td>
<td class="border px-2 py-1.5">
@if(($row['source'] ?? '') === 'fattura_elettronica')
<span class="rounded bg-sky-100 px-1.5 py-0.5 text-[10px] font-semibold text-sky-800">FE</span>
@elseif(($row['source'] ?? '') === 'ncom_wholesale_csv')
<span class="rounded bg-emerald-100 px-1.5 py-0.5 text-[10px] font-semibold text-emerald-800">CSV</span>
@else
<span class="rounded bg-slate-100 px-1.5 py-0.5 text-[10px] font-semibold text-slate-700">manuale</span>
@endif
</td>
<td class="border px-2 py-1.5">
<div class="font-mono">{{ $row['public_reference'] !== '' ? $row['public_reference'] : '-' }}</div>
@if(($row['publication_mode'] ?? '') === 'internal_only')
<div class="text-[11px] text-slate-500">solo interno</div>
@endif
</td>
<td class="border px-2 py-1.5">{{ (int) ($row['identifiers_count'] ?? 0) }}</td>
<td class="border px-2 py-1.5">
{{ (int) ($row['serials_count'] ?? 0) }}
@if($row['track_serials'])
<span class="ml-1 rounded bg-sky-100 px-1.5 py-0.5 text-[10px] font-semibold text-sky-800">track</span>
@endif
</td>
<td class="border px-2 py-1.5">
<div>{{ (int) ($row['offers_count'] ?? 0) }} totali</div>
<div class="text-[11px] text-slate-500">
@if(($row['own_offer_price'] ?? null) !== null)
tuo {{ number_format((float) $row['own_offer_price'], 2, ',', '.') }}
@else
tuo n/d
@endif
</div>
<div class="text-[11px] text-slate-500">
@if(($row['best_competitor_price'] ?? null) !== null)
competitor {{ number_format((float) $row['best_competitor_price'], 2, ',', '.') }}
@if(($row['best_competitor_source'] ?? '') !== '')
| {{ $row['best_competitor_source'] }}
@endif
@else
competitor n/d
@endif
</div>
@if(($row['amazon_referral_url'] ?? '') !== '')
<div class="text-[11px] text-slate-500">Amazon referral pronto</div>
@endif
</td>
<td class="border px-2 py-1.5">
<div>Link sorgente: {{ (int) ($row['private_links'] ?? 0) }}</div>
<div class="text-[11px] text-slate-500">
@if(($row['price_wholesale'] ?? null) !== null)
{{ number_format((float) $row['price_wholesale'], 2, ',', '.') }}
@else
prezzo n/d
@endif
@if(($row['stock_quantity'] ?? null) !== null)
| stock {{ (int) $row['stock_quantity'] }}
@endif
</div>
@if(($row['categories'] ?? '') !== '')
<div class="truncate text-[11px] text-slate-500">{{ $row['categories'] }}</div>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="9" class="border px-2 py-3 text-center text-gray-500">Nessun prodotto presente per questo fornitore.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
<div class="rounded-lg border p-4" x-show="tab === 'profilo' || tab === 'contabilita'" x-cloak>
<div class="text-lg font-semibold">Pagamenti</div>
<div class="mt-2 grid grid-cols-1 gap-2 md:grid-cols-2">
<div><span class="font-medium">IBAN:</span> {{ $fornitore->iban ?? '-' }}</div>
<div><span class="font-medium">BIC:</span> {{ $fornitore->bic ?? '-' }}</div>
<div class="md:col-span-2"><span class="font-medium">Modalità predefinita:</span> {{ $fornitore->modalita_pagamento_predefinita ?? '-' }}</div>
</div>
</div>
<div class="rounded-lg border p-4" x-show="tab === 'profilo'" x-cloak>
<div class="text-lg font-semibold">Anagrafica unica (Rubrica)</div>
@if($fornitore->rubrica)
<div class="mt-2 grid grid-cols-1 gap-2 md:grid-cols-2">
<div><span class="font-medium">Codice:</span> {{ $fornitore->rubrica->codice_univoco ?? '-' }}</div>
<div><span class="font-medium">Nominativo:</span> {{ $fornitore->rubrica->nome_completo ?? '-' }}</div>
<div><span class="font-medium">Categoria:</span> {{ $fornitore->rubrica->categoria ?? '-' }}</div>
<div><span class="font-medium">Stato:</span> {{ $fornitore->rubrica->stato ?? '-' }}</div>
</div>
@else
<div class="mt-2 text-sm text-gray-600">Nessun collegamento presente.</div>
@endif
</div>
<div class="rounded-lg border p-4" x-data="fornitoreTagsBox(@js($tagSuggestions))" x-show="tab === 'profilo'" x-cloak>
<div class="text-lg font-semibold">TAG Fornitore</div>
<div class="mt-1 text-xs text-gray-500">Digita tag separati da virgola. Premi TAB per accettare il suggerimento corrente e aggiungere automaticamente una virgola.</div>
<div class="mt-3">
<input
id="fornitore-tags-input"
type="text"
list="fornitore-tags-suggestions"
wire:model.defer="tagsInput"
autocomplete="off"
class="w-full rounded-lg border-gray-300 text-sm"
placeholder="es. idr, manut, assicur..."
x-on:input="updateSuggestion($event.target.value)"
x-on:keydown.tab.prevent="acceptSuggestion($event.target)"
x-on:keydown.comma="clearHint()"
/>
<datalist id="fornitore-tags-suggestions">
@foreach($tagSuggestions as $tag)
<option value="{{ $tag }}"></option>
@endforeach
</datalist>
<div class="mt-1 text-xs text-gray-500" x-show="hint !== ''" x-text="'Suggerimento: ' + hint"></div>
</div>
<div class="mt-3 flex flex-wrap gap-2">
<x-filament::button color="primary" type="button" wire:click="saveTags">Salva TAG</x-filament::button>
<x-filament::button color="gray" type="button" wire:click="importLegacyTags">Importa da legacy</x-filament::button>
</div>
</div>
</div>
<div class="min-w-0 space-y-6">
@php
$features = is_array($box['fornitore_features'] ?? null) ? $box['fornitore_features'] : [];
$acqua = is_array($features['acqua'] ?? null) ? $features['acqua'] : [];
$acquaEnabled = (bool) ($acqua['enabled'] ?? false);
$acquaScan = (bool) ($acqua['scan_enabled'] ?? false);
@endphp
<div class="rounded-lg border p-4" x-show="tab === 'assistenza'" x-cloak>
<div class="flex items-start justify-between gap-4">
<div>
<div class="text-base font-semibold">TecnoRepair / seriali</div>
<div class="mt-1 text-sm text-gray-600">Import MDB in anagrafica fornitore e aggancio automatico di seriali e prodotti assistenza.</div>
</div>
<x-filament::button size="sm" color="gray" type="button" wire:click="mountAction('importa_tecnorepair')">
Importa TecnoRepair
</x-filament::button>
</div>
<div class="mt-4 grid grid-cols-2 gap-3 text-sm">
<div class="flex items-center justify-between rounded-md bg-slate-50 px-3 py-2">
<span>Schede</span>
<span class="font-semibold">{{ (int) ($box['tecnorepair']['schede'] ?? 0) }}</span>
</div>
<div class="flex items-center justify-between rounded-md bg-slate-50 px-3 py-2">
<span>Aperte / attesa</span>
<span class="font-semibold">{{ (int) ($box['tecnorepair']['aperte'] ?? 0) }}</span>
</div>
<div class="flex items-center justify-between rounded-md bg-slate-50 px-3 py-2">
<span>Chiuse</span>
<span class="font-semibold">{{ (int) ($box['tecnorepair']['chiuse'] ?? 0) }}</span>
</div>
<div class="flex items-center justify-between rounded-md bg-slate-50 px-3 py-2">
<span>Seriali</span>
<span class="font-semibold">{{ (int) ($box['tecnorepair']['seriali'] ?? 0) }}</span>
</div>
</div>
<div class="mt-4 space-y-2 text-sm">
@forelse($tecnorepairRows as $row)
<div class="rounded-md border px-3 py-2">
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="font-medium">{{ $row['legacy_numero'] !== '' ? $row['legacy_numero'] : ('Scheda #' . $row['id']) }}</div>
<div class="truncate text-gray-600">{{ $row['product_model'] !== '' ? $row['product_model'] : '-' }}</div>
<div class="truncate text-xs text-gray-500">Codice: {{ $row['product_code'] !== '' ? $row['product_code'] : '-' }} | Seriale: {{ $row['serial_number'] !== '' ? $row['serial_number'] : '-' }}</div>
</div>
<div class="text-right">
<div class="rounded px-2 py-0.5 text-[10px] font-semibold {{ ($row['status_bucket'] ?? '') === 'closed' ? 'bg-emerald-100 text-emerald-800' : ((($row['status_bucket'] ?? '') === 'waiting') ? 'bg-amber-100 text-amber-800' : 'bg-rose-100 text-rose-800') }}">
{{ $row['status_label'] !== '' ? $row['status_label'] : ($row['status_bucket'] !== '' ? $row['status_bucket'] : 'stato') }}
</div>
<div class="mt-1 text-xs text-gray-500">Allegati: {{ (int) ($row['allegati_count'] ?? 0) }}</div>
</div>
</div>
</div>
@empty
<div class="text-sm text-gray-600">Nessuna scheda TecnoRepair collegata a questo fornitore.</div>
@endforelse
</div>
</div>
<div class="rounded-lg border p-4" x-show="tab === 'assistenza'" x-cloak>
<div class="text-base font-semibold">Automazioni / Consumi</div>
<div class="mt-1 text-sm text-gray-600">Configura acquisizione dati (PDF) e scansione massiva sulle FE già importate.</div>
<div class="mt-3 space-y-1 text-sm">
<div class="flex items-center justify-between">
<span class="font-medium">Acqua</span>
<span>{{ $acquaEnabled ? 'ATTIVA' : 'disattiva' }}</span>
</div>
<div class="flex items-center justify-between">
<span class="font-medium">Scansione batch</span>
<span>{{ $acquaScan ? 'ATTIVA' : 'disattiva' }}</span>
</div>
<div class="flex items-center justify-between">
<span class="font-medium">Righe FE</span>
<span>{{ (bool) ($fornitore->escludi_righe_fe ?? false) ? 'escluse' : 'incluse' }}</span>
</div>
</div>
<div class="mt-4 rounded-md bg-slate-100 px-3 py-2 text-xs text-slate-600">Le azioni FE/acqua sono state raccolte nella toolbar in alto.</div>
</div>
<div class="rounded-lg border p-4" x-show="tab === 'contabilita'" x-cloak>
<div class="flex items-start justify-between gap-4">
<div>
<div class="text-lg font-semibold">Fatture (stabile attivo)</div>
<div class="text-sm text-gray-600">Riepilogo AdE / FE / Contabilità / RA</div>
</div>
<a
class="text-sm font-medium text-primary-600 hover:underline"
href="{{ \App\Filament\Pages\Contabilita\FattureElettronicheP7mRicevute::getUrl(panel: 'admin-filament') }}"
>
Apri FE
</a>
</div>
<div class="mt-4 space-y-2 text-sm">
<div class="flex items-center justify-between">
<span class="font-semibold">Totale da pagare</span>
<span class="font-semibold">{{ number_format((float) ($box['da_pagare']['importo'] ?? 0), 2, ',', '.') }} </span>
</div>
<div class="text-xs text-gray-600">
Fonte: {{ (string) ($box['da_pagare']['source'] ?? 'n/d') }}
</div>
<div class="border-t pt-2"></div>
<div class="flex items-center justify-between">
<span class="font-medium">AdE (staging)</span>
<span>{{ (int) ($box['ade']['count'] ?? 0) }} {{ number_format((float) ($box['ade']['lordo'] ?? 0), 2, ',', '.') }} </span>
</div>
<div class="flex items-center justify-between">
<span class="font-medium">FE importate</span>
<span>{{ (int) ($box['fe']['count'] ?? 0) }} {{ number_format((float) ($box['fe']['totale'] ?? 0), 2, ',', '.') }} </span>
</div>
<div class="flex items-center justify-between">
<span class="font-medium">FE contabilizzate</span>
<span>{{ (int) ($box['fe']['contabilizzate'] ?? 0) }}</span>
</div>
<div class="mt-2 border-t pt-2">
<div class="flex items-center justify-between">
<span class="font-medium">Da pagare (contabilità)</span>
<span>{{ (int) ($box['contabilita']['aperte_count'] ?? 0) }} {{ number_format((float) ($box['contabilita']['aperte_netto'] ?? 0), 2, ',', '.') }} </span>
</div>
<div class="flex items-center justify-between">
<span class="font-medium">Pagate (contabilità)</span>
<span>{{ (int) ($box['contabilita']['pagate_count'] ?? 0) }} {{ number_format((float) ($box['contabilita']['pagate_netto'] ?? 0), 2, ',', '.') }} </span>
</div>
</div>
<div class="mt-2 border-t pt-2">
<div class="flex items-center justify-between">
<span class="font-medium">RA da versare</span>
<span>{{ number_format((float) ($box['ra']['da_versare'] ?? 0), 2, ',', '.') }} </span>
</div>
<div class="flex items-center justify-between">
<span class="font-medium">RA versata</span>
<span>{{ number_format((float) ($box['ra']['versata'] ?? 0), 2, ',', '.') }} </span>
</div>
<div class="flex items-center justify-between">
<span class="font-medium">RA compensata</span>
<span>{{ number_format((float) ($box['ra']['compensata'] ?? 0), 2, ',', '.') }} </span>
</div>
</div>
</div>
</div>
<div class="rounded-lg border p-4" x-show="tab === 'contabilita'" x-cloak>
<div class="text-base font-semibold">Anteprima AdE</div>
@if(!empty($anteprimaAde))
<div class="mt-3 space-y-2 text-sm">
@foreach($anteprimaAde as $r)
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="font-medium">{{ $r['data'] ?: '-' }} {{ $r['numero'] ?: '-' }}</div>
<div class="truncate text-gray-600">SDI: {{ $r['sdi_file'] ?: '-' }}</div>
</div>
<div class="whitespace-nowrap">{{ number_format((float) ($r['lordo'] ?? 0), 2, ',', '.') }} </div>
</div>
@endforeach
</div>
@else
<div class="mt-2 text-sm text-gray-600">Nessuna fattura AdE trovata per questo fornitore.</div>
@endif
</div>
<div class="rounded-lg border p-4" x-show="tab === 'contabilita'" x-cloak>
<div class="text-base font-semibold">Anteprima FE</div>
@if(!empty($anteprimaFe))
<div class="mt-3 space-y-2 text-sm">
@foreach($anteprimaFe as $r)
<a
class="block rounded-md px-2 py-1 hover:bg-gray-50"
href="{{ \App\Filament\Pages\Contabilita\FatturaElettronicaScheda::getUrl(['record' => (int) $r['id']], panel: 'admin-filament') }}"
>
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="font-medium">{{ $r['data'] ?: '-' }} {{ $r['numero'] ?: '-' }}</div>
<div class="truncate text-gray-600">SDI: {{ $r['sdi_file'] ?: '-' }} @if(($r['stato'] ?? '') !== '') {{ $r['stato'] }} @endif</div>
</div>
<div class="whitespace-nowrap">{{ number_format((float) ($r['totale'] ?? 0), 2, ',', '.') }} </div>
</div>
</a>
@endforeach
</div>
@else
<div class="mt-2 text-sm text-gray-600">Nessuna FE importata trovata per questo fornitore.</div>
@endif
</div>
<div class="rounded-lg border p-4" x-show="tab === 'contabilita'" x-cloak>
<div class="text-base font-semibold">Anteprima contabilità</div>
@if(!empty($anteprimaContabilita))
<div class="mt-3 space-y-2 text-sm">
@foreach($anteprimaContabilita as $r)
<a
class="block rounded-md px-2 py-1 hover:bg-gray-50"
href="{{ \App\Filament\Pages\Contabilita\FatturaFornitoreScheda::getUrl(['record' => (int) $r['id']], panel: 'admin-filament') }}"
>
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="font-medium">{{ $r['data'] ?: '-' }} {{ $r['numero'] ?: '-' }}</div>
<div class="truncate text-gray-600">Stato: {{ $r['stato'] ?: '-' }}</div>
</div>
<div class="whitespace-nowrap">{{ number_format((float) ($r['netto'] ?? 0), 2, ',', '.') }} </div>
</div>
</a>
@endforeach
</div>
@else
<div class="mt-2 text-sm text-gray-600">Nessuna registrazione contabile trovata per questo fornitore.</div>
@endif
</div>
<div class="rounded-lg border p-4" x-show="tab === 'contabilita'" x-cloak>
<div class="text-base font-semibold">Fatture associate (fornitore)</div>
@if(!empty($fattureAssociate))
<div class="mt-3 space-y-2 text-sm">
@foreach($fattureAssociate as $r)
<a
class="block rounded-md px-2 py-1 hover:bg-gray-50"
href="{{ \App\Filament\Pages\Contabilita\FatturaFornitoreScheda::getUrl(['record' => (int) $r['id']], panel: 'admin-filament') }}"
>
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="font-medium">{{ $r['data'] ?: '-' }} {{ $r['numero'] ?: '-' }}</div>
<div class="truncate text-gray-600">{{ $r['source'] }} @if(($r['stato'] ?? '') !== '') {{ $r['stato'] }} @endif</div>
</div>
<div class="whitespace-nowrap text-right">
<div>{{ number_format((float) ($r['totale'] ?? 0), 2, ',', '.') }} </div>
<div class="text-xs text-gray-500">Netto {{ number_format((float) ($r['netto'] ?? 0), 2, ',', '.') }} </div>
</div>
</div>
</a>
@endforeach
</div>
@else
<div class="mt-2 text-sm text-gray-600">Nessuna fattura associata trovata per questo fornitore.</div>
@endif
</div>
<div class="rounded-lg border p-4" x-show="tab === 'contabilita'" x-cloak>
<div class="text-base font-semibold">RA versate/compensate</div>
@if(!empty($raVersateRows))
<div class="mt-3 space-y-2 text-sm">
@foreach($raVersateRows as $ra)
<div class="rounded-md px-2 py-1">
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="font-medium">{{ $ra['data_versamento'] ?: '-' }} {{ strtoupper($ra['stato'] ?: '-') }}</div>
<div class="truncate text-gray-600">Tributo {{ $ra['tributo'] ?: '1040' }} @if(($ra['f24'] ?? '') !== '') F24 {{ $ra['f24'] }} @endif</div>
</div>
<div class="whitespace-nowrap">{{ number_format((float) ($ra['importo'] ?? 0), 2, ',', '.') }} </div>
</div>
</div>
@endforeach
</div>
@else
<div class="mt-2 text-sm text-gray-600">Nessuna RA versata/compensata trovata per questo fornitore.</div>
@endif
</div>
</div>
</div>
</div>
<script>
function fornitoreTagsBox(suggestions) {
return {
hint: '',
suggestions: Array.isArray(suggestions) ? suggestions : [],
clearHint() {
this.hint = '';
},
updateSuggestion(value) {
const token = this.currentToken(value);
if (!token) {
this.hint = '';
return;
}
const lower = token.toLowerCase();
const found = this.suggestions.find((item) => item.toLowerCase().startsWith(lower));
this.hint = found && found.toLowerCase() !== lower ? found : '';
},
acceptSuggestion(inputEl) {
const value = inputEl.value || '';
const token = this.currentToken(value);
if (!token) {
inputEl.value = value.endsWith(',') ? value : value + ', ';
inputEl.dispatchEvent(new Event('input'));
this.hint = '';
return;
}
const lower = token.toLowerCase();
const found = this.suggestions.find((item) => item.toLowerCase().startsWith(lower));
if (!found) {
inputEl.value = value.endsWith(',') ? value : value + ', ';
inputEl.dispatchEvent(new Event('input'));
this.hint = '';
return;
}
const idx = value.lastIndexOf(',');
const prefix = idx >= 0 ? value.slice(0, idx + 1) : '';
const next = (prefix ? prefix + ' ' : '') + found + ', ';
inputEl.value = next;
inputEl.dispatchEvent(new Event('input'));
this.hint = '';
},
currentToken(value) {
const idx = value.lastIndexOf(',');
const token = idx >= 0 ? value.slice(idx + 1) : value;
return token.trim();
},
};
}
</script>
</x-filament-panels::page>