Prima implementazione pagina "Attività"
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
@page "/attivita"
|
||||
@rendermode @(InteractiveServer)
|
||||
@inject MockAttivitaService MockService
|
||||
|
||||
<div class="attivita-page">
|
||||
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h1 class="page-title">Attività</h1>
|
||||
<span class="page-date">@DateTime.Today.ToString("dddd d MMMM", new System.Globalization.CultureInfo("it-IT"))</span>
|
||||
</div>
|
||||
<div class="page-header-actions">
|
||||
<span class="counter-badge">@_attivita.Count(a => a.Stato == StatoAttivita.Aperta) aperte</span>
|
||||
<button type="button" class="btn-fine-viaggio" @onclick="FineViaggio">
|
||||
<i class="ri-flag-2-line"></i>
|
||||
Fine Viaggio
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (!_attivita.Any())
|
||||
{
|
||||
<NoDataAvailable
|
||||
ImageSource="_content/Fixiy.Shared/images/empty-state.svg"
|
||||
Text="Nessuna attività per oggi" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="attivita-list">
|
||||
@foreach (var item in AttivitaOrdinata)
|
||||
{
|
||||
<AttivitaCard
|
||||
Attivita="item"
|
||||
OnChiudi="ApriChiusura"
|
||||
OnVisualizzaAllegati="ApriAllegati"
|
||||
OnDragStart="OnDragStart"
|
||||
OnDrop="OnDrop" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<ChiusuraModal
|
||||
Attivita="_attivitaSelezionata"
|
||||
Visible="_chiusuraVisible"
|
||||
OnClosed="() => _chiusuraVisible = false"
|
||||
OnConferma="OnConfermaChiusura" />
|
||||
|
||||
<AllegatiModal
|
||||
Attivita="_attivitaSelezionata"
|
||||
Visible="_allegatiVisible"
|
||||
OnClosed="() => _allegatiVisible = false" />
|
||||
|
||||
@code {
|
||||
List<AttivitaItem> _attivita = [];
|
||||
AttivitaItem? _attivitaSelezionata;
|
||||
bool _chiusuraVisible;
|
||||
bool _allegatiVisible;
|
||||
AttivitaItem? _dragSource;
|
||||
|
||||
IEnumerable<AttivitaItem> AttivitaOrdinata =>
|
||||
_attivita.OrderBy(a => a.Priorita switch
|
||||
{
|
||||
PrioritaAttivita.Emergenza => 0,
|
||||
PrioritaAttivita.Alta => 1,
|
||||
_ => 2
|
||||
})
|
||||
.ThenBy(a => a.Ordine);
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_attivita = MockService.GetAttivitaOggi();
|
||||
}
|
||||
|
||||
void ApriChiusura(AttivitaItem item)
|
||||
{
|
||||
_attivitaSelezionata = item;
|
||||
_chiusuraVisible = true;
|
||||
}
|
||||
|
||||
void ApriAllegati(AttivitaItem item)
|
||||
{
|
||||
_attivitaSelezionata = item;
|
||||
_allegatiVisible = true;
|
||||
}
|
||||
|
||||
void OnConfermaChiusura((AttivitaItem item, StatoAttivita stato) args)
|
||||
{
|
||||
var idx = _attivita.IndexOf(args.item);
|
||||
if (idx >= 0)
|
||||
_attivita[idx] = args.item with { Stato = args.stato };
|
||||
|
||||
_chiusuraVisible = false;
|
||||
}
|
||||
|
||||
void OnDragStart(AttivitaItem item)
|
||||
{
|
||||
if (!item.IsLocked)
|
||||
_dragSource = item;
|
||||
}
|
||||
|
||||
void OnDrop(AttivitaItem target)
|
||||
{
|
||||
if (_dragSource is null || _dragSource == target || target.IsLocked)
|
||||
return;
|
||||
|
||||
var srcIdx = _attivita.IndexOf(_dragSource);
|
||||
var tgtIdx = _attivita.IndexOf(target);
|
||||
|
||||
if (srcIdx < 0 || tgtIdx < 0) return;
|
||||
|
||||
_attivita.RemoveAt(srcIdx);
|
||||
_attivita.Insert(tgtIdx, _dragSource);
|
||||
|
||||
for (int i = 0; i < _attivita.Count; i++)
|
||||
_attivita[i] = _attivita[i] with { Ordine = i };
|
||||
|
||||
_dragSource = null;
|
||||
}
|
||||
|
||||
void FineViaggio()
|
||||
{
|
||||
// TODO: generare e inviare PDF/CSV via email
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
.attivita-page {
|
||||
padding: 0;
|
||||
padding-top: calc(0.75rem + env(safe-area-inset-top, 0px));
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 1.4rem;
|
||||
}
|
||||
|
||||
.page-header-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 0.5rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.page-date {
|
||||
font-size: 0.78rem;
|
||||
color: #999;
|
||||
text-transform: capitalize;
|
||||
margin-top: 0.15rem;
|
||||
}
|
||||
|
||||
.counter-badge {
|
||||
background: var(--primary-color);
|
||||
color: #fff;
|
||||
font-size: 0.72rem;
|
||||
font-weight: 700;
|
||||
padding: 0.3rem 0.85rem;
|
||||
border-radius: 100px;
|
||||
white-space: nowrap;
|
||||
box-shadow: 0 4px 12px rgba(83, 82, 237, 0.28);
|
||||
}
|
||||
|
||||
.attivita-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
/* spazio per la bottom nav */
|
||||
padding-bottom: 7rem;
|
||||
}
|
||||
|
||||
/* Bottone "Fine Viaggio" integrato nell'header */
|
||||
.btn-fine-viaggio {
|
||||
background: linear-gradient(135deg, #5352ed, #3f3bc4);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 100px;
|
||||
padding: 0.5rem 1.1rem;
|
||||
font-family: inherit;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.01em;
|
||||
white-space: nowrap;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.4rem;
|
||||
box-shadow: 0 5px 16px rgba(83, 82, 237, 0.32);
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.18s ease, transform 0.15s ease;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.btn-fine-viaggio i {
|
||||
font-size: 1.05rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.btn-fine-viaggio:hover {
|
||||
box-shadow: 0 7px 20px rgba(83, 82, 237, 0.42);
|
||||
}
|
||||
|
||||
.btn-fine-viaggio:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
@page "/scheda-viaggi"
|
||||
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">Scheda Viaggi</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<NoDataAvailable
|
||||
ImageSource="_content/Fixiy.Shared/images/empty-state.svg"
|
||||
Text="Nessun viaggio disponibile" />
|
||||
</div>
|
||||
Reference in New Issue
Block a user