aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/app/routes/settings.tsx
diff options
context:
space:
mode:
authorAriel Costas Guerrero <ariel@costas.dev>2026-03-16 13:56:06 +0100
committerAriel Costas Guerrero <ariel@costas.dev>2026-03-16 13:56:15 +0100
commit8942cf3c705bbc78a6b3317599658e9bb86dd31b (patch)
treec02c432dad7b31fa11160f16c221dfac45255920 /src/frontend/app/routes/settings.tsx
parent3ce586243a49f34b36d0fe4099bbfb2631610f11 (diff)
Add legal document shenanigans
Closes #147
Diffstat (limited to 'src/frontend/app/routes/settings.tsx')
-rw-r--r--src/frontend/app/routes/settings.tsx82
1 files changed, 81 insertions, 1 deletions
diff --git a/src/frontend/app/routes/settings.tsx b/src/frontend/app/routes/settings.tsx
index e7fdffa..0497f34 100644
--- a/src/frontend/app/routes/settings.tsx
+++ b/src/frontend/app/routes/settings.tsx
@@ -1,5 +1,7 @@
-import { Computer, Moon, Sun } from "lucide-react";
+import { Computer, Moon, Sun, Trash2 } from "lucide-react";
+import { useState } from "react";
import { useTranslation } from "react-i18next";
+import { Link } from "react-router";
import { usePageTitle } from "~/contexts/PageTitleContext";
import { useApp, type Theme } from "../AppContext";
import "../tailwind-full.css";
@@ -7,6 +9,8 @@ import "../tailwind-full.css";
export default function Settings() {
const { t, i18n } = useTranslation();
usePageTitle(t("navbar.settings", "Ajustes"));
+ const [showClearConfirm, setShowClearConfirm] = useState(false);
+ const [cleared, setCleared] = useState(false);
const {
theme,
setTheme,
@@ -192,6 +196,82 @@ export default function Settings() {
<option value="en-GB">English</option>
</select>
</section>
+
+ {/* Privacy / Clear data */}
+ <section className="mt-8 pt-8 border-t border-border">
+ <h2 className="text-xl font-semibold mb-4 text-text">
+ {t("settings.privacy_title", "Privacidad y datos")}
+ </h2>
+ {!showClearConfirm && !cleared && (
+ <button
+ onClick={() => setShowClearConfirm(true)}
+ className="flex items-center gap-2 px-4 py-3 rounded-lg border border-border
+ bg-surface text-text hover:bg-red-50 hover:border-red-300 hover:text-red-700
+ dark:hover:bg-red-950 dark:hover:border-red-700 dark:hover:text-red-400
+ transition-colors duration-200 focus:outline-none focus:ring focus:ring-red-300"
+ >
+ <Trash2 className="w-5 h-5" />
+ {t("settings.clear_data", "Borrar mis datos guardados")}
+ </button>
+ )}
+ {showClearConfirm && (
+ <div className="p-4 rounded-lg border border-red-300 bg-red-50 dark:bg-red-950 dark:border-red-700">
+ <p className="text-sm text-text mb-4">
+ {t(
+ "settings.clear_data_confirm",
+ "Se eliminarán tus paradas favoritas, nombres personalizados, paradas recientes, historial de rutas, lugares guardados y posición del mapa. Las preferencias de ajustes se conservarán."
+ )}
+ </p>
+ <div className="flex gap-3">
+ <button
+ onClick={() => {
+ const personalKeys = [
+ "mapState",
+ "specialPlace_home",
+ "specialPlace_work",
+ "recentPlaces",
+ "planner_route_history",
+ `favouriteStops`,
+ `recentStops`,
+ `customStopNames`,
+ `stops_cache`,
+ ];
+ personalKeys.forEach((key) => localStorage.removeItem(key));
+ setShowClearConfirm(false);
+ setCleared(true);
+ }}
+ className="px-4 py-2 rounded-lg bg-red-600 text-white hover:bg-red-700
+ transition-colors duration-200 focus:outline-none focus:ring focus:ring-red-300"
+ >
+ {t("settings.clear_data_confirm_btn", "Sí, borrar datos")}
+ </button>
+ <button
+ onClick={() => setShowClearConfirm(false)}
+ className="px-4 py-2 rounded-lg border border-border bg-surface text-text
+ hover:bg-surface/50 transition-colors duration-200 focus:outline-none focus:ring focus:ring-primary/50"
+ >
+ {t("settings.cancel", "Cancelar")}
+ </button>
+ </div>
+ </div>
+ )}
+ {cleared && (
+ <p className="text-sm text-green-700 dark:text-green-400">
+ {t(
+ "settings.clear_data_done",
+ "Tus datos se han borrado correctamente."
+ )}
+ </p>
+ )}
+ <p className="mt-4 text-sm text-muted">
+ <Link
+ to="/politica-privacidad"
+ className="underline hover:text-text transition-colors"
+ >
+ {t("settings.privacy_policy_link", "Política de privacidad")}
+ </Link>
+ </p>
+ </section>
</div>
);
}