feat: implement multi-city support with city management features

- Added a new cities table to the database to manage multiple cities independently.
- Created a middleware to resolve city context based on X-City-Id header.
- Updated routes and services to handle city-specific data for routes, stops, and alerts.
- Implemented a CityContext in the frontend to manage active city state and provide city data across the application.
- Added a CitySelector component for users to switch between cities.
- Created a CitiesPage for admins to manage cities, including adding new cities with validation.
- Updated various components and pages to reflect the active city context, ensuring data is displayed correctly based on the selected city.
- Enhanced the schedule import functionality to restrict imports based on the active city.
This commit is contained in:
2026-09-17 19:41:17 +03:00
parent d284c6e940
commit d13cc92d82
27 changed files with 730 additions and 144 deletions

View File

@@ -2,8 +2,8 @@ const crypto = require('node:crypto');
const INSERT_ALERT_SQL = `
WITH inserted AS (
INSERT INTO alerts (route_id, alert_type, title, message, start_time, end_time, is_active)
VALUES ($1, $2, $3, $4, $5, $6, $7)
INSERT INTO alerts (route_id, alert_type, title, message, start_time, end_time, is_active, city_id)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING *
)
SELECT inserted.*, routes.route_number AS notification_route_number
@@ -43,7 +43,8 @@ function normalizeAlertInput(payload) {
message: payload.message,
start_time: payload.start_time,
end_time: payload.end_time || null,
is_active: payload.is_active !== false
is_active: payload.is_active !== false,
city_id: payload.city_id || null
};
}
@@ -63,7 +64,8 @@ function createAlertRequestHash(alert) {
message: normalizeHashValue(alert.message),
start_time: normalizeHashValue(alert.start_time),
end_time: normalizeHashValue(alert.end_time),
is_active: normalizeHashValue(alert.is_active)
is_active: normalizeHashValue(alert.is_active),
city_id: normalizeHashValue(alert.city_id)
};
return crypto
@@ -146,7 +148,8 @@ class AlertCreationService {
alertInput.message,
alertInput.start_time,
alertInput.end_time,
alertInput.is_active
alertInput.is_active,
alertInput.city_id
]);
const row = result.rows[0];