Added Simplied Fuel Entry

This commit is contained in:
Eric Gullickson
2025-07-20 15:07:26 -05:00
parent 048d6c3bcb
commit 196df07a24
6 changed files with 207 additions and 48 deletions

View File

@@ -133,6 +133,14 @@ namespace MotoVaultPro.Controllers
return Json(result);
}
[HttpPost]
public IActionResult SaveSimpleFuelEntryPreference(bool useSimpleFuelEntry)
{
var currentConfig = _config.GetUserConfig(User);
currentConfig.UseSimpleFuelEntry = useSimpleFuelEntry;
var result = _config.SaveUserConfig(User, currentConfig);
return Json(result);
}
[HttpPost]
public IActionResult GetGasRecordsEditModal(List<int> recordIds)
{
var extraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.GasRecord).ExtraFields;

View File

@@ -337,6 +337,7 @@ namespace MotoVaultPro.Helper
PreferredGasMileageUnit = CheckString(nameof(UserConfig.PreferredGasMileageUnit)),
PreferredGasUnit = CheckString(nameof(UserConfig.PreferredGasUnit)),
UseUnitForFuelCost = CheckBool(CheckString(nameof(UserConfig.UseUnitForFuelCost))),
UseSimpleFuelEntry = CheckBool(CheckString(nameof(UserConfig.UseSimpleFuelEntry))),
UserLanguage = CheckString(nameof(UserConfig.UserLanguage), "en_US"),
HideSoldVehicles = CheckBool(CheckString(nameof(UserConfig.HideSoldVehicles))),
EnableShopSupplies = CheckBool(CheckString(nameof(UserConfig.EnableShopSupplies))),

View File

