commit
This commit is contained in:
@ -17,4 +17,7 @@ public class CommessaPosizione : EntitaBase
|
||||
[ForeignKey(nameof(Commessa))]
|
||||
public Guid? CommessaId { get; set; }
|
||||
public Commessa Commessa { get; set; }
|
||||
|
||||
[InverseProperty(nameof(CommessaPosizioneLavorazione.CommessaPosizione))]
|
||||
public List<CommessaPosizioneLavorazione> PosizioneLavorazioni { get; set; }
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
@page "/commesse/modifica/DettaglioLavorazioni"
|
||||
@page "/commesse/modifica/DettaglioLavorazioni/{CommessaPosizioneId:guid}/{CommessaId:guid}"
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using TecniStamp.Model.Commesse
|
||||
@using TecniStamp.Model.Common
|
||||
@using TecniStamp.Utils
|
||||
|
||||
@rendermode InteractiveServer
|
||||
<PageTitle>Dettaglio Lavorazioni</PageTitle>
|
||||
<Breadcrumb Items="BreadcrumbList" />
|
||||
|
||||
<style>
|
||||
.zoom-icon {
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.zoom-icon:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.zoom-icon:active, .zoom-icon:focus {
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid p-0 mt-5">
|
||||
|
||||
<div class="card border-0 shadow-none" style="width: 100%;">
|
||||
<div class="card-body">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h5 class="m-0 fw-bold" style="font-size: 1rem;">Dettaglio Lavorazioni posizione</h5>
|
||||
|
||||
<div class="d-flex align-items-end gap-3">
|
||||
<RadzenIcon Icon="calendar_month"
|
||||
class="zoom-icon"
|
||||
Style="font-size: 2rem; color: #3a4b67; margin-bottom: 2px;"
|
||||
@onclick="@goToCalendar" />
|
||||
|
||||
<div class="d-flex flex-column">
|
||||
<label class="text-muted mb-1" style="font-size: 12px;">Data ultima modifica:</label>
|
||||
<RadzenTextBox Disabled="true" Style="width: 130px; height: 30px;" />
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column">
|
||||
<label class="text-muted mb-1" style="font-size: 12px;">Data ultimo Check:</label>
|
||||
<RadzenTextBox Disabled="true" Style="width: 130px; height: 30px;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<RadzenDataGrid @ref="posizioneLavorazioniGrid"
|
||||
AllowFiltering="true"
|
||||
AllowColumnResize="true"
|
||||
Data="@CommessePosLavList"
|
||||
TItem="CommessaPosizioneLavorazioneViewModel"
|
||||
Style="width: 100%;">
|
||||
<Columns>
|
||||
<RadzenDataGridColumn TItem="CommessaPosizioneLavorazioneViewModel" Property="DescLavorazione" Title="Lavorazione" />
|
||||
<RadzenDataGridColumn TItem="CommessaPosizioneLavorazioneViewModel" Property="PrimoTempoPresidiato" Title="1° Tempo Presidiato" />
|
||||
<RadzenDataGridColumn TItem="CommessaPosizioneLavorazioneViewModel" Property="TempoNonPresidiato" Title="Tempo non Presidiato" />
|
||||
<RadzenDataGridColumn TItem="CommessaPosizioneLavorazioneViewModel" Property="SecondoTempoPresidiato" Title="2° Tempo Presidiato" />
|
||||
<RadzenDataGridColumn TItem="CommessaPosizioneLavorazioneViewModel" Property="NomeMacchinario" Title="Macchinario" />
|
||||
<RadzenDataGridColumn TItem="CommessaPosizioneLavorazioneViewModel" Property="Spostabile" Title="Non Spostabile" />
|
||||
<RadzenDataGridColumn TItem="CommessaPosizioneLavorazioneViewModel" Property="DataInizioPrevista" Title="Data Inizio Prev." />
|
||||
<RadzenDataGridColumn TItem="CommessaPosizioneLavorazioneViewModel" Property="DataFinePrevista" Title="Data Fine Prev." />
|
||||
</Columns>
|
||||
</RadzenDataGrid>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end gap-2">
|
||||
<div class="col-2 mb-3">
|
||||
<button type="button" class="btn btn-default w-100" @onclick="backToHome">
|
||||
Annulla
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] public Guid? CommessaPosizioneId { get; set; }
|
||||
[Parameter] public Guid? CommessaId { get; set; }
|
||||
|
||||
public List<CommessaPosizioneLavorazioneViewModel> CommessePosLavList { get; set; } = new();
|
||||
RadzenDataGrid<CommessaPosizioneLavorazioneViewModel> posizioneLavorazioniGrid;
|
||||
public List<BreadcrumbViewModel> BreadcrumbList { get; set; } = new();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
CommessePosLavList = (await _managerService.CommessaPosizioneLavorazioneService.RicercaQueryable(
|
||||
x => x.Eliminato == false && x.CommessaPosizioneId == CommessaPosizioneId,
|
||||
includi: x => x.Include(x => x.Lavorazione).Include(x => x.Macchinario)))
|
||||
.Select(x => (CommessaPosizioneLavorazioneViewModel)x).ToList();
|
||||
|
||||
BreadcrumbList = await BreadcrumbUtils.BuildBreadcrumbByFeature(_managerService, "Commesse_Info", "Modifica", "/commesse");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Torna all’elenco commesse senza applicare altre azioni.
|
||||
/// </summary>
|
||||
private void backToHome()
|
||||
{
|
||||
_navManager.NavigateTo($"/commesse/modifica/{CommessaId}");
|
||||
}
|
||||
|
||||
private void goToCalendar()
|
||||
{
|
||||
_navManager.NavigateTo($"/commesse/modifica/Pianificatore");
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
<div class="col-3 mb-3">
|
||||
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Data ordine</RadzenText>
|
||||
<RadzenDatePicker @bind-Value=@Model.DataOrdine ShowCalendarWeek DateFormat="dd/MM/yyyy" />
|
||||
<RadzenDatePicker Style="width: 100%" @bind-Value=@Model.DataOrdine ShowCalendarWeek DateFormat="dd/MM/yyyy" />
|
||||
<ValidationMessage For="@(() => Model.DataOrdine)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,6 +4,27 @@
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="row g-5">
|
||||
<div class="col-3 mb-3">
|
||||
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Riferimento cliente</RadzenText>
|
||||
<RadzenTextBox Style="width: 100%" aria-label="Nome" Value="@Model.RiferimentoCliente" Disabled />
|
||||
</div>
|
||||
|
||||
<div class="col-3 mb-3">
|
||||
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Commessa</RadzenText>
|
||||
<RadzenTextBox Style="width: 100%" ReadOnly="true" aria-label="Nome" Value="@Model.CodiceCommessa" Disabled />
|
||||
</div>
|
||||
|
||||
<div class="col-3 mb-3">
|
||||
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Commessa</RadzenText>
|
||||
<RadzenTextBox Style="width: 100%" ReadOnly="true" aria-label="Nome" Value="@Model.RagioneSocialeCliente" Disabled />
|
||||
</div>
|
||||
|
||||
<div class="col-3 mb-3">
|
||||
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Ordine N°</RadzenText>
|
||||
<RadzenTextBox Style="width: 100%" ReadOnly="true" aria-label="Nome" Value="@Model.OrdineNr" Disabled />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3 g-5">
|
||||
<div class="table-responsive">
|
||||
<RadzenDataGrid @ref="posizioniGrid" AllowFiltering="true" AllowColumnResize="true" AllowAlternatingRows="false" FilterMode="FilterMode.CheckBoxList" AllowSorting="true" PageSize="25"
|
||||
AllowPaging="true" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true"
|
||||
@ -49,7 +70,7 @@
|
||||
|
||||
private async Task EditRow(CommessaPosizioneViewModel posizione)
|
||||
{
|
||||
/*_navManager.NavigateTo($"/commesse/modifica/{commessa.Id}");*/
|
||||
_navManager.NavigateTo($"/commesse/modifica/DettaglioLavorazioni/{posizione.Id}/{Model.Id}");
|
||||
}
|
||||
|
||||
private async Task DeleteRow(CommessaPosizioneViewModel posizione)
|
||||
|
||||
@ -0,0 +1,258 @@
|
||||
@page "/commesse/modifica/Pianificatore"
|
||||
@using TecniStamp.Model.Commesse
|
||||
@using TecniStamp.Model.Common
|
||||
@using TecniStamp.Utils
|
||||
@* @page "/commesse/modifica/Pianificatore/{CommessaPosizioneId:guid}/{CommessaId:guid}" *@
|
||||
|
||||
<PageTitle>Pianificatore</PageTitle>
|
||||
<Breadcrumb Items="BreadcrumbList" />
|
||||
|
||||
<style>
|
||||
|
||||
/* Contenitore che permette lo scroll */
|
||||
.scheduler-wrapper {
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
max-height: 80vh; /* Altezza massima prima dello scroll verticale */
|
||||
border: 1px solid #dee2e6;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.scheduler-table {
|
||||
width: 100%;
|
||||
border-collapse: separate; /* Necessario per sticky */
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.scheduler-table th, .scheduler-table td {
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
border-right: 1px solid #dee2e6;
|
||||
min-width: 250px; /* Larghezza minima della colonna Giorno */
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* --- LOGICA STICKY (Blocca la prima colonna) --- */
|
||||
.sticky-col {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
background-color: white; /* Importante per coprire il testo che scorre sotto */
|
||||
z-index: 10;
|
||||
border-right: 2px solid #ccc; /* Bordo più marcato per separare */
|
||||
width: 200px;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
/* Fix per l'intestazione (deve stare sopra tutto) */
|
||||
thead tr:first-child th.sticky-col {
|
||||
z-index: 30;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
thead tr:first-child th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background-color: #f8f9fa;
|
||||
z-index: 20;
|
||||
border-bottom: 2px solid #ccc;
|
||||
}
|
||||
|
||||
/* --- STILE CARD (Simile alla tua immagine) --- */
|
||||
.job-card {
|
||||
background-color: #f4f4f4;
|
||||
border-radius: 6px;
|
||||
padding: 10px;
|
||||
border: 1px solid #e0e0e0;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.job-header {
|
||||
font-weight: bold;
|
||||
font-size: 0.85rem;
|
||||
color: #555;
|
||||
margin-bottom: 8px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.job-stats {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.65rem;
|
||||
color: #888;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-weight: bold;
|
||||
font-size: 1.1rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container-fluid pt-4 mt-5">
|
||||
<h2 class="mb-4">Calendario OE</h2>
|
||||
|
||||
@* al momento questa row con le 3 col sono solo dimostrative *@
|
||||
<div class="row mb-4 g-3">
|
||||
|
||||
<div class="col-lg-2 col-md-4 col-sm-12">
|
||||
<RadzenText TextStyle="TextStyle.Caption" class="text-muted mb-1">Reparto</RadzenText>
|
||||
<RadzenDropDown TValue="string"
|
||||
Data="@(new List<string>())"
|
||||
Placeholder="Cerca..."
|
||||
AllowFiltering="true"
|
||||
Class="w-100" />
|
||||
</div>
|
||||
|
||||
<div class="col-lg-2 col-md-4 col-sm-12">
|
||||
<RadzenText TextStyle="TextStyle.Caption" class="text-muted mb-1">Commessa</RadzenText>
|
||||
<RadzenDropDown TValue="string"
|
||||
Data="@(new List<string>())"
|
||||
Placeholder=""
|
||||
AllowFiltering="true"
|
||||
Class="w-100" />
|
||||
</div>
|
||||
|
||||
<div class="col-lg-2 col-md-4 col-sm-12">
|
||||
<RadzenText TextStyle="TextStyle.Caption" class="text-muted mb-1">Posizione</RadzenText>
|
||||
<RadzenDropDown TValue="string"
|
||||
Data="@(new List<string>())"
|
||||
Placeholder="Cerca..."
|
||||
AllowFiltering="true"
|
||||
Class="w-100" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="scheduler-wrapper shadow-sm">
|
||||
<table class="scheduler-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sticky-col text-center align-middle">
|
||||
POSIZIONI
|
||||
</th>
|
||||
|
||||
@foreach (var giorno in Giorni)
|
||||
{
|
||||
<th class="text-center">
|
||||
<div class="fw-bold">@giorno.ToString("dddd").ToUpper()</div>
|
||||
<div class="small text-muted">@giorno.ToString("dd MMM yyyy")</div>
|
||||
</th>
|
||||
}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var lavorazione in Lavorazioni)
|
||||
{
|
||||
<tr>
|
||||
<td class="sticky-col align-middle fw-bold text-secondary">
|
||||
@lavorazione.Nome
|
||||
</td>
|
||||
|
||||
@foreach (var giorno in Giorni)
|
||||
{
|
||||
<td>
|
||||
@{
|
||||
var task = lavorazione.Tasks.FirstOrDefault(t => t.Data.Date == giorno.Date);
|
||||
}
|
||||
|
||||
@if (task != null)
|
||||
{
|
||||
<div class="job-card">
|
||||
<div class="job-header">
|
||||
@task.Macchinario
|
||||
</div>
|
||||
<div class="job-stats">
|
||||
<div class="stat-box">
|
||||
<span class="stat-label">Presidiato</span>
|
||||
<span class="stat-value">@task.MinutiPresidiati m</span>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<span class="stat-label">Non Pres.</span>
|
||||
<span class="stat-value">@task.OreNonPresidiate h</span>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<span class="stat-label">Totale</span>
|
||||
<span class="stat-value">@task.MinutiTotali m</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 text-end">
|
||||
<RadzenButton Icon="edit" Size="ButtonSize.ExtraSmall" ButtonStyle="ButtonStyle.Light" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code{
|
||||
|
||||
public List<BreadcrumbViewModel> BreadcrumbList { get; set; } = new();
|
||||
|
||||
// --- VARIABILI PAGINA ---
|
||||
List<DateTime> Giorni = new();
|
||||
List<LavorazionePianificatoreModel> Lavorazioni = new();
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
// 1. Genero 30 giorni a partire da oggi
|
||||
var oggi = DateTime.Today;
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
Giorni.Add(oggi.AddDays(i));
|
||||
}
|
||||
|
||||
// 2. Creo dati finti simili alla tua immagine
|
||||
Lavorazioni.Add(new LavorazionePianificatoreModel
|
||||
{
|
||||
Nome = "LAVORAZIONE 1",
|
||||
Tasks = new List<TaskPianificatoreModel>
|
||||
{
|
||||
new TaskPianificatoreModel { Data = oggi, Macchinario = "SPINNER VC1650", MinutiPresidiati = 10, OreNonPresidiate = 6, MinutiTotali = 10 },
|
||||
new TaskPianificatoreModel { Data = oggi.AddDays(2), Macchinario = "SPINNER VC1650", MinutiPresidiati = 20, OreNonPresidiate = 4, MinutiTotali = 30 }
|
||||
}
|
||||
});
|
||||
|
||||
Lavorazioni.Add(new LavorazionePianificatoreModel
|
||||
{
|
||||
Nome = "LAVORAZIONE 2",
|
||||
Tasks = new List<TaskPianificatoreModel>
|
||||
{
|
||||
new TaskPianificatoreModel { Data = oggi, Macchinario = "SPINNER VC1650", MinutiPresidiati = 10, OreNonPresidiate = 6, MinutiTotali = 10 }
|
||||
}
|
||||
});
|
||||
|
||||
Lavorazioni.Add(new LavorazionePianificatoreModel
|
||||
{
|
||||
Nome = "LAVORAZIONE 3",
|
||||
Tasks = new List<TaskPianificatoreModel>
|
||||
{
|
||||
new TaskPianificatoreModel { Data = oggi.AddDays(1), Macchinario = "MAZAK QT200", MinutiPresidiati = 45, OreNonPresidiate = 0, MinutiTotali = 45 }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
BreadcrumbList = await BreadcrumbUtils.BuildBreadcrumbByFeature(_managerService, "Pianificatore_Info");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using TecniStamp.Domain;
|
||||
|
||||
namespace TecniStamp.Model.Commesse;
|
||||
|
||||
public class CommessaPosizioneLavorazioneViewModel : BaseViewModel
|
||||
{
|
||||
public Guid? CommessaPosizioneId { get; set; }
|
||||
public CommessaPosizione CommessaPosizione { get; set; }
|
||||
public Guid? LavorazioneId { get; set; }
|
||||
public Lavorazione Lavorazione { get; set; }
|
||||
public Guid? MacchinarioId { get; set; }
|
||||
public Macchinario Macchinario { get; set; }
|
||||
|
||||
public int PrimoTempoPresidiato { get; set; }
|
||||
public int TempoNonPresidiato { get; set; }
|
||||
public int SecondoTempoPresidiato { get; set; }
|
||||
public bool Spostabile { get; set; }
|
||||
public DateTime? DataInizioPrevista { get; set; }
|
||||
public DateTime? DataFinePrevista { get; set; }
|
||||
|
||||
public string DescLavorazione { get; set; }
|
||||
public string NomeMacchinario { get; set; }
|
||||
public override void Validate(){}
|
||||
|
||||
public static implicit operator CommessaPosizioneLavorazioneViewModel(CommessaPosizioneLavorazione model)
|
||||
{
|
||||
return model == null
|
||||
? null
|
||||
: new CommessaPosizioneLavorazioneViewModel()
|
||||
{
|
||||
DescLavorazione = model.Lavorazione?.Descrizione ?? "",
|
||||
NomeMacchinario = model.Macchinario?.Nome ?? "",
|
||||
PrimoTempoPresidiato = model.PrimoTempoPresidiato,
|
||||
TempoNonPresidiato = model.TempoNonPresidiato,
|
||||
SecondoTempoPresidiato = model.SecondoTempoPresidiato,
|
||||
Spostabile = model.Spostabile,
|
||||
DataFinePrevista = model.DataFinePrevista,
|
||||
DataInizioPrevista = model.DataInizioPrevista,
|
||||
Id = model.Id
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
namespace TecniStamp.Model.Commesse
|
||||
{
|
||||
public class LavorazionePianificatoreModel
|
||||
{
|
||||
public string Nome { get; set; }
|
||||
public List<TaskPianificatoreModel> Tasks { get; set; } = new();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
namespace TecniStamp.Model.Commesse
|
||||
{
|
||||
public class TaskPianificatoreModel
|
||||
{
|
||||
public DateTime Data { get; set; }
|
||||
public string Macchinario { get; set; }
|
||||
public int MinutiPresidiati { get; set; }
|
||||
public int OreNonPresidiate { get; set; }
|
||||
public int MinutiTotali { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user