11@page " /production-log/new"
22@page " /production-log/edit/{logId:int}"
33@using MESS .Data .Models
4+ @using MESS .Services .BrowserCacheManager
5+ @using MESS .Services .Product
46@using MESS .Services .ProductionLog
57@using MESS .Services .WorkInstruction
6- @using Serilog
8+ @using MESS .Blazor .Components .Utility
9+ @using MESS .Services .SessionManager
10+ @using MESS .Services .WorkStation
711@inject IProductionLogService ProductionLogService
812@inject NavigationManager NavigationManager
913@inject IWorkInstructionService WorkInstructionService
10- @rendermode InteractiveServer
11-
12- <EditForm FormName =" EditProductionLog" Model =" @ProductionLog" OnValidSubmit =" HandleSubmit" >
13- <DataAnnotationsValidator />
14- <div class =" mb-3" >
15- <label for =" Name" class =" form-label" >Product Name</label >
16- <div class =" col-md-4" >
17- @if (ProductionLog .Product != null )
18- {
19- <InputText class =" form-control" @bind-Value =" ProductionLog.Product.Name" />
20- <ValidationMessage For =" @(() => ProductionLog.Product.Name)" />
21- }
22- </div >
23-
24- <div >
25- @if (WorkInstructions != null )
26- {
27- <select @bind =" SelectedWorkInstructionId" >
28- <option value =" " >Select Work Instruction </option >
29- @foreach ( var instruction in WorkInstructions )
14+ @inject IProductService ProductService
15+ @inject ILocalCacheManager LocalCacheManager
16+ @inject IWorkStationService WorkStationService
17+ @inject ISessionManager SessionManager
18+
19+ <PageTitle >@Title </PageTitle >
20+ <ErrorBoundary >
21+ <ChildContent >
22+ <EditForm class =" container" FormName =" EditProductionLog" Model =" ProductionLog" OnValidSubmit =" HandleSubmit" >
23+ <DataAnnotationsValidator />
24+ <ValidationSummary />
25+ <TimeFormValidator TModel =" ProductionLog" Validator =" _validator" ></TimeFormValidator >
26+ <div class =" mb-3" >
27+ <div class =" container ps-0 d-inline-flex justify-content-between gap-4 mb-2 flex-wrap" >
28+ @if (! IsWorkflowActive && ! IsEditMode )
3029 {
31- <option value =" @instruction.Id" >@instruction.Title </option >
30+ <WorkStationSelect WorkStations =" @WorkStations" OnWorkStationSelected =" @SetActiveWorkStation" />
31+ var stationProducts = LoadAssociatedProductsFromStation ();
32+ <ProductSelect Disabled =" @(string.IsNullOrWhiteSpace(ActiveWorkStation))" Products =" @stationProducts" OnProductSelected =" @SetActiveProduct" />
3233 }
33- </select >
34-
35- }
36- </div >
37-
38- <div >
39- @if (ActiveWorkInstruction != null )
40- {
41- <ul class =" list-group list-group-numbered container" >
42- @foreach ( var step in ActiveWorkInstruction .Steps )
34+ else
4335 {
44- var logStep = ProductionLog .LogSteps ? .FirstOrDefault (ls => ls .WorkInstructionStepId == step .Id );
45- var isChecked = logStep ? .Success ?? false ;
46-
47- if (logStep == null && ProductionLog .LogSteps != null )
48- {
49- logStep = new ProductionLogStep { WorkInstructionStepId = step .Id , ProductionLogId = ProductionLog .Id };
50- ProductionLog .LogSteps .Add (logStep );
51- }
52-
53- <li class =" list-group-item btn-group mb-2" role =" group" >
54- <div class =" row" >
55- <div class =" col-8" >
56- @step.Name
57- </div >
58-
59- <div class =" col-4" >
60- <input type =" radio"
61- checked =" @isChecked"
62- autocomplete =" off"
63- @onclick =" () => ShowOptionalNotesField = !ShowOptionalNotesField"
64- class =" btn-check"
65- name =" radioBtn{@step.Name}"
66- id =" radioFailureBtn{@step.Name}"
67- @onchange =" @(e => OnStepCompleted(step, e, false))" />
68- <label class =" btn btn-outline-danger" for =" radioFailureBtn{@step.Name}" >Failure </label >
69-
70- <input type =" radio"
71- checked =" @isChecked"
72- autocomplete =" off"
73- class =" btn-check"
74- name =" radioBtn{@step.Name}"
75- id =" radioSuccessBtn{@step.Name}"
76- @onchange =" @(e => OnStepCompleted(step, e, true))" />
77- <label class =" btn btn-outline-success" for =" radioSuccessBtn{@step.Name}" >Success </label >
78- </div >
36+ <CreateHeader ActiveProduct =" @ActiveProduct" WorkStation =" @ActiveWorkStation" />
37+ }
7938
80- @if (showNotesForStep .ContainsKey (step .Id ) && showNotesForStep [step .Id ] && logStep != null )
39+ <div class =" d-inline-flex gap-4 align-items-center flex-sm-wrap" >
40+ <div class =" " >
41+ <p class =" mb-0" >
42+ @if (IsSaved )
8143 {
82- <div class =" col-12" >
83- @if (logStep != null )
84- {
85- <InputTextArea @bind-Value =" logStep.Notes" />
86- }
87- else
88- {
89- <p >Loading .. .</p >
90- }
91- </div >
44+ <span class =" badge text-bg-success p-2" >Saved </span >
9245 }
93-
46+ else
47+ {
48+ <span class =" badge text-bg-danger p-2" >Unsaved </span >
49+ }
50+ </p >
51+ </div >
52+ @if (! IsEditMode )
53+ {
54+ <div >
55+ <button type =" button" disabled =" @(WorkInstructionStatus is Status.InProgress or Status.Completed)" class =" btn btn-warning" @onclick =" HandleResetConfiguration" >Reset Configuration </button >
9456 </div >
95-
96- </li >
97- }
98- </ul >
99- }
100- </div >
101- </div >
102-
103- <div class =" form-group" >
104- <button type =" submit" class =" btn btn-primary" >Save</button >
105- </div >
106- </EditForm >
107-
108- @code {
109- [Parameter ]
110- public int ? logId { get ; set ; }
111- protected string Title = " Add" ;
112- protected ProductionLog ProductionLog = new ();
113- private Dictionary <int , bool > showNotesForStep = new ();
114-
115- private bool ShowOptionalNotesField { get ; set ; } = false ;
116- private List <WorkInstruction >? WorkInstructions { get ; set ; }
117- private WorkInstruction ? ActiveWorkInstruction { get ; set ; }
118- private int ? _selectedWorkInstructionId ;
119- private int ? SelectedWorkInstructionId
120- {
121- get => _selectedWorkInstructionId ;
122- set
123- {
124- if (_selectedWorkInstructionId == value ) return ;
125- _selectedWorkInstructionId = value ;
126- if (value .HasValue )
127- {
128- _ = LoadActiveWorkInstruction (value .Value );
129- }
130- }
131- }
132-
133- private async Task LoadActiveWorkInstruction (int id )
134- {
135- ActiveWorkInstruction = await WorkInstructionService .GetByIdAsync (id );
136-
137- if (ActiveWorkInstruction != null )
138- {
139- // For each step in the work instruction
140- foreach (var step in ActiveWorkInstruction .Steps )
141- {
142- // Try to find existing log step
143- var existingLogStep = ProductionLog .LogSteps
144- .FirstOrDefault (ls => ls .WorkInstructionStepId == step .Id );
145-
146- if (existingLogStep != null )
147- {
148- // Sync the step with existing log data
149- step .Success = existingLogStep .Success ;
150- step .SubmitTime = existingLogStep .SubmitTime ;
151- }
152- else if (! ProductionLog .LogSteps .Any ())
57+ }
58+ </div >
59+
60+ </div >
61+
62+ @if (ActiveWorkInstruction != null && ActiveProduct != null )
15363 {
154- // For new logs, initialize first step
155- if (ActiveWorkInstruction .Steps .First () == step )
156- {
157- step .SubmitTime = DateTimeOffset .UtcNow ;
158- }
64+ <WorkInstructionStepList ActiveWorkInstruction =" @ActiveWorkInstruction" ProductionLog =" ProductionLog" OnStepCompleted =" @(async (args) => await OnStepCompleted(args.Item1, args.Item2))" IsEditMode =" @IsEditMode" />
15965 }
160- }
161- }
162-
163- StateHasChanged ();
164- }
165-
166-
167-
168- protected override async Task OnInitializedAsync ()
169- {
170- WorkInstructions = await WorkInstructionService .GetAllAsync ();
171-
172- if (logId .HasValue && logId .Value != 0 )
173- {
174- await LoadExistingLog (logId .Value );
175- }
176-
177- if (ActiveWorkInstruction != null )
178- {
179- foreach (var step in ActiveWorkInstruction .Steps )
180- {
181- showNotesForStep [step .Id ] = false ;
182- }
183- }
184- }
185-
186- private async Task LoadExistingLog (int id )
187- {
188- var existingProductionLog = await ProductionLogService .GetByIdAsync (id );
189- if (existingProductionLog != null )
190- {
191- Title = " Edit" ;
192- ProductionLog = existingProductionLog ;
193-
194- if (ProductionLog .WorkInstruction != null )
195- {
196- SelectedWorkInstructionId = ProductionLog .WorkInstruction .Id ;
197- }
198- }
199- else
200- {
201- Console .WriteLine ($" Production log with ID {id } not found." );
202- }
203- }
20466
205-
206-
207- protected async void HandleSubmit ()
208- {
209- if (ActiveWorkInstruction == null )
210- {
211- Console .WriteLine (" No Work Instruction selected." );
212- return ;
213- }
67+ </div >
68+ <div class =" d-flex justify-content-center mt-4 gap-4" >
21469
215- var currentTime = DateTimeOffset .UtcNow ;
216- foreach (var step in ActiveWorkInstruction .Steps )
217- {
218- var logStep = ProductionLog .LogSteps .FirstOrDefault (ls => ls .WorkInstructionStepId == step .Id );
219- if (logStep == null ) continue ;
220- logStep .Success = step .Success ;
221- logStep .SubmitTime = step .SubmitTime ;
222- }
223-
224-
225- ProductionLog .WorkInstruction = ActiveWorkInstruction ;
226-
227- if (logId .HasValue )
228- {
229- // Update existing log
230- ProductionLog .LastModifiedOn = currentTime ;
231- await ProductionLogService .UpdateAsync (ProductionLog );
232- }
233- else
234- {
235- // Create new log
236- ProductionLog .CreatedOn = currentTime ;
237- ProductionLog .LastModifiedOn = currentTime ;
238- ProductionLogService .Create (ProductionLog );
239- }
240-
241- Cancel ();
242- }
243-
244- private void OnStepCompleted (Step step , ChangeEventArgs e , bool success )
245- {
246- if (ActiveWorkInstruction ? .Steps == null ) return ;
247-
248- var currentTime = DateTimeOffset .UtcNow ;
249-
250- if (success )
251- {
252- step .Success = true ;
253- step .SubmitTime = currentTime ;
254- }
255- else
256- {
257- step .Success = false ;
258- step .SubmitTime = currentTime ;
259- showNotesForStep [step .Id ] = true ;
260- }
70+ @if (IsEditMode )
71+ {
72+ <div class =" d-flex align-items-center form-control" >
73+ <label for =" timePickerSubmit" class =" me-2" >Submit Time : </label >
74+ <div id =" timePickerSubmit" >
75+ <TimePicker @bind-Time =" ProductionLog.SubmitTime"
76+ Min =" @GetLatestStepTime()" Max =" null" CssClass =" mb-0" />
77+ </div >
78+ </div >
79+ }
26180
262- StateHasChanged ();
263- }
264-
265- private void Cancel ()
266- {
267- NavigationManager .NavigateTo (" /production-log" );
268- }
269- }
81+ <div class =" mb-4" >
82+ <button disabled =" @(WorkInstructionStatus is Status.NotStarted or Status.InProgress)" type =" submit" class =" btn btn-primary" >Save</button >
83+ </div >
84+
85+ </div >
86+ </EditForm >
87+ </ChildContent >
88+ <ErrorContent Context =" ex" >
89+ <div class =" alert alert-danger" role =" alert" >
90+ An error occurred: @ex.Message
91+ </div >
92+ </ErrorContent >
93+ </ErrorBoundary >
0 commit comments