diff --git a/wwwroot/css/site.css b/wwwroot/css/site.css
index 4789422..cb6fd78 100644
--- a/wwwroot/css/site.css
+++ b/wwwroot/css/site.css
@@ -98,12 +98,292 @@ html {
aspect-ratio: 1/1;
border-style: dashed;
border-width: 2px;
- page-break-after: always;
}
- .recordSticker {
- height: 100%;
- page-break-after: always;
+}
+
+/* Mobile-First Modal Improvements */
+@media (max-width: 768px) {
+ /* Full-screen modal on mobile */
+ .modal-dialog {
+ margin: 0;
+ width: 100vw;
+ height: 100vh;
+ max-width: none;
+ max-height: none;
}
+
+ .modal-content {
+ height: 100vh;
+ border-radius: 0;
+ border: none;
+ display: flex;
+ flex-direction: column;
+ }
+
+ /* Slide-up animation for mobile modals */
+ .modal.fade .modal-dialog {
+ transform: translateY(100%);
+ transition: transform 0.3s ease-out;
+ }
+
+ .modal.show .modal-dialog {
+ transform: translateY(0);
+ }
+
+ .modal-body {
+ flex: 1;
+ overflow-y: auto;
+ padding: 1rem;
+ }
+
+ .modal-header {
+ flex-shrink: 0;
+ padding: 1rem;
+ border-bottom: 1px solid #dee2e6;
+ }
+
+ .modal-footer {
+ flex-shrink: 0;
+ padding: 1rem;
+ border-top: 1px solid #dee2e6;
+ }
+
+ /* Touch-friendly targets - minimum 44px */
+ .btn {
+ min-height: 44px;
+ min-width: 44px;
+ padding: 0.75rem 1rem;
+ }
+
+ .btn-sm {
+ min-height: 44px;
+ min-width: 44px;
+ padding: 0.5rem 0.75rem;
+ }
+
+ .btn-close {
+ width: 44px;
+ height: 44px;
+ padding: 0.75rem;
+ }
+
+ .form-control {
+ min-height: 44px;
+ padding: 0.75rem;
+ font-size: 16px; /* Prevents zoom on iOS */
+ }
+
+ .form-select {
+ min-height: 44px;
+ padding: 0.75rem;
+ font-size: 16px;
+ }
+
+ .form-check-input {
+ width: 1.5rem;
+ height: 1.5rem;
+ margin-top: 0.25rem;
+ }
+
+ .form-check-label {
+ min-height: 44px;
+ display: flex;
+ align-items: center;
+ padding-left: 0.5rem;
+ }
+
+ .input-group-text {
+ min-height: 44px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ /* Single column layout on mobile */
+ .col-md-6 {
+ flex: 0 0 100% !important;
+ max-width: 100% !important;
+ }
+
+ /* Mobile form spacing */
+ .form-group {
+ margin-bottom: 1.5rem;
+ }
+
+ .form-group label {
+ margin-bottom: 0.75rem;
+ font-weight: 500;
+ }
+
+ .form-group input,
+ .form-group select,
+ .form-group textarea {
+ margin-bottom: 1rem;
+ }
+
+ /* Simplified header layout on mobile */
+ .modal-header .d-flex {
+ flex-direction: column;
+ align-items: stretch !important;
+ }
+
+ .modal-header .modal-title {
+ margin-bottom: 1rem;
+ text-align: center;
+ }
+
+ .modal-header .form-check {
+ justify-content: center;
+ margin-bottom: 0.5rem;
+ }
+
+ .modal-header .btn-close {
+ position: absolute;
+ top: 1rem;
+ right: 1rem;
+ margin: 0;
+ }
+
+ /* Mobile-friendly footer buttons */
+ .modal-footer {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ }
+
+ .modal-footer .btn {
+ width: 100%;
+ margin: 0;
+ }
+
+ .modal-footer .btn:first-child {
+ order: 2; /* Move delete button to bottom */
+ }
+
+ .modal-footer .btn:last-child {
+ order: 1; /* Move primary action to top */
+ }
+
+ .modal-footer .btn:nth-child(2) {
+ order: 3; /* Cancel button in middle */
+ }
+
+ /* Bottom sheet pattern for mobile */
+ .modal-content {
+ position: relative;
+ }
+
+ .modal-content::before {
+ content: '';
+ position: absolute;
+ top: 8px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 40px;
+ height: 4px;
+ background-color: #dee2e6;
+ border-radius: 2px;
+ z-index: 1000;
+ cursor: grab;
+ }
+
+ .modal-content::before:active {
+ cursor: grabbing;
+ }
+
+ /* Touch feedback for interactive elements */
+ .btn:active,
+ .form-control:active,
+ .form-check-input:active {
+ transform: scale(0.98);
+ transition: transform 0.1s ease;
+ }
+
+ /* Improved focus states for mobile */
+ .form-control:focus,
+ .form-select:focus {
+ border-color: #86b7fe;
+ box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
+ outline: none;
+ }
+
+ /* Mobile tag input styling */
+ .mobile-tag-input .bootstrap-tagsinput {
+ border-radius: 6px;
+ border: 1px solid #ced4da;
+ }
+
+ .mobile-tag-input .bootstrap-tagsinput:focus-within {
+ border-color: #86b7fe;
+ box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
+ }
+
+ .mobile-tag-input .tag {
+ background-color: #0d6efd;
+ color: white;
+ border-radius: 4px;
+ margin: 2px;
+ padding: 4px 8px;
+ font-size: 14px;
+ }
+
+ /* Enhanced mobile breakpoints for better responsiveness */
+ .mobile-single-column {
+ width: 100% !important;
+ max-width: 100% !important;
+ flex: 0 0 100% !important;
+ }
+
+ /* Improved mobile modal animations */
+ .modal.fade .modal-dialog {
+ transform: translateY(100%);
+ transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ }
+
+ .modal.show .modal-dialog {
+ transform: translateY(0);
+ }
+
+ /* Mobile keyboard adjustments */
+ .modal-body {
+ /* Prevent viewport scaling when keyboard appears */
+ position: relative;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ }
+
+ /* Accessibility improvements for mobile */
+ .form-label {
+ font-weight: 600;
+ color: #212529;
+ margin-bottom: 0.5rem;
+ }
+
+ /* Error state improvements for mobile */
+ .is-invalid {
+ border-color: #dc3545 !important;
+ border-width: 2px !important;
+ }
+
+ .is-invalid:focus {
+ box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25) !important;
+ }
+
+ /* Success state for mobile */
+ .is-valid {
+ border-color: #198754 !important;
+ border-width: 2px !important;
+ }
+
+ .is-valid:focus {
+ box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25) !important;
+ }
+}
+
+.recordSticker {
+ height: 100%;
+ page-break-after: always;
+}
.stickerNote {
height:100%;
}
diff --git a/wwwroot/js/gasrecord.js b/wwwroot/js/gasrecord.js
index 44677f7..83ca779 100644
--- a/wwwroot/js/gasrecord.js
+++ b/wwwroot/js/gasrecord.js
@@ -1,11 +1,133 @@
+// Mobile detection utility
+function isMobileDevice() {
+ return window.matchMedia("(max-width: 768px)").matches ||
+ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
+}
+
+// Initialize form inputs based on device type
+function initializeFormInputs() {
+ if (isMobileDevice()) {
+ // Convert date input to native HTML5 on mobile
+ var dateInput = $('#gasRecordDate');
+ if (dateInput.length) {
+ dateInput.attr('type', 'date');
+ dateInput.removeClass('datepicker'); // Remove Bootstrap datepicker class
+ }
+
+ // Default to simple mode on mobile
+ var modeToggle = $('#fuelEntryModeToggle');
+ if (modeToggle.length && !modeToggle.is(':checked')) {
+ modeToggle.prop('checked', true);
+ toggleFuelEntryMode(true);
+ }
+
+ // Initialize mobile-friendly tag selector
+ initMobileTagSelector($("#gasRecordTag"));
+ } else {
+ // Use Bootstrap datepicker on desktop
+ initDatePicker($('#gasRecordDate'));
+
+ // Use standard tag selector on desktop
+ initTagSelector($("#gasRecordTag"));
+ }
+}
+
+// Mobile-optimized tag selector
+function initMobileTagSelector(input) {
+ if (input.length) {
+ // Initialize with mobile-friendly options
+ input.tagsinput({
+ maxTags: 5, // Limit tags on mobile
+ trimValue: true,
+ confirmKeys: [13, 44, 32], // Enter, comma, space
+ focusClass: 'focus',
+ freeInput: true
+ });
+
+ // Add mobile-specific styling
+ input.parent().addClass('mobile-tag-input');
+
+ // Increase touch target size for mobile
+ input.parent().find('.bootstrap-tagsinput').css({
+ 'min-height': '44px',
+ 'padding': '8px',
+ 'font-size': '16px' // Prevent zoom on iOS
+ });
+
+ // Style the input within tags
+ input.parent().find('.bootstrap-tagsinput input').css({
+ 'font-size': '16px',
+ 'min-height': '30px'
+ });
+ }
+}
+
+// Swipe to dismiss functionality for mobile modals
+function initSwipeToDismiss() {
+ if (!isMobileDevice()) return;
+
+ var modal = $('#gasRecordModal');
+ var modalContent = modal.find('.modal-content');
+ var startY = 0;
+ var currentY = 0;
+ var isDragging = false;
+ var threshold = 100; // Minimum swipe distance to dismiss
+
+ // Touch start
+ modalContent.on('touchstart', function(e) {
+ startY = e.originalEvent.touches[0].clientY;
+ isDragging = true;
+ modalContent.css('transition', 'none');
+ });
+
+ // Touch move
+ modalContent.on('touchmove', function(e) {
+ if (!isDragging) return;
+
+ currentY = e.originalEvent.touches[0].clientY;
+ var deltaY = currentY - startY;
+
+ // Only allow downward swipes
+ if (deltaY > 0) {
+ modalContent.css('transform', `translateY(${deltaY}px)`);
+ }
+ });
+
+ // Touch end
+ modalContent.on('touchend', function(e) {
+ if (!isDragging) return;
+
+ isDragging = false;
+ var deltaY = currentY - startY;
+
+ modalContent.css('transition', 'transform 0.3s ease-out');
+
+ if (deltaY > threshold) {
+ // Dismiss modal
+ modalContent.css('transform', 'translateY(100%)');
+ setTimeout(function() {
+ hideAddGasRecordModal();
+ modalContent.css('transform', '');
+ }, 300);
+ } else {
+ // Snap back
+ modalContent.css('transform', '');
+ }
+ });
+}
+
function showAddGasRecordModal() {
$.get(`/Vehicle/GetAddGasRecordPartialView?vehicleId=${GetVehicleId().vehicleId}`, function (data) {
if (data) {
$("#gasRecordModalContent").html(data);
- //initiate datepicker
- initDatePicker($('#gasRecordDate'));
- initTagSelector($("#gasRecordTag"));
+
+ // Initialize inputs based on device type
+ initializeFormInputs();
+
$('#gasRecordModal').modal('show');
+
+ // Initialize swipe to dismiss for mobile
+ initSwipeToDismiss();
}
});
}
@@ -25,11 +147,16 @@ function showEditGasRecordModal(gasRecordId, nocache) {
$.get(`/Vehicle/GetGasRecordForEditById?gasRecordId=${gasRecordId}`, function (data) {
if (data) {
$("#gasRecordModalContent").html(data);
- //initiate datepicker
- initDatePicker($('#gasRecordDate'));
- initTagSelector($("#gasRecordTag"));
+
+ // Initialize inputs based on device type
+ initializeFormInputs();
+
$('#gasRecordModal').modal('show');
bindModalInputChanges('gasRecordModal');
+
+ // Initialize swipe to dismiss for mobile
+ initSwipeToDismiss();
+
$('#gasRecordModal').off('shown.bs.modal').on('shown.bs.modal', function () {
if (getGlobalConfig().useMarkDown) {
toggleMarkDownOverlay("gasRecordNotes");
@@ -441,10 +568,14 @@ function editMultipleGasRecords(ids) {
$.post('/Vehicle/GetGasRecordsEditModal', { recordIds: ids }, function (data) {
if (data) {
$("#gasRecordModalContent").html(data);
- //initiate datepicker
- initDatePicker($('#gasRecordDate'));
- initTagSelector($("#gasRecordTag"));
+
+ // Initialize inputs based on device type
+ initializeFormInputs();
+
$('#gasRecordModal').modal('show');
+
+ // Initialize swipe to dismiss for mobile
+ initSwipeToDismiss();
}
});
}