mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 09:33:13 +00:00
- Replace all Contacts.Name with (FirstName + " " + LastName) pattern - Fix ContactService, Index.razor, QuotesPDF, QuotesDetails, CreateQuotes - Fix WorkOrderPDF, Viewworkorder, UserViewWordOrder, Addworkorders - Fix ViewTemplate, AddTemplate, Templates settings pages - Blazor project now builds successfully
506 lines
No EOL
18 KiB
Text
506 lines
No EOL
18 KiB
Text
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">WO ID:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<input type="text" class="form-control" readonly disabled @bind="model.WorkerOrderNumber" />
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">Work Order Title:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<input type="text" class="form-control" readonly disabled @bind="model.WorkerOrderTitle" />
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">Description:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<textarea class="form-control" readonly disabled rows="4" @bind="model.Description"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">PO #:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<input type="text" class="form-control" readonly disabled @bind="model.TT" />
|
|
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">TT #:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<input type="text" class="form-control" readonly disabled @bind="model.TT" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">POC:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
@if (model != null && model.Id != 0 && model.WorkOrderContacts != null)
|
|
{
|
|
foreach (var itm in model.WorkOrderContacts)
|
|
{
|
|
<span class="badge badge-info me-2">@((itm.POC?.FirstName + " " + itm.POC?.LastName).Trim())</span>
|
|
}
|
|
}
|
|
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label>Procedure</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<a href="javascript:;" @onclick="OpenPopup" class= ms-3" style="color:#7878E6 !important"><u>Sign Off</u></a>
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">Assigned To:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<label>@model.AssignToUser?.FirstName</label>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">Due Date:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<input type="date" class="form-control" readonly disabled @bind="model.DueDate" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">Priority:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<input type="text" class="form-control" readonly disabled @bind="model.Priority" />
|
|
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">Location:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<label>@model.Locations?.Name</label>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">Categories:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
@if (model != null && model.WorkOrderCategories != null)
|
|
{
|
|
foreach (var itm in model.WorkOrderCategories)
|
|
{
|
|
<span class="badge badge-info me-2">@itm.Category?.Name</span>
|
|
}
|
|
}
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label for="exampleFormControlInput1" class="form-label">Attachment:</label>
|
|
<div class="col-md-8">
|
|
|
|
@if (model.workOrderAttachments != null)
|
|
{
|
|
int q = 0;
|
|
foreach (var itm in model.workOrderAttachments)
|
|
{
|
|
q++;
|
|
<a href="@itm.Attachments" class="text-info" target="_blank"><u> View Attachment @q</u> </a>
|
|
|
|
<br />
|
|
}
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<ModalDialog @ref="@ModalDialog" Title="Sign Off">
|
|
<div class="row">
|
|
<h6>Before Photos</h6>
|
|
<div class="col-6">
|
|
<label for="exampleFormControlInput1" class="form-label">Issue:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<input type="text" class="form-control" @bind="model.BeforPhotoIssue" />
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<label for="exampleFormControlInput1" class="form-label">Attachments:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<InputFile type="file" name="attachment2" class="form-control" OnChange="@HandleFileUpload1" />
|
|
</div>
|
|
</div>
|
|
<h6>After Photos</h6>
|
|
<div class="col-6">
|
|
<label for="exampleFormControlInput1" class="form-label">Issue:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<input type="text" class="form-control" @bind="model.AfterPhotoIssue" />
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<label for="exampleFormControlInput1" class="form-label">Attachments:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<InputFile type="file" name="attachment3" class="form-control" OnChange="@HandleFileUpload2" />
|
|
</div>
|
|
</div>
|
|
<h6>Sign Off</h6>
|
|
<div class="col-6">
|
|
<label for="exampleFormControlInput1" class="form-label">Issue:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<input type="text" class="form-control" @bind="model.SignOffName" />
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<label for="exampleFormControlInput1" class="form-label">Attachments:</label>
|
|
<div class="input-group input-group-outline mt-1 mb-2">
|
|
<InputFile type="file" name="attachment4" class="form-control" OnChange="@HandleFileUpload3" />
|
|
</div>
|
|
</div>
|
|
<div class="row mt-1">
|
|
<div class="col-6">
|
|
<label class="custom-control-label text-dark" for="customRadio1">Sign:</label>
|
|
<div class="px-1 py-1" style="border: 1px solid;border-style: dashed;">
|
|
<canvas id="signatureCanvas1" width="300" height="44"></canvas>
|
|
</div>
|
|
<button type="button" class="float-end mt-2" @onclick="SaveSignature" style="border:none;border-radius:8px; background-color: #babcc2;" title="Save Signature">View <i class="fa fa-eye ms-2"></i></button>
|
|
</div>
|
|
<div class="col-6">
|
|
<label class="custom-control-label text-dark" for="customRadio1">Preview</label>
|
|
<div class="px-5 py-3" style="border: 1px solid; border-style: dashed;">
|
|
<img src="@signaturePreview" class="h-5 text-center">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-12 text-end">
|
|
<button type="button" class="btn btn-sm bg-gradient-info" @onclick="ClosePopup">Close</button>
|
|
</div>
|
|
</ModalDialog>
|
|
|
|
@using SeaHavenIndustries.Components.Layout
|
|
@using SeaHavenIndustries.Data.IRepository;
|
|
@inject ISettingsRepository _service;
|
|
@inject IWorkOrderRepository _serviceworkorder;
|
|
@using Microsoft.JSInterop
|
|
@using SeaHavenIndustries.ViewModel
|
|
@using System.Text.Json
|
|
@using global::Data.SeaHavenIndustries
|
|
@inject IJSRuntime JSRuntime
|
|
@inject NavigationManager Navigation
|
|
@code {
|
|
private bool isLoading = true;
|
|
|
|
private int step = 0;
|
|
private ModalDialog? ModalDialog { get; set; }
|
|
[Parameter]
|
|
public int? id { get; set; }
|
|
private WorkOrder model = new();
|
|
private List<WorkOrder>? templates { get; set; }
|
|
private IEnumerable<ApplicationUser>? users { get; set; }
|
|
private IEnumerable<ApplicationUser>? userslist { get; set; }
|
|
private IEnumerable<Category>? category { get; set; }
|
|
private IEnumerable<Category>? categorylist { get; set; }
|
|
private IEnumerable<Locations>? locations { get; set; }
|
|
private IEnumerable<Locations>? locationslist { get; set; }
|
|
private IEnumerable<Contacts>? contacts { get; set; }
|
|
private IEnumerable<Contacts>? contactslist { get; set; }
|
|
private List<FileUploadViewModel> files = new List<FileUploadViewModel>();
|
|
|
|
List<int>? workordercontacts = new List<int>();
|
|
List<int>? workordercategories = new List<int>();
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
if (id != 0)
|
|
{
|
|
var result = await _service.ViewTemplate(id.Value);
|
|
if (result != null)
|
|
{
|
|
model = result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
model.WorkOrderContacts = new List<WorkOrderContacts>();
|
|
model.WorkOrderCategories = new List<WorkOrderCategories>();
|
|
}
|
|
}
|
|
|
|
protected void LoadcontactData(LoadDataArgs args)
|
|
{
|
|
|
|
var query = contactslist;
|
|
if (!string.IsNullOrEmpty(args.Filter))
|
|
{
|
|
query = query.Where(c => (c.FirstName + " " + c.LastName).ToLower().Contains(args.Filter.ToLower()));
|
|
}
|
|
if (query != null)
|
|
{
|
|
contacts = query.ToList();
|
|
}
|
|
InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
protected void LoadUserData(LoadDataArgs args)
|
|
{
|
|
var query = userslist;
|
|
|
|
if (!string.IsNullOrEmpty(args.Filter))
|
|
{
|
|
query = query.Where(c => c.FirstName.ToLower().Contains(args.Filter.ToLower())).ToList();
|
|
}
|
|
if (query != null)
|
|
{
|
|
users = query.ToList();
|
|
}
|
|
InvokeAsync(StateHasChanged);
|
|
}
|
|
protected void LoadLocationData(LoadDataArgs args)
|
|
{
|
|
var query = locationslist;
|
|
if (!string.IsNullOrEmpty(args.Filter))
|
|
{
|
|
query = query.Where(c => c.Name.ToLower().Contains(args.Filter.ToLower()));
|
|
}
|
|
if (query != null)
|
|
{
|
|
locations = query.ToList();
|
|
}
|
|
InvokeAsync(StateHasChanged);
|
|
}
|
|
protected void LoadcategoryData(LoadDataArgs args)
|
|
{
|
|
|
|
var query = categorylist;
|
|
|
|
if (!string.IsNullOrEmpty(args.Filter))
|
|
{
|
|
query = query.Where(c => c.Name.ToLower().Contains(args.Filter.ToLower()));
|
|
}
|
|
if (query != null)
|
|
{
|
|
category = query.ToList();
|
|
}
|
|
InvokeAsync(StateHasChanged);
|
|
}
|
|
private string signaturePreview = string.Empty;
|
|
private string signatureData = string.Empty;
|
|
private IJSObjectReference signaturePad;
|
|
|
|
protected async Task SaveSignature()
|
|
{
|
|
signatureData = await signaturePad.InvokeAsync<string>("toDataURL");
|
|
UpdateSignaturePreview();
|
|
}
|
|
private void UpdateSignaturePreview()
|
|
{
|
|
var base64Index = signatureData.IndexOf("base64,", StringComparison.OrdinalIgnoreCase);
|
|
|
|
if (base64Index != -1)
|
|
{
|
|
// Skip "base64," to get the actual base64-encoded string
|
|
var base64String = signatureData.Substring(base64Index + 7);
|
|
signaturePreview = $"data:image/png;base64,{base64String}";
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("Invalid signatureData format");
|
|
}
|
|
}
|
|
[JSInvokable]
|
|
public static Task UpdateSignatureData(string signatureData)
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
protected async Task SaveData()
|
|
{
|
|
try
|
|
{
|
|
model.SignOffSignature = await signaturePad.InvokeAsync<string>("toDataURL");
|
|
}
|
|
catch
|
|
{
|
|
|
|
}
|
|
model.istemplate = true;
|
|
model.WorkOrderContacts = null;
|
|
model.WorkOrderContacts = model.WorkOrderContacts == null ? new List<WorkOrderContacts>() : model.WorkOrderContacts;
|
|
foreach (var itm in workordercontacts)
|
|
{
|
|
model.WorkOrderContacts.Add(new WorkOrderContacts { ContactId = itm });
|
|
}
|
|
model.WorkOrderCategories = null;
|
|
model.WorkOrderCategories = model.WorkOrderCategories == null ? new List<WorkOrderCategories>() : model.WorkOrderCategories;
|
|
foreach (var itm in workordercategories)
|
|
{
|
|
model.WorkOrderCategories.Add(new WorkOrderCategories { CategoryId = itm });
|
|
}
|
|
var res = await _serviceworkorder.Addworkorder(model, files);
|
|
if (res == "success")
|
|
{
|
|
await ShowSweetAlert("Sucessfully Saved Data", "success");
|
|
var result = await _service.GetTemplates();
|
|
if (result != null)
|
|
{
|
|
templates = result;
|
|
step = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
await ShowSweetAlert(res, "error");
|
|
}
|
|
}
|
|
private int eid = 0;
|
|
protected async Task Edit(int id)
|
|
{
|
|
if (id != 0)
|
|
{
|
|
eid = id;
|
|
step = 1;
|
|
var result = await _service.ViewTemplate(id);
|
|
if (result != null)
|
|
{
|
|
model = result;
|
|
}
|
|
workordercategories = result.WorkOrderCategories
|
|
.Select(s => s.CategoryId)
|
|
.Where(value => value.HasValue)
|
|
.Select(value => value.Value)
|
|
.ToList();
|
|
workordercontacts = result.WorkOrderContacts
|
|
.Select(s => s.ContactId)
|
|
.Where(value => value.HasValue)
|
|
.Select(value => value.Value)
|
|
.ToList();
|
|
}
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
protected async Task View(int id)
|
|
{
|
|
if (id != 0)
|
|
{
|
|
step = 2;
|
|
var result = await _service.ViewTemplate(id);
|
|
if (result != null)
|
|
{
|
|
model = result;
|
|
}
|
|
workordercategories = result.WorkOrderCategories
|
|
.Select(s => s.CategoryId)
|
|
.Where(value => value.HasValue)
|
|
.Select(value => value.Value)
|
|
.ToList();
|
|
workordercontacts = result.WorkOrderContacts
|
|
.Select(s => s.ContactId)
|
|
.Where(value => value.HasValue)
|
|
.Select(value => value.Value)
|
|
.ToList();
|
|
}
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
protected async void OpenPopup()
|
|
{
|
|
ModalDialog.Open();
|
|
await JSRuntime.InvokeVoidAsync("initializedsignature1");
|
|
var canvasElement = await JSRuntime.InvokeAsync<IJSObjectReference>("document.querySelector", "#signatureCanvas1");
|
|
await canvasElement.InvokeVoidAsync("setAttribute", "data-signature-pad", "new SignaturePad()");
|
|
signaturePad = canvasElement;
|
|
await signaturePad.InvokeVoidAsync("addEventListener", "change", DotNetObjectReference.Create(this));
|
|
}
|
|
protected void ClosePopup()
|
|
{
|
|
ModalDialog.Close();
|
|
}
|
|
|
|
private async Task HandleFileUpload(InputFileChangeEventArgs e)
|
|
{
|
|
var imageFile = e.File;
|
|
files.Add(new FileUploadViewModel { file = imageFile, Name = "attachment1" });
|
|
}
|
|
private async Task HandleFileUpload1(InputFileChangeEventArgs e)
|
|
{
|
|
var imageFile = e.File;
|
|
files.Add(new FileUploadViewModel { file = imageFile, Name = "attachment2" });
|
|
}
|
|
private async Task HandleFileUpload2(InputFileChangeEventArgs e)
|
|
{
|
|
var imageFile = e.File;
|
|
files.Add(new FileUploadViewModel { file = imageFile, Name = "attachment3" });
|
|
}
|
|
private async Task HandleFileUpload3(InputFileChangeEventArgs e)
|
|
{
|
|
var imageFile = e.File;
|
|
files.Add(new FileUploadViewModel { file = imageFile, Name = "attachment4" });
|
|
}
|
|
|
|
private async Task ShowSweetAlert(string title, string icon)
|
|
{
|
|
// Display a SweetAlert dialog
|
|
await JSRuntime.InvokeVoidAsync("Swal.fire", new
|
|
{
|
|
toast = true,
|
|
showConfirmButton = false,
|
|
timer = 3000,
|
|
title = title,
|
|
icon = icon,
|
|
position = "top-end"
|
|
});
|
|
await JSRuntime.InvokeVoidAsync("closemodal");
|
|
}
|
|
private async Task Delete(int val)
|
|
{
|
|
var result = await JSRuntime.InvokeAsync<JsonElement>("Swal.fire", new
|
|
{
|
|
title = "Are you sure?",
|
|
text = "You won't be able to revert this!",
|
|
type = "warning",
|
|
showCancelButton = true,
|
|
customClass = new
|
|
{
|
|
confirmButton = "btn btn-success m-1",
|
|
cancelButton = "btn btn-danger m-1"
|
|
},
|
|
buttonsStyling = false,
|
|
confirmButtonText = "Yes, delete it!"
|
|
});
|
|
|
|
if (result.TryGetProperty("isConfirmed", out var isConfirmedProperty) && isConfirmedProperty.GetBoolean())
|
|
{
|
|
// Call your delete API here
|
|
var response = await _service.DeleteTemplate(val);
|
|
if (response == "success")
|
|
{
|
|
await JSRuntime.InvokeVoidAsync("Swal.fire", new
|
|
{
|
|
icon = "success",
|
|
title = "Deleted!",
|
|
text = "Data has been deleted.",
|
|
type = "info",
|
|
showCancelButton = false,
|
|
customClass = new
|
|
{
|
|
confirmButton = "btn btn-success",
|
|
cancelButton = "btn btn-danger"
|
|
},
|
|
buttonsStyling = false,
|
|
confirmButtonText = "Ok"
|
|
});
|
|
templates = await _service.GetTemplates();
|
|
// await JSRuntime.InvokeVoidAsync("location.reload");
|
|
}
|
|
else
|
|
{
|
|
await JSRuntime.InvokeVoidAsync("Swal.fire", new
|
|
{
|
|
title = "Not Deleted!",
|
|
text = "Unsuccessful! Cannot delete this.",
|
|
type = "danger"
|
|
});
|
|
}
|
|
}
|
|
}
|
|
private void Changestep(int val)
|
|
{
|
|
step = val;
|
|
if (val == 1)
|
|
{
|
|
model = new WorkOrder();
|
|
}
|
|
}
|
|
} |