Primo commit
This commit is contained in:
46
resources/views/livewire/assegnazioni/assegna.blade.php
Normal file
46
resources/views/livewire/assegnazioni/assegna.blade.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Assegna Territorio</h1>
|
||||
<a href="{{ route('territori.index') }}" class="text-sm text-indigo-600 hover:text-indigo-800">← Torna ai territori</a>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 max-w-lg">
|
||||
<form wire:submit="save" class="space-y-4">
|
||||
<div>
|
||||
<label for="territorio_id" class="block text-sm font-medium text-gray-700">Territorio *</label>
|
||||
<select wire:model="territorio_id" id="territorio_id" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm" @if($preselectedTerritorioId) disabled @endif>
|
||||
<option value="">Seleziona un territorio</option>
|
||||
@foreach($territoriDisponibili as $t)
|
||||
<option value="{{ $t->id }}">N° {{ $t->numero }} — {{ $t->zona?->nome }} ({{ $t->tipologia?->nome }})</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@if($preselectedTerritorioId)
|
||||
<input type="hidden" wire:model="territorio_id" value="{{ $preselectedTerritorioId }}">
|
||||
@endif
|
||||
@error('territorio_id') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="proclamatore_id" class="block text-sm font-medium text-gray-700">Proclamatore *</label>
|
||||
<select wire:model="proclamatore_id" id="proclamatore_id" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||
<option value="">Seleziona un proclamatore</option>
|
||||
@foreach($proclamatoriAttivi as $p)
|
||||
<option value="{{ $p->id }}">{{ $p->cognome }} {{ $p->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('proclamatore_id') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="assigned_at" class="block text-sm font-medium text-gray-700">Data Assegnazione *</label>
|
||||
<input wire:model="assigned_at" type="date" id="assigned_at" max="{{ now()->format('Y-m-d') }}" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||
@error('assigned_at') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3 pt-4">
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">Assegna</button>
|
||||
<a href="{{ route('territori.index') }}" class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition">Annulla</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
60
resources/views/livewire/assegnazioni/rientra.blade.php
Normal file
60
resources/views/livewire/assegnazioni/rientra.blade.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Rientro Territorio</h1>
|
||||
<a href="{{ route('territori.show', $assegnazione->territorio) }}" class="text-sm text-indigo-600 hover:text-indigo-800">← Torna al territorio</a>
|
||||
</div>
|
||||
|
||||
{{-- Assignment summary --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4 mb-6">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Territorio</p>
|
||||
<p class="mt-1 text-lg font-bold text-gray-900">N° {{ $assegnazione->territorio->numero }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Proclamatore</p>
|
||||
<p class="mt-1 text-sm text-gray-900">{{ $assegnazione->proclamatore->nome_completo }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Assegnato il</p>
|
||||
<p class="mt-1 text-sm text-gray-900">{{ $assegnazione->assigned_at->format('d/m/Y') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 max-w-lg">
|
||||
<form wire:submit="save" class="space-y-4">
|
||||
<div>
|
||||
<label for="returned_at" class="block text-sm font-medium text-gray-700">Data Rientro *</label>
|
||||
<input wire:model.live="returned_at" type="date" id="returned_at"
|
||||
min="{{ $assegnazione->assigned_at->format('Y-m-d') }}"
|
||||
max="{{ now()->format('Y-m-d') }}"
|
||||
class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||
@error('returned_at') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
{{-- Campaign retroactive prompt --}}
|
||||
@if($showCampaignPrompt && $campagna)
|
||||
<div class="bg-amber-50 border border-amber-200 rounded-lg p-4">
|
||||
<p class="text-sm font-medium text-amber-800 mb-2">
|
||||
⚠️ Campagna Attiva: <strong>{{ $campagna->descrizione }}</strong>
|
||||
</p>
|
||||
<p class="text-xs text-amber-700 mb-3">
|
||||
Questo territorio è stato assegnato durante la campagna "{{ $campagna->descrizione }}"
|
||||
({{ $campagna->start_date->format('d/m/Y') }} — {{ $campagna->end_date->format('d/m/Y') }}).
|
||||
Vuoi conteggiarlo nella percentuale di percorrenza?
|
||||
</p>
|
||||
<div class="flex items-center gap-2">
|
||||
<input wire:model="counted_in_campaign" type="checkbox" id="counted_in_campaign" class="rounded border-gray-300 text-amber-600 focus:ring-amber-500">
|
||||
<label for="counted_in_campaign" class="text-sm text-amber-800">Sì, conteggia in campagna</label>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="flex items-center gap-3 pt-4">
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-green-600 rounded-lg hover:bg-green-700 transition">Registra Rientro</button>
|
||||
<a href="{{ route('territori.show', $assegnazione->territorio) }}" class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition">Annulla</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
108
resources/views/livewire/audit-log.blade.php
Normal file
108
resources/views/livewire/audit-log.blade.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Audit Log</h1>
|
||||
<p class="text-sm text-gray-500">Registro di tutte le azioni eseguite nel sistema.</p>
|
||||
</div>
|
||||
|
||||
{{-- Filters --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4 mb-4">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
|
||||
<input wire:model.live.debounce.300ms="search" type="text" placeholder="Cerca..." class="rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<select wire:model.live="filterEvent" class="rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutti gli eventi</option>
|
||||
@foreach($events as $event)
|
||||
<option value="{{ $event }}">{{ $event }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<select wire:model.live="filterCauser" class="rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutti gli utenti</option>
|
||||
@foreach($users as $user)
|
||||
<option value="{{ $user->id }}">{{ $user->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Table --}}
|
||||
<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 text-sm">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase">Data/Ora</th>
|
||||
<th class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase">Utente</th>
|
||||
<th class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase">Evento</th>
|
||||
<th class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase">Soggetto</th>
|
||||
<th class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase">Dettagli</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
@forelse($activities as $activity)
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td class="px-3 py-2 text-xs text-gray-500 whitespace-nowrap">{{ $activity->created_at->format('d/m/Y H:i:s') }}</td>
|
||||
<td class="px-3 py-2 text-xs">{{ $activity->causer?->name ?? 'Sistema' }}</td>
|
||||
<td class="px-3 py-2">
|
||||
<span class="inline-flex px-2 py-0.5 text-xs font-medium rounded-full
|
||||
{{ match($activity->description) {
|
||||
'created' => 'bg-green-100 text-green-800',
|
||||
'updated' => 'bg-blue-100 text-blue-800',
|
||||
'deleted' => 'bg-red-100 text-red-800',
|
||||
'assigned' => 'bg-indigo-100 text-indigo-800',
|
||||
'returned' => 'bg-amber-100 text-amber-800',
|
||||
'restored' => 'bg-purple-100 text-purple-800',
|
||||
'login' => 'bg-cyan-100 text-cyan-800',
|
||||
default => 'bg-gray-100 text-gray-700',
|
||||
} }}">
|
||||
{{ $activity->description }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-3 py-2 text-xs text-gray-600">
|
||||
@if($activity->subject_type)
|
||||
{{ class_basename($activity->subject_type) }} #{{ $activity->subject_id }}
|
||||
@else
|
||||
-
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-3 py-2 text-xs text-gray-500">
|
||||
@if($activity->properties->isNotEmpty())
|
||||
<details>
|
||||
<summary class="cursor-pointer text-indigo-600 hover:text-indigo-800">Mostra</summary>
|
||||
<div class="mt-1 p-2 bg-gray-50 rounded text-xs font-mono max-w-xs overflow-auto">
|
||||
@if($activity->properties->has('old'))
|
||||
<div class="mb-1">
|
||||
<span class="font-semibold text-red-600">Vecchio:</span>
|
||||
@foreach($activity->properties['old'] as $k => $v)
|
||||
<div>{{ $k }}: {{ is_string($v) ? $v : json_encode($v) }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-semibold text-green-600">Nuovo:</span>
|
||||
@foreach($activity->properties['attributes'] ?? [] as $k => $v)
|
||||
<div>{{ $k }}: {{ is_string($v) ? $v : json_encode($v) }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
@foreach($activity->properties->toArray() as $k => $v)
|
||||
<div>{{ $k }}: {{ is_string($v) ? $v : json_encode($v) }}</div>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
</details>
|
||||
@else
|
||||
-
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="px-4 py-8 text-center text-gray-500">Nessuna attività registrata.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="px-4 py-3 border-t border-gray-200">
|
||||
{{ $activities->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
38
resources/views/livewire/auth/login.blade.php
Normal file
38
resources/views/livewire/auth/login.blade.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<div class="bg-white shadow-xl rounded-2xl p-8">
|
||||
<div class="text-center mb-8">
|
||||
<div class="mx-auto h-12 w-12 bg-indigo-600 rounded-xl flex items-center justify-center text-white font-bold text-xl mb-4">T2</div>
|
||||
<h2 class="text-2xl font-bold text-gray-900">TerManager2</h2>
|
||||
<p class="text-gray-500 text-sm mt-1">Accedi per continuare</p>
|
||||
</div>
|
||||
|
||||
<form wire:submit="login" class="space-y-5">
|
||||
<div>
|
||||
<label for="email" class="block text-sm font-medium text-gray-700">Email</label>
|
||||
<input wire:model="email" type="email" id="email" autocomplete="email"
|
||||
class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5">
|
||||
@error('email') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="password" class="block text-sm font-medium text-gray-700">Password</label>
|
||||
<input wire:model="password" type="password" id="password" autocomplete="current-password"
|
||||
class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5">
|
||||
@error('password') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<input wire:model="remember" type="checkbox" id="remember"
|
||||
class="h-4 w-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500">
|
||||
<label for="remember" class="ml-2 text-sm text-gray-600">Ricordami</label>
|
||||
</div>
|
||||
|
||||
<button type="submit"
|
||||
class="w-full flex justify-center py-2.5 px-4 border border-transparent rounded-lg shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition">
|
||||
<span wire:loading.remove>Accedi</span>
|
||||
<span wire:loading class="flex items-center gap-2">
|
||||
<svg class="animate-spin h-4 w-4" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>
|
||||
Accesso in corso...
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
34
resources/views/livewire/campagne/campagna-form.blade.php
Normal file
34
resources/views/livewire/campagne/campagna-form.blade.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">{{ $titolo }}</h1>
|
||||
<a href="{{ route('campagne.index') }}" class="text-sm text-indigo-600 hover:text-indigo-800">← Torna alla lista</a>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 max-w-lg">
|
||||
<form wire:submit="save" class="space-y-4">
|
||||
<div>
|
||||
<label for="descrizione" class="block text-sm font-medium text-gray-700">Descrizione *</label>
|
||||
<input wire:model="descrizione" type="text" id="descrizione" placeholder="es. Campagna della Commemorazione 2025" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm" required>
|
||||
@error('descrizione') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<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>
|
||||
@error('start_date') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<div>
|
||||
<label for="end_date" class="block text-sm font-medium text-gray-700">Data Fine *</label>
|
||||
<input wire:model="end_date" type="date" id="end_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>
|
||||
@error('end_date') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3 pt-4">
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">{{ $btnLabel }}</button>
|
||||
<a href="{{ route('campagne.index') }}" class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition">Annulla</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
67
resources/views/livewire/campagne/campagna-index.blade.php
Normal file
67
resources/views/livewire/campagne/campagna-index.blade.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<div>
|
||||
<div class="mb-6 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Campagne</h1>
|
||||
@can('campagne.manage')
|
||||
<a href="{{ route('campagne.create') }}" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">
|
||||
+ Nuova Campagna
|
||||
</a>
|
||||
@endcan
|
||||
</div>
|
||||
|
||||
<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">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Descrizione</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Inizio</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Fine</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Stato</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">% Percorrenza</th>
|
||||
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
@forelse($campagne as $campagna)
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td class="px-4 py-3 text-sm font-medium text-gray-900">{{ $campagna->descrizione }}</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-600">{{ $campagna->start_date->format('d/m/Y') }}</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-600">{{ $campagna->end_date->format('d/m/Y') }}</td>
|
||||
<td class="px-4 py-3 text-sm">
|
||||
@if($campagna->is_attiva)
|
||||
<span class="inline-flex px-2 py-0.5 text-xs font-medium rounded-full bg-green-100 text-green-800">Attiva</span>
|
||||
@elseif($campagna->end_date->isPast())
|
||||
<span class="inline-flex px-2 py-0.5 text-xs font-medium rounded-full bg-gray-100 text-gray-600">Conclusa</span>
|
||||
@else
|
||||
<span class="inline-flex px-2 py-0.5 text-xs font-medium rounded-full bg-blue-100 text-blue-800">Futura</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-20 bg-gray-200 rounded-full h-2">
|
||||
<div class="bg-indigo-500 h-2 rounded-full" style="width:{{ min($campagna->percentuale_percorrenza, 100) }}%"></div>
|
||||
</div>
|
||||
<span class="text-xs text-gray-600">{{ $campagna->percentuale_percorrenza }}%</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-right space-x-2">
|
||||
<a href="{{ route('campagne.show', $campagna) }}" class="text-indigo-600 hover:text-indigo-800 text-xs">Dettaglio</a>
|
||||
@can('campagne.manage')
|
||||
<a href="{{ route('campagne.edit', $campagna) }}" class="text-yellow-600 hover:text-yellow-800 text-xs">Modifica</a>
|
||||
<button wire:click="deleteCampagna({{ $campagna->id }})" wire:confirm="Eliminare la campagna '{{ $campagna->descrizione }}'?" class="text-red-500 hover:text-red-700 text-xs">Elimina</button>
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="px-4 py-8 text-center text-gray-500 text-sm">Nessuna campagna registrata.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="px-4 py-3 border-t border-gray-200">
|
||||
{{ $campagne->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
75
resources/views/livewire/campagne/campagna-show.blade.php
Normal file
75
resources/views/livewire/campagne/campagna-show.blade.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<div>
|
||||
<div class="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-gray-900">{{ $campagna->descrizione }}</h1>
|
||||
<a href="{{ route('campagne.index') }}" class="text-sm text-indigo-600 hover:text-indigo-800">← Torna alla lista</a>
|
||||
</div>
|
||||
@can('campagne.manage')
|
||||
<a href="{{ route('campagne.edit', $campagna) }}" class="px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">Modifica</a>
|
||||
@endcan
|
||||
</div>
|
||||
|
||||
{{-- Stats --}}
|
||||
<div class="grid grid-cols-1 sm:grid-cols-4 gap-4 mb-6">
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Periodo</p>
|
||||
<p class="mt-1 text-sm font-medium text-gray-900">{{ $campagna->start_date->format('d/m/Y') }} — {{ $campagna->end_date->format('d/m/Y') }}</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Stato</p>
|
||||
@if($campagna->is_attiva)
|
||||
<span class="inline-flex mt-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">Attiva</span>
|
||||
@elseif($campagna->end_date->isPast())
|
||||
<span class="inline-flex mt-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600">Conclusa</span>
|
||||
@else
|
||||
<span class="inline-flex mt-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">Futura</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Conteggiati / Assegnati</p>
|
||||
<p class="mt-1 text-2xl font-bold text-indigo-600">{{ $conteggiate->count() }} / {{ $assegnateNelRange }}</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Percentuale</p>
|
||||
<p class="mt-1 text-2xl font-bold text-gray-900">{{ $campagna->percentuale_percorrenza }}%</p>
|
||||
<div class="mt-2 w-full bg-gray-200 rounded-full h-2">
|
||||
<div class="bg-indigo-500 h-2 rounded-full" style="width: {{ min($campagna->percentuale_percorrenza, 100) }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Counted assignments --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
||||
<div class="px-4 py-3 bg-gray-50 border-b">
|
||||
<h3 class="text-sm font-semibold text-gray-700">Territori Conteggiati</h3>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200 text-sm">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500">Territorio</th>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500">Proclamatore</th>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500">Assegnato</th>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500">Rientrato</th>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500">Giorni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
@forelse($conteggiate as $a)
|
||||
<tr>
|
||||
<td class="px-4 py-2"><a href="{{ route('territori.show', $a->territorio_id) }}" class="text-indigo-600 hover:underline">N° {{ $a->territorio?->numero }}</a></td>
|
||||
<td class="px-4 py-2">{{ $a->proclamatore?->nome_completo ?? 'N/A' }}</td>
|
||||
<td class="px-4 py-2">{{ $a->assigned_at->format('d/m/Y') }}</td>
|
||||
<td class="px-4 py-2">{{ $a->returned_at?->format('d/m/Y') }}</td>
|
||||
<td class="px-4 py-2">{{ $a->giorni }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="px-4 py-6 text-center text-gray-500">Nessun territorio conteggiato in questa campagna.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
139
resources/views/livewire/home.blade.php
Normal file
139
resources/views/livewire/home.blade.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<div>
|
||||
{{-- Header --}}
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Dashboard</h1>
|
||||
@if($annoCorrente)
|
||||
<p class="text-sm text-gray-500">Anno Teocratico {{ $annoCorrente->label }} — {{ $annoCorrente->mesi_trascorsi }} mesi trascorsi</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Stats cards --}}
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Territori Attivi</p>
|
||||
<p class="mt-1 text-3xl font-bold text-gray-900">{{ $totTerritoriAttivi }}</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Assegnati</p>
|
||||
<p class="mt-1 text-3xl font-bold text-blue-600">{{ $totAssegnati }}</p>
|
||||
<p class="text-xs text-gray-500">{{ $totInReparto }} in reparto</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Percorsi (anno)</p>
|
||||
<p class="mt-1 text-3xl font-bold text-green-600">{{ $territoriPercorsi }}</p>
|
||||
<p class="text-xs text-gray-500">media {{ $mediaPercorrenzaMensile }}/mese</p>
|
||||
</div>
|
||||
@if($campagnaStats)
|
||||
<div class="bg-amber-50 rounded-xl shadow-sm border border-amber-200 p-4">
|
||||
<p class="text-xs font-medium text-amber-600 uppercase">Campagna</p>
|
||||
<p class="mt-1 text-lg font-bold text-amber-800">{{ $campagnaStats['descrizione'] }}</p>
|
||||
<div class="mt-2">
|
||||
<div class="flex justify-between text-xs text-amber-700 mb-1">
|
||||
<span>{{ $campagnaStats['percentuale'] }}%</span>
|
||||
<span>scade {{ $campagnaStats['fine'] }}</span>
|
||||
</div>
|
||||
<div class="w-full bg-amber-200 rounded-full h-2">
|
||||
<div class="bg-amber-500 h-2 rounded-full transition-all" style="width: {{ min($campagnaStats['percentuale'], 100) }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Campagna</p>
|
||||
<p class="mt-1 text-sm text-gray-400">Nessuna campagna attiva</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Quick lists --}}
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{{-- Da assegnare --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
||||
<div class="px-4 py-3 bg-green-50 border-b border-green-100">
|
||||
<h3 class="text-sm font-semibold text-green-800">Da Assegnare</h3>
|
||||
</div>
|
||||
<ul class="divide-y divide-gray-100">
|
||||
@forelse($daAssegnare as $t)
|
||||
<li class="px-4 py-2.5 flex items-center justify-between hover:bg-gray-50">
|
||||
<div>
|
||||
<a href="{{ route('territori.show', $t) }}" class="text-sm font-semibold text-gray-900 hover:text-indigo-600">N° {{ $t->numero }}</a>
|
||||
<p class="text-xs text-gray-500">{{ $t->zona?->nome }} — {{ $t->tipologia?->nome }}</p>
|
||||
</div>
|
||||
@can('territori.assign')
|
||||
<a href="{{ route('assegnazioni.assegna', ['territorioId' => $t->id]) }}" class="text-xs font-medium text-green-600 hover:text-green-800">Assegna →</a>
|
||||
@endcan
|
||||
</li>
|
||||
@empty
|
||||
<li class="px-4 py-4 text-sm text-gray-400 text-center">Tutti assegnati</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
@if($daAssegnare->count() >= 10)
|
||||
<div class="px-4 py-2 bg-gray-50 border-t text-center">
|
||||
<a href="{{ route('territori.index') }}?filtroStato=in_reparto" class="text-xs text-indigo-600 hover:text-indigo-800">Vedi tutti →</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Prioritari --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
||||
<div class="px-4 py-3 bg-amber-50 border-b border-amber-100">
|
||||
<h3 class="text-sm font-semibold text-amber-800">★ Prioritari</h3>
|
||||
</div>
|
||||
<ul class="divide-y divide-gray-100">
|
||||
@forelse($prioritari as $t)
|
||||
<li class="px-4 py-2.5 flex items-center justify-between hover:bg-gray-50">
|
||||
<div>
|
||||
<a href="{{ route('territori.show', $t) }}" class="text-sm font-semibold text-gray-900 hover:text-indigo-600">N° {{ $t->numero }}</a>
|
||||
<p class="text-xs text-gray-500">
|
||||
{{ $t->zona?->nome }}
|
||||
@if($t->ultimaAssegnazione?->returned_at)
|
||||
— ultimo rientro {{ $t->ultimaAssegnazione->returned_at->diffForHumans() }}
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
<span class="text-xs font-medium text-amber-600">
|
||||
{{ $t->prioritario ? 'Man' : 'Auto' }}
|
||||
</span>
|
||||
</li>
|
||||
@empty
|
||||
<li class="px-4 py-4 text-sm text-gray-400 text-center">Nessun territorio prioritario</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
@if($prioritari->count() >= 10)
|
||||
<div class="px-4 py-2 bg-gray-50 border-t text-center">
|
||||
<a href="{{ route('territori.index') }}?filtroStato=prioritari" class="text-xs text-indigo-600 hover:text-indigo-800">Vedi tutti →</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Da rientrare --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
||||
<div class="px-4 py-3 bg-red-50 border-b border-red-100">
|
||||
<h3 class="text-sm font-semibold text-red-800">Da Rientrare</h3>
|
||||
</div>
|
||||
<ul class="divide-y divide-gray-100">
|
||||
@forelse($daRientrare as $t)
|
||||
<li class="px-4 py-2.5 flex items-center justify-between hover:bg-gray-50">
|
||||
<div>
|
||||
<a href="{{ route('territori.show', $t) }}" class="text-sm font-semibold text-gray-900 hover:text-indigo-600">N° {{ $t->numero }}</a>
|
||||
<p class="text-xs text-gray-500">
|
||||
{{ $t->assegnazioneCorrente?->proclamatore?->nome_completo }}
|
||||
— {{ $t->assegnazioneCorrente?->giorni }} giorni
|
||||
</p>
|
||||
</div>
|
||||
@can('territori.return')
|
||||
<a href="{{ route('assegnazioni.rientra', $t->assegnazioneCorrente) }}" class="text-xs font-medium text-red-600 hover:text-red-800">Rientra →</a>
|
||||
@endcan
|
||||
</li>
|
||||
@empty
|
||||
<li class="px-4 py-4 text-sm text-gray-400 text-center">Nessun territorio da rientrare</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
@if($daRientrare->count() >= 10)
|
||||
<div class="px-4 py-2 bg-gray-50 border-t text-center">
|
||||
<a href="{{ route('territori.index') }}?filtroStato=da_rientrare" class="text-xs text-indigo-600 hover:text-indigo-800">Vedi tutti →</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
72
resources/views/livewire/privacy.blade.php
Normal file
72
resources/views/livewire/privacy.blade.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<div>
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<h1 class="text-2xl font-bold text-gray-900 mb-6">Informativa Privacy</h1>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 md:p-8 space-y-6 text-sm text-gray-700 leading-relaxed">
|
||||
|
||||
<section>
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-2">Titolare del trattamento</h2>
|
||||
<p>Congregazione: <strong>{{ $congregazione }}</strong></p>
|
||||
<p>L'applicazione TerManager2 è utilizzata esclusivamente per la gestione interna dei territori di predicazione.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-2">Dati trattati</h2>
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
<li><strong>Proclamatori</strong>: nome e cognome — conservati in forma crittografata (AES-256-CBC) nel database.</li>
|
||||
<li><strong>Territori</strong>: numero, località, zona, tipologia, mappe PDF — nessun dato personale.</li>
|
||||
<li><strong>Assegnazioni</strong>: collegamento tra proclamatore e territorio con date di assegnazione e rientro.</li>
|
||||
<li><strong>Utenti</strong>: nome, email e ruolo per l'accesso all'applicazione.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-2">Finalità del trattamento</h2>
|
||||
<p>I dati personali sono trattati esclusivamente per:</p>
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
<li>Organizzare l'assegnazione e il rientro dei territori di predicazione.</li>
|
||||
<li>Monitorare la copertura territoriale per anno teocratico.</li>
|
||||
<li>Gestire le campagne speciali di predicazione.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-2">Base giuridica</h2>
|
||||
<p>Il trattamento è basato sul legittimo interesse dell'organizzazione religiosa nella gestione delle proprie attività interne (Art. 6(1)(f) GDPR) e sull'appartenenza volontaria dei proclamatori alla congregazione (Art. 9(2)(d) GDPR).</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-2">Misure di sicurezza</h2>
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
<li><strong>Crittografia</strong>: i dati personali (nome/cognome) sono crittografati con AES-256-CBC prima della memorizzazione.</li>
|
||||
<li><strong>Controllo accessi</strong>: sistema RBAC con tre ruoli (Admin, Servitore di Territorio, Proclamatore Semplificato).</li>
|
||||
<li><strong>Audit trail</strong>: tutte le operazioni sono registrate e conservate per {{ $auditRetention }} giorni.</li>
|
||||
<li><strong>Comunicazioni sicure</strong>: l'accesso avviene tramite HTTPS.</li>
|
||||
<li><strong>Hosting locale</strong>: i dati risiedono sull'infrastruttura della congregazione, non su servizi cloud di terze parti.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-2">Conservazione dei dati</h2>
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
<li>I dati dei proclamatori inattivi possono essere anonimizzati su richiesta.</li>
|
||||
<li>I territori eliminati sono conservati nel cestino (soft-delete) prima dell'eliminazione definitiva.</li>
|
||||
<li>I log di audit sono conservati per <strong>{{ $auditRetention }} giorni</strong>, configurabili nelle impostazioni.</li>
|
||||
<li>Lo storico assegnazioni è conservato per la durata necessaria alla gestione territoriale.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-2">Diritti dell'interessato</h2>
|
||||
<p>In conformità al GDPR, ogni persona i cui dati sono trattati ha il diritto di:</p>
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
<li><strong>Accesso</strong>: richiedere copia dei propri dati.</li>
|
||||
<li><strong>Rettifica</strong>: correggere dati inesatti.</li>
|
||||
<li><strong>Cancellazione</strong>: richiedere l'anonimizzazione o la rimozione dei propri dati.</li>
|
||||
<li><strong>Portabilità</strong>: richiedere l'esportazione dei propri dati.</li>
|
||||
</ul>
|
||||
<p class="mt-2">Le richieste possono essere inoltrate al Servitore di Territorio o all'Amministratore dell'applicazione.</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,37 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Cestino Proclamatori</h1>
|
||||
<a href="{{ route('proclamatori.index') }}" class="text-sm text-indigo-600 hover:text-indigo-800">← Torna alla lista</a>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Nome Completo</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Eliminato il</th>
|
||||
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
@forelse($proclamatori as $proclamatore)
|
||||
<tr class="hover:bg-gray-50">
|
||||
<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-right space-x-2">
|
||||
<button wire:click="restore({{ $proclamatore->id }})" class="text-green-600 hover:text-green-800 text-xs font-medium">Ripristina</button>
|
||||
<button wire:click="forceDelete({{ $proclamatore->id }})" wire:confirm="Eliminare DEFINITIVAMENTE questo proclamatore? Questa azione è irreversibile." class="text-red-600 hover:text-red-800 text-xs font-medium">Elimina definitivamente</button>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="3" class="px-4 py-8 text-center text-gray-500 text-sm">Il cestino è vuoto.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="px-4 py-3 border-t border-gray-200">
|
||||
{{ $proclamatori->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,32 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">{{ $titolo }}</h1>
|
||||
<a href="{{ route('proclamatori.index') }}" class="text-sm text-indigo-600 hover:text-indigo-800">← Torna alla lista</a>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 max-w-lg">
|
||||
<form wire:submit="save" class="space-y-4">
|
||||
<div>
|
||||
<label for="cognome" class="block text-sm font-medium text-gray-700">Cognome *</label>
|
||||
<input wire:model="cognome" type="text" id="cognome" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm" required>
|
||||
@error('cognome') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="nome" class="block text-sm font-medium text-gray-700">Nome *</label>
|
||||
<input wire:model="nome" type="text" id="nome" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm" required>
|
||||
@error('nome') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<input wire:model="attivo" type="checkbox" id="attivo" class="rounded border-gray-300 text-indigo-600 focus:ring-indigo-500">
|
||||
<label for="attivo" class="text-sm text-gray-700">Attivo</label>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3 pt-4">
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">{{ $btnLabel }}</button>
|
||||
<a href="{{ route('proclamatori.index') }}" class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition">Annulla</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,81 @@
|
||||
<div>
|
||||
<div class="mb-6 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Proclamatori</h1>
|
||||
@can('proclamatori.manage')
|
||||
<a href="{{ route('proclamatori.create') }}" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">
|
||||
+ Nuovo Proclamatore
|
||||
</a>
|
||||
@endcan
|
||||
</div>
|
||||
|
||||
{{-- Filters --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4 mb-4">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
|
||||
<input wire:model.live.debounce.300ms="search" type="text" placeholder="Cerca nome o cognome..." class="rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<select wire:model.live="filtroStato" class="rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutti</option>
|
||||
<option value="attivo">Attivi</option>
|
||||
<option value="inattivo">Inattivi</option>
|
||||
</select>
|
||||
<div class="text-xs text-gray-500 flex items-center">
|
||||
@can('proclamatori.manage')
|
||||
<a href="{{ route('proclamatori.cestino') }}" class="text-red-500 hover:text-red-700">🗑 Cestino</a>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Table --}}
|
||||
<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">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th wire:click="sortBy('cognome')" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase cursor-pointer hover:text-gray-700">
|
||||
Cognome @if($sortField==='cognome') {{ $sortDirection==='asc'?'↑':'↓' }} @endif
|
||||
</th>
|
||||
<th wire:click="sortBy('nome')" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase cursor-pointer hover:text-gray-700">
|
||||
Nome @if($sortField==='nome') {{ $sortDirection==='asc'?'↑':'↓' }} @endif
|
||||
</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Stato</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Territori Assegnati</th>
|
||||
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
@forelse($proclamatori as $proclamatore)
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td class="px-4 py-3 text-sm font-medium text-gray-900">{{ $proclamatore->cognome }}</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-700">{{ $proclamatore->nome }}</td>
|
||||
<td class="px-4 py-3 text-sm">
|
||||
@if($proclamatore->attivo)
|
||||
<span class="inline-flex px-2 py-0.5 text-xs font-medium rounded-full bg-green-100 text-green-800">Attivo</span>
|
||||
@else
|
||||
<span class="inline-flex px-2 py-0.5 text-xs font-medium rounded-full bg-gray-100 text-gray-600">Inattivo</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-600">{{ $proclamatore->assegnazioni()->aperte()->count() }}</td>
|
||||
<td class="px-4 py-3 text-sm text-right space-x-2">
|
||||
<a href="{{ route('proclamatori.show', $proclamatore) }}" class="text-indigo-600 hover:text-indigo-800 text-xs">Dettaglio</a>
|
||||
@can('proclamatori.manage')
|
||||
<a href="{{ route('proclamatori.edit', $proclamatore) }}" class="text-yellow-600 hover:text-yellow-800 text-xs">Modifica</a>
|
||||
<button wire:click="toggleActive({{ $proclamatore->id }})" class="text-xs {{ $proclamatore->attivo ? 'text-gray-500 hover:text-gray-700' : 'text-green-600 hover:text-green-800' }}">
|
||||
{{ $proclamatore->attivo ? 'Disattiva' : 'Attiva' }}
|
||||
</button>
|
||||
<button wire:click="deleteProclamatore({{ $proclamatore->id }})" wire:confirm="Spostare il proclamatore nel cestino?" class="text-red-500 hover:text-red-700 text-xs">Elimina</button>
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="px-4 py-8 text-center text-gray-500 text-sm">Nessun proclamatore trovato.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="px-4 py-3 border-t border-gray-200">
|
||||
{{ $proclamatori->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,85 @@
|
||||
<div>
|
||||
<div class="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-gray-900">{{ $proclamatore->nome_completo }}</h1>
|
||||
<a href="{{ route('proclamatori.index') }}" class="text-sm text-indigo-600 hover:text-indigo-800">← Torna alla lista</a>
|
||||
</div>
|
||||
@can('proclamatori.manage')
|
||||
<a href="{{ route('proclamatori.edit', $proclamatore) }}" class="px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">Modifica</a>
|
||||
@endcan
|
||||
</div>
|
||||
|
||||
{{-- Stats --}}
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 mb-6">
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Stato</p>
|
||||
@if($proclamatore->attivo)
|
||||
<span class="inline-flex mt-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">Attivo</span>
|
||||
@else
|
||||
<span class="inline-flex mt-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600">Inattivo</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Territori Attualmente</p>
|
||||
<p class="mt-1 text-2xl font-bold text-indigo-600">{{ $stats['attualmente_assegnati'] }}</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Media Giorni Trattenuta</p>
|
||||
<p class="mt-1 text-2xl font-bold text-gray-900">{{ $stats['media_giorni'] }} gg</p>
|
||||
<p class="text-xs text-gray-500">su {{ $stats['totale_assegnazioni'] }} assegnazioni totali</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Assignment history --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Storico Assegnazioni</h3>
|
||||
|
||||
@forelse($assegnazioniPerAnno as $annoLabel => $assegnazioni)
|
||||
<div class="mb-6">
|
||||
<h4 class="text-sm font-semibold text-indigo-600 mb-2">Anno Teocratico {{ $annoLabel }}</h4>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200 text-sm">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Territorio</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Assegnato</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Rientrato</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Giorni</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Campagna</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
@foreach($assegnazioni as $assegnazione)
|
||||
<tr>
|
||||
<td class="px-3 py-2">
|
||||
<a href="{{ route('territori.show', $assegnazione->territorio_id) }}" class="text-indigo-600 hover:underline">
|
||||
{{ $assegnazione->territorio?->numero ?? 'N/A' }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="px-3 py-2">{{ $assegnazione->assigned_at->format('d/m/Y') }}</td>
|
||||
<td class="px-3 py-2">
|
||||
@if($assegnazione->returned_at)
|
||||
{{ $assegnazione->returned_at->format('d/m/Y') }}
|
||||
@else
|
||||
<span class="text-amber-600 font-medium">In corso</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-3 py-2">{{ $assegnazione->giorni }}</td>
|
||||
<td class="px-3 py-2">
|
||||
@if($assegnazione->counted_in_campaign)
|
||||
<span class="text-green-600">{{ $assegnazione->campagna?->descrizione }}</span>
|
||||
@else
|
||||
<span class="text-gray-400">-</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<p class="text-gray-500 text-sm">Nessuna assegnazione registrata.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
93
resources/views/livewire/registro.blade.php
Normal file
93
resources/views/livewire/registro.blade.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Registro Assegnazioni</h1>
|
||||
</div>
|
||||
|
||||
{{-- Filters --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4 mb-4">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||
<input wire:model.live.debounce.300ms="search" type="text" placeholder="Cerca territorio o proclamatore..." class="rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<select wire:model.live="filtroAnno" class="rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutti gli anni</option>
|
||||
@foreach($anni as $anno)
|
||||
<option value="{{ $anno->id }}">{{ $anno->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<select wire:model.live="filtroZona" class="rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutte le zone</option>
|
||||
@foreach($zone as $zona)
|
||||
<option value="{{ $zona->id }}">{{ $zona->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<select wire:model.live="filtroTipologia" class="rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutte le tipologie</option>
|
||||
@foreach($tipologie as $tipologia)
|
||||
<option value="{{ $tipologia->id }}">{{ $tipologia->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<select wire:model.live="filtroStato" class="rounded-lg border-gray-300 text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutte</option>
|
||||
<option value="aperte">Aperte (in corso)</option>
|
||||
<option value="chiuse">Chiuse (rientrate)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Table --}}
|
||||
<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 text-sm">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th wire:click="sortBy('territorio_id')" class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase cursor-pointer">Territorio</th>
|
||||
<th class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase">Proclamatore</th>
|
||||
<th wire:click="sortBy('assigned_at')" class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase cursor-pointer">
|
||||
Assegnato @if($sortField==='assigned_at') {{ $sortDirection==='asc'?'↑':'↓' }} @endif
|
||||
</th>
|
||||
<th wire:click="sortBy('returned_at')" class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase cursor-pointer">
|
||||
Rientrato @if($sortField==='returned_at') {{ $sortDirection==='asc'?'↑':'↓' }} @endif
|
||||
</th>
|
||||
<th class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase">Giorni</th>
|
||||
<th class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase">Anno</th>
|
||||
<th class="px-3 py-3 text-left text-xs font-medium text-gray-500 uppercase">Campagna</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
@forelse($assegnazioni as $a)
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td class="px-3 py-2">
|
||||
<a href="{{ route('territori.show', $a->territorio_id) }}" class="text-indigo-600 hover:underline font-medium">N° {{ $a->territorio?->numero }}</a>
|
||||
<span class="text-xs text-gray-400 ml-1">{{ $a->territorio?->zona?->nome }}</span>
|
||||
</td>
|
||||
<td class="px-3 py-2">{{ $a->proclamatore?->nome_completo ?? 'N/A' }}</td>
|
||||
<td class="px-3 py-2">{{ $a->assigned_at->format('d/m/Y') }}</td>
|
||||
<td class="px-3 py-2">
|
||||
@if($a->returned_at)
|
||||
{{ $a->returned_at->format('d/m/Y') }}
|
||||
@else
|
||||
<span class="text-amber-600 font-medium text-xs">In corso</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-3 py-2">{{ $a->giorni }}</td>
|
||||
<td class="px-3 py-2 text-xs text-gray-500">{{ $a->annoTeocratico?->label }}</td>
|
||||
<td class="px-3 py-2 text-xs">
|
||||
@if($a->counted_in_campaign)
|
||||
<span class="text-green-600">{{ $a->campagna?->descrizione }}</span>
|
||||
@else
|
||||
<span class="text-gray-300">-</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7" class="px-4 py-8 text-center text-gray-500">Nessuna assegnazione trovata.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="px-4 py-3 border-t border-gray-200">
|
||||
{{ $assegnazioni->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
47
resources/views/livewire/settings/settings-edit.blade.php
Normal file
47
resources/views/livewire/settings/settings-edit.blade.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Impostazioni</h1>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 max-w-lg">
|
||||
@if (session()->has('success'))
|
||||
<div x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 3000)" x-transition.duration.500ms
|
||||
class="mb-4 rounded-lg bg-green-50 p-4 text-sm text-green-700 border border-green-200">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form wire:submit="save" class="space-y-5">
|
||||
<div>
|
||||
<label for="congregazione_nome" class="block text-sm font-medium text-gray-700">Nome Congregazione *</label>
|
||||
<input wire:model="congregazione_nome" type="text" id="congregazione_nome" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm" required>
|
||||
@error('congregazione_nome') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="giorni_giacenza_prioritari" class="block text-sm font-medium text-gray-700">Soglia Priorità (giorni)</label>
|
||||
<p class="text-xs text-gray-500 mb-1">Dopo quanti giorni dal rientro un territorio diventa prioritario automaticamente.</p>
|
||||
<input wire:model="giorni_giacenza_prioritari" type="number" min="1" max="730" id="giorni_giacenza_prioritari" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||
@error('giorni_giacenza_prioritari') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="giorni_per_smarrito" class="block text-sm font-medium text-gray-700">Soglia Rientro (giorni)</label>
|
||||
<p class="text-xs text-gray-500 mb-1">Dopo quanti giorni dall'assegnazione un territorio appare nella lista "da rientrare".</p>
|
||||
<input wire:model="giorni_per_smarrito" type="number" min="30" max="365" id="giorni_per_smarrito" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||
@error('giorni_per_smarrito') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="audit_retention_days" class="block text-sm font-medium text-gray-700">Conservazione Audit (giorni)</label>
|
||||
<p class="text-xs text-gray-500 mb-1">I log più vecchi di questo periodo verranno cancellati automaticamente.</p>
|
||||
<input wire:model="audit_retention_days" type="number" min="30" max="3650" id="audit_retention_days" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||
@error('audit_retention_days') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
|
||||
<div class="pt-4">
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">Salva Impostazioni</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
49
resources/views/livewire/settings/tipologie-index.blade.php
Normal file
49
resources/views/livewire/settings/tipologie-index.blade.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Gestione Tipologie</h1>
|
||||
</div>
|
||||
|
||||
{{-- Add new --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4 mb-4 max-w-lg">
|
||||
<form wire:submit="addTipologia" class="flex items-end gap-3">
|
||||
<div class="flex-1">
|
||||
<label for="nuovaTipologia" class="block text-sm font-medium text-gray-700">Nuova Tipologia</label>
|
||||
<input wire:model="nuovaTipologia" type="text" id="nuovaTipologia" placeholder="Nome tipologia..." class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||
@error('nuovaTipologia') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">Aggiungi</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{-- List --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden max-w-lg">
|
||||
<ul class="divide-y divide-gray-200">
|
||||
@forelse($tipologie as $tipo)
|
||||
<li class="px-4 py-3 flex items-center justify-between hover:bg-gray-50">
|
||||
@if($editingId === $tipo->id)
|
||||
<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">
|
||||
<button type="submit" class="text-green-600 hover:text-green-800 text-xs font-medium">Salva</button>
|
||||
<button type="button" wire:click="cancelEdit" class="text-gray-500 hover:text-gray-700 text-xs">Annulla</button>
|
||||
</form>
|
||||
@else
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-sm font-medium {{ $tipo->attivo ? 'text-gray-900' : 'text-gray-400 line-through' }}">{{ $tipo->nome }}</span>
|
||||
@if(!$tipo->attivo)
|
||||
<span class="text-xs text-gray-400">(inattiva)</span>
|
||||
@endif
|
||||
<span class="text-xs text-gray-400">{{ $tipo->territori()->count() }} territori</span>
|
||||
</div>
|
||||
<div class="flex 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="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>
|
||||
</div>
|
||||
@endif
|
||||
</li>
|
||||
@empty
|
||||
<li class="px-4 py-6 text-center text-gray-500 text-sm">Nessuna tipologia configurata.</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
49
resources/views/livewire/settings/zone-index.blade.php
Normal file
49
resources/views/livewire/settings/zone-index.blade.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Gestione Zone</h1>
|
||||
</div>
|
||||
|
||||
{{-- Add new --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4 mb-4 max-w-lg">
|
||||
<form wire:submit="addZona" class="flex items-end gap-3">
|
||||
<div class="flex-1">
|
||||
<label for="nuovaZona" class="block text-sm font-medium text-gray-700">Nuova Zona</label>
|
||||
<input wire:model="nuovaZona" type="text" id="nuovaZona" placeholder="Nome zona..." class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||
@error('nuovaZona') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">Aggiungi</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{-- List --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden max-w-lg">
|
||||
<ul class="divide-y divide-gray-200">
|
||||
@forelse($zone as $zona)
|
||||
<li class="px-4 py-3 flex items-center justify-between hover:bg-gray-50">
|
||||
@if($editingId === $zona->id)
|
||||
<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">
|
||||
<button type="submit" class="text-green-600 hover:text-green-800 text-xs font-medium">Salva</button>
|
||||
<button type="button" wire:click="cancelEdit" class="text-gray-500 hover:text-gray-700 text-xs">Annulla</button>
|
||||
</form>
|
||||
@else
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-sm font-medium {{ $zona->attivo ? 'text-gray-900' : 'text-gray-400 line-through' }}">{{ $zona->nome }}</span>
|
||||
@if(!$zona->attivo)
|
||||
<span class="text-xs text-gray-400">(inattiva)</span>
|
||||
@endif
|
||||
<span class="text-xs text-gray-400">{{ $zona->territori()->count() }} territori</span>
|
||||
</div>
|
||||
<div class="flex 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="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>
|
||||
</div>
|
||||
@endif
|
||||
</li>
|
||||
@empty
|
||||
<li class="px-4 py-6 text-center text-gray-500 text-sm">Nessuna zona configurata.</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
105
resources/views/livewire/setup/wizard.blade.php
Normal file
105
resources/views/livewire/setup/wizard.blade.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<div class="bg-white shadow-xl rounded-2xl p-8 w-full max-w-lg mx-auto">
|
||||
<div class="text-center mb-6">
|
||||
<h2 class="text-2xl font-bold text-gray-900">Setup iniziale</h2>
|
||||
<p class="text-gray-500 text-sm mt-1">Passo {{ $step }} di 3</p>
|
||||
<div class="flex gap-2 justify-center mt-3">
|
||||
@for($i = 1; $i <= 3; $i++)
|
||||
<div class="h-2 w-12 rounded-full {{ $i <= $step ? 'bg-indigo-600' : 'bg-gray-200' }}"></div>
|
||||
@endfor
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Step 1: Congregazione --}}
|
||||
@if($step === 1)
|
||||
<div class="space-y-4">
|
||||
<h3 class="text-lg font-semibold text-gray-800">Dati Congregazione</h3>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Nome Congregazione *</label>
|
||||
<input wire:model="congregazione_nome" type="text" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5" placeholder="Nome della congregazione">
|
||||
@error('congregazione_nome') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Logo (opzionale)</label>
|
||||
<input wire:model="logo" type="file" accept="image/*" class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100">
|
||||
@error('logo') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<button wire:click="nextStep" class="w-full py-2.5 px-4 rounded-lg text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 transition">Avanti</button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Step 2: Soglie --}}
|
||||
@if($step === 2)
|
||||
<div class="space-y-4">
|
||||
<h3 class="text-lg font-semibold text-gray-800">Soglie e limiti</h3>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Giorni giacenza per "da assegnare"</label>
|
||||
<input wire:model="giorni_giacenza_da_assegnare" type="number" min="1" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5">
|
||||
@error('giorni_giacenza_da_assegnare') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Giorni giacenza per "prioritari"</label>
|
||||
<input wire:model="giorni_giacenza_prioritari" type="number" min="1" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5">
|
||||
@error('giorni_giacenza_prioritari') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Giorni per "smarrito / da rientrare"</label>
|
||||
<input wire:model="giorni_per_smarrito" type="number" min="1" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5">
|
||||
@error('giorni_per_smarrito') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Limite lista rapida (Home)</label>
|
||||
<input wire:model="home_limit_list" type="number" min="1" max="100" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5">
|
||||
@error('home_limit_list') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<div class="flex gap-3">
|
||||
<button wire:click="previousStep" class="flex-1 py-2.5 px-4 rounded-lg text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 transition">Indietro</button>
|
||||
<button wire:click="nextStep" class="flex-1 py-2.5 px-4 rounded-lg text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 transition">Avanti</button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Step 3: Conferma --}}
|
||||
@if($step === 3)
|
||||
<div class="space-y-4">
|
||||
<h3 class="text-lg font-semibold text-gray-800">Conferma e completa</h3>
|
||||
|
||||
<div class="bg-gray-50 rounded-lg p-4 text-sm space-y-2">
|
||||
<p><span class="font-medium">Congregazione:</span> {{ $congregazione_nome }}</p>
|
||||
<p><span class="font-medium">Giacenza da assegnare:</span> {{ $giorni_giacenza_da_assegnare }} gg</p>
|
||||
<p><span class="font-medium">Giacenza prioritari:</span> {{ $giorni_giacenza_prioritari }} gg</p>
|
||||
<p><span class="font-medium">Soglia smarrito:</span> {{ $giorni_per_smarrito }} gg</p>
|
||||
<p><span class="font-medium">Limite liste Home:</span> {{ $home_limit_list }}</p>
|
||||
</div>
|
||||
|
||||
@if($needsAdmin)
|
||||
<div class="border-t pt-4 space-y-4">
|
||||
<h4 class="text-md font-semibold text-gray-700">Crea account amministratore</h4>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Nome</label>
|
||||
<input wire:model="admin_name" type="text" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5">
|
||||
@error('admin_name') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Email</label>
|
||||
<input wire:model="admin_email" type="email" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5">
|
||||
@error('admin_email') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Password</label>
|
||||
<input wire:model="admin_password" type="password" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5">
|
||||
@error('admin_password') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Conferma Password</label>
|
||||
<input wire:model="admin_password_confirmation" type="password" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm px-4 py-2.5">
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="flex gap-3">
|
||||
<button wire:click="previousStep" class="flex-1 py-2.5 px-4 rounded-lg text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 transition">Indietro</button>
|
||||
<button wire:click="finish" class="flex-1 py-2.5 px-4 rounded-lg text-sm font-medium text-white bg-green-600 hover:bg-green-700 transition">Completa Setup</button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@@ -0,0 +1,37 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Cestino Territori</h1>
|
||||
<a href="{{ route('territori.index') }}" class="text-sm text-indigo-600 hover:text-indigo-800">← Torna alla lista</a>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">N°</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Eliminato il</th>
|
||||
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
@forelse($territori as $territorio)
|
||||
<tr class="hover:bg-gray-50">
|
||||
<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-right space-x-2">
|
||||
<button wire:click="restore({{ $territorio->id }})" class="text-green-600 hover:text-green-800 text-xs font-medium">Ripristina</button>
|
||||
<button wire:click="forceDelete({{ $territorio->id }})" wire:confirm="Eliminare DEFINITIVAMENTE il territorio {{ $territorio->numero }}? Questa azione è irreversibile." class="text-red-600 hover:text-red-800 text-xs font-medium">Elimina definitivamente</button>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="3" class="px-4 py-8 text-center text-gray-500 text-sm">Il cestino è vuoto.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="px-4 py-3 border-t border-gray-200">
|
||||
{{ $territori->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
68
resources/views/livewire/territori/territorio-form.blade.php
Normal file
68
resources/views/livewire/territori/territorio-form.blade.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<div>
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">{{ $title }}</h1>
|
||||
<a href="{{ route('territori.index') }}" class="text-sm text-indigo-600 hover:text-indigo-800">← Torna alla lista</a>
|
||||
</div>
|
||||
|
||||
<form wire:submit="save" class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 space-y-5 max-w-2xl">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-5">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Numero *</label>
|
||||
<input wire:model="numero" type="text" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm">
|
||||
@error('numero') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Zona</label>
|
||||
<select wire:model="zona_id" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm">
|
||||
<option value="">-- Nessuna --</option>
|
||||
@foreach($zone as $zona)
|
||||
<option value="{{ $zona->id }}">{{ $zona->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Tipologia</label>
|
||||
<select wire:model="tipologia_id" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm">
|
||||
<option value="">-- Nessuna --</option>
|
||||
@foreach($tipologie as $tipologia)
|
||||
<option value="{{ $tipologia->id }}">{{ $tipologia->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex items-center gap-3 pt-6">
|
||||
<input wire:model="prioritario" type="checkbox" id="prioritario" class="h-4 w-4 text-indigo-600 border-gray-300 rounded">
|
||||
<label for="prioritario" class="text-sm text-gray-700">Prioritario (manuale)</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Note</label>
|
||||
<textarea wire:model="note" rows="3" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm"></textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">Confini</label>
|
||||
<textarea wire:model="confini" rows="3" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 text-sm"></textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700">PDF Territorio</label>
|
||||
<input wire:model="pdf" type="file" accept=".pdf" class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100">
|
||||
@error('pdf') <p class="mt-1 text-sm text-red-600">{{ $message }}</p> @enderror
|
||||
|
||||
@if($isEdit && $this->territorio->pdf_path)
|
||||
<div class="mt-2 flex items-center gap-2 text-sm">
|
||||
<span class="text-green-600">PDF presente</span>
|
||||
<button type="button" wire:click="removePdf" wire:confirm="Rimuovere il PDF?" class="text-red-600 hover:text-red-800 text-xs underline">Rimuovi PDF</button>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="flex gap-3 pt-2">
|
||||
<a href="{{ route('territori.index') }}" class="px-4 py-2.5 rounded-lg text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 transition">Annulla</a>
|
||||
<button type="submit" class="px-6 py-2.5 rounded-lg text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 transition">
|
||||
{{ $isEdit ? 'Aggiorna' : 'Crea' }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
107
resources/views/livewire/territori/territorio-index.blade.php
Normal file
107
resources/views/livewire/territori/territorio-index.blade.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<div>
|
||||
<div class="sm:flex sm:items-center sm:justify-between mb-6">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-gray-900">Territori</h1>
|
||||
<p class="text-sm text-gray-500 mt-1">Gestione dei territori della congregazione</p>
|
||||
</div>
|
||||
<div class="mt-4 sm:mt-0 flex gap-2">
|
||||
<a href="{{ route('territori.cestino') }}" class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition">Cestino</a>
|
||||
<a href="{{ route('territori.create') }}" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">+ Nuovo territorio</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Filters --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4 mb-4">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<input wire:model.live.debounce.300ms="search" type="text" placeholder="Cerca numero..."
|
||||
class="rounded-lg border-gray-300 text-sm focus:border-indigo-500 focus:ring-indigo-500">
|
||||
<select wire:model.live="filterZona" class="rounded-lg border-gray-300 text-sm focus:border-indigo-500 focus:ring-indigo-500">
|
||||
<option value="">Tutte le zone</option>
|
||||
@foreach($zone as $zona)
|
||||
<option value="{{ $zona->id }}">{{ $zona->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<select wire:model.live="filterTipologia" class="rounded-lg border-gray-300 text-sm focus:border-indigo-500 focus:ring-indigo-500">
|
||||
<option value="">Tutte le tipologie</option>
|
||||
@foreach($tipologie as $tipologia)
|
||||
<option value="{{ $tipologia->id }}">{{ $tipologia->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<select wire:model.live="filterStato" class="rounded-lg border-gray-300 text-sm focus:border-indigo-500 focus:ring-indigo-500">
|
||||
<option value="">Tutti gli stati</option>
|
||||
<option value="in_reparto">In reparto</option>
|
||||
<option value="assegnato">Assegnato</option>
|
||||
<option value="da_rientrare">Da rientrare</option>
|
||||
<option value="inattivo">Inattivo</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Table --}}
|
||||
<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">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th wire:click="sortBy('numero')" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase cursor-pointer hover:text-gray-700">
|
||||
N° @if($sortField === 'numero') <span>{{ $sortDirection === 'asc' ? '▲' : '▼' }}</span> @endif
|
||||
</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Zona</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Tipologia</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Stato</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Assegnatario</th>
|
||||
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
@forelse($territori as $territorio)
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td class="px-4 py-3 text-sm font-semibold text-gray-900">
|
||||
<a href="{{ route('territori.show', $territorio) }}" class="hover:text-indigo-600">{{ $territorio->numero }}</a>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-600">{{ $territorio->zona?->nome ?? '-' }}</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-600">{{ $territorio->tipologia?->nome ?? '-' }}</td>
|
||||
<td class="px-4 py-3 text-sm">
|
||||
@php $stato = $territorio->stato; @endphp
|
||||
<span class="inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-medium
|
||||
{{ match($stato) {
|
||||
'in_reparto' => 'bg-green-100 text-green-800',
|
||||
'assegnato' => 'bg-blue-100 text-blue-800',
|
||||
'da_rientrare' => 'bg-red-100 text-red-800',
|
||||
'inattivo' => 'bg-gray-100 text-gray-600',
|
||||
default => 'bg-gray-100 text-gray-600'
|
||||
} }}">
|
||||
{{ str_replace('_', ' ', ucfirst($stato)) }}
|
||||
</span>
|
||||
@if($territorio->is_prioritario)
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-amber-100 text-amber-800 ml-1"
|
||||
title="{{ $territorio->prioritario ? 'Prioritario (manuale)' : 'Prioritario (giacenza)' }}">
|
||||
★ {{ $territorio->prioritario ? 'Man.' : 'Auto' }}
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-gray-600">
|
||||
{{ $territorio->assegnatario?->nome_completo ?? '-' }}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-sm text-right space-x-1">
|
||||
<a href="{{ route('territori.show', $territorio) }}" class="text-indigo-600 hover:text-indigo-800 text-xs font-medium">Dettaglio</a>
|
||||
<a href="{{ route('territori.edit', $territorio) }}" class="text-gray-600 hover:text-gray-800 text-xs font-medium">Modifica</a>
|
||||
<button wire:click="toggleActive({{ $territorio->id }})" class="text-xs font-medium {{ $territorio->attivo ? 'text-amber-600 hover:text-amber-800' : 'text-green-600 hover:text-green-800' }}">
|
||||
{{ $territorio->attivo ? 'Disattiva' : 'Attiva' }}
|
||||
</button>
|
||||
<button wire:click="deleteTerritorio({{ $territorio->id }})" wire:confirm="Spostare il territorio {{ $territorio->numero }} nel cestino?" class="text-red-600 hover:text-red-800 text-xs font-medium">Elimina</button>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="px-4 py-8 text-center text-gray-500 text-sm">Nessun territorio trovato.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="px-4 py-3 border-t border-gray-200">
|
||||
{{ $territori->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
123
resources/views/livewire/territori/territorio-show.blade.php
Normal file
123
resources/views/livewire/territori/territorio-show.blade.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<div>
|
||||
<div class="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-gray-900">Territorio {{ $territorio->numero }}</h1>
|
||||
<a href="{{ route('territori.index') }}" class="text-sm text-indigo-600 hover:text-indigo-800">← Torna alla lista</a>
|
||||
</div>
|
||||
<a href="{{ route('territori.edit', $territorio) }}" class="px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 transition">Modifica</a>
|
||||
</div>
|
||||
|
||||
{{-- Info card --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Stato</p>
|
||||
@php $stato = $territorio->stato; @endphp
|
||||
<span class="inline-flex items-center mt-1 px-2.5 py-0.5 rounded-full text-xs font-medium
|
||||
{{ match($stato) {
|
||||
'in_reparto' => 'bg-green-100 text-green-800',
|
||||
'assegnato' => 'bg-blue-100 text-blue-800',
|
||||
'da_rientrare' => 'bg-red-100 text-red-800',
|
||||
'inattivo' => 'bg-gray-100 text-gray-600',
|
||||
default => 'bg-gray-100 text-gray-600'
|
||||
} }}">
|
||||
{{ str_replace('_', ' ', ucfirst($stato)) }}
|
||||
</span>
|
||||
@if($territorio->is_prioritario)
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-amber-100 text-amber-800 ml-1">★ Prioritario</span>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Zona</p>
|
||||
<p class="mt-1 text-sm text-gray-900">{{ $territorio->zona?->nome ?? '-' }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Tipologia</p>
|
||||
<p class="mt-1 text-sm text-gray-900">{{ $territorio->tipologia?->nome ?? '-' }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Assegnatario</p>
|
||||
<p class="mt-1 text-sm text-gray-900">{{ $territorio->assegnatario?->nome_completo ?? 'Nessuno' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($territorio->note)
|
||||
<div class="mt-4 pt-4 border-t">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Note</p>
|
||||
<p class="mt-1 text-sm text-gray-700">{{ $territorio->note }}</p>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($territorio->confini)
|
||||
<div class="mt-4 pt-4 border-t">
|
||||
<p class="text-xs font-medium text-gray-500 uppercase">Confini</p>
|
||||
<p class="mt-1 text-sm text-gray-700">{{ $territorio->confini }}</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- PDF viewer --}}
|
||||
@if($territorio->pdf_path)
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-4 mb-6">
|
||||
<h3 class="text-sm font-semibold text-gray-700 mb-3">PDF Territorio</h3>
|
||||
<div class="w-full" style="min-height: 500px;">
|
||||
<embed src="{{ asset('storage/' . $territorio->pdf_path) }}" type="application/pdf" width="100%" height="500px">
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
Se il PDF non è visibile:
|
||||
<a href="{{ asset('storage/' . $territorio->pdf_path) }}" target="_blank" class="text-indigo-600 hover:underline">Scarica PDF</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Assignment history --}}
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Storico Assegnazioni</h3>
|
||||
|
||||
@forelse($assegnazioniPerAnno as $annoLabel => $assegnazioni)
|
||||
<div class="mb-6">
|
||||
<h4 class="text-sm font-semibold text-indigo-600 mb-2">Anno Teocratico {{ $annoLabel }}</h4>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200 text-sm">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Proclamatore</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Assegnato</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Rientrato</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Giorni</th>
|
||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Campagna</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
@foreach($assegnazioni as $assegnazione)
|
||||
<tr>
|
||||
<td class="px-3 py-2">{{ $assegnazione->proclamatore?->nome_completo ?? 'N/A' }}</td>
|
||||
<td class="px-3 py-2">{{ $assegnazione->assigned_at->format('d/m/Y') }}</td>
|
||||
<td class="px-3 py-2">
|
||||
@if($assegnazione->returned_at)
|
||||
{{ $assegnazione->returned_at->format('d/m/Y') }}
|
||||
@else
|
||||
<span class="text-amber-600 font-medium">In corso</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-3 py-2">{{ $assegnazione->giorni }}</td>
|
||||
<td class="px-3 py-2">
|
||||
@if($assegnazione->counted_in_campaign)
|
||||
<span class="text-green-600">Sì — {{ $assegnazione->campagna?->descrizione }}</span>
|
||||
@elseif($assegnazione->counted_in_campaign === false)
|
||||
<span class="text-gray-400">No</span>
|
||||
@else
|
||||
<span class="text-gray-300">-</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<p class="text-gray-500 text-sm">Nessuna assegnazione registrata.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user