Files
edgar.friendly 003b1e209f
deploy-branch / deploy (push) Failing after 6s
deploy-branch / teardown (push) Skipped
feat(propuesta): pasarela paso a paso con autodetección de ubicación y FAB
- Campo universal de ubicación (Google Maps/Waze/OSM/coordenadas/dirección)
  sobre proveedores extensibles (src/utils/ubicacion) con resolver e inferencia
  inversa Nominatim (nombre/provincia pre-rellenados, alias cooficiales)
- FAB flotante abajo a la derecha que abre la pasarela en un modal accesible
  (Escape, foco contenido, responsive); sin descripción ni puntuación;
  avisos de duplicado y filtro de palabras dentro del modal
- Aviso PWA reposicionado: tarjeta abajo a la izquierda en móvil,
  botón compacto arriba a la izquierda en PC (no tapa el FAB)
- Suite de pruebas: 88 unitarias/componente (vitest + RTL, offline) y
  10 de integración (supertest + SQLite :memory: y Nominatim real opt-in)
- CI: workflow de Gitea Actions con npm test + build en push/PR e
  integración manual
2026-08-16 01:35:02 +02:00

90 lines
2.7 KiB
JavaScript

import Database from "better-sqlite3";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
const __dirname = dirname(fileURLToPath(import.meta.url));
// Ruta de la BD sobreescribible para pruebas (admite ":memory:"); en
// producción se usa el archivo del repo.
const dbPath = process.env.LOCALESP_DB || join(__dirname, "../localesp.db");
const db = new Database(dbPath);
db.exec(`
CREATE TABLE IF NOT EXISTS locales (
id TEXT PRIMARY KEY,
nombre TEXT NOT NULL,
descripcion TEXT,
provincia TEXT,
subcategoria TEXT,
direccion TEXT,
enlaceGoogleMaps TEXT,
puntuacion INTEGER DEFAULT 0,
categoria TEXT,
fecha TEXT DEFAULT CURRENT_TIMESTAMP,
lat REAL,
lng REAL
);
CREATE TABLE IF NOT EXISTS pendientes (
id TEXT PRIMARY KEY,
nombre TEXT NOT NULL,
descripcion TEXT,
provincia TEXT,
subcategoria TEXT,
direccion TEXT,
enlaceGoogleMaps TEXT,
puntuacion INTEGER DEFAULT 0,
categoria TEXT,
estado TEXT DEFAULT 'pendiente',
fechaPropuesta TEXT DEFAULT CURRENT_TIMESTAMP,
lat REAL,
lng REAL
);
CREATE TABLE IF NOT EXISTS config (
id TEXT PRIMARY KEY,
datos TEXT
);
CREATE TABLE IF NOT EXISTS reportes (
id TEXT PRIMARY KEY,
localId TEXT NOT NULL,
motivo TEXT,
comentario TEXT,
fecha TEXT DEFAULT CURRENT_TIMESTAMP,
estado TEXT DEFAULT 'pendiente'
);
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
created TEXT DEFAULT CURRENT_TIMESTAMP
);
`);
// Migración suave: si la base de datos ya existía con el esquema antiguo
// (sin provincia/subcategoria/direccion/enlaceGoogleMaps/puntuacion),
// añadimos las columnas que falten sin borrar nada, porque
// CREATE TABLE IF NOT EXISTS no modifica tablas ya creadas.
function ensureColumn(table, column, definition) {
const cols = db.prepare(`PRAGMA table_info(${table})`).all().map(c => c.name);
if (!cols.includes(column)) {
db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
}
}
for (const table of ["locales", "pendientes"]) {
ensureColumn(table, "provincia", "TEXT");
ensureColumn(table, "subcategoria", "TEXT");
ensureColumn(table, "direccion", "TEXT");
ensureColumn(table, "enlaceGoogleMaps", "TEXT");
ensureColumn(table, "puntuacion", "INTEGER DEFAULT 0");
}
// fechaConfirmacion: última vez que alguien confirmó que el local sigue activo.
// Al aprobarse por primera vez se inicializa igual a "fecha"; luego se actualiza
// con /api/locales/:id/confirmar cada vez que un usuario pulsa "Sigue aquí".
ensureColumn("locales", "fechaConfirmacion", "TEXT");
db.prepare("UPDATE locales SET fechaConfirmacion = fecha WHERE fechaConfirmacion IS NULL").run();
export default db;