postgres DAL + New UI

This commit is contained in:
2025-12-01 23:00:34 -07:00
parent eeb63fa510
commit 75581a9ddc
2 changed files with 6 additions and 39 deletions

View File

@@ -1,6 +1,4 @@
// ------------------------------
// MAP SETUP
// ------------------------------
var streets = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { var streets = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors' attribution: '© OpenStreetMap contributors'
}); });
@@ -23,10 +21,6 @@ const MJR_LINES = ["701", "703", "704", "720", "750"];
const LRT_LINES = ["701", "703", "704", "720"]; const LRT_LINES = ["701", "703", "704", "720"];
const FRONTRUNNER = ["750"]; const FRONTRUNNER = ["750"];
const API_URL = "http://localhost:7653/api/v0/"; const API_URL = "http://localhost:7653/api/v0/";
// ------------------------------
// ROUTE STYLES
// ------------------------------
const ROUTE_STYLES = { const ROUTE_STYLES = {
"701": { color: "#0074D9", train: "🔵", stop: "🔹" }, "701": { color: "#0074D9", train: "🔵", stop: "🔹" },
"704": { color: "#2ECC40", train: "🟢", stop: "🟩" }, "704": { color: "#2ECC40", train: "🟢", stop: "🟩" },
@@ -35,11 +29,8 @@ const ROUTE_STYLES = {
"720": { color: "#000000", train: "⚪", stop: "🔷" } "720": { color: "#000000", train: "⚪", stop: "🔷" }
}; };
// ------------------------------
// ICON BUILDER
// ------------------------------
function buildIcon(emoji, bearing) { function buildIcon(emoji, bearing) {
const rotate = bearing ? `transform: rotate(${bearing}deg); transform-origin: center;` : '';
const svg = ` const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
<text x="50%" y="50%" text-anchor="middle" <text x="50%" y="50%" text-anchor="middle"
@@ -59,9 +50,6 @@ function buildIcon(emoji, bearing) {
}); });
} }
// ------------------------------
// MARKER HELPER
// ------------------------------
function addMarker(lat, lon, content, icon) { function addMarker(lat, lon, content, icon) {
if (!isNaN(lat) && !isNaN(lon)) { if (!isNaN(lat) && !isNaN(lon)) {
const marker = L.marker([lat, lon], { icon }); const marker = L.marker([lat, lon], { icon });
@@ -71,9 +59,7 @@ function addMarker(lat, lon, content, icon) {
console.warn("Invalid coordinates:", lat, lon); console.warn("Invalid coordinates:", lat, lon);
} }
// ------------------------------
// ROUTE LINES
// ------------------------------
function drawPolyLine(polylinePoints, color) { function drawPolyLine(polylinePoints, color) {
L.polyline(polylinePoints, { color, weight: 4, opacity: 0.8 }).addTo(map); L.polyline(polylinePoints, { color, weight: 4, opacity: 0.8 }).addTo(map);
} }
@@ -108,9 +94,7 @@ function drawLines() {
MJR_LINES.forEach(drawLine); MJR_LINES.forEach(drawLine);
} }
// ------------------------------
// STOPS
// ------------------------------
let stopMarkers = {}; let stopMarkers = {};
function getStopsByRoute(route) { function getStopsByRoute(route) {
if (stopMarkers[route]) return; if (stopMarkers[route]) return;
@@ -134,9 +118,6 @@ function getStopsByRoute(route) {
.catch(err => console.error("Error fetching stops:", err)); .catch(err => console.error("Error fetching stops:", err));
} }
// ------------------------------
// VEHICLES
// ------------------------------
let trainMarkers = {}; let trainMarkers = {};
let filterType = "all"; let filterType = "all";
@@ -153,14 +134,12 @@ function refreshVehicles() {
.then(data => { .then(data => {
let vehicles = data.data; let vehicles = data.data;
// Apply filter
if (filterType === "lrt") { if (filterType === "lrt") {
vehicles = vehicles.filter(v => LRT_LINES.includes(v.routeNum) || FRONTRUNNER.includes(v.routeNum)); vehicles = vehicles.filter(v => LRT_LINES.includes(v.routeNum) || FRONTRUNNER.includes(v.routeNum));
} }
vehicles = vehicles.filter(v => MJR_LINES.includes(v.routeNum)); vehicles = vehicles.filter(v => MJR_LINES.includes(v.routeNum));
// Remove vehicles no longer active
Object.keys(trainMarkers).forEach(id => { Object.keys(trainMarkers).forEach(id => {
if (!vehicles.find(v => v.vehicleId == id)) { if (!vehicles.find(v => v.vehicleId == id)) {
map.removeLayer(trainMarkers[id]); map.removeLayer(trainMarkers[id]);
@@ -194,9 +173,7 @@ function refreshVehicles() {
.catch(err => console.error("Error refreshing vehicles:", err)); .catch(err => console.error("Error refreshing vehicles:", err));
} }
// ------------------------------
// USER LOCATION & TRAIN DETECTION
// ------------------------------
let userMarker, accuracyCircle; let userMarker, accuracyCircle;
const ON_BOARD_RADIUS = 50; // meters const ON_BOARD_RADIUS = 50; // meters
@@ -237,7 +214,6 @@ if (navigator.geolocation) {
if (userMarker) userMarker.setLatLng([userLat, userLon]); if (userMarker) userMarker.setLatLng([userLat, userLon]);
if (accuracyCircle) accuracyCircle.setLatLng([userLat, userLon]).setRadius(position.coords.accuracy); if (accuracyCircle) accuracyCircle.setLatLng([userLat, userLon]).setRadius(position.coords.accuracy);
// Detect if user is on a train
const vehicles = Object.values(trainMarkers).map(m => m.vehicleData); const vehicles = Object.values(trainMarkers).map(m => m.vehicleData);
let closest = null, minDistance = Infinity; let closest = null, minDistance = Infinity;
@@ -260,9 +236,6 @@ if (navigator.geolocation) {
console.warn("Geolocation not supported by this browser."); console.warn("Geolocation not supported by this browser.");
} }
// ------------------------------
// INITIAL LOAD
// ------------------------------
drawLines(); drawLines();
MJR_LINES.forEach(r => getStopsByRoute(r)); MJR_LINES.forEach(r => getStopsByRoute(r));
refreshVehicles(); refreshVehicles();

View File

@@ -1,4 +1,3 @@
// src/dal/postgresdal.js
import pg from "pg"; import pg from "pg";
const pool = new pg.Pool({ const pool = new pg.Pool({
@@ -20,7 +19,6 @@ function toNumber(v) {
return Number.isFinite(n) ? n : undefined; return Number.isFinite(n) ? n : undefined;
} }
/* Vehicles */
export async function getVehicles() { export async function getVehicles() {
const rows = await dbQuery( const rows = await dbQuery(
@@ -71,7 +69,6 @@ export async function getVehicleById(id) {
}; };
} }
/* Routes */
export async function getRoutes() { export async function getRoutes() {
const rows = await dbQuery(`SELECT data FROM routes ORDER BY route_id`); const rows = await dbQuery(`SELECT data FROM routes ORDER BY route_id`);
@@ -89,7 +86,6 @@ export async function getRouteById(routeId) {
return rows[0]?.data || null; return rows[0]?.data || null;
} }
/* Route paths */
export async function getRoutePathsMap() { export async function getRoutePathsMap() {
const rows = await dbQuery(`SELECT route_id, path FROM route_paths`); const rows = await dbQuery(`SELECT route_id, path FROM route_paths`);
@@ -111,7 +107,6 @@ export async function getRoutePath(routeId) {
return rows[0]?.path || null; return rows[0]?.path || null;
} }
/* Stations */
function transformationStationRow(row) { function transformationStationRow(row) {
return { return {
@@ -131,7 +126,6 @@ function transformationStationRow(row) {
} }
export async function getStationsRaw() { export async function getStationsRaw() {
// For compatibility, just return the full array of normalized station rows.
const rows = await dbQuery(`SELECT * FROM stations`); const rows = await dbQuery(`SELECT * FROM stations`);
return rows; return rows;
} }
@@ -143,7 +137,6 @@ export async function getStations() {
export async function getStopsByRoute(routeId) { export async function getStopsByRoute(routeId) {
if (routeId == null) return []; if (routeId == null) return [];
// lines @> ARRAY[$1]::text[] means: lines contains this value
const rows = await dbQuery( const rows = await dbQuery(
`SELECT * FROM stations WHERE lines @> ARRAY[$1]::text[]`, `SELECT * FROM stations WHERE lines @> ARRAY[$1]::text[]`,
[String(routeId)] [String(routeId)]
@@ -163,3 +156,4 @@ export async function getStationById(id) {
return transformationStationRow(rows[0]); return transformationStationRow(rows[0]);
} }