++ fix mobile

This commit is contained in:
Francesco Picone
2026-07-25 23:18:54 +02:00
parent 24a6d3d59f
commit 177523994d
10 changed files with 50 additions and 11 deletions

View File

@@ -147,6 +147,21 @@ assistente e operatore); creazione/modifica/cestino restano su `territori.manage
sono sotto `@can('territori.manage')`; il link "Dettaglio" resta visibile a sono sotto `@can('territori.manage')`; il link "Dettaglio" resta visibile a
tutti. Il menu laterale mostra "Territori" a chi ha `territori.assign`. tutti. Il menu laterale mostra "Territori" a chi ha `territori.assign`.
### Assegnare un territorio ne azzera il flag "prioritario"
`prioritario` è un flag **manuale**; `is_prioritario` è true se il flag è acceso
*oppure* se la giacenza supera la soglia — ma la parte a soglia vale solo per i
territori *in reparto* (`scopePrioritari`/`getIsPrioritarioAttribute` filtrano su
`inReparto`). Quindi un territorio assegnato può risultare prioritario **solo**
per via del flag manuale. Regola: alla creazione di un'assegnazione **aperta** il
flag viene spento. È implementata come evento `Assegnazione::created` (in
`booted()`), guardato su `returned_at === null` e `prioritario === true`, così
copre ogni via di creazione (pagina Assegna, CRUD del Registro, import XML) senza
duplicare la logica. Interazione con l'import XML: per i backup creati dopo questa
regola è un no-op (nessun territorio assegnato è prioritario); su backup vecchi
con stato contraddittorio l'import normalizza il flag anziché riprodurlo tale e
quale.
### Export/Import XML: backup completo e round-trip ### Export/Import XML: backup completo e round-trip
`Livewire/Settings/XmlExchange` esporta e reimporta **tutti** i dati gestionali, `Livewire/Settings/XmlExchange` esporta e reimporta **tutti** i dati gestionali,

View File

@@ -35,6 +35,26 @@ class Assegnazione extends Model
]; ];
} }
protected static function booted(): void
{
// Assegnare un territorio ne azzera il flag "prioritario": una volta in
// carico a un proclamatore (assegnazione aperta) non ha più senso
// segnalarlo come prioritario. La priorità automatica per soglia di
// giacenza riguarda solo i territori in reparto, quindi resta il solo
// flag manuale da spegnere. Vale per ogni via di creazione (pagina
// Assegna, CRUD del Registro, import XML di assegnazioni aperte).
static::created(function (self $assegnazione): void {
if ($assegnazione->returned_at !== null) {
return;
}
$territorio = $assegnazione->territorio;
if ($territorio && $territorio->prioritario) {
$territorio->update(['prioritario' => false]);
}
});
}
// ─── Relationships ───────────────────────────────────────── // ─── Relationships ─────────────────────────────────────────
public function territorio() public function territorio()

View File

@@ -15,7 +15,7 @@
@error('descrizione') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror @error('descrizione') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
</div> </div>
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <div>
<label for="start_date" class="block text-sm font-medium text-gray-700">Data Inizio *</label> <label for="start_date" class="block text-sm font-medium text-gray-700">Data Inizio *</label>
<input wire:model="start_date" type="date" id="start_date" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm" required> <input wire:model="start_date" type="date" id="start_date" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm" required>

View File

@@ -46,7 +46,7 @@
</div> </div>
</td> </td>
<td class="px-4 py-3 text-sm text-right"> <td class="px-4 py-3 text-sm text-right">
<div class="flex items-center justify-end gap-1"> <div class="flex flex-wrap items-center justify-end gap-1">
<a href="{{ route('campagne.show', $campagna) }}" class="btn-action btn-action-indigo" title="Dettaglio"> <a href="{{ route('campagne.show', $campagna) }}" class="btn-action btn-action-indigo" title="Dettaglio">
<svg class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> <svg class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>
</a> </a>

View File

@@ -8,6 +8,7 @@
</div> </div>
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden"> <div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 table-striped"> <table class="min-w-full divide-y divide-gray-200 table-striped">
<thead style="background:linear-gradient(180deg,#f9fafb,#f3f4f6)"> <thead style="background:linear-gradient(180deg,#f9fafb,#f3f4f6)">
<tr> <tr>
@@ -22,7 +23,7 @@
<td class="px-4 py-3 text-sm font-semibold text-gray-900">{{ $proclamatore->nome_completo }}</td> <td class="px-4 py-3 text-sm font-semibold text-gray-900">{{ $proclamatore->nome_completo }}</td>
<td class="px-4 py-3 text-sm text-gray-600">{{ $proclamatore->deleted_at->format('d/m/Y H:i') }}</td> <td class="px-4 py-3 text-sm text-gray-600">{{ $proclamatore->deleted_at->format('d/m/Y H:i') }}</td>
<td class="px-4 py-3 text-sm text-right"> <td class="px-4 py-3 text-sm text-right">
<div class="flex items-center justify-end gap-1"> <div class="flex flex-wrap items-center justify-end gap-1">
<button wire:click="restore({{ $proclamatore->id }})" class="btn-action btn-action-green">Ripristina</button> <button wire:click="restore({{ $proclamatore->id }})" class="btn-action btn-action-green">Ripristina</button>
<button wire:click="forceDelete({{ $proclamatore->id }})" wire:confirm="Eliminare DEFINITIVAMENTE questo proclamatore? Questa azione è irreversibile." class="btn-action btn-action-red">Elimina</button> <button wire:click="forceDelete({{ $proclamatore->id }})" wire:confirm="Eliminare DEFINITIVAMENTE questo proclamatore? Questa azione è irreversibile." class="btn-action btn-action-red">Elimina</button>
</div> </div>
@@ -35,6 +36,7 @@
@endforelse @endforelse
</tbody> </tbody>
</table> </table>
</div>
<div class="px-4 py-3 border-t border-gray-200"> <div class="px-4 py-3 border-t border-gray-200">
{{ $proclamatori->links() }} {{ $proclamatori->links() }}
</div> </div>

View File

@@ -57,7 +57,7 @@
</td> </td>
<td class="px-4 py-3 text-sm text-gray-600">{{ $proclamatore->assegnazioni_aperte_count ?? $proclamatore->assegnazioni()->aperte()->count() }}</td> <td class="px-4 py-3 text-sm text-gray-600">{{ $proclamatore->assegnazioni_aperte_count ?? $proclamatore->assegnazioni()->aperte()->count() }}</td>
<td class="px-4 py-3 text-sm text-right"> <td class="px-4 py-3 text-sm text-right">
<div class="flex items-center justify-end gap-1"> <div class="flex flex-wrap items-center justify-end gap-1">
<a href="{{ route('proclamatori.show', $proclamatore) }}" class="btn-action btn-action-indigo" title="Dettaglio"> <a href="{{ route('proclamatori.show', $proclamatore) }}" class="btn-action btn-action-indigo" title="Dettaglio">
<svg class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg> <svg class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>
</a> </a>

View File

@@ -1,5 +1,5 @@
<div> <div>
<div class="mb-6 flex items-center justify-between"> <div class="mb-6 flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<h1 class="text-2xl font-bold text-gray-900">Registro Assegnazioni</h1> <h1 class="text-2xl font-bold text-gray-900">Registro Assegnazioni</h1>
@can('settings.manage') @can('settings.manage')
<button wire:click="openCreate" class="btn-action btn-action-indigo" style="padding:8px 18px;font-size:14px;border-radius:8px"> <button wire:click="openCreate" class="btn-action btn-action-indigo" style="padding:8px 18px;font-size:14px;border-radius:8px">
@@ -143,7 +143,7 @@
{{ $editingId ? 'Modifica voce' : 'Nuova voce' }} {{ $editingId ? 'Modifica voce' : 'Nuova voce' }}
</h2> </h2>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;"> <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;">
{{-- Territorio --}} {{-- Territorio --}}
<div style="grid-column:1/-1;"> <div style="grid-column:1/-1;">
<label style="font-size:13px;font-weight:600;color:#374151;display:block;margin-bottom:4px;">Territorio *</label> <label style="font-size:13px;font-weight:600;color:#374151;display:block;margin-bottom:4px;">Territorio *</label>

View File

@@ -19,7 +19,7 @@
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden max-w-lg"> <div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden max-w-lg">
<ul class="divide-y divide-gray-200"> <ul class="divide-y divide-gray-200">
@forelse($tipologie as $tipo) @forelse($tipologie as $tipo)
<li class="px-4 py-3 flex items-center justify-between hover:bg-gray-50"> <li class="px-4 py-3 flex flex-wrap items-center justify-between gap-x-2 gap-y-1 hover:bg-gray-50">
@if($editingId === $tipo->id) @if($editingId === $tipo->id)
<form wire:submit="saveEdit" class="flex items-center gap-2 flex-1"> <form wire:submit="saveEdit" class="flex items-center gap-2 flex-1">
<input wire:model="editingNome" type="text" class="flex-1 rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500"> <input wire:model="editingNome" type="text" class="flex-1 rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
@@ -34,7 +34,7 @@
@endif @endif
<span class="text-xs text-gray-400">{{ $tipo->territori()->count() }} territori</span> <span class="text-xs text-gray-400">{{ $tipo->territori()->count() }} territori</span>
</div> </div>
<div class="flex items-center gap-2"> <div class="flex flex-wrap items-center gap-2">
<button wire:click="startEdit({{ $tipo->id }})" class="text-yellow-600 hover:text-yellow-800 text-xs">Rinomina</button> <button wire:click="startEdit({{ $tipo->id }})" class="text-yellow-600 hover:text-yellow-800 text-xs">Rinomina</button>
<button wire:click="toggleActive({{ $tipo->id }})" class="text-xs {{ $tipo->attivo ? 'text-gray-500' : 'text-green-600' }}">{{ $tipo->attivo ? 'Disattiva' : 'Attiva' }}</button> <button wire:click="toggleActive({{ $tipo->id }})" class="text-xs {{ $tipo->attivo ? 'text-gray-500' : 'text-green-600' }}">{{ $tipo->attivo ? 'Disattiva' : 'Attiva' }}</button>
<button wire:click="deleteTipologia({{ $tipo->id }})" wire:confirm="Eliminare la tipologia '{{ $tipo->nome }}'?" class="text-red-500 hover:text-red-700 text-xs">Elimina</button> <button wire:click="deleteTipologia({{ $tipo->id }})" wire:confirm="Eliminare la tipologia '{{ $tipo->nome }}'?" class="text-red-500 hover:text-red-700 text-xs">Elimina</button>

View File

@@ -19,7 +19,7 @@
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden max-w-lg"> <div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden max-w-lg">
<ul class="divide-y divide-gray-200"> <ul class="divide-y divide-gray-200">
@forelse($zone as $zona) @forelse($zone as $zona)
<li class="px-4 py-3 flex items-center justify-between hover:bg-gray-50"> <li class="px-4 py-3 flex flex-wrap items-center justify-between gap-x-2 gap-y-1 hover:bg-gray-50">
@if($editingId === $zona->id) @if($editingId === $zona->id)
<form wire:submit="saveEdit" class="flex items-center gap-2 flex-1"> <form wire:submit="saveEdit" class="flex items-center gap-2 flex-1">
<input wire:model="editingNome" type="text" class="flex-1 rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500"> <input wire:model="editingNome" type="text" class="flex-1 rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
@@ -34,7 +34,7 @@
@endif @endif
<span class="text-xs text-gray-400">{{ $zona->territori()->count() }} territori</span> <span class="text-xs text-gray-400">{{ $zona->territori()->count() }} territori</span>
</div> </div>
<div class="flex items-center gap-2"> <div class="flex flex-wrap items-center gap-2">
<button wire:click="startEdit({{ $zona->id }})" class="text-yellow-600 hover:text-yellow-800 text-xs">Rinomina</button> <button wire:click="startEdit({{ $zona->id }})" class="text-yellow-600 hover:text-yellow-800 text-xs">Rinomina</button>
<button wire:click="toggleActive({{ $zona->id }})" class="text-xs {{ $zona->attivo ? 'text-gray-500' : 'text-green-600' }}">{{ $zona->attivo ? 'Disattiva' : 'Attiva' }}</button> <button wire:click="toggleActive({{ $zona->id }})" class="text-xs {{ $zona->attivo ? 'text-gray-500' : 'text-green-600' }}">{{ $zona->attivo ? 'Disattiva' : 'Attiva' }}</button>
<button wire:click="deleteZona({{ $zona->id }})" wire:confirm="Eliminare la zona '{{ $zona->nome }}'?" class="text-red-500 hover:text-red-700 text-xs">Elimina</button> <button wire:click="deleteZona({{ $zona->id }})" wire:confirm="Eliminare la zona '{{ $zona->nome }}'?" class="text-red-500 hover:text-red-700 text-xs">Elimina</button>

View File

@@ -8,6 +8,7 @@
</div> </div>
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden"> <div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 table-striped"> <table class="min-w-full divide-y divide-gray-200 table-striped">
<thead style="background:linear-gradient(180deg,#f9fafb,#f3f4f6)"> <thead style="background:linear-gradient(180deg,#f9fafb,#f3f4f6)">
<tr> <tr>
@@ -22,7 +23,7 @@
<td class="px-4 py-3 text-sm font-semibold text-gray-900">{{ $territorio->numero }}</td> <td class="px-4 py-3 text-sm font-semibold text-gray-900">{{ $territorio->numero }}</td>
<td class="px-4 py-3 text-sm text-gray-600">{{ $territorio->deleted_at->format('d/m/Y H:i') }}</td> <td class="px-4 py-3 text-sm text-gray-600">{{ $territorio->deleted_at->format('d/m/Y H:i') }}</td>
<td class="px-4 py-3 text-sm text-right"> <td class="px-4 py-3 text-sm text-right">
<div class="flex items-center justify-end gap-1"> <div class="flex flex-wrap items-center justify-end gap-1">
<button wire:click="restore({{ $territorio->id }})" class="btn-action btn-action-green">Ripristina</button> <button wire:click="restore({{ $territorio->id }})" class="btn-action btn-action-green">Ripristina</button>
<button wire:click="forceDelete({{ $territorio->id }})" wire:confirm="Eliminare DEFINITIVAMENTE il territorio {{ $territorio->numero }}? Questa azione è irreversibile." class="btn-action btn-action-red">Elimina</button> <button wire:click="forceDelete({{ $territorio->id }})" wire:confirm="Eliminare DEFINITIVAMENTE il territorio {{ $territorio->numero }}? Questa azione è irreversibile." class="btn-action btn-action-red">Elimina</button>
</div> </div>
@@ -35,6 +36,7 @@
@endforelse @endforelse
</tbody> </tbody>
</table> </table>
</div>
<div class="px-4 py-3 border-t border-gray-200"> <div class="px-4 py-3 border-t border-gray-200">
{{ $territori->links() }} {{ $territori->links() }}
</div> </div>