Cargando asignaturas…
diff --git a/src/data/api/plans.api.ts b/src/data/api/plans.api.ts
index f9daed5..93dfcef 100644
--- a/src/data/api/plans.api.ts
+++ b/src/data/api/plans.api.ts
@@ -221,7 +221,9 @@ export async function plan_lineas_list(
const supabase = supabaseBrowser()
const { data, error } = await supabase
.from('lineas_plan')
- .select('id,plan_estudio_id,nombre,orden,area,creado_en,actualizado_en')
+ .select(
+ 'id,plan_estudio_id,nombre,orden,area,creado_en,actualizado_en,color',
+ )
.eq('plan_estudio_id', planId)
.order('orden', { ascending: true })
diff --git a/src/data/api/subjects.api.ts b/src/data/api/subjects.api.ts
index 9b4ab51..e745812 100644
--- a/src/data/api/subjects.api.ts
+++ b/src/data/api/subjects.api.ts
@@ -499,6 +499,7 @@ export async function lineas_insert(linea: {
plan_estudio_id: string
orden: number
area?: string
+ color?: string | null
}) {
const supabase = supabaseBrowser()
const { data, error } = await supabase
@@ -514,7 +515,12 @@ export async function lineas_insert(linea: {
// Actualizar una línea existente
export async function lineas_update(
lineaId: string,
- patch: { nombre?: string; orden?: number; area?: string },
+ patch: {
+ nombre?: string
+ orden?: number
+ area?: string
+ color?: string | null
+ },
) {
const supabase = supabaseBrowser()
const { data, error } = await supabase
diff --git a/src/routes/dashboard.tsx b/src/routes/dashboard.tsx
index 862ba12..7f70a9e 100644
--- a/src/routes/dashboard.tsx
+++ b/src/routes/dashboard.tsx
@@ -30,7 +30,7 @@ function RouteComponent() {
4. px-4 md:px-6: Padding RESPONSIVO interno (seguro para móviles y desktop).
5. py-6: Padding vertical (opcional, para separarse del header).
*/}
-
+
-
+
{/* 2. Header del Plan */}
{isLoading ? (
/* ===== SKELETON ===== */
diff --git a/src/routes/planes/$planId/_detalle/mapa.tsx b/src/routes/planes/$planId/_detalle/mapa.tsx
index cf6e3ad..e3622b7 100644
--- a/src/routes/planes/$planId/_detalle/mapa.tsx
+++ b/src/routes/planes/$planId/_detalle/mapa.tsx
@@ -2,10 +2,10 @@
import { createFileRoute } from '@tanstack/react-router'
import { Plus, AlertTriangle, Trash2, Download } from 'lucide-react'
import * as Icons from 'lucide-react'
-import { useMemo, useState, useEffect, Fragment } from 'react'
+import { useMemo, useState, useEffect, Fragment, useRef } from 'react'
import type { TipoAsignatura } from '@/data'
-import type { Asignatura, LineaCurricular } from '@/types/plan'
+import type { Asignatura } from '@/types/plan'
import type { TablesUpdate } from '@/types/supabase'
import { Badge } from '@/components/ui/badge'
@@ -17,6 +17,8 @@ import {
DialogTitle,
} from '@/components/ui/dialog'
import { Input } from '@/components/ui/input'
+import { Label } from '@/components/ui/label'
+import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
import {
Select,
SelectContent,
@@ -24,6 +26,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
+import { Separator } from '@/components/ui/separator'
import {
Tooltip,
TooltipContent,
@@ -39,6 +42,8 @@ import {
useUpdateAsignatura,
useUpdateLinea,
} from '@/data'
+import { cn } from '@/lib/utils'
+import { generarColorContrastante } from '@/utils/colors'
// --- Mapeadores (Fuera del componente para mayor limpieza) ---
const palette = [
@@ -52,9 +57,16 @@ const palette = [
'#C026D3', // fucsia
]
+type LineaCurricularUI = {
+ id: string
+ nombre: string
+ orden: number
+ color: string
+}
+
const mapLineasToLineaCurricular = (
lineasApi: Array
= [],
-): Array => {
+): Array => {
return lineasApi.map((linea, index) => ({
id: linea.id,
nombre: linea.nombre,
@@ -276,11 +288,6 @@ function AsignaturaCardItem({
-
- {/* drag affordance */}
-
-
-
@@ -311,20 +318,26 @@ function MapaCurricularPage() {
const { data } = usePlan(planId)
const [totalCiclos, setTotalCiclos] = useState(0)
const [editingLineaId, setEditingLineaId] = useState