Files
labre-web/src/lib/supabase.ts
T
LakG e159e8d297 Perfil + onboarding + home reformulado + fixes
Perfil de usuario:
- /perfil con avatar, matrícula, semestre, tutor, foto de perfil
- /onboarding opcional (skippeable) para primer login
- Avatar con prioridad: foto propia > Google OAuth > iniciales sobre color HSL
- Endpoint PATCH /api/profile con validación y guard self-only
- Middleware carga semestre, tutor_id, foto_path
- Sidebar footer con Avatar + link a perfil

CRUD admin de maestros:
- /admin/maestros con tabla desktop / cards mobile
- MaestroForm + EliminarMaestro (mismo patrón que categorias)
- Endpoints POST/PATCH/DELETE con guard admin + 23503 traducido
- Subnav de inventario ahora incluye tab Maestros

Home reformulado:
- Alumno: saludo por hora + CTA "¿Qué vas a pedir hoy?" + card de último préstamo activo
- Admin: saludo + 2 KPIs de alerta (Pendientes, Vencidos) + últimas 2 pendientes + actividad reciente (tabla desktop, cards mobile — fix del bug 6)
- Helper saludoHora() y fmtFechaRelativa() en date.ts con offset MX

Checkout con tutor auto:
- SolicitudCart: input maestro → textarea con placeholder = nombre del tutor
- Guard perfil incompleto: CTA "Completa tu perfil" si !matricula || !tutor_id
- RPC crear_solicitud: fallback automático al nombre del tutor si textarea vacío

Fixes:
- Bug upload imagen: Dockerfile ARG + docker-compose build.args pasan PUBLIC_* al bundle client de Vite
- Grid inventario mobile: acciones en grid 2-col con prop compact en botones
- UnidadesManager mobile: tabla reemplazada por cards, select estado con min-width 130px
- Chart donut: Legend horizontal debajo (sin labels internos cortadas)
- Chart barras: YAxis width fijo 100 + tickFormatter que trunca >14 chars
- Panel admin mobile: tabla ahora tiene versión cards mobile (parte del rediseño home)
2026-08-24 08:46:39 -07:00

51 lines
1.6 KiB
TypeScript

import { createServerClient, createBrowserClient, type CookieOptionsWithName } from '@supabase/ssr';
import { createClient } from '@supabase/supabase-js';
import type { AstroCookies } from 'astro';
const SCHEMA = 'prestamos';
const SUPABASE_URL = process.env.PUBLIC_SUPABASE_URL ?? import.meta.env.PUBLIC_SUPABASE_URL;
const SUPABASE_ANON_KEY = process.env.PUBLIC_SUPABASE_ANON_KEY ?? import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
const SUPABASE_SERVICE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY ?? import.meta.env.SUPABASE_SERVICE_ROLE_KEY;
// ponytail: solo para preview local sin login. Bypass RLS con service_role.
// Su uso queda tras un flag de DEV en el middleware.
export function serviceClient() {
return createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY, {
db: { schema: SCHEMA },
auth: { persistSession: false, autoRefreshToken: false },
});
}
const cookieOptions: CookieOptionsWithName = {
name: 'sb',
path: '/',
sameSite: 'lax',
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
};
export function serverClient(cookies: AstroCookies) {
return createServerClient(
SUPABASE_URL,
SUPABASE_ANON_KEY,
{
db: { schema: SCHEMA },
cookieOptions,
cookies: {
get: (name) => cookies.get(name)?.value,
set: (name, value, options) => cookies.set(name, value, options),
remove: (name, options) => cookies.delete(name, options),
},
},
);
}
export function browserClient() {
return createBrowserClient(
SUPABASE_URL,
SUPABASE_ANON_KEY,
{ db: { schema: SCHEMA }, cookieOptions },
);
}