up source events
This commit is contained in:
parent
7971e48636
commit
f18383fb9e
3 changed files with 489 additions and 27 deletions
|
@ -152,10 +152,11 @@ class DemoMainResource:
|
|||
<li><a href="/event?what=music" >Search Music Events</a></li>
|
||||
<li><a href="/event?what=sport" >Search Sport Events</a></li>
|
||||
</ul>
|
||||
<p><a href="/demo/add" class="add-event-btn" style="display: block; text-align: center; margin-top: 15px; padding: 8px; background-color: #0078ff; color: white; border-radius: 4px; font-weight: bold;">+ Add New Event</a></p>
|
||||
<p><a href="/demo/traffic" class="add-event-btn" style="display: block; text-align: center; margin-top: 15px; padding: 8px; background-color: #0078ff; color: white; border-radius: 4px; font-weight: bold;">+ Traffic event</a></p>
|
||||
<p><a href="/demo/add" class="add-event-btn" style="display: block; text-align: center; margin-top: 15px; padding: 8px; background-color: #0078ff; color: white; border-radius: 4px; font-weight: bold;">+ Any Event</a></p>
|
||||
<p style="text-align: center; margin-top: 10px;">
|
||||
<a href="https://source.cipherbliss.com/tykayn/oedb-backend" title="View Source Code on Cipherbliss" style="font-size: 24px;">
|
||||
<i class="fas fa-code-branch"></i>
|
||||
<i class="fas fa-code-branch"></i> sources
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -279,8 +280,8 @@ class DemoMainResource:
|
|||
|
||||
// Function to fetch events from the API
|
||||
function fetchEvents() {
|
||||
// Fetch events from the API - using default behavior to get currently active events
|
||||
fetch('/event')
|
||||
// Fetch events from the API - using the external API endpoint
|
||||
fetch('https://api.openeventdatabase.org/event?')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.features && data.features.length > 0) {
|
||||
|
@ -349,6 +350,10 @@ class DemoMainResource:
|
|||
displayValue = `<pre style="margin: 0; white-space: pre-wrap;">${JSON.stringify(value, null, 2)}</pre>`;
|
||||
} else if (typeof value === 'string' && value.startsWith('http')) {
|
||||
displayValue = `<a href="${value}" >${value}</a>`;
|
||||
} else if (typeof value === 'string' && (key === 'start' || key === 'stop' || key.includes('date') || key.includes('time'))) {
|
||||
// For date fields, show both the original date and the relative time
|
||||
const relativeTime = getRelativeTimeString(value);
|
||||
displayValue = `${value} <span style="color: #666; font-style: italic;">(il y a ${relativeTime})</span>`;
|
||||
} else {
|
||||
displayValue = String(value);
|
||||
}
|
||||
|
@ -425,6 +430,35 @@ class DemoMainResource:
|
|||
});
|
||||
}
|
||||
|
||||
// Function to calculate relative time (e.g., "2 hours 30 minutes ago")
|
||||
function getRelativeTimeString(dateString) {
|
||||
if (!dateString) return '';
|
||||
|
||||
// Parse the date string
|
||||
const date = new Date(dateString);
|
||||
if (isNaN(date.getTime())) return dateString; // Return original if invalid
|
||||
|
||||
// Calculate time difference in milliseconds
|
||||
const now = new Date();
|
||||
const diffMs = now - date;
|
||||
|
||||
// Convert to hours and minutes
|
||||
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
||||
const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
|
||||
|
||||
// Format the relative time string
|
||||
let relativeTime = '';
|
||||
if (diffHours > 0) {
|
||||
relativeTime += `${diffHours} heure${diffHours > 1 ? 's' : ''}`;
|
||||
}
|
||||
if (diffMinutes > 0 || diffHours === 0) {
|
||||
if (diffHours > 0) relativeTime += ' ';
|
||||
relativeTime += `${diffMinutes} minute${diffMinutes > 1 ? 's' : ''}`;
|
||||
}
|
||||
|
||||
return relativeTime || "à l instant";
|
||||
}
|
||||
|
||||
// Function to fit map to events bounds
|
||||
function fitMapToBounds(geojson) {
|
||||
if (geojson.features.length === 0) return;
|
||||
|
|
|
@ -419,3 +419,95 @@ button:hover {
|
|||
padding: 1rem 2rem;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#report_issue_button{
|
||||
position: fixed;
|
||||
bottom: 0.5rem;
|
||||
right: 0.5rem;
|
||||
}
|
||||
|
||||
/* Tab styles */
|
||||
.tabs {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
border-bottom: none;
|
||||
margin-right: 5px;
|
||||
border-radius: 5px 5px 0 0;
|
||||
background-color: #f8f9fa;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.tab-item i {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tab-item:hover {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
background-color: white;
|
||||
border-color: #ddd;
|
||||
border-bottom-color: white;
|
||||
margin-bottom: -1px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tab-pane {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-pane.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Family-based colors for issue buttons */
|
||||
.issue-button.road {
|
||||
background-color: #2196f3; /* Blue for road issues */
|
||||
color: white;
|
||||
}
|
||||
|
||||
.issue-button.rail {
|
||||
background-color: #673ab7; /* Purple for rail issues */
|
||||
color: white;
|
||||
}
|
||||
|
||||
.issue-button.weather {
|
||||
background-color: #ff9800; /* Orange for weather issues */
|
||||
color: white;
|
||||
}
|
||||
|
||||
.issue-button.emergency {
|
||||
background-color: #f44336; /* Red for emergency issues */
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Disabled button styles */
|
||||
button:disabled,
|
||||
button[disabled] {
|
||||
background-color: #cccccc !important;
|
||||
color: #666666 !important;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* Invalid form field styles */
|
||||
input:invalid,
|
||||
select:invalid {
|
||||
border-color: #f44336;
|
||||
background-color: #fff8f8;
|
||||
}
|
|
@ -63,22 +63,111 @@
|
|||
</div>
|
||||
|
||||
<h3>Select Issue Type</h3>
|
||||
<div class="issue-buttons">
|
||||
<div class="issue-button pothole" onclick="fillForm('pothole')">
|
||||
<i class="fas fa-dot-circle"></i>
|
||||
Pothole
|
||||
|
||||
<!-- Tab Navigation -->
|
||||
<div class="tabs">
|
||||
<div class="tab-item active" data-tab="road">
|
||||
<i class="fas fa-road"></i> Road
|
||||
</div>
|
||||
<div class="issue-button obstacle" onclick="fillForm('obstacle')">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
Obstacle
|
||||
<div class="tab-item" data-tab="rail">
|
||||
<i class="fas fa-train"></i> Rail
|
||||
</div>
|
||||
<div class="issue-button vehicle" onclick="fillForm('vehicle')">
|
||||
<i class="fas fa-car"></i>
|
||||
Vehicle on Side
|
||||
<div class="tab-item" data-tab="weather">
|
||||
<i class="fas fa-cloud-sun-rain"></i> Weather
|
||||
</div>
|
||||
<div class="issue-button danger" onclick="fillForm('danger')">
|
||||
<i class="fas fa-skull-crossbones"></i>
|
||||
Danger
|
||||
<div class="tab-item" data-tab="emergency">
|
||||
<i class="fas fa-exclamation-circle"></i> Emergency
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab Content -->
|
||||
<div class="tab-content">
|
||||
<!-- Road Tab -->
|
||||
<div class="tab-pane active" id="road-tab">
|
||||
<div class="issue-buttons">
|
||||
<div class="issue-button road pothole" onclick="fillForm('pothole')">
|
||||
<i class="fas fa-dot-circle"></i>
|
||||
Pothole
|
||||
</div>
|
||||
<div class="issue-button road obstacle" onclick="fillForm('obstacle')">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
Obstacle
|
||||
</div>
|
||||
<div class="issue-button road vehicle" onclick="fillForm('vehicle')">
|
||||
<i class="fas fa-car"></i>
|
||||
Vehicle on Side
|
||||
</div>
|
||||
<div class="issue-button road danger" onclick="fillForm('danger')">
|
||||
<i class="fas fa-skull-crossbones"></i>
|
||||
Danger
|
||||
</div>
|
||||
<div class="issue-button road accident" onclick="fillForm('accident')">
|
||||
<i class="fas fa-car-crash"></i>
|
||||
Accident
|
||||
</div>
|
||||
<div class="issue-button road flooded-road" onclick="fillForm('flooded_road')">
|
||||
<i class="fas fa-water"></i>
|
||||
Flooded Road
|
||||
</div>
|
||||
<div class="issue-button road roadwork" onclick="fillForm('roadwork')">
|
||||
<i class="fas fa-hard-hat"></i>
|
||||
Roadwork
|
||||
</div>
|
||||
<div class="issue-button road black-traffic" onclick="fillForm('black_traffic')">
|
||||
<i class="fas fa-traffic-light"></i>
|
||||
Black Traffic
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Rail Tab -->
|
||||
<div class="tab-pane" id="rail-tab">
|
||||
<div class="issue-buttons">
|
||||
<div class="issue-button rail unattended-luggage" onclick="fillForm('unattended_luggage')">
|
||||
<i class="fas fa-suitcase"></i>
|
||||
Unattended Luggage
|
||||
</div>
|
||||
<div class="issue-button rail transport-delay" onclick="fillForm('transport_delay')">
|
||||
<i class="fas fa-hourglass-half"></i>
|
||||
Delay
|
||||
</div>
|
||||
<div class="issue-button rail major-delay" onclick="fillForm('major_transport_delay')">
|
||||
<i class="fas fa-hourglass-end"></i>
|
||||
Major Delay
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Weather Tab -->
|
||||
<div class="tab-pane" id="weather-tab">
|
||||
<div class="issue-buttons">
|
||||
<div class="issue-button weather flood-danger" onclick="fillForm('flood_danger')">
|
||||
<i class="fas fa-water"></i>
|
||||
Flood Alert
|
||||
</div>
|
||||
<div class="issue-button weather thunderstorm" onclick="fillForm('thunderstorm_alert')">
|
||||
<i class="fas fa-bolt"></i>
|
||||
Thunderstorm
|
||||
</div>
|
||||
<div class="issue-button weather fog" onclick="fillForm('fog_warning')">
|
||||
<i class="fas fa-smog"></i>
|
||||
Fog Warning
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Emergency Tab -->
|
||||
<div class="tab-pane" id="emergency-tab">
|
||||
<div class="issue-buttons">
|
||||
<div class="issue-button emergency emergency-alert" onclick="fillForm('emergency_alert')">
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
Emergency Alert
|
||||
</div>
|
||||
<div class="issue-button emergency daylight-saving" onclick="fillForm('daylight_saving')">
|
||||
<i class="fas fa-clock"></i>
|
||||
Daylight Saving
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -134,7 +223,7 @@
|
|||
<div class="note">Click on the map to set the issue location or use the "Get My Current Location" button</div>
|
||||
</div>
|
||||
|
||||
<button type="submit">Report Issue</button>
|
||||
<button id="report_issue_button" type="submit" disabled>Report Issue</button>
|
||||
</form>
|
||||
|
||||
<div id="result"></div>
|
||||
|
@ -161,6 +250,49 @@
|
|||
// Call function to set default dates
|
||||
setDefaultDates();
|
||||
|
||||
// Tab switching functionality
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Get all tab items
|
||||
const tabItems = document.querySelectorAll('.tab-item');
|
||||
|
||||
// Add click event listener to each tab item
|
||||
tabItems.forEach(tab => {
|
||||
tab.addEventListener('click', function() {
|
||||
// Remove active class from all tab items
|
||||
tabItems.forEach(item => item.classList.remove('active'));
|
||||
|
||||
// Add active class to clicked tab item
|
||||
this.classList.add('active');
|
||||
|
||||
// Get the tab name from data-tab attribute
|
||||
const tabName = this.getAttribute('data-tab');
|
||||
|
||||
// Get all tab panes
|
||||
const tabPanes = document.querySelectorAll('.tab-pane');
|
||||
|
||||
// Remove active class from all tab panes
|
||||
tabPanes.forEach(pane => pane.classList.remove('active'));
|
||||
|
||||
// Add active class to the corresponding tab pane
|
||||
document.getElementById(tabName + '-tab').classList.add('active');
|
||||
|
||||
// Save active tab to localStorage
|
||||
localStorage.setItem('activeTab', tabName);
|
||||
});
|
||||
});
|
||||
|
||||
// Restore active tab from localStorage
|
||||
const activeTab = localStorage.getItem('activeTab');
|
||||
if (activeTab) {
|
||||
// Find the tab item with the saved tab name
|
||||
const tabItem = document.querySelector(`.tab-item[data-tab="${activeTab}"]`);
|
||||
if (tabItem) {
|
||||
// Trigger click event on the tab item
|
||||
tabItem.click();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize the map
|
||||
const map = new maplibregl.Map({
|
||||
container: 'map',
|
||||
|
@ -178,6 +310,64 @@
|
|||
color: '#ff3860' // Red color for traffic jam
|
||||
});
|
||||
|
||||
// Store existing traffic event markers
|
||||
let existingMarkers = [];
|
||||
|
||||
// Function to fetch and display existing traffic events
|
||||
function fetchExistingTrafficEvents() {
|
||||
// Clear existing markers first
|
||||
existingMarkers.forEach(marker => marker.remove());
|
||||
existingMarkers = [];
|
||||
|
||||
// Fetch traffic events from the API
|
||||
fetch('https://api.openeventdatabase.org/event?what=traffic')
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
throw new Error('Failed to fetch existing traffic events');
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
if (data && data.features && Array.isArray(data.features)) {
|
||||
// Add markers for each event
|
||||
data.features.forEach(event => {
|
||||
if (event.geometry && event.geometry.type === 'Point') {
|
||||
const coords = event.geometry.coordinates;
|
||||
// Create a gray marker for existing events
|
||||
const eventMarker = new maplibregl.Marker({
|
||||
color: '#888888' // Gray color for existing events
|
||||
})
|
||||
.setLngLat(coords)
|
||||
.addTo(map);
|
||||
|
||||
// Add popup with event details
|
||||
const popup = new maplibregl.Popup({ offset: 25 })
|
||||
.setHTML(`
|
||||
<h3>${event.properties.label || 'Traffic Event'}</h3>
|
||||
<p>Type: ${event.properties.what || 'Unknown'}</p>
|
||||
<p>Start: ${event.properties.start || 'Unknown'}</p>
|
||||
<p>End: ${event.properties.stop || 'Unknown'}</p>
|
||||
`);
|
||||
|
||||
eventMarker.setPopup(popup);
|
||||
|
||||
// Store marker reference for later removal
|
||||
existingMarkers.push(eventMarker);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Loaded ${existingMarkers.length} existing traffic events`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching traffic events:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// Fetch existing events when the map loads
|
||||
map.on('load', fetchExistingTrafficEvents);
|
||||
|
||||
// Add marker on map click
|
||||
map.on('click', function(e) {
|
||||
marker.setLngLat(e.lngLat).addTo(map);
|
||||
|
@ -201,28 +391,100 @@
|
|||
switch(issueType) {
|
||||
case 'pothole':
|
||||
labelInput.value = 'Nid de poule';
|
||||
issueTypeInput.value = 'road.hazard.pothole';
|
||||
issueTypeInput.value = 'traffic.hazard.pothole';
|
||||
severitySelect.value = 'medium';
|
||||
markerColor = '#ff9800';
|
||||
break;
|
||||
case 'obstacle':
|
||||
labelInput.value = 'Obstacle';
|
||||
issueTypeInput.value = 'road.hazard.obstacle';
|
||||
issueTypeInput.value = 'traffic.hazard.obstacle';
|
||||
severitySelect.value = 'high';
|
||||
markerColor = '#f44336';
|
||||
break;
|
||||
case 'vehicle':
|
||||
labelInput.value = 'Véhicule sur le bas côté de la route';
|
||||
issueTypeInput.value = 'road.hazard.vehicle';
|
||||
issueTypeInput.value = 'traffic.hazard.vehicle';
|
||||
severitySelect.value = 'low';
|
||||
markerColor = '#2196f3';
|
||||
break;
|
||||
case 'danger':
|
||||
labelInput.value = 'Danger non classé';
|
||||
issueTypeInput.value = 'road.hazard.danger';
|
||||
issueTypeInput.value = 'traffic.hazard.danger';
|
||||
severitySelect.value = 'high';
|
||||
markerColor = '#9c27b0';
|
||||
break;
|
||||
case 'emergency_alert':
|
||||
labelInput.value = 'Alerte d\'urgence (SAIP)';
|
||||
issueTypeInput.value = 'alert.emergency';
|
||||
severitySelect.value = 'high';
|
||||
markerColor = '#e91e63'; // Pink
|
||||
break;
|
||||
case 'daylight_saving':
|
||||
labelInput.value = 'Période d\'heure d\'été';
|
||||
issueTypeInput.value = 'time.daylight.summer';
|
||||
severitySelect.value = 'low';
|
||||
markerColor = '#ffc107'; // Amber
|
||||
break;
|
||||
case 'accident':
|
||||
labelInput.value = 'Accident de la route';
|
||||
issueTypeInput.value = 'traffic.accident';
|
||||
severitySelect.value = 'high';
|
||||
markerColor = '#d32f2f'; // Dark red
|
||||
break;
|
||||
case 'flooded_road':
|
||||
labelInput.value = 'Route inondée';
|
||||
issueTypeInput.value = 'traffic.closed.flood';
|
||||
severitySelect.value = 'high';
|
||||
markerColor = '#1976d2'; // Blue
|
||||
break;
|
||||
case 'black_traffic':
|
||||
labelInput.value = 'Période noire bison futé vers la province';
|
||||
issueTypeInput.value = 'traffic.forecast.black.out';
|
||||
severitySelect.value = 'high';
|
||||
markerColor = '#212121'; // Black
|
||||
break;
|
||||
case 'roadwork':
|
||||
labelInput.value = 'Travaux';
|
||||
issueTypeInput.value = 'traffic.roadwork';
|
||||
severitySelect.value = 'medium';
|
||||
markerColor = '#ff5722'; // Deep orange
|
||||
break;
|
||||
case 'flood_danger':
|
||||
labelInput.value = 'Vigilance rouge inondation';
|
||||
issueTypeInput.value = 'weather.danger.flood';
|
||||
severitySelect.value = 'high';
|
||||
markerColor = '#b71c1c'; // Dark red
|
||||
break;
|
||||
case 'thunderstorm_alert':
|
||||
labelInput.value = 'Vigilance orange orages';
|
||||
issueTypeInput.value = 'weather.alert.thunderstorm';
|
||||
severitySelect.value = 'medium';
|
||||
markerColor = '#ff9800'; // Orange
|
||||
break;
|
||||
case 'fog_warning':
|
||||
labelInput.value = 'Vigilance jaune brouillard';
|
||||
issueTypeInput.value = 'weather.warning.fog';
|
||||
severitySelect.value = 'low';
|
||||
markerColor = '#ffeb3b'; // Yellow
|
||||
break;
|
||||
case 'unattended_luggage':
|
||||
labelInput.value = 'Bagage abandonné';
|
||||
issueTypeInput.value = 'public_transport.incident.unattended_luggage';
|
||||
severitySelect.value = 'medium';
|
||||
markerColor = '#673ab7'; // Deep purple
|
||||
break;
|
||||
case 'transport_delay':
|
||||
labelInput.value = 'Retard';
|
||||
issueTypeInput.value = 'public_transport.delay';
|
||||
severitySelect.value = 'low';
|
||||
markerColor = '#ffc107'; // Amber
|
||||
break;
|
||||
case 'major_transport_delay':
|
||||
labelInput.value = 'Retard important';
|
||||
issueTypeInput.value = 'public_transport.delay.major';
|
||||
severitySelect.value = 'medium';
|
||||
markerColor = '#ff5722'; // Deep orange
|
||||
break;
|
||||
default:
|
||||
labelInput.value = 'Bouchon';
|
||||
issueTypeInput.value = 'traffic.jam';
|
||||
|
@ -240,6 +502,9 @@
|
|||
if (currentLngLat) {
|
||||
marker.setLngLat(currentLngLat).addTo(map);
|
||||
}
|
||||
|
||||
// Validate form after filling in values
|
||||
validateForm();
|
||||
}
|
||||
|
||||
// Handle geolocation button click
|
||||
|
@ -272,6 +537,9 @@
|
|||
// Show success message
|
||||
showResult('Current location detected successfully', 'success');
|
||||
|
||||
// Validate form after setting marker
|
||||
validateForm();
|
||||
|
||||
// Try to get address using reverse geocoding
|
||||
fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}`)
|
||||
.then(response => response.json())
|
||||
|
@ -341,10 +609,75 @@
|
|||
}
|
||||
});
|
||||
|
||||
// Form validation function
|
||||
function validateForm() {
|
||||
// Get all required form fields
|
||||
const requiredFields = document.querySelectorAll('#trafficForm [required]');
|
||||
const submitButton = document.getElementById('report_issue_button');
|
||||
|
||||
// Check if all required fields are filled
|
||||
let isValid = true;
|
||||
|
||||
// Check each required field
|
||||
requiredFields.forEach(field => {
|
||||
if (!field.value.trim()) {
|
||||
isValid = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Check if marker is set
|
||||
if (!marker || !marker.getLngLat()) {
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// Enable or disable submit button based on form validity
|
||||
submitButton.disabled = !isValid;
|
||||
|
||||
// Add or remove disabled class
|
||||
if (isValid) {
|
||||
submitButton.classList.remove('disabled');
|
||||
} else {
|
||||
submitButton.classList.add('disabled');
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// Add event listeners to form fields to trigger validation
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Get all form fields
|
||||
const formFields = document.querySelectorAll('#trafficForm input, #trafficForm select');
|
||||
|
||||
// Add input event listener to each field
|
||||
formFields.forEach(field => {
|
||||
field.addEventListener('input', validateForm);
|
||||
});
|
||||
|
||||
// Add change event listener to each field
|
||||
formFields.forEach(field => {
|
||||
field.addEventListener('change', validateForm);
|
||||
});
|
||||
|
||||
// Validate form on page load
|
||||
validateForm();
|
||||
});
|
||||
|
||||
// Update validation when marker is set
|
||||
map.on('click', function() {
|
||||
// Validate form after marker is set
|
||||
setTimeout(validateForm, 100);
|
||||
});
|
||||
|
||||
// Handle form submission
|
||||
document.getElementById('trafficForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Validate form before submission
|
||||
if (!validateForm()) {
|
||||
showResult('Please fill in all required fields and set a location on the map', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get form values
|
||||
const label = document.getElementById('label').value;
|
||||
const issueType = document.getElementById('issueType').value;
|
||||
|
@ -354,7 +687,7 @@
|
|||
const stop = document.getElementById('stop').value;
|
||||
const where = document.getElementById('where').value;
|
||||
|
||||
// Check if marker is set
|
||||
// Check if marker is set (redundant but kept for safety)
|
||||
if (!marker.getLngLat()) {
|
||||
showResult('Please set a location by clicking on the map or using the geolocation button', 'error');
|
||||
return;
|
||||
|
@ -413,7 +746,7 @@
|
|||
saveEventToLocalStorage(event);
|
||||
|
||||
// Submit event to API
|
||||
fetch('/event', {
|
||||
fetch('https://api.openeventdatabase.org/event', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -441,7 +774,7 @@
|
|||
const resultElement = document.getElementById('result');
|
||||
resultElement.innerHTML += `
|
||||
<p>
|
||||
<a href="/event/${data.id}" >View Report on Server</a> |
|
||||
<a href="https://api.openeventdatabase.org/event/${data.id}" >View Report on Server</a> |
|
||||
<a href="/demo/view-events" >View Saved Reports</a> |
|
||||
<a href="/demo">Back to Map</a>
|
||||
</p>`;
|
||||
|
@ -452,6 +785,9 @@
|
|||
setDefaultDates();
|
||||
// Remove marker
|
||||
marker.remove();
|
||||
|
||||
// Refresh the map to show the new event along with existing ones
|
||||
fetchExistingTrafficEvents();
|
||||
})
|
||||
.catch(error => {
|
||||
showResult(`Error reporting issue: ${error.message}`, 'error');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue