Files
tankstopp-app/geolocation_test.html
T
2025-07-07 01:44:12 +02:00

477 lines
19 KiB
HTML

<!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>