water-station-tracker/public/city-select.html
Will Bradley 275c91f4e1 Allow users to edit the station itself when clicking a station (description, etc). Humanize refill/empty date/time formats. Remove last
updated line on the popup. On the select city page only show the add new city section and heading when logged in, adjust the login link
  based on logged-in status, and say click to update on each city button when logged in.
2025-07-16 13:16:16 -07:00

349 lines
10 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Select City - Water Station Tracker</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
}
.container {
background: white;
border-radius: 10px;
box-shadow: 0 15px 35px rgba(0,0,0,0.1);
padding: 2rem;
width: 100%;
max-width: 500px;
}
.header {
text-align: center;
margin-bottom: 2rem;
}
.header h1 {
color: #333;
font-size: 2rem;
margin-bottom: 0.5rem;
}
.header p {
color: #666;
font-size: 1rem;
}
.city-list {
max-height: 400px;
overflow-y: auto;
margin-bottom: 2rem;
}
.city-item {
padding: 1rem;
border: 2px solid #e1e1e1;
border-radius: 8px;
margin-bottom: 1rem;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
justify-content: space-between;
align-items: center;
}
.city-item:hover {
border-color: #667eea;
background: #f8f9ff;
}
.city-name {
font-size: 1.1rem;
font-weight: 500;
color: #333;
}
.city-stats {
font-size: 0.9rem;
color: #666;
}
.add-city-form {
border-top: 1px solid #e1e1e1;
padding-top: 2rem;
}
.form-group {
margin-bottom: 1rem;
}
label {
display: block;
margin-bottom: 0.5rem;
color: #333;
font-weight: 500;
}
input[type="text"] {
width: 100%;
padding: 0.8rem;
border: 2px solid #e1e1e1;
border-radius: 6px;
font-size: 1rem;
transition: border-color 0.3s;
}
input[type="text"]:focus {
outline: none;
border-color: #667eea;
}
.btn {
width: 100%;
padding: 0.8rem;
border: none;
border-radius: 6px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: background-color 0.3s;
}
.btn-primary {
background: #667eea;
color: white;
}
.btn-primary:hover {
background: #5a6fd8;
}
.btn-secondary {
background: #6c757d;
color: white;
margin-top: 1rem;
}
.btn-secondary:hover {
background: #5a6268;
}
.message {
padding: 0.8rem;
margin-bottom: 1rem;
border-radius: 6px;
font-size: 0.9rem;
}
.message.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.loading {
text-align: center;
padding: 2rem;
color: #666;
}
.auth-links {
text-align: center;
margin-top: 1rem;
}
.auth-links a {
color: #667eea;
text-decoration: none;
margin: 0 0.5rem;
}
.auth-links a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>💧 Water Station Tracker</h1>
<p>Select a city to view water stations</p>
</div>
<div id="message"></div>
<div id="cityList" class="city-list">
<div class="loading">Loading cities...</div>
</div>
<div class="add-city-form" id="addCitySection" style="display: none;">
<h3>Add New City</h3>
<form id="addCityForm">
<div class="form-group">
<label for="cityName">City Name</label>
<input type="text" id="cityName" name="display_name" required placeholder="e.g., San Francisco">
</div>
<button type="submit" class="btn btn-primary">Add City</button>
</form>
</div>
<div class="auth-links">
<a href="/login">Login</a>
<span>|</span>
<a href="/city/salem">View Salem (Default)</a>
</div>
</div>
<script>
let cities = [];
let user = null;
async function initPage() {
await checkAuth();
loadCities();
}
async function checkAuth() {
try {
const response = await fetch('/api/user');
const data = await response.json();
user = data.user;
updateUIBasedOnAuth();
} catch (error) {
console.error('Auth check failed:', error);
updateUIBasedOnAuth();
}
}
function updateUIBasedOnAuth() {
const addCitySection = document.getElementById('addCitySection');
const authLinks = document.querySelector('.auth-links');
if (user) {
addCitySection.style.display = 'block';
authLinks.innerHTML = `
<a href="/dashboard">Dashboard</a>
<span>|</span>
<a href="/city/salem">View Salem (Default)</a>
`;
} else {
addCitySection.style.display = 'none';
authLinks.innerHTML = `
<a href="/login">Login</a>
<span>|</span>
<a href="/city/salem">View Salem (Default)</a>
`;
}
}
async function loadCities() {
try {
const response = await fetch('/api/cities');
const data = await response.json();
cities = data;
displayCities();
} catch (error) {
console.error('Error loading cities:', error);
showMessage('Failed to load cities', 'error');
}
}
function displayCities() {
const cityList = document.getElementById('cityList');
if (cities.length === 0) {
cityList.innerHTML = '<p class="loading">No cities available</p>';
return;
}
const clickText = user ? 'Click to update' : 'Click to view';
cityList.innerHTML = cities.map(city => `
<div class="city-item" onclick="selectCity('${city.name}')">
<div class="city-name">${city.display_name}</div>
<div class="city-stats">${clickText}</div>
</div>
`).join('');
}
function selectCity(cityName) {
const urlParams = new URLSearchParams(window.location.search);
const fromDashboard = urlParams.get('from') === 'dashboard';
if (user || fromDashboard) {
window.location.href = `/city/${cityName}/dashboard`;
} else {
window.location.href = `/city/${cityName}`;
}
}
function showMessage(message, type = 'success') {
const messageDiv = document.getElementById('message');
messageDiv.innerHTML = `<div class="message ${type}">${message}</div>`;
setTimeout(() => {
messageDiv.innerHTML = '';
}, 5000);
}
document.getElementById('addCityForm').addEventListener('submit', async (e) => {
e.preventDefault();
if (!user) {
showMessage('Please log in to add a city', 'error');
return;
}
const formData = new FormData(e.target);
const displayName = formData.get('display_name');
const data = {
name: displayName.toLowerCase().replace(/\s+/g, '-'),
display_name: displayName
};
try {
const response = await fetch('/api/cities', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
const result = await response.json();
if (response.ok) {
showMessage(`City "${displayName}" added successfully!`);
e.target.reset();
loadCities();
} else {
showMessage(result.error || 'Failed to add city', 'error');
}
} catch (error) {
showMessage('Failed to add city', 'error');
}
});
document.addEventListener('DOMContentLoaded', initPage);
</script>
</body>
</html>