Items 16-22: Icon classification, accessibility, responsive design, API params
- Consolidate 5 weather icon methods into classifyWeatherIcon/applyWeatherIconClasses - Add focus-visible styles, ARIA attributes, keyboard nav on config button/modal - Add responsive breakpoints for departure cards, weather widget, config modal - Simplify CSS selectors: replace :not(:is(...)) chains with body.normal - Fix upsidedown layout margin assumption with transform-based centering - Upgrade weather icons from @2x to @4x for high-DPI displays - Add forecast window and transport filter params to SL departures API Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,11 +8,19 @@ const https = require('https');
|
||||
/**
|
||||
* Fetch departures for a specific site from SL Transport API
|
||||
* @param {string} siteId - The site ID to fetch departures for
|
||||
* @param {Object} options - Query options
|
||||
* @param {number} options.forecast - Time window in minutes (default: 60)
|
||||
* @param {string} options.transport - Transport mode filter (e.g. 'BUS', 'METRO')
|
||||
* @returns {Promise<Object>} - Departure data
|
||||
*/
|
||||
function fetchDeparturesForSite(siteId) {
|
||||
function fetchDeparturesForSite(siteId, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const apiUrl = `https://transport.integration.sl.se/v1/sites/${siteId}/departures`;
|
||||
const params = new URLSearchParams();
|
||||
params.set('forecast', options.forecast || 60);
|
||||
if (options.transport) {
|
||||
params.set('transport', options.transport);
|
||||
}
|
||||
const apiUrl = `https://transport.integration.sl.se/v1/sites/${siteId}/departures?${params}`;
|
||||
console.log(`Fetching data from: ${apiUrl}`);
|
||||
|
||||
https.get(apiUrl, (res) => {
|
||||
@@ -46,15 +54,19 @@ function fetchDeparturesForSite(siteId) {
|
||||
* @param {Array} enabledSites - Array of enabled site configurations
|
||||
* @returns {Promise<Object>} - Object with sites array containing departure data
|
||||
*/
|
||||
async function fetchAllDepartures(enabledSites) {
|
||||
async function fetchAllDepartures(enabledSites, globalOptions = {}) {
|
||||
if (enabledSites.length === 0) {
|
||||
return { sites: [], error: 'No enabled sites configured' };
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const sitesPromises = enabledSites.map(async (site) => {
|
||||
try {
|
||||
const departureData = await fetchDeparturesForSite(site.id);
|
||||
const siteOptions = {
|
||||
forecast: site.forecast || globalOptions.forecast || 60,
|
||||
transport: site.transport || globalOptions.transport || ''
|
||||
};
|
||||
const departureData = await fetchDeparturesForSite(site.id, siteOptions);
|
||||
return {
|
||||
siteId: site.id,
|
||||
siteName: site.name,
|
||||
@@ -87,7 +99,11 @@ async function fetchAllDepartures(enabledSites) {
|
||||
async function handleDepartures(req, res, config) {
|
||||
try {
|
||||
const enabledSites = config.sites.filter(site => site.enabled);
|
||||
const data = await fetchAllDepartures(enabledSites);
|
||||
const globalOptions = {
|
||||
forecast: config.forecast || 60,
|
||||
transport: config.transport || ''
|
||||
};
|
||||
const data = await fetchAllDepartures(enabledSites, globalOptions);
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify(data));
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user