Rimetti i reparti richiudibili e il "+" sul reparto
Le schede di un reparto erano un elenco fisso: con quattro reparti aperti
la pagina diventava un rotolo, e per aggiungere una scheda a un reparto
preciso bisognava passare dal comando generale e ridichiarare il reparto.
La testata del reparto torna a essere un comando: si tocca per richiudere
il gruppo, e la freccia dice da che parte sta. I conteggi salgono nella
testata ("3 schede · 1 da inviare · 1 da completare") invece di stare nel
corpo: un reparto compattato non deve nascondere quello che gli manca.
Accanto torna il "+", che apre la scheda nuova con il reparto gia'
scelto. E' l'unica differenza con il "+" della barra, ed e' quella che
toglie un passaggio a chi sta lavorando su un reparto alla volta.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -151,41 +151,55 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@* Un reparto per volta: la testata si tocca per richiudere il
|
||||||
|
gruppo, e i conteggi restano scritti li' anche da chiuso — un
|
||||||
|
reparto compattato non deve nascondere quello che gli manca. *@
|
||||||
@foreach (var group in SchedeGrouped)
|
@foreach (var group in SchedeGrouped)
|
||||||
{
|
{
|
||||||
|
var reparto = group.Key;
|
||||||
|
var chiuso = IsCollapsed(reparto);
|
||||||
var daInviare = group.Value.CountDaInviare();
|
var daInviare = group.Value.CountDaInviare();
|
||||||
var daCompletare = group.Value.CountBozze();
|
|
||||||
|
|
||||||
<section>
|
<section class="reparto @(chiuso ? "reparto--collapsed" : "")">
|
||||||
<div class="section-header">
|
<div class="reparto__head">
|
||||||
<div class="section-header__text">
|
<button type="button" class="reparto__toggle" @onclick="@(() => Toggle(reparto))"
|
||||||
<h2 class="section-header__title">@group.Key.Descrizione</h2>
|
aria-expanded="@((!chiuso).ToString().ToLowerInvariant())">
|
||||||
<p class="section-header__desc">
|
<i class="reparto__chevron ri-arrow-down-s-line" aria-hidden="true"></i>
|
||||||
@(group.Value.Count == 1 ? "1 scheda" : $"{group.Value.Count} schede")
|
<span class="reparto__text">
|
||||||
</p>
|
<span class="reparto__title">@reparto.Descrizione</span>
|
||||||
</div>
|
<span class="reparto__meta">@Conteggi(group.Value)</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
@if (!IsCompleted && NetworkService.IsNetworkAvailable() && daInviare > 0)
|
<div class="reparto__actions">
|
||||||
|
@if (!IsCompleted)
|
||||||
|
{
|
||||||
|
@* Da qui la scheda nasce gia' con il suo reparto: e'
|
||||||
|
l'unica differenza con il "+" della barra. *@
|
||||||
|
<button type="button" class="reparto__add"
|
||||||
|
disabled="@(!NetworkService.IsNetworkAvailable())"
|
||||||
|
aria-label="@($"Nuova scheda nel reparto {reparto.Descrizione}")"
|
||||||
|
title="@($"Nuova scheda in {reparto.Descrizione}")"
|
||||||
|
@onclick="@(() => CreateNewScheda(reparto))">
|
||||||
|
<i class="ri-add-line" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
@if (NetworkService.IsNetworkAvailable() && daInviare > 0)
|
||||||
{
|
{
|
||||||
<div class="section-header__aside">
|
|
||||||
<MudButton Variant="Variant.Outlined" Size="Size.Small"
|
<MudButton Variant="Variant.Outlined" Size="Size.Small"
|
||||||
StartIcon="@Icons.Material.Rounded.CloudUpload"
|
StartIcon="@Icons.Material.Rounded.CloudUpload"
|
||||||
aria-label="@($"Invia le schede del reparto {group.Key.Descrizione}")"
|
aria-label="@($"Invia le schede del reparto {reparto.Descrizione}")"
|
||||||
OnClick="@(() => ExportReparto(group.Key))">
|
OnClick="@(() => ExportReparto(reparto))">
|
||||||
Invia @daInviare
|
Invia @daInviare
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</div>
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@if (daCompletare > 0)
|
@if (!chiuso)
|
||||||
{
|
{
|
||||||
<div class="badge-row" style="margin-bottom: var(--space-10);">
|
<div class="card-list reparto__body">
|
||||||
<Badge Spec="@SyncState.Bozza.ToBadge()" Text="@($"{daCompletare} da completare")"/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="card-list">
|
|
||||||
@foreach (var scheda in group.Value)
|
@foreach (var scheda in group.Value)
|
||||||
{
|
{
|
||||||
<SchedaCard Scheda="scheda" Ispezione="Ispezione"
|
<SchedaCard Scheda="scheda" Ispezione="Ispezione"
|
||||||
@@ -194,6 +208,7 @@
|
|||||||
OnBusyChanged="@(b => VisibleOverlay = b)"/>
|
OnBusyChanged="@(b => VisibleOverlay = b)"/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</section>
|
</section>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,6 +311,43 @@
|
|||||||
if (modal is { Canceled: false }) LoadSchede();
|
if (modal is { Canceled: false }) LoadSchede();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stessa scheda nuova, ma con il reparto gia' scelto: partendo da un
|
||||||
|
/// reparto non ha senso richiederlo.
|
||||||
|
private async Task CreateNewScheda(JtbFasiDto reparto)
|
||||||
|
{
|
||||||
|
var modal = await Dialog.OpenFormScheda(
|
||||||
|
Ispezione.CodMdep, Ispezione.Data, true, new Scheda { Reparto = reparto }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (modal is { Canceled: false }) LoadSchede();
|
||||||
|
}
|
||||||
|
|
||||||
|
// I reparti richiusi stanno qui e non nell'entita': e' uno stato della
|
||||||
|
// schermata, non del documento.
|
||||||
|
private readonly HashSet<string> _collapsed = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
private bool IsCollapsed(JtbFasiDto reparto) =>
|
||||||
|
reparto.CodJfas is not null && _collapsed.Contains(reparto.CodJfas);
|
||||||
|
|
||||||
|
private void Toggle(JtbFasiDto reparto)
|
||||||
|
{
|
||||||
|
if (reparto.CodJfas is null) return;
|
||||||
|
if (!_collapsed.Remove(reparto.CodJfas)) _collapsed.Add(reparto.CodJfas);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string Conteggi(List<Scheda> schede)
|
||||||
|
{
|
||||||
|
var parti = new List<string> { schede.Count == 1 ? "1 scheda" : $"{schede.Count} schede" };
|
||||||
|
|
||||||
|
var daInviare = schede.CountDaInviare();
|
||||||
|
if (daInviare > 0) parti.Add($"{daInviare} da inviare");
|
||||||
|
|
||||||
|
var bozze = schede.CountBozze();
|
||||||
|
if (bozze > 0) parti.Add($"{bozze} da completare");
|
||||||
|
|
||||||
|
return string.Join(" · ", parti);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ConfirmCompleteInspection()
|
private async Task ConfirmCompleteInspection()
|
||||||
{
|
{
|
||||||
_actionsOpen = false;
|
_actionsOpen = false;
|
||||||
|
|||||||
@@ -140,6 +140,98 @@
|
|||||||
|
|
||||||
.section-header__aside { flex: 0 0 auto; }
|
.section-header__aside { flex: 0 0 auto; }
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
Reparto — gruppo di schede richiudibile
|
||||||
|
La testata e' un comando a tutta riga: si tocca ovunque per chiudere il
|
||||||
|
gruppo. I conteggi stanno nella testata e non nel corpo, cosi' restano
|
||||||
|
leggibili anche da chiuso.
|
||||||
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.reparto__head {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-xs);
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reparto__toggle {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-4);
|
||||||
|
min-height: var(--touch-min);
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
font-family: inherit;
|
||||||
|
text-align: left;
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reparto__chevron {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
font-size: 24px;
|
||||||
|
color: var(--ink-muted);
|
||||||
|
transition: transform var(--duration-base) var(--ease-out);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reparto--collapsed .reparto__chevron { transform: rotate(-90deg); }
|
||||||
|
|
||||||
|
.reparto__text {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reparto__title {
|
||||||
|
display: block;
|
||||||
|
font-size: var(--title-lg-size);
|
||||||
|
line-height: var(--title-lg-height);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reparto__meta {
|
||||||
|
display: block;
|
||||||
|
margin-top: var(--space-2);
|
||||||
|
font-size: var(--body-md-size);
|
||||||
|
line-height: var(--body-md-height);
|
||||||
|
font-weight: 400;
|
||||||
|
color: var(--ink-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reparto__actions {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Il "+" del reparto non porta l'accento: l'accento e' del comando principale
|
||||||
|
della schermata, e qui i bottoni sono due in fila. */
|
||||||
|
.reparto__add {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: var(--touch-min);
|
||||||
|
height: var(--touch-min);
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border: 1px solid var(--divider);
|
||||||
|
border-radius: var(--radius-pill);
|
||||||
|
background-color: var(--surface);
|
||||||
|
color: var(--ink);
|
||||||
|
font-size: 22px;
|
||||||
|
transition: transform var(--duration-fast) var(--ease-out),
|
||||||
|
background-color var(--duration-fast) var(--ease-out);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reparto__add:active { transform: scale(0.94); background-color: var(--surface-muted); }
|
||||||
|
.reparto__add:disabled { color: var(--ink-muted); background-color: var(--surface-muted); }
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.reparto__add:active { transform: none; }
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
§6.4 Badge — stato in pillola
|
§6.4 Badge — stato in pillola
|
||||||
Mai il solo colore: sempre icona + etichetta.
|
Mai il solo colore: sempre icona + etichetta.
|
||||||
|
|||||||
Reference in New Issue
Block a user