Separación vista/lógica del wizard de creación de plan
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/asignaturas/$asignaturaId')({
|
||||
export const Route = createFileRoute('/planes/$planId/asignaturas/$asignaturaId')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
@@ -35,7 +35,9 @@ import {
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip'
|
||||
|
||||
export const Route = createFileRoute('/asignaturas/_lista/nueva')({
|
||||
export const Route = createFileRoute(
|
||||
'/planes/$planId/asignaturas/_lista/nueva',
|
||||
)({
|
||||
component: NuevaMateriaModal,
|
||||
})
|
||||
|
||||
@@ -54,7 +56,7 @@ type MateriaPreview = {
|
||||
|
||||
type NewSubjectWizardState = {
|
||||
step: 1 | 2 | 3 | 4
|
||||
// planId: string
|
||||
planId: string
|
||||
modoCreacion: ModoCreacion | null
|
||||
subModoClonado?: SubModoClonado
|
||||
datosBasicos: {
|
||||
@@ -175,12 +177,12 @@ const Wizard = defineStepper(
|
||||
|
||||
function NuevaMateriaModal() {
|
||||
const navigate = useNavigate()
|
||||
// const { planId } = Route.useParams()
|
||||
const { planId } = Route.useParams()
|
||||
const role = auth_get_current_user_role()
|
||||
|
||||
const [wizard, setWizard] = useState<NewSubjectWizardState>({
|
||||
step: 1,
|
||||
// planId: planId,
|
||||
planId: planId,
|
||||
modoCreacion: null,
|
||||
datosBasicos: {
|
||||
nombre: '',
|
||||
@@ -207,7 +209,7 @@ function NuevaMateriaModal() {
|
||||
|
||||
const handleClose = () => {
|
||||
// Redirige a la pestaña de materias del plan
|
||||
navigate({ to: `/planes`, resetScroll: false })
|
||||
navigate({ to: `/planes/${planId}/asignaturas`, resetScroll: false })
|
||||
}
|
||||
|
||||
// --- Validaciones ---
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createFileRoute, Outlet } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/asignaturas/_lista')({
|
||||
export const Route = createFileRoute('/planes/$planId/asignaturas/_lista')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
@@ -8,6 +8,7 @@ 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,6 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/planes/$planId')({
|
||||
export const Route = createFileRoute('/planes/$planId/')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,65 +0,0 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import { defineStepper } from '@/components/stepper'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
export const Route = createFileRoute('/stepper')({
|
||||
component: MyFirstStepper,
|
||||
})
|
||||
|
||||
const stepperInstance = defineStepper(
|
||||
{ id: 'step-1', title: 'Step 1' },
|
||||
{ id: 'step-2', title: 'Step 2' },
|
||||
{ id: 'step-3', title: 'Step 3' },
|
||||
)
|
||||
|
||||
export function MyFirstStepper() {
|
||||
return (
|
||||
<stepperInstance.Stepper.Provider className="space-y-4">
|
||||
{({ methods }) => (
|
||||
<>
|
||||
<stepperInstance.Stepper.Navigation>
|
||||
{methods.all.map((step) => (
|
||||
<stepperInstance.Stepper.Step
|
||||
of={step.id}
|
||||
onClick={() => methods.goTo(step.id)}
|
||||
>
|
||||
<stepperInstance.Stepper.Title>
|
||||
{step.title}
|
||||
</stepperInstance.Stepper.Title>
|
||||
</stepperInstance.Stepper.Step>
|
||||
))}
|
||||
</stepperInstance.Stepper.Navigation>
|
||||
{methods.switch({
|
||||
'step-1': (step) => <Content id={step.id} />,
|
||||
'step-2': (step) => <Content id={step.id} />,
|
||||
'step-3': (step) => <Content id={step.id} />,
|
||||
})}
|
||||
<stepperInstance.Stepper.Controls>
|
||||
{!methods.isLast && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
onClick={methods.prev}
|
||||
disabled={methods.isFirst}
|
||||
>
|
||||
Previous
|
||||
</Button>
|
||||
)}
|
||||
<Button onClick={methods.isLast ? methods.reset : methods.next}>
|
||||
{methods.isLast ? 'Reset' : 'Next'}
|
||||
</Button>
|
||||
</stepperInstance.Stepper.Controls>
|
||||
</>
|
||||
)}
|
||||
</stepperInstance.Stepper.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
const Content = ({ id }: { id: string }) => {
|
||||
return (
|
||||
<stepperInstance.Stepper.Panel className="h-50 content-center rounded border bg-slate-50 p-8">
|
||||
<p className="text-xl font-normal">Content for {id}</p>
|
||||
</stepperInstance.Stepper.Panel>
|
||||
)
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import { CircularProgress } from '@/components/CircularProgress'
|
||||
import { defineStepper } from '@/components/stepper' // Tu wrapper
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
export const Route = createFileRoute('/stepper2')({
|
||||
component: MobileStepperView,
|
||||
})
|
||||
|
||||
// 1. Definimos los pasos igual que siempre
|
||||
const myStepper = defineStepper(
|
||||
{ id: 'contact', title: 'Contact Details' },
|
||||
{ id: 'shipping', title: 'Shipping Information' },
|
||||
{ id: 'billing', title: 'Billing Address' },
|
||||
{ id: 'review', title: 'Payment Review' },
|
||||
)
|
||||
|
||||
export default function MobileStepperView() {
|
||||
return (
|
||||
// Usa el Provider del wrapper para tener el contexto
|
||||
<myStepper.Stepper.Provider>
|
||||
{({ methods }) => {
|
||||
// Calculamos índices para el gráfico
|
||||
const currentIndex =
|
||||
methods.all.findIndex((s) => s.id === methods.current.id) + 1
|
||||
const totalSteps = methods.all.length
|
||||
const nextStep = methods.all[currentIndex] // El paso siguiente (si existe)
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col bg-white p-4">
|
||||
{/* --- AQUÍ ESTÁ LA MAGIA (Tu UI Personalizada) --- */}
|
||||
<div className="mb-6 flex items-center gap-4">
|
||||
{/* El Gráfico Circular */}
|
||||
<CircularProgress current={currentIndex} total={totalSteps} />
|
||||
|
||||
{/* Los Textos */}
|
||||
<div className="flex flex-col">
|
||||
<h2 className="text-lg font-bold text-slate-900">
|
||||
{methods.current.title}
|
||||
</h2>
|
||||
{nextStep && (
|
||||
<p className="text-sm text-slate-400">
|
||||
Next: {nextStep.title}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* ----------------------------------------------- */}
|
||||
|
||||
{/* El contenido de los pasos (Switch) */}
|
||||
<div className="flex-1">
|
||||
{methods.switch({
|
||||
contact: () => <div>Formulario Contacto...</div>,
|
||||
shipping: () => <div>Formulario Envío...</div>,
|
||||
billing: () => <div>Formulario Facturación...</div>,
|
||||
review: () => <div>Resumen...</div>,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Controles de Navegación (Footer) */}
|
||||
<div className="mt-4 flex justify-between">
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={methods.prev}
|
||||
disabled={methods.isFirst}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
<Button
|
||||
className="bg-red-500 text-white hover:bg-red-600"
|
||||
onClick={methods.next}
|
||||
>
|
||||
{methods.isLast ? 'Finish' : 'Next'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</myStepper.Stepper.Provider>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user