++ fix
This commit is contained in:
@@ -48,6 +48,10 @@ class Registro extends Component
|
|||||||
public bool $showDeleteConfirm = false;
|
public bool $showDeleteConfirm = false;
|
||||||
public ?int $deleteId = null;
|
public ?int $deleteId = null;
|
||||||
|
|
||||||
|
// ─── Modal modulo S-13 ──────────────────────────────────────
|
||||||
|
public bool $showS13Modal = false;
|
||||||
|
public string $s13Anno = '';
|
||||||
|
|
||||||
protected $queryString = [
|
protected $queryString = [
|
||||||
'search' => ['except' => ''],
|
'search' => ['except' => ''],
|
||||||
'filtroAnno' => ['except' => ''],
|
'filtroAnno' => ['except' => ''],
|
||||||
@@ -176,10 +180,28 @@ class Registro extends Component
|
|||||||
|
|
||||||
// ─── Modulo S-13 ────────────────────────────────────────────
|
// ─── Modulo S-13 ────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chiede quale anno di servizio stampare. L'anno del filtro è solo la
|
||||||
|
* proposta iniziale: il modulo finisce in archivio e viene firmato, quindi
|
||||||
|
* la scelta va confermata invece di essere ereditata da uno stato della
|
||||||
|
* pagina che l'utente può non avere presente.
|
||||||
|
*/
|
||||||
|
public function openS13(): void
|
||||||
|
{
|
||||||
|
abort_if(!auth()->user()->can('settings.manage'), 403);
|
||||||
|
|
||||||
|
$this->s13Anno = $this->filtroAnno !== ''
|
||||||
|
? $this->filtroAnno
|
||||||
|
: (string) AnnoTeocratico::corrente()->id;
|
||||||
|
|
||||||
|
$this->resetValidation();
|
||||||
|
$this->showS13Modal = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modulo ufficiale S-13-I ("Registrazione delle assegnazioni del
|
* Modulo ufficiale S-13-I ("Registrazione delle assegnazioni del
|
||||||
* territorio") compilato con le assegnazioni dell'anno di servizio
|
* territorio") compilato con le assegnazioni dell'anno di servizio scelto
|
||||||
* selezionato nei filtri.
|
* nella modale.
|
||||||
*
|
*
|
||||||
* Solo amministratore, come il resto del CRUD di questa pagina: il modulo
|
* Solo amministratore, come il resto del CRUD di questa pagina: il modulo
|
||||||
* espone in un unico file l'anagrafica completa di chi ha avuto quale
|
* espone in un unico file l'anagrafica completa di chi ha avuto quale
|
||||||
@@ -190,12 +212,17 @@ class Registro extends Component
|
|||||||
{
|
{
|
||||||
abort_if(!auth()->user()->can('settings.manage'), 403);
|
abort_if(!auth()->user()->can('settings.manage'), 403);
|
||||||
|
|
||||||
// Il modulo è per definizione relativo a un singolo anno di servizio:
|
$this->validate(
|
||||||
// con "Tutti gli anni" selezionato si ripiega sull'anno corrente.
|
['s13Anno' => 'required|exists:anni_teocratici,id'],
|
||||||
$anno = $this->filtroAnno
|
[
|
||||||
? AnnoTeocratico::find($this->filtroAnno)
|
's13Anno.required' => "Seleziona l'anno di servizio da stampare.",
|
||||||
: null;
|
's13Anno.exists' => "L'anno di servizio selezionato non esiste.",
|
||||||
$anno ??= AnnoTeocratico::corrente();
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$anno = AnnoTeocratico::findOrFail($this->s13Anno);
|
||||||
|
|
||||||
|
$this->showS13Modal = false;
|
||||||
|
|
||||||
$pdf = Pdf::loadView('pdf.registro-s13', [
|
$pdf = Pdf::loadView('pdf.registro-s13', [
|
||||||
'annoLabel' => $anno->label,
|
'annoLabel' => $anno->label,
|
||||||
|
|||||||
@@ -3,14 +3,11 @@
|
|||||||
<h1 class="text-2xl font-bold text-gray-900">Registro Assegnazioni</h1>
|
<h1 class="text-2xl font-bold text-gray-900">Registro Assegnazioni</h1>
|
||||||
@can('settings.manage')
|
@can('settings.manage')
|
||||||
<div class="flex flex-wrap items-center gap-2">
|
<div class="flex flex-wrap items-center gap-2">
|
||||||
<button wire:click="downloadS13"
|
<button wire:click="openS13"
|
||||||
wire:loading.attr="disabled"
|
|
||||||
wire:target="downloadS13"
|
|
||||||
class="btn-action btn-action-green" style="padding:8px 18px;font-size:14px;border-radius:8px"
|
class="btn-action btn-action-green" style="padding:8px 18px;font-size:14px;border-radius:8px"
|
||||||
title="Scarica il modulo S-13 compilato con le ultime 4 assegnazioni dell'anno selezionato">
|
title="Scarica il modulo S-13 compilato con le ultime 4 assegnazioni di un anno di servizio">
|
||||||
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3M3 17V7a2 2 0 012-2h5l2 2h7a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z"/></svg>
|
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3M3 17V7a2 2 0 012-2h5l2 2h7a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z"/></svg>
|
||||||
<span wire:loading.remove wire:target="downloadS13">Modulo S-13</span>
|
Modulo S-13
|
||||||
<span wire:loading wire:target="downloadS13">Generazione…</span>
|
|
||||||
</button>
|
</button>
|
||||||
<button wire:click="openCreate" class="btn-action btn-action-indigo" style="padding:8px 18px;font-size:14px;border-radius:8px">
|
<button wire:click="openCreate" class="btn-action btn-action-indigo" style="padding:8px 18px;font-size:14px;border-radius:8px">
|
||||||
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/></svg>
|
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/></svg>
|
||||||
@@ -145,6 +142,44 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- ─── Modal Modulo S-13 (solo admin) ─────────────────────── --}}
|
||||||
|
@can('settings.manage')
|
||||||
|
@if($showS13Modal)
|
||||||
|
<div style="position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:50;display:flex;align-items:center;justify-content:center;padding:16px;">
|
||||||
|
<div style="background:#fff;border-radius:12px;width:100%;max-width:440px;padding:24px;">
|
||||||
|
<h2 style="font-size:18px;font-weight:700;color:#111827;margin-bottom:6px;">Modulo S-13</h2>
|
||||||
|
<p style="font-size:13px;color:#6b7280;margin-bottom:18px;">
|
||||||
|
Registrazione delle assegnazioni del territorio. Per ogni territorio vengono
|
||||||
|
riportate le ultime 4 assegnazioni dell'anno scelto.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<label style="font-size:13px;font-weight:600;color:#374151;display:block;margin-bottom:4px;">Anno di servizio *</label>
|
||||||
|
<select wire:model="s13Anno" style="width:100%;border:1px solid #d1d5db;border-radius:8px;padding:8px 10px;font-size:14px;">
|
||||||
|
<option value="">-- seleziona --</option>
|
||||||
|
@foreach($anni as $anno)
|
||||||
|
<option value="{{ $anno->id }}">{{ $anno->label }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
@error('s13Anno') <span style="color:#dc2626;font-size:12px;">{{ $message }}</span> @enderror
|
||||||
|
|
||||||
|
<div style="display:flex;justify-content:flex-end;gap:10px;margin-top:20px;">
|
||||||
|
<button wire:click="$set('showS13Modal', false)"
|
||||||
|
style="background:#f3f4f6;color:#374151;border:none;border-radius:8px;padding:8px 18px;font-size:14px;cursor:pointer;">
|
||||||
|
Annulla
|
||||||
|
</button>
|
||||||
|
<button wire:click="downloadS13"
|
||||||
|
wire:loading.attr="disabled"
|
||||||
|
wire:target="downloadS13"
|
||||||
|
style="background:#16a34a;color:#fff;border:none;border-radius:8px;padding:8px 18px;font-size:14px;cursor:pointer;">
|
||||||
|
<span wire:loading.remove wire:target="downloadS13">Scarica PDF</span>
|
||||||
|
<span wire:loading wire:target="downloadS13">Generazione…</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@endcan
|
||||||
|
|
||||||
{{-- ─── Modal Crea / Modifica (solo admin) ────────────────── --}}
|
{{-- ─── Modal Crea / Modifica (solo admin) ────────────────── --}}
|
||||||
@can('settings.manage')
|
@can('settings.manage')
|
||||||
@if($showModal)
|
@if($showModal)
|
||||||
|
|||||||
@@ -18,20 +18,39 @@
|
|||||||
--}}
|
--}}
|
||||||
@php
|
@php
|
||||||
/**
|
/**
|
||||||
* Il nome del proclamatore deve stare su una riga in una cella larga
|
* Il nome del proclamatore deve stare su una riga: le righe hanno altezza
|
||||||
* ~35mm. DejaVu Sans ha larghezza media ~0.52em per carattere, quindi a
|
* fissa e la cella è nowrap, quindi mandare a capo sfonderebbe la griglia.
|
||||||
* 8pt entrano circa 23 caratteri: sotto quella soglia si scala il corpo
|
* Invece di andare a capo si scala il corpo.
|
||||||
* invece di mandare a capo, che sfonderebbe l'altezza fissa della riga.
|
*
|
||||||
|
* Larghezza utile della cella ~34.8mm (due colonne meno il padding).
|
||||||
|
* DejaVu Sans occupa in media 0.52em per carattere, cioè ~0.1835mm per
|
||||||
|
* carattere per punto di corpo: da lì il corpo massimo che entra.
|
||||||
|
*
|
||||||
|
* Sotto i 4.5pt il testo non sarebbe più leggibile, quindi oltre i 42
|
||||||
|
* caratteri si tronca — l'ellissi rende visibile l'accorciamento, mentre
|
||||||
|
* un nome che deborda corromperebbe la griglia in silenzio.
|
||||||
*/
|
*/
|
||||||
$nomeFontSize = static function (string $nome): string {
|
$LARGHEZZA_CELLA_MM = 34.8;
|
||||||
|
$MM_PER_CARATTERE_PER_PUNTO = 0.1835;
|
||||||
|
$CORPO_MAX_PT = 8.0;
|
||||||
|
$CORPO_MIN_PT = 4.5;
|
||||||
|
|
||||||
|
$maxCaratteri = (int) floor($LARGHEZZA_CELLA_MM / ($CORPO_MIN_PT * $MM_PER_CARATTERE_PER_PUNTO));
|
||||||
|
|
||||||
|
$nomeTroncato = static fn (string $nome): string => mb_strlen($nome) > $maxCaratteri
|
||||||
|
? mb_substr($nome, 0, $maxCaratteri - 1) . '…'
|
||||||
|
: $nome;
|
||||||
|
|
||||||
|
$nomeFontSize = static function (string $nome) use ($LARGHEZZA_CELLA_MM, $MM_PER_CARATTERE_PER_PUNTO, $CORPO_MAX_PT, $CORPO_MIN_PT): string {
|
||||||
$len = mb_strlen($nome);
|
$len = mb_strlen($nome);
|
||||||
|
|
||||||
return match (true) {
|
if ($len === 0) {
|
||||||
$len <= 23 => '8pt',
|
return $CORPO_MAX_PT . 'pt';
|
||||||
$len <= 27 => '7pt',
|
}
|
||||||
$len <= 32 => '6.2pt',
|
|
||||||
default => '5.5pt',
|
$pt = $LARGHEZZA_CELLA_MM / ($len * $MM_PER_CARATTERE_PER_PUNTO);
|
||||||
};
|
|
||||||
|
return round(max($CORPO_MIN_PT, min($CORPO_MAX_PT, $pt)), 1) . 'pt';
|
||||||
};
|
};
|
||||||
|
|
||||||
$ultimaPagina = $pagine->count() - 1;
|
$ultimaPagina = $pagine->count() - 1;
|
||||||
@@ -42,11 +61,22 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>S-13 — Registrazione delle assegnazioni del territorio</title>
|
<title>S-13 — Registrazione delle assegnazioni del territorio</title>
|
||||||
<style>
|
<style>
|
||||||
@page { margin: 12mm 10mm 10mm 10mm; }
|
/* dompdf riporta i margini di @page sull'elemento body, quindi il
|
||||||
|
reset universale qui sotto li azzererebbe: vanno ridichiarati su
|
||||||
|
body, che per specificità vince su "*". Tenere i due valori
|
||||||
|
allineati — è @page a definire l'area utile, body a farla
|
||||||
|
sopravvivere al reset.
|
||||||
|
I margini laterali sono i più larghi perché sono quelli che si
|
||||||
|
vedono; in verticale si sta stretti, il foglio pieno misura ~266mm
|
||||||
|
e ne restano 273. Alzando questi valori, o gli spazi sotto il
|
||||||
|
titolo e sopra il codice, il piè di pagina scivola su una pagina
|
||||||
|
nuova e ogni foglio ne occupa due: rimisurare dopo ogni modifica. */
|
||||||
|
@page { margin: 14mm 16mm 10mm 16mm; }
|
||||||
|
|
||||||
* { margin: 0; padding: 0; }
|
* { margin: 0; padding: 0; }
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
margin: 14mm 16mm 10mm 16mm;
|
||||||
font-family: "DejaVu Sans", sans-serif;
|
font-family: "DejaVu Sans", sans-serif;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
@@ -58,7 +88,7 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
letter-spacing: 0.2pt;
|
letter-spacing: 0.2pt;
|
||||||
margin-bottom: 9mm;
|
margin-bottom: 6mm;
|
||||||
}
|
}
|
||||||
|
|
||||||
.anno {
|
.anno {
|
||||||
@@ -89,7 +119,10 @@
|
|||||||
/* Intestazione */
|
/* Intestazione */
|
||||||
thead th { font-weight: normal; padding: 0.5mm 0.5mm; }
|
thead th { font-weight: normal; padding: 0.5mm 0.5mm; }
|
||||||
th.terr { font-size: 7.5pt; line-height: 1.15; }
|
th.terr { font-size: 7.5pt; line-height: 1.15; }
|
||||||
th.restituito { font-size: 6.6pt; line-height: 1.15; }
|
/* 6.2pt e non di più: a 6.6pt "l'ultima volta il*" non entra nei
|
||||||
|
~21mm utili della colonna e l'intestazione passa da due righe a tre,
|
||||||
|
allontanandosi dal modulo originale. */
|
||||||
|
th.restituito { font-size: 6.2pt; line-height: 1.15; white-space: nowrap; }
|
||||||
th.assegnato-a { font-size: 8pt; }
|
th.assegnato-a { font-size: 8pt; }
|
||||||
th.sotto { font-size: 6.4pt; }
|
th.sotto { font-size: 6.4pt; }
|
||||||
|
|
||||||
@@ -103,7 +136,7 @@
|
|||||||
td.nome { line-height: 1.1; padding: 0 0.6mm; white-space: nowrap; }
|
td.nome { line-height: 1.1; padding: 0 0.6mm; white-space: nowrap; }
|
||||||
|
|
||||||
.nota { font-size: 7.4pt; margin-top: 1.6mm; }
|
.nota { font-size: 7.4pt; margin-top: 1.6mm; }
|
||||||
.codice { font-size: 8pt; margin-top: 5mm; }
|
.codice { font-size: 8pt; margin-top: 3mm; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -142,7 +175,8 @@
|
|||||||
<td class="numero" rowspan="2">{{ $riga['numero'] }}</td>
|
<td class="numero" rowspan="2">{{ $riga['numero'] }}</td>
|
||||||
<td class="rientro-prec" rowspan="2">{{ $riga['rientro_precedente'] }}</td>
|
<td class="rientro-prec" rowspan="2">{{ $riga['rientro_precedente'] }}</td>
|
||||||
@foreach($riga['assegnazioni'] as $a)
|
@foreach($riga['assegnazioni'] as $a)
|
||||||
<td class="nome" colspan="2" style="font-size:{{ $nomeFontSize($a['nome']) }}">{{ $a['nome'] }}</td>
|
@php($nome = $nomeTroncato($a['nome']))
|
||||||
|
<td class="nome" colspan="2" style="font-size:{{ $nomeFontSize($nome) }}">{{ $nome }}</td>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="riga-date">
|
<tr class="riga-date">
|
||||||
|
|||||||
Reference in New Issue
Block a user