@@ -12,7 +12,7 @@ namespace MotoVaultPro.Helper
/// </summary>
public static class StaticHelper
{
public const string VersionNumber = "1.4.9";
public const string VersionNumber = "1.0.0";
public const string DbName = "data/cartracker.db";
public const string UserConfigPath = "data/config/userConfig.json";
public const string ServerConfigPath = "data/config/serverConfig.json";

View File

@@ -22,6 +22,7 @@
public string PreferredGasUnit { get; set; } = string.Empty;
public string PreferredGasMileageUnit { get; set; } = string.Empty;
public bool UseUnitForFuelCost { get; set; }
public bool UseSimpleFuelEntry { get; set; }
public bool ShowCalendar { get; set; }
public bool ShowVehicleThumbnail { get; set; }
public List<UserColumnPreference> UserColumnPreferences { get; set; } = new List<UserColumnPreference>();

View File

@@ -13,6 +13,7 @@
var useHours = Model.UseHours;
var isNew = Model.GasRecord.Id == 0;
var useUnitFuelCost = userConfig.UseUnitForFuelCost;
var useSimpleFuelEntry = userConfig.UseSimpleFuelEntry;
string consumptionUnit;
string distanceUnit;
if (useKwh)
@@ -40,8 +41,16 @@
}
}
<div class="modal-header">
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Gas Record") : translator.Translate(userLanguage, "Edit Gas Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditGasRecordModal({Model.GasRecord.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
<button type="button" class="btn-close" onclick="hideAddGasRecordModal()" aria-label="Close"></button>
<div class="d-flex justify-content-between align-items-center w-100">
<h5 class="modal-title">@(isNew ? translator.Translate(userLanguage, "Add New Gas Record") : translator.Translate(userLanguage, "Edit Gas Record"))<small style="display:none; @(isNew ? "" : "cursor:pointer;")" class="cached-banner ms-2 text-warning" onclick='@(isNew ? "" : $"showEditGasRecordModal({Model.GasRecord.Id}, true)" )'>@translator.Translate(userLanguage, "Unsaved Changes")</small></h5>
<div class="d-flex align-items-center">
<div class="form-check form-switch me-3">
<input class="form-check-input" type="checkbox" role="switch" id="fuelEntryModeToggle" @(useSimpleFuelEntry ? "checked" : "") onchange="toggleFuelEntryMode(this.checked)">
<label class="form-check-label" for="fuelEntryModeToggle">@translator.Translate(userLanguage, "Simple Mode")</label>
</div>
<button type="button" class="btn-close" onclick="hideAddGasRecordModal()" aria-label="Close"></button>
</div>
</div>
</div>
<div class="modal-body" onkeydown="handleEnter(this)">
<form>
@@ -49,57 +58,85 @@
<div class="row">
<div class="col-md-6 col-12">
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
<label for="gasRecordDate">@translator.Translate(userLanguage,"Date")</label>
<div class="input-group">
<input type="text" id="gasRecordDate" placeholder="@translator.Translate(userLanguage,"Date refueled")" class="form-control" value="@Model.GasRecord.Date">
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
<!-- Simple Mode Fields -->
<div id="simpleModeFields" style="@(useSimpleFuelEntry ? "" : "display:none;")">
<label for="gasRecordMileage">@($"{translator.Translate(userLanguage,"Odometer Reading")}({distanceUnit})")</label>
<div class="input-group">
<input type="number" inputmode="numeric" id="gasRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when refueled")" value="@(isNew || Model.GasRecord.Mileage == default ? "" : Model.GasRecord.Mileage)">
@if (isNew)
{
<div class="input-group-text">
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('gasRecordMileage')"><i class="bi bi-plus"></i></button>
</div>
}
</div>
<label for="gasRecordUnitCost">@($"{translator.Translate(userLanguage, "Cost Per")} {consumptionUnit}")</label>
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="@(useThreeDecimals ? "fixDecimalInput(this, 3)" : "fixDecimalInput(this, 2)"); calculateTotalCost()" id="gasRecordUnitCost" class="form-control" placeholder="@($"{translator.Translate(userLanguage, "Price per")} {consumptionUnit}")" value="">
<label for="gasRecordGallons">@($"{translator.Translate(userLanguage, "Fuel Consumption")}({consumptionUnit})")</label>
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="@(useThreeDecimalsConsumption ? "fixDecimalInput(this, 3)" : "fixDecimalInput(this, 2)"); calculateTotalCost()" id="gasRecordGallons" class="form-control" placeholder="@translator.Translate(userLanguage,"Amount of gas refueled")" value="@(isNew ? "" : Model.GasRecord.Gallons)">
<label for="gasRecordCost">@translator.Translate(userLanguage,"Total Cost") <small class="text-muted">(auto-calculated)</small></label>
<input type="text" inputmode="decimal" id="gasRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"Total cost calculated automatically")" value="@(isNew ? "" : Model.GasRecord.Cost)" readonly>
<!-- Hidden fields for simple mode with default values -->
<input type="hidden" id="simpleGasRecordDate" value="@DateTime.Now.ToShortDateString()">
<input type="hidden" id="simpleGasIsFillToFull" value="true">
<input type="hidden" id="simpleGasIsMissed" value="false">
<input type="hidden" id="simpleGasRecordNotes" value="">
<input type="hidden" id="simpleGasRecordTag" value="">
</div>
<label for="gasRecordMileage">@($"{translator.Translate(userLanguage,"Odometer Reading")}({distanceUnit})")</label>
<div class="input-group">
<input type="number" inputmode="numeric" id="gasRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when refueled")" value="@(isNew || Model.GasRecord.Mileage == default ? "" : Model.GasRecord.Mileage)">
<!-- Advanced Mode Fields -->
<div id="advancedModeFields" style="@(useSimpleFuelEntry ? "display:none;" : "")">
<label for="gasRecordDate">@translator.Translate(userLanguage,"Date")</label>
<div class="input-group">
<input type="text" id="gasRecordDate" placeholder="@translator.Translate(userLanguage,"Date refueled")" class="form-control" value="@Model.GasRecord.Date">
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
</div>
<label for="gasRecordMileage">@($"{translator.Translate(userLanguage,"Odometer Reading")}({distanceUnit})")</label>
<div class="input-group">
<input type="number" inputmode="numeric" id="gasRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"Odometer reading when refueled")" value="@(isNew || Model.GasRecord.Mileage == default ? "" : Model.GasRecord.Mileage)">
@if (isNew)
{
<div class="input-group-text">
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('gasRecordMileage')"><i class="bi bi-plus"></i></button>
</div>
}
</div>
<label for="gasRecordGallons">@($"{translator.Translate(userLanguage, "Fuel Consumption")}({consumptionUnit})")</label>
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="@(useThreeDecimalsConsumption ? "fixDecimalInput(this, 3)" : "fixDecimalInput(this, 2)")" id="gasRecordGallons" class="form-control" placeholder="@translator.Translate(userLanguage,"Amount of gas refueled")" value="@(isNew ? "" : Model.GasRecord.Gallons)">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="gasIsFillToFull" checked="@Model.GasRecord.IsFillToFull">
<label class="form-check-label" for="gasIsFillToFull">@translator.Translate(userLanguage,"Is Filled To Full")</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="gasIsMissed" checked="@Model.GasRecord.MissedFuelUp">
<label class="form-check-label" for="gasIsMissed">@translator.Translate(userLanguage,"Missed Fuel Up(Skip MPG Calculation)")</label>
</div>
<label for="GasRecordCost">@translator.Translate(userLanguage,"Cost")</label>
@if (isNew)
{
<div class="input-group-text">
<button type="button" class="btn btn-sm btn-primary zero-y-padding" onclick="getLastOdometerReadingAndIncrement('gasRecordMileage')"><i class="bi bi-plus"></i></button>
<div class="input-group">
<input type="text" onkeydown="interceptDecimalKeys(event)" onkeyup="@(useThreeDecimals ? "fixDecimalInput(this, 3)" : "fixDecimalInput(this, 2)")" inputmode="decimal" id="gasRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"Cost of gas refueled")" value="@(isNew ? "" : Model.GasRecord.Cost)">
<div class="input-group-text">
<select class="form-select form-select-sm" id="gasCostType">
<!option @(useUnitFuelCost ? "" : "selected") value="total">@translator.Translate(userLanguage,"Total")</!option>
<!option @(useUnitFuelCost ? "selected" : "") value="unit">@translator.Translate(userLanguage,"Unit")</!option>
</select>
</div>
</div>
}
</div>
<label for="gasRecordGallons">@($"{translator.Translate(userLanguage, "Fuel Consumption")}({consumptionUnit})")</label>
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="@(useThreeDecimalsConsumption ? "fixDecimalInput(this, 3)" : "fixDecimalInput(this, 2)")" id="gasRecordGallons" class="form-control" placeholder="@translator.Translate(userLanguage,"Amount of gas refueled")" value="@(isNew ? "" : Model.GasRecord.Gallons)">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="gasIsFillToFull" checked="@Model.GasRecord.IsFillToFull">
<label class="form-check-label" for="gasIsFillToFull">@translator.Translate(userLanguage,"Is Filled To Full")</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="gasIsMissed" checked="@Model.GasRecord.MissedFuelUp">
<label class="form-check-label" for="gasIsMissed">@translator.Translate(userLanguage,"Missed Fuel Up(Skip MPG Calculation)")</label>
</div>
<label for="GasRecordCost">@translator.Translate(userLanguage,"Cost")</label>
@if (isNew)
{
<div class="input-group">
<input type="text" onkeydown="interceptDecimalKeys(event)" onkeyup="@(useThreeDecimals ? "fixDecimalInput(this, 3)" : "fixDecimalInput(this, 2)")" inputmode="decimal" id="gasRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"Cost of gas refueled")" value="@(isNew ? "" : Model.GasRecord.Cost)">
<div class="input-group-text">
<select class="form-select form-select-sm" id="gasCostType">
<!option @(useUnitFuelCost ? "" : "selected") value="total">@translator.Translate(userLanguage,"Total")</!option>
<!option @(useUnitFuelCost ? "selected" : "") value="unit">@translator.Translate(userLanguage,"Unit")</!option>
</select>
</div>
</div>
} else
{
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="@(useThreeDecimals ? "fixDecimalInput(this, 3)" : "fixDecimalInput(this, 2)")" id="gasRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"Cost of gas refueled")" value="@(isNew ? "" : Model.GasRecord.Cost)">
}
<label for="gasRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
<select multiple class="form-select" id="gasRecordTag">
@foreach (string tag in Model.GasRecord.Tags)
} else
{
<!option value="@tag">@tag</!option>
<input type="text" inputmode="decimal" onkeydown="interceptDecimalKeys(event)" onkeyup="@(useThreeDecimals ? "fixDecimalInput(this, 3)" : "fixDecimalInput(this, 2)")" id="gasRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"Cost of gas refueled")" value="@(isNew ? "" : Model.GasRecord.Cost)">
}
</select>
@await Html.PartialAsync("_ExtraField", Model.GasRecord.ExtraFields)
<label for="gasRecordTag">@translator.Translate(userLanguage,"Tags(optional)")</label>
<select multiple class="form-select" id="gasRecordTag">
@foreach (string tag in Model.GasRecord.Tags)
{
<!option value="@tag">@tag</!option>
}
</select>
@await Html.PartialAsync("_ExtraField", Model.GasRecord.ExtraFields)
</div>
</div>
<div class="col-md-6 col-12">
<div class="col-md-6 col-12" id="secondColumnFields" style="@(useSimpleFuelEntry ? "display:none;" : "")">
<label for="gasRecordNotes">@translator.Translate(userLanguage,"Notes(optional)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
<textarea id="gasRecordNotes" class="form-control" rows="5">@Model.GasRecord.Notes</textarea>
<div>

View File

@@ -68,7 +68,15 @@ function deleteGasRecord(gasRecordId) {
}
function saveGasRecordToVehicle(isEdit) {
//get values
var formValues = getAndValidateGasRecordValues();
var isSimpleMode = $("#fuelEntryModeToggle").is(":checked");
var formValues;
if (isSimpleMode) {
formValues = getAndValidateGasRecordValuesSimple();
} else {
formValues = getAndValidateGasRecordValues();
}
//validate
if (formValues.hasError) {
errorToast("Please check the form data");
@@ -495,4 +503,108 @@ function saveMultipleGasRecordsToVehicle() {
errorToast(genericErrorMessage());
}
})
}
// Simple/Advanced fuel entry mode toggle functions
function toggleFuelEntryMode(useSimpleMode) {
if (useSimpleMode) {
// Switch to simple mode
$("#simpleModeFields").show();
$("#advancedModeFields").hide();
$("#secondColumnFields").hide();
// Initialize simple mode values if editing existing record
var existingCost = $("#gasRecordCost").val();
var existingGallons = $("#gasRecordGallons").val();
if (existingCost && existingGallons && globalParseFloat(existingGallons) > 0) {
var unitCost = globalParseFloat(existingCost) / globalParseFloat(existingGallons);
$("#gasRecordUnitCost").val(globalFloatToString(unitCost.toFixed(3)));
}
} else {
// Switch to advanced mode
$("#simpleModeFields").hide();
$("#advancedModeFields").show();
$("#secondColumnFields").show();
}
// Save user preference
$.post('/Vehicle/SaveSimpleFuelEntryPreference', { useSimpleFuelEntry: useSimpleMode }, function (data) {
if (!data) {
errorToast("Error saving preference");
}
});
}
// Auto-calculate total cost based on unit cost and gallons
function calculateTotalCost() {
var unitCost = globalParseFloat($("#gasRecordUnitCost").val());
var gallons = globalParseFloat($("#gasRecordGallons").val());
if (!isNaN(unitCost) && !isNaN(gallons) && unitCost > 0 && gallons > 0) {
var totalCost = unitCost * gallons;
var decimalPoints = getGlobalConfig().useThreeDecimals ? 3 : 2;
$("#gasRecordCost").val(globalFloatToString(totalCost.toFixed(decimalPoints)));
} else {
$("#gasRecordCost").val("");
}
}
// Simple mode validation function
function getAndValidateGasRecordValuesSimple() {
var gasDate = $("#simpleGasRecordDate").val();
var gasMileage = parseInt(globalParseFloat($("#gasRecordMileage").val())).toString();
var gasGallons = $("#gasRecordGallons").val();
var gasCost = $("#gasRecordCost").val();
var gasIsFillToFull = $("#simpleGasIsFillToFull").val() === "true";
var gasIsMissed = $("#simpleGasIsMissed").val() === "true";
var gasNotes = $("#simpleGasRecordNotes").val();
var gasTags = $("#simpleGasRecordTag").val() ? [$("#simpleGasRecordTag").val()] : [];
var vehicleId = GetVehicleId().vehicleId;
var gasRecordId = getGasRecordModelData().id;
//Odometer Adjustments
if (isNaN(gasMileage) && GetVehicleId().odometerOptional) {
gasMileage = '0';
}
gasMileage = GetAdjustedOdometer(gasRecordId, gasMileage);
// Validation for simple mode
var hasError = false;
if (gasMileage.trim() == '' || isNaN(gasMileage) || parseInt(gasMileage) < 0) {
hasError = true;
$("#gasRecordMileage").addClass("is-invalid");
} else {
$("#gasRecordMileage").removeClass("is-invalid");
}
if (gasGallons.trim() == '' || globalParseFloat(gasGallons) <= 0) {
hasError = true;
$("#gasRecordGallons").addClass("is-invalid");
} else {
$("#gasRecordGallons").removeClass("is-invalid");
}
if (gasCost.trim() == '' || !isValidMoney(gasCost)) {
hasError = true;
$("#gasRecordCost").addClass("is-invalid");
} else {
$("#gasRecordCost").removeClass("is-invalid");
}
return {
id: gasRecordId,
hasError: hasError,
vehicleId: vehicleId,
date: gasDate,
mileage: gasMileage,
gallons: gasGallons,
cost: gasCost,
files: [], // Simple mode doesn't support file uploads
tags: gasTags,
isFillToFull: gasIsFillToFull,
missedFuelUp: gasIsMissed,
notes: gasNotes,
extraFields: [] // Simple mode doesn't use extra fields
};
}