new system for address confrimation

This commit is contained in:
admin 2025-07-16 18:25:50 -06:00
parent ff3e1e868b
commit 65c786d3db
5 changed files with 166 additions and 23 deletions

View File

@ -177,6 +177,28 @@ body {
background-color: #c0392b; background-color: #c0392b;
} }
/* Disabled button styles */
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
background-color: #6c757d;
}
.btn:disabled:hover {
background-color: #6c757d;
transform: none;
}
.btn-primary:disabled {
background-color: #6c757d;
border-color: #6c757d;
}
.btn-primary:disabled:hover {
background-color: #6c757d;
border-color: #6c757d;
}
/* Crosshair for location selection */ /* Crosshair for location selection */
.crosshair { .crosshair {
position: absolute; position: absolute;

View File

@ -171,8 +171,8 @@
<label for="edit-location-address">Address</label> <label for="edit-location-address">Address</label>
<div style="display: flex; gap: 10px;"> <div style="display: flex; gap: 10px;">
<input type="text" id="edit-location-address" name="Address" style="flex: 1;"> <input type="text" id="edit-location-address" name="Address" style="flex: 1;">
<button type="button" class="btn btn-secondary btn-sm" id="lookup-address-edit-btn"> <button type="button" class="btn btn-secondary btn-sm" id="confirm-address-edit-btn">
📍 Lookup Address 📍 Confirm Address
</button> </button>
</div> </div>
</div> </div>
@ -282,8 +282,8 @@
<div style="display: flex; gap: 10px;"> <div style="display: flex; gap: 10px;">
<input type="text" id="location-address" name="Address" <input type="text" id="location-address" name="Address"
placeholder="Enter address" style="flex: 1;"> placeholder="Enter address" style="flex: 1;">
<button type="button" class="btn btn-secondary btn-sm" id="lookup-address-add-btn"> <button type="button" class="btn btn-secondary btn-sm" id="confirm-address-add-btn">
📍 Lookup Address 📍 Confirm Address
</button> </button>
</div> </div>
</div> </div>
@ -336,7 +336,7 @@
<button type="button" class="btn btn-secondary" id="cancel-modal-btn"> <button type="button" class="btn btn-secondary" id="cancel-modal-btn">
Cancel Cancel
</button> </button>
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary" id="save-location-btn" disabled>
Save Location Save Location
</button> </button>
</div> </div>

View File

@ -2,6 +2,7 @@
import { map } from './map-manager.js'; import { map } from './map-manager.js';
import { showStatus, updateLocationCount, escapeHtml } from './utils.js'; import { showStatus, updateLocationCount, escapeHtml } from './utils.js';
import { currentUser } from './auth.js'; import { currentUser } from './auth.js';
import { resetAddressConfirmation } from './ui-controls.js';
export let markers = []; export let markers = [];
export let currentEditingLocation = null; export let currentEditingLocation = null;
@ -144,6 +145,14 @@ function createPopupContent(location) {
export async function handleAddLocation(e) { export async function handleAddLocation(e) {
e.preventDefault(); e.preventDefault();
// Check if address is confirmed
const { getAddressConfirmationState } = await import('./ui-controls.js');
const { isAddressConfirmed } = getAddressConfirmationState();
if (!isAddressConfirmed) {
showStatus('Please confirm the address before saving the location', 'warning');
return;
}
const formData = new FormData(e.target); const formData = new FormData(e.target);
const data = {}; const data = {};
@ -202,6 +211,9 @@ export function openEditForm(location) {
return; return;
} }
// Reset address confirmation state
resetAddressConfirmation('edit');
// Store the ID in a data attribute for later use // Store the ID in a data attribute for later use
document.getElementById('edit-location-id').value = locationId; document.getElementById('edit-location-id').value = locationId;
document.getElementById('edit-location-id').setAttribute('data-location-id', locationId); document.getElementById('edit-location-id').setAttribute('data-location-id', locationId);
@ -235,6 +247,14 @@ export async function handleEditLocation(e) {
if (!currentEditingLocation) return; if (!currentEditingLocation) return;
// Check if address is confirmed
const { getAddressConfirmationState } = await import('./ui-controls.js');
const { isEditAddressConfirmed } = getAddressConfirmationState();
if (!isEditAddressConfirmed) {
showStatus('Please confirm the address before saving changes', 'warning');
return;
}
// Get the stored location ID // Get the stored location ID
const locationIdElement = document.getElementById('edit-location-id'); const locationIdElement = document.getElementById('edit-location-id');
const locationId = locationIdElement.getAttribute('data-location-id') || locationIdElement.value; const locationId = locationIdElement.getAttribute('data-location-id') || locationIdElement.value;
@ -345,6 +365,9 @@ export function openAddModal(lat, lng) {
const lngInput = document.getElementById('location-lng'); const lngInput = document.getElementById('location-lng');
const geoInput = document.getElementById('geo-location'); const geoInput = document.getElementById('geo-location');
// Reset address confirmation state
resetAddressConfirmation('add');
// Set coordinates // Set coordinates
latInput.value = lat.toFixed(8); latInput.value = lat.toFixed(8);
lngInput.value = lng.toFixed(8); lngInput.value = lng.toFixed(8);

View File

@ -5,6 +5,16 @@ import { loadLocations, handleAddLocation, handleEditLocation, handleDeleteLocat
export let userLocationMarker = null; export let userLocationMarker = null;
export let isAddingLocation = false; export let isAddingLocation = false;
export let isAddressConfirmed = false;
export let isEditAddressConfirmed = false;
// Export function to get current confirmation states
export function getAddressConfirmationState() {
return {
isAddressConfirmed,
isEditAddressConfirmed
};
}
// Add logout function // Add logout function
async function logout() { async function logout() {
@ -192,19 +202,21 @@ export function toggleFullscreen() {
} }
} }
export async function lookupAddress(mode) { export async function confirmAddress(mode) {
let latInput, lngInput, addressInput; let latInput, lngInput, addressInput, saveButton;
if (mode === 'add') { if (mode === 'add') {
latInput = document.getElementById('location-lat'); latInput = document.getElementById('location-lat');
lngInput = document.getElementById('location-lng'); lngInput = document.getElementById('location-lng');
addressInput = document.getElementById('location-address'); addressInput = document.getElementById('location-address');
saveButton = document.getElementById('save-location-btn');
} else if (mode === 'edit') { } else if (mode === 'edit') {
latInput = document.getElementById('edit-location-lat'); latInput = document.getElementById('edit-location-lat');
lngInput = document.getElementById('edit-location-lng'); lngInput = document.getElementById('edit-location-lng');
addressInput = document.getElementById('edit-location-address'); addressInput = document.getElementById('edit-location-address');
saveButton = document.getElementById('save-edit-location-btn'); // We'll need to add this ID to edit form
} else { } else {
console.error('Invalid lookup mode:', mode); console.error('Invalid confirm mode:', mode);
return; return;
} }
@ -221,12 +233,37 @@ export async function lookupAddress(mode) {
return; return;
} }
// Show loading state // Get the confirm button
const button = mode === 'add' ? const button = mode === 'add' ?
document.getElementById('lookup-address-add-btn') : document.getElementById('confirm-address-add-btn') :
document.getElementById('lookup-address-edit-btn'); document.getElementById('confirm-address-edit-btn');
const originalText = button ? button.textContent : ''; const originalText = button ? button.textContent : '';
// Check if already confirmed
const currentlyConfirmed = mode === 'add' ? isAddressConfirmed : isEditAddressConfirmed;
// If already confirmed, just enable save
if (currentlyConfirmed) {
if (mode === 'add') {
isAddressConfirmed = false;
} else {
isEditAddressConfirmed = false;
}
// Reset button and disable save
if (button) {
button.textContent = '📍 Confirm Address';
button.classList.remove('btn-success');
button.classList.add('btn-secondary');
}
if (saveButton) {
saveButton.disabled = true;
}
showStatus('Please confirm address again to enable saving', 'info');
return;
}
if (button) { if (button) {
button.disabled = true; button.disabled = true;
button.textContent = 'Looking up...'; button.textContent = 'Looking up...';
@ -248,7 +285,27 @@ export async function lookupAddress(mode) {
const address = data.data.formattedAddress || data.data.fullAddress; const address = data.data.formattedAddress || data.data.fullAddress;
if (address) { if (address) {
addressInput.value = address; addressInput.value = address;
showStatus('Address found!', 'success');
// Mark as confirmed
if (mode === 'add') {
isAddressConfirmed = true;
} else {
isEditAddressConfirmed = true;
}
// Update button to show confirmed state
if (button) {
button.textContent = '✅ Address Confirmed';
button.classList.remove('btn-secondary');
button.classList.add('btn-success');
}
// Enable save button
if (saveButton) {
saveButton.disabled = false;
}
showStatus('Address confirmed! You can now save the location.', 'success');
} else { } else {
showStatus('No address found for these coordinates', 'warning'); showStatus('No address found for these coordinates', 'warning');
} }
@ -260,14 +317,47 @@ export async function lookupAddress(mode) {
console.error('Address lookup error:', error); console.error('Address lookup error:', error);
showStatus(`Address lookup failed: ${error.message}`, 'error'); showStatus(`Address lookup failed: ${error.message}`, 'error');
} finally { } finally {
// Restore button state // Restore button state if not confirmed
if (button) { const finallyConfirmed = mode === 'add' ? isAddressConfirmed : isEditAddressConfirmed;
if (button && !finallyConfirmed) {
button.disabled = false; button.disabled = false;
button.textContent = originalText; button.textContent = originalText;
} }
} }
} }
export function resetAddressConfirmation(mode) {
if (mode === 'add') {
isAddressConfirmed = false;
const button = document.getElementById('confirm-address-add-btn');
const saveButton = document.getElementById('save-location-btn');
if (button) {
button.textContent = '📍 Confirm Address';
button.classList.remove('btn-success');
button.classList.add('btn-secondary');
button.disabled = false;
}
if (saveButton) {
saveButton.disabled = true;
}
} else if (mode === 'edit') {
isEditAddressConfirmed = false;
const button = document.getElementById('confirm-address-edit-btn');
const saveButton = document.getElementById('save-edit-location-btn');
if (button) {
button.textContent = '📍 Confirm Address';
button.classList.remove('btn-success');
button.classList.add('btn-secondary');
button.disabled = false;
}
if (saveButton) {
saveButton.disabled = true;
}
}
}
export function setupGeoLocationSync() { export function setupGeoLocationSync() {
// For add form // For add form
const addLatInput = document.getElementById('location-lat'); const addLatInput = document.getElementById('location-lat');
@ -282,6 +372,8 @@ export function setupGeoLocationSync() {
if (lat && lng) { if (lat && lng) {
addGeoInput.value = `${lat};${lng}`; addGeoInput.value = `${lat};${lng}`;
} }
// Reset address confirmation when coordinates change
resetAddressConfirmation('add');
}); });
}); });
@ -291,6 +383,8 @@ export function setupGeoLocationSync() {
addLatInput.value = coords.lat; addLatInput.value = coords.lat;
addLngInput.value = coords.lng; addLngInput.value = coords.lng;
} }
// Reset address confirmation when geo-location changes
resetAddressConfirmation('add');
}); });
} }
@ -307,6 +401,8 @@ export function setupGeoLocationSync() {
if (lat && lng) { if (lat && lng) {
editGeoInput.value = `${lat};${lng}`; editGeoInput.value = `${lat};${lng}`;
} }
// Reset address confirmation when coordinates change
resetAddressConfirmation('edit');
}); });
}); });
@ -316,6 +412,8 @@ export function setupGeoLocationSync() {
editLatInput.value = coords.lat; editLatInput.value = coords.lat;
editLngInput.value = coords.lng; editLngInput.value = coords.lng;
} }
// Reset address confirmation when geo-location changes
resetAddressConfirmation('edit');
}); });
} }
} }
@ -376,13 +474,13 @@ export function setupEventListeners() {
// Delete button // Delete button
document.getElementById('delete-location-btn')?.addEventListener('click', handleDeleteLocation); document.getElementById('delete-location-btn')?.addEventListener('click', handleDeleteLocation);
// Address lookup buttons // Address confirm buttons
document.getElementById('lookup-address-add-btn')?.addEventListener('click', () => { document.getElementById('confirm-address-add-btn')?.addEventListener('click', () => {
lookupAddress('add'); confirmAddress('add');
}); });
document.getElementById('lookup-address-edit-btn')?.addEventListener('click', () => { document.getElementById('confirm-address-edit-btn')?.addEventListener('click', () => {
lookupAddress('edit'); confirmAddress('edit');
}); });
// Auto address lookup event listener // Auto address lookup event listener
@ -391,7 +489,7 @@ export function setupEventListeners() {
if (mode === 'add') { if (mode === 'add') {
// Add a small delay to ensure the form is fully rendered // Add a small delay to ensure the form is fully rendered
setTimeout(() => { setTimeout(() => {
lookupAddress('add'); confirmAddress('add');
}, 200); }, 200);
} }
}); });

View File

@ -112,7 +112,7 @@ Favicon for the web application.
# app/public/index.html # app/public/index.html
Main map viewer HTML page for the canvassing application. Main map viewer HTML page for the canvassing application. Features "Confirm Address" functionality that requires users to confirm the geocoded address before saving location data.
# app/public/login.html # app/public/login.html
@ -136,7 +136,7 @@ Global configuration constants for the frontend app.
# app/public/js/location-manager.js # app/public/js/location-manager.js
JavaScript for loading, displaying, and managing map locations on the frontend. JavaScript for loading, displaying, and managing map locations on the frontend. Includes address confirmation validation that prevents saving locations until the geocoded address is confirmed by the user.
# app/public/js/main.js # app/public/js/main.js
@ -156,7 +156,7 @@ JavaScript for volunteer shift signup, management, and UI logic with both grid a
# app/public/js/ui-controls.js # app/public/js/ui-controls.js
JavaScript for UI controls, event handlers, and user interaction logic. JavaScript for UI controls, event handlers, and user interaction logic. Includes address confirmation functionality that manages state for ensuring users confirm geocoded addresses before saving locations.
# app/public/js/utils.js # app/public/js/utils.js