added upgrade tab functionality.
This commit is contained in:
@@ -99,6 +99,7 @@ namespace CarCareTracker.Controllers
|
||||
_taxRecordDataAccess.DeleteAllTaxRecordsByVehicleId(vehicleId) &&
|
||||
_noteDataAccess.DeleteNoteByVehicleId(vehicleId) &&
|
||||
_reminderRecordDataAccess.DeleteAllReminderRecordsByVehicleId(vehicleId) &&
|
||||
_upgradeRecordDataAccess.DeleteAllUpgradeRecordsByVehicleId(vehicleId) &&
|
||||
_dataAccess.DeleteVehicle(vehicleId);
|
||||
return Json(result);
|
||||
}
|
||||
@@ -544,19 +545,22 @@ namespace CarCareTracker.Controllers
|
||||
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
|
||||
var collisionRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
|
||||
var taxRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
|
||||
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
||||
if (year != default)
|
||||
{
|
||||
serviceRecords.RemoveAll(x => x.Date.Year != year);
|
||||
gasRecords.RemoveAll(x => x.Date.Year != year);
|
||||
collisionRecords.RemoveAll(x => x.Date.Year != year);
|
||||
taxRecords.RemoveAll(x => x.Date.Year != year);
|
||||
upgradeRecords.RemoveAll(x => x.Date.Year != year);
|
||||
}
|
||||
var viewModel = new CostMakeUpForVehicle
|
||||
{
|
||||
ServiceRecordSum = serviceRecords.Sum(x => x.Cost),
|
||||
GasRecordSum = gasRecords.Sum(x => x.Cost),
|
||||
CollisionRecordSum = collisionRecords.Sum(x => x.Cost),
|
||||
TaxRecordSum = taxRecords.Sum(x => x.Cost)
|
||||
TaxRecordSum = taxRecords.Sum(x => x.Cost),
|
||||
UpgradeRecordSum = upgradeRecords.Sum(x=>x.Cost)
|
||||
};
|
||||
return PartialView("_CostMakeUpReport", viewModel);
|
||||
}
|
||||
@@ -594,6 +598,11 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
numbersArray.Add(gasRecords.Max(x => x.Mileage));
|
||||
}
|
||||
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
|
||||
if (upgradeRecords.Any())
|
||||
{
|
||||
numbersArray.Add(upgradeRecords.Max(x => x.Mileage));
|
||||
}
|
||||
return numbersArray.Any() ? numbersArray.Max() : 0;
|
||||
}
|
||||
private List<ReminderRecordViewModel> GetRemindersAndUrgency(int vehicleId)
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
public decimal GasRecordSum { get; set; }
|
||||
public decimal TaxRecordSum { get; set; }
|
||||
public decimal CollisionRecordSum { get; set; }
|
||||
public decimal UpgradeRecordSum { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<script src="~/js/collisionrecord.js" asp-append-version="true"></script>
|
||||
<script src="~/js/taxrecord.js" asp-append-version="true"></script>
|
||||
<script src="~/js/reminderrecord.js" asp-append-version="true"></script>
|
||||
<script src="~/js/upgraderecord.js" asp-append-version="true"></script>
|
||||
<script src="~/lib/chart-js/chart.umd.js"></script>
|
||||
}
|
||||
<div class="container">
|
||||
@@ -27,6 +28,9 @@
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="accident-tab" data-bs-toggle="tab" data-bs-target="#accident-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-exclamation-octagon me-2"></i>Repairs</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="upgrade-tab" data-bs-toggle="tab" data-bs-target="#upgrade-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-wrench-adjustable me-2"></i>Upgrades</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="gas-tab" data-bs-toggle="tab" data-bs-target="#gas-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-fuel-pump me-2"></i>Fuel</button>
|
||||
</li>
|
||||
@@ -71,6 +75,7 @@
|
||||
<div class="tab-pane fade" id="accident-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="reminder-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="report-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="upgrade-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="editVehicleModal" tabindex="-1" role="dialog">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@model CostMakeUpForVehicle
|
||||
@if (Model.CollisionRecordSum + Model.ServiceRecordSum + Model.GasRecordSum + Model.TaxRecordSum > 0)
|
||||
@if (Model.CollisionRecordSum + Model.ServiceRecordSum + Model.GasRecordSum + Model.TaxRecordSum + Model.UpgradeRecordSum > 0)
|
||||
{
|
||||
<canvas id="pie-chart"></canvas>
|
||||
<script>
|
||||
@@ -9,17 +9,18 @@
|
||||
new Chart($("#pie-chart"), {
|
||||
type: 'pie',
|
||||
data: {
|
||||
labels: ["Planned Maintenance(Service Records)", "Unplanned Maintenance(Repairs)", "Tax", "Fuel"],
|
||||
labels: ["Planned Maintenance(Service Records)", "Unplanned Maintenance(Repairs)", "Upgrades", "Tax", "Fuel"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Expenses by Category",
|
||||
backgroundColor: ["#003f5c", "#58508d", "#bc5090", "#ff6361"],
|
||||
backgroundColor: ["#003f5c", "#58508d", "#bc5090", "#ff6361", "#ffa600"],
|
||||
data: [
|
||||
@Model.ServiceRecordSum,
|
||||
@Model.CollisionRecordSum,
|
||||
@Model.UpgradeRecordSum,
|
||||
@Model.TaxRecordSum,
|
||||
@Model.GasRecordSum
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -41,7 +42,8 @@
|
||||
});
|
||||
}
|
||||
</script>
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
<h1>No data found or all records have zero sums, insert records with non-zero sums to see visualizations here.</h1>
|
||||
}
|
||||
|
||||
84
Views/Vehicle/_UpgradeRecordModal.cshtml
Normal file
84
Views/Vehicle/_UpgradeRecordModal.cshtml
Normal file
@@ -0,0 +1,84 @@
|
||||
@model UpgradeRecordInput
|
||||
@{
|
||||
var isNew = Model.Id == 0;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? "Add New Upgrade Record" : "Edit Upgrade Record")</h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddUpgradeRecordModal()" 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="upgradeRecordDate">Date</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="upgradeRecordDate" class="form-control" placeholder="Date service was performed" value="@Model.Date">
|
||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||
</div>
|
||||
<label for="upgradeRecordMileage">Odometer</label>
|
||||
<input type="number" id="upgradeRecordMileage" class="form-control" placeholder="Odometer reading when serviced" value="@(isNew ? "" : Model.Mileage)">
|
||||
<label for="upgradeRecordDescription">Description</label>
|
||||
<input type="text" id="upgradeRecordDescription" class="form-control" placeholder="Description of item(s) serviced(i.e. Oil Change)" value="@Model.Description">
|
||||
<label for="upgradeRecordCost">Cost</label>
|
||||
<input type="number" id="upgradeRecordCost" class="form-control" placeholder="Cost of the service" value="@(isNew ? "" : Model.Cost)">
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<label for="upgradeRecordNotes">Notes(optional)</label>
|
||||
<textarea id="upgradeRecordNotes" class="form-control" rows="5">@Model.Notes</textarea>
|
||||
@if (Model.Files.Any())
|
||||
{
|
||||
<div>
|
||||
@await Html.PartialAsync("_UploadedFiles", Model.Files)
|
||||
<label for="upgradeRecordFiles">Upload more documents</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="upgradeRecordFiles">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (isNew)
|
||||
{
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" value="" id="addReminderCheck">
|
||||
<label class="form-check-label" for="addReminderCheck">
|
||||
Add Reminder
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
<label for="upgradeRecordFiles">Upload documents(optional)</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="upgradeRecordFiles">
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@if (!isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-danger" onclick="deleteUpgradeRecord(@Model.Id)" style="margin-right:auto;">Delete</button>
|
||||
}
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAddUpgradeRecordModal()">Cancel</button>
|
||||
@if (isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveUpgradeRecordToVehicle()">Add New Upgrade Record</button>
|
||||
}
|
||||
else if (!isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveUpgradeRecordToVehicle(true)">Edit Upgrade Record</button>
|
||||
}
|
||||
</div>
|
||||
<script>
|
||||
var uploadedFiles = [];
|
||||
getUploadedFilesFromModel();
|
||||
function getUploadedFilesFromModel() {
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
{
|
||||
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
|
||||
}
|
||||
}
|
||||
function getUpgradeRecordModelData() {
|
||||
return { id: @Model.Id}
|
||||
}
|
||||
</script>
|
||||
66
Views/Vehicle/_UpgradeRecords.cshtml
Normal file
66
Views/Vehicle/_UpgradeRecords.cshtml
Normal file
@@ -0,0 +1,66 @@
|
||||
@inject IConfiguration Configuration
|
||||
@{
|
||||
var enableCsvImports = bool.Parse(Configuration[nameof(UserConfig.EnableCsvImports)]);
|
||||
var hideZero = bool.Parse(Configuration[nameof(UserConfig.HideZero)]);
|
||||
}
|
||||
@model List<UpgradeRecord>
|
||||
<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 Upgrade Records: {Model.Count()}")</span>
|
||||
<span class="ms-2 badge bg-primary">@($"Total: {Model.Sum(x => x.Cost).ToString("C")}")</span>
|
||||
</div>
|
||||
<div>
|
||||
@if (enableCsvImports)
|
||||
{
|
||||
<div class="btn-group">
|
||||
<button onclick="showAddUpgradeRecordModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square me-2"></i>Add Upgrade 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('UpgradeRecord')">Import via CSV</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button onclick="showAddUpgradeRecordModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square me-2"></i>Add Upgrade Record</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row vehicleDetailTabContainer">
|
||||
<div class="col-12">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr class="d-flex">
|
||||
<th scope="col" class="col-1">Date</th>
|
||||
<th scope="col" class="col-2">Odometer</th>
|
||||
<th scope="col" class="col-4">Description</th>
|
||||
<th scope="col" class="col-2">Cost</th>
|
||||
<th scope="col" class="col-3">Notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (UpgradeRecord upgradeRecord in Model)
|
||||
{
|
||||
<tr class="d-flex" style="cursor:pointer;" onclick="showEditUpgradeRecordModal(@upgradeRecord.Id)">
|
||||
<td class="col-1">@upgradeRecord.Date.ToShortDateString()</td>
|
||||
<td class="col-2">@upgradeRecord.Mileage</td>
|
||||
<td class="col-4">@upgradeRecord.Description</td>
|
||||
<td class="col-2">@((hideZero && upgradeRecord.Cost == default) ? "---" : upgradeRecord.Cost.ToString("C"))</td>
|
||||
<td class="col-3 text-truncate">@upgradeRecord.Notes</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" data-bs-focus="false" id="upgradeRecordModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content" id="upgradeRecordModalContent">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
124
wwwroot/js/upgraderecord.js
Normal file
124
wwwroot/js/upgraderecord.js
Normal file
@@ -0,0 +1,124 @@
|
||||
function showAddUpgradeRecordModal() {
|
||||
$.get('/Vehicle/GetAddUpgradeRecordPartialView', function (data) {
|
||||
if (data) {
|
||||
$("#upgradeRecordModalContent").html(data);
|
||||
//initiate datepicker
|
||||
$('#upgradeRecordDate').datepicker({
|
||||
endDate: "+0d",
|
||||
format: getShortDatePattern().pattern
|
||||
});
|
||||
$('#upgradeRecordModal').modal('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditUpgradeRecordModal(upgradeRecordId) {
|
||||
$.get(`/Vehicle/GetUpgradeRecordForEditById?upgradeRecordId=${upgradeRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#upgradeRecordModalContent").html(data);
|
||||
//initiate datepicker
|
||||
$('#upgradeRecordDate').datepicker({
|
||||
endDate: "+0d",
|
||||
format: getShortDatePattern().pattern
|
||||
});
|
||||
$('#upgradeRecordModal').modal('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
function hideAddUpgradeRecordModal() {
|
||||
$('#upgradeRecordModal').modal('hide');
|
||||
}
|
||||
function deleteUpgradeRecord(upgradeRecordId) {
|
||||
$("#workAroundInput").show();
|
||||
Swal.fire({
|
||||
title: "Confirm Deletion?",
|
||||
text: "Deleted Upgrade Records cannot be restored.",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Delete",
|
||||
confirmButtonColor: "#dc3545"
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$.post(`/Vehicle/DeleteUpgradeRecordById?upgradeRecordId=${upgradeRecordId}`, function (data) {
|
||||
if (data) {
|
||||
hideAddUpgradeRecordModal();
|
||||
successToast("Upgrade Record Deleted");
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
getVehicleUpgradeRecords(vehicleId);
|
||||
} else {
|
||||
errorToast("An error has occurred, please try again later.");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$("#workAroundInput").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
function saveUpgradeRecordToVehicle(isEdit) {
|
||||
//get values
|
||||
var formValues = getAndValidateUpgradeRecordValues();
|
||||
//validate
|
||||
if (formValues.hasError) {
|
||||
errorToast("Please check the form data");
|
||||
return;
|
||||
}
|
||||
//save to db.
|
||||
$.post('/Vehicle/SaveUpgradeRecordToVehicleId', { upgradeRecord: formValues }, function (data) {
|
||||
if (data) {
|
||||
successToast(isEdit ? "Upgrade Record Updated" : "Upgrade Record Added.");
|
||||
hideAddUpgradeRecordModal();
|
||||
getVehicleUpgradeRecords(formValues.vehicleId);
|
||||
if (formValues.addReminderRecord) {
|
||||
setTimeout(function () { showAddReminderModal(formValues); }, 500);
|
||||
}
|
||||
} else {
|
||||
errorToast("An error has occurred, please try again later.");
|
||||
}
|
||||
})
|
||||
}
|
||||
function getAndValidateUpgradeRecordValues() {
|
||||
var serviceDate = $("#upgradeRecordDate").val();
|
||||
var serviceMileage = $("#upgradeRecordMileage").val();
|
||||
var serviceDescription = $("#upgradeRecordDescription").val();
|
||||
var serviceCost = $("#upgradeRecordCost").val();
|
||||
var serviceNotes = $("#upgradeRecordNotes").val();
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
var upgradeRecordId = getUpgradeRecordModelData().id;
|
||||
var addReminderRecord = $("#addReminderCheck").is(":checked");
|
||||
//validation
|
||||
var hasError = false;
|
||||
if (serviceDate.trim() == '') { //eliminates whitespace.
|
||||
hasError = true;
|
||||
$("#upgradeRecordDate").addClass("is-invalid");
|
||||
} else {
|
||||
$("#upgradeRecordDate").removeClass("is-invalid");
|
||||
}
|
||||
if (serviceMileage.trim() == '' || parseInt(serviceMileage) < 0) {
|
||||
hasError = true;
|
||||
$("#upgradeRecordMileage").addClass("is-invalid");
|
||||
} else {
|
||||
$("#upgradeRecordMileage").removeClass("is-invalid");
|
||||
}
|
||||
if (serviceDescription.trim() == '') {
|
||||
hasError = true;
|
||||
$("#upgradeRecordDescription").addClass("is-invalid");
|
||||
} else {
|
||||
$("#upgradeRecordDescription").removeClass("is-invalid");
|
||||
}
|
||||
if (serviceCost.trim() == '') {
|
||||
hasError = true;
|
||||
$("#upgradeRecordCost").addClass("is-invalid");
|
||||
} else {
|
||||
$("#upgradeRecordCost").removeClass("is-invalid");
|
||||
}
|
||||
return {
|
||||
id: upgradeRecordId,
|
||||
hasError: hasError,
|
||||
vehicleId: vehicleId,
|
||||
date: serviceDate,
|
||||
mileage: serviceMileage,
|
||||
description: serviceDescription,
|
||||
cost: serviceCost,
|
||||
notes: serviceNotes,
|
||||
files: uploadedFiles,
|
||||
addReminderRecord: addReminderRecord
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,9 @@ $(document).ready(function () {
|
||||
case "reminder-tab":
|
||||
getVehicleReminders(vehicleId);
|
||||
break;
|
||||
case "upgrade-tab":
|
||||
getVehicleUpgradeRecords(vehicleId);
|
||||
break;
|
||||
}
|
||||
switch (e.relatedTarget.id) { //clear out previous tabs with grids in them to help with performance
|
||||
case "servicerecord-tab":
|
||||
@@ -57,6 +60,9 @@ $(document).ready(function () {
|
||||
case "reminder-tab":
|
||||
$("#reminder-tab-pane").html("");
|
||||
break;
|
||||
case "upgrade-tab":
|
||||
$("#upgrade-tab-pane").html("");
|
||||
break;
|
||||
}
|
||||
});
|
||||
getVehicleServiceRecords(vehicleId);
|
||||
@@ -75,7 +81,15 @@ function getVehicleServiceRecords(vehicleId) {
|
||||
$("#servicerecord-tab-pane").html(data);
|
||||
getVehicleHaveImportantReminders(vehicleId);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
function getVehicleUpgradeRecords(vehicleId) {
|
||||
$.get(`/Vehicle/GetUpgradeRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
$("#upgrade-tab-pane").html(data);
|
||||
getVehicleHaveImportantReminders(vehicleId);
|
||||
}
|
||||
});
|
||||
}
|
||||
function getVehicleGasRecords(vehicleId) {
|
||||
$.get(`/Vehicle/GetGasRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
|
||||
Reference in New Issue
Block a user