mirror of
https://github.com/hargata/lubelog.git
synced 2025-12-10 17:20:15 -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.Filter;
|
||||||
using CarCareTracker.Helper;
|
using CarCareTracker.Helper;
|
||||||
using CarCareTracker.Logic;
|
using CarCareTracker.Logic;
|
||||||
@ -20,6 +21,7 @@ namespace CarCareTracker.Controllers
|
|||||||
private readonly ITaxRecordDataAccess _taxRecordDataAccess;
|
private readonly ITaxRecordDataAccess _taxRecordDataAccess;
|
||||||
private readonly IReminderRecordDataAccess _reminderRecordDataAccess;
|
private readonly IReminderRecordDataAccess _reminderRecordDataAccess;
|
||||||
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
||||||
|
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
|
||||||
private readonly IReminderHelper _reminderHelper;
|
private readonly IReminderHelper _reminderHelper;
|
||||||
private readonly IGasHelper _gasHelper;
|
private readonly IGasHelper _gasHelper;
|
||||||
private readonly IUserLogic _userLogic;
|
private readonly IUserLogic _userLogic;
|
||||||
@ -34,6 +36,7 @@ namespace CarCareTracker.Controllers
|
|||||||
ITaxRecordDataAccess taxRecordDataAccess,
|
ITaxRecordDataAccess taxRecordDataAccess,
|
||||||
IReminderRecordDataAccess reminderRecordDataAccess,
|
IReminderRecordDataAccess reminderRecordDataAccess,
|
||||||
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
||||||
|
IOdometerRecordDataAccess odometerRecordDataAccess,
|
||||||
IFileHelper fileHelper,
|
IFileHelper fileHelper,
|
||||||
IUserLogic userLogic)
|
IUserLogic userLogic)
|
||||||
{
|
{
|
||||||
@ -45,6 +48,7 @@ namespace CarCareTracker.Controllers
|
|||||||
_taxRecordDataAccess = taxRecordDataAccess;
|
_taxRecordDataAccess = taxRecordDataAccess;
|
||||||
_reminderRecordDataAccess = reminderRecordDataAccess;
|
_reminderRecordDataAccess = reminderRecordDataAccess;
|
||||||
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
||||||
|
_odometerRecordDataAccess = odometerRecordDataAccess;
|
||||||
_gasHelper = gasHelper;
|
_gasHelper = gasHelper;
|
||||||
_reminderHelper = reminderHelper;
|
_reminderHelper = reminderHelper;
|
||||||
_userLogic = userLogic;
|
_userLogic = userLogic;
|
||||||
@ -164,6 +168,11 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
numbersArray.Add(upgradeRecords.Max(x => x.Mileage));
|
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;
|
return numbersArray.Any() ? numbersArray.Max() : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ namespace CarCareTracker.Controllers
|
|||||||
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
||||||
private readonly ISupplyRecordDataAccess _supplyRecordDataAccess;
|
private readonly ISupplyRecordDataAccess _supplyRecordDataAccess;
|
||||||
private readonly IPlanRecordDataAccess _planRecordDataAccess;
|
private readonly IPlanRecordDataAccess _planRecordDataAccess;
|
||||||
|
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
|
||||||
private readonly IWebHostEnvironment _webEnv;
|
private readonly IWebHostEnvironment _webEnv;
|
||||||
private readonly IConfigHelper _config;
|
private readonly IConfigHelper _config;
|
||||||
private readonly IFileHelper _fileHelper;
|
private readonly IFileHelper _fileHelper;
|
||||||
@ -50,6 +51,7 @@ namespace CarCareTracker.Controllers
|
|||||||
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
||||||
ISupplyRecordDataAccess supplyRecordDataAccess,
|
ISupplyRecordDataAccess supplyRecordDataAccess,
|
||||||
IPlanRecordDataAccess planRecordDataAccess,
|
IPlanRecordDataAccess planRecordDataAccess,
|
||||||
|
IOdometerRecordDataAccess odometerRecordDataAccess,
|
||||||
IUserLogic userLogic,
|
IUserLogic userLogic,
|
||||||
IWebHostEnvironment webEnv,
|
IWebHostEnvironment webEnv,
|
||||||
IConfigHelper config)
|
IConfigHelper config)
|
||||||
@ -69,6 +71,7 @@ namespace CarCareTracker.Controllers
|
|||||||
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
||||||
_supplyRecordDataAccess = supplyRecordDataAccess;
|
_supplyRecordDataAccess = supplyRecordDataAccess;
|
||||||
_planRecordDataAccess = planRecordDataAccess;
|
_planRecordDataAccess = planRecordDataAccess;
|
||||||
|
_odometerRecordDataAccess = odometerRecordDataAccess;
|
||||||
_userLogic = userLogic;
|
_userLogic = userLogic;
|
||||||
_webEnv = webEnv;
|
_webEnv = webEnv;
|
||||||
_config = config;
|
_config = config;
|
||||||
@ -143,7 +146,7 @@ namespace CarCareTracker.Controllers
|
|||||||
_dataAccess.DeleteVehicle(vehicleId);
|
_dataAccess.DeleteVehicle(vehicleId);
|
||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
#region "Bulk Imports"
|
#region "Bulk Imports and Exports"
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult GetBulkImportModalPartialView(ImportMode mode)
|
public IActionResult GetBulkImportModalPartialView(ImportMode mode)
|
||||||
{
|
{
|
||||||
@ -215,6 +218,24 @@ namespace CarCareTracker.Controllers
|
|||||||
return Json($"/{fileNameToExport}");
|
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)
|
else if (mode == ImportMode.SupplyRecord)
|
||||||
{
|
{
|
||||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
||||||
@ -406,6 +427,17 @@ namespace CarCareTracker.Controllers
|
|||||||
};
|
};
|
||||||
_serviceRecordDataAccess.SaveServiceRecordToVehicle(convertedRecord);
|
_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)
|
else if (mode == ImportMode.PlanRecord)
|
||||||
{
|
{
|
||||||
var progressIsEnum = Enum.TryParse(importModel.Progress, out PlanProgress parsedProgress);
|
var progressIsEnum = Enum.TryParse(importModel.Progress, out PlanProgress parsedProgress);
|
||||||
@ -1012,6 +1044,11 @@ namespace CarCareTracker.Controllers
|
|||||||
{
|
{
|
||||||
numbersArray.Add(upgradeRecords.Max(x => x.Mileage));
|
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;
|
return numbersArray.Any() ? numbersArray.Max() : 0;
|
||||||
}
|
}
|
||||||
private List<ReminderRecordViewModel> GetRemindersAndUrgency(int vehicleId, DateTime dateCompare)
|
private List<ReminderRecordViewModel> GetRemindersAndUrgency(int vehicleId, DateTime dateCompare)
|
||||||
@ -1369,5 +1406,58 @@ namespace CarCareTracker.Controllers
|
|||||||
return Json(result);
|
return Json(result);
|
||||||
}
|
}
|
||||||
#endregion
|
#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 Notes { get; set; }
|
||||||
public string Cost { 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 class TaxRecordExportModel
|
||||||
{
|
{
|
||||||
public string Date { get; set; }
|
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<IUserConfigDataAccess, UserConfigDataAccess>();
|
||||||
builder.Services.AddSingleton<ISupplyRecordDataAccess, SupplyRecordDataAccess>();
|
builder.Services.AddSingleton<ISupplyRecordDataAccess, SupplyRecordDataAccess>();
|
||||||
builder.Services.AddSingleton<IPlanRecordDataAccess, PlanRecordDataAccess>();
|
builder.Services.AddSingleton<IPlanRecordDataAccess, PlanRecordDataAccess>();
|
||||||
|
builder.Services.AddSingleton<IOdometerRecordDataAccess, OdometerRecordDataAccess>();
|
||||||
|
|
||||||
//configure helpers
|
//configure helpers
|
||||||
builder.Services.AddSingleton<IFileHelper, FileHelper>();
|
builder.Services.AddSingleton<IFileHelper, FileHelper>();
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
<script src="~/js/reports.js" asp-append-version="true"></script>
|
<script src="~/js/reports.js" asp-append-version="true"></script>
|
||||||
<script src="~/js/supplyrecord.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/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>
|
<script src="~/lib/chart-js/chart.umd.js"></script>
|
||||||
}
|
}
|
||||||
<div class="lubelogger-mobile-nav" onclick="hideMobileNav()">
|
<div class="lubelogger-mobile-nav" onclick="hideMobileNav()">
|
||||||
@ -35,6 +36,9 @@
|
|||||||
<li class="nav-item" role="presentation">
|
<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>
|
<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>
|
||||||
|
<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">
|
<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>
|
<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>
|
</li>
|
||||||
@ -83,6 +87,9 @@
|
|||||||
<li class="nav-item" role="presentation">
|
<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>
|
<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>
|
||||||
|
<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">
|
<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>
|
<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>
|
</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.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.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.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>
|
</div>
|
||||||
<div class="modal fade" id="editVehicleModal" tabindex="-1" role="dialog">
|
<div class="modal fade" id="editVehicleModal" tabindex="-1" role="dialog">
|
||||||
|
|||||||
@ -31,6 +31,9 @@
|
|||||||
} else if (Model == ImportMode.PlanRecord)
|
} else if (Model == ImportMode.PlanRecord)
|
||||||
{
|
{
|
||||||
<a class="btn btn-link" href="/defaults/plansample.csv" target="_blank">Download Sample</a>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
@ -72,6 +75,8 @@
|
|||||||
getVehicleSupplyRecords(vehicleId);
|
getVehicleSupplyRecords(vehicleId);
|
||||||
} else if (mode == "PlanRecord"){
|
} else if (mode == "PlanRecord"){
|
||||||
getVehiclePlanRecords(vehicleId);
|
getVehiclePlanRecords(vehicleId);
|
||||||
|
} else if (mode == "OdometerRecord") {
|
||||||
|
getVehicleOdometerRecords(vehicleId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errorToast("An error has occurred, please double check the data and try again.");
|
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":
|
case "plan-tab":
|
||||||
getVehiclePlanRecords(vehicleId);
|
getVehiclePlanRecords(vehicleId);
|
||||||
break;
|
break;
|
||||||
|
case "odometer-tab":
|
||||||
|
getVehicleOdometerRecords(vehicleId);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
switch (e.relatedTarget.id) { //clear out previous tabs with grids in them to help with performance
|
switch (e.relatedTarget.id) { //clear out previous tabs with grids in them to help with performance
|
||||||
case "servicerecord-tab":
|
case "servicerecord-tab":
|
||||||
@ -68,6 +71,9 @@ $(document).ready(function () {
|
|||||||
case "plan-tab":
|
case "plan-tab":
|
||||||
$("#plan-tab-pane").html("");
|
$("#plan-tab-pane").html("");
|
||||||
break;
|
break;
|
||||||
|
case "odometer-tab":
|
||||||
|
$("odometer-tab-pane").html("");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var defaultTab = GetDefaultTab().tab;
|
var defaultTab = GetDefaultTab().tab;
|
||||||
@ -102,6 +108,9 @@ $(document).ready(function () {
|
|||||||
case "PlanRecord":
|
case "PlanRecord":
|
||||||
getVehiclePlanRecords(vehicleId);
|
getVehiclePlanRecords(vehicleId);
|
||||||
break;
|
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) {
|
function getVehicleSupplyRecords(vehicleId) {
|
||||||
$.get(`/Vehicle/GetSupplyRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
$.get(`/Vehicle/GetSupplyRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user