First indication that the location geocoder is working

This commit is contained in:
Eli Ribble 2026-01-08 22:21:59 +00:00
parent 2c85624583
commit 06767ff39a
No known key found for this signature in database
5 changed files with 133 additions and 5 deletions

View file

@ -8,6 +8,7 @@ import (
"strconv"
"time"
"github.com/Gleipnir-Technology/nidus-sync/config"
"github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/db/enums"
"github.com/Gleipnir-Technology/nidus-sync/db/models"
@ -70,7 +71,9 @@ func getPool(w http.ResponseWriter, r *http.Request) {
htmlpage.RenderOrError(
w,
Pool,
ContextPool{},
ContextPool{
MapboxToken: config.MapboxToken,
},
)
}
func getQuick(w http.ResponseWriter, r *http.Request) {

View file

@ -17,7 +17,9 @@ type ContextNuisance struct{}
type ContextNuisanceSubmitComplete struct {
ReportID string
}
type ContextPool struct{}
type ContextPool struct{
MapboxToken string
}
type ContextQuick struct{}
type ContextQuickSubmitComplete struct {
ReportID string
@ -39,7 +41,7 @@ var (
Status = buildTemplate("status", "base")
)
var components = [...]string{"footer", "photo-upload", "photo-upload-header"}
var components = [...]string{"footer", "location-geocode", "location-geocode-header", "photo-upload", "photo-upload-header"}
func buildTemplate(files ...string) *htmlpage.BuiltTemplate {
subdir := "public-report"

View file

@ -0,0 +1,108 @@
{{define "location-geocode-header"}}
<style>
.suggestions-container {
position: absolute;
width: 100%;
max-height: 300px;
overflow-y: auto;
z-index: 1000;
}
.suggestion-item {
cursor: pointer;
padding: 8px 12px;
}
.suggestion-item:hover {
background-color: #f8f9fa;
}
</style>
<script>
// Replace with your actual Mapbox access token
const MAPBOX_ACCESS_TOKEN = '{{.MapboxToken}}';
// Display suggestions in the dropdown
function displaySuggestions(suggestions) {
const suggestionsContainer = document.getElementById('suggestions');
// Clear previous suggestions
suggestionsContainer.innerHTML = '';
if (suggestions.length === 0) {
suggestionsContainer.classList.add('d-none');
return;
}
// Create and append suggestion items
suggestions.forEach(suggestion => {
const item = document.createElement('div');
item.className = 'suggestion-item list-group-item';
item.textContent = suggestion.properties.name || suggestion.properties.full_address;
// Handle click on a suggestion
item.addEventListener('click', function() {
addressInput.value = suggestion.properties.name || suggestion.properties.full_address;
suggestionsContainer.classList.add('d-none');
// Display the selected location details
locationDetails.textContent = JSON.stringify(suggestion, null, 2);
});
suggestionsContainer.appendChild(item);
});
// Show the suggestions container
suggestionsContainer.classList.remove('d-none');
}
// Fetch suggestions from Mapbox API
async function fetchGeocodingSuggestions(query) {
try {
const url = `https://api.mapbox.com/search/geocode/v6/forward?q=${encodeURIComponent(query)}&access_token=${MAPBOX_ACCESS_TOKEN}`;
const response = await fetch(url);
const data = await response.json();
displaySuggestions(data.features || []);
} catch (error) {
console.error('Error fetching geocoding suggestions:', error);
}
}
function onAddressInput() {
const suggestionsContainer = document.getElementById('suggestions');
let debounceTimer;
const query = this.value.trim();
// Clear previous timer
clearTimeout(debounceTimer);
// Clear suggestions if input is less than 3 characters
if (query.length < 3) {
suggestionsContainer.classList.add('d-none');
suggestionsContainer.innerHTML = '';
return;
}
// Debounce API calls (wait 300ms after typing stops)
debounceTimer = setTimeout(() => {
fetchGeocodingSuggestions(query);
}, 300);
}
document.addEventListener('DOMContentLoaded', function() {
const addressInput = document.getElementById('addressInput');
const suggestionsContainer = document.getElementById('suggestions');
const locationDetails = document.getElementById('locationDetails');
// Listen for input changes
addressInput.addEventListener('input', onAddressInput);
// Close suggestions when clicking outside
document.addEventListener('click', function(event) {
if (!addressInput.contains(event.target) && !suggestionsContainer.contains(event.target)) {
suggestionsContainer.classList.add('d-none');
}
});
});
</script>
{{end}}

View file

@ -0,0 +1,15 @@
{{define "location-geocode"}}
<div class="col-md-6">
<h2 class="mb-4">Address Search</h2>
<div class="mb-3 position-relative">
<label for="addressInput" class="form-label">Enter address</label>
<input type="text" class="form-control" id="addressInput"
placeholder="Start typing an address (min 3 characters)">
<div id="suggestions" class="suggestions-container list-group d-none"></div>
</div>
<div class="mt-3">
<h5>Selected Location Details:</h5>
<pre id="locationDetails" class="p-3 bg-light">No location selected</pre>
</div>
</div>
{{end}}

View file

@ -2,6 +2,7 @@
{{define "title"}}Green Pool{{end}}
{{define "extraheader"}}
{{template "location-geocode-header" .}}
{{template "photo-upload-header"}}
<style>
.district-logo {
@ -99,8 +100,7 @@
<div class="row mb-3">
<div class="col-md-12">
<label for="address" class="form-label">Address or Description of Location</label>
<input type="text" class="form-control" id="address" placeholder="123 Main St, City, State or nearby landmark description">
{{template "location-geocode"}}
</div>
</div>