Multi-tenant scheduling SaaS (AgendaPro-equivalent): - Backend: Node + Express + node:sqlite, multi-tenant (admin/owner/employee), versioned migrations, 4 templates (estetica-spa, barberia, clinica, blank). - Frontend: React 18 + TS + Vite + Tailwind, FullCalendar drag-and-drop, Recharts dashboard, mobile-first (day/list views on mobile). - Features: calendar+services+employees+clients+tickets, dashboard with best employee/service, top tickets, top/frequent clients, commissions, cancellation policy + no-show tracking, public online booking (/b/:slug), cash register (cierre de caja), reminders/notifications center. - Verification: 65/65 e2e API, 58/58 visual (0 overflow, 0 console errors), typecheck clean, vite build OK.
33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
import { Router } from "express";
|
|
import { db } from "../db.ts";
|
|
import { authRequired, type AuthedRequest } from "../lib/auth.ts";
|
|
|
|
export const authRouter = Router();
|
|
|
|
authRouter.post("/login", (req, res) => {
|
|
const { email, password } = req.body ?? {};
|
|
if (!email || !password) return res.status(400).json({ error: "Faltan credenciales" });
|
|
const user = db
|
|
.prepare(`SELECT id, business_id, email, name, role, employee_id, avatar_color, password FROM users WHERE email = ?`)
|
|
.get(String(email).toLowerCase().trim()) as any;
|
|
if (!user || user.password !== password) {
|
|
return res.status(401).json({ error: "Correo o contraseña incorrectos" });
|
|
}
|
|
const { password: _pw, ...safe } = user;
|
|
res.json({ token: String(user.id), user: safe });
|
|
});
|
|
|
|
authRouter.get("/me", authRequired, (req: AuthedRequest, res) => {
|
|
res.json({ user: req.user });
|
|
});
|
|
|
|
authRouter.get("/demo-users", (_req, res) => {
|
|
const users = db
|
|
.prepare(
|
|
`SELECT email, name, role, avatar_color FROM users
|
|
ORDER BY CASE role WHEN 'admin' THEN 0 WHEN 'owner' THEN 1 ELSE 2 END, name`
|
|
)
|
|
.all();
|
|
res.json({ users });
|
|
});
|