glastree_on_gitea
This commit is contained in:
@@ -0,0 +1,244 @@
|
||||
@extends('layouts.adminlte')
|
||||
@section('title', 'Nuovo Gruppo')
|
||||
@section('page_title', 'Nuovo Gruppo')
|
||||
|
||||
@section('content')
|
||||
<form action="/gruppi" method="POST">
|
||||
@csrf
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-folder mr-2"></i>Dati Gruppo</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label>Nome *</label>
|
||||
<input type="text" name="nome" class="form-control @error('nome') is-invalid @enderror" value="{{ old('nome') }}" required>
|
||||
@error('nome')
|
||||
<span class="invalid-feedback">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Gruppo Padre</label>
|
||||
<select name="parent_id" class="form-control">
|
||||
<option value="">Nessuno (gruppo radice)</option>
|
||||
@foreach($allGruppi as $g)
|
||||
<option value="{{ $g->id }}" {{ old('parent_id') == $g->id || ($selectedParent && $selectedParent->id == $g->id) ? 'selected' : '' }}>
|
||||
{{ $g->full_path }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@if($selectedParent)
|
||||
<small class="form-text text-muted">
|
||||
Verrà creato come sottogruppo di: <strong>{{ $selectedParent->nome }}</strong>
|
||||
</small>
|
||||
@endif
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Diocesi</label>
|
||||
<select name="diocesi_id" class="form-control">
|
||||
<option value="">Seleziona...</option>
|
||||
@foreach($diocesi as $d)
|
||||
<option value="{{ $d->id }}" {{ old('diocesi_id') == $d->id ? 'selected' : '' }}>{{ $d->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Responsabili</label>
|
||||
<select name="responsabile_ids[]" class="form-control" multiple size="4" id="responsabile-select">
|
||||
<option value="">-- Nessuno --</option>
|
||||
</select>
|
||||
<small class="text-muted">Ctrl+click per selezionare più responsabili</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Descrizione</label>
|
||||
<textarea name="descrizione" class="form-control" rows="3">{{ old('descrizione') }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header"><h3 class="card-title"><i class="fas fa-map-marker-alt mr-2"></i>Luogo Incontro</h3></div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label>Indirizzo</label>
|
||||
<input type="text" name="indirizzo_incontro" class="form-control" value="{{ old('indirizzo_incontro') }}">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-4">
|
||||
<label>CAP</label>
|
||||
<input type="text" name="cap_incontro" class="form-control" value="{{ old('cap_incontro') }}">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<label>Città</label>
|
||||
<input type="text" name="città_incontro" class="form-control" value="{{ old('città_incontro') }}">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label>Provincia</label>
|
||||
<input type="text" name="sigla_provincia_incontro" class="form-control" maxlength="2" value="{{ old('sigla_provincia_incontro') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<label>URL Mappa</label>
|
||||
<input type="url" name="mappa_posizione" class="form-control" value="{{ old('mappa_posizione') }}" placeholder="https://...">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-users mr-2"></i>Membri</h3>
|
||||
<button type="button" class="btn btn-xs btn-success float-right" onclick="aggiungiMembro()">
|
||||
<i class="fas fa-plus mr-1"></i> Aggiungi Membro
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<table class="table table-bordered mb-0" id="membri-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th style="width: 30%;">Individuo</th>
|
||||
<th>Codice</th>
|
||||
<th>Contatti</th>
|
||||
<th style="width: 20%;">Ruolo</th>
|
||||
<th style="width: 100px;">Data Adesione</th>
|
||||
<th style="width: 50px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="membri-tbody">
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="no-membri-msg" class="text-center text-muted py-4">
|
||||
<p class="mb-0">Nessun membro aggiunto. Clicca su "Aggiungi Membro" per iniziare.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save mr-1"></i> Salva
|
||||
</button>
|
||||
<a href="/gruppi" class="btn btn-secondary">
|
||||
<i class="fas fa-times mr-1"></i> Annulla
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
let membriIndex = 0;
|
||||
const membriResponsabiliMap = new Map();
|
||||
|
||||
function aggiungiMembro() {
|
||||
const tbody = document.getElementById('membri-tbody');
|
||||
const noMsg = document.getElementById('no-membri-msg');
|
||||
if (noMsg) noMsg.style.display = 'none';
|
||||
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
<td>
|
||||
<select name="individui[${membriIndex}][individuo_id]" class="form-control" onchange="updateMembroInfo(this); updateResponsabiliFromMembri();" required>
|
||||
<option value="">Seleziona...</option>
|
||||
@foreach($individui as $i)
|
||||
<option value="{{ $i->id }}" data-codice="{{ $i->codice_id }}" data-email="{{ $i->email_primaria }}" data-telefono="{{ $i->telefono_primario }}">
|
||||
{{ $i->cognome }} {{ $i->nome }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</td>
|
||||
<td><span class="text-muted membro-codice">-</span></td>
|
||||
<td><small class="text-muted membro-contatti">-</small></td>
|
||||
<td><input type="text" name="individui[${membriIndex}][ruolo_nel_gruppo]" class="form-control" placeholder="Es. Membro"></td>
|
||||
<td><input type="date" name="individui[${membriIndex}][data_adesione]" class="form-control"></td>
|
||||
<td><button type="button" class="btn btn-danger btn-xs" onclick="rimuoviMembro(this); updateResponsabiliFromMembri();"><i class="fas fa-trash"></i></button></td>
|
||||
`;
|
||||
tbody.appendChild(row);
|
||||
membriIndex++;
|
||||
}
|
||||
|
||||
function updateMembroInfo(select) {
|
||||
const row = select.closest('tr');
|
||||
const option = select.options[select.selectedIndex];
|
||||
const codice = option.dataset.codice || '-';
|
||||
const email = option.dataset.email || '';
|
||||
const telefono = option.dataset.telefono || '';
|
||||
|
||||
row.querySelector('.membro-codice').textContent = codice;
|
||||
|
||||
let contatti = [];
|
||||
if (email) contatti.push('<span class="text-primary">'+email+'</span>');
|
||||
if (telefono) contatti.push('<span class="text-success">'+telefono+'</span>');
|
||||
row.querySelector('.membro-contatti').innerHTML = contatti.length ? contatti.join(' | ') : '-';
|
||||
}
|
||||
|
||||
function rimuoviMembro(btn) {
|
||||
const row = btn.closest('tr');
|
||||
row.remove();
|
||||
if (document.getElementById('membri-tbody').children.length === 0) {
|
||||
document.getElementById('no-membri-msg').style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
function updateResponsabiliFromMembri() {
|
||||
const respSelect = document.getElementById('responsabile-select');
|
||||
const currentSelected = Array.from(respSelect.selectedOptions).map(o => o.value);
|
||||
const tbody = document.getElementById('membri-tbody');
|
||||
const rows = tbody.querySelectorAll('tr');
|
||||
|
||||
const membroIds = new Set();
|
||||
const membroNames = new Map();
|
||||
|
||||
rows.forEach(row => {
|
||||
const select = row.querySelector('select[name*="individuo_id"]');
|
||||
if (select && select.value) {
|
||||
membroIds.add(select.value);
|
||||
const option = select.options[select.selectedIndex];
|
||||
membroNames.set(select.value, option.text);
|
||||
}
|
||||
});
|
||||
|
||||
respSelect.innerHTML = '';
|
||||
|
||||
if (membroIds.size === 0) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = '';
|
||||
opt.textContent = '-- Aggiungi prima dei membri --';
|
||||
opt.disabled = true;
|
||||
respSelect.appendChild(opt);
|
||||
} else {
|
||||
membroIds.forEach(id => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = id;
|
||||
opt.textContent = membroNames.get(id);
|
||||
if (currentSelected.includes(id)) opt.selected = true;
|
||||
respSelect.appendChild(opt);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const respSelect = document.getElementById('responsabile-select');
|
||||
const individuiList = @json($individui->map(fn($i) => ['id' => $i->id, 'text' => $i->cognome . ' ' . $i->nome]));
|
||||
const initialResponsabili = @json(old('responsabile_ids', []));
|
||||
|
||||
const optPlaceholder = document.createElement('option');
|
||||
optPlaceholder.value = '';
|
||||
optPlaceholder.textContent = '-- Aggiungi prima dei membri --';
|
||||
optPlaceholder.disabled = true;
|
||||
respSelect.appendChild(optPlaceholder);
|
||||
|
||||
initialResponsabili.forEach(id => {
|
||||
const match = individuiList.find(i => i.id == id);
|
||||
if (match) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = match.id;
|
||||
opt.textContent = match.text;
|
||||
opt.selected = true;
|
||||
respSelect.appendChild(opt);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@@ -0,0 +1,477 @@
|
||||
@extends('layouts.adminlte')
|
||||
@section('title', 'Modifica Gruppo')
|
||||
@section('page_title', 'Modifica Gruppo')
|
||||
|
||||
@section('content')
|
||||
<form action="/gruppi/{{ $gruppo->id }}" method="POST">
|
||||
@csrf @method('PUT')
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-folder mr-2"></i>Dati Gruppo</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label>Nome *</label>
|
||||
<input type="text" name="nome" class="form-control" value="{{ old('nome', $gruppo->nome) }}" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Gruppo Padre</label>
|
||||
<select name="parent_id" class="form-control">
|
||||
<option value="">Nessuno (gruppo radice)</option>
|
||||
@foreach($gruppi as $g)
|
||||
@if($g->id !== $gruppo->id)
|
||||
<option value="{{ $g->id }}" {{ old('parent_id', $gruppo->parent_id) == $g->id ? 'selected' : '' }}>
|
||||
{{ $g->full_path }}
|
||||
</option>
|
||||
@endif
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Diocesi</label>
|
||||
<select name="diocesi_id" class="form-control">
|
||||
<option value="">Seleziona...</option>
|
||||
@foreach($diocesi as $d)
|
||||
<option value="{{ $d->id }}" {{ old('diocesi_id', $gruppo->diocesi_id) == $d->id ? 'selected' : '' }}>{{ $d->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Responsabili (solo membri)</label>
|
||||
<select name="responsabile_ids[]" class="form-control" multiple size="4">
|
||||
@foreach($membri as $m)
|
||||
<option value="{{ $m->id }}" {{ in_array($m->id, old('responsabile_ids', $gruppo->getResponsabiliIds() ?? [])) ? 'selected' : '' }}>
|
||||
{{ $m->cognome }} {{ $m->nome }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@if($membri->isEmpty())
|
||||
<small class="text-muted">Prima aggiungi dei membri al gruppo</small>
|
||||
@else
|
||||
<small class="text-muted">Ctrl+click per selezionare più responsabili</small>
|
||||
@endif
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Descrizione</label>
|
||||
<textarea name="descrizione" class="form-control" rows="3">{{ old('descrizione', $gruppo->descrizione) }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header"><h3 class="card-title"><i class="fas fa-map-marker-alt mr-2"></i>Luogo Incontro</h3></div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label>Indirizzo</label>
|
||||
<input type="text" name="indirizzo_incontro" class="form-control" value="{{ old('indirizzo_incontro', $gruppo->indirizzo_incontro) }}">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-4">
|
||||
<label>CAP</label>
|
||||
<input type="text" name="cap_incontro" class="form-control" value="{{ old('cap_incontro', $gruppo->cap_incontro) }}">
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<label>Città</label>
|
||||
<input type="text" name="città_incontro" class="form-control" value="{{ old('città_incontro', $gruppo->città_incontro) }}">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label>Provincia</label>
|
||||
<input type="text" name="sigla_provincia_incontro" class="form-control" maxlength="2" value="{{ old('sigla_provincia_incontro', $gruppo->sigla_provincia_incontro) }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<label>URL Mappa</label>
|
||||
<input type="url" name="mappa_posizione" class="form-control" value="{{ old('mappa_posizione', $gruppo->mappa_posizione) }}" placeholder="https://...">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-users mr-2"></i>Membri</h3>
|
||||
<button type="button" class="btn btn-xs btn-success float-right" onclick="showMembroForm()">
|
||||
<i class="fas fa-plus mr-1"></i> Aggiungi
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
|
||||
@if($gruppo->individui->count() > 0)
|
||||
<table class="table table-bordered table-hover table-striped mb-0">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th style="width: 25%;">Individuo</th>
|
||||
<th style="width: 80px;">Codice</th>
|
||||
<th style="width: 25%;">Contatti</th>
|
||||
<th style="width: 130px;">Ruolo</th>
|
||||
<th style="width: 110px;">Data Adesione</th>
|
||||
<th style="width: 80px;">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($gruppo->individui as $membro)
|
||||
<tr id="membro-row-{{ $membro->id }}">
|
||||
<td>
|
||||
<i class="fas fa-user text-primary mr-1"></i>
|
||||
<a href="/individui/{{ $membro->id }}">{{ $membro->cognome }} {{ $membro->nome }}</a>
|
||||
</td>
|
||||
<td>{{ $membro->codice_id }}</td>
|
||||
<td>
|
||||
<small>
|
||||
@if($membro->email_primaria)
|
||||
<span class="text-primary">{{ $membro->email_primaria }}</span><br>
|
||||
@endif
|
||||
@if($membro->telefono_primario)
|
||||
<span class="text-success">{{ $membro->telefono_primario }}</span>
|
||||
@endif
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
@php $ruoliMembro = $membro->getRuoliForGruppo($gruppo->id) @endphp
|
||||
@if($ruoliMembro->count() > 0)
|
||||
@foreach($ruoliMembro as $ruolo)
|
||||
<span class="badge badge-info mr-1">{{ $ruolo->nome }}</span>
|
||||
@endforeach
|
||||
@else
|
||||
-
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $membro->pivot->data_adesione ? \Carbon\Carbon::parse($membro->pivot->data_adesione)->format('d/m/Y') : '-' }}</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-xs btn-warning" onclick="editMembroInline({{ $membro->id }})" title="Modifica">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-xs btn-danger" onclick="deleteMembro({{ $membro->id }})" title="Rimuovi">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="membro-edit-{{ $membro->id }}" style="display:none;">
|
||||
<td colspan="6">
|
||||
<form action="/gruppi/{{ $gruppo->id }}/membri/{{ $membro->id }}" method="POST" class="mb-0">
|
||||
@csrf @method('PUT')
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control form-control-sm" value="{{ $membro->cognome }} {{ $membro->nome }}" disabled>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input type="text" class="form-control form-control-sm" value="{{ $membro->codice_id }}" disabled>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select name="ruolo_ids[]" class="form-control form-control-sm" multiple size="3">
|
||||
@foreach(\App\Models\Ruolo::attive() as $ruolo)
|
||||
@php $selected = in_array($ruolo->id, $membro->getRuoloIdsForGruppo($gruppo->id)) @endphp
|
||||
<option value="{{ $ruolo->id }}" {{ $selected ? 'selected' : '' }}>{{ $ruolo->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input type="date" name="data_adesione" class="form-control form-control-sm" value="{{ $membro->pivot->data_adesione }}">
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="submit" class="btn btn-xs btn-success"><i class="fas fa-check"></i></button>
|
||||
<button type="button" class="btn btn-xs btn-secondary" onclick="cancelEditMembro({{ $membro->id }})"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@else
|
||||
<div class="text-center text-muted py-4">
|
||||
<i class="fas fa-users fa-2x mb-2"></i>
|
||||
<p class="mb-0">Nessun membro associato</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-file mr-2"></i>Documenti</h3>
|
||||
<button type="button" class="btn btn-xs btn-success float-right" onclick="showDocumentoForm()">
|
||||
<i class="fas fa-plus mr-1"></i> Carica
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div id="documento-add-form" style="display:none;" class="p-3 bg-light border-bottom">
|
||||
<form action="/documenti" method="POST" enctype="multipart/form-data" class="mb-0">
|
||||
@csrf
|
||||
<input type="hidden" name="visibilita" value="gruppo">
|
||||
<input type="hidden" name="visibilita_target_id" value="{{ $gruppo->id }}">
|
||||
<input type="hidden" name="visibilita_target_type" value="App\Models\Gruppo">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<input type="text" name="nome_file" class="form-control form-control-sm" placeholder="Nome documento" required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select name="tipologia" class="form-control form-control-sm" required>
|
||||
<option value="">Tipologia...</option>
|
||||
<option value="documento">Documento</option>
|
||||
<option value="statuto">Statuto</option>
|
||||
<option value="avatar">Avatar</option>
|
||||
<option value="galleria">Galleria</option>
|
||||
<option value="altro">Altro</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="file" name="file" class="form-control form-control-sm" required>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="submit" class="btn btn-xs btn-success"><i class="fas fa-upload mr-1"></i>Carica</button>
|
||||
<button type="button" class="btn btn-xs btn-secondary" onclick="hideDocumentoForm()"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@if($gruppo->documenti && $gruppo->documenti->count() > 0)
|
||||
<table class="table table-bordered table-hover table-striped mb-0">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th>Nome</th>
|
||||
<th style="width: 120px;">Tipologia</th>
|
||||
<th style="width: 80px;">Dimensione</th>
|
||||
<th style="width: 130px;">Data Upload</th>
|
||||
<th style="width: 80px;">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($gruppo->documenti as $documento)
|
||||
<tr>
|
||||
<td>
|
||||
<i class="fas fa-file text-secondary mr-1"></i>
|
||||
{{ $documento->nome_file }}
|
||||
</td>
|
||||
<td>{{ ucfirst(str_replace('_', ' ', $documento->tipologia)) }}</td>
|
||||
<td>{{ number_format($documento->dimensione / 1024, 1) }} KB</td>
|
||||
<td>{{ $documento->created_at->format('d/m/Y') }}</td>
|
||||
<td>
|
||||
@if($documento->file_path)
|
||||
<button type="button" class="btn btn-xs btn-primary" onclick="previewDocumento({{ $documento->id }}, '{{ $documento->mime_type }}')" title="Anteprima">
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
@endif
|
||||
<form action="/documenti/{{ $documento->id }}" method="POST" class="d-inline">
|
||||
@csrf @method('DELETE')
|
||||
<button type="submit" class="btn btn-xs btn-danger" onclick="return confirm('Eliminare questo documento?')" title="Elimina">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@else
|
||||
<div class="text-center text-muted py-4">
|
||||
<i class="fas fa-file fa-2x mb-2"></i>
|
||||
<p class="mb-0">Nessun documento</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="fas fa-save mr-1"></i> Salva Modifiche
|
||||
</button>
|
||||
<a href="/gruppi/{{ $gruppo->id }}" class="btn btn-secondary">
|
||||
<i class="fas fa-times mr-1"></i> Annulla
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="card mt-3" id="membro-card" style="display:none; background-color: #fff3cd; border-color: #ffc107;">
|
||||
<div class="card-header bg-warning">
|
||||
<h3 class="card-title"><i class="fas fa-user-plus mr-2"></i>Aggiungi Membro</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="membro-form-container">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<select id="new-membro-individuo" class="form-control form-control-sm">
|
||||
<option value="">Seleziona individuo...</option>
|
||||
@foreach(\App\Models\Individuo::whereNotIn('id', $membri->pluck('id'))->orderBy('cognome')->orderBy('nome')->get() as $i)
|
||||
<option value="{{ $i->id }}">{{ $i->cognome }} {{ $i->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select id="new-membro-ruolo" class="form-control form-control-sm" multiple size="3">
|
||||
@foreach(\App\Models\Ruolo::attive() as $ruolo)
|
||||
<option value="{{ $ruolo->id }}">{{ $ruolo->nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<small class="text-muted">Ctrl+click per selezionare più ruoli</small>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="date" id="new-membro-data" class="form-control form-control-sm">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="button" class="btn btn-success btn-sm" onclick="submitMembroForm()">
|
||||
<i class="fas fa-check mr-1"></i> Associa
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary btn-sm" onclick="hideMembroForm()">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="previewModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document" style="max-width: 90vw;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-file mr-2"></i><span id="previewModalTitle">Anteprima</span></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Chiudi">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body text-center p-0" style="min-height: 400px;">
|
||||
<iframe id="previewFrame" src="" style="width: 100%; height: 70vh; border: none;"></iframe>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a id="previewDownloadBtn" href="#" class="btn btn-primary" download>
|
||||
<i class="fas fa-download mr-1"></i> Scarica
|
||||
</a>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Chiudi</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
function showMembroForm() {
|
||||
console.log('showMembroForm called');
|
||||
var card = document.getElementById('membro-card');
|
||||
console.log('Card element:', card);
|
||||
if (card) {
|
||||
card.style.display = 'block';
|
||||
card.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
console.log('Card shown');
|
||||
} else {
|
||||
console.error('Card not found');
|
||||
}
|
||||
}
|
||||
|
||||
function hideMembroForm() {
|
||||
var card = document.getElementById('membro-card');
|
||||
if (card) {
|
||||
card.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function submitMembroForm() {
|
||||
var individuoId = document.getElementById('new-membro-individuo').value;
|
||||
var ruoloSelect = document.getElementById('new-membro-ruolo');
|
||||
var dataAdesione = document.getElementById('new-membro-data').value;
|
||||
|
||||
if (!individuoId) {
|
||||
alert('Seleziona un individuo');
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('new-membro-individuo').removeAttribute('required');
|
||||
|
||||
var formData = new URLSearchParams();
|
||||
formData.append('individuo_id', individuoId);
|
||||
|
||||
var selectedRuoli = Array.from(ruoloSelect.selectedOptions).map(opt => opt.value).filter(v => v);
|
||||
selectedRuoli.forEach(function(ruoloId) {
|
||||
formData.append('ruolo_ids[]', ruoloId);
|
||||
});
|
||||
|
||||
formData.append('data_adesione', dataAdesione);
|
||||
|
||||
fetch('/gruppi/{{ $gruppo->id }}/membri', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: formData
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
return response.text().then(text => { throw new Error(text); });
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
hideMembroForm();
|
||||
window.location.reload();
|
||||
} else {
|
||||
alert(data.error || 'Errore');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Errore: ' + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
function editMembroInline(id) {
|
||||
document.getElementById('membro-row-' + id).style.display = 'none';
|
||||
document.getElementById('membro-edit-' + id).style.display = 'table-row';
|
||||
}
|
||||
|
||||
function cancelEditMembro(id) {
|
||||
document.getElementById('membro-row-' + id).style.display = 'table-row';
|
||||
document.getElementById('membro-edit-' + id).style.display = 'none';
|
||||
}
|
||||
|
||||
function deleteMembro(individuoId) {
|
||||
if (!confirm('Rimuovere questo membro dal gruppo?')) return;
|
||||
|
||||
fetch('/gruppi/{{ $gruppo->id }}/membri/' + individuoId, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
return response.text().then(text => { throw new Error(text); });
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
alert(data.error || 'Errore');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Errore: ' + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
function showDocumentoForm() {
|
||||
document.getElementById('documento-add-form').style.display = 'block';
|
||||
}
|
||||
|
||||
function hideDocumentoForm() {
|
||||
document.getElementById('documento-add-form').style.display = 'none';
|
||||
}
|
||||
|
||||
function previewDocumento(id, mimeType) {
|
||||
document.getElementById('previewFrame').src = '/documenti/' + id + '/preview';
|
||||
document.getElementById('previewDownloadBtn').href = '/documenti/' + id + '/download';
|
||||
$('#previewModal').modal('show');
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
@@ -0,0 +1,434 @@
|
||||
@extends('layouts.adminlte')
|
||||
@section('title', 'Gruppi')
|
||||
@section('page_title', 'Elenco Gruppi')
|
||||
|
||||
@php
|
||||
$canWriteGruppi = Auth::user()->canManage('gruppi');
|
||||
$canDeleteGruppi = Auth::user()->canDelete('gruppi');
|
||||
$columnLabels = [
|
||||
'nome' => 'Nome',
|
||||
'descrizione' => 'Descrizione',
|
||||
'diocesi' => 'Diocesi',
|
||||
'livello' => 'Livello',
|
||||
'padre' => 'Gruppo Padre',
|
||||
'membri' => 'Membri',
|
||||
'responsabili' => 'Responsabili',
|
||||
'indirizzo' => 'Indirizzo',
|
||||
'citta' => 'Città',
|
||||
'telefono' => 'Telefono',
|
||||
'email' => 'Email',
|
||||
];
|
||||
$vistaDefaultJson = $vista ? $vista->toJson() : 'null';
|
||||
$allColumnsJson = json_encode($allColumns);
|
||||
$visibleColumnsJson = json_encode($visibleColumns);
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session('error'))
|
||||
<div class="alert alert-danger alert-dismissible">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-sitemap mr-2"></i>Elenco Gruppi</h3>
|
||||
<div class="card-tools">
|
||||
<div class="btn-group mr-2">
|
||||
<button type="button" class="btn btn-sm btn-outline-primary {{ $viewMode === 'table' ? 'active' : '' }}" onclick="switchView('table')" id="btn-table-view">
|
||||
<i class="fas fa-table mr-1"></i> Tabella
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary {{ $viewMode === 'tree' ? 'active' : '' }}" onclick="switchView('tree')" id="btn-tree-view">
|
||||
<i class="fas fa-sitemap mr-1"></i> Albero
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary btn-sm mr-1" onclick="showSaveVistaModal()">
|
||||
<i class="fas fa-save mr-1"></i> Salva Vista
|
||||
</button>
|
||||
@if($canWriteGruppi)
|
||||
<a href="{{ route('gruppi.create') }}" class="btn btn-success btn-sm">
|
||||
<i class="fas fa-plus"></i> Nuovo Gruppo
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($viewMode === 'table')
|
||||
<div class="card-body p-0">
|
||||
<table class="table table-bordered table-hover table-striped mb-0" id="gruppi-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
@if(in_array('nome', $visibleColumns))
|
||||
<th data-sortable="true" onclick="sortTable('nome')" style="cursor:pointer;">Nome <i class="fas fa-sort float-right text-muted"></i></th>
|
||||
@endif
|
||||
@if(in_array('descrizione', $visibleColumns))
|
||||
<th data-sortable="true" onclick="sortTable('descrizione')" style="cursor:pointer;">Descrizione <i class="fas fa-sort float-right text-muted"></i></th>
|
||||
@endif
|
||||
@if(in_array('diocesi', $visibleColumns))
|
||||
<th>Diocesi</th>
|
||||
@endif
|
||||
@if(in_array('livello', $visibleColumns))
|
||||
<th style="width: 80px;">Livello</th>
|
||||
@endif
|
||||
@if(in_array('padre', $visibleColumns))
|
||||
<th>Gruppo Padre</th>
|
||||
@endif
|
||||
@if(in_array('membri', $visibleColumns))
|
||||
<th style="width: 100px;">Membri</th>
|
||||
@endif
|
||||
@if(in_array('responsabili', $visibleColumns))
|
||||
<th>Responsabili</th>
|
||||
@endif
|
||||
@if(in_array('indirizzo', $visibleColumns))
|
||||
<th>Indirizzo</th>
|
||||
@endif
|
||||
@if(in_array('citta', $visibleColumns))
|
||||
<th>Città</th>
|
||||
@endif
|
||||
@if(in_array('telefono', $visibleColumns))
|
||||
<th>Telefono</th>
|
||||
@endif
|
||||
@if(in_array('email', $visibleColumns))
|
||||
<th>Email</th>
|
||||
@endif
|
||||
<th style="width: 120px;">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="table-body">
|
||||
@foreach($gruppi as $gruppo)
|
||||
<tr data-id="{{ $gruppo->id }}">
|
||||
@if(in_array('nome', $visibleColumns))
|
||||
<td>
|
||||
<span style="padding-left: {{ ($gruppo->depth ?? 0) * 20 }}px;">
|
||||
<i class="fas fa-{{ $gruppo->children->count() > 0 ? 'folder' : 'folder-open' }} text-{{ ($gruppo->depth ?? 0) == 0 ? 'warning' : 'secondary' }} mr-1"></i>
|
||||
<a href="{{ route('gruppi.show', $gruppo->id) }}">{{ $gruppo->nome }}</a>
|
||||
</span>
|
||||
</td>
|
||||
@endif
|
||||
@if(in_array('descrizione', $visibleColumns))
|
||||
<td>{{ Str::limit($gruppo->descrizione, 50) ?: '-' }}</td>
|
||||
@endif
|
||||
@if(in_array('diocesi', $visibleColumns))
|
||||
<td>{{ $gruppo->diocesi?->nome ?? '-' }}</td>
|
||||
@endif
|
||||
@if(in_array('livello', $visibleColumns))
|
||||
<td><span class="badge badge-{{ ($gruppo->depth ?? 0) == 0 ? 'primary' : 'secondary' }}">{{ $gruppo->depth ?? 0 }}</span></td>
|
||||
@endif
|
||||
@if(in_array('padre', $visibleColumns))
|
||||
<td>{{ $gruppo->parent?->nome ?? '-' }}</td>
|
||||
@endif
|
||||
@if(in_array('membri', $visibleColumns))
|
||||
<td><span class="badge badge-info">{{ $gruppo->individui->count() }}</span></td>
|
||||
@endif
|
||||
@if(in_array('responsabili', $visibleColumns))
|
||||
<td>
|
||||
@php $resp = $gruppo->getResponsabili() @endphp
|
||||
@if($resp->count() > 0)
|
||||
{{ $resp->pluck('cognome')->implode(', ') }}
|
||||
@else
|
||||
-
|
||||
@endif
|
||||
</td>
|
||||
@endif
|
||||
@if(in_array('indirizzo', $visibleColumns))
|
||||
<td>{{ $gruppo->indirizzo_incontro ?: '-' }}</td>
|
||||
@endif
|
||||
@if(in_array('citta', $visibleColumns))
|
||||
<td>{{ $gruppo->città_incontro ?: '-' }}</td>
|
||||
@endif
|
||||
@if(in_array('telefono', $visibleColumns))
|
||||
<td>-</td>
|
||||
@endif
|
||||
@if(in_array('email', $visibleColumns))
|
||||
<td>-</td>
|
||||
@endif
|
||||
<td>
|
||||
<a href="{{ route('gruppi.show', $gruppo->id) }}" class="btn btn-xs btn-info" title="Visualizza">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
@if($canWriteGruppi)
|
||||
<a href="{{ url('/gruppi/' . $gruppo->id . '/edit') }}" class="btn btn-xs btn-warning" title="Modifica">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
@endif
|
||||
@if($canDeleteGruppi)
|
||||
<form action="{{ url('/gruppi/' . $gruppo->id) }}" method="POST" class="d-inline">
|
||||
@csrf @method('DELETE')
|
||||
<button type="submit" class="btn btn-xs btn-danger" onclick="return confirm('Confermi l\'eliminazione?')" title="Elimina">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@else
|
||||
<div class="card-body p-0">
|
||||
<div class="tree-view" style="padding: 15px;">
|
||||
@php $rootGruppi = $gruppi->filter(fn($g) => $g->parent_id === null) @endphp
|
||||
@forelse($rootGruppi as $gruppo)
|
||||
@include('gruppi.partials.tree-item', ['gruppo' => $gruppo, 'isRoot' => true])
|
||||
@empty
|
||||
<div class="text-center text-muted py-4">
|
||||
<i class="fas fa-folder-open fa-2x mb-2"></i>
|
||||
<p>Nessun gruppo presente.
|
||||
@if($canWriteGruppi)
|
||||
<a href="{{ route('gruppi.create') }}">Crea il primo gruppo</a>
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="saveVistaModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-save mr-2"></i>Salva Vista</h5>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Nome Vista *</label>
|
||||
<input type="text" id="vista-nome" class="form-control" placeholder="Es. Elenco gruppi attivi">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Colonne visibili</label>
|
||||
<div class="row" id="colonne-checkboxes">
|
||||
@foreach($allColumns as $col)
|
||||
<div class="col-md-4 mb-2">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input col-checkbox" id="col-{{ $col }}" value="{{ $col }}" {{ in_array($col, $visibleColumns) ? 'checked' : '' }}>
|
||||
<label class="custom-control-label" for="col-{{ $col }}">{{ $columnLabels[$col] ?? $col }}</label>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="vista-default">
|
||||
<label class="custom-control-label" for="vista-default">Imposta come vista predefinita</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Annulla</button>
|
||||
<button type="button" class="btn btn-primary" onclick="saveVista()">
|
||||
<i class="fas fa-save mr-1"></i> Salva
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="vistaListModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-bookmark mr-2"></i>Viste Salvate</h5>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@php
|
||||
$visteSalvate = \App\Models\VistaReport::where('user_id', Auth::id())
|
||||
->where('tipo', 'gruppi')
|
||||
->orderBy('is_default', 'desc')
|
||||
->orderBy('nome')
|
||||
->get();
|
||||
@endphp
|
||||
@if($visteSalvate->count() > 0)
|
||||
<div class="list-group">
|
||||
@foreach($visteSalvate as $v)
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<a href="?vista_id={{ $v->id }}">{{ $v->nome }}</a>
|
||||
@if($v->is_default)
|
||||
<span class="badge badge-success ml-1">Predefinita</span>
|
||||
@endif
|
||||
</div>
|
||||
<form action="{{ route('gruppi.delete-vista', $v->id) }}" method="POST" class="d-inline">
|
||||
@csrf @method('DELETE')
|
||||
<button type="submit" class="btn btn-xs btn-danger" onclick="return confirm('Eliminare questa vista?')">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<p class="text-muted text-center">Nessuna vista salvata</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
function switchView(mode) {
|
||||
window.location.href = '?view=' + mode;
|
||||
}
|
||||
|
||||
function toggleItem(id) {
|
||||
const el = document.getElementById('group-' + id);
|
||||
const icon = document.getElementById('icon-' + id);
|
||||
if (el.style.display === 'none') {
|
||||
el.style.display = 'block';
|
||||
icon.classList.remove('fa-chevron-right');
|
||||
icon.classList.add('fa-chevron-down');
|
||||
} else {
|
||||
el.style.display = 'none';
|
||||
icon.classList.remove('fa-chevron-down');
|
||||
icon.classList.add('fa-chevron-right');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAllGroups() {
|
||||
const collapsed = document.querySelectorAll('.tree-children[style*="display: none"]').length > 0;
|
||||
document.querySelectorAll('.tree-children').forEach(el => {
|
||||
el.style.display = collapsed ? 'block' : 'none';
|
||||
});
|
||||
document.querySelectorAll('.tree-toggle i').forEach(icon => {
|
||||
if (collapsed) {
|
||||
icon.classList.remove('fa-chevron-right');
|
||||
icon.classList.add('fa-chevron-down');
|
||||
} else {
|
||||
icon.classList.remove('fa-chevron-down');
|
||||
icon.classList.add('fa-chevron-right');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let sortDirection = {};
|
||||
|
||||
function sortTable(column) {
|
||||
const tbody = document.getElementById('table-body');
|
||||
const rows = Array.from(tbody.querySelectorAll('tr'));
|
||||
|
||||
sortDirection[column] = sortDirection[column] === 'asc' ? 'desc' : 'asc';
|
||||
const dir = sortDirection[column];
|
||||
|
||||
rows.sort(function(a, b) {
|
||||
const cellA = a.querySelector(`td:nth-child(${getColumnIndex(column)})`)?.textContent.trim() || '';
|
||||
const cellB = b.querySelector(`td:nth-child(${getColumnIndex(column)})`)?.textContent.trim() || '';
|
||||
|
||||
if (dir === 'asc') {
|
||||
return cellA.localeCompare(cellB, 'it');
|
||||
}
|
||||
return cellB.localeCompare(cellA, 'it');
|
||||
});
|
||||
|
||||
rows.forEach(row => tbody.appendChild(row));
|
||||
|
||||
document.querySelectorAll('th i.fa-sort').forEach(icon => {
|
||||
icon.className = 'fas fa-sort float-right text-muted';
|
||||
});
|
||||
const th = document.querySelector(`th[data-sortable][onclick="sortTable('${column}')"] i`);
|
||||
if (th) {
|
||||
th.className = `fas fa-sort-${dir === 'asc' ? 'up' : 'down'} float-right`;
|
||||
}
|
||||
}
|
||||
|
||||
function getColumnIndex(column) {
|
||||
const th = document.querySelector(`th[onclick="sortTable('${column}')"]`);
|
||||
if (th) {
|
||||
return Array.from(th.parentNode.children).indexOf(th) + 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
function showSaveVistaModal() {
|
||||
document.getElementById('vista-nome').value = '';
|
||||
document.getElementById('vista-default').checked = false;
|
||||
$('#saveVistaModal').modal('show');
|
||||
}
|
||||
|
||||
function saveVista() {
|
||||
const nome = document.getElementById('vista-nome').value.trim();
|
||||
if (!nome) {
|
||||
alert('Inserisci un nome per la vista');
|
||||
return;
|
||||
}
|
||||
|
||||
const colonneVisibili = Array.from(document.querySelectorAll('.col-checkbox:checked')).map(cb => cb.value);
|
||||
const isDefault = document.getElementById('vista-default').checked;
|
||||
|
||||
fetch('/gruppi/save-vista', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nome: nome,
|
||||
colonne_visibili: colonneVisibili,
|
||||
is_default: isDefault,
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
$('#saveVistaModal').modal('hide');
|
||||
window.location.reload();
|
||||
} else {
|
||||
alert('Errore nel salvataggio della vista');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Errore: ' + error.message);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.tree-item { margin-bottom: 5px; }
|
||||
.tree-children {
|
||||
margin-left: 25px;
|
||||
border-left: 1px dashed #dee2e6;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.tree-toggle {
|
||||
cursor: pointer;
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.tree-toggle:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.tree-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.badge-level {
|
||||
font-size: 0.7em;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
.btn-group .btn.active {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border-color: #007bff;
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
@@ -0,0 +1,72 @@
|
||||
@php
|
||||
$children = $gruppo->children()->with(['diocesi', 'individui'])->orderBy('nome')->get();
|
||||
$hasChildren = $children->count() > 0;
|
||||
$canWriteGruppi = Auth::user()->canManage('gruppi');
|
||||
$responsabili = $gruppo->getResponsabili();
|
||||
@endphp
|
||||
|
||||
<div class="tree-item" style="margin-left: {{ $gruppo->depth ?? 0 }}px;">
|
||||
<div class="tree-label">
|
||||
@if($hasChildren)
|
||||
<span class="tree-toggle" onclick="toggleItem({{ $gruppo->id }})">
|
||||
<i id="icon-{{ $gruppo->id }}" class="fas fa-chevron-right text-muted"></i>
|
||||
</span>
|
||||
@else
|
||||
<span style="width: 22px; display: inline-block;"></span>
|
||||
@endif
|
||||
<i class="fas fa-{{ $hasChildren ? 'folder' : 'folder-open' }} text-{{ $gruppo->depth == 0 ? 'warning' : 'secondary' }} mr-1"></i>
|
||||
<a href="{{ route('gruppi.show', $gruppo->id) }}" class="{{ ($gruppo->depth ?? 0) == 0 ? 'font-weight-bold' : '' }}">
|
||||
{{ $gruppo->nome }}
|
||||
</a>
|
||||
<span class="badge badge-{{ ($gruppo->depth ?? 0) == 0 ? 'primary' : 'secondary' }} badge-level">{{ $gruppo->depth ?? 0 }}</span>
|
||||
<small class="text-muted ml-2">
|
||||
{{ $gruppo->diocesi?->nome ?? '' }}
|
||||
@if($responsabili->count() > 0)
|
||||
· <i class="fas fa-user text-info"></i> {{ $responsabili->pluck('cognome')->implode(', ') }}
|
||||
@endif
|
||||
</small>
|
||||
<span class="ml-auto">
|
||||
@if($gruppo->individui_count > 0)
|
||||
<span class="badge badge-info">{{ $gruppo->individui_count }} membri</span>
|
||||
@endif
|
||||
@if($hasChildren)
|
||||
<span class="badge badge-warning">{{ $children->count() }} figli</span>
|
||||
@endif
|
||||
</span>
|
||||
<span class="ml-2">
|
||||
<a href="{{ route('gruppi.show', $gruppo->id) }}" class="btn btn-xs btn-info" title="Visualizza">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
@if($canWriteGruppi)
|
||||
<a href="{{ url('/gruppi/' . $gruppo->id . '/edit') }}" class="btn btn-xs btn-warning" title="Modifica">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
@php
|
||||
$isParent = $hasChildren;
|
||||
$isSuperAdmin = Auth::user()->isSuperAdmin();
|
||||
$canDelete = !$isParent || $isSuperAdmin;
|
||||
@endphp
|
||||
@if($canDelete)
|
||||
<form action="{{ url('/gruppi/' . $gruppo->id) }}" method="POST" class="d-inline">
|
||||
@csrf @method('DELETE')
|
||||
<button type="submit" class="btn btn-xs btn-danger" onclick="return confirm('Confermi l\'eliminazione? Verranno eliminati anche tutti i sottogruppi.')" title="Elimina">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
@else
|
||||
<button type="button" class="btn btn-xs btn-danger disabled" title="Solo il superamministratore può eliminare gruppi con sottogruppi">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
@endif
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($hasChildren)
|
||||
<div id="group-{{ $gruppo->id }}" class="tree-children" style="display: none;">
|
||||
@foreach($children as $child)
|
||||
@include('gruppi.partials.tree-item', ['gruppo' => $child])
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
@@ -0,0 +1,515 @@
|
||||
@extends('layouts.adminlte')
|
||||
@section('title', 'Dettaglio Gruppo')
|
||||
@section('page_title', 'Dettaglio Gruppo')
|
||||
|
||||
@php
|
||||
$canWriteGruppi = Auth::user()->canManage('gruppi');
|
||||
$canDeleteGruppi = Auth::user()->canDelete('gruppi');
|
||||
@endphp
|
||||
|
||||
@section('breadcrumbs')
|
||||
<li class="breadcrumb-item"><a href="{{ route('gruppi.index') }}">Gruppi</a></li>
|
||||
<li class="breadcrumb-item active">{{ $gruppo->nome }}</li>
|
||||
@endsection
|
||||
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
@if(session('error'))
|
||||
<div class="alert alert-danger alert-dismissible">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-folder text-warning mr-2"></i>
|
||||
{{ $gruppo->nome }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-sm table-borderless">
|
||||
<tr>
|
||||
<td style="width: 130px;"><strong>Path:</strong></td>
|
||||
<td class="text-muted small">{{ $gruppo->full_path }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Gruppo Padre:</strong></td>
|
||||
<td>
|
||||
@if($gruppo->parent)
|
||||
<a href="{{ route('gruppi.show', $gruppo->parent->id) }}">{{ $gruppo->parent->nome }}</a>
|
||||
@else
|
||||
<span class="badge badge-success">Gruppo radice</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Diocesi:</strong></td>
|
||||
<td>{{ $gruppo->diocesi?->nome ?? '-' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Responsabili:</strong></td>
|
||||
<td>
|
||||
@php $responsabili = $gruppo->getResponsabili() @endphp
|
||||
@if($responsabili->count() > 0)
|
||||
@foreach($responsabili as $resp)
|
||||
<a href="{{ route('individui.show', $resp->id) }}">
|
||||
<i class="fas fa-user text-info mr-1"></i>
|
||||
{{ $resp->nome_completo }}
|
||||
</a><br>
|
||||
@endforeach
|
||||
@else
|
||||
<span class="text-muted">-</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header"><h3 class="card-title"><i class="fas fa-map-marker-alt mr-2"></i>Luogo Incontro</h3></div>
|
||||
<div class="card-body">
|
||||
<table class="table table-sm table-borderless mb-0">
|
||||
<tr>
|
||||
<td style="width: 100px;"><strong>Indirizzo:</strong></td>
|
||||
<td>{{ $gruppo->indirizzo_incontro ?: '-' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>CAP:</strong></td>
|
||||
<td>{{ $gruppo->cap_incontro ?: '-' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Città:</strong></td>
|
||||
<td>{{ $gruppo->città_incontro ?: '-' }} {{ $gruppo->sigla_provincia_incontro ? "({$gruppo->sigla_provincia_incontro})" : '' }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
@if($gruppo->mappa_posizione)
|
||||
<a href="{{ $gruppo->mappa_posizione }}" target="_blank" class="btn btn-sm btn-outline-primary mt-2">
|
||||
<i class="fas fa-external-link-alt mr-1"></i> Visualizza su mappa
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header"><h3 class="card-title"><i class="fas fa-chart-pie mr-2"></i>Statistiche</h3></div>
|
||||
<div class="card-body">
|
||||
<div class="row text-center">
|
||||
<div class="col-6">
|
||||
<div class="border-right">
|
||||
<h2 class="mb-0 text-primary">{{ $gruppo->individui->count() }}</h2>
|
||||
<small class="text-muted">Membri</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h2 class="mb-0 text-warning">{{ $gruppo->children->count() }}</h2>
|
||||
<small class="text-muted">Sottogruppi</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@php
|
||||
$incontroEvento = $gruppo->eventi->where('is_incontro_gruppo', true)->first();
|
||||
@endphp
|
||||
@if($incontroEvento)
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-calendar-check mr-2"></i>
|
||||
Giorno di Incontro
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-sm table-borderless mb-0">
|
||||
<tr>
|
||||
<td style="width: 100px;"><strong>Evento:</strong></td>
|
||||
<td>{{ $incontroEvento->nome_evento }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Quando:</strong></td>
|
||||
<td>
|
||||
@if($incontroEvento->tipo_recorrenza === 'settimanale')
|
||||
{{ $incontroEvento->giorno_settimana_label }}
|
||||
<span class="badge badge-info ml-1">Settimanale</span>
|
||||
@elseif($incontroEvento->tipo_recorrenza === 'mensile')
|
||||
{{ $incontroEvento->occorrenza_mensile_label }}
|
||||
@if($incontroEvento->mesi_recorrenza)
|
||||
<small class="text-muted">({{ $incontroEvento->mesi_recorrenza_label }})</small>
|
||||
@endif
|
||||
<span class="badge badge-info ml-1">Mensile</span>
|
||||
@elseif($incontroEvento->tipo_recorrenza === 'annuale')
|
||||
{{ $incontroEvento->mese_annuale_label }}
|
||||
<span class="badge badge-info ml-1">Annuale</span>
|
||||
@elseif($incontroEvento->tipo_recorrenza === 'altro')
|
||||
{{ $incontroEvento->giorno_settimana_label }}
|
||||
<span class="badge badge-info ml-1">Altro</span>
|
||||
@else
|
||||
{{ $incontroEvento->data_specifica?->format('d/m/Y') ?: '-' }}
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@if($incontroEvento->ora_inizio)
|
||||
<tr>
|
||||
<td><strong>Ora:</strong></td>
|
||||
<td>ore {{ $incontroEvento->ora_inizio->format('H:i') }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
</table>
|
||||
@if($incontroEvento->responsabili->count() > 0)
|
||||
<hr>
|
||||
<small class="text-muted"><strong>Responsabili:</strong></small>
|
||||
@foreach($incontroEvento->responsabili as $resp)
|
||||
<div class="mt-1">
|
||||
<i class="fas fa-user text-info mr-1"></i>
|
||||
<a href="/individui/{{ $resp->id }}">{{ $resp->cognome }} {{ $resp->nome }}</a>
|
||||
@if($resp->telefono_primario)
|
||||
<br><small class="text-success ml-3">{{ $resp->telefono_primario }}</small>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
<div class="mt-2">
|
||||
<a href="/eventi/{{ $incontroEvento->id }}" class="btn btn-xs btn-outline-primary">
|
||||
<i class="fas fa-eye mr-1"></i> Vedi evento
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($gruppo->descrizione)
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header"><h3 class="card-title"><i class="fas fa-align-left mr-2"></i>Descrizione</h3></div>
|
||||
<div class="card-body">
|
||||
<p class="mb-0">{!! nl2br(e($gruppo->descrizione)) !!}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-users mr-2"></i>Membri ({{ $gruppo->individui->count() }})
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
@if($gruppo->individui->count() > 0)
|
||||
<table class="table table-bordered table-hover table-striped mb-0">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th style="width: 100px;">Codice</th>
|
||||
<th>Nome Completo</th>
|
||||
<th>Email</th>
|
||||
<th>Telefono</th>
|
||||
<th style="width: 150px;">Ruolo</th>
|
||||
<th style="width: 110px;">Data Adesione</th>
|
||||
<th style="width: 80px;">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($gruppo->individui as $individuo)
|
||||
<tr>
|
||||
<td><span class="badge badge-secondary">{{ $individuo->codice_id }}</span></td>
|
||||
<td>
|
||||
<a href="{{ route('individui.show', $individuo->id) }}">
|
||||
<i class="fas fa-user text-info mr-1"></i>
|
||||
{{ $individuo->cognome }} {{ $individuo->nome }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ $individuo->email_primaria ?? '-' }}</td>
|
||||
<td>{{ $individuo->telefono_primario ?? '-' }}</td>
|
||||
<td>
|
||||
@php
|
||||
$ruoloIds = $individuo->pivot->ruolo_ids ? json_decode($individuo->pivot->ruolo_ids, true) : [];
|
||||
$ruoli = \App\Models\Ruolo::findByIds($ruoloIds);
|
||||
@endphp
|
||||
@if($ruoli->count() > 0)
|
||||
@foreach($ruoli as $ruolo)
|
||||
<span class="badge badge-info mr-1">{{ $ruolo->nome }}</span>
|
||||
@endforeach
|
||||
@else
|
||||
<span class="text-muted">-</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($individuo->pivot->data_adesione)
|
||||
{{ \Carbon\Carbon::parse($individuo->pivot->data_adesione)->format('d/m/Y') }}
|
||||
@else
|
||||
<span class="text-muted">-</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ route('individui.show', $individuo->id) }}" class="btn btn-xs btn-info" title="Visualizza">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@else
|
||||
<div class="text-center text-muted py-4">
|
||||
<i class="fas fa-users fa-2x mb-2"></i>
|
||||
<p class="mb-0">Nessun membro</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-file mr-2"></i>Documenti ({{ $gruppo->documenti->count() }})
|
||||
</h3>
|
||||
@if($canWriteGruppi)
|
||||
<button type="button" class="btn btn-xs btn-primary float-right" data-toggle="modal" data-target="#uploadDocumentoModal">
|
||||
<i class="fas fa-upload mr-1"></i> Carica
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
@if($gruppo->documenti->count() > 0)
|
||||
<table class="table table-bordered table-hover table-striped mb-0">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th>Nome</th>
|
||||
<th style="width: 120px;">Tipologia</th>
|
||||
<th style="width: 80px;">Dimensione</th>
|
||||
<th style="width: 130px;">Data Upload</th>
|
||||
<th style="width: 100px;">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($gruppo->documenti as $documento)
|
||||
<tr>
|
||||
<td>
|
||||
<a href="#" onclick="event.preventDefault(); previewDocumento({{ $documento->id }}, '{{ $documento->mime_type }}');">
|
||||
<i class="fas fa-file text-secondary mr-1"></i>
|
||||
{{ $documento->nome_file }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ ucfirst(str_replace('_', ' ', $documento->tipologia)) }}</td>
|
||||
<td>{{ number_format($documento->dimensione / 1024, 1) }} KB</td>
|
||||
<td>{{ $documento->created_at->format('d/m/Y') }}</td>
|
||||
<td>
|
||||
@if($documento->file_path)
|
||||
<a href="{{ url('/documenti/' . $documento->id . '/download') }}" class="btn btn-xs btn-primary" title="Scarica">
|
||||
<i class="fas fa-download"></i>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@else
|
||||
<div class="text-center text-muted py-4">
|
||||
<i class="fas fa-file fa-2x mb-2"></i>
|
||||
<p class="mb-0">Nessun documento</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-sitemap mr-2"></i>Sottogruppi ({{ $gruppo->children->count() }})
|
||||
</h3>
|
||||
<a href="{{ route('gruppi.create', ['parent_id' => $gruppo->id]) }}" class="btn btn-xs btn-success float-right">
|
||||
<i class="fas fa-plus mr-1"></i> Aggiungi Sottogruppo
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
@if($gruppo->children->count() > 0)
|
||||
<table class="table table-bordered table-hover table-striped mb-0">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th>Nome</th>
|
||||
<th>Diocesi</th>
|
||||
<th>Responsabile</th>
|
||||
<th style="text-align: center;">Membri</th>
|
||||
<th style="width: 100px;">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($gruppo->children->sortBy('nome') as $child)
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ route('gruppi.show', $child->id) }}">
|
||||
<i class="fas fa-folder-open text-warning mr-1"></i>
|
||||
{{ $child->nome }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ $child->diocesi?->nome ?? '-' }}</td>
|
||||
<td>{{ $child->getResponsabili()->isNotEmpty() ? $child->getResponsabili()->first()->nome_completo : '-' }}</td>
|
||||
<td class="text-center">
|
||||
@if($child->individui()->count() > 0)
|
||||
<span class="badge badge-info">{{ $child->individui()->count() }}</span>
|
||||
@else
|
||||
<span class="text-muted">-</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ route('gruppi.show', $child->id) }}" class="btn btn-xs btn-info" title="Visualizza">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
@if($canWriteGruppi)
|
||||
<a href="{{ route('gruppi.edit', $child->id) }}" class="btn btn-xs btn-warning" title="Modifica">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
@endif
|
||||
@if($canDeleteGruppi)
|
||||
<form action="{{ route('gruppi.destroy', $child->id) }}" method="POST" class="d-inline">
|
||||
@csrf @method('DELETE')
|
||||
<button type="submit" class="btn btn-xs btn-danger" onclick="return confirm('Eliminare {{ $child->nome }}?')" title="Elimina">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@else
|
||||
<div class="text-center text-muted py-4">
|
||||
<i class="fas fa-folder-open fa-2x mb-2"></i>
|
||||
<p class="mb-0">Nessun sottogruppo</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
@if($canWriteGruppi)
|
||||
<a href="{{ url('/gruppi/' . $gruppo->id . '/edit') }}" class="btn btn-warning">
|
||||
<i class="fas fa-edit mr-1"></i> Modifica
|
||||
</a>
|
||||
@endif
|
||||
@if($canDeleteGruppi)
|
||||
<form action="{{ url('/gruppi/' . $gruppo->id) }}" method="POST" class="d-inline">
|
||||
@csrf @method('DELETE')
|
||||
<button type="submit" class="btn btn-danger" onclick="return confirm('Confermi l\'eliminazione di {{ $gruppo->nome }}? Verranno eliminati anche tutti i sottogruppi.')">
|
||||
<i class="fas fa-trash mr-1"></i> Elimina
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
<a href="{{ route('gruppi.index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left mr-1"></i> Torna all'elenco
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="uploadDocumentoModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title"><i class="fas fa-upload mr-2"></i>Carica Documento</h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="/documenti" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<input type="hidden" name="visibilita" value="gruppo">
|
||||
<input type="hidden" name="visibilita_target_id" value="{{ $gruppo->id }}">
|
||||
<input type="hidden" name="visibilita_target_type" value="App\Models\Gruppo">
|
||||
<input type="hidden" name="_redirect" value="{{ url()->current() }}">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Nome *</label>
|
||||
<input type="text" name="nome_file" class="form-control" placeholder="Nome del documento" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Tipologia *</label>
|
||||
<select name="tipologia" class="form-control" required>
|
||||
<option value="">Seleziona...</option>
|
||||
<option value="documento">Documento</option>
|
||||
<option value="statuto">Statuto</option>
|
||||
<option value="avatar">Avatar</option>
|
||||
<option value="galleria">Galleria</option>
|
||||
<option value="altro">Altro</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>File *</label>
|
||||
<input type="file" name="file" class="form-control" required>
|
||||
<small class="text-muted">Max 10MB</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Annulla</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-upload mr-1"></i> Carica
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="previewModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document" style="max-width: 90vw;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-file mr-2"></i><span id="previewModalTitle">Anteprima</span></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Chiudi">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body text-center p-0" style="min-height: 400px;">
|
||||
<iframe id="previewFrame" src="" style="width: 100%; height: 70vh; border: none;"></iframe>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a id="previewDownloadBtn" href="#" class="btn btn-primary" download>
|
||||
<i class="fas fa-download mr-1"></i> Scarica
|
||||
</a>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Chiudi</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
function previewDocumento(id, mimeType) {
|
||||
var previewUrl = '/documenti/' + id + '/preview';
|
||||
var downloadUrl = '/documenti/' + id + '/download';
|
||||
|
||||
document.getElementById('previewFrame').src = previewUrl;
|
||||
document.getElementById('previewDownloadBtn').href = downloadUrl;
|
||||
document.getElementById('previewModalTitle').textContent = 'Anteprima';
|
||||
|
||||
if (mimeType && mimeType.startsWith('image/')) {
|
||||
document.getElementById('previewDownloadBtn').style.display = 'inline-block';
|
||||
} else {
|
||||
document.getElementById('previewDownloadBtn').style.display = 'none';
|
||||
}
|
||||
|
||||
$('#previewModal').modal('show');
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user