mirror of
https://github.com/hargata/lubelog.git
synced 2025-12-10 00:46:08 -06:00
added odometer tab.
This commit is contained in:
parent
975bbadaae
commit
ae8a885b4d
@ -1,4 +1,5 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.External.Implementations;
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Filter;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Logic;
|
||||
@ -20,6 +21,7 @@ namespace CarCareTracker.Controllers
|
||||
private readonly ITaxRecordDataAccess _taxRecordDataAccess;
|
||||
private readonly IReminderRecordDataAccess _reminderRecordDataAccess;
|
||||
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
||||
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
|
||||
private readonly IReminderHelper _reminderHelper;
|
||||
private readonly IGasHelper _gasHelper;
|
||||
private readonly IUserLogic _userLogic;
|
||||
@ -34,6 +36,7 @@ namespace CarCareTracker.Controllers
|
||||
ITaxRecordDataAccess taxRecordDataAccess,
|
||||
IReminderRecordDataAccess reminderRecordDataAccess,
|
||||
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
||||
IOdometerRecordDataAccess odometerRecordDataAccess,
|
||||
IFileHelper fileHelper,
|
||||
IUserLogic userLogic)
|
||||
{
|
||||
@ -45,6 +48,7 @@ namespace CarCareTracker.Controllers
|
||||
_taxRecordDataAccess = taxRecordDataAccess;
|
||||
_reminderRecordDataAccess = reminderRecordDataAccess;
|
||||
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
||||
_odometerRecordDataAccess = odometerRecordDataAccess;
|
||||
_gasHelper = gasHelper;
|
||||
_reminderHelper = reminderHelper;
|
||||
_userLogic = userLogic;
|
||||
@ -164,6 +168,11 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
numbersArray.Add(upgradeRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||
if (odometerRecords.Any())
|
||||
{
|
||||
numbersArray.Add(odometerRecords.Max(x => x.Mileage));
|
||||
}
|
||||
return numbersArray.Any() ? numbersArray.Max() : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ namespace CarCareTracker.Controllers
|
||||
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
||||
private readonly ISupplyRecordDataAccess _supplyRecordDataAccess;
|
||||
private readonly IPlanRecordDataAccess _planRecordDataAccess;
|
||||
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
|
||||
private readonly IWebHostEnvironment _webEnv;
|
||||
private readonly IConfigHelper _config;
|
||||
private readonly IFileHelper _fileHelper;
|
||||
@ -50,6 +51,7 @@ namespace CarCareTracker.Controllers
|
||||
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
||||
ISupplyRecordDataAccess supplyRecordDataAccess,
|
||||
IPlanRecordDataAccess planRecordDataAccess,
|
||||
IOdometerRecordDataAccess odometerRecordDataAccess,
|
||||
IUserLogic userLogic,
|
||||
IWebHostEnvironment webEnv,
|
||||
IConfigHelper config)
|
||||
@ -69,6 +71,7 @@ namespace CarCareTracker.Controllers
|
||||
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
||||
_supplyRecordDataAccess = supplyRecordDataAccess;
|
||||
_planRecordDataAccess = planRecordDataAccess;
|
||||
_odometerRecordDataAccess = odometerRecordDataAccess;
|
||||
_userLogic = userLogic;
|
||||
_webEnv = webEnv;
|
||||
_config = config;
|
||||
@ -143,7 +146,7 @@ namespace CarCareTracker.Controllers
|
||||
_dataAccess.DeleteVehicle(vehicleId);
|
||||
return Json(result);
|
||||
}
|
||||
#region "Bulk Imports"
|
||||
#region "Bulk Imports and Exports"
|
||||
[HttpGet]
|
||||
public IActionResult GetBulkImportModalPartialView(ImportMode mode)
|
||||
{
|
||||
@ -215,6 +218,24 @@ namespace CarCareTracker.Controllers
|
||||
return Json($"/{fileNameToExport}");
|
||||
}
|
||||
}
|
||||
else if (mode == ImportMode.OdometerRecord)
|
||||
{
|
||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
||||
var vehicleRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||
if (vehicleRecords.Any())
|
||||
{
|
||||
var exportData = vehicleRecords.Select(x => new OdometerRecordExportModel { Date = x.Date.ToShortDateString(), Notes = x.Notes, Odometer = x.Mileage.ToString() });
|
||||
using (var writer = new StreamWriter(fullExportFilePath))
|
||||
{
|
||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||
{
|
||||
csv.WriteRecords(exportData);
|
||||
}
|
||||
}
|
||||
return Json($"/{fileNameToExport}");
|
||||
}
|
||||
}
|
||||
else if (mode == ImportMode.SupplyRecord)
|
||||
{
|
||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
||||
@ -406,6 +427,17 @@ namespace CarCareTracker.Controllers
|
||||
};
|
||||
_serviceRecordDataAccess.SaveServiceRecordToVehicle(convertedRecord);
|
||||
}
|
||||
else if (mode == ImportMode.OdometerRecord)
|
||||
{
|
||||
var convertedRecord = new OdometerRecord()
|
||||
{
|
||||
VehicleId = vehicleId,
|
||||
Date = DateTime.Parse(importModel.Date),
|
||||
Mileage = int.Parse(importModel.Odometer, NumberStyles.Any),
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes
|
||||
};
|
||||
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(convertedRecord);
|
||||
}
|
||||
else if (mode == ImportMode.PlanRecord)
|
||||
{
|
||||
var progressIsEnum = Enum.TryParse(importModel.Progress, out PlanProgress parsedProgress);
|
||||
@ -1012,6 +1044,11 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
numbersArray.Add(upgradeRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||
if (odometerRecords.Any())
|
||||
{
|
||||
numbersArray.Add(odometerRecords.Max(x => x.Mileage));
|
||||
}
|
||||
return numbersArray.Any() ? numbersArray.Max() : 0;
|
||||
}
|
||||
private List<ReminderRecordViewModel> GetRemindersAndUrgency(int vehicleId, DateTime dateCompare)
|
||||
@ -1369,5 +1406,58 @@ namespace CarCareTracker.Controllers
|
||||
return Json(result);
|
||||
}
|
||||
#endregion
|
||||
#region "Odometer Records"
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
[HttpGet]
|
||||
public IActionResult GetOdometerRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
var result = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
|
||||
bool _useDescending = _config.GetUserConfig(User).UseDescending;
|
||||
if (_useDescending)
|
||||
{
|
||||
result = result.OrderByDescending(x => x.Date).ThenByDescending(x => x.Mileage).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result.OrderBy(x => x.Date).ThenBy(x => x.Mileage).ToList();
|
||||
}
|
||||
return PartialView("_OdometerRecords", result);
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult SaveOdometerRecordToVehicleId(OdometerRecordInput odometerRecord)
|
||||
{
|
||||
//move files from temp.
|
||||
odometerRecord.Files = odometerRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||
var result = _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord.ToOdometerRecord());
|
||||
return Json(result);
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetAddOdometerRecordPartialView()
|
||||
{
|
||||
return PartialView("_OdometerRecordModal", new OdometerRecordInput());
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetOdometerRecordForEditById(int odometerRecordId)
|
||||
{
|
||||
var result = _odometerRecordDataAccess.GetOdometerRecordById(odometerRecordId);
|
||||
//convert to Input object.
|
||||
var convertedResult = new OdometerRecordInput
|
||||
{
|
||||
Id = result.Id,
|
||||
Date = result.Date.ToShortDateString(),
|
||||
Mileage = result.Mileage,
|
||||
Notes = result.Notes,
|
||||
VehicleId = result.VehicleId,
|
||||
Files = result.Files
|
||||
};
|
||||
return PartialView("_OdometerRecordModal", convertedResult);
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult DeleteOdometerRecordById(int odometerRecordId)
|
||||
{
|
||||
var result = _odometerRecordDataAccess.DeleteOdometerRecordById(odometerRecordId);
|
||||
return Json(result);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
57
External/Implementations/OdometerRecordDataAccess.cs
vendored
Normal file
57
External/Implementations/OdometerRecordDataAccess.cs
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class OdometerRecordDataAccess : IOdometerRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private static string tableName = "odometerrecords";
|
||||
public List<OdometerRecord> GetOdometerRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
var odometerRecords = table.Find(Query.EQ(nameof(OdometerRecord.VehicleId), vehicleId));
|
||||
return odometerRecords.ToList() ?? new List<OdometerRecord>();
|
||||
};
|
||||
}
|
||||
public OdometerRecord GetOdometerRecordById(int odometerRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
return table.FindById(odometerRecordId);
|
||||
};
|
||||
}
|
||||
public bool DeleteOdometerRecordById(int odometerRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
table.Delete(odometerRecordId);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
public bool SaveOdometerRecordToVehicle(OdometerRecord odometerRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
table.Upsert(odometerRecord);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
public bool DeleteAllOdometerRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<OdometerRecord>(tableName);
|
||||
var odometerRecords = table.DeleteMany(Query.EQ(nameof(OdometerRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
13
External/Interfaces/IOdometerRecordDataAccess.cs
vendored
Normal file
13
External/Interfaces/IOdometerRecordDataAccess.cs
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
using CarCareTracker.Models;
|
||||
|
||||
namespace CarCareTracker.External.Interfaces
|
||||
{
|
||||
public interface IOdometerRecordDataAccess
|
||||
{
|
||||
public List<OdometerRecord> GetOdometerRecordsByVehicleId(int vehicleId);
|
||||
public OdometerRecord GetOdometerRecordById(int odometerRecordId);
|
||||
public bool DeleteOdometerRecordById(int odometerRecordId);
|
||||
public bool SaveOdometerRecordToVehicle(OdometerRecord odometerRecord);
|
||||
public bool DeleteAllOdometerRecordsByVehicleId(int vehicleId);
|
||||
}
|
||||
}
|
||||
@ -44,6 +44,12 @@
|
||||
public string Notes { get; set; }
|
||||
public string Cost { get; set; }
|
||||
}
|
||||
public class OdometerRecordExportModel
|
||||
{
|
||||
public string Date { get; set; }
|
||||
public string Odometer { get; set; }
|
||||
public string Notes { get; set; }
|
||||
}
|
||||
public class TaxRecordExportModel
|
||||
{
|
||||
public string Date { get; set; }
|
||||
|
||||
12
Models/OdometerRecord/OdometerRecord.cs
Normal file
12
Models/OdometerRecord/OdometerRecord.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class OdometerRecord
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int VehicleId { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public int Mileage { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
|
||||
}
|
||||
}
|
||||
13
Models/OdometerRecord/OdometerRecordInput.cs
Normal file
13
Models/OdometerRecord/OdometerRecordInput.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class OdometerRecordInput
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int VehicleId { get; set; }
|
||||
public string Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||
public int Mileage { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
|
||||
public OdometerRecord ToOdometerRecord() { return new OdometerRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Mileage = Mileage, Notes = Notes, Files = Files }; }
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,7 @@ builder.Services.AddSingleton<IUserAccessDataAccess, UserAccessDataAccess>();
|
||||
builder.Services.AddSingleton<IUserConfigDataAccess, UserConfigDataAccess>();
|
||||
builder.Services.AddSingleton<ISupplyRecordDataAccess, SupplyRecordDataAccess>();
|
||||
builder.Services.AddSingleton<IPlanRecordDataAccess, PlanRecordDataAccess>();
|
||||
builder.Services.AddSingleton<IOdometerRecordDataAccess, OdometerRecordDataAccess>();
|
||||
|
||||
//configure helpers
|
||||
builder.Services.AddSingleton<IFileHelper, FileHelper>();
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
<script src="~/js/reports.js" asp-append-version="true"></script>
|
||||
<script src="~/js/supplyrecord.js" asp-append-version="true"></script>
|
||||
<script src="~/js/planrecord.js" asp-append-version="true"></script>
|
||||
<script src="~/js/odometerrecord.js" asp-append-version="true"></script>
|
||||
<script src="~/lib/chart-js/chart.umd.js"></script>
|
||||
}
|
||||
<div class="lubelogger-mobile-nav" onclick="hideMobileNav()">
|
||||
@ -35,6 +36,9 @@
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.PlanRecord)" id="plan-tab" data-bs-toggle="tab" data-bs-target="#plan-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-bar-chart-steps me-2"></i>Planner</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.OdometerRecord)" id="odometer-tab" data-bs-toggle="tab" data-bs-target="#odometer-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-speedometer me-2"></i>Odometer</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.ServiceRecord)" id="servicerecord-tab" data-bs-toggle="tab" data-bs-target="#servicerecord-tab-pane" type="button" role="tab" aria-selected="true"><span class="display-3 ms-2"><i class="bi bi-card-checklist me-2"></i>Service Records</span></button>
|
||||
</li>
|
||||
@ -83,6 +87,9 @@
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.PlanRecord)" id="plan-tab" data-bs-toggle="tab" data-bs-target="#plan-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-bar-chart-steps me-2"></i>Planner</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.OdometerRecord)" id="odometer-tab" data-bs-toggle="tab" data-bs-target="#odometer-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-speedometer me-2"></i>Odometer</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.ServiceRecord)" id="servicerecord-tab" data-bs-toggle="tab" data-bs-target="#servicerecord-tab-pane" type="button" role="tab" aria-selected="true"><i class="bi bi-card-checklist me-2"></i>Service Records</button>
|
||||
</li>
|
||||
@ -125,6 +132,7 @@
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.UpgradeRecord)" id="upgrade-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.SupplyRecord)" id="supply-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.PlanRecord)" id="plan-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.OdometerRecord)" id="odometer-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="editVehicleModal" tabindex="-1" role="dialog">
|
||||
|
||||
@ -31,6 +31,9 @@
|
||||
} else if (Model == ImportMode.PlanRecord)
|
||||
{
|
||||
<a class="btn btn-link" href="/defaults/plansample.csv" target="_blank">Download Sample</a>
|
||||
} else if (Model == ImportMode.OdometerRecord)
|
||||
{
|
||||
<a class="btn btn-link" href="/defaults/odometersample.csv" target="_blank">Download Sample</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@ -72,6 +75,8 @@
|
||||
getVehicleSupplyRecords(vehicleId);
|
||||
} else if (mode == "PlanRecord"){
|
||||
getVehiclePlanRecords(vehicleId);
|
||||
} else if (mode == "OdometerRecord") {
|
||||
getVehicleOdometerRecords(vehicleId);
|
||||
}
|
||||
} else {
|
||||
errorToast("An error has occurred, please double check the data and try again.");
|
||||
|
||||
71
Views/Vehicle/_OdometerRecordModal.cshtml
Normal file
71
Views/Vehicle/_OdometerRecordModal.cshtml
Normal file
@ -0,0 +1,71 @@
|
||||
@model OdometerRecordInput
|
||||
@{
|
||||
var isNew = Model.Id == 0;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? "Add New Odometer Record" : "Edit Odometer Record")</h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddOdometerRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12">
|
||||
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
|
||||
<label for="odometerRecordDate">Date</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="odometerRecordDate" class="form-control" placeholder="Date recorded" value="@Model.Date">
|
||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||
</div>
|
||||
<label for="odometerRecordMileage">Odometer</label>
|
||||
<input type="number" id="odometerRecordMileage" class="form-control" placeholder="Odometer reading" value="@(isNew ? "" : Model.Mileage)">
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<label for="odometerRecordNotes">Notes(optional)</label>
|
||||
<textarea id="odometerRecordNotes" class="form-control" rows="5">@Model.Notes</textarea>
|
||||
@if (Model.Files.Any())
|
||||
{
|
||||
<div>
|
||||
@await Html.PartialAsync("_UploadedFiles", Model.Files)
|
||||
<label for="odometerRecordFiles">Upload more documents</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="odometerRecordFiles">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<label for="odometerRecordFiles">Upload documents(optional)</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="odometerRecordFiles">
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@if (!isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-danger" onclick="deleteOdometerRecord(@Model.Id)" style="margin-right:auto;">Delete</button>
|
||||
}
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAddOdometerRecordModal()">Cancel</button>
|
||||
@if (isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveOdometerRecordToVehicle()">Add New Odometer Record</button>
|
||||
}
|
||||
else if (!isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveOdometerRecordToVehicle(true)">Edit Odometer Record</button>
|
||||
}
|
||||
</div>
|
||||
<script>
|
||||
var uploadedFiles = [];
|
||||
getUploadedFilesFromModel();
|
||||
function getUploadedFilesFromModel() {
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
{
|
||||
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
|
||||
}
|
||||
}
|
||||
function getOdometerRecordModelData() {
|
||||
return { id: @Model.Id}
|
||||
}
|
||||
</script>
|
||||
69
Views/Vehicle/_OdometerRecords.cshtml
Normal file
69
Views/Vehicle/_OdometerRecords.cshtml
Normal file
@ -0,0 +1,69 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@{
|
||||
var enableCsvImports = config.GetUserConfig(User).EnableCsvImports;
|
||||
var hideZero = config.GetUserConfig(User).HideZero;
|
||||
}
|
||||
@model List<OdometerRecord>
|
||||
<div class="row">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="d-flex align-items-center flex-wrap">
|
||||
<span class="ms-2 badge bg-success">@($"# of Odometer Records: {Model.Count()}")</span>
|
||||
</div>
|
||||
<div>
|
||||
@if (enableCsvImports)
|
||||
{
|
||||
<div class="btn-group">
|
||||
<button onclick="showAddOdometerRecordModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square me-2"></i>Add Odometer Record</button>
|
||||
<button type="button" class="btn btn-md btn-primary btn-md mt-1 mb-1 dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<span class="visually-hidden">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" onclick="showBulkImportModal('OdometerRecord')">Import via CSV</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="exportVehicleData('OdometerRecord')">Export to CSV</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button onclick="showAddOdometerRecordModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square me-2"></i>Add Odometer Record</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row vehicleDetailTabContainer">
|
||||
<div class="col-12">
|
||||
<div class="row mt-2 showOnPrint">
|
||||
<div class="d-flex">
|
||||
<img src="/defaults/lubelogger_logo.png" />
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<thead class="sticky-top">
|
||||
<tr class="d-flex">
|
||||
<th scope="col" class="col-2 col-xl-1">Date</th>
|
||||
<th scope="col" class="col-3">Odometer</th>
|
||||
<th scope="col" class="col-7 col-xl-8">Notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (OdometerRecord odometerRecord in Model)
|
||||
{
|
||||
<tr class="d-flex" style="cursor:pointer;" onclick="showEditOdometerRecordModal(@odometerRecord.Id)">
|
||||
<td class="col-2 col-xl-1">@odometerRecord.Date.ToShortDateString()</td>
|
||||
<td class="col-3">@odometerRecord.Mileage</td>
|
||||
<td class="col-7 col-xl-8 text-truncate">@CarCareTracker.Helper.StaticHelper.TruncateStrings(odometerRecord.Notes)</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal fade" data-bs-focus="false" id="odometerRecordModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content" id="odometerRecordModalContent">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
2
wwwroot/defaults/odometersample.csv
Normal file
2
wwwroot/defaults/odometersample.csv
Normal file
@ -0,0 +1,2 @@
|
||||
Date,Odometer,Notes
|
||||
1/1/2024,260001,test test
|
||||
|
101
wwwroot/js/odometerrecord.js
Normal file
101
wwwroot/js/odometerrecord.js
Normal file
@ -0,0 +1,101 @@
|
||||
function showAddOdometerRecordModal() {
|
||||
$.get('/Vehicle/GetAddOdometerRecordPartialView', function (data) {
|
||||
if (data) {
|
||||
$("#odometerRecordModalContent").html(data);
|
||||
//initiate datepicker
|
||||
initDatePicker($('#odometerRecordDate'));
|
||||
$('#odometerRecordModal').modal('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditOdometerRecordModal(odometerRecordId) {
|
||||
$.get(`/Vehicle/GetOdometerRecordForEditById?odometerRecordId=${odometerRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#odometerRecordModalContent").html(data);
|
||||
//initiate datepicker
|
||||
initDatePicker($('#odometerRecordDate'));
|
||||
$('#odometerRecordModal').modal('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
function hideAddOdometerRecordModal() {
|
||||
$('#odometerRecordModal').modal('hide');
|
||||
}
|
||||
function deleteOdometerRecord(odometerRecordId) {
|
||||
$("#workAroundInput").show();
|
||||
Swal.fire({
|
||||
title: "Confirm Deletion?",
|
||||
text: "Deleted Odometer Records cannot be restored.",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Delete",
|
||||
confirmButtonColor: "#dc3545"
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$.post(`/Vehicle/DeleteOdometerRecordById?odometerRecordId=${odometerRecordId}`, function (data) {
|
||||
if (data) {
|
||||
hideAddOdometerRecordModal();
|
||||
successToast("Odometer Record Deleted");
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
getVehicleOdometerRecords(vehicleId);
|
||||
} else {
|
||||
errorToast("An error has occurred, please try again later.");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$("#workAroundInput").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
function saveOdometerRecordToVehicle(isEdit) {
|
||||
//get values
|
||||
var formValues = getAndValidateOdometerRecordValues();
|
||||
//validate
|
||||
if (formValues.hasError) {
|
||||
errorToast("Please check the form data");
|
||||
return;
|
||||
}
|
||||
//save to db.
|
||||
$.post('/Vehicle/SaveOdometerRecordToVehicleId', { odometerRecord: formValues }, function (data) {
|
||||
if (data) {
|
||||
successToast(isEdit ? "Odometer Record Updated" : "Odometer Record Added.");
|
||||
hideAddOdometerRecordModal();
|
||||
saveScrollPosition();
|
||||
getVehicleOdometerRecords(formValues.vehicleId);
|
||||
if (formValues.addReminderRecord) {
|
||||
setTimeout(function () { showAddReminderModal(formValues); }, 500);
|
||||
}
|
||||
} else {
|
||||
errorToast("An error has occurred, please try again later.");
|
||||
}
|
||||
})
|
||||
}
|
||||
function getAndValidateOdometerRecordValues() {
|
||||
var serviceDate = $("#odometerRecordDate").val();
|
||||
var serviceMileage = $("#odometerRecordMileage").val();
|
||||
var serviceNotes = $("#odometerRecordNotes").val();
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
var odometerRecordId = getOdometerRecordModelData().id;
|
||||
//validation
|
||||
var hasError = false;
|
||||
if (serviceDate.trim() == '') { //eliminates whitespace.
|
||||
hasError = true;
|
||||
$("#odometerRecordDate").addClass("is-invalid");
|
||||
} else {
|
||||
$("#odometerRecordDate").removeClass("is-invalid");
|
||||
}
|
||||
if (serviceMileage.trim() == '' || parseInt(serviceMileage) < 0) {
|
||||
hasError = true;
|
||||
$("#odometerRecordMileage").addClass("is-invalid");
|
||||
} else {
|
||||
$("#odometerRecordMileage").removeClass("is-invalid");
|
||||
}
|
||||
return {
|
||||
id: odometerRecordId,
|
||||
hasError: hasError,
|
||||
vehicleId: vehicleId,
|
||||
date: serviceDate,
|
||||
mileage: serviceMileage,
|
||||
notes: serviceNotes,
|
||||
files: uploadedFiles
|
||||
}
|
||||
}
|
||||
@ -36,6 +36,9 @@ $(document).ready(function () {
|
||||
case "plan-tab":
|
||||
getVehiclePlanRecords(vehicleId);
|
||||
break;
|
||||
case "odometer-tab":
|
||||
getVehicleOdometerRecords(vehicleId);
|
||||
break;
|
||||
}
|
||||
switch (e.relatedTarget.id) { //clear out previous tabs with grids in them to help with performance
|
||||
case "servicerecord-tab":
|
||||
@ -68,6 +71,9 @@ $(document).ready(function () {
|
||||
case "plan-tab":
|
||||
$("#plan-tab-pane").html("");
|
||||
break;
|
||||
case "odometer-tab":
|
||||
$("odometer-tab-pane").html("");
|
||||
break;
|
||||
}
|
||||
});
|
||||
var defaultTab = GetDefaultTab().tab;
|
||||
@ -102,6 +108,9 @@ $(document).ready(function () {
|
||||
case "PlanRecord":
|
||||
getVehiclePlanRecords(vehicleId);
|
||||
break;
|
||||
case "OdometerRecord":
|
||||
getVehicleOdometerRecords(vehicleId);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@ -131,6 +140,15 @@ function getVehiclePlanRecords(vehicleId) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function getVehicleOdometerRecords(vehicleId) {
|
||||
$.get(`/Vehicle/GetOdometerRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
$("#odometer-tab-pane").html(data);
|
||||
restoreScrollPosition();
|
||||
getVehicleHaveImportantReminders(vehicleId);
|
||||
}
|
||||
});
|
||||
}
|
||||
function getVehicleSupplyRecords(vehicleId) {
|
||||
$.get(`/Vehicle/GetSupplyRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user