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;
}
/* 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 {
position: absolute;

View File

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

View File

@ -2,6 +2,7 @@
import { map } from './map-manager.js';
import { showStatus, updateLocationCount, escapeHtml } from './utils.js';
import { currentUser } from './auth.js';
import { resetAddressConfirmation } from './ui-controls.js';
export let markers = [];
export let currentEditingLocation = null;
@ -144,6 +145,14 @@ function createPopupContent(location) {
export async function handleAddLocation(e) {
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 data = {};
@ -202,6 +211,9 @@ export function openEditForm(location) {
return;
}
// Reset address confirmation state
resetAddressConfirmation('edit');
// Store the ID in a data attribute for later use
document.getElementById('edit-location-id').value = locationId;
document.getElementById('edit-location-id').setAttribute('data-location-id', locationId);
@ -235,6 +247,14 @@ export async function handleEditLocation(e) {
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
const locationIdElement = document.getElementById('edit-location-id');
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 geoInput = document.getElementById('geo-location');
// Reset address confirmation state
resetAddressConfirmation('add');
// Set coordinates
latInput.value = lat.toFixed(8);
lngInput.value = lng.toFixed(8);

View File

@ -5,6 +5,16 @@ import { loadLocations, handleAddLocation, handleEditLocation, handleDeleteLocat
export let userLocationMarker = null;
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
async function logout() {
@ -192,19 +202,21 @@ export function toggleFullscreen() {
}
}
export async function lookupAddress(mode) {
let latInput, lngInput, addressInput;
export async function confirmAddress(mode) {
let latInput, lngInput, addressInput, saveButton;
if (mode === 'add') {
latInput = document.getElementById('location-lat');
lngInput = document.getElementById('location-lng');
addressInput = document.getElementById('location-address');
saveButton = document.getElementById('save-location-btn');
} else if (mode === 'edit') {
latInput = document.getElementById('edit-location-lat');
lngInput = document.getElementById('edit-location-lng');
addressInput = document.getElementById('edit-location-address');
saveButton = document.getElementById('save-edit-location-btn'); // We'll need to add this ID to edit form
} else {
console.error('Invalid lookup mode:', mode);
console.error('Invalid confirm mode:', mode);
return;
}
@ -221,12 +233,37 @@ export async function lookupAddress(mode) {
return;
}
// Show loading state
// Get the confirm button
const button = mode === 'add' ?
document.getElementById('lookup-address-add-btn') :
document.getElementById('lookup-address-edit-btn');
document.getElementById('confirm-address-add-btn') :
document.getElementById('confirm-address-edit-btn');
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) {
button.disabled = true;
button.textContent = 'Looking up...';
@ -248,7 +285,27 @@ export async function lookupAddress(mode) {
const address = data.data.formattedAddress || data.data.fullAddress;
if (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 {
showStatus('No address found for these coordinates', 'warning');
}
@ -260,14 +317,47 @@ export async function lookupAddress(mode) {
console.error('Address lookup error:', error);
showStatus(`Address lookup failed: ${error.message}`, 'error');
} finally {
// Restore button state
if (button) {
// Restore button state if not confirmed
const finallyConfirmed = mode === 'add' ? isAddressConfirmed : isEditAddressConfirmed;
if (button && !finallyConfirmed) {
button.disabled = false;
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() {
// For add form
const addLatInput = document.getElementById('location-lat');
@ -282,6 +372,8 @@ export function setupGeoLocationSync() {
if (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;
addLngInput.value = coords.lng;
}
// Reset address confirmation when geo-location changes
resetAddressConfirmation('add');
});
}
@ -307,6 +401,8 @@ export function setupGeoLocationSync() {
if (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;
editLngInput.value = coords.lng;
}
// Reset address confirmation when geo-location changes
resetAddressConfirmation('edit');
});
}
}
@ -376,13 +474,13 @@ export function setupEventListeners() {
// Delete button
document.getElementById('delete-location-btn')?.addEventListener('click', handleDeleteLocation);
// Address lookup buttons
document.getElementById('lookup-address-add-btn')?.addEventListener('click', () => {
lookupAddress('add');
// Address confirm buttons
document.getElementById('confirm-address-add-btn')?.addEventListener('click', () => {
confirmAddress('add');
});
document.getElementById('lookup-address-edit-btn')?.addEventListener('click', () => {
lookupAddress('edit');
document.getElementById('confirm-address-edit-btn')?.addEventListener('click', () => {
confirmAddress('edit');
});
// Auto address lookup event listener
@ -391,7 +489,7 @@ export function setupEventListeners() {
if (mode === 'add') {
// Add a small delay to ensure the form is fully rendered
setTimeout(() => {
lookupAddress('add');
confirmAddress('add');
}, 200);
}
});

View File

@ -112,7 +112,7 @@ Favicon for the web application.
# 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
@ -136,7 +136,7 @@ Global configuration constants for the frontend app.
# 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
@ -156,7 +156,7 @@ JavaScript for volunteer shift signup, management, and UI logic with both grid a
# 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