Sistema de préstamos LabRe UABC — implementación inicial

Sistema web para gestión de préstamos de material del Laboratorio de
Sistemas Computacionales de la UABC.

- Backend: Supabase self-hosted, schema aislado `prestamos` con RLS,
  triggers de stock y audit log (supabase/migrations/0001_init.sql).
- Auth: Google OAuth restringido a @uabc.edu.mx, verificado en
  middleware y como segunda línea en trigger de DB.
- Frontend: Astro 7 (SSR con adapter Node) + React islands + Tailwind
  v4 con paleta UABC (primary #00723F, secondary #DD971A) bajo regla
  60/30/10.
- Interfaz alumno mobile-first: catálogo con filtro por categorías,
  solicitud de préstamos, historial personal.
- Interfaz admin desktop-first: panel con KPIs, bandeja de solicitudes
  (aprobar/rechazar/devolver), CRUD de inventario y categorías,
  reportes filtrables con export CSV nativo.
- Modales con `<dialog>` nativo, cero librerías de UI adicionales.
- Deploy: Dockerfile multi-stage node:22-alpine + docker-compose para
  publicar bajo prestamos.buglabs.dev vía Cloudflare Tunnel.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-08-14 19:37:49 -07:00
parent 6bbd6d3a6b
commit 1121ab7199
58 changed files with 6281 additions and 252 deletions
+77
View File
@@ -0,0 +1,77 @@
@import "tailwindcss";
@import "@fontsource-variable/inter";
@theme {
--color-primary: #00723F;
--color-primary-hover: #005f34;
--color-secondary: #DD971A;
--color-secondary-hover: #c78614;
--color-surface: #F4F7F5;
--color-ink: #2D3748;
--color-danger: #C53030;
--font-sans: "Inter Variable", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
--radius-card: 0.5rem;
}
@layer base {
html {
color-scheme: light;
}
body {
background: var(--color-surface);
color: var(--color-ink);
font-family: var(--font-sans);
-webkit-font-smoothing: antialiased;
}
:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
}
@layer components {
.btn {
@apply inline-flex items-center justify-center gap-2 rounded-lg px-4 py-2.5 font-medium
transition-[filter,background-color,color,border-color] duration-150 ease-out
motion-safe:hover:brightness-110
focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--color-primary)]
disabled:opacity-50 disabled:pointer-events-none;
min-height: 44px;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
.btn-primary {
background: var(--color-primary);
color: white;
}
.btn-secondary {
background: var(--color-secondary);
color: white;
}
.btn-ghost {
background: transparent;
color: var(--color-ink);
border: 1px solid color-mix(in oklab, var(--color-ink) 15%, transparent);
}
.card {
@apply rounded-lg bg-white p-6;
border: 1px solid color-mix(in oklab, var(--color-ink) 10%, transparent);
}
.input {
@apply w-full rounded-lg bg-white px-3 py-2.5
transition-[border-color,box-shadow] duration-150
focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2
focus-visible:outline-[color:var(--color-primary)];
border: 1px solid color-mix(in oklab, var(--color-ink) 20%, transparent);
min-height: 44px;
touch-action: manipulation;
}
.label {
@apply block text-sm font-medium mb-1;
color: color-mix(in oklab, var(--color-ink) 90%, transparent);
}
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }
}