wip
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { TemplateSelectorCard } from './TemplateSelectorCard'
|
||||
|
||||
import type { NivelPlanEstudio, TipoCiclo } from '@/data/types/domain'
|
||||
import type { CARRERAS } from '@/features/planes/nuevo/catalogs'
|
||||
import type { NewPlanWizardState } from '@/features/planes/nuevo/types'
|
||||
|
||||
@@ -13,6 +14,7 @@ import {
|
||||
SelectValue,
|
||||
} from '@/components/ui/select'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { useCatalogosPlanes } from '@/data/hooks/usePlans'
|
||||
import {
|
||||
FACULTADES,
|
||||
NIVELES,
|
||||
@@ -31,6 +33,18 @@ export function PasoBasicosForm({
|
||||
onChange: React.Dispatch<React.SetStateAction<NewPlanWizardState>>
|
||||
carrerasFiltradas: typeof CARRERAS
|
||||
}) {
|
||||
const { data: catalogos } = useCatalogosPlanes()
|
||||
|
||||
// Preferir los catálogos remotos si están disponibles; si no, usar los locales
|
||||
const facultadesList = catalogos?.facultades ?? FACULTADES
|
||||
const rawCarreras = catalogos?.carreras ?? carrerasFiltradas
|
||||
|
||||
const filteredCarreras = rawCarreras.filter((c: any) => {
|
||||
const facId = wizard.datosBasicos.facultadId
|
||||
if (!facId) return true
|
||||
// soportar ambos shapes: `facultad_id` (BD) o `facultadId` (local)
|
||||
return c.facultad_id ? c.facultad_id === facId : c.facultadId === facId
|
||||
})
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="grid gap-4 sm:grid-cols-2">
|
||||
@@ -40,7 +54,7 @@ export function PasoBasicosForm({
|
||||
</Label>
|
||||
<Input
|
||||
id="nombrePlan"
|
||||
placeholder="Ej. Ingeniería en Sistemas 2026"
|
||||
placeholder="Ej. Ingeniería en Sistemas (2026)"
|
||||
value={wizard.datosBasicos.nombrePlan}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
onChange((w) => ({
|
||||
@@ -79,7 +93,7 @@ export function PasoBasicosForm({
|
||||
<SelectValue placeholder="Ej. Facultad de Ingeniería" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{FACULTADES.map((f) => (
|
||||
{facultadesList.map((f: any) => (
|
||||
<SelectItem key={f.id} value={f.id}>
|
||||
{f.nombre}
|
||||
</SelectItem>
|
||||
@@ -112,7 +126,7 @@ export function PasoBasicosForm({
|
||||
<SelectValue placeholder="Ej. Ingeniería en Cibernética y Sistemas Computacionales" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{carrerasFiltradas.map((c) => (
|
||||
{filteredCarreras.map((c: any) => (
|
||||
<SelectItem key={c.id} value={c.id}>
|
||||
{c.nombre}
|
||||
</SelectItem>
|
||||
@@ -125,11 +139,13 @@ export function PasoBasicosForm({
|
||||
<Label htmlFor="nivel">Nivel</Label>
|
||||
<Select
|
||||
value={wizard.datosBasicos.nivel}
|
||||
onValueChange={(value) =>
|
||||
onChange((w) => ({
|
||||
...w,
|
||||
datosBasicos: { ...w.datosBasicos, nivel: value },
|
||||
}))
|
||||
onValueChange={(value: NivelPlanEstudio) =>
|
||||
onChange(
|
||||
(w): NewPlanWizardState => ({
|
||||
...w,
|
||||
datosBasicos: { ...w.datosBasicos, nivel: value },
|
||||
}),
|
||||
)
|
||||
}
|
||||
>
|
||||
<SelectTrigger
|
||||
@@ -157,7 +173,7 @@ export function PasoBasicosForm({
|
||||
<Label htmlFor="tipoCiclo">Tipo de ciclo</Label>
|
||||
<Select
|
||||
value={wizard.datosBasicos.tipoCiclo}
|
||||
onValueChange={(value) =>
|
||||
onValueChange={(value: TipoCiclo) =>
|
||||
onChange((w) => ({
|
||||
...w,
|
||||
datosBasicos: {
|
||||
@@ -180,8 +196,8 @@ export function PasoBasicosForm({
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{TIPOS_CICLO.map((t) => (
|
||||
<SelectItem key={t.value} value={t.value}>
|
||||
{t.label}
|
||||
<SelectItem key={t} value={t}>
|
||||
{t}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
|
||||
@@ -30,7 +30,7 @@ export function PasoDetallesPanel({
|
||||
onGenerarIA: () => void
|
||||
isLoading: boolean
|
||||
}) {
|
||||
if (wizard.modoCreacion === 'MANUAL') {
|
||||
if (wizard.tipoOrigen === 'MANUAL') {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
@@ -43,7 +43,7 @@ export function PasoDetallesPanel({
|
||||
)
|
||||
}
|
||||
|
||||
if (wizard.modoCreacion === 'IA') {
|
||||
if (wizard.tipoOrigen === 'IA') {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-1">
|
||||
@@ -162,10 +162,7 @@ export function PasoDetallesPanel({
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
wizard.modoCreacion === 'CLONADO' &&
|
||||
wizard.subModoClonado === 'INTERNO'
|
||||
) {
|
||||
if (wizard.tipoOrigen === 'CLONADO_INTERNO') {
|
||||
return (
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-3 sm:grid-cols-3">
|
||||
@@ -269,10 +266,7 @@ export function PasoDetallesPanel({
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
wizard.modoCreacion === 'CLONADO' &&
|
||||
wizard.subModoClonado === 'TRADICIONAL'
|
||||
) {
|
||||
if (wizard.tipoOrigen === 'CLONADO_TRADICIONAL') {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-1">
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import * as Icons from 'lucide-react'
|
||||
|
||||
import type {
|
||||
NewPlanWizardState,
|
||||
ModoCreacion,
|
||||
SubModoClonado,
|
||||
} from '@/features/planes/nuevo/types'
|
||||
import type { TipoOrigen } from '@/data/types/domain'
|
||||
import type { NewPlanWizardState } from '@/features/planes/nuevo/types'
|
||||
|
||||
import {
|
||||
Card,
|
||||
@@ -21,8 +18,7 @@ export function PasoModoCardGroup({
|
||||
wizard: NewPlanWizardState
|
||||
onChange: React.Dispatch<React.SetStateAction<NewPlanWizardState>>
|
||||
}) {
|
||||
const isSelected = (m: ModoCreacion) => wizard.modoCreacion === m
|
||||
const isSubSelected = (s: SubModoClonado) => wizard.subModoClonado === s
|
||||
const isSelected = (m: TipoOrigen) => wizard.tipoOrigen === m
|
||||
const handleKeyActivate = (e: React.KeyboardEvent, cb: () => void) => {
|
||||
const key = e.key
|
||||
if (
|
||||
@@ -41,19 +37,21 @@ export function PasoModoCardGroup({
|
||||
<Card
|
||||
className={isSelected('MANUAL') ? 'ring-ring ring-2' : ''}
|
||||
onClick={() =>
|
||||
onChange((w) => ({
|
||||
...w,
|
||||
modoCreacion: 'MANUAL',
|
||||
subModoClonado: undefined,
|
||||
}))
|
||||
onChange(
|
||||
(w): NewPlanWizardState => ({
|
||||
...w,
|
||||
tipoOrigen: 'MANUAL',
|
||||
}),
|
||||
)
|
||||
}
|
||||
onKeyDown={(e: React.KeyboardEvent) =>
|
||||
handleKeyActivate(e, () =>
|
||||
onChange((w) => ({
|
||||
...w,
|
||||
modoCreacion: 'MANUAL',
|
||||
subModoClonado: undefined,
|
||||
})),
|
||||
onChange(
|
||||
(w): NewPlanWizardState => ({
|
||||
...w,
|
||||
tipoOrigen: 'MANUAL',
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
role="button"
|
||||
@@ -70,19 +68,21 @@ export function PasoModoCardGroup({
|
||||
<Card
|
||||
className={isSelected('IA') ? 'ring-ring ring-2' : ''}
|
||||
onClick={() =>
|
||||
onChange((w) => ({
|
||||
...w,
|
||||
modoCreacion: 'IA',
|
||||
subModoClonado: undefined,
|
||||
}))
|
||||
onChange(
|
||||
(w): NewPlanWizardState => ({
|
||||
...w,
|
||||
tipoOrigen: 'IA',
|
||||
}),
|
||||
)
|
||||
}
|
||||
onKeyDown={(e: React.KeyboardEvent) =>
|
||||
handleKeyActivate(e, () =>
|
||||
onChange((w) => ({
|
||||
...w,
|
||||
modoCreacion: 'IA',
|
||||
subModoClonado: undefined,
|
||||
})),
|
||||
onChange(
|
||||
(w): NewPlanWizardState => ({
|
||||
...w,
|
||||
tipoOrigen: 'IA',
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
role="button"
|
||||
@@ -99,11 +99,13 @@ export function PasoModoCardGroup({
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
className={isSelected('CLONADO') ? 'ring-ring ring-2' : ''}
|
||||
onClick={() => onChange((w) => ({ ...w, modoCreacion: 'CLONADO' }))}
|
||||
className={isSelected('OTRO') ? 'ring-ring ring-2' : ''}
|
||||
onClick={() =>
|
||||
onChange((w): NewPlanWizardState => ({ ...w, tipoOrigen: 'OTRO' }))
|
||||
}
|
||||
onKeyDown={(e: React.KeyboardEvent) =>
|
||||
handleKeyActivate(e, () =>
|
||||
onChange((w) => ({ ...w, modoCreacion: 'CLONADO' })),
|
||||
onChange((w): NewPlanWizardState => ({ ...w, tipoOrigen: 'OTRO' })),
|
||||
)
|
||||
}
|
||||
role="button"
|
||||
@@ -115,22 +117,34 @@ export function PasoModoCardGroup({
|
||||
</CardTitle>
|
||||
<CardDescription>Desde un plan existente o archivos.</CardDescription>
|
||||
</CardHeader>
|
||||
{wizard.modoCreacion === 'CLONADO' && (
|
||||
{(wizard.tipoOrigen === 'OTRO' ||
|
||||
wizard.tipoOrigen === 'CLONADO_INTERNO' ||
|
||||
wizard.tipoOrigen === 'CLONADO_TRADICIONAL') && (
|
||||
<CardContent className="flex flex-col gap-3">
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onChange((w) => ({ ...w, subModoClonado: 'INTERNO' }))
|
||||
onChange(
|
||||
(w): NewPlanWizardState => ({
|
||||
...w,
|
||||
tipoOrigen: 'CLONADO_INTERNO',
|
||||
}),
|
||||
)
|
||||
}}
|
||||
onKeyDown={(e: React.KeyboardEvent) =>
|
||||
handleKeyActivate(e, () =>
|
||||
onChange((w) => ({ ...w, subModoClonado: 'INTERNO' })),
|
||||
onChange(
|
||||
(w): NewPlanWizardState => ({
|
||||
...w,
|
||||
tipoOrigen: 'CLONADO_INTERNO',
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
className={`hover:border-primary/50 hover:bg-accent flex cursor-pointer flex-row items-center justify-center gap-2 rounded-lg border p-4 text-center transition-all sm:flex-col ${
|
||||
isSubSelected('INTERNO')
|
||||
isSelected('CLONADO_INTERNO')
|
||||
? 'border-primary bg-primary/5 ring-primary text-primary ring-1'
|
||||
: 'border-border text-muted-foreground'
|
||||
} `}
|
||||
@@ -144,15 +158,25 @@ export function PasoModoCardGroup({
|
||||
tabIndex={0}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onChange((w) => ({ ...w, subModoClonado: 'TRADICIONAL' }))
|
||||
onChange(
|
||||
(w): NewPlanWizardState => ({
|
||||
...w,
|
||||
tipoOrigen: 'CLONADO_TRADICIONAL',
|
||||
}),
|
||||
)
|
||||
}}
|
||||
onKeyDown={(e: React.KeyboardEvent) =>
|
||||
handleKeyActivate(e, () =>
|
||||
onChange((w) => ({ ...w, subModoClonado: 'TRADICIONAL' })),
|
||||
onChange(
|
||||
(w): NewPlanWizardState => ({
|
||||
...w,
|
||||
tipoOrigen: 'CLONADO_TRADICIONAL',
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
className={`hover:border-primary/50 hover:bg-accent flex cursor-pointer flex-row items-center justify-center gap-2 rounded-lg border p-4 text-center transition-all sm:flex-col ${
|
||||
isSubSelected('TRADICIONAL')
|
||||
isSelected('CLONADO_TRADICIONAL')
|
||||
? 'border-primary bg-primary/5 ring-primary text-primary ring-1'
|
||||
: 'border-border text-muted-foreground'
|
||||
} `}
|
||||
|
||||
Reference in New Issue
Block a user