Compare commits
6 Commits
ddb3a5023c
...
9065899616
| Author | SHA1 | Date | |
|---|---|---|---|
| 9065899616 | |||
| 9cad2a0f62 | |||
| dc85e2c946 | |||
| 4e00262ab0 | |||
| 35ea4caa39 | |||
| 5224e632f8 |
@@ -87,7 +87,8 @@ export function IAMateriaTab({
|
|||||||
const availableFields = useMemo(() => {
|
const availableFields = useMemo(() => {
|
||||||
// Extraemos las claves directamente del objeto datosGenerales
|
// Extraemos las claves directamente del objeto datosGenerales
|
||||||
// ["nombre", "descripcion", "perfil_de_egreso", "fines_de_aprendizaje_o_formacion"]
|
// ["nombre", "descripcion", "perfil_de_egreso", "fines_de_aprendizaje_o_formacion"]
|
||||||
return Object.keys(datosGenerales).map((key) => {
|
if (!datosGenerales.datos) return []
|
||||||
|
return Object.keys(datosGenerales.datos).map((key) => {
|
||||||
// Buscamos si existe un nombre amigable en la estructura de campos
|
// Buscamos si existe un nombre amigable en la estructura de campos
|
||||||
const estructuraCampo = campos.find((c) => c.id === key)
|
const estructuraCampo = campos.find((c) => c.id === key)
|
||||||
|
|
||||||
@@ -110,12 +111,15 @@ export function IAMateriaTab({
|
|||||||
const state = routerState.location.state as any
|
const state = routerState.location.state as any
|
||||||
|
|
||||||
if (state?.prefillCampo && availableFields.length > 0) {
|
if (state?.prefillCampo && availableFields.length > 0) {
|
||||||
|
console.log(state?.prefillCampo)
|
||||||
|
console.log(availableFields)
|
||||||
|
|
||||||
const field = availableFields.find((f) => f.key === state.prefillCampo)
|
const field = availableFields.find((f) => f.key === state.prefillCampo)
|
||||||
|
|
||||||
if (field && !selectedFields.find((sf) => sf.key === field.key)) {
|
if (field && !selectedFields.find((sf) => sf.key === field.key)) {
|
||||||
setSelectedFields([field])
|
setSelectedFields([field])
|
||||||
// Sincronizamos el texto inicial con el campo pre-seleccionado
|
// Sincronizamos el texto inicial con el campo pre-seleccionado
|
||||||
setInput(`Mejora el campo ${field.key}: `)
|
setInput(`Mejora el campo ${field.label}: `)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
@@ -139,37 +143,32 @@ export function IAMateriaTab({
|
|||||||
setSelectedFields((prev) => {
|
setSelectedFields((prev) => {
|
||||||
const isSelected = prev.find((f) => f.key === field.key)
|
const isSelected = prev.find((f) => f.key === field.key)
|
||||||
|
|
||||||
// Si lo estamos seleccionando (no estaba antes)
|
// 1. Si ya está seleccionado, lo quitamos (Toggle OFF)
|
||||||
if (!isSelected) {
|
if (isSelected) {
|
||||||
// Actualizamos el texto del input:
|
|
||||||
// Si termina en ":", lo reemplazamos por el key para que sea "Mejora perfil_de_egreso "
|
|
||||||
// Si no, simplemente lo añadimos al final.
|
|
||||||
setInput((prevText) => {
|
|
||||||
const [beforeColon, afterColon = ''] = prevText.split(':')
|
|
||||||
|
|
||||||
// Campos ya escritos después de :
|
|
||||||
const existingKeys = afterColon
|
|
||||||
.split(',')
|
|
||||||
.map((k) => k.trim())
|
|
||||||
.filter(Boolean)
|
|
||||||
|
|
||||||
// Si ya existe, no lo volvemos a agregar
|
|
||||||
if (existingKeys.includes(field.key)) {
|
|
||||||
return prevText
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedKeys = [...existingKeys, field.key].join(', ')
|
|
||||||
|
|
||||||
return `${beforeColon.trim()}: ${updatedKeys} `
|
|
||||||
})
|
|
||||||
|
|
||||||
return [field]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si lo estamos deseleccionando, solo quitamos el tag
|
|
||||||
return prev.filter((f) => f.key !== field.key)
|
return prev.filter((f) => f.key !== field.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Si no está, lo agregamos a la lista (Toggle ON)
|
||||||
|
const newSelected = [...prev, field]
|
||||||
|
|
||||||
|
// 3. Actualizamos el texto del input para reflejar los títulos (labels)
|
||||||
|
setInput((prevText) => {
|
||||||
|
// Separamos lo que el usuario escribió antes del disparador ":"
|
||||||
|
// y lo que viene después (posibles keys/labels previos)
|
||||||
|
const parts = prevText.split(':')
|
||||||
|
const beforeColon = parts[0]
|
||||||
|
|
||||||
|
// Creamos un string con los labels de todos los campos seleccionados
|
||||||
|
const labelsPath = newSelected.map((f) => f.label).join(', ')
|
||||||
|
|
||||||
|
return `${beforeColon.trim()}: ${labelsPath} `
|
||||||
})
|
})
|
||||||
setShowSuggestions(false)
|
|
||||||
|
return newSelected
|
||||||
|
})
|
||||||
|
|
||||||
|
// Opcional: mantener abierto si quieres que el usuario elija varios seguidos
|
||||||
|
// setShowSuggestions(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildPrompt = (userInput: string) => {
|
const buildPrompt = (userInput: string) => {
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
|||||||
import { Separator } from '@/components/ui/separator'
|
import { Separator } from '@/components/ui/separator'
|
||||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
|
||||||
import { Textarea } from '@/components/ui/textarea'
|
import { Textarea } from '@/components/ui/textarea'
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from '@/components/ui/tooltip'
|
||||||
import { useSubject } from '@/data/hooks/useSubjects'
|
import { useSubject } from '@/data/hooks/useSubjects'
|
||||||
import {
|
import {
|
||||||
mockMateria,
|
mockMateria,
|
||||||
@@ -150,7 +156,7 @@ export default function MateriaDetailPage() {
|
|||||||
/* ---------- sincronizar API ---------- */
|
/* ---------- sincronizar API ---------- */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (asignaturasApi?.datos) {
|
if (asignaturasApi?.datos) {
|
||||||
setDatosGenerales(asignaturasApi.datos)
|
setDatosGenerales(asignaturasApi)
|
||||||
}
|
}
|
||||||
}, [asignaturasApi])
|
}, [asignaturasApi])
|
||||||
|
|
||||||
@@ -211,7 +217,7 @@ export default function MateriaDetailPage() {
|
|||||||
<section className="bg-gradient-to-b from-[#0b1d3a] to-[#0e2a5c] text-white">
|
<section className="bg-gradient-to-b from-[#0b1d3a] to-[#0e2a5c] text-white">
|
||||||
<div className="mx-auto max-w-7xl px-6 py-10">
|
<div className="mx-auto max-w-7xl px-6 py-10">
|
||||||
<Link
|
<Link
|
||||||
to="/planes/$planId"
|
to="/planes/$planId/asignaturas"
|
||||||
params={{ planId }}
|
params={{ planId }}
|
||||||
className="mb-4 flex items-center gap-2 text-sm text-blue-200 hover:text-white"
|
className="mb-4 flex items-center gap-2 text-sm text-blue-200 hover:text-white"
|
||||||
>
|
>
|
||||||
@@ -392,6 +398,13 @@ function DatosGenerales({
|
|||||||
const formatTitle = (key: string): string =>
|
const formatTitle = (key: string): string =>
|
||||||
key.replace(/_/g, ' ').replace(/\b\w/g, (l: string) => l.toUpperCase())
|
key.replace(/_/g, ' ').replace(/\b\w/g, (l: string) => l.toUpperCase())
|
||||||
|
|
||||||
|
// 1. Extraemos la definición de la estructura (los metadatos)
|
||||||
|
const structureProps =
|
||||||
|
data?.estructuras_asignatura?.definicion?.properties || {}
|
||||||
|
|
||||||
|
// 2. Extraemos los valores reales (el contenido redactado)
|
||||||
|
const valoresActuales = data?.datos || {}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="animate-in fade-in mx-auto max-w-7xl space-y-8 px-4 py-8 duration-500">
|
<div className="animate-in fade-in mx-auto max-w-7xl space-y-8 px-4 py-8 duration-500">
|
||||||
{/* Encabezado de la Sección */}
|
{/* Encabezado de la Sección */}
|
||||||
@@ -413,19 +426,47 @@ function DatosGenerales({
|
|||||||
{isLoading && <p>Cargando información...</p>}
|
{isLoading && <p>Cargando información...</p>}
|
||||||
|
|
||||||
{!isLoading &&
|
{!isLoading &&
|
||||||
Object.entries(data).map(([key, value]) => (
|
Object.entries(structureProps).map(
|
||||||
|
([key, config]: [string, any]) => {
|
||||||
|
// 1. METADATOS (Vienen de structureProps -> config)
|
||||||
|
const cardTitle = config.title || key
|
||||||
|
const description = config.description || ''
|
||||||
|
|
||||||
|
// Obtenemos el placeholder del arreglo 'examples' de la estructura
|
||||||
|
const placeholder =
|
||||||
|
config.examples && config.examples.length > 0
|
||||||
|
? config.examples[0]
|
||||||
|
: ''
|
||||||
|
|
||||||
|
// 2. CONTENIDO REAL (Viene de data.datos -> valoresActuales)
|
||||||
|
// El problema: Si 'description' en 'datos' es igual a la de la 'estructura',
|
||||||
|
// el usuario aún no ha redactado nada real.
|
||||||
|
|
||||||
|
const valActual = valoresActuales[key]
|
||||||
|
|
||||||
|
// Lógica para determinar si mostrar el contenido o dejarlo vacío (para que salga el placeholder)
|
||||||
|
// Si el contenido en 'datos' es idéntico a la instrucción de la 'estructura',
|
||||||
|
// asumimos que no hay contenido real todavía.
|
||||||
|
const isContentEmpty =
|
||||||
|
!valActual?.description ||
|
||||||
|
valActual.description === config.description
|
||||||
|
|
||||||
|
const currentContent = valActual.description ?? ''
|
||||||
|
|
||||||
|
return (
|
||||||
<InfoCard
|
<InfoCard
|
||||||
asignaturaId={asignaturaId}
|
asignaturaId={asignaturaId}
|
||||||
key={key}
|
key={key}
|
||||||
clave={key}
|
clave={key}
|
||||||
title={formatTitle(key)}
|
title={cardTitle}
|
||||||
initialContent={value}
|
initialContent={currentContent} // Si es igual a la descripción de la SEP, pasamos vacío
|
||||||
onEnhanceAI={(contenido) => {
|
placeholder={placeholder} // Aquí irá "Primer semestre", "MAT-101", etc.
|
||||||
console.log('Llevar a IA:', contenido)
|
description={description} // El texto largo de "Indicar el ciclo..."
|
||||||
// Aquí tu lógica: setPestañaActiva('mejorar-con-ia');
|
onEnhanceAI={(contenido) => console.log(contenido)}
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
))}
|
)
|
||||||
|
},
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Columna Lateral (Información Secundaria) */}
|
{/* Columna Lateral (Información Secundaria) */}
|
||||||
@@ -469,11 +510,14 @@ function DatosGenerales({
|
|||||||
|
|
||||||
interface InfoCardProps {
|
interface InfoCardProps {
|
||||||
asignaturaId?: string
|
asignaturaId?: string
|
||||||
clave: string
|
clave?: string
|
||||||
title: string
|
title: string
|
||||||
initialContent: any
|
initialContent: any
|
||||||
|
placeholder?: string
|
||||||
|
description?: string
|
||||||
|
required?: boolean // Nueva prop para el asterisco
|
||||||
type?: 'text' | 'requirements' | 'evaluation'
|
type?: 'text' | 'requirements' | 'evaluation'
|
||||||
onEnhanceAI?: (content: any) => void // Nueva prop para la acción de IA
|
onEnhanceAI?: (content: any) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function InfoCard({
|
function InfoCard({
|
||||||
@@ -481,57 +525,86 @@ function InfoCard({
|
|||||||
clave,
|
clave,
|
||||||
title,
|
title,
|
||||||
initialContent,
|
initialContent,
|
||||||
|
placeholder,
|
||||||
|
description,
|
||||||
|
required,
|
||||||
type = 'text',
|
type = 'text',
|
||||||
onEnhanceAI,
|
|
||||||
}: InfoCardProps) {
|
}: InfoCardProps) {
|
||||||
const [isEditing, setIsEditing] = useState(false)
|
const [isEditing, setIsEditing] = useState(false)
|
||||||
const [data, setData] = useState(initialContent)
|
const [data, setData] = useState(initialContent)
|
||||||
const [tempText, setTempText] = useState(
|
const [tempText, setTempText] = useState(initialContent)
|
||||||
type === 'text' ? initialContent : JSON.stringify(initialContent, null, 2),
|
|
||||||
)
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setData(initialContent)
|
||||||
|
setTempText(initialContent)
|
||||||
|
}, [initialContent])
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
setData(tempText)
|
setData(tempText)
|
||||||
setIsEditing(false)
|
setIsEditing(false)
|
||||||
|
// Aquí iría tu lógica de guardado a la DB
|
||||||
}
|
}
|
||||||
const handleIARequest = (data) => {
|
|
||||||
console.log(data)
|
const handleIARequest = (campoClave: string) => {
|
||||||
console.log(asignaturaId)
|
console.log(placeholder)
|
||||||
|
|
||||||
navigate({
|
navigate({
|
||||||
to: '/planes/$planId/asignaturas/$asignaturaId',
|
to: '/planes/$planId/asignaturas/$asignaturaId',
|
||||||
params: {
|
params: { asignaturaId: asignaturaId! },
|
||||||
asignaturaId: asignaturaId,
|
|
||||||
},
|
|
||||||
state: {
|
state: {
|
||||||
activeTab: 'ia',
|
activeTab: 'ia',
|
||||||
prefillCampo: data,
|
prefillCampo: campoClave,
|
||||||
prefillContenido: data, // el contenido actual del card
|
prefillContenido: data,
|
||||||
} as any,
|
} as any,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="transition-all hover:border-slate-300">
|
<Card className="overflow-hidden transition-all hover:border-slate-300">
|
||||||
<CardHeader className="flex flex-row items-start justify-between space-y-0 pb-3">
|
<TooltipProvider>
|
||||||
<CardTitle className="text-sm font-bold text-slate-700">
|
<CardHeader className="border-b bg-slate-50/50 px-5 py-3">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<CardTitle className="cursor-help text-sm font-bold text-slate-700">
|
||||||
{title}
|
{title}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="top" className="max-w-xs text-xs">
|
||||||
|
{description || 'Información del campo'}
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
{required && (
|
||||||
|
<span
|
||||||
|
className="text-sm font-bold text-red-500"
|
||||||
|
title="Requerido"
|
||||||
|
>
|
||||||
|
*
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{!isEditing && (
|
{!isEditing && (
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
{/* NUEVO: Botón de Mejorar con IA */}
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="h-8 w-8 text-blue-500 hover:bg-blue-50 hover:text-blue-600"
|
className="h-8 w-8 text-blue-500 hover:bg-blue-100"
|
||||||
onClick={() => handleIARequest(clave)} // Enviamos la data actual a la IA
|
onClick={() => handleIARequest(clave)}
|
||||||
title="Mejorar con IA"
|
|
||||||
>
|
>
|
||||||
<Sparkles className="h-4 w-4" />
|
<Sparkles className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>Mejorar con IA</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
{/* Botón de Editar original */}
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
@@ -540,17 +613,23 @@ function InfoCard({
|
|||||||
>
|
>
|
||||||
<Pencil className="h-3 w-3" />
|
<Pencil className="h-3 w-3" />
|
||||||
</Button>
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>Editar campo</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
<CardContent>
|
<CardContent className="pt-4">
|
||||||
{isEditing ? (
|
{isEditing ? (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<Textarea
|
<Textarea
|
||||||
value={tempText}
|
value={tempText}
|
||||||
|
placeholder={placeholder}
|
||||||
onChange={(e) => setTempText(e.target.value)}
|
onChange={(e) => setTempText(e.target.value)}
|
||||||
className="min-h-[100px] text-xs"
|
className="min-h-[120px] text-sm leading-relaxed"
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-end gap-2">
|
<div className="flex justify-end gap-2">
|
||||||
<Button
|
<Button
|
||||||
@@ -570,10 +649,17 @@ function InfoCard({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-sm">
|
<div className="text-sm leading-relaxed text-slate-600">
|
||||||
|
{type === 'text' &&
|
||||||
|
(data ? (
|
||||||
|
<p className="whitespace-pre-wrap">{data}</p>
|
||||||
|
) : (
|
||||||
|
<p className="text-slate-400 italic">
|
||||||
|
Sin información. Ejemplo: {placeholder}
|
||||||
|
</p>
|
||||||
|
))}
|
||||||
{type === 'requirements' && <RequirementsView items={data} />}
|
{type === 'requirements' && <RequirementsView items={data} />}
|
||||||
{type === 'evaluation' && <EvaluationView items={data} />}
|
{type === 'evaluation' && <EvaluationView items={data} />}
|
||||||
{type === 'text' && <p className="text-slate-600">{data}</p>}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -118,7 +118,10 @@ export function WizardControls({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex grow items-center justify-between">
|
||||||
|
<Button variant="secondary" onClick={onPrev} disabled={disablePrev}>
|
||||||
|
Anterior
|
||||||
|
</Button>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
{errorMessage && (
|
{errorMessage && (
|
||||||
<span className="text-destructive text-sm font-medium">
|
<span className="text-destructive text-sm font-medium">
|
||||||
@@ -126,10 +129,6 @@ export function WizardControls({
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-4">
|
|
||||||
<Button variant="secondary" onClick={onPrev} disabled={disablePrev}>
|
|
||||||
Anterior
|
|
||||||
</Button>
|
|
||||||
{isLastStep ? (
|
{isLastStep ? (
|
||||||
<Button onClick={handleCreate} disabled={disableCreate}>
|
<Button onClick={handleCreate} disabled={disableCreate}>
|
||||||
Crear plan
|
Crear plan
|
||||||
@@ -140,6 +139,5 @@ export function WizardControls({
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
44
src/components/ui/NotFoundPage.tsx
Normal file
44
src/components/ui/NotFoundPage.tsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { Link, useRouter } from '@tanstack/react-router'
|
||||||
|
import { FileQuestion, Home, ArrowLeft } from 'lucide-react'
|
||||||
|
|
||||||
|
import { Button } from './button'
|
||||||
|
|
||||||
|
interface NotFoundPageProps {
|
||||||
|
title?: string
|
||||||
|
message?: string
|
||||||
|
children?: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NotFoundPage({
|
||||||
|
title = 'Página no encontrada',
|
||||||
|
message = 'Lo sentimos, no pudimos encontrar lo que buscabas. Es posible que la página haya sido movida o eliminada.',
|
||||||
|
children,
|
||||||
|
}: NotFoundPageProps) {
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-[60vh] flex-col items-center justify-center p-4 text-center">
|
||||||
|
<div className="bg-muted mb-6 rounded-full p-6">
|
||||||
|
<FileQuestion className="text-muted-foreground h-12 w-12" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 className="mb-2 text-3xl font-bold tracking-tight">{title}</h1>
|
||||||
|
<p className="text-muted-foreground mb-8 max-w-125">{message}</p>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2 sm:flex-row">
|
||||||
|
<Button variant="outline" onClick={() => router.history.back()}>
|
||||||
|
<ArrowLeft className="mr-2 h-4 w-4" />
|
||||||
|
Regresar
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button asChild>
|
||||||
|
<Link to="/">
|
||||||
|
<Home className="mr-2 h-4 w-4" />
|
||||||
|
Ir al inicio
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -123,6 +123,8 @@ export async function plans_list(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function plans_get(planId: UUID): Promise<PlanEstudio> {
|
export async function plans_get(planId: UUID): Promise<PlanEstudio> {
|
||||||
|
console.log('plans_get')
|
||||||
|
|
||||||
const supabase = supabaseBrowser()
|
const supabase = supabaseBrowser()
|
||||||
|
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
|
|||||||
@@ -53,7 +53,10 @@ export function usePlanes(filters: PlanListFilters) {
|
|||||||
export function usePlan(planId: UUID | null | undefined) {
|
export function usePlan(planId: UUID | null | undefined) {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: planId ? qk.plan(planId) : ['planes', 'detail', null],
|
queryKey: planId ? qk.plan(planId) : ['planes', 'detail', null],
|
||||||
queryFn: () => plans_get(planId as UUID),
|
queryFn: () => {
|
||||||
|
console.log('usePlan')
|
||||||
|
return plans_get(planId as UUID)
|
||||||
|
},
|
||||||
enabled: Boolean(planId),
|
enabled: Boolean(planId),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,18 +14,16 @@ import { Route as DashboardRouteImport } from './routes/dashboard'
|
|||||||
import { Route as IndexRouteImport } from './routes/index'
|
import { Route as IndexRouteImport } from './routes/index'
|
||||||
import { Route as DemoTanstackQueryRouteImport } from './routes/demo/tanstack-query'
|
import { Route as DemoTanstackQueryRouteImport } from './routes/demo/tanstack-query'
|
||||||
import { Route as PlanesListaRouteRouteImport } from './routes/planes/_lista/route'
|
import { Route as PlanesListaRouteRouteImport } from './routes/planes/_lista/route'
|
||||||
import { Route as PlanesPlanIdIndexRouteImport } from './routes/planes/$planId/index'
|
|
||||||
import { Route as PlanesListaNuevoRouteImport } from './routes/planes/_lista/nuevo'
|
import { Route as PlanesListaNuevoRouteImport } from './routes/planes/_lista/nuevo'
|
||||||
import { Route as PlanesPlanIdAsignaturasRouteRouteImport } from './routes/planes/$planId/asignaturas/route'
|
import { Route as PlanesPlanIdAsignaturasRouteRouteImport } from './routes/planes/$planId/asignaturas/route'
|
||||||
import { Route as PlanesPlanIdDetalleRouteRouteImport } from './routes/planes/$planId/_detalle/route'
|
import { Route as PlanesPlanIdDetalleRouteRouteImport } from './routes/planes/$planId/_detalle/route'
|
||||||
import { Route as PlanesPlanIdAsignaturasIndexRouteImport } from './routes/planes/$planId/asignaturas/index'
|
import { Route as PlanesPlanIdDetalleIndexRouteImport } from './routes/planes/$planId/_detalle/index'
|
||||||
import { Route as PlanesPlanIdDetalleMateriasRouteImport } from './routes/planes/$planId/_detalle/materias'
|
|
||||||
import { Route as PlanesPlanIdDetalleMapaRouteImport } from './routes/planes/$planId/_detalle/mapa'
|
import { Route as PlanesPlanIdDetalleMapaRouteImport } from './routes/planes/$planId/_detalle/mapa'
|
||||||
import { Route as PlanesPlanIdDetalleIaplanRouteImport } from './routes/planes/$planId/_detalle/iaplan'
|
import { Route as PlanesPlanIdDetalleIaplanRouteImport } from './routes/planes/$planId/_detalle/iaplan'
|
||||||
import { Route as PlanesPlanIdDetalleHistorialRouteImport } from './routes/planes/$planId/_detalle/historial'
|
import { Route as PlanesPlanIdDetalleHistorialRouteImport } from './routes/planes/$planId/_detalle/historial'
|
||||||
import { Route as PlanesPlanIdDetalleFlujoRouteImport } from './routes/planes/$planId/_detalle/flujo'
|
import { Route as PlanesPlanIdDetalleFlujoRouteImport } from './routes/planes/$planId/_detalle/flujo'
|
||||||
import { Route as PlanesPlanIdDetalleDocumentoRouteImport } from './routes/planes/$planId/_detalle/documento'
|
import { Route as PlanesPlanIdDetalleDocumentoRouteImport } from './routes/planes/$planId/_detalle/documento'
|
||||||
import { Route as PlanesPlanIdDetalleDatosRouteImport } from './routes/planes/$planId/_detalle/datos'
|
import { Route as PlanesPlanIdDetalleAsignaturasRouteImport } from './routes/planes/$planId/_detalle/asignaturas'
|
||||||
import { Route as PlanesPlanIdAsignaturasListaRouteRouteImport } from './routes/planes/$planId/asignaturas/_lista/route'
|
import { Route as PlanesPlanIdAsignaturasListaRouteRouteImport } from './routes/planes/$planId/asignaturas/_lista/route'
|
||||||
import { Route as PlanesPlanIdAsignaturasAsignaturaIdRouteRouteImport } from './routes/planes/$planId/asignaturas/$asignaturaId/route'
|
import { Route as PlanesPlanIdAsignaturasAsignaturaIdRouteRouteImport } from './routes/planes/$planId/asignaturas/$asignaturaId/route'
|
||||||
import { Route as PlanesPlanIdAsignaturasListaNuevaRouteImport } from './routes/planes/$planId/asignaturas/_lista/nueva'
|
import { Route as PlanesPlanIdAsignaturasListaNuevaRouteImport } from './routes/planes/$planId/asignaturas/_lista/nueva'
|
||||||
@@ -55,11 +53,6 @@ const PlanesListaRouteRoute = PlanesListaRouteRouteImport.update({
|
|||||||
path: '/planes',
|
path: '/planes',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
const PlanesPlanIdIndexRoute = PlanesPlanIdIndexRouteImport.update({
|
|
||||||
id: '/planes/$planId/',
|
|
||||||
path: '/planes/$planId/',
|
|
||||||
getParentRoute: () => rootRouteImport,
|
|
||||||
} as any)
|
|
||||||
const PlanesListaNuevoRoute = PlanesListaNuevoRouteImport.update({
|
const PlanesListaNuevoRoute = PlanesListaNuevoRouteImport.update({
|
||||||
id: '/nuevo',
|
id: '/nuevo',
|
||||||
path: '/nuevo',
|
path: '/nuevo',
|
||||||
@@ -77,16 +70,10 @@ const PlanesPlanIdDetalleRouteRoute =
|
|||||||
path: '/planes/$planId',
|
path: '/planes/$planId',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
const PlanesPlanIdAsignaturasIndexRoute =
|
const PlanesPlanIdDetalleIndexRoute =
|
||||||
PlanesPlanIdAsignaturasIndexRouteImport.update({
|
PlanesPlanIdDetalleIndexRouteImport.update({
|
||||||
id: '/',
|
id: '/',
|
||||||
path: '/',
|
path: '/',
|
||||||
getParentRoute: () => PlanesPlanIdAsignaturasRouteRoute,
|
|
||||||
} as any)
|
|
||||||
const PlanesPlanIdDetalleMateriasRoute =
|
|
||||||
PlanesPlanIdDetalleMateriasRouteImport.update({
|
|
||||||
id: '/materias',
|
|
||||||
path: '/materias',
|
|
||||||
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
||||||
} as any)
|
} as any)
|
||||||
const PlanesPlanIdDetalleMapaRoute = PlanesPlanIdDetalleMapaRouteImport.update({
|
const PlanesPlanIdDetalleMapaRoute = PlanesPlanIdDetalleMapaRouteImport.update({
|
||||||
@@ -118,10 +105,10 @@ const PlanesPlanIdDetalleDocumentoRoute =
|
|||||||
path: '/documento',
|
path: '/documento',
|
||||||
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
||||||
} as any)
|
} as any)
|
||||||
const PlanesPlanIdDetalleDatosRoute =
|
const PlanesPlanIdDetalleAsignaturasRoute =
|
||||||
PlanesPlanIdDetalleDatosRouteImport.update({
|
PlanesPlanIdDetalleAsignaturasRouteImport.update({
|
||||||
id: '/datos',
|
id: '/asignaturas',
|
||||||
path: '/datos',
|
path: '/asignaturas',
|
||||||
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
||||||
} as any)
|
} as any)
|
||||||
const PlanesPlanIdAsignaturasListaRouteRoute =
|
const PlanesPlanIdAsignaturasListaRouteRoute =
|
||||||
@@ -149,18 +136,15 @@ export interface FileRoutesByFullPath {
|
|||||||
'/planes': typeof PlanesListaRouteRouteWithChildren
|
'/planes': typeof PlanesListaRouteRouteWithChildren
|
||||||
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
||||||
'/planes/$planId': typeof PlanesPlanIdDetalleRouteRouteWithChildren
|
'/planes/$planId': typeof PlanesPlanIdDetalleRouteRouteWithChildren
|
||||||
'/planes/$planId/asignaturas': typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
'/planes/$planId/asignaturas': typeof PlanesPlanIdDetalleAsignaturasRoute
|
||||||
'/planes/nuevo': typeof PlanesListaNuevoRoute
|
'/planes/nuevo': typeof PlanesListaNuevoRoute
|
||||||
'/planes/$planId/': typeof PlanesPlanIdIndexRoute
|
|
||||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||||
'/planes/$planId/datos': typeof PlanesPlanIdDetalleDatosRoute
|
|
||||||
'/planes/$planId/documento': typeof PlanesPlanIdDetalleDocumentoRoute
|
'/planes/$planId/documento': typeof PlanesPlanIdDetalleDocumentoRoute
|
||||||
'/planes/$planId/flujo': typeof PlanesPlanIdDetalleFlujoRoute
|
'/planes/$planId/flujo': typeof PlanesPlanIdDetalleFlujoRoute
|
||||||
'/planes/$planId/historial': typeof PlanesPlanIdDetalleHistorialRoute
|
'/planes/$planId/historial': typeof PlanesPlanIdDetalleHistorialRoute
|
||||||
'/planes/$planId/iaplan': typeof PlanesPlanIdDetalleIaplanRoute
|
'/planes/$planId/iaplan': typeof PlanesPlanIdDetalleIaplanRoute
|
||||||
'/planes/$planId/mapa': typeof PlanesPlanIdDetalleMapaRoute
|
'/planes/$planId/mapa': typeof PlanesPlanIdDetalleMapaRoute
|
||||||
'/planes/$planId/materias': typeof PlanesPlanIdDetalleMateriasRoute
|
'/planes/$planId/': typeof PlanesPlanIdDetalleIndexRoute
|
||||||
'/planes/$planId/asignaturas/': typeof PlanesPlanIdAsignaturasIndexRoute
|
|
||||||
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||||
}
|
}
|
||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
@@ -169,17 +153,15 @@ export interface FileRoutesByTo {
|
|||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/planes': typeof PlanesListaRouteRouteWithChildren
|
'/planes': typeof PlanesListaRouteRouteWithChildren
|
||||||
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
||||||
'/planes/$planId': typeof PlanesPlanIdIndexRoute
|
'/planes/$planId/asignaturas': typeof PlanesPlanIdDetalleAsignaturasRoute
|
||||||
'/planes/nuevo': typeof PlanesListaNuevoRoute
|
'/planes/nuevo': typeof PlanesListaNuevoRoute
|
||||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||||
'/planes/$planId/asignaturas': typeof PlanesPlanIdAsignaturasIndexRoute
|
|
||||||
'/planes/$planId/datos': typeof PlanesPlanIdDetalleDatosRoute
|
|
||||||
'/planes/$planId/documento': typeof PlanesPlanIdDetalleDocumentoRoute
|
'/planes/$planId/documento': typeof PlanesPlanIdDetalleDocumentoRoute
|
||||||
'/planes/$planId/flujo': typeof PlanesPlanIdDetalleFlujoRoute
|
'/planes/$planId/flujo': typeof PlanesPlanIdDetalleFlujoRoute
|
||||||
'/planes/$planId/historial': typeof PlanesPlanIdDetalleHistorialRoute
|
'/planes/$planId/historial': typeof PlanesPlanIdDetalleHistorialRoute
|
||||||
'/planes/$planId/iaplan': typeof PlanesPlanIdDetalleIaplanRoute
|
'/planes/$planId/iaplan': typeof PlanesPlanIdDetalleIaplanRoute
|
||||||
'/planes/$planId/mapa': typeof PlanesPlanIdDetalleMapaRoute
|
'/planes/$planId/mapa': typeof PlanesPlanIdDetalleMapaRoute
|
||||||
'/planes/$planId/materias': typeof PlanesPlanIdDetalleMateriasRoute
|
'/planes/$planId': typeof PlanesPlanIdDetalleIndexRoute
|
||||||
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||||
}
|
}
|
||||||
export interface FileRoutesById {
|
export interface FileRoutesById {
|
||||||
@@ -192,17 +174,15 @@ export interface FileRoutesById {
|
|||||||
'/planes/$planId/_detalle': typeof PlanesPlanIdDetalleRouteRouteWithChildren
|
'/planes/$planId/_detalle': typeof PlanesPlanIdDetalleRouteRouteWithChildren
|
||||||
'/planes/$planId/asignaturas': typeof PlanesPlanIdAsignaturasRouteRouteWithChildren
|
'/planes/$planId/asignaturas': typeof PlanesPlanIdAsignaturasRouteRouteWithChildren
|
||||||
'/planes/_lista/nuevo': typeof PlanesListaNuevoRoute
|
'/planes/_lista/nuevo': typeof PlanesListaNuevoRoute
|
||||||
'/planes/$planId/': typeof PlanesPlanIdIndexRoute
|
|
||||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||||
'/planes/$planId/asignaturas/_lista': typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
'/planes/$planId/asignaturas/_lista': typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
||||||
'/planes/$planId/_detalle/datos': typeof PlanesPlanIdDetalleDatosRoute
|
'/planes/$planId/_detalle/asignaturas': typeof PlanesPlanIdDetalleAsignaturasRoute
|
||||||
'/planes/$planId/_detalle/documento': typeof PlanesPlanIdDetalleDocumentoRoute
|
'/planes/$planId/_detalle/documento': typeof PlanesPlanIdDetalleDocumentoRoute
|
||||||
'/planes/$planId/_detalle/flujo': typeof PlanesPlanIdDetalleFlujoRoute
|
'/planes/$planId/_detalle/flujo': typeof PlanesPlanIdDetalleFlujoRoute
|
||||||
'/planes/$planId/_detalle/historial': typeof PlanesPlanIdDetalleHistorialRoute
|
'/planes/$planId/_detalle/historial': typeof PlanesPlanIdDetalleHistorialRoute
|
||||||
'/planes/$planId/_detalle/iaplan': typeof PlanesPlanIdDetalleIaplanRoute
|
'/planes/$planId/_detalle/iaplan': typeof PlanesPlanIdDetalleIaplanRoute
|
||||||
'/planes/$planId/_detalle/mapa': typeof PlanesPlanIdDetalleMapaRoute
|
'/planes/$planId/_detalle/mapa': typeof PlanesPlanIdDetalleMapaRoute
|
||||||
'/planes/$planId/_detalle/materias': typeof PlanesPlanIdDetalleMateriasRoute
|
'/planes/$planId/_detalle/': typeof PlanesPlanIdDetalleIndexRoute
|
||||||
'/planes/$planId/asignaturas/': typeof PlanesPlanIdAsignaturasIndexRoute
|
|
||||||
'/planes/$planId/asignaturas/_lista/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
'/planes/$planId/asignaturas/_lista/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||||
}
|
}
|
||||||
export interface FileRouteTypes {
|
export interface FileRouteTypes {
|
||||||
@@ -216,16 +196,13 @@ export interface FileRouteTypes {
|
|||||||
| '/planes/$planId'
|
| '/planes/$planId'
|
||||||
| '/planes/$planId/asignaturas'
|
| '/planes/$planId/asignaturas'
|
||||||
| '/planes/nuevo'
|
| '/planes/nuevo'
|
||||||
| '/planes/$planId/'
|
|
||||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||||
| '/planes/$planId/datos'
|
|
||||||
| '/planes/$planId/documento'
|
| '/planes/$planId/documento'
|
||||||
| '/planes/$planId/flujo'
|
| '/planes/$planId/flujo'
|
||||||
| '/planes/$planId/historial'
|
| '/planes/$planId/historial'
|
||||||
| '/planes/$planId/iaplan'
|
| '/planes/$planId/iaplan'
|
||||||
| '/planes/$planId/mapa'
|
| '/planes/$planId/mapa'
|
||||||
| '/planes/$planId/materias'
|
| '/planes/$planId/'
|
||||||
| '/planes/$planId/asignaturas/'
|
|
||||||
| '/planes/$planId/asignaturas/nueva'
|
| '/planes/$planId/asignaturas/nueva'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
to:
|
to:
|
||||||
@@ -234,17 +211,15 @@ export interface FileRouteTypes {
|
|||||||
| '/login'
|
| '/login'
|
||||||
| '/planes'
|
| '/planes'
|
||||||
| '/demo/tanstack-query'
|
| '/demo/tanstack-query'
|
||||||
| '/planes/$planId'
|
| '/planes/$planId/asignaturas'
|
||||||
| '/planes/nuevo'
|
| '/planes/nuevo'
|
||||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||||
| '/planes/$planId/asignaturas'
|
|
||||||
| '/planes/$planId/datos'
|
|
||||||
| '/planes/$planId/documento'
|
| '/planes/$planId/documento'
|
||||||
| '/planes/$planId/flujo'
|
| '/planes/$planId/flujo'
|
||||||
| '/planes/$planId/historial'
|
| '/planes/$planId/historial'
|
||||||
| '/planes/$planId/iaplan'
|
| '/planes/$planId/iaplan'
|
||||||
| '/planes/$planId/mapa'
|
| '/planes/$planId/mapa'
|
||||||
| '/planes/$planId/materias'
|
| '/planes/$planId'
|
||||||
| '/planes/$planId/asignaturas/nueva'
|
| '/planes/$planId/asignaturas/nueva'
|
||||||
id:
|
id:
|
||||||
| '__root__'
|
| '__root__'
|
||||||
@@ -256,17 +231,15 @@ export interface FileRouteTypes {
|
|||||||
| '/planes/$planId/_detalle'
|
| '/planes/$planId/_detalle'
|
||||||
| '/planes/$planId/asignaturas'
|
| '/planes/$planId/asignaturas'
|
||||||
| '/planes/_lista/nuevo'
|
| '/planes/_lista/nuevo'
|
||||||
| '/planes/$planId/'
|
|
||||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||||
| '/planes/$planId/asignaturas/_lista'
|
| '/planes/$planId/asignaturas/_lista'
|
||||||
| '/planes/$planId/_detalle/datos'
|
| '/planes/$planId/_detalle/asignaturas'
|
||||||
| '/planes/$planId/_detalle/documento'
|
| '/planes/$planId/_detalle/documento'
|
||||||
| '/planes/$planId/_detalle/flujo'
|
| '/planes/$planId/_detalle/flujo'
|
||||||
| '/planes/$planId/_detalle/historial'
|
| '/planes/$planId/_detalle/historial'
|
||||||
| '/planes/$planId/_detalle/iaplan'
|
| '/planes/$planId/_detalle/iaplan'
|
||||||
| '/planes/$planId/_detalle/mapa'
|
| '/planes/$planId/_detalle/mapa'
|
||||||
| '/planes/$planId/_detalle/materias'
|
| '/planes/$planId/_detalle/'
|
||||||
| '/planes/$planId/asignaturas/'
|
|
||||||
| '/planes/$planId/asignaturas/_lista/nueva'
|
| '/planes/$planId/asignaturas/_lista/nueva'
|
||||||
fileRoutesById: FileRoutesById
|
fileRoutesById: FileRoutesById
|
||||||
}
|
}
|
||||||
@@ -278,7 +251,6 @@ export interface RootRouteChildren {
|
|||||||
DemoTanstackQueryRoute: typeof DemoTanstackQueryRoute
|
DemoTanstackQueryRoute: typeof DemoTanstackQueryRoute
|
||||||
PlanesPlanIdDetalleRouteRoute: typeof PlanesPlanIdDetalleRouteRouteWithChildren
|
PlanesPlanIdDetalleRouteRoute: typeof PlanesPlanIdDetalleRouteRouteWithChildren
|
||||||
PlanesPlanIdAsignaturasRouteRoute: typeof PlanesPlanIdAsignaturasRouteRouteWithChildren
|
PlanesPlanIdAsignaturasRouteRoute: typeof PlanesPlanIdAsignaturasRouteRouteWithChildren
|
||||||
PlanesPlanIdIndexRoute: typeof PlanesPlanIdIndexRoute
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@tanstack/react-router' {
|
declare module '@tanstack/react-router' {
|
||||||
@@ -318,25 +290,6 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof PlanesListaRouteRouteImport
|
preLoaderRoute: typeof PlanesListaRouteRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
'/planes/$planId/': {
|
|
||||||
id: '/planes/$planId/'
|
|
||||||
path: '/planes/$planId'
|
|
||||||
<<<<<<< HEAD
|
|
||||||
fullPath: '/planes/$planId/'
|
|
||||||
=======
|
|
||||||
<<<<<<< HEAD
|
|
||||||
<<<<<<< HEAD
|
|
||||||
fullPath: '/planes/$planId/'
|
|
||||||
=======
|
|
||||||
fullPath: '/planes/$planId'
|
|
||||||
>>>>>>> 4950f7efbf664bbd31ac8a673fe594af5baf07f6
|
|
||||||
=======
|
|
||||||
fullPath: '/planes/$planId/'
|
|
||||||
>>>>>>> cbe4e54 (Se cierran incidencias #10, #21, #24, #25; se añade generación manual de planes)
|
|
||||||
>>>>>>> 9584cd0c048cf1f4477a4db80947de38e6c75632
|
|
||||||
preLoaderRoute: typeof PlanesPlanIdIndexRouteImport
|
|
||||||
parentRoute: typeof rootRouteImport
|
|
||||||
}
|
|
||||||
'/planes/_lista/nuevo': {
|
'/planes/_lista/nuevo': {
|
||||||
id: '/planes/_lista/nuevo'
|
id: '/planes/_lista/nuevo'
|
||||||
path: '/nuevo'
|
path: '/nuevo'
|
||||||
@@ -358,18 +311,11 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof PlanesPlanIdDetalleRouteRouteImport
|
preLoaderRoute: typeof PlanesPlanIdDetalleRouteRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
'/planes/$planId/asignaturas/': {
|
'/planes/$planId/_detalle/': {
|
||||||
id: '/planes/$planId/asignaturas/'
|
id: '/planes/$planId/_detalle/'
|
||||||
path: '/'
|
path: '/'
|
||||||
fullPath: '/planes/$planId/asignaturas/'
|
fullPath: '/planes/$planId/'
|
||||||
preLoaderRoute: typeof PlanesPlanIdAsignaturasIndexRouteImport
|
preLoaderRoute: typeof PlanesPlanIdDetalleIndexRouteImport
|
||||||
parentRoute: typeof PlanesPlanIdAsignaturasRouteRoute
|
|
||||||
}
|
|
||||||
'/planes/$planId/_detalle/materias': {
|
|
||||||
id: '/planes/$planId/_detalle/materias'
|
|
||||||
path: '/materias'
|
|
||||||
fullPath: '/planes/$planId/materias'
|
|
||||||
preLoaderRoute: typeof PlanesPlanIdDetalleMateriasRouteImport
|
|
||||||
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
||||||
}
|
}
|
||||||
'/planes/$planId/_detalle/mapa': {
|
'/planes/$planId/_detalle/mapa': {
|
||||||
@@ -407,11 +353,11 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof PlanesPlanIdDetalleDocumentoRouteImport
|
preLoaderRoute: typeof PlanesPlanIdDetalleDocumentoRouteImport
|
||||||
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
||||||
}
|
}
|
||||||
'/planes/$planId/_detalle/datos': {
|
'/planes/$planId/_detalle/asignaturas': {
|
||||||
id: '/planes/$planId/_detalle/datos'
|
id: '/planes/$planId/_detalle/asignaturas'
|
||||||
path: '/datos'
|
path: '/asignaturas'
|
||||||
fullPath: '/planes/$planId/datos'
|
fullPath: '/planes/$planId/asignaturas'
|
||||||
preLoaderRoute: typeof PlanesPlanIdDetalleDatosRouteImport
|
preLoaderRoute: typeof PlanesPlanIdDetalleAsignaturasRouteImport
|
||||||
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
||||||
}
|
}
|
||||||
'/planes/$planId/asignaturas/_lista': {
|
'/planes/$planId/asignaturas/_lista': {
|
||||||
@@ -450,24 +396,24 @@ const PlanesListaRouteRouteWithChildren =
|
|||||||
PlanesListaRouteRoute._addFileChildren(PlanesListaRouteRouteChildren)
|
PlanesListaRouteRoute._addFileChildren(PlanesListaRouteRouteChildren)
|
||||||
|
|
||||||
interface PlanesPlanIdDetalleRouteRouteChildren {
|
interface PlanesPlanIdDetalleRouteRouteChildren {
|
||||||
PlanesPlanIdDetalleDatosRoute: typeof PlanesPlanIdDetalleDatosRoute
|
PlanesPlanIdDetalleAsignaturasRoute: typeof PlanesPlanIdDetalleAsignaturasRoute
|
||||||
PlanesPlanIdDetalleDocumentoRoute: typeof PlanesPlanIdDetalleDocumentoRoute
|
PlanesPlanIdDetalleDocumentoRoute: typeof PlanesPlanIdDetalleDocumentoRoute
|
||||||
PlanesPlanIdDetalleFlujoRoute: typeof PlanesPlanIdDetalleFlujoRoute
|
PlanesPlanIdDetalleFlujoRoute: typeof PlanesPlanIdDetalleFlujoRoute
|
||||||
PlanesPlanIdDetalleHistorialRoute: typeof PlanesPlanIdDetalleHistorialRoute
|
PlanesPlanIdDetalleHistorialRoute: typeof PlanesPlanIdDetalleHistorialRoute
|
||||||
PlanesPlanIdDetalleIaplanRoute: typeof PlanesPlanIdDetalleIaplanRoute
|
PlanesPlanIdDetalleIaplanRoute: typeof PlanesPlanIdDetalleIaplanRoute
|
||||||
PlanesPlanIdDetalleMapaRoute: typeof PlanesPlanIdDetalleMapaRoute
|
PlanesPlanIdDetalleMapaRoute: typeof PlanesPlanIdDetalleMapaRoute
|
||||||
PlanesPlanIdDetalleMateriasRoute: typeof PlanesPlanIdDetalleMateriasRoute
|
PlanesPlanIdDetalleIndexRoute: typeof PlanesPlanIdDetalleIndexRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlanesPlanIdDetalleRouteRouteChildren: PlanesPlanIdDetalleRouteRouteChildren =
|
const PlanesPlanIdDetalleRouteRouteChildren: PlanesPlanIdDetalleRouteRouteChildren =
|
||||||
{
|
{
|
||||||
PlanesPlanIdDetalleDatosRoute: PlanesPlanIdDetalleDatosRoute,
|
PlanesPlanIdDetalleAsignaturasRoute: PlanesPlanIdDetalleAsignaturasRoute,
|
||||||
PlanesPlanIdDetalleDocumentoRoute: PlanesPlanIdDetalleDocumentoRoute,
|
PlanesPlanIdDetalleDocumentoRoute: PlanesPlanIdDetalleDocumentoRoute,
|
||||||
PlanesPlanIdDetalleFlujoRoute: PlanesPlanIdDetalleFlujoRoute,
|
PlanesPlanIdDetalleFlujoRoute: PlanesPlanIdDetalleFlujoRoute,
|
||||||
PlanesPlanIdDetalleHistorialRoute: PlanesPlanIdDetalleHistorialRoute,
|
PlanesPlanIdDetalleHistorialRoute: PlanesPlanIdDetalleHistorialRoute,
|
||||||
PlanesPlanIdDetalleIaplanRoute: PlanesPlanIdDetalleIaplanRoute,
|
PlanesPlanIdDetalleIaplanRoute: PlanesPlanIdDetalleIaplanRoute,
|
||||||
PlanesPlanIdDetalleMapaRoute: PlanesPlanIdDetalleMapaRoute,
|
PlanesPlanIdDetalleMapaRoute: PlanesPlanIdDetalleMapaRoute,
|
||||||
PlanesPlanIdDetalleMateriasRoute: PlanesPlanIdDetalleMateriasRoute,
|
PlanesPlanIdDetalleIndexRoute: PlanesPlanIdDetalleIndexRoute,
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlanesPlanIdDetalleRouteRouteWithChildren =
|
const PlanesPlanIdDetalleRouteRouteWithChildren =
|
||||||
@@ -493,7 +439,6 @@ const PlanesPlanIdAsignaturasListaRouteRouteWithChildren =
|
|||||||
interface PlanesPlanIdAsignaturasRouteRouteChildren {
|
interface PlanesPlanIdAsignaturasRouteRouteChildren {
|
||||||
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute: typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute: typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||||
PlanesPlanIdAsignaturasListaRouteRoute: typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
PlanesPlanIdAsignaturasListaRouteRoute: typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
||||||
PlanesPlanIdAsignaturasIndexRoute: typeof PlanesPlanIdAsignaturasIndexRoute
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlanesPlanIdAsignaturasRouteRouteChildren: PlanesPlanIdAsignaturasRouteRouteChildren =
|
const PlanesPlanIdAsignaturasRouteRouteChildren: PlanesPlanIdAsignaturasRouteRouteChildren =
|
||||||
@@ -502,7 +447,6 @@ const PlanesPlanIdAsignaturasRouteRouteChildren: PlanesPlanIdAsignaturasRouteRou
|
|||||||
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute,
|
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute,
|
||||||
PlanesPlanIdAsignaturasListaRouteRoute:
|
PlanesPlanIdAsignaturasListaRouteRoute:
|
||||||
PlanesPlanIdAsignaturasListaRouteRouteWithChildren,
|
PlanesPlanIdAsignaturasListaRouteRouteWithChildren,
|
||||||
PlanesPlanIdAsignaturasIndexRoute: PlanesPlanIdAsignaturasIndexRoute,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlanesPlanIdAsignaturasRouteRouteWithChildren =
|
const PlanesPlanIdAsignaturasRouteRouteWithChildren =
|
||||||
@@ -519,7 +463,6 @@ const rootRouteChildren: RootRouteChildren = {
|
|||||||
PlanesPlanIdDetalleRouteRoute: PlanesPlanIdDetalleRouteRouteWithChildren,
|
PlanesPlanIdDetalleRouteRoute: PlanesPlanIdDetalleRouteRouteWithChildren,
|
||||||
PlanesPlanIdAsignaturasRouteRoute:
|
PlanesPlanIdAsignaturasRouteRoute:
|
||||||
PlanesPlanIdAsignaturasRouteRouteWithChildren,
|
PlanesPlanIdAsignaturasRouteRouteWithChildren,
|
||||||
PlanesPlanIdIndexRoute: PlanesPlanIdIndexRoute,
|
|
||||||
}
|
}
|
||||||
export const routeTree = rootRouteImport
|
export const routeTree = rootRouteImport
|
||||||
._addFileChildren(rootRouteChildren)
|
._addFileChildren(rootRouteChildren)
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import TanStackQueryDevtools from '../integrations/tanstack-query/devtools'
|
|||||||
|
|
||||||
import type { QueryClient } from '@tanstack/react-query'
|
import type { QueryClient } from '@tanstack/react-query'
|
||||||
|
|
||||||
|
import { NotFoundPage } from '@/components/ui/NotFoundPage'
|
||||||
|
|
||||||
interface MyRouterContext {
|
interface MyRouterContext {
|
||||||
queryClient: QueryClient
|
queryClient: QueryClient
|
||||||
}
|
}
|
||||||
@@ -31,6 +33,8 @@ export const Route = createRootRouteWithContext<MyRouterContext>()({
|
|||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
|
||||||
|
notFoundComponent: () => <NotFoundPage />,
|
||||||
|
|
||||||
errorComponent: ({ error, reset }) => {
|
errorComponent: ({ error, reset }) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-[50vh] flex-col items-center justify-center space-y-4 p-6 text-center">
|
<div className="flex min-h-[50vh] flex-col items-center justify-center space-y-4 p-6 text-center">
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ const mapAsignaturas = (asigApi: Array<any> = []): Array<Materia> => {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Route = createFileRoute('/planes/$planId/_detalle/materias')({
|
export const Route = createFileRoute('/planes/$planId/_detalle/asignaturas')({
|
||||||
component: MateriasPage,
|
component: MateriasPage,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ function MateriasPage() {
|
|||||||
|
|
||||||
{/* Barra de Filtros Avanzada */}
|
{/* Barra de Filtros Avanzada */}
|
||||||
<div className="flex flex-wrap items-center gap-3 rounded-xl border bg-slate-50 p-4">
|
<div className="flex flex-wrap items-center gap-3 rounded-xl border bg-slate-50 p-4">
|
||||||
<div className="relative min-w-[240px] flex-1">
|
<div className="relative min-w-60 flex-1">
|
||||||
<Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
|
<Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
|
||||||
<Input
|
<Input
|
||||||
placeholder="Buscar por nombre o clave..."
|
placeholder="Buscar por nombre o clave..."
|
||||||
@@ -153,7 +153,7 @@ function MateriasPage() {
|
|||||||
<Filter className="text-muted-foreground mr-1 h-4 w-4" />
|
<Filter className="text-muted-foreground mr-1 h-4 w-4" />
|
||||||
|
|
||||||
<Select value={filterTipo} onValueChange={setFilterTipo}>
|
<Select value={filterTipo} onValueChange={setFilterTipo}>
|
||||||
<SelectTrigger className="w-[140px] bg-white">
|
<SelectTrigger className="w-35 bg-white">
|
||||||
<SelectValue placeholder="Tipo" />
|
<SelectValue placeholder="Tipo" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -164,7 +164,7 @@ function MateriasPage() {
|
|||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<Select value={filterEstado} onValueChange={setFilterEstado}>
|
<Select value={filterEstado} onValueChange={setFilterEstado}>
|
||||||
<SelectTrigger className="w-[140px] bg-white">
|
<SelectTrigger className="w-35 bg-white">
|
||||||
<SelectValue placeholder="Estado" />
|
<SelectValue placeholder="Estado" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -176,7 +176,7 @@ function MateriasPage() {
|
|||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<Select value={filterLinea} onValueChange={setFilterLinea}>
|
<Select value={filterLinea} onValueChange={setFilterLinea}>
|
||||||
<SelectTrigger className="w-[180px] bg-white">
|
<SelectTrigger className="w-45 bg-white">
|
||||||
<SelectValue placeholder="Línea" />
|
<SelectValue placeholder="Línea" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -196,14 +196,14 @@ function MateriasPage() {
|
|||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow className="bg-slate-50/50">
|
<TableRow className="bg-slate-50/50">
|
||||||
<TableHead className="w-[120px]">Clave</TableHead>
|
<TableHead className="w-30">Clave</TableHead>
|
||||||
<TableHead>Nombre</TableHead>
|
<TableHead>Nombre</TableHead>
|
||||||
<TableHead className="text-center">Créditos</TableHead>
|
<TableHead className="text-center">Créditos</TableHead>
|
||||||
<TableHead className="text-center">Ciclo</TableHead>
|
<TableHead className="text-center">Ciclo</TableHead>
|
||||||
<TableHead>Línea Curricular</TableHead>
|
<TableHead>Línea Curricular</TableHead>
|
||||||
<TableHead>Tipo</TableHead>
|
<TableHead>Tipo</TableHead>
|
||||||
<TableHead>Estado</TableHead>
|
<TableHead>Estado</TableHead>
|
||||||
<TableHead className="w-[50px]"></TableHead>
|
<TableHead className="w-12.5"></TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
import { usePlan } from '@/data'
|
import { usePlan } from '@/data'
|
||||||
|
|
||||||
// import { toast } from 'sonner' // Asegúrate de tener sonner instalado o quita la línea
|
// import { toast } from 'sonner' // Asegúrate de tener sonner instalado o quita la línea
|
||||||
export const Route = createFileRoute('/planes/$planId/_detalle/datos')({
|
export const Route = createFileRoute('/planes/$planId/_detalle/')({
|
||||||
component: DatosGeneralesPage,
|
component: DatosGeneralesPage,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -204,8 +204,8 @@ function DatosGeneralesPage() {
|
|||||||
<Textarea
|
<Textarea
|
||||||
value={editValue}
|
value={editValue}
|
||||||
onChange={(e) => setEditValue(e.target.value)}
|
onChange={(e) => setEditValue(e.target.value)}
|
||||||
className="min-h-[120px]"
|
className="placeholder:text-muted-foreground/70 min-h-30 not-italic placeholder:italic"
|
||||||
placeholder={campo.holder}
|
placeholder={`Ej. ${campo.holder[0] as string}`}
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-end gap-2">
|
<div className="flex justify-end gap-2">
|
||||||
<Button
|
<Button
|
||||||
@@ -225,7 +225,7 @@ function DatosGeneralesPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="min-h-[100px]">
|
<div className="min-h-25">
|
||||||
{campo.value ? (
|
{campo.value ? (
|
||||||
<div className="text-sm leading-relaxed text-slate-600">
|
<div className="text-sm leading-relaxed text-slate-600">
|
||||||
{campo.tipo === 'lista' ? (
|
{campo.tipo === 'lista' ? (
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createFileRoute, Outlet, Link } from '@tanstack/react-router'
|
import { createFileRoute, Outlet, Link, notFound } from '@tanstack/react-router'
|
||||||
import {
|
import {
|
||||||
ChevronLeft,
|
ChevronLeft,
|
||||||
GraduationCap,
|
GraduationCap,
|
||||||
@@ -17,10 +17,37 @@ import {
|
|||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '@/components/ui/dropdown-menu'
|
} from '@/components/ui/dropdown-menu'
|
||||||
|
import { NotFoundPage } from '@/components/ui/NotFoundPage'
|
||||||
import { Skeleton } from '@/components/ui/skeleton'
|
import { Skeleton } from '@/components/ui/skeleton'
|
||||||
|
import { plans_get } from '@/data/api/plans.api'
|
||||||
import { usePlan } from '@/data/hooks/usePlans'
|
import { usePlan } from '@/data/hooks/usePlans'
|
||||||
|
import { qk } from '@/data/query/keys'
|
||||||
|
|
||||||
export const Route = createFileRoute('/planes/$planId/_detalle')({
|
export const Route = createFileRoute('/planes/$planId/_detalle')({
|
||||||
|
loader: async ({ context: { queryClient }, params: { planId } }) => {
|
||||||
|
try {
|
||||||
|
console.log('loader')
|
||||||
|
|
||||||
|
await queryClient.ensureQueryData({
|
||||||
|
queryKey: qk.plan(planId),
|
||||||
|
queryFn: () => plans_get(planId),
|
||||||
|
})
|
||||||
|
} catch (e: any) {
|
||||||
|
// PGRST116: The result contains 0 rows
|
||||||
|
if (e?.code === 'PGRST116') {
|
||||||
|
throw notFound()
|
||||||
|
}
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
},
|
||||||
|
notFoundComponent: () => {
|
||||||
|
return (
|
||||||
|
<NotFoundPage
|
||||||
|
title="Plan de Estudios no encontrado"
|
||||||
|
message="El plan de estudios que intentas consultar no existe o no tienes permisos para verlo."
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
component: RouteComponent,
|
component: RouteComponent,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -86,11 +113,11 @@ function RouteComponent() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mx-auto max-w-[1600px] space-y-8 p-8">
|
<div className="mx-auto max-w-400 space-y-8 p-8">
|
||||||
{/* Header del Plan */}
|
{/* Header del Plan */}
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
/* ===== SKELETON ===== */
|
/* ===== SKELETON ===== */
|
||||||
<div className="mx-auto max-w-[1600px] p-8">
|
<div className="mx-auto max-w-400 p-8">
|
||||||
<div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
<div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
||||||
{Array.from({ length: 6 }).map((_, i) => (
|
{Array.from({ length: 6 }).map((_, i) => (
|
||||||
<DatosGeneralesSkeleton key={i} />
|
<DatosGeneralesSkeleton key={i} />
|
||||||
@@ -189,13 +216,13 @@ function RouteComponent() {
|
|||||||
{/* 4. Navegación de Tabs */}
|
{/* 4. Navegación de Tabs */}
|
||||||
<div className="scrollbar-hide overflow-x-auto border-b">
|
<div className="scrollbar-hide overflow-x-auto border-b">
|
||||||
<nav className="flex min-w-max gap-8">
|
<nav className="flex min-w-max gap-8">
|
||||||
<Tab to="/planes/$planId/datos" params={{ planId }}>
|
<Tab to="/planes/$planId/" params={{ planId }}>
|
||||||
Datos Generales
|
Datos Generales
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab to="/planes/$planId/mapa" params={{ planId }}>
|
<Tab to="/planes/$planId/mapa" params={{ planId }}>
|
||||||
Mapa Curricular
|
Mapa Curricular
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab to="/planes/$planId/materias" params={{ planId }}>
|
<Tab to="/planes/$planId/asignaturas" params={{ planId }}>
|
||||||
Materias
|
Materias
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab to="/planes/$planId/flujo" params={{ planId }}>
|
<Tab to="/planes/$planId/flujo" params={{ planId }}>
|
||||||
@@ -237,7 +264,7 @@ const InfoCard = forwardRef<
|
|||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
{...props}
|
{...props}
|
||||||
className={`flex h-[72px] w-full items-center gap-4 rounded-xl border border-slate-200/60 bg-slate-50/50 p-4 shadow-sm transition-all ${
|
className={`flex h-18 w-full items-center gap-4 rounded-xl border border-slate-200/60 bg-slate-50/50 p-4 shadow-sm transition-all ${
|
||||||
isEditable
|
isEditable
|
||||||
? 'cursor-pointer hover:border-teal-200 hover:bg-white focus:outline-none focus-visible:ring-2 focus-visible:ring-teal-500/40'
|
? 'cursor-pointer hover:border-teal-200 hover:bg-white focus:outline-none focus-visible:ring-2 focus-visible:ring-teal-500/40'
|
||||||
: ''
|
: ''
|
||||||
@@ -273,6 +300,9 @@ function Tab({
|
|||||||
params={params}
|
params={params}
|
||||||
className="border-b-2 border-transparent pb-3 text-sm font-medium text-slate-500 transition-all hover:text-slate-800"
|
className="border-b-2 border-transparent pb-3 text-sm font-medium text-slate-500 transition-all hover:text-slate-800"
|
||||||
activeProps={{ className: 'border-teal-600 text-teal-700 font-bold' }}
|
activeProps={{ className: 'border-teal-600 text-teal-700 font-bold' }}
|
||||||
|
activeOptions={{
|
||||||
|
exact: true,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
import { createFileRoute, redirect } from '@tanstack/react-router'
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/planes/$planId/asignaturas/')({
|
|
||||||
beforeLoad: ({ params }) => {
|
|
||||||
throw redirect({
|
|
||||||
to: '/planes/$planId/materias',
|
|
||||||
params,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -1,6 +1,31 @@
|
|||||||
import { createFileRoute, Outlet } from '@tanstack/react-router'
|
import { createFileRoute, Outlet, notFound } from '@tanstack/react-router'
|
||||||
|
|
||||||
|
import { NotFoundPage } from '@/components/ui/NotFoundPage'
|
||||||
|
import { plans_get } from '@/data/api/plans.api'
|
||||||
|
import { qk } from '@/data/query/keys'
|
||||||
|
|
||||||
export const Route = createFileRoute('/planes/$planId/asignaturas')({
|
export const Route = createFileRoute('/planes/$planId/asignaturas')({
|
||||||
|
loader: async ({ context: { queryClient }, params: { planId } }) => {
|
||||||
|
try {
|
||||||
|
await queryClient.ensureQueryData({
|
||||||
|
queryKey: qk.plan(planId),
|
||||||
|
queryFn: () => plans_get(planId),
|
||||||
|
})
|
||||||
|
} catch (e: any) {
|
||||||
|
if (e?.code === 'PGRST116') {
|
||||||
|
throw notFound()
|
||||||
|
}
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
},
|
||||||
|
notFoundComponent: () => {
|
||||||
|
return (
|
||||||
|
<NotFoundPage
|
||||||
|
title="Plan de Estudios no encontrado"
|
||||||
|
message="El plan de estudios que intentas consultar no existe o no tienes permisos para verlo."
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
component: AsignaturasLayout,
|
component: AsignaturasLayout,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
import { createFileRoute, redirect } from '@tanstack/react-router'
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/planes/$planId/')({
|
|
||||||
beforeLoad: ({ params }) => {
|
|
||||||
throw redirect({
|
|
||||||
to: '/planes/$planId/materias',
|
|
||||||
params,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
Reference in New Issue
Block a user