first commit
This commit is contained in:
@@ -0,0 +1,476 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Geolocation Test - TankStopp Debug</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
.debug-info {
|
||||
background: #f8f9fa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 0.375rem;
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
font-family: monospace;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.success { color: #198754; }
|
||||
.error { color: #dc3545; }
|
||||
.warning { color: #fd7e14; }
|
||||
.info { color: #0d6efd; }
|
||||
.test-step {
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 0.375rem;
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.status-indicator {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.status-pass { background-color: #198754; }
|
||||
.status-fail { background-color: #dc3545; }
|
||||
.status-warn { background-color: #fd7e14; }
|
||||
.status-pending { background-color: #6c757d; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-4">
|
||||
<h1>Geolocation Test Page</h1>
|
||||
<p class="lead">This page helps debug geolocation issues with the fuel station finder.</p>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<strong>Instructions:</strong>
|
||||
<ol class="mb-0">
|
||||
<li>Click "Run All Tests" to check your browser's geolocation capabilities</li>
|
||||
<li>Review the results below to identify any issues</li>
|
||||
<li>Use the detailed logs to troubleshoot problems</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<button class="btn btn-primary" onclick="runAllTests()">Run All Tests</button>
|
||||
<button class="btn btn-secondary" onclick="clearLog()">Clear Log</button>
|
||||
<button class="btn btn-outline-info" onclick="testStationSearch()">Test Station Search</button>
|
||||
</div>
|
||||
|
||||
<div id="test-results">
|
||||
<div class="test-step">
|
||||
<h5><span class="status-indicator status-pending" id="status-env"></span>Environment Check</h5>
|
||||
<div id="result-env">Click "Run All Tests" to start...</div>
|
||||
</div>
|
||||
|
||||
<div class="test-step">
|
||||
<h5><span class="status-indicator status-pending" id="status-geolocation"></span>Geolocation Support</h5>
|
||||
<div id="result-geolocation">Waiting for test...</div>
|
||||
</div>
|
||||
|
||||
<div class="test-step">
|
||||
<h5><span class="status-indicator status-pending" id="status-permissions"></span>Permission Status</h5>
|
||||
<div id="result-permissions">Waiting for test...</div>
|
||||
</div>
|
||||
|
||||
<div class="test-step">
|
||||
<h5><span class="status-indicator status-pending" id="status-location"></span>Get Current Location</h5>
|
||||
<div id="result-location">Waiting for test...</div>
|
||||
</div>
|
||||
|
||||
<div class="test-step">
|
||||
<h5><span class="status-indicator status-pending" id="status-api"></span>OpenStreetMap API Test</h5>
|
||||
<div id="result-api">Waiting for test...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<h3>Debug Log</h3>
|
||||
<div id="debug-log" class="debug-info" style="height: 300px; overflow-y: auto;">
|
||||
Waiting for tests to run...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<h3>Manual Station Search Test</h3>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control mb-2" id="manual-lat" placeholder="Latitude (e.g., 52.5200)" value="52.5200">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control mb-2" id="manual-lon" placeholder="Longitude (e.g., 13.4050)" value="13.4050">
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-outline-primary" onclick="searchStationsAtCoords()">Search Stations at Coordinates</button>
|
||||
<div id="manual-search-results" class="mt-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
let debugLog = [];
|
||||
|
||||
function log(message, type = 'info') {
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
const logEntry = `[${timestamp}] ${message}`;
|
||||
debugLog.push(logEntry);
|
||||
|
||||
const logDiv = document.getElementById('debug-log');
|
||||
const colorClass = type === 'error' ? 'error' :
|
||||
type === 'success' ? 'success' :
|
||||
type === 'warning' ? 'warning' : 'info';
|
||||
|
||||
logDiv.innerHTML += `<div class="${colorClass}">${logEntry}</div>`;
|
||||
logDiv.scrollTop = logDiv.scrollHeight;
|
||||
|
||||
console.log(logEntry);
|
||||
}
|
||||
|
||||
function setStatus(testId, status) {
|
||||
const indicator = document.getElementById(`status-${testId}`);
|
||||
indicator.className = `status-indicator status-${status}`;
|
||||
}
|
||||
|
||||
function setResult(testId, html) {
|
||||
document.getElementById(`result-${testId}`).innerHTML = html;
|
||||
}
|
||||
|
||||
function clearLog() {
|
||||
debugLog = [];
|
||||
document.getElementById('debug-log').innerHTML = '';
|
||||
}
|
||||
|
||||
async function runAllTests() {
|
||||
clearLog();
|
||||
log('Starting geolocation tests...', 'info');
|
||||
|
||||
await testEnvironment();
|
||||
await testGeolocationSupport();
|
||||
await testPermissions();
|
||||
await testGetLocation();
|
||||
|
||||
log('All tests completed!', 'success');
|
||||
}
|
||||
|
||||
async function testEnvironment() {
|
||||
log('Testing environment...', 'info');
|
||||
|
||||
const isHttps = location.protocol === 'https:';
|
||||
const isLocalhost = location.hostname === 'localhost' || location.hostname === '127.0.0.1';
|
||||
const isSecure = isHttps || isLocalhost;
|
||||
|
||||
let result = `
|
||||
<div><strong>Protocol:</strong> ${location.protocol}</div>
|
||||
<div><strong>Hostname:</strong> ${location.hostname}</div>
|
||||
<div><strong>Port:</strong> ${location.port || 'default'}</div>
|
||||
<div><strong>Secure Context:</strong> ${isSecure ? '✅ Yes' : '❌ No'}</div>
|
||||
<div><strong>User Agent:</strong> ${navigator.userAgent}</div>
|
||||
`;
|
||||
|
||||
if (!isSecure) {
|
||||
result += '<div class="alert alert-warning mt-2">⚠️ Geolocation requires HTTPS or localhost</div>';
|
||||
setStatus('env', 'warn');
|
||||
log('Warning: Not in secure context', 'warning');
|
||||
} else {
|
||||
setStatus('env', 'pass');
|
||||
log('Environment check passed', 'success');
|
||||
}
|
||||
|
||||
setResult('env', result);
|
||||
}
|
||||
|
||||
async function testGeolocationSupport() {
|
||||
log('Testing geolocation support...', 'info');
|
||||
|
||||
const supported = !!navigator.geolocation;
|
||||
|
||||
let result = `
|
||||
<div><strong>Geolocation API:</strong> ${supported ? '✅ Supported' : '❌ Not Supported'}</div>
|
||||
<div><strong>Navigator Object:</strong> ${typeof navigator}</div>
|
||||
`;
|
||||
|
||||
if (supported) {
|
||||
result += `
|
||||
<div><strong>getCurrentPosition:</strong> ${typeof navigator.geolocation.getCurrentPosition}</div>
|
||||
<div><strong>watchPosition:</strong> ${typeof navigator.geolocation.watchPosition}</div>
|
||||
`;
|
||||
setStatus('geolocation', 'pass');
|
||||
log('Geolocation API is supported', 'success');
|
||||
} else {
|
||||
setStatus('geolocation', 'fail');
|
||||
log('Geolocation API is not supported', 'error');
|
||||
}
|
||||
|
||||
setResult('geolocation', result);
|
||||
}
|
||||
|
||||
async function testPermissions() {
|
||||
log('Testing permission status...', 'info');
|
||||
|
||||
let result = '<div><strong>Permissions API:</strong> ';
|
||||
|
||||
if (navigator.permissions) {
|
||||
result += '✅ Supported</div>';
|
||||
|
||||
try {
|
||||
const permission = await navigator.permissions.query({name: 'geolocation'});
|
||||
result += `<div><strong>Current Status:</strong> ${permission.state}</div>`;
|
||||
|
||||
switch(permission.state) {
|
||||
case 'granted':
|
||||
result += '<div class="alert alert-success mt-2">✅ Location permission granted</div>';
|
||||
setStatus('permissions', 'pass');
|
||||
log('Location permission is granted', 'success');
|
||||
break;
|
||||
case 'denied':
|
||||
result += '<div class="alert alert-danger mt-2">❌ Location permission denied</div>';
|
||||
setStatus('permissions', 'fail');
|
||||
log('Location permission is denied', 'error');
|
||||
break;
|
||||
case 'prompt':
|
||||
result += '<div class="alert alert-info mt-2">🔔 Location permission will be requested</div>';
|
||||
setStatus('permissions', 'warn');
|
||||
log('Location permission will be prompted', 'warning');
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
result += `<div class="alert alert-warning mt-2">⚠️ Permission query failed: ${error.message}</div>`;
|
||||
setStatus('permissions', 'warn');
|
||||
log(`Permission query error: ${error.message}`, 'warning');
|
||||
}
|
||||
} else {
|
||||
result += '❌ Not Supported</div>';
|
||||
result += '<div class="alert alert-warning mt-2">⚠️ Cannot check permission status</div>';
|
||||
setStatus('permissions', 'warn');
|
||||
log('Permissions API not supported', 'warning');
|
||||
}
|
||||
|
||||
setResult('permissions', result);
|
||||
}
|
||||
|
||||
async function testGetLocation() {
|
||||
log('Testing location retrieval...', 'info');
|
||||
setResult('location', '<div>🔄 Requesting location... Please allow when prompted.</div>');
|
||||
|
||||
if (!navigator.geolocation) {
|
||||
setResult('location', '<div class="alert alert-danger">❌ Geolocation not supported</div>');
|
||||
setStatus('location', 'fail');
|
||||
return;
|
||||
}
|
||||
|
||||
const options = {
|
||||
enableHighAccuracy: true,
|
||||
timeout: 15000,
|
||||
maximumAge: 300000
|
||||
};
|
||||
|
||||
try {
|
||||
log('Requesting current position with high accuracy...', 'info');
|
||||
|
||||
const position = await new Promise((resolve, reject) => {
|
||||
navigator.geolocation.getCurrentPosition(resolve, reject, options);
|
||||
});
|
||||
|
||||
const { latitude, longitude, accuracy, timestamp } = position.coords;
|
||||
|
||||
let result = `
|
||||
<div class="alert alert-success">✅ Location obtained successfully!</div>
|
||||
<div><strong>Latitude:</strong> ${latitude}</div>
|
||||
<div><strong>Longitude:</strong> ${longitude}</div>
|
||||
<div><strong>Accuracy:</strong> ${Math.round(accuracy)}m</div>
|
||||
<div><strong>Timestamp:</strong> ${new Date(timestamp).toLocaleString()}</div>
|
||||
`;
|
||||
|
||||
if (position.coords.altitude !== null) {
|
||||
result += `<div><strong>Altitude:</strong> ${Math.round(position.coords.altitude)}m</div>`;
|
||||
}
|
||||
|
||||
if (position.coords.speed !== null) {
|
||||
result += `<div><strong>Speed:</strong> ${Math.round(position.coords.speed * 3.6)}km/h</div>`;
|
||||
}
|
||||
|
||||
setResult('location', result);
|
||||
setStatus('location', 'pass');
|
||||
log(`Location obtained: ${latitude}, ${longitude} (±${Math.round(accuracy)}m)`, 'success');
|
||||
|
||||
// Automatically test API with obtained coordinates
|
||||
await testOpenStreetMapAPI(latitude, longitude);
|
||||
|
||||
} catch (error) {
|
||||
let errorMsg = 'Unknown error';
|
||||
let suggestion = '';
|
||||
|
||||
switch(error.code) {
|
||||
case 1: // PERMISSION_DENIED
|
||||
errorMsg = 'Permission denied';
|
||||
suggestion = 'Please allow location access and refresh the page.';
|
||||
break;
|
||||
case 2: // POSITION_UNAVAILABLE
|
||||
errorMsg = 'Position unavailable';
|
||||
suggestion = 'Check GPS settings and try again.';
|
||||
break;
|
||||
case 3: // TIMEOUT
|
||||
errorMsg = 'Request timeout';
|
||||
suggestion = 'Try again or move to a location with better signal.';
|
||||
break;
|
||||
default:
|
||||
errorMsg = error.message || 'Unknown error';
|
||||
suggestion = 'Check browser console for more details.';
|
||||
}
|
||||
|
||||
const result = `
|
||||
<div class="alert alert-danger">❌ Failed to get location</div>
|
||||
<div><strong>Error:</strong> ${errorMsg} (Code: ${error.code})</div>
|
||||
<div><strong>Suggestion:</strong> ${suggestion}</div>
|
||||
`;
|
||||
|
||||
setResult('location', result);
|
||||
setStatus('location', 'fail');
|
||||
log(`Location error: ${errorMsg} (${error.code})`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function testOpenStreetMapAPI(lat, lon) {
|
||||
log('Testing OpenStreetMap API...', 'info');
|
||||
setResult('api', '<div>🔄 Testing API connection...</div>');
|
||||
|
||||
const overpassUrl = 'https://overpass-api.de/api/interpreter';
|
||||
const query = `
|
||||
[out:json][timeout:25];
|
||||
(
|
||||
node["amenity"="fuel"](around:2000,${lat},${lon});
|
||||
);
|
||||
out center meta;
|
||||
`;
|
||||
|
||||
try {
|
||||
log('Sending request to OpenStreetMap...', 'info');
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 30000);
|
||||
|
||||
const response = await fetch(overpassUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: 'data=' + encodeURIComponent(query),
|
||||
signal: controller.signal
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.elements && data.elements.length > 0) {
|
||||
const stations = data.elements.slice(0, 5); // Show first 5
|
||||
|
||||
let result = `
|
||||
<div class="alert alert-success">✅ API test successful!</div>
|
||||
<div><strong>Stations Found:</strong> ${data.elements.length}</div>
|
||||
<div><strong>Sample Results:</strong></div>
|
||||
<ul class="mt-2">
|
||||
`;
|
||||
|
||||
stations.forEach(station => {
|
||||
const name = station.tags?.name || station.tags?.brand || 'Unknown Station';
|
||||
const address = [
|
||||
station.tags?.['addr:street'],
|
||||
station.tags?.['addr:city']
|
||||
].filter(Boolean).join(', ') || 'No address';
|
||||
|
||||
result += `<li><strong>${name}</strong> - ${address}</li>`;
|
||||
});
|
||||
|
||||
result += '</ul>';
|
||||
|
||||
setResult('api', result);
|
||||
setStatus('api', 'pass');
|
||||
log(`API test successful: Found ${data.elements.length} stations`, 'success');
|
||||
} else {
|
||||
setResult('api', '<div class="alert alert-warning">⚠️ API works but no stations found in 2km radius</div>');
|
||||
setStatus('api', 'warn');
|
||||
log('API works but no stations found nearby', 'warning');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
let errorMsg = 'API request failed';
|
||||
|
||||
if (error.name === 'AbortError') {
|
||||
errorMsg = 'Request timed out';
|
||||
} else if (error.message.includes('Failed to fetch')) {
|
||||
errorMsg = 'Network error - check internet connection';
|
||||
} else {
|
||||
errorMsg = error.message;
|
||||
}
|
||||
|
||||
const result = `
|
||||
<div class="alert alert-danger">❌ API test failed</div>
|
||||
<div><strong>Error:</strong> ${errorMsg}</div>
|
||||
<div><strong>Suggestion:</strong> Check internet connection and try again.</div>
|
||||
`;
|
||||
|
||||
setResult('api', result);
|
||||
setStatus('api', 'fail');
|
||||
log(`API test failed: ${errorMsg}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function testStationSearch() {
|
||||
log('Testing full station search flow...', 'info');
|
||||
|
||||
if (!navigator.geolocation) {
|
||||
alert('Geolocation not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const position = await new Promise((resolve, reject) => {
|
||||
navigator.geolocation.getCurrentPosition(resolve, reject, {
|
||||
enableHighAccuracy: true,
|
||||
timeout: 10000,
|
||||
maximumAge: 300000
|
||||
});
|
||||
});
|
||||
|
||||
await testOpenStreetMapAPI(position.coords.latitude, position.coords.longitude);
|
||||
} catch (error) {
|
||||
log(`Station search test failed: ${error.message}`, 'error');
|
||||
alert(`Failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function searchStationsAtCoords() {
|
||||
const lat = parseFloat(document.getElementById('manual-lat').value);
|
||||
const lon = parseFloat(document.getElementById('manual-lon').value);
|
||||
|
||||
if (isNaN(lat) || isNaN(lon)) {
|
||||
alert('Please enter valid coordinates');
|
||||
return;
|
||||
}
|
||||
|
||||
log(`Manual search at coordinates: ${lat}, ${lon}`, 'info');
|
||||
|
||||
const resultsDiv = document.getElementById('manual-search-results');
|
||||
resultsDiv.innerHTML = '<div class="text-center">🔄 Searching...</div>';
|
||||
|
||||
try {
|
||||
await testOpenStreetMapAPI(lat, lon);
|
||||
resultsDiv.innerHTML = '<div class="alert alert-success">Check the API test results above!</div>';
|
||||
} catch (error) {
|
||||
resultsDiv.innerHTML = `<div class="alert alert-danger">Search failed: ${error.message}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
// Run basic checks on page load
|
||||
window.addEventListener('load', function() {
|
||||
log('Page loaded, ready for testing', 'info');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user