e159e8d297
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)
30 lines
956 B
Docker
30 lines
956 B
Docker
# syntax=docker/dockerfile:1
|
|
FROM node:22-alpine AS deps
|
|
WORKDIR /app
|
|
COPY package.json package-lock.json ./
|
|
RUN npm ci
|
|
|
|
FROM node:22-alpine AS build
|
|
WORKDIR /app
|
|
ARG PUBLIC_SUPABASE_URL
|
|
ARG PUBLIC_SUPABASE_ANON_KEY
|
|
ARG PUBLIC_APP_URL
|
|
ENV PUBLIC_SUPABASE_URL=$PUBLIC_SUPABASE_URL \
|
|
PUBLIC_SUPABASE_ANON_KEY=$PUBLIC_SUPABASE_ANON_KEY \
|
|
PUBLIC_APP_URL=$PUBLIC_APP_URL
|
|
COPY --from=deps /app/node_modules ./node_modules
|
|
COPY . .
|
|
RUN npm run build
|
|
|
|
FROM node:22-alpine AS runtime
|
|
WORKDIR /app
|
|
ENV NODE_ENV=production HOST=0.0.0.0 PORT=4321
|
|
COPY package.json package-lock.json ./
|
|
RUN npm ci --omit=dev --ignore-scripts && npm cache clean --force
|
|
COPY --from=build /app/dist ./dist
|
|
USER node
|
|
EXPOSE 4321
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
|
CMD node -e "require('http').get('http://127.0.0.1:4321/login',r=>process.exit(r.statusCode>=500?1:0)).on('error',()=>process.exit(1))"
|
|
CMD ["node", "./dist/server/entry.mjs"]
|