@@ -890,15 +889,15 @@ function AsignaturaCard({ a, onClone, onAddToCart }: { a: Asignatura; onClone: (
{a.plan.carrera && (
}
- label={a.plan.carrera.nombre}
- />
+ label={a.plan.carrera.nombre}
+ />
)}
{a.plan.carrera?.facultad && (
}
label={a.plan.carrera.facultad.nombre}
- tint={a.plan.carrera.facultad.color}
- />
+ tint={a.plan.carrera.facultad.color}
+ />
)}
)}
diff --git a/src/routes/_authenticated/plan/$planId.tsx b/src/routes/_authenticated/plan/$planId.tsx
index 2dfb041..76e0e02 100644
--- a/src/routes/_authenticated/plan/$planId.tsx
+++ b/src/routes/_authenticated/plan/$planId.tsx
@@ -7,7 +7,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { AcademicSections, planKeys } from "@/components/planes/academic-sections"
import { GradientMesh } from "../../../components/planes/GradientMesh"
-import { asignaturaExtraOptions, asignaturaKeys, asignaturasCountOptions, asignaturasPreviewOptions, planByIdOptions, type AsignaturaLite, type PlanFull } from "@/components/planes/planQueries"
+import { asignaturaExtraOptions, asignaturaKeys, asignaturasPreviewOptions, planByIdOptions, type AsignaturaLite, type PlanFull } from "@/components/planes/planQueries"
import { softAccentStyle } from "@/components/planes/planHelpers"
import { Dialog, DialogContent, DialogDescription, DialogTitle } from "@/components/ui/dialog"
import { DialogFooter, DialogHeader } from "@/components/ui/dialog"
diff --git a/src/routes/_authenticated/usuarios.tsx b/src/routes/_authenticated/usuarios.tsx
index 8345f17..9405dd1 100644
--- a/src/routes/_authenticated/usuarios.tsx
+++ b/src/routes/_authenticated/usuarios.tsx
@@ -17,13 +17,6 @@ import { toast } from "sonner"
-/* -------------------- Tipos -------------------- */
-
-
-const SCOPED_ROLES = ["director_facultad", "secretario_academico", "jefe_carrera"] as const
-
-
-
/* -------------------- Query Keys & Fetcher -------------------- */
const usersKeys = {
@@ -149,35 +142,6 @@ function RouteComponent() {
carrera_id?: string | null
}>({ email: "", password: "" })
- function genPassword() {
- /*
- Supabase requiere que las contraseñas tengan las siguientes características:
- - Mínimo de 6 caracteres
- - Debe contener al menos una letra minúscula
- - Debe contener al menos una letra mayúscula
- - Debe contener al menos un número
- - Debe contener al menos un carácter especial
- Para garantizar la seguridad, generaremos contraseñas de 12 caracteres en vez del mínimo de 6
- */
-
- // 1. Generar una permutación de los números de 1 al 12 con el método Fisher-Yates
-
- const positions = Array.from({ length: 12 }, (_, i) => i);
- for (let i = positions.length - 1; i > 0; i--) {
- const j = Math.floor(Math.random() * (i + 1));
- [positions[i], positions[j]] = [positions[j], positions[i]];
- }
-
- // 2. Las correspondencias son las siguientes:
- // - El primer número indica la posición de la letra minúscula
- // - El segundo número indica la posición de la letra mayúscula
- // - El tercer número indica la posición del número
- // - El cuarto número indica la posición del carácter especial
- // - En las demás posiciones puede haber cualquier caracter alfanumérico
-
- const s = Array.from(crypto.getRandomValues(new Uint32Array(4))).map((n) => n.toString(36)).join("")
- return s.slice(0, 14)
- }
function RolePill({ role }: { role: Role }) {
const meta = ROLE_META[role]
@@ -197,61 +161,6 @@ function RouteComponent() {
router.invalidate()
}
- const upsertNombramiento = useMutation({
- mutationFn: async (opts: {
- user_id: string
- puesto: "director_facultad" | "secretario_academico" | "jefe_carrera"
- facultad_id?: string | null
- carrera_id?: string | null
- }) => {
- // cierra vigentes
- if (opts.puesto === "jefe_carrera") {
- if (!opts.carrera_id) throw new Error("Selecciona carrera")
- await supabase
- .from("nombramientos")
- .update({ hasta: new Date().toISOString().slice(0, 10) })
- .eq("puesto", "jefe_carrera")
- .eq("carrera_id", opts.carrera_id)
- .is("hasta", null)
- } else {
- if (!opts.facultad_id) throw new Error("Selecciona facultad")
- await supabase
- .from("nombramientos")
- .update({ hasta: new Date().toISOString().slice(0, 10) })
- .eq("puesto", opts.puesto)
- .eq("facultad_id", opts.facultad_id)
- .is("hasta", null)
- }
- const { error } = await supabase.from("nombramientos").insert({
- user_id: opts.user_id,
- puesto: opts.puesto,
- facultad_id: opts.facultad_id ?? null,
- carrera_id: opts.carrera_id ?? null,
- desde: new Date().toISOString().slice(0, 10),
- hasta: null,
- })
- if (error) throw error
- },
- onError: (e: any) => toast.error(e?.message || "Error al registrar nombramiento"),
- })
-
- const toggleBan = useMutation({
- mutationFn: async (u: UserClaims) => {
- throw new Error("Funcionalidad de baneo no implementada aún.")
- const banned = false // cuando se tenga acceso a ese campo
- // const banned = !!u.banned_until && new Date(u.banned_until) > new Date()
- const payload = banned ? { banned_until: null } : { banned_until: new Date(Date.now() + 100 * 365 * 24 * 60 * 60 * 1000).toISOString() }
- // const { error } = await supabase.auth.admin.updateUserById(u.id, payload as any)
- // if (error) throw new Error(error.message)
- return !banned
- },
- onSuccess: async (isBanned) => {
- toast.success(isBanned ? "Usuario baneado" : "Usuario desbaneado")
- await invalidateAll()
- },
- onError: (e: any) => toast.error(e?.message || "Error al cambiar estado de baneo"),
- })
-
const createUser = useMutation({
mutationFn: async (payload: typeof createForm) => {
// Validaciones previas
@@ -409,7 +318,7 @@ function RouteComponent() {