Skip to main content
Estas acciones gestionan los dos tipos de entidades principales del sistema: los estudiantes que completan el cuestionario SENA, y los usuarios del staff (psicólogos, orientadores, directores y administradores) que operan la plataforma.

Acciones de estudiantes

registrarEstudiante

export async function registrarEstudiante(
  _prev: RegistrarEstudianteResult,
  formData: FormData
): Promise<RegistrarEstudianteResult>
Registra un nuevo estudiante en la base de datos. Diseñada para usarse con useActionState de React en el formulario de registro. Tras un registro exitoso, redirige a /estudiantes/{id}?nuevo=1 e invalida la caché de /estudiantes.

Campos del FormData

CampoTipoValidación
nombrestringMínimo 3 caracteres
curpstringFormato CURP mexicano (18 caracteres, regex estricto)
fechaNacstringFecha ISO — usada para calcular la edad automáticamente
sexostringMASCULINO, FEMENINO o OTRO
gradostringGrado escolar
grupostringGrupo (se convierte a mayúsculas, ej. A, B)
escuelastringNombre del plantel
La edad se calcula automáticamente a partir de fechaNac. No se recibe como campo independiente.

Retorno

export type RegistrarEstudianteResult = {
  error?: string
  fieldErrors?: Record<string, string>
} | undefined
  • undefined — éxito (la función llama a redirect() antes de retornar)
  • { fieldErrors } — errores de validación por campo
  • { error } — error genérico de base de datos

Errores comunes

CampoMensaje
nombre"Ingresa el nombre completo"
curp"CURP inválida — verifica el formato (18 caracteres)"
curp"Ya existe un estudiante con esa CURP" (código Prisma P2002)
fechaNac"Selecciona la fecha de nacimiento"
sexo"Selecciona el sexo"
grado"Selecciona el grado"
grupo"Ingresa el grupo (ej. A, B, C)"
escuela"Ingresa el nombre del plantel"

Ejemplo

import { registrarEstudiante } from "@/lib/actions/estudiante"
import { useActionState } from "react"

function FormularioEstudiante() {
  const [state, formAction] = useActionState(registrarEstudiante, undefined)

  return (
    <form action={formAction}>
      <input name="nombre" />
      <input name="curp" />
      <input name="fechaNac" type="date" />
      <select name="sexo">
        <option value="MASCULINO">Masculino</option>
        <option value="FEMENINO">Femenino</option>
        <option value="OTRO">Otro</option>
      </select>
      <input name="grado" />
      <input name="grupo" />
      <input name="escuela" />
      {state?.fieldErrors?.nombre && <p>{state.fieldErrors.nombre}</p>}
      <button type="submit">Registrar</button>
    </form>
  )
}

Modelo de datos: Estudiante

CampoTipoDescripción
idStringCUID autogenerado, clave primaria
curpStringCURP mexicana — única por estudiante
nombreStringNombre completo
edadIntEdad calculada desde fecha de nacimiento
sexoSexoEnum: MASCULINO, FEMENINO, OTRO
gradoStringGrado escolar
grupoStringGrupo (letra, ej. A)
escuelaStringNombre del plantel
tokenEncuestaStringToken único para acceso al cuestionario (CUID autogenerado)

Acciones de usuarios

Todas las acciones de usuarios requieren que la sesión activa tenga el rol ADMIN. Cualquier intento de un rol diferente lanza Error("No autorizado").

crearUsuario

export async function crearUsuario(data: {
  nombre: string
  email: string
  password: string
  rol: string
}): Promise<void>
Crea un nuevo usuario del staff. La contraseña se hashea con bcrypt (12 rondas) antes de persistir. Invalida la caché de /usuarios.

Parámetros

CampoTipoDescripción
nombrestringNombre completo (se recorta con .trim())
emailstringCorreo electrónico — único en la tabla Usuario
passwordstringMínimo 6 caracteres
rolstringDebe ser uno de: ADMIN, PSICOLOGO, DIRECTOR, ORIENTADOR

Errores lanzados (throw)

MensajeCausa
"No autorizado"Sesión sin rol ADMIN
"Rol no válido"Rol fuera de los valores permitidos del staff
"La contraseña debe tener al menos 6 caracteres"Contraseña muy corta
"El usuario no puede estar vacío"Email vacío tras trim
"Ya existe un usuario con ese nombre"Email duplicado

Ejemplo

import { crearUsuario } from "@/lib/actions/usuario"

await crearUsuario({
  nombre: "Dr. Carlos Pérez",
  email: "cperez@cecyten.edu.mx",
  password: "segura123",
  rol: "PSICOLOGO",
})

actualizarUsuario

export async function actualizarUsuario(
  id: string,
  data: {
    nombre: string
    email: string
    rol: string
    password?: string
  }
): Promise<void>
Actualiza los datos de un usuario existente. Si password se proporciona y no está vacío, se rehashea. El administrador no puede cambiar su propio rol.

Parámetros

ParámetroTipoDescripción
idstringID del usuario a actualizar
data.nombrestringNuevo nombre
data.emailstringNuevo email
data.rolstringNuevo rol (ADMIN, PSICOLOGO, DIRECTOR, ORIENTADOR)
data.passwordstring?Nueva contraseña — opcional. Si se omite o es vacío, no se modifica

Ejemplo

import { actualizarUsuario } from "@/lib/actions/usuario"

await actualizarUsuario("cm1xyz789", {
  nombre: "Dra. Ana Martínez",
  email: "amartinez@cecyten.edu.mx",
  rol: "ORIENTADOR",
  // sin password → no se modifica
})

eliminarUsuario

export async function eliminarUsuario(id: string): Promise<void>
Elimina un usuario del sistema. El administrador no puede eliminarse a sí mismo.

Parámetros

ParámetroTipoDescripción
idstringID del usuario a eliminar

Errores lanzados (throw)

MensajeCausa
"No autorizado"Sesión sin rol ADMIN
"Usuario no encontrado"El ID no existe
"No puedes eliminar tu propio usuario"El ID corresponde al admin en sesión

Ejemplo

import { eliminarUsuario } from "@/lib/actions/usuario"

await eliminarUsuario("cm1xyz789")

Modelo de datos: Usuario

CampoTipoDescripción
idStringCUID autogenerado
emailStringCorreo electrónico — único
passwordStringHash bcrypt (no se expone en consultas)
nombreStringNombre completo
rolRolEnum de rol
creadoEnDateTimeFecha de creación (automática)
estudianteIdString?FK a Estudiante si el usuario es un estudiante

Enums

Rol

import type { Rol } from "@/lib/enums"
ValorDescripción
ESTUDIANTESolo puede contestar su propio cuestionario
PSICOLOGOGestiona citas, sesiones, canalizaciones y expedientes
ORIENTADORGestiona citas, sesiones, canalizaciones y expedientes
DIRECTORAcceso de lectura al dashboard
ADMINAcceso total — crea y administra usuarios
El rol ESTUDIANTE es para cuentas vinculadas a un registro de estudiante. Las acciones de usuario (crearUsuario, actualizarUsuario) solo aceptan los roles de staff: ADMIN, PSICOLOGO, DIRECTOR y ORIENTADOR.

Sexo

import type { Sexo } from "@/lib/enums"
ValorDescripción
MASCULINOSexo masculino
FEMENINOSexo femenino
OTROOtra opción

Build docs developers (and LLMs) love