aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/app/routes
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/app/routes')
-rw-r--r--src/frontend/app/routes/settings.css83
-rw-r--r--src/frontend/app/routes/settings.tsx72
-rw-r--r--src/frontend/app/routes/stoplist.tsx3
3 files changed, 152 insertions, 6 deletions
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<string | null>(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 (
<div className="page-container">
@@ -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) => (
<option key={r.id} value={r.id}>
@@ -118,13 +143,13 @@ export default function Settings() {
<h2>{t("about.credits")}</h2>
<p>
<a
- href="https://github.com/arielcostas/urbanovigo-web"
+ href="https://github.com/arielcostas/busurbano"
className="about-link"
rel="nofollow noreferrer noopener"
>
{t("about.github")}
</a>{" "}
- -{t("about.developed_by")}{" "}
+ - {t("about.developed_by")}{" "}
<a
href="https://www.costas.dev"
className="about-link"
@@ -133,6 +158,7 @@ export default function Settings() {
Ariel Costas
</a>
</p>
+ {region === "vigo" && (
<p>
{t("about.data_source_prefix")}{" "}
<a
@@ -149,8 +175,44 @@ export default function Settings() {
rel="nofollow noreferrer noopener"
>
Open Data Commons Attribution License
- </a>
+ </a>.
</p>
+ )}
+ {region === "santiago" && (
+ <p>
+ Datos obtenidos de app MaisBus (Concello de Santiago/TUSSA),
+ gracias a la documentación de [TP Galicia](https://tpgalicia.github.io/urban/santiago/)
+ en GitHub.
+ </p>
+ )}
+
+ {showModal && (
+ <div className="modal-overlay" onClick={cancelRegionChange}>
+ <div className="modal-content" onClick={(e) => e.stopPropagation()}>
+ <h2>{t("about.region_change_title", "Cambiar región")}</h2>
+ <p>
+ {t(
+ "about.region_change_message",
+ "¿Estás seguro de que quieres cambiar la región? Serás redirigido a la lista de paradas."
+ )}
+ </p>
+ <div className="modal-buttons">
+ <button
+ className="modal-button modal-button-cancel"
+ onClick={cancelRegionChange}
+ >
+ {t("about.cancel", "Cancelar")}
+ </button>
+ <button
+ className="modal-button modal-button-confirm"
+ onClick={confirmRegionChange}
+ >
+ {t("about.confirm", "Confirmar")}
+ </button>
+ </div>
+ </div>
+ </div>
+ )}
</div>
);
}
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 (
<div className="page-container stoplist-page">
- <h1 className="page-title">UrbanoVigo Web</h1>
+ <h1 className="page-title">BusUrbano - {REGIONS[region].name}</h1>
<form className="search-form">
<div className="form-group">