Breadcrumb e pagina commesse
This commit is contained in:
13
TecniStamp/TecniStamp.Service/FeatureService.cs
Normal file
13
TecniStamp/TecniStamp.Service/FeatureService.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using OAService.Service.Servizi.Implementazioni;
|
||||||
|
using TecniStamp.Domain;
|
||||||
|
using TecniStamp.Service.Interfaces;
|
||||||
|
using TecniStamp.Service.Repository;
|
||||||
|
|
||||||
|
namespace TecniStamp.Service;
|
||||||
|
|
||||||
|
public class FeatureService : TService<Feature>, IFeatureService
|
||||||
|
{
|
||||||
|
public FeatureService(ITecniStampUnitOfWork unitOfWork) : base(unitOfWork)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
using OAService.Service.Servizi.Interfacce;
|
||||||
|
using TecniStamp.Domain;
|
||||||
|
|
||||||
|
namespace TecniStamp.Service.Interfaces;
|
||||||
|
|
||||||
|
public interface IFeatureService : ITService<Feature>
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
public interface IManagerService
|
public interface IManagerService
|
||||||
{
|
{
|
||||||
|
IFeatureService FeatureService { get; set; }
|
||||||
IPermissionService PermissionService { get; set; }
|
IPermissionService PermissionService { get; set; }
|
||||||
IRuoloService RuoloService{ get; set; }
|
IRuoloService RuoloService{ get; set; }
|
||||||
ISezioneService SezioneService { get; set; }
|
ISezioneService SezioneService { get; set; }
|
||||||
|
|||||||
@ -4,14 +4,16 @@ namespace TecniStamp.Service;
|
|||||||
|
|
||||||
public class ManagerService : IManagerService
|
public class ManagerService : IManagerService
|
||||||
{
|
{
|
||||||
public ManagerService(IUserService userService, ISezioneService sezioneService, IPermissionService permissionService, IRuoloService ruoloService)
|
public ManagerService(IUserService userService, ISezioneService sezioneService, IPermissionService permissionService, IRuoloService ruoloService, IFeatureService featureService)
|
||||||
{
|
{
|
||||||
UtenteService = userService;
|
UtenteService = userService;
|
||||||
SezioneService = sezioneService;
|
SezioneService = sezioneService;
|
||||||
PermissionService = permissionService;
|
PermissionService = permissionService;
|
||||||
RuoloService = ruoloService;
|
RuoloService = ruoloService;
|
||||||
|
FeatureService = featureService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IFeatureService FeatureService { get; set; }
|
||||||
public IPermissionService PermissionService { get; set; }
|
public IPermissionService PermissionService { get; set; }
|
||||||
public IRuoloService RuoloService { get; set; }
|
public IRuoloService RuoloService { get; set; }
|
||||||
public ISezioneService SezioneService { get; set; }
|
public ISezioneService SezioneService { get; set; }
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
<base href="/"/>
|
<base href="/"/>
|
||||||
<link rel="stylesheet" href="bootstrap/bootstrap.min.css"/>
|
<link rel="stylesheet" href="bootstrap/bootstrap.min.css"/>
|
||||||
<link rel="stylesheet" href="app.css"/>
|
<link rel="stylesheet" href="app.css"/>
|
||||||
|
<link rel="stylesheet" href="css/space.css"/>
|
||||||
<link rel="stylesheet" href="TecniStamp.styles.css"/>
|
<link rel="stylesheet" href="TecniStamp.styles.css"/>
|
||||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
@page "/anagrafiche"
|
@page "/anagrafiche"
|
||||||
|
|
||||||
@using Microsoft.EntityFrameworkCore
|
@using Microsoft.EntityFrameworkCore
|
||||||
@using TecniStamp.Components.Widget
|
|
||||||
@using TecniStamp.Model.Common
|
@using TecniStamp.Model.Common
|
||||||
@using TecniStamp.Utils
|
@using TecniStamp.Utils
|
||||||
|
|
||||||
|
<PageTitle>Anagrafiche</PageTitle>
|
||||||
<Breadcrumb Items="BreadcrumbList" />
|
<Breadcrumb Items="BreadcrumbList" />
|
||||||
|
|
||||||
<main role="main">
|
<main role="main">
|
||||||
|
|||||||
@ -1,23 +1,19 @@
|
|||||||
@page "/Anagrafiche/Operatori"
|
@page "/Anagrafiche/Operatori"
|
||||||
@using Microsoft.EntityFrameworkCore
|
@using Microsoft.EntityFrameworkCore
|
||||||
@using TecniStamp.Domain
|
|
||||||
@using TecniStamp.Model
|
@using TecniStamp.Model
|
||||||
|
@using TecniStamp.Model.Common
|
||||||
@using TecniStamp.Utils
|
@using TecniStamp.Utils
|
||||||
|
|
||||||
@rendermode InteractiveServer
|
@rendermode InteractiveServer
|
||||||
@inject AuthenticationStateProvider auth
|
@inject AuthenticationStateProvider auth
|
||||||
|
|
||||||
<PageTitle>Operatori</PageTitle>
|
<PageTitle>Operatori</PageTitle>
|
||||||
|
<Breadcrumb Items="BreadcrumbList" />
|
||||||
|
|
||||||
<div class="page-wrapper">
|
<main role="main">
|
||||||
<!-- BEGIN PAGE BODY -->
|
<div class="container-fluid h-100 mt-5">
|
||||||
<div class="page-body">
|
<div class="row justify-content-start">
|
||||||
<div class="container-xl">
|
|
||||||
<div class="row row-cards">
|
<div class="row row-cards">
|
||||||
<div class="col">
|
|
||||||
<!-- Page pre-title -->
|
|
||||||
<h2 class="page-title">Operatori</h2>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto ms-auto">
|
<div class="col-auto ms-auto">
|
||||||
<div class="btn-list">
|
<div class="btn-list">
|
||||||
<a href="/Anagrafiche/Operatori/Modifica" class="btn btn-primary btn-5 d-none d-sm-inline-block">
|
<a href="/Anagrafiche/Operatori/Modifica" class="btn btn-primary btn-5 d-none d-sm-inline-block">
|
||||||
@ -51,11 +47,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
List<UserViewModel> utenti;
|
List<UserViewModel> utenti;
|
||||||
RadzenDataGrid<UserViewModel> userGrid;
|
RadzenDataGrid<UserViewModel> userGrid;
|
||||||
|
public List<BreadcrumbViewModel> BreadcrumbList { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Carica la lista degli utenti non eliminati, ordinandoli per cognome e nome.
|
/// Carica la lista degli utenti non eliminati, ordinandoli per cognome e nome.
|
||||||
@ -69,6 +66,8 @@
|
|||||||
includi: x => x.Include(y => y.Ruolo),
|
includi: x => x.Include(y => y.Ruolo),
|
||||||
ordinamento: x => x.OrderBy(y => y.Cognome).ThenBy(z => z.Nome)))
|
ordinamento: x => x.OrderBy(y => y.Cognome).ThenBy(z => z.Nome)))
|
||||||
.Select(x => (UserViewModel)x).ToList();
|
.Select(x => (UserViewModel)x).ToList();
|
||||||
|
|
||||||
|
BreadcrumbList = await BreadcrumbUtils.BuildBreadcrumbByFeature(_managerService, "Operatori_Insert");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -2,28 +2,26 @@
|
|||||||
@page "/Anagrafiche/Operatori/Modifica/{UserId:guid}"
|
@page "/Anagrafiche/Operatori/Modifica/{UserId:guid}"
|
||||||
@using Microsoft.AspNetCore.Identity
|
@using Microsoft.AspNetCore.Identity
|
||||||
@using Microsoft.EntityFrameworkCore
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
|
||||||
@using TecniStamp.Domain
|
@using TecniStamp.Domain
|
||||||
@using TecniStamp.Model
|
@using TecniStamp.Model
|
||||||
|
@using TecniStamp.Utils
|
||||||
|
|
||||||
|
@using TecniStamp.Model.Common
|
||||||
|
|
||||||
@rendermode InteractiveServer
|
@rendermode InteractiveServer
|
||||||
|
|
||||||
<PageTitle>@pageTitle</PageTitle>
|
<PageTitle>@pageTitle</PageTitle>
|
||||||
|
<Breadcrumb Items="BreadcrumbList" />
|
||||||
|
|
||||||
<div class="page-wrapper">
|
<main role="main">
|
||||||
<!-- BEGIN PAGE HEADER -->
|
<div class="container-fluid h-100 mt-5">
|
||||||
<div class="page-header d-print-none" aria-label="Page header">
|
<div class="row justify-content-start">
|
||||||
<div class="container-xl">
|
<div class="row row-cards">
|
||||||
<div class="row g-2 align-items-center">
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h2 class="page-title">@pageTitle</h2>
|
<h2 class="page-title">@pageTitle</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- END PAGE HEADER -->
|
|
||||||
<!-- BEGIN PAGE BODY -->
|
|
||||||
<div class="page-body">
|
|
||||||
<div class="container-xl">
|
|
||||||
<div class="row row-cards">
|
<div class="row row-cards">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@ -87,8 +85,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter] public Guid? UserId { get; set; }
|
[Parameter] public Guid? UserId { get; set; }
|
||||||
@ -98,6 +95,7 @@
|
|||||||
private string pageTitle => Model?.Id == Guid.Empty ? "Nuovo operatore" : $"Modifica operatore {Model}";
|
private string pageTitle => Model?.Id == Guid.Empty ? "Nuovo operatore" : $"Modifica operatore {Model}";
|
||||||
private List<RuoloViewModel> ruoli { get; set; } = new();
|
private List<RuoloViewModel> ruoli { get; set; } = new();
|
||||||
|
|
||||||
|
public List<BreadcrumbViewModel> BreadcrumbList { get; set; } = new();
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
@ -109,6 +107,8 @@
|
|||||||
|
|
||||||
ruoli = (await _managerService.RuoloService.RicercaQueryable(x => x.Eliminato == false))
|
ruoli = (await _managerService.RuoloService.RicercaQueryable(x => x.Eliminato == false))
|
||||||
.Select(x => (RuoloViewModel)x).ToList();
|
.Select(x => (RuoloViewModel)x).ToList();
|
||||||
|
|
||||||
|
BreadcrumbList = await BreadcrumbUtils.BuildBreadcrumbByFeature(_managerService, "Operatori_Insert", "Modifica", "/Anagrafiche/Operatori");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
@using Microsoft.EntityFrameworkCore
|
@using Microsoft.EntityFrameworkCore
|
||||||
@using TecniStamp.Model
|
@using TecniStamp.Model
|
||||||
|
|
||||||
|
@rendermode InteractiveServer
|
||||||
|
|
||||||
<PageTitle>Ruoli</PageTitle>
|
<PageTitle>Ruoli</PageTitle>
|
||||||
|
|
||||||
<div class="page-wrapper">
|
<div class="page-wrapper">
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
@page "/Anagrafiche/ruoli/Modifica"
|
@page "/Anagrafiche/ruoli/Modifica"
|
||||||
@page "/Anagrafiche/ruoli/Modifica/{RuoloId:guid}"
|
@page "/Anagrafiche/ruoli/Modifica/{RuoloId:guid}"
|
||||||
@using Microsoft.AspNetCore.Identity
|
|
||||||
@using Microsoft.EntityFrameworkCore
|
|
||||||
@using TecniStamp.Domain
|
@using TecniStamp.Domain
|
||||||
@using TecniStamp.Model
|
@using TecniStamp.Model
|
||||||
|
|
||||||
|
|||||||
@ -1,130 +1,223 @@
|
|||||||
@page "/Carico"
|
@page "/carico"
|
||||||
|
@using System.Globalization
|
||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
@using TecniStamp.Model.Carico
|
@using TecniStamp.Model.Carico
|
||||||
|
@using TecniStamp.Model.Common
|
||||||
|
@using TecniStamp.Utils
|
||||||
|
|
||||||
<RadzenDataGrid Data="@righe" TItem="CalendarioRigaViewModel"
|
<PageTitle>Carico Macchinari</PageTitle>
|
||||||
ColumnWidth="120px"
|
<Breadcrumb Items="BreadcrumbList" />
|
||||||
AllowFiltering="false"
|
|
||||||
AllowSorting="false">
|
|
||||||
|
|
||||||
<Columns>
|
<main role="main">
|
||||||
<!-- Colonna fissa -->
|
<div class="container-fluid h-100 mt-10">
|
||||||
<RadzenDataGridColumn TItem="CalendarioRigaViewModel"
|
<div class="row justify-content-start">
|
||||||
Property="Lavorazione"
|
<div class="calendar-wrapper">
|
||||||
Title="Lavorazione"
|
<div class="calendar-scroll">
|
||||||
Frozen="true"
|
<table class="calendar-table">
|
||||||
Width="100px" />
|
<thead>
|
||||||
|
<!-- Riga MESI -->
|
||||||
|
<tr class="month-row">
|
||||||
|
<th class="sticky-col month-spacer"></th>
|
||||||
|
|
||||||
<!-- Colonne dinamiche: settimane -->
|
@foreach (var m in mesiHeader)
|
||||||
@foreach (var settimana in settimane)
|
|
||||||
{
|
{
|
||||||
<RadzenDataGridColumn TItem="CalendarioRigaViewModel"
|
<th class="month-cell" colspan="@m.ColSpan">
|
||||||
Title="@($"SETTIMANA {settimana.Numero}")"
|
@m.Nome
|
||||||
Width="175px">
|
</th>
|
||||||
<Template Context="riga">
|
|
||||||
@{
|
|
||||||
riga.Settimane.TryGetValue(settimana.Numero, out var cella);
|
|
||||||
}
|
}
|
||||||
|
</tr>
|
||||||
|
|
||||||
@if (cella != null)
|
<!-- Riga SETTIMANE -->
|
||||||
|
<tr class="week-row">
|
||||||
|
<th class="sticky-col week-spacer">Lavorazione</th>
|
||||||
|
|
||||||
|
@foreach (var s in settimane)
|
||||||
|
{
|
||||||
|
<th class="week-cell">
|
||||||
|
SETTIMANA @s.Numero
|
||||||
|
</th>
|
||||||
|
}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach (var riga in righe)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td class="sticky-col row-title">
|
||||||
|
@riga.Lavorazione
|
||||||
|
</td>
|
||||||
|
|
||||||
|
@foreach (var s in settimane)
|
||||||
|
{
|
||||||
|
riga.Settimane.TryGetValue(s.Numero, out var cella);
|
||||||
|
|
||||||
|
<td class="data-cell">
|
||||||
|
@if (cella is not null)
|
||||||
{
|
{
|
||||||
<div class="calendar-card">
|
<div class="calendar-card">
|
||||||
<div class="card-header">
|
<div class="card-top">
|
||||||
<span class="status">@cella.Stato</span>
|
<span class="status">@cella.Stato</span>
|
||||||
|
|
||||||
|
<div class="card-actions">
|
||||||
|
<RadzenButton Text="Vedi dettaglio"
|
||||||
|
Size="ButtonSize.Small"
|
||||||
|
ButtonStyle="ButtonStyle.Light"
|
||||||
|
Click="@(() => ApriDettaglio(riga, s, cella))"/>
|
||||||
<RadzenButton Icon="more_horiz"
|
<RadzenButton Icon="more_horiz"
|
||||||
Size="ButtonSize.Small"
|
Size="ButtonSize.Small"
|
||||||
ButtonStyle="ButtonStyle.Light" />
|
ButtonStyle="ButtonStyle.Light"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<small>Commesse: @cella.Stato</small>
|
<div class="sub">Commesse: @cella.Commesse</div>
|
||||||
|
<div class="sub small">@cella.Ore/@cella.Capacita h</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RadzenProgressBar Value="@cella.Percentuale"
|
<RadzenProgressBar Value="@cella.Percentuale"
|
||||||
ShowValue="false"
|
ShowValue="true"
|
||||||
Unit="%"
|
Unit="%"
|
||||||
Style="height:12px"
|
ProgressBarStyle="@GetProgressStyle(cella.Percentuale)"
|
||||||
Color="@GetColor(cella.Percentuale)" />
|
Style="height:8px"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</Template>
|
</td>
|
||||||
</RadzenDataGridColumn>
|
|
||||||
}
|
}
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
</Columns>
|
@code
|
||||||
</RadzenDataGrid>
|
{
|
||||||
|
// ====== DATA ======
|
||||||
|
|
||||||
@code {
|
|
||||||
private List<SettimanaViewModel> settimane = new();
|
private List<SettimanaViewModel> settimane = new();
|
||||||
|
private List<MeseHeaderViewModel> mesiHeader = new();
|
||||||
private List<CalendarioRigaViewModel> righe = new();
|
private List<CalendarioRigaViewModel> righe = new();
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
|
public List<BreadcrumbViewModel> BreadcrumbList { get; set; } = new();
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
await base.OnInitializedAsync();
|
settimane = GeneraSettimaneDaPrimoGennaio(2026);
|
||||||
settimane = GeneraSettimaneAnno(2026);
|
|
||||||
var settimanePerMese = settimane
|
// Header mesi: raggruppa le settimane per mese (in base alla data di inizio settimana)
|
||||||
.GroupBy(s => new { s.Anno, Mese = s.Inizio.Month })
|
mesiHeader = settimane
|
||||||
.Select(g => new
|
.GroupBy(s => s.Inizio.Month)
|
||||||
|
.Select(g => new MeseHeaderViewModel
|
||||||
{
|
{
|
||||||
Mese = g.Key.Mese,
|
Mese = g.Key,
|
||||||
Nome = new DateTime(2026, g.Key.Mese, 1).ToString("MMMM").ToUpper(),
|
Nome = new DateTime(2026, g.Key, 1).ToString("MMMM", CultureInfo.GetCultureInfo("it-IT")).ToUpperInvariant(),
|
||||||
Count = g.Count()
|
ColSpan = g.Count()
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
// Mock righe/celle
|
||||||
righe = new List<CalendarioRigaViewModel>
|
righe = new List<CalendarioRigaViewModel>
|
||||||
{
|
{
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
Lavorazione = "Taglio laser – Commessa A",
|
Lavorazione = "TAGLIO",
|
||||||
Settimane = new Dictionary<int, CalendarioCellaViewModel>
|
Settimane =
|
||||||
{
|
{
|
||||||
[6] = new() { Ore = 16, Stato = "InCorso", Percentuale = 50 },
|
[3] = new() { Ore = 90, Capacita = 100, Stato = "Estremamente Saturo", Commesse = "24-24, 25-25, ..." },
|
||||||
[7] = new() { Ore = 24, Stato = "InCorso", Percentuale = 75 }
|
[4] = new() { Ore = 100, Capacita = 100, Stato = "Saturo", Commesse = "16-24, 28-24, ..." }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = 2,
|
Id = 2,
|
||||||
Lavorazione = "Saldatura – Commessa A",
|
Lavorazione = "TORNITURA",
|
||||||
Settimane = new Dictionary<int, CalendarioCellaViewModel>
|
Settimane =
|
||||||
{
|
{
|
||||||
[7] = new() { Ore = 32, Stato = "Pianificato", Percentuale = 40},
|
[1] = new() { Ore = 100, Capacita = 100, Stato = "Saturo", Commesse = "15-24, 25-24, ..." },
|
||||||
[8] = new() { Ore = 16, Stato = "Pianificato", Percentuale = 60}
|
[5] = new() { Ore = 60, Capacita = 100, Stato = "Non Saturo", Commesse = "35-25, 65-25, ..." }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = 3,
|
Id = 3,
|
||||||
Lavorazione = "Verniciatura – Commessa B",
|
Lavorazione = "FRESATURA",
|
||||||
Settimane = new Dictionary<int, CalendarioCellaViewModel>
|
Settimane =
|
||||||
{
|
{
|
||||||
[8] = new() { Ore = 40, Stato = "Pianificato", Percentuale = 90}
|
[2] = new() { Ore = 40, Capacita = 100, Stato = "Non Saturo", Commesse = "12-11, 44-11, ..." },
|
||||||
|
[3] = new() { Ore = 100, Capacita = 100, Stato = "Saturo", Commesse = "17-22, 19-22, ..." }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SettimanaViewModel> GeneraSettimaneAnno(int anno)
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
|
||||||
|
BreadcrumbList = await BreadcrumbUtils.BuildBreadcrumbByFeature(_managerService, "Carico_Info");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApriDettaglio(CalendarioRigaViewModel riga, SettimanaViewModel settimana, CalendarioCellaViewModel cella)
|
||||||
|
{
|
||||||
|
// qui ci attacchi un RadzenDialogService se vuoi
|
||||||
|
// es: DialogService.Open(...)
|
||||||
|
|
||||||
|
Console.WriteLine($"Dettaglio: {riga.Lavorazione} - W{settimana.Numero} - {cella.Ore}/{cella.Capacita}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProgressBarStyle GetProgressStyle(int percentuale)
|
||||||
|
{
|
||||||
|
// taralo come vuoi
|
||||||
|
if (percentuale >= 100) return ProgressBarStyle.Success;
|
||||||
|
if (percentuale >= 80) return ProgressBarStyle.Warning;
|
||||||
|
return ProgressBarStyle.Info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== ISO WEEKS (corretto) ======
|
||||||
|
private static List<SettimanaViewModel> GeneraSettimaneISO(int anno)
|
||||||
|
{
|
||||||
|
var list = new List<SettimanaViewModel>();
|
||||||
|
|
||||||
|
// ISOWeek è disponibile su .NET 6+ (quindi ok per Blazor moderno)
|
||||||
|
int weeksInYear = ISOWeek.GetWeeksInYear(anno);
|
||||||
|
|
||||||
|
for (int w = 1; w <= weeksInYear; w++)
|
||||||
|
{
|
||||||
|
// Lunedì della settimana ISO
|
||||||
|
DateTime start = ISOWeek.ToDateTime(anno, w, DayOfWeek.Monday);
|
||||||
|
DateTime end = start.AddDays(6);
|
||||||
|
|
||||||
|
list.Add(new SettimanaViewModel
|
||||||
|
{
|
||||||
|
Anno = anno,
|
||||||
|
Numero = w,
|
||||||
|
Inizio = start,
|
||||||
|
Fine = end
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<SettimanaViewModel> GeneraSettimaneDaPrimoGennaio(int anno)
|
||||||
{
|
{
|
||||||
var settimane = new List<SettimanaViewModel>();
|
var settimane = new List<SettimanaViewModel>();
|
||||||
|
|
||||||
// ISO: settimana 1 = quella che contiene il 4 gennaio
|
var start = new DateTime(anno, 1, 1);
|
||||||
var jan4 = new DateTime(anno, 1, 4);
|
var endOfYear = new DateTime(anno, 12, 31);
|
||||||
|
|
||||||
// lunedì della settimana 1
|
int weekNumber = 1;
|
||||||
var startOfWeek1 = jan4.AddDays(-(int)(jan4.DayOfWeek == DayOfWeek.Sunday
|
var currentStart = start;
|
||||||
? 6
|
|
||||||
: jan4.DayOfWeek - DayOfWeek.Monday));
|
|
||||||
|
|
||||||
var currentStart = startOfWeek1;
|
while (currentStart <= endOfYear)
|
||||||
var weekNumber = 1;
|
|
||||||
|
|
||||||
while (currentStart.Year <= anno)
|
|
||||||
{
|
{
|
||||||
var currentEnd = currentStart.AddDays(6);
|
var currentEnd = currentStart.AddDays(6);
|
||||||
|
if (currentEnd > endOfYear)
|
||||||
|
currentEnd = endOfYear;
|
||||||
|
|
||||||
settimane.Add(new SettimanaViewModel
|
settimane.Add(new SettimanaViewModel
|
||||||
{
|
{
|
||||||
@ -140,9 +233,4 @@
|
|||||||
|
|
||||||
return settimane;
|
return settimane;
|
||||||
}
|
}
|
||||||
|
|
||||||
object GetColor(int valuePercentuale)
|
|
||||||
{
|
|
||||||
return "Red";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,35 +1,118 @@
|
|||||||
.calendar-month-header {
|
.calendar-wrapper {
|
||||||
display: grid;
|
border: 1px solid #ddd;
|
||||||
grid-template-columns: 250px repeat(53, 120px);
|
border-radius: 6px;
|
||||||
border-bottom: 1px solid #ddd;
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-scroll {
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 70vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
table-layout: fixed;
|
||||||
|
width: max-content; /* importantissimo per far lavorare lo scroll orizzontale */
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* larghezze: devono combaciare con il tuo mock */
|
||||||
|
.calendar-table th,
|
||||||
|
.calendar-table td {
|
||||||
|
border: 1px solid #e3e3e3;
|
||||||
|
width: 120px;
|
||||||
|
min-width: 120px;
|
||||||
|
padding: 8px;
|
||||||
|
vertical-align: top;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Colonna sticky (lavorazioni) */
|
||||||
|
.sticky-col {
|
||||||
|
position: sticky;
|
||||||
|
left: 0;
|
||||||
|
z-index: 3;
|
||||||
|
width: 250px !important;
|
||||||
|
min-width: 250px !important;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* header sticky in alto */
|
||||||
|
thead th {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 4;
|
||||||
|
background: #f5f5f5;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* incrocio sticky (top + left) */
|
||||||
|
thead .sticky-col {
|
||||||
|
z-index: 6;
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.month-header {
|
.month-row th {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 600;
|
font-size: 12px;
|
||||||
padding: 8px 0;
|
letter-spacing: .5px;
|
||||||
border-left: 1px solid #ddd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.month-spacer {
|
.week-row th {
|
||||||
border-right: 1px solid #ddd;
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-title {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #666;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-cell {
|
||||||
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-card {
|
.calendar-card {
|
||||||
background: #f7f7f7;
|
background: #f7f7f7;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
padding: 6px;
|
padding: 8px;
|
||||||
box-shadow: inset 0 0 0 1px #ddd;
|
box-shadow: inset 0 0 0 1px #dedede;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-header {
|
.card-top {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: start;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-size: 12px;
|
gap: 8px;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status {
|
.status {
|
||||||
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
color: #444;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body .sub {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body .small {
|
||||||
|
font-size: 10px;
|
||||||
|
color: #888;
|
||||||
}
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
@page "/commesse"
|
||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
@using TecniStamp.Model.Common
|
||||||
|
@using TecniStamp.Utils
|
||||||
|
|
||||||
|
<PageTitle>Commesse</PageTitle>
|
||||||
|
<Breadcrumb Items="BreadcrumbList" />
|
||||||
|
|
||||||
|
@code {
|
||||||
|
public List<BreadcrumbViewModel> BreadcrumbList { get; set; } = new();
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
|
||||||
|
BreadcrumbList = await BreadcrumbUtils.BuildBreadcrumbByFeature(_managerService, "Commesse_Info");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
@using Microsoft.AspNetCore.Authorization
|
@using Microsoft.AspNetCore.Authorization
|
||||||
@using Microsoft.EntityFrameworkCore
|
@using Microsoft.EntityFrameworkCore
|
||||||
@using TecniStamp.Components.Widget
|
|
||||||
@using TecniStamp.Model.Common
|
@using TecniStamp.Model.Common
|
||||||
@using TecniStamp.Utils
|
@using TecniStamp.Utils
|
||||||
|
|
||||||
|
<PageTitle>Home</PageTitle>
|
||||||
<Breadcrumb Items="BreadcrumbList" />
|
<Breadcrumb Items="BreadcrumbList" />
|
||||||
|
|
||||||
<main role="main">
|
<main role="main">
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
@using Microsoft.JSInterop
|
@using Microsoft.JSInterop
|
||||||
@using TecniStamp
|
@using TecniStamp
|
||||||
@using TecniStamp.Components
|
@using TecniStamp.Components
|
||||||
|
@using TecniStamp.Components.Widget
|
||||||
|
|
||||||
@using Radzen
|
@using Radzen
|
||||||
@using Radzen.Blazor
|
@using Radzen.Blazor
|
||||||
|
|||||||
@ -3,6 +3,22 @@
|
|||||||
public class CalendarioCellaViewModel
|
public class CalendarioCellaViewModel
|
||||||
{
|
{
|
||||||
public int Ore { get; set; }
|
public int Ore { get; set; }
|
||||||
|
public int Capacita { get; set; } = 100;
|
||||||
public string Stato { get; set; }
|
public string Stato { get; set; }
|
||||||
|
public string Commesse { get; set; } = "";
|
||||||
public int Percentuale { get; set; }
|
public int Percentuale { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class MeseHeaderViewModel
|
||||||
|
{
|
||||||
|
public int Mese { get; set; }
|
||||||
|
public string Nome { get; set; } = "";
|
||||||
|
public int ColSpan { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CalendarioHeaderViewModel
|
||||||
|
{
|
||||||
|
public int Mese { get; set; }
|
||||||
|
public string Nome { get; set; }
|
||||||
|
public int Count { get; set; }
|
||||||
|
}
|
||||||
@ -1,11 +1,25 @@
|
|||||||
using TecniStamp.Domain;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using TecniStamp.Domain;
|
||||||
using TecniStamp.Model.Common;
|
using TecniStamp.Model.Common;
|
||||||
|
using TecniStamp.Service.Interfaces;
|
||||||
|
|
||||||
namespace TecniStamp.Utils;
|
namespace TecniStamp.Utils;
|
||||||
|
|
||||||
public static class BreadcrumbUtils
|
public static class BreadcrumbUtils
|
||||||
{
|
{
|
||||||
public static List<BreadcrumbViewModel> BuildBreadcrumb(Sezione sezione)
|
public static async Task<List<BreadcrumbViewModel>> BuildBreadcrumbByFeature(IManagerService _managerService, string featureName,
|
||||||
|
string? extraText = null,
|
||||||
|
string? parentUrlOverride = null)
|
||||||
|
{
|
||||||
|
var section = await _managerService.FeatureService.RicercaPer(x => x.Nome == featureName,
|
||||||
|
includi:x => x.Include(y => y.Sezione).ThenInclude(x => x.Parent));
|
||||||
|
return BuildBreadcrumb(section.Sezione, extraText, parentUrlOverride);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<BreadcrumbViewModel> BuildBreadcrumb(
|
||||||
|
Sezione sezione,
|
||||||
|
string? extraText = null,
|
||||||
|
string? parentUrlOverride = null)
|
||||||
{
|
{
|
||||||
var stack = new Stack<Sezione>();
|
var stack = new Stack<Sezione>();
|
||||||
var current = sezione;
|
var current = sezione;
|
||||||
@ -37,9 +51,30 @@ public static class BreadcrumbUtils
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
breadcrumb.Last().IsActive = true;
|
if (!string.IsNullOrWhiteSpace(extraText))
|
||||||
breadcrumb.Last().Url = null;
|
{
|
||||||
|
// 🔹 rendo cliccabile il penultimo (la sezione)
|
||||||
|
var parent = breadcrumb.Last();
|
||||||
|
parent.IsActive = false;
|
||||||
|
parent.Url = parentUrlOverride;
|
||||||
|
|
||||||
|
// 🔹 aggiungo la voce finale custom
|
||||||
|
breadcrumb.Add(new BreadcrumbViewModel
|
||||||
|
{
|
||||||
|
Text = extraText,
|
||||||
|
Url = null,
|
||||||
|
IsActive = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// comportamento originale (index)
|
||||||
|
var last = breadcrumb.Last();
|
||||||
|
last.IsActive = true;
|
||||||
|
last.Url = null;
|
||||||
|
}
|
||||||
|
|
||||||
return breadcrumb;
|
return breadcrumb;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user