From 5d6fd75899e96826f8e8aa0c84f7f186cbc7e471 Mon Sep 17 00:00:00 2001 From: Ariel Costas Guerrero Date: Wed, 22 Oct 2025 00:06:52 +0200 Subject: Confirm region change, make app name more consistent --- src/frontend/app/AppContext.tsx | 14 ++---- src/frontend/app/i18n/locales/en-GB.json | 4 +- src/frontend/app/i18n/locales/es-ES.json | 2 +- src/frontend/app/i18n/locales/gl-ES.json | 2 +- src/frontend/app/root.tsx | 14 +++--- src/frontend/app/routes/settings.css | 83 ++++++++++++++++++++++++++++++++ src/frontend/app/routes/settings.tsx | 72 +++++++++++++++++++++++++-- src/frontend/app/routes/stoplist.tsx | 3 +- 8 files changed, 168 insertions(+), 26 deletions(-) (limited to 'src/frontend/app') diff --git a/src/frontend/app/AppContext.tsx b/src/frontend/app/AppContext.tsx index 1a9b511..8f47a49 100644 --- a/src/frontend/app/AppContext.tsx +++ b/src/frontend/app/AppContext.tsx @@ -7,7 +7,7 @@ import { type ReactNode, } from "react"; import { type LngLatLike } from "maplibre-gl"; -import { type RegionId, DEFAULT_REGION, getRegionConfig, isValidRegion } from "./data/RegionConfig"; +import { type RegionId, DEFAULT_REGION, getRegionConfig, isValidRegion, REGIONS } from "./data/RegionConfig"; export type Theme = "light" | "dark" | "system"; type TableStyle = "regular" | "grouped"; @@ -43,10 +43,6 @@ interface AppContextProps { setRegion: (region: RegionId) => void; } -// Coordenadas por defecto centradas en Vigo -const DEFAULT_CENTER: LngLatLike = [42.229188855975046, -8.72246955783102]; -const DEFAULT_ZOOM = 14; - const AppContext = createContext(undefined); export const AppProvider = ({ children }: { children: ReactNode }) => { @@ -187,8 +183,8 @@ export const AppProvider = ({ children }: { children: ReactNode }) => { try { const parsed = JSON.parse(savedMapState); return { - center: parsed.center || DEFAULT_CENTER, - zoom: parsed.zoom || DEFAULT_ZOOM, + center: parsed.center || REGIONS[region].defaultCenter, + zoom: parsed.zoom || REGIONS[region].defaultZoom, userLocation: parsed.userLocation || null, hasLocationPermission: parsed.hasLocationPermission || false, }; @@ -197,8 +193,8 @@ export const AppProvider = ({ children }: { children: ReactNode }) => { } } return { - center: DEFAULT_CENTER, - zoom: DEFAULT_ZOOM, + center: REGIONS[region].defaultCenter, + zoom: REGIONS[region].defaultZoom, userLocation: null, hasLocationPermission: false, }; diff --git a/src/frontend/app/i18n/locales/en-GB.json b/src/frontend/app/i18n/locales/en-GB.json index 4d0c91b..12c8121 100644 --- a/src/frontend/app/i18n/locales/en-GB.json +++ b/src/frontend/app/i18n/locales/en-GB.json @@ -1,7 +1,7 @@ { "about": { - "title": "About UrbanoVigo Web", - "description": "Web app to find stops and arrival times for Vigo's urban buses, Spain.", + "title": "About BusUrbano", + "description": "Web app to find stops and arrival times for urban buses, Spain.", "credits": "Credits", "github": "Code on GitHub", "developed_by": "Developed by", diff --git a/src/frontend/app/i18n/locales/es-ES.json b/src/frontend/app/i18n/locales/es-ES.json index 0915361..e929382 100644 --- a/src/frontend/app/i18n/locales/es-ES.json +++ b/src/frontend/app/i18n/locales/es-ES.json @@ -1,6 +1,6 @@ { "about": { - "title": "Sobre UrbanoVigo Web", + "title": "Sobre BusUrbano", "description": "Aplicación web para encontrar paradas y tiempos de llegada de los autobuses urbanos de Vigo, España.", "credits": "Créditos", "github": "Código en GitHub", diff --git a/src/frontend/app/i18n/locales/gl-ES.json b/src/frontend/app/i18n/locales/gl-ES.json index 8949333..ed1ef53 100644 --- a/src/frontend/app/i18n/locales/gl-ES.json +++ b/src/frontend/app/i18n/locales/gl-ES.json @@ -1,6 +1,6 @@ { "about": { - "title": "Sobre UrbanoVigo Web", + "title": "Sobre BusUrbano", "description": "Aplicación web para atopar paradas e tempos de chegada dos autobuses urbanos de Vigo, España.", "credits": "Créditos", "github": "Código en GitHub", diff --git a/src/frontend/app/root.tsx b/src/frontend/app/root.tsx index 25a873f..4815d2f 100644 --- a/src/frontend/app/root.tsx +++ b/src/frontend/app/root.tsx @@ -45,28 +45,28 @@ export function Layout({ children }: { children: React.ReactNode }) { - + - + - + diff --git a/src/frontend/app/routes/settings.css b/src/frontend/app/routes/settings.css index ef9fbd5..c08ed68 100644 --- a/src/frontend/app/routes/settings.css +++ b/src/frontend/app/routes/settings.css @@ -183,6 +183,76 @@ to { transform: rotate(360deg); } } +/* Modal styles */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + padding: 1rem; +} + +.modal-content { + background-color: var(--message-background-color); + padding: 2rem; + border-radius: 12px; + max-width: 500px; + width: 100%; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); +} + +.modal-content h2 { + margin-top: 0; + margin-bottom: 1rem; + color: var(--text-color); +} + +.modal-content p { + margin-bottom: 1.5rem; + line-height: 1.6; + color: var(--text-color); +} + +.modal-buttons { + display: flex; + gap: 1rem; + justify-content: flex-end; +} + +.modal-button { + padding: 0.75rem 1.5rem; + border: none; + border-radius: 8px; + font-size: 1rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.modal-button-cancel { + background-color: #6c757d; + color: white; +} + +.modal-button-cancel:hover { + background-color: #5a6268; +} + +.modal-button-confirm { + background-color: var(--button-background-color); + color: white; +} + +.modal-button-confirm:hover { + background-color: var(--button-hover-background-color); +} + @media (max-width: 768px) { .update-controls { flex-direction: column; @@ -192,4 +262,17 @@ .clear-cache-button { justify-content: center; } + + .modal-content { + padding: 1.5rem; + } + + .modal-buttons { + flex-direction: column; + gap: 0.5rem; + } + + .modal-button { + width: 100%; + } } diff --git a/src/frontend/app/routes/settings.tsx b/src/frontend/app/routes/settings.tsx index eae6ad8..cb64f4e 100644 --- a/src/frontend/app/routes/settings.tsx +++ b/src/frontend/app/routes/settings.tsx @@ -2,10 +2,12 @@ import { type Theme, useApp } from "../AppContext"; import "./settings.css"; import { useTranslation } from "react-i18next"; import { useState } from "react"; -import { getAvailableRegions } from "../data/RegionConfig"; +import { getAvailableRegions, REGIONS } from "../data/RegionConfig"; +import { useNavigate } from "react-router"; export default function Settings() { const { t, i18n } = useTranslation(); + const navigate = useNavigate(); const { theme, setTheme, @@ -18,6 +20,29 @@ export default function Settings() { } = useApp(); const regions = getAvailableRegions(); + const [showModal, setShowModal] = useState(false); + const [pendingRegion, setPendingRegion] = useState(null); + + const handleRegionChange = (newRegion: string) => { + if (newRegion !== region) { + setPendingRegion(newRegion); + setShowModal(true); + } + }; + + const confirmRegionChange = () => { + if (pendingRegion) { + setRegion(pendingRegion as any); + setShowModal(false); + setPendingRegion(null); + navigate("/stops"); + } + }; + + const cancelRegionChange = () => { + setShowModal(false); + setPendingRegion(null); + }; return (
@@ -33,7 +58,7 @@ export default function Settings() { id="region" className="form-select-inline" value={region} - onChange={(e) => setRegion(e.target.value as any)} + onChange={(e) => handleRegionChange(e.target.value)} > {regions.map((r) => (
); } diff --git a/src/frontend/app/routes/stoplist.tsx b/src/frontend/app/routes/stoplist.tsx index 13d3584..71b7d3c 100644 --- a/src/frontend/app/routes/stoplist.tsx +++ b/src/frontend/app/routes/stoplist.tsx @@ -6,6 +6,7 @@ import Fuse from "fuse.js"; import "./stoplist.css"; import { useTranslation } from "react-i18next"; import { useApp } from "../AppContext"; +import { REGIONS } from "~/data/RegionConfig"; export default function StopList() { const { t } = useTranslation(); @@ -100,7 +101,7 @@ export default function StopList() { return (
-

UrbanoVigo Web

+

BusUrbano - {REGIONS[region].name}

-- cgit v1.3