Compare commits
2 Commits
main
...
729051ff87
| Author | SHA1 | Date | |
|---|---|---|---|
| 729051ff87 | |||
| 4be8d5d426 |
@@ -451,7 +451,7 @@ function DatosGenerales({
|
||||
!valActual?.description ||
|
||||
valActual.description === config.description
|
||||
|
||||
const currentContent = valActual.description ?? ''
|
||||
const currentContent = valActual?.description ?? ''
|
||||
|
||||
return (
|
||||
<InfoCard
|
||||
@@ -654,9 +654,7 @@ function InfoCard({
|
||||
(data ? (
|
||||
<p className="whitespace-pre-wrap">{data}</p>
|
||||
) : (
|
||||
<p className="text-slate-400 italic">
|
||||
Sin información. Ejemplo: {placeholder}
|
||||
</p>
|
||||
<p className="text-slate-400 italic">Sin información.</p>
|
||||
))}
|
||||
{type === 'requirements' && <RequirementsView items={data} />}
|
||||
{type === 'evaluation' && <EvaluationView items={data} />}
|
||||
|
||||
@@ -23,43 +23,41 @@ export function WizardControls({
|
||||
const isLast = idx >= Wizard.steps.length - 1
|
||||
|
||||
return (
|
||||
<div className="flex-none border-t bg-white p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1">
|
||||
{wizard.errorMessage && (
|
||||
<span className="text-destructive text-sm font-medium">
|
||||
{wizard.errorMessage}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1">
|
||||
{wizard.errorMessage && (
|
||||
<span className="text-destructive text-sm font-medium">
|
||||
{wizard.errorMessage}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4">
|
||||
<div className="flex gap-4">
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => methods.prev()}
|
||||
disabled={idx === 0 || wizard.isLoading}
|
||||
>
|
||||
Anterior
|
||||
</Button>
|
||||
|
||||
{!isLast ? (
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => methods.prev()}
|
||||
disabled={idx === 0 || wizard.isLoading}
|
||||
onClick={() => methods.next()}
|
||||
disabled={
|
||||
wizard.isLoading ||
|
||||
(idx === 0 && !canContinueDesdeMetodo) ||
|
||||
(idx === 1 && !canContinueDesdeBasicos) ||
|
||||
(idx === 2 && !canContinueDesdeConfig)
|
||||
}
|
||||
>
|
||||
Anterior
|
||||
Siguiente
|
||||
</Button>
|
||||
|
||||
{!isLast ? (
|
||||
<Button
|
||||
onClick={() => methods.next()}
|
||||
disabled={
|
||||
wizard.isLoading ||
|
||||
(idx === 0 && !canContinueDesdeMetodo) ||
|
||||
(idx === 1 && !canContinueDesdeBasicos) ||
|
||||
(idx === 2 && !canContinueDesdeConfig)
|
||||
}
|
||||
>
|
||||
Siguiente
|
||||
</Button>
|
||||
) : (
|
||||
<Button onClick={onCreate} disabled={wizard.isLoading}>
|
||||
{wizard.isLoading ? 'Creando...' : 'Crear Asignatura'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Button onClick={onCreate} disabled={wizard.isLoading}>
|
||||
{wizard.isLoading ? 'Creando...' : 'Crear Asignatura'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
41
src/components/wizard/StepWithTooltip.tsx
Normal file
41
src/components/wizard/StepWithTooltip.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { useState } from 'react'
|
||||
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip'
|
||||
|
||||
export function StepWithTooltip({
|
||||
title,
|
||||
desc,
|
||||
}: {
|
||||
title: string
|
||||
desc: string
|
||||
}) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
return (
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip open={isOpen} onOpenChange={setIsOpen}>
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
className="cursor-help decoration-dotted underline-offset-4 hover:underline"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setIsOpen((prev) => !prev)
|
||||
}}
|
||||
onMouseEnter={() => setIsOpen(true)}
|
||||
onMouseLeave={() => setIsOpen(false)}
|
||||
>
|
||||
{title}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-50 text-xs">
|
||||
<p>{desc}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
)
|
||||
}
|
||||
52
src/components/wizard/WizardLayout.tsx
Normal file
52
src/components/wizard/WizardLayout.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import * as Icons from 'lucide-react'
|
||||
|
||||
import { CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Dialog, DialogContent } from '@/components/ui/dialog'
|
||||
|
||||
export function WizardLayout({
|
||||
title,
|
||||
onClose,
|
||||
headerSlot,
|
||||
footerSlot,
|
||||
children,
|
||||
}: {
|
||||
title: string
|
||||
onClose: () => void
|
||||
headerSlot?: React.ReactNode
|
||||
footerSlot?: React.ReactNode
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<Dialog open={true} onOpenChange={(open) => !open && onClose()}>
|
||||
<DialogContent
|
||||
className="flex h-[90vh] w-[calc(100%-2rem)] flex-col gap-0 overflow-hidden p-0 sm:max-w-4xl"
|
||||
onInteractOutside={(e) => {
|
||||
e.preventDefault()
|
||||
}}
|
||||
>
|
||||
<div className="z-10 flex-none border-b bg-white">
|
||||
<CardHeader className="flex flex-row items-center justify-between gap-4 p-6 pb-4">
|
||||
<CardTitle>{title}</CardTitle>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none"
|
||||
>
|
||||
<Icons.X className="h-4 w-4" />
|
||||
<span className="sr-only">Cerrar</span>
|
||||
</button>
|
||||
</CardHeader>
|
||||
|
||||
{headerSlot ? <div className="px-6 pb-6">{headerSlot}</div> : null}
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-y-auto bg-gray-50/30 p-6">
|
||||
{children}
|
||||
</div>
|
||||
|
||||
{footerSlot ? (
|
||||
<div className="flex-none border-t bg-white p-6">{footerSlot}</div>
|
||||
) : null}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
59
src/components/wizard/WizardResponsiveHeader.tsx
Normal file
59
src/components/wizard/WizardResponsiveHeader.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import { CircularProgress } from '@/components/CircularProgress'
|
||||
import { StepWithTooltip } from '@/components/wizard/StepWithTooltip'
|
||||
|
||||
export function WizardResponsiveHeader({
|
||||
wizard,
|
||||
methods,
|
||||
}: {
|
||||
wizard: any
|
||||
methods: any
|
||||
}) {
|
||||
const idx = wizard.utils.getIndex(methods.current.id)
|
||||
const totalSteps = wizard.steps.length
|
||||
const currentIndex = idx + 1
|
||||
const hasNextStep = idx < totalSteps - 1
|
||||
const nextStep = wizard.steps[currentIndex]
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="block sm:hidden">
|
||||
<div className="flex items-center gap-5">
|
||||
<CircularProgress current={currentIndex} total={totalSteps} />
|
||||
<div className="flex flex-col justify-center">
|
||||
<h2 className="text-lg font-bold text-slate-900">
|
||||
<StepWithTooltip
|
||||
title={methods.current.title}
|
||||
desc={methods.current.description}
|
||||
/>
|
||||
</h2>
|
||||
{hasNextStep && nextStep ? (
|
||||
<p className="text-sm text-slate-400">
|
||||
Siguiente: {nextStep.title}
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-sm font-medium text-green-500">
|
||||
¡Último paso!
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="hidden sm:block">
|
||||
<wizard.Stepper.Navigation className="border-border/60 rounded-xl border bg-slate-50 p-2">
|
||||
{wizard.steps.map((step: any) => (
|
||||
<wizard.Stepper.Step
|
||||
key={step.id}
|
||||
of={step.id}
|
||||
className="whitespace-nowrap"
|
||||
>
|
||||
<wizard.Stepper.Title>
|
||||
<StepWithTooltip title={step.title} desc={step.description} />
|
||||
</wizard.Stepper.Title>
|
||||
</wizard.Stepper.Step>
|
||||
))}
|
||||
</wizard.Stepper.Navigation>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,31 +1,33 @@
|
||||
export const qk = {
|
||||
auth: ["auth"] as const,
|
||||
session: () => ["auth", "session"] as const,
|
||||
meProfile: () => ["auth", "meProfile"] as const,
|
||||
auth: ['auth'] as const,
|
||||
session: () => ['auth', 'session'] as const,
|
||||
meProfile: () => ['auth', 'meProfile'] as const,
|
||||
|
||||
facultades: () => ["meta", "facultades"] as const,
|
||||
facultades: () => ['meta', 'facultades'] as const,
|
||||
carreras: (facultadId?: string | null) =>
|
||||
["meta", "carreras", { facultadId: facultadId ?? null }] as const,
|
||||
['meta', 'carreras', { facultadId: facultadId ?? null }] as const,
|
||||
estructurasPlan: (nivel?: string | null) =>
|
||||
["meta", "estructurasPlan", { nivel: nivel ?? null }] as const,
|
||||
estructurasAsignatura: () => ["meta", "estructurasAsignatura"] as const,
|
||||
estadosPlan: () => ["meta", "estadosPlan"] as const,
|
||||
['meta', 'estructurasPlan', { nivel: nivel ?? null }] as const,
|
||||
estructurasAsignatura: () => ['meta', 'estructurasAsignatura'] as const,
|
||||
estadosPlan: () => ['meta', 'estadosPlan'] as const,
|
||||
|
||||
planesList: (filters: unknown) => ["planes", "list", filters] as const,
|
||||
plan: (planId: string) => ["planes", "detail", planId] as const,
|
||||
planLineas: (planId: string) => ["planes", planId, "lineas"] as const,
|
||||
planAsignaturas: (planId: string) => ["planes", planId, "asignaturas"] as const,
|
||||
planHistorial: (planId: string) => ["planes", planId, "historial"] as const,
|
||||
planDocumento: (planId: string) => ["planes", planId, "documento"] as const,
|
||||
planesList: (filters: unknown) => ['planes', 'list', filters] as const,
|
||||
plan: (planId: string) => ['planes', 'detail', planId] as const,
|
||||
planLineas: (planId: string) => ['planes', planId, 'lineas'] as const,
|
||||
planAsignaturas: (planId: string) =>
|
||||
['planes', planId, 'asignaturas'] as const,
|
||||
planHistorial: (planId: string) => ['planes', planId, 'historial'] as const,
|
||||
planDocumento: (planId: string) => ['planes', planId, 'documento'] as const,
|
||||
|
||||
asignatura: (asignaturaId: string) => ["asignaturas", "detail", asignaturaId] as const,
|
||||
asignatura: (asignaturaId: string) =>
|
||||
['asignaturas', 'detail', asignaturaId] as const,
|
||||
asignaturaBibliografia: (asignaturaId: string) =>
|
||||
["asignaturas", asignaturaId, "bibliografia"] as const,
|
||||
['asignaturas', asignaturaId, 'bibliografia'] as const,
|
||||
asignaturaHistorial: (asignaturaId: string) =>
|
||||
["asignaturas", asignaturaId, "historial"] as const,
|
||||
['asignaturas', asignaturaId, 'historial'] as const,
|
||||
asignaturaDocumento: (asignaturaId: string) =>
|
||||
["asignaturas", asignaturaId, "documento"] as const,
|
||||
['asignaturas', asignaturaId, 'documento'] as const,
|
||||
|
||||
tareas: () => ["tareas", "mias"] as const,
|
||||
notificaciones: () => ["notificaciones", "mias"] as const,
|
||||
};
|
||||
tareas: () => ['tareas', 'mias'] as const,
|
||||
notificaciones: () => ['notificaciones', 'mias'] as const,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useNavigate } from '@tanstack/react-router'
|
||||
import * as Icons from 'lucide-react'
|
||||
|
||||
import { useNuevaAsignaturaWizard } from './hooks/useNuevaAsignaturaWizard'
|
||||
|
||||
@@ -6,11 +7,20 @@ import { PasoBasicosForm } from '@/components/asignaturas/wizard/PasoBasicosForm
|
||||
import { PasoConfiguracionPanel } from '@/components/asignaturas/wizard/PasoConfiguracionPanel'
|
||||
import { PasoMetodoCardGroup } from '@/components/asignaturas/wizard/PasoMetodoCardGroup'
|
||||
import { PasoResumenCard } from '@/components/asignaturas/wizard/PasoResumenCard'
|
||||
import { VistaSinPermisos } from '@/components/asignaturas/wizard/VistaSinPermisos'
|
||||
import { WizardControls } from '@/components/asignaturas/wizard/WizardControls'
|
||||
import { WizardHeader } from '@/components/asignaturas/wizard/WizardHeader'
|
||||
import { defineStepper } from '@/components/stepper'
|
||||
import { Dialog, DialogContent } from '@/components/ui/dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@/components/ui/card'
|
||||
import { WizardLayout } from '@/components/wizard/WizardLayout'
|
||||
import { WizardResponsiveHeader } from '@/components/wizard/WizardResponsiveHeader'
|
||||
|
||||
const auth_get_current_user_role = (): string => 'JEFE_CARRERA'
|
||||
|
||||
const Wizard = defineStepper(
|
||||
{
|
||||
@@ -24,8 +34,8 @@ const Wizard = defineStepper(
|
||||
description: 'Nombre y estructura',
|
||||
},
|
||||
{
|
||||
id: 'configuracion',
|
||||
title: 'Configuración',
|
||||
id: 'detalles',
|
||||
title: 'Detalles',
|
||||
description: 'Detalles según modo',
|
||||
},
|
||||
{
|
||||
@@ -35,8 +45,6 @@ const Wizard = defineStepper(
|
||||
},
|
||||
)
|
||||
|
||||
const auth_get_current_user_role = () => 'JEFE_CARRERA' as const
|
||||
|
||||
export function NuevaAsignaturaModalContainer({ planId }: { planId: string }) {
|
||||
const navigate = useNavigate()
|
||||
const role = auth_get_current_user_role()
|
||||
@@ -55,59 +63,46 @@ export function NuevaAsignaturaModalContainer({ planId }: { planId: string }) {
|
||||
navigate({ to: `/planes/${planId}/asignaturas`, resetScroll: false })
|
||||
}
|
||||
|
||||
if (role !== 'JEFE_CARRERA') {
|
||||
return (
|
||||
<WizardLayout title="Nueva Asignatura" onClose={handleClose}>
|
||||
<Card className="border-destructive/40">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-destructive flex items-center gap-2">
|
||||
<Icons.ShieldAlert className="h-5 w-5" />
|
||||
Sin permisos
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Solo el Jefe de Carrera puede crear asignaturas.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex justify-end">
|
||||
<Button variant="secondary" onClick={handleClose}>
|
||||
Volver
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</WizardLayout>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={true} onOpenChange={(open) => !open && handleClose()}>
|
||||
<DialogContent
|
||||
className="flex h-[90vh] w-[calc(100%-2rem)] flex-col gap-0 overflow-hidden p-0 sm:max-w-4xl"
|
||||
onInteractOutside={(e) => e.preventDefault()}
|
||||
>
|
||||
{role !== 'JEFE_CARRERA' ? (
|
||||
<VistaSinPermisos onClose={handleClose} />
|
||||
) : (
|
||||
<Wizard.Stepper.Provider
|
||||
initialStep={Wizard.utils.getFirst().id}
|
||||
className="flex h-full flex-col"
|
||||
>
|
||||
{({ methods }) => (
|
||||
<>
|
||||
<WizardHeader
|
||||
title="Nueva Asignatura"
|
||||
Wizard={Wizard}
|
||||
methods={{ ...methods, onClose: handleClose }}
|
||||
/>
|
||||
|
||||
<div className="flex-1 overflow-y-auto bg-gray-50/30 p-6">
|
||||
<div className="mx-auto max-w-3xl">
|
||||
{Wizard.utils.getIndex(methods.current.id) === 0 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoMetodoCardGroup
|
||||
wizard={wizard}
|
||||
onChange={setWizard}
|
||||
/>
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
{Wizard.utils.getIndex(methods.current.id) === 1 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoBasicosForm wizard={wizard} onChange={setWizard} />
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
{Wizard.utils.getIndex(methods.current.id) === 2 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoConfiguracionPanel
|
||||
wizard={wizard}
|
||||
onChange={setWizard}
|
||||
onGenerarIA={simularGeneracionIA}
|
||||
/>
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
{Wizard.utils.getIndex(methods.current.id) === 3 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoResumenCard wizard={wizard} />
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Wizard.Stepper.Provider
|
||||
initialStep={Wizard.utils.getFirst().id}
|
||||
className="flex h-full flex-col"
|
||||
>
|
||||
{({ methods }) => {
|
||||
const idx = Wizard.utils.getIndex(methods.current.id)
|
||||
|
||||
return (
|
||||
<WizardLayout
|
||||
title="Nueva Asignatura"
|
||||
onClose={handleClose}
|
||||
headerSlot={
|
||||
<WizardResponsiveHeader wizard={Wizard} methods={methods} />
|
||||
}
|
||||
footerSlot={
|
||||
<Wizard.Stepper.Controls>
|
||||
<WizardControls
|
||||
Wizard={Wizard}
|
||||
methods={methods}
|
||||
@@ -117,11 +112,41 @@ export function NuevaAsignaturaModalContainer({ planId }: { planId: string }) {
|
||||
canContinueDesdeConfig={canContinueDesdeConfig}
|
||||
onCreate={() => crearAsignatura(handleClose)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Wizard.Stepper.Provider>
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</Wizard.Stepper.Controls>
|
||||
}
|
||||
>
|
||||
<div className="mx-auto max-w-3xl">
|
||||
{idx === 0 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoMetodoCardGroup wizard={wizard} onChange={setWizard} />
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
|
||||
{idx === 1 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoBasicosForm wizard={wizard} onChange={setWizard} />
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
|
||||
{idx === 2 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoConfiguracionPanel
|
||||
wizard={wizard}
|
||||
onChange={setWizard}
|
||||
onGenerarIA={simularGeneracionIA}
|
||||
/>
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
|
||||
{idx === 3 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoResumenCard wizard={wizard} />
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
</div>
|
||||
</WizardLayout>
|
||||
)
|
||||
}}
|
||||
</Wizard.Stepper.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import { PasoDetallesPanel } from '@/components/planes/wizard/PasoDetallesPanel/
|
||||
import { PasoModoCardGroup } from '@/components/planes/wizard/PasoModoCardGroup'
|
||||
import { PasoResumenCard } from '@/components/planes/wizard/PasoResumenCard'
|
||||
import { WizardControls } from '@/components/planes/wizard/WizardControls'
|
||||
import { WizardHeader } from '@/components/planes/wizard/WizardHeader'
|
||||
import { defineStepper } from '@/components/stepper'
|
||||
import {
|
||||
Card,
|
||||
@@ -19,16 +18,12 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@/components/ui/card'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { WizardLayout } from '@/components/wizard/WizardLayout'
|
||||
import { WizardResponsiveHeader } from '@/components/wizard/WizardResponsiveHeader'
|
||||
// import { useGeneratePlanAI } from '@/data/hooks/usePlans'
|
||||
|
||||
// Mock de permisos/rol
|
||||
const auth_get_current_user_role = () => 'JEFE_CARRERA' as const
|
||||
const auth_get_current_user_role = (): string => 'JEFE_CARRERA'
|
||||
|
||||
const Wizard = defineStepper(
|
||||
{
|
||||
@@ -64,136 +59,97 @@ export default function NuevoPlanModalContainer() {
|
||||
|
||||
// Crear plan: ahora la lógica vive en WizardControls
|
||||
|
||||
if (role !== 'JEFE_CARRERA') {
|
||||
return (
|
||||
<WizardLayout title="Nuevo plan de estudios" onClose={handleClose}>
|
||||
<Card className="border-destructive/40">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Icons.ShieldAlert className="text-destructive h-5 w-5" />
|
||||
Sin permisos
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
No tienes permisos para crear planes de estudio.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex justify-end">
|
||||
<button
|
||||
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground rounded-md border px-3 py-2 text-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none"
|
||||
onClick={handleClose}
|
||||
>
|
||||
Volver
|
||||
</button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</WizardLayout>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={true} onOpenChange={(open) => !open && handleClose()}>
|
||||
<DialogContent
|
||||
className="flex h-[90vh] w-[calc(100%-2rem)] flex-col gap-0 overflow-hidden p-0 sm:max-w-4xl"
|
||||
onInteractOutside={(e) => {
|
||||
e.preventDefault()
|
||||
}}
|
||||
>
|
||||
{role !== 'JEFE_CARRERA' ? (
|
||||
<>
|
||||
<DialogHeader className="flex-none border-b p-6">
|
||||
<DialogTitle>Nuevo plan de estudios</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="flex-1 p-6">
|
||||
<Card className="border-destructive/40">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Icons.ShieldAlert className="text-destructive h-5 w-5" />
|
||||
Sin permisos
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
No tienes permisos para crear planes de estudio.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex justify-end">
|
||||
<button
|
||||
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground rounded-md border px-3 py-2 text-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none"
|
||||
onClick={handleClose}
|
||||
>
|
||||
Volver
|
||||
</button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<Wizard.Stepper.Provider
|
||||
initialStep={Wizard.utils.getFirst().id}
|
||||
className="flex h-full flex-col"
|
||||
<Wizard.Stepper.Provider
|
||||
initialStep={Wizard.utils.getFirst().id}
|
||||
className="flex h-full flex-col"
|
||||
>
|
||||
{({ methods }) => {
|
||||
const idx = Wizard.utils.getIndex(methods.current.id)
|
||||
|
||||
return (
|
||||
<WizardLayout
|
||||
title="Nuevo plan de estudios"
|
||||
onClose={handleClose}
|
||||
headerSlot={
|
||||
<WizardResponsiveHeader wizard={Wizard} methods={methods} />
|
||||
}
|
||||
footerSlot={
|
||||
<Wizard.Stepper.Controls>
|
||||
<WizardControls
|
||||
errorMessage={wizard.errorMessage}
|
||||
onPrev={() => methods.prev()}
|
||||
onNext={() => methods.next()}
|
||||
disablePrev={idx === 0 || wizard.isLoading}
|
||||
disableNext={
|
||||
wizard.isLoading ||
|
||||
(idx === 0 && !canContinueDesdeModo) ||
|
||||
(idx === 1 && !canContinueDesdeBasicos) ||
|
||||
(idx === 2 && !canContinueDesdeDetalles)
|
||||
}
|
||||
disableCreate={wizard.isLoading}
|
||||
isLastStep={idx >= Wizard.steps.length - 1}
|
||||
wizard={wizard}
|
||||
setWizard={setWizard}
|
||||
/>
|
||||
</Wizard.Stepper.Controls>
|
||||
}
|
||||
>
|
||||
{({ methods }) => {
|
||||
const currentIndex = Wizard.utils.getIndex(methods.current.id) + 1
|
||||
const totalSteps = Wizard.steps.length
|
||||
const nextStep = Wizard.steps[currentIndex] ?? {
|
||||
title: '',
|
||||
description: '',
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<WizardHeader
|
||||
currentIndex={currentIndex}
|
||||
totalSteps={totalSteps}
|
||||
currentTitle={methods.current.title}
|
||||
currentDescription={methods.current.description}
|
||||
nextTitle={nextStep.title}
|
||||
onClose={handleClose}
|
||||
Wizard={Wizard}
|
||||
<div className="mx-auto max-w-3xl">
|
||||
{idx === 0 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoModoCardGroup wizard={wizard} onChange={setWizard} />
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
{idx === 1 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoBasicosForm wizard={wizard} onChange={setWizard} />
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
{idx === 2 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoDetallesPanel
|
||||
wizard={wizard}
|
||||
onChange={setWizard}
|
||||
isLoading={wizard.isLoading}
|
||||
/>
|
||||
|
||||
<div className="flex-1 overflow-y-auto bg-gray-50/30 p-6">
|
||||
<div className="mx-auto max-w-3xl">
|
||||
{Wizard.utils.getIndex(methods.current.id) === 0 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoModoCardGroup
|
||||
wizard={wizard}
|
||||
onChange={setWizard}
|
||||
/>
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
{Wizard.utils.getIndex(methods.current.id) === 1 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoBasicosForm
|
||||
wizard={wizard}
|
||||
onChange={setWizard}
|
||||
/>
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
{Wizard.utils.getIndex(methods.current.id) === 2 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoDetallesPanel
|
||||
wizard={wizard}
|
||||
onChange={setWizard}
|
||||
isLoading={wizard.isLoading}
|
||||
/>
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
{Wizard.utils.getIndex(methods.current.id) === 3 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoResumenCard wizard={wizard} />
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-none border-t bg-white p-6">
|
||||
<Wizard.Stepper.Controls>
|
||||
<WizardControls
|
||||
errorMessage={wizard.errorMessage}
|
||||
onPrev={() => methods.prev()}
|
||||
onNext={() => methods.next()}
|
||||
disablePrev={
|
||||
Wizard.utils.getIndex(methods.current.id) === 0 ||
|
||||
wizard.isLoading
|
||||
}
|
||||
disableNext={
|
||||
wizard.isLoading ||
|
||||
(Wizard.utils.getIndex(methods.current.id) === 0 &&
|
||||
!canContinueDesdeModo) ||
|
||||
(Wizard.utils.getIndex(methods.current.id) === 1 &&
|
||||
!canContinueDesdeBasicos) ||
|
||||
(Wizard.utils.getIndex(methods.current.id) === 2 &&
|
||||
!canContinueDesdeDetalles)
|
||||
}
|
||||
disableCreate={wizard.isLoading}
|
||||
isLastStep={
|
||||
Wizard.utils.getIndex(methods.current.id) >=
|
||||
Wizard.steps.length - 1
|
||||
}
|
||||
wizard={wizard}
|
||||
setWizard={setWizard}
|
||||
/>
|
||||
</Wizard.Stepper.Controls>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}}
|
||||
</Wizard.Stepper.Provider>
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
{idx === 3 && (
|
||||
<Wizard.Stepper.Panel>
|
||||
<PasoResumenCard wizard={wizard} />
|
||||
</Wizard.Stepper.Panel>
|
||||
)}
|
||||
</div>
|
||||
</WizardLayout>
|
||||
)
|
||||
}}
|
||||
</Wizard.Stepper.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,21 +12,19 @@ import { Route as rootRouteImport } from './routes/__root'
|
||||
import { Route as LoginRouteImport } from './routes/login'
|
||||
import { Route as DashboardRouteImport } from './routes/dashboard'
|
||||
import { Route as IndexRouteImport } from './routes/index'
|
||||
import { Route as PlanesListaRouteImport } from './routes/planes/_lista'
|
||||
import { Route as DemoTanstackQueryRouteImport } from './routes/demo/tanstack-query'
|
||||
import { Route as PlanesListaRouteRouteImport } from './routes/planes/_lista/route'
|
||||
import { Route as PlanesListaNuevoRouteImport } from './routes/planes/_lista/nuevo'
|
||||
import { Route as PlanesPlanIdAsignaturasRouteRouteImport } from './routes/planes/$planId/asignaturas/route'
|
||||
import { Route as PlanesPlanIdDetalleRouteRouteImport } from './routes/planes/$planId/_detalle/route'
|
||||
import { Route as PlanesPlanIdDetalleRouteImport } from './routes/planes/$planId/_detalle'
|
||||
import { Route as PlanesPlanIdDetalleIndexRouteImport } from './routes/planes/$planId/_detalle/index'
|
||||
import { Route as PlanesPlanIdAsignaturasAsignaturaIdRouteImport } from './routes/planes/$planId/asignaturas/$asignaturaId'
|
||||
import { Route as PlanesPlanIdDetalleMapaRouteImport } from './routes/planes/$planId/_detalle/mapa'
|
||||
import { Route as PlanesPlanIdDetalleIaplanRouteImport } from './routes/planes/$planId/_detalle/iaplan'
|
||||
import { Route as PlanesPlanIdDetalleHistorialRouteImport } from './routes/planes/$planId/_detalle/historial'
|
||||
import { Route as PlanesPlanIdDetalleFlujoRouteImport } from './routes/planes/$planId/_detalle/flujo'
|
||||
import { Route as PlanesPlanIdDetalleDocumentoRouteImport } from './routes/planes/$planId/_detalle/documento'
|
||||
import { Route as PlanesPlanIdDetalleAsignaturasRouteImport } from './routes/planes/$planId/_detalle/asignaturas'
|
||||
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 PlanesPlanIdAsignaturasListaNuevaRouteImport } from './routes/planes/$planId/asignaturas/_lista/nueva'
|
||||
import { Route as PlanesPlanIdDetalleAsignaturasIndexRouteImport } from './routes/planes/$planId/_detalle/asignaturas/index'
|
||||
import { Route as PlanesPlanIdDetalleAsignaturasNuevaRouteImport } from './routes/planes/$planId/_detalle/asignaturas/nueva'
|
||||
|
||||
const LoginRoute = LoginRouteImport.update({
|
||||
id: '/login',
|
||||
@@ -43,147 +41,133 @@ const IndexRoute = IndexRouteImport.update({
|
||||
path: '/',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const PlanesListaRoute = PlanesListaRouteImport.update({
|
||||
id: '/planes/_lista',
|
||||
path: '/planes',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const DemoTanstackQueryRoute = DemoTanstackQueryRouteImport.update({
|
||||
id: '/demo/tanstack-query',
|
||||
path: '/demo/tanstack-query',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const PlanesListaRouteRoute = PlanesListaRouteRouteImport.update({
|
||||
id: '/planes/_lista',
|
||||
path: '/planes',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const PlanesListaNuevoRoute = PlanesListaNuevoRouteImport.update({
|
||||
id: '/nuevo',
|
||||
path: '/nuevo',
|
||||
getParentRoute: () => PlanesListaRouteRoute,
|
||||
getParentRoute: () => PlanesListaRoute,
|
||||
} as any)
|
||||
const PlanesPlanIdDetalleRoute = PlanesPlanIdDetalleRouteImport.update({
|
||||
id: '/planes/$planId/_detalle',
|
||||
path: '/planes/$planId',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const PlanesPlanIdAsignaturasRouteRoute =
|
||||
PlanesPlanIdAsignaturasRouteRouteImport.update({
|
||||
id: '/planes/$planId/asignaturas',
|
||||
path: '/planes/$planId/asignaturas',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const PlanesPlanIdDetalleRouteRoute =
|
||||
PlanesPlanIdDetalleRouteRouteImport.update({
|
||||
id: '/planes/$planId/_detalle',
|
||||
path: '/planes/$planId',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const PlanesPlanIdDetalleIndexRoute =
|
||||
PlanesPlanIdDetalleIndexRouteImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
||||
getParentRoute: () => PlanesPlanIdDetalleRoute,
|
||||
} as any)
|
||||
const PlanesPlanIdAsignaturasAsignaturaIdRoute =
|
||||
PlanesPlanIdAsignaturasAsignaturaIdRouteImport.update({
|
||||
id: '/planes/$planId/asignaturas/$asignaturaId',
|
||||
path: '/planes/$planId/asignaturas/$asignaturaId',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const PlanesPlanIdDetalleMapaRoute = PlanesPlanIdDetalleMapaRouteImport.update({
|
||||
id: '/mapa',
|
||||
path: '/mapa',
|
||||
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
||||
getParentRoute: () => PlanesPlanIdDetalleRoute,
|
||||
} as any)
|
||||
const PlanesPlanIdDetalleIaplanRoute =
|
||||
PlanesPlanIdDetalleIaplanRouteImport.update({
|
||||
id: '/iaplan',
|
||||
path: '/iaplan',
|
||||
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
||||
getParentRoute: () => PlanesPlanIdDetalleRoute,
|
||||
} as any)
|
||||
const PlanesPlanIdDetalleHistorialRoute =
|
||||
PlanesPlanIdDetalleHistorialRouteImport.update({
|
||||
id: '/historial',
|
||||
path: '/historial',
|
||||
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
||||
getParentRoute: () => PlanesPlanIdDetalleRoute,
|
||||
} as any)
|
||||
const PlanesPlanIdDetalleFlujoRoute =
|
||||
PlanesPlanIdDetalleFlujoRouteImport.update({
|
||||
id: '/flujo',
|
||||
path: '/flujo',
|
||||
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
||||
getParentRoute: () => PlanesPlanIdDetalleRoute,
|
||||
} as any)
|
||||
const PlanesPlanIdDetalleDocumentoRoute =
|
||||
PlanesPlanIdDetalleDocumentoRouteImport.update({
|
||||
id: '/documento',
|
||||
path: '/documento',
|
||||
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
||||
getParentRoute: () => PlanesPlanIdDetalleRoute,
|
||||
} as any)
|
||||
const PlanesPlanIdDetalleAsignaturasRoute =
|
||||
PlanesPlanIdDetalleAsignaturasRouteImport.update({
|
||||
id: '/asignaturas',
|
||||
path: '/asignaturas',
|
||||
getParentRoute: () => PlanesPlanIdDetalleRouteRoute,
|
||||
const PlanesPlanIdDetalleAsignaturasIndexRoute =
|
||||
PlanesPlanIdDetalleAsignaturasIndexRouteImport.update({
|
||||
id: '/asignaturas/',
|
||||
path: '/asignaturas/',
|
||||
getParentRoute: () => PlanesPlanIdDetalleRoute,
|
||||
} as any)
|
||||
const PlanesPlanIdAsignaturasListaRouteRoute =
|
||||
PlanesPlanIdAsignaturasListaRouteRouteImport.update({
|
||||
id: '/_lista',
|
||||
getParentRoute: () => PlanesPlanIdAsignaturasRouteRoute,
|
||||
} as any)
|
||||
const PlanesPlanIdAsignaturasAsignaturaIdRouteRoute =
|
||||
PlanesPlanIdAsignaturasAsignaturaIdRouteRouteImport.update({
|
||||
id: '/$asignaturaId',
|
||||
path: '/$asignaturaId',
|
||||
getParentRoute: () => PlanesPlanIdAsignaturasRouteRoute,
|
||||
} as any)
|
||||
const PlanesPlanIdAsignaturasListaNuevaRoute =
|
||||
PlanesPlanIdAsignaturasListaNuevaRouteImport.update({
|
||||
id: '/nueva',
|
||||
path: '/nueva',
|
||||
getParentRoute: () => PlanesPlanIdAsignaturasListaRouteRoute,
|
||||
const PlanesPlanIdDetalleAsignaturasNuevaRoute =
|
||||
PlanesPlanIdDetalleAsignaturasNuevaRouteImport.update({
|
||||
id: '/asignaturas/nueva',
|
||||
path: '/asignaturas/nueva',
|
||||
getParentRoute: () => PlanesPlanIdDetalleRoute,
|
||||
} as any)
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexRoute
|
||||
'/dashboard': typeof DashboardRoute
|
||||
'/login': typeof LoginRoute
|
||||
'/planes': typeof PlanesListaRouteRouteWithChildren
|
||||
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
||||
'/planes/$planId': typeof PlanesPlanIdDetalleRouteRouteWithChildren
|
||||
'/planes/$planId/asignaturas': typeof PlanesPlanIdDetalleAsignaturasRoute
|
||||
'/planes': typeof PlanesListaRouteWithChildren
|
||||
'/planes/$planId': typeof PlanesPlanIdDetalleRouteWithChildren
|
||||
'/planes/nuevo': typeof PlanesListaNuevoRoute
|
||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||
'/planes/$planId/documento': typeof PlanesPlanIdDetalleDocumentoRoute
|
||||
'/planes/$planId/flujo': typeof PlanesPlanIdDetalleFlujoRoute
|
||||
'/planes/$planId/historial': typeof PlanesPlanIdDetalleHistorialRoute
|
||||
'/planes/$planId/iaplan': typeof PlanesPlanIdDetalleIaplanRoute
|
||||
'/planes/$planId/mapa': typeof PlanesPlanIdDetalleMapaRoute
|
||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRoute
|
||||
'/planes/$planId/': typeof PlanesPlanIdDetalleIndexRoute
|
||||
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdDetalleAsignaturasNuevaRoute
|
||||
'/planes/$planId/asignaturas/': typeof PlanesPlanIdDetalleAsignaturasIndexRoute
|
||||
}
|
||||
export interface FileRoutesByTo {
|
||||
'/': typeof IndexRoute
|
||||
'/dashboard': typeof DashboardRoute
|
||||
'/login': typeof LoginRoute
|
||||
'/planes': typeof PlanesListaRouteRouteWithChildren
|
||||
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
||||
'/planes/$planId/asignaturas': typeof PlanesPlanIdDetalleAsignaturasRoute
|
||||
'/planes': typeof PlanesListaRouteWithChildren
|
||||
'/planes/nuevo': typeof PlanesListaNuevoRoute
|
||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||
'/planes/$planId/documento': typeof PlanesPlanIdDetalleDocumentoRoute
|
||||
'/planes/$planId/flujo': typeof PlanesPlanIdDetalleFlujoRoute
|
||||
'/planes/$planId/historial': typeof PlanesPlanIdDetalleHistorialRoute
|
||||
'/planes/$planId/iaplan': typeof PlanesPlanIdDetalleIaplanRoute
|
||||
'/planes/$planId/mapa': typeof PlanesPlanIdDetalleMapaRoute
|
||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRoute
|
||||
'/planes/$planId': typeof PlanesPlanIdDetalleIndexRoute
|
||||
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||
'/planes/$planId/asignaturas/nueva': typeof PlanesPlanIdDetalleAsignaturasNuevaRoute
|
||||
'/planes/$planId/asignaturas': typeof PlanesPlanIdDetalleAsignaturasIndexRoute
|
||||
}
|
||||
export interface FileRoutesById {
|
||||
__root__: typeof rootRouteImport
|
||||
'/': typeof IndexRoute
|
||||
'/dashboard': typeof DashboardRoute
|
||||
'/login': typeof LoginRoute
|
||||
'/planes/_lista': typeof PlanesListaRouteRouteWithChildren
|
||||
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
|
||||
'/planes/$planId/_detalle': typeof PlanesPlanIdDetalleRouteRouteWithChildren
|
||||
'/planes/$planId/asignaturas': typeof PlanesPlanIdAsignaturasRouteRouteWithChildren
|
||||
'/planes/_lista': typeof PlanesListaRouteWithChildren
|
||||
'/planes/$planId/_detalle': typeof PlanesPlanIdDetalleRouteWithChildren
|
||||
'/planes/_lista/nuevo': typeof PlanesListaNuevoRoute
|
||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||
'/planes/$planId/asignaturas/_lista': typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
||||
'/planes/$planId/_detalle/asignaturas': typeof PlanesPlanIdDetalleAsignaturasRoute
|
||||
'/planes/$planId/_detalle/documento': typeof PlanesPlanIdDetalleDocumentoRoute
|
||||
'/planes/$planId/_detalle/flujo': typeof PlanesPlanIdDetalleFlujoRoute
|
||||
'/planes/$planId/_detalle/historial': typeof PlanesPlanIdDetalleHistorialRoute
|
||||
'/planes/$planId/_detalle/iaplan': typeof PlanesPlanIdDetalleIaplanRoute
|
||||
'/planes/$planId/_detalle/mapa': typeof PlanesPlanIdDetalleMapaRoute
|
||||
'/planes/$planId/asignaturas/$asignaturaId': typeof PlanesPlanIdAsignaturasAsignaturaIdRoute
|
||||
'/planes/$planId/_detalle/': typeof PlanesPlanIdDetalleIndexRoute
|
||||
'/planes/$planId/asignaturas/_lista/nueva': typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||
'/planes/$planId/_detalle/asignaturas/nueva': typeof PlanesPlanIdDetalleAsignaturasNuevaRoute
|
||||
'/planes/$planId/_detalle/asignaturas/': typeof PlanesPlanIdDetalleAsignaturasIndexRoute
|
||||
}
|
||||
export interface FileRouteTypes {
|
||||
fileRoutesByFullPath: FileRoutesByFullPath
|
||||
@@ -191,66 +175,64 @@ export interface FileRouteTypes {
|
||||
| '/'
|
||||
| '/dashboard'
|
||||
| '/login'
|
||||
| '/planes'
|
||||
| '/demo/tanstack-query'
|
||||
| '/planes'
|
||||
| '/planes/$planId'
|
||||
| '/planes/$planId/asignaturas'
|
||||
| '/planes/nuevo'
|
||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||
| '/planes/$planId/documento'
|
||||
| '/planes/$planId/flujo'
|
||||
| '/planes/$planId/historial'
|
||||
| '/planes/$planId/iaplan'
|
||||
| '/planes/$planId/mapa'
|
||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||
| '/planes/$planId/'
|
||||
| '/planes/$planId/asignaturas/nueva'
|
||||
| '/planes/$planId/asignaturas/'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to:
|
||||
| '/'
|
||||
| '/dashboard'
|
||||
| '/login'
|
||||
| '/planes'
|
||||
| '/demo/tanstack-query'
|
||||
| '/planes/$planId/asignaturas'
|
||||
| '/planes'
|
||||
| '/planes/nuevo'
|
||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||
| '/planes/$planId/documento'
|
||||
| '/planes/$planId/flujo'
|
||||
| '/planes/$planId/historial'
|
||||
| '/planes/$planId/iaplan'
|
||||
| '/planes/$planId/mapa'
|
||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||
| '/planes/$planId'
|
||||
| '/planes/$planId/asignaturas/nueva'
|
||||
| '/planes/$planId/asignaturas'
|
||||
id:
|
||||
| '__root__'
|
||||
| '/'
|
||||
| '/dashboard'
|
||||
| '/login'
|
||||
| '/planes/_lista'
|
||||
| '/demo/tanstack-query'
|
||||
| '/planes/_lista'
|
||||
| '/planes/$planId/_detalle'
|
||||
| '/planes/$planId/asignaturas'
|
||||
| '/planes/_lista/nuevo'
|
||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||
| '/planes/$planId/asignaturas/_lista'
|
||||
| '/planes/$planId/_detalle/asignaturas'
|
||||
| '/planes/$planId/_detalle/documento'
|
||||
| '/planes/$planId/_detalle/flujo'
|
||||
| '/planes/$planId/_detalle/historial'
|
||||
| '/planes/$planId/_detalle/iaplan'
|
||||
| '/planes/$planId/_detalle/mapa'
|
||||
| '/planes/$planId/asignaturas/$asignaturaId'
|
||||
| '/planes/$planId/_detalle/'
|
||||
| '/planes/$planId/asignaturas/_lista/nueva'
|
||||
| '/planes/$planId/_detalle/asignaturas/nueva'
|
||||
| '/planes/$planId/_detalle/asignaturas/'
|
||||
fileRoutesById: FileRoutesById
|
||||
}
|
||||
export interface RootRouteChildren {
|
||||
IndexRoute: typeof IndexRoute
|
||||
DashboardRoute: typeof DashboardRoute
|
||||
LoginRoute: typeof LoginRoute
|
||||
PlanesListaRouteRoute: typeof PlanesListaRouteRouteWithChildren
|
||||
DemoTanstackQueryRoute: typeof DemoTanstackQueryRoute
|
||||
PlanesPlanIdDetalleRouteRoute: typeof PlanesPlanIdDetalleRouteRouteWithChildren
|
||||
PlanesPlanIdAsignaturasRouteRoute: typeof PlanesPlanIdAsignaturasRouteRouteWithChildren
|
||||
PlanesListaRoute: typeof PlanesListaRouteWithChildren
|
||||
PlanesPlanIdDetalleRoute: typeof PlanesPlanIdDetalleRouteWithChildren
|
||||
PlanesPlanIdAsignaturasAsignaturaIdRoute: typeof PlanesPlanIdAsignaturasAsignaturaIdRoute
|
||||
}
|
||||
|
||||
declare module '@tanstack/react-router' {
|
||||
@@ -276,6 +258,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof IndexRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/planes/_lista': {
|
||||
id: '/planes/_lista'
|
||||
path: '/planes'
|
||||
fullPath: '/planes'
|
||||
preLoaderRoute: typeof PlanesListaRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/demo/tanstack-query': {
|
||||
id: '/demo/tanstack-query'
|
||||
path: '/demo/tanstack-query'
|
||||
@@ -283,32 +272,18 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof DemoTanstackQueryRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/planes/_lista': {
|
||||
id: '/planes/_lista'
|
||||
path: '/planes'
|
||||
fullPath: '/planes'
|
||||
preLoaderRoute: typeof PlanesListaRouteRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/planes/_lista/nuevo': {
|
||||
id: '/planes/_lista/nuevo'
|
||||
path: '/nuevo'
|
||||
fullPath: '/planes/nuevo'
|
||||
preLoaderRoute: typeof PlanesListaNuevoRouteImport
|
||||
parentRoute: typeof PlanesListaRouteRoute
|
||||
}
|
||||
'/planes/$planId/asignaturas': {
|
||||
id: '/planes/$planId/asignaturas'
|
||||
path: '/planes/$planId/asignaturas'
|
||||
fullPath: '/planes/$planId/asignaturas'
|
||||
preLoaderRoute: typeof PlanesPlanIdAsignaturasRouteRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
parentRoute: typeof PlanesListaRoute
|
||||
}
|
||||
'/planes/$planId/_detalle': {
|
||||
id: '/planes/$planId/_detalle'
|
||||
path: '/planes/$planId'
|
||||
fullPath: '/planes/$planId'
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleRouteRouteImport
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/planes/$planId/_detalle/': {
|
||||
@@ -316,153 +291,115 @@ declare module '@tanstack/react-router' {
|
||||
path: '/'
|
||||
fullPath: '/planes/$planId/'
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleIndexRouteImport
|
||||
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
||||
parentRoute: typeof PlanesPlanIdDetalleRoute
|
||||
}
|
||||
'/planes/$planId/asignaturas/$asignaturaId': {
|
||||
id: '/planes/$planId/asignaturas/$asignaturaId'
|
||||
path: '/planes/$planId/asignaturas/$asignaturaId'
|
||||
fullPath: '/planes/$planId/asignaturas/$asignaturaId'
|
||||
preLoaderRoute: typeof PlanesPlanIdAsignaturasAsignaturaIdRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/planes/$planId/_detalle/mapa': {
|
||||
id: '/planes/$planId/_detalle/mapa'
|
||||
path: '/mapa'
|
||||
fullPath: '/planes/$planId/mapa'
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleMapaRouteImport
|
||||
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
||||
parentRoute: typeof PlanesPlanIdDetalleRoute
|
||||
}
|
||||
'/planes/$planId/_detalle/iaplan': {
|
||||
id: '/planes/$planId/_detalle/iaplan'
|
||||
path: '/iaplan'
|
||||
fullPath: '/planes/$planId/iaplan'
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleIaplanRouteImport
|
||||
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
||||
parentRoute: typeof PlanesPlanIdDetalleRoute
|
||||
}
|
||||
'/planes/$planId/_detalle/historial': {
|
||||
id: '/planes/$planId/_detalle/historial'
|
||||
path: '/historial'
|
||||
fullPath: '/planes/$planId/historial'
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleHistorialRouteImport
|
||||
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
||||
parentRoute: typeof PlanesPlanIdDetalleRoute
|
||||
}
|
||||
'/planes/$planId/_detalle/flujo': {
|
||||
id: '/planes/$planId/_detalle/flujo'
|
||||
path: '/flujo'
|
||||
fullPath: '/planes/$planId/flujo'
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleFlujoRouteImport
|
||||
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
||||
parentRoute: typeof PlanesPlanIdDetalleRoute
|
||||
}
|
||||
'/planes/$planId/_detalle/documento': {
|
||||
id: '/planes/$planId/_detalle/documento'
|
||||
path: '/documento'
|
||||
fullPath: '/planes/$planId/documento'
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleDocumentoRouteImport
|
||||
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
||||
parentRoute: typeof PlanesPlanIdDetalleRoute
|
||||
}
|
||||
'/planes/$planId/_detalle/asignaturas': {
|
||||
id: '/planes/$planId/_detalle/asignaturas'
|
||||
'/planes/$planId/_detalle/asignaturas/': {
|
||||
id: '/planes/$planId/_detalle/asignaturas/'
|
||||
path: '/asignaturas'
|
||||
fullPath: '/planes/$planId/asignaturas'
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleAsignaturasRouteImport
|
||||
parentRoute: typeof PlanesPlanIdDetalleRouteRoute
|
||||
fullPath: '/planes/$planId/asignaturas/'
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleAsignaturasIndexRouteImport
|
||||
parentRoute: typeof PlanesPlanIdDetalleRoute
|
||||
}
|
||||
'/planes/$planId/asignaturas/_lista': {
|
||||
id: '/planes/$planId/asignaturas/_lista'
|
||||
path: ''
|
||||
fullPath: '/planes/$planId/asignaturas'
|
||||
preLoaderRoute: typeof PlanesPlanIdAsignaturasListaRouteRouteImport
|
||||
parentRoute: typeof PlanesPlanIdAsignaturasRouteRoute
|
||||
}
|
||||
'/planes/$planId/asignaturas/$asignaturaId': {
|
||||
id: '/planes/$planId/asignaturas/$asignaturaId'
|
||||
path: '/$asignaturaId'
|
||||
fullPath: '/planes/$planId/asignaturas/$asignaturaId'
|
||||
preLoaderRoute: typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRouteImport
|
||||
parentRoute: typeof PlanesPlanIdAsignaturasRouteRoute
|
||||
}
|
||||
'/planes/$planId/asignaturas/_lista/nueva': {
|
||||
id: '/planes/$planId/asignaturas/_lista/nueva'
|
||||
path: '/nueva'
|
||||
'/planes/$planId/_detalle/asignaturas/nueva': {
|
||||
id: '/planes/$planId/_detalle/asignaturas/nueva'
|
||||
path: '/asignaturas/nueva'
|
||||
fullPath: '/planes/$planId/asignaturas/nueva'
|
||||
preLoaderRoute: typeof PlanesPlanIdAsignaturasListaNuevaRouteImport
|
||||
parentRoute: typeof PlanesPlanIdAsignaturasListaRouteRoute
|
||||
preLoaderRoute: typeof PlanesPlanIdDetalleAsignaturasNuevaRouteImport
|
||||
parentRoute: typeof PlanesPlanIdDetalleRoute
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface PlanesListaRouteRouteChildren {
|
||||
interface PlanesListaRouteChildren {
|
||||
PlanesListaNuevoRoute: typeof PlanesListaNuevoRoute
|
||||
}
|
||||
|
||||
const PlanesListaRouteRouteChildren: PlanesListaRouteRouteChildren = {
|
||||
const PlanesListaRouteChildren: PlanesListaRouteChildren = {
|
||||
PlanesListaNuevoRoute: PlanesListaNuevoRoute,
|
||||
}
|
||||
|
||||
const PlanesListaRouteRouteWithChildren =
|
||||
PlanesListaRouteRoute._addFileChildren(PlanesListaRouteRouteChildren)
|
||||
const PlanesListaRouteWithChildren = PlanesListaRoute._addFileChildren(
|
||||
PlanesListaRouteChildren,
|
||||
)
|
||||
|
||||
interface PlanesPlanIdDetalleRouteRouteChildren {
|
||||
PlanesPlanIdDetalleAsignaturasRoute: typeof PlanesPlanIdDetalleAsignaturasRoute
|
||||
interface PlanesPlanIdDetalleRouteChildren {
|
||||
PlanesPlanIdDetalleDocumentoRoute: typeof PlanesPlanIdDetalleDocumentoRoute
|
||||
PlanesPlanIdDetalleFlujoRoute: typeof PlanesPlanIdDetalleFlujoRoute
|
||||
PlanesPlanIdDetalleHistorialRoute: typeof PlanesPlanIdDetalleHistorialRoute
|
||||
PlanesPlanIdDetalleIaplanRoute: typeof PlanesPlanIdDetalleIaplanRoute
|
||||
PlanesPlanIdDetalleMapaRoute: typeof PlanesPlanIdDetalleMapaRoute
|
||||
PlanesPlanIdDetalleIndexRoute: typeof PlanesPlanIdDetalleIndexRoute
|
||||
PlanesPlanIdDetalleAsignaturasNuevaRoute: typeof PlanesPlanIdDetalleAsignaturasNuevaRoute
|
||||
PlanesPlanIdDetalleAsignaturasIndexRoute: typeof PlanesPlanIdDetalleAsignaturasIndexRoute
|
||||
}
|
||||
|
||||
const PlanesPlanIdDetalleRouteRouteChildren: PlanesPlanIdDetalleRouteRouteChildren =
|
||||
{
|
||||
PlanesPlanIdDetalleAsignaturasRoute: PlanesPlanIdDetalleAsignaturasRoute,
|
||||
PlanesPlanIdDetalleDocumentoRoute: PlanesPlanIdDetalleDocumentoRoute,
|
||||
PlanesPlanIdDetalleFlujoRoute: PlanesPlanIdDetalleFlujoRoute,
|
||||
PlanesPlanIdDetalleHistorialRoute: PlanesPlanIdDetalleHistorialRoute,
|
||||
PlanesPlanIdDetalleIaplanRoute: PlanesPlanIdDetalleIaplanRoute,
|
||||
PlanesPlanIdDetalleMapaRoute: PlanesPlanIdDetalleMapaRoute,
|
||||
PlanesPlanIdDetalleIndexRoute: PlanesPlanIdDetalleIndexRoute,
|
||||
}
|
||||
|
||||
const PlanesPlanIdDetalleRouteRouteWithChildren =
|
||||
PlanesPlanIdDetalleRouteRoute._addFileChildren(
|
||||
PlanesPlanIdDetalleRouteRouteChildren,
|
||||
)
|
||||
|
||||
interface PlanesPlanIdAsignaturasListaRouteRouteChildren {
|
||||
PlanesPlanIdAsignaturasListaNuevaRoute: typeof PlanesPlanIdAsignaturasListaNuevaRoute
|
||||
const PlanesPlanIdDetalleRouteChildren: PlanesPlanIdDetalleRouteChildren = {
|
||||
PlanesPlanIdDetalleDocumentoRoute: PlanesPlanIdDetalleDocumentoRoute,
|
||||
PlanesPlanIdDetalleFlujoRoute: PlanesPlanIdDetalleFlujoRoute,
|
||||
PlanesPlanIdDetalleHistorialRoute: PlanesPlanIdDetalleHistorialRoute,
|
||||
PlanesPlanIdDetalleIaplanRoute: PlanesPlanIdDetalleIaplanRoute,
|
||||
PlanesPlanIdDetalleMapaRoute: PlanesPlanIdDetalleMapaRoute,
|
||||
PlanesPlanIdDetalleIndexRoute: PlanesPlanIdDetalleIndexRoute,
|
||||
PlanesPlanIdDetalleAsignaturasNuevaRoute:
|
||||
PlanesPlanIdDetalleAsignaturasNuevaRoute,
|
||||
PlanesPlanIdDetalleAsignaturasIndexRoute:
|
||||
PlanesPlanIdDetalleAsignaturasIndexRoute,
|
||||
}
|
||||
|
||||
const PlanesPlanIdAsignaturasListaRouteRouteChildren: PlanesPlanIdAsignaturasListaRouteRouteChildren =
|
||||
{
|
||||
PlanesPlanIdAsignaturasListaNuevaRoute:
|
||||
PlanesPlanIdAsignaturasListaNuevaRoute,
|
||||
}
|
||||
|
||||
const PlanesPlanIdAsignaturasListaRouteRouteWithChildren =
|
||||
PlanesPlanIdAsignaturasListaRouteRoute._addFileChildren(
|
||||
PlanesPlanIdAsignaturasListaRouteRouteChildren,
|
||||
)
|
||||
|
||||
interface PlanesPlanIdAsignaturasRouteRouteChildren {
|
||||
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute: typeof PlanesPlanIdAsignaturasAsignaturaIdRouteRoute
|
||||
PlanesPlanIdAsignaturasListaRouteRoute: typeof PlanesPlanIdAsignaturasListaRouteRouteWithChildren
|
||||
}
|
||||
|
||||
const PlanesPlanIdAsignaturasRouteRouteChildren: PlanesPlanIdAsignaturasRouteRouteChildren =
|
||||
{
|
||||
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute:
|
||||
PlanesPlanIdAsignaturasAsignaturaIdRouteRoute,
|
||||
PlanesPlanIdAsignaturasListaRouteRoute:
|
||||
PlanesPlanIdAsignaturasListaRouteRouteWithChildren,
|
||||
}
|
||||
|
||||
const PlanesPlanIdAsignaturasRouteRouteWithChildren =
|
||||
PlanesPlanIdAsignaturasRouteRoute._addFileChildren(
|
||||
PlanesPlanIdAsignaturasRouteRouteChildren,
|
||||
)
|
||||
const PlanesPlanIdDetalleRouteWithChildren =
|
||||
PlanesPlanIdDetalleRoute._addFileChildren(PlanesPlanIdDetalleRouteChildren)
|
||||
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
IndexRoute: IndexRoute,
|
||||
DashboardRoute: DashboardRoute,
|
||||
LoginRoute: LoginRoute,
|
||||
PlanesListaRouteRoute: PlanesListaRouteRouteWithChildren,
|
||||
DemoTanstackQueryRoute: DemoTanstackQueryRoute,
|
||||
PlanesPlanIdDetalleRouteRoute: PlanesPlanIdDetalleRouteRouteWithChildren,
|
||||
PlanesPlanIdAsignaturasRouteRoute:
|
||||
PlanesPlanIdAsignaturasRouteRouteWithChildren,
|
||||
PlanesListaRoute: PlanesListaRouteWithChildren,
|
||||
PlanesPlanIdDetalleRoute: PlanesPlanIdDetalleRouteWithChildren,
|
||||
PlanesPlanIdAsignaturasAsignaturaIdRoute:
|
||||
PlanesPlanIdAsignaturasAsignaturaIdRoute,
|
||||
}
|
||||
export const routeTree = rootRouteImport
|
||||
._addFileChildren(rootRouteChildren)
|
||||
|
||||
@@ -35,6 +35,8 @@ export const Route = createFileRoute('/planes/$planId/_detalle')({
|
||||
} catch (e: any) {
|
||||
// PGRST116: The result contains 0 rows
|
||||
if (e?.code === 'PGRST116') {
|
||||
console.log('not found on', Route.path)
|
||||
|
||||
throw notFound()
|
||||
}
|
||||
throw e
|
||||
@@ -62,7 +62,7 @@ const mapAsignaturas = (asigApi: Array<any> = []): Array<Materia> => {
|
||||
}))
|
||||
}
|
||||
|
||||
export const Route = createFileRoute('/planes/$planId/_detalle/asignaturas')({
|
||||
export const Route = createFileRoute('/planes/$planId/_detalle/asignaturas/')({
|
||||
component: MateriasPage,
|
||||
})
|
||||
|
||||
@@ -131,7 +131,17 @@ function MateriasPage() {
|
||||
<Button variant="outline" size="sm">
|
||||
<Copy className="mr-2 h-4 w-4" /> Clonar
|
||||
</Button>
|
||||
<Button className="bg-emerald-700 hover:bg-emerald-800">
|
||||
<Button
|
||||
onClick={() => {
|
||||
console.log('planId desde asignaturas', planId)
|
||||
|
||||
navigate({
|
||||
to: `/planes/${planId}/asignaturas/nueva`,
|
||||
resetScroll: false,
|
||||
})
|
||||
}}
|
||||
className="ring-offset-background bg-primary text-primary-foreground hover:bg-primary/90 inline-flex h-11 items-center justify-center gap-2 rounded-md px-8 text-sm font-medium shadow-md transition-colors"
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" /> Nueva Materia
|
||||
</Button>
|
||||
</div>
|
||||
@@ -3,12 +3,13 @@ import { createFileRoute } from '@tanstack/react-router'
|
||||
import { NuevaAsignaturaModalContainer } from '@/features/asignaturas/nueva/NuevaAsignaturaModalContainer'
|
||||
|
||||
export const Route = createFileRoute(
|
||||
'/planes/$planId/asignaturas/_lista/nueva',
|
||||
'/planes/$planId/_detalle/asignaturas/nueva',
|
||||
)({
|
||||
component: NuevaAsignaturaModal,
|
||||
})
|
||||
|
||||
function NuevaAsignaturaModal() {
|
||||
const { planId } = Route.useParams()
|
||||
console.log('planId desde nueva', planId)
|
||||
return <NuevaAsignaturaModalContainer planId={planId} />
|
||||
}
|
||||
44
src/routes/planes/$planId/asignaturas/$asignaturaId.tsx
Normal file
44
src/routes/planes/$planId/asignaturas/$asignaturaId.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import { createFileRoute, notFound } from '@tanstack/react-router'
|
||||
|
||||
import MateriaDetailPage from '@/components/asignaturas/detalle/MateriaDetailPage'
|
||||
import { NotFoundPage } from '@/components/ui/NotFoundPage'
|
||||
import { subjects_get } from '@/data/api/subjects.api'
|
||||
import { qk } from '@/data/query/keys'
|
||||
|
||||
export const Route = createFileRoute(
|
||||
'/planes/$planId/asignaturas/$asignaturaId',
|
||||
)({
|
||||
loader: async ({ context: { queryClient }, params: { asignaturaId } }) => {
|
||||
try {
|
||||
await queryClient.ensureQueryData({
|
||||
queryKey: qk.asignatura(asignaturaId),
|
||||
queryFn: () => subjects_get(asignaturaId),
|
||||
})
|
||||
} catch (e: any) {
|
||||
// PGRST116: The result contains 0 rows (Supabase Single response error)
|
||||
if (e?.code === 'PGRST116') {
|
||||
throw notFound()
|
||||
}
|
||||
throw e
|
||||
}
|
||||
},
|
||||
notFoundComponent: () => {
|
||||
return (
|
||||
<NotFoundPage
|
||||
title="Materia no encontrada"
|
||||
message="La asignatura que buscas no existe o fue eliminada."
|
||||
/>
|
||||
)
|
||||
},
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
function RouteComponent() {
|
||||
// const { planId, asignaturaId } = Route.useParams()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<MateriaDetailPage></MateriaDetailPage>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import MateriaDetailPage from '@/components/asignaturas/detalle/MateriaDetailPage'
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute(
|
||||
'/planes/$planId/asignaturas/$asignaturaId'
|
||||
)({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
function RouteComponent() {
|
||||
//const { planId, asignaturaId } = Route.useParams()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<MateriaDetailPage></MateriaDetailPage>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { createFileRoute, Outlet } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/planes/$planId/asignaturas/_lista')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<main className="bg-background min-h-screen w-full">
|
||||
<div className="mx-auto flex w-full max-w-7xl flex-col gap-4 px-4 py-6 md:px-6 lg:px-8">
|
||||
<h1 className="text-foreground text-2xl font-semibold">Asignaturas</h1>
|
||||
<Outlet />
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
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')({
|
||||
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,
|
||||
})
|
||||
|
||||
function AsignaturasLayout() {
|
||||
return <Outlet />
|
||||
}
|
||||
@@ -125,7 +125,11 @@ function RouteComponent() {
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => navigate({ to: '/planes/nuevo' })}
|
||||
onClick={() => {
|
||||
console.log('planId')
|
||||
|
||||
navigate({ to: '/planes/nuevo', resetScroll: false })
|
||||
}}
|
||||
className="ring-offset-background bg-primary text-primary-foreground hover:bg-primary/90 inline-flex h-11 items-center justify-center gap-2 rounded-md px-8 text-sm font-medium shadow-md transition-colors"
|
||||
>
|
||||
<Icons.Plus /> Nuevo plan de estudios
|
||||
Reference in New Issue
Block a user