wip
This commit is contained in:
@@ -1,182 +0,0 @@
|
|||||||
import type { CARRERAS } from '@/features/planes/nuevo/catalogs'
|
|
||||||
import type { NewPlanWizardState } from '@/features/planes/nuevo/types'
|
|
||||||
|
|
||||||
import { Input } from '@/components/ui/input'
|
|
||||||
import { Label } from '@/components/ui/label'
|
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from '@/components/ui/select'
|
|
||||||
import {
|
|
||||||
FACULTADES,
|
|
||||||
NIVELES,
|
|
||||||
TIPOS_CICLO,
|
|
||||||
} from '@/features/planes/nuevo/catalogs'
|
|
||||||
|
|
||||||
export function PasoBasicosForm({
|
|
||||||
wizard,
|
|
||||||
onChange,
|
|
||||||
carrerasFiltradas,
|
|
||||||
}: {
|
|
||||||
wizard: NewPlanWizardState
|
|
||||||
onChange: React.Dispatch<React.SetStateAction<NewPlanWizardState>>
|
|
||||||
carrerasFiltradas: typeof CARRERAS
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<div className="grid gap-4 sm:grid-cols-2">
|
|
||||||
<div className="grid gap-1 sm:col-span-2">
|
|
||||||
<Label htmlFor="nombrePlan">Nombre del plan</Label>
|
|
||||||
<Input
|
|
||||||
id="nombrePlan"
|
|
||||||
placeholder="Ej. Ingeniería en Sistemas 2026"
|
|
||||||
value={wizard.datosBasicos.nombrePlan}
|
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
||||||
onChange((w) => ({
|
|
||||||
...w,
|
|
||||||
datosBasicos: { ...w.datosBasicos, nombrePlan: e.target.value },
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-1">
|
|
||||||
<Label htmlFor="facultad">Facultad</Label>
|
|
||||||
<Select
|
|
||||||
value={wizard.datosBasicos.facultadId}
|
|
||||||
onValueChange={(value) =>
|
|
||||||
onChange((w) => ({
|
|
||||||
...w,
|
|
||||||
datosBasicos: {
|
|
||||||
...w.datosBasicos,
|
|
||||||
facultadId: value,
|
|
||||||
carreraId: '',
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<SelectTrigger
|
|
||||||
id="facultad"
|
|
||||||
className="w-full min-w-0 [&>span]:block! [&>span]:truncate!"
|
|
||||||
>
|
|
||||||
<SelectValue placeholder="Selecciona facultad…" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{FACULTADES.map((f) => (
|
|
||||||
<SelectItem key={f.id} value={f.id}>
|
|
||||||
{f.nombre}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-1">
|
|
||||||
<Label htmlFor="carrera">Carrera</Label>
|
|
||||||
<Select
|
|
||||||
value={wizard.datosBasicos.carreraId}
|
|
||||||
onValueChange={(value) =>
|
|
||||||
onChange((w) => ({
|
|
||||||
...w,
|
|
||||||
datosBasicos: { ...w.datosBasicos, carreraId: value },
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
disabled={!wizard.datosBasicos.facultadId}
|
|
||||||
>
|
|
||||||
<SelectTrigger
|
|
||||||
id="carrera"
|
|
||||||
className="w-full min-w-0 [&>span]:block! [&>span]:truncate!"
|
|
||||||
>
|
|
||||||
<SelectValue placeholder="Selecciona carrera…" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{carrerasFiltradas.map((c) => (
|
|
||||||
<SelectItem key={c.id} value={c.id}>
|
|
||||||
{c.nombre}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-1">
|
|
||||||
<Label htmlFor="nivel">Nivel</Label>
|
|
||||||
<Select
|
|
||||||
value={wizard.datosBasicos.nivel}
|
|
||||||
onValueChange={(value) =>
|
|
||||||
onChange((w) => ({
|
|
||||||
...w,
|
|
||||||
datosBasicos: { ...w.datosBasicos, nivel: value },
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<SelectTrigger
|
|
||||||
id="nivel"
|
|
||||||
className="w-full min-w-0 [&>span]:block! [&>span]:truncate!"
|
|
||||||
>
|
|
||||||
<SelectValue placeholder="Selecciona nivel…" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{NIVELES.map((n) => (
|
|
||||||
<SelectItem key={n} value={n}>
|
|
||||||
{n}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-1">
|
|
||||||
<Label htmlFor="tipoCiclo">Tipo de ciclo</Label>
|
|
||||||
<Select
|
|
||||||
value={wizard.datosBasicos.tipoCiclo}
|
|
||||||
onValueChange={(value) =>
|
|
||||||
onChange((w) => ({
|
|
||||||
...w,
|
|
||||||
datosBasicos: {
|
|
||||||
...w.datosBasicos,
|
|
||||||
tipoCiclo: value as any,
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<SelectTrigger
|
|
||||||
id="tipoCiclo"
|
|
||||||
className="w-full min-w-0 [&>span]:block! [&>span]:truncate!"
|
|
||||||
>
|
|
||||||
<SelectValue placeholder="Selecciona tipo de ciclo…" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{TIPOS_CICLO.map((t) => (
|
|
||||||
<SelectItem key={t.value} value={t.value}>
|
|
||||||
{t.label}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-1">
|
|
||||||
<Label htmlFor="numCiclos">Número de ciclos</Label>
|
|
||||||
<Input
|
|
||||||
id="numCiclos"
|
|
||||||
type="number"
|
|
||||||
min={1}
|
|
||||||
value={wizard.datosBasicos.numCiclos}
|
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
||||||
onChange((w) => ({
|
|
||||||
...w,
|
|
||||||
datosBasicos: {
|
|
||||||
...w.datosBasicos,
|
|
||||||
numCiclos: Number(e.target.value || 1),
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
placeholder="1"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
202
src/components/planes/wizard/PasoBasicosForm/PasoBasicosForm.tsx
Normal file
202
src/components/planes/wizard/PasoBasicosForm/PasoBasicosForm.tsx
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
import { TemplateSelectorCard } from './TemplateSelectorCard'
|
||||||
|
|
||||||
|
import type { CARRERAS } from '@/features/planes/nuevo/catalogs'
|
||||||
|
import type { NewPlanWizardState } from '@/features/planes/nuevo/types'
|
||||||
|
|
||||||
|
import { Input } from '@/components/ui/input'
|
||||||
|
import { Label } from '@/components/ui/label'
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select'
|
||||||
|
import { Separator } from '@/components/ui/separator'
|
||||||
|
import {
|
||||||
|
FACULTADES,
|
||||||
|
NIVELES,
|
||||||
|
TIPOS_CICLO,
|
||||||
|
PLANTILLAS_ANEXO_1,
|
||||||
|
PLANTILLAS_ANEXO_2,
|
||||||
|
} from '@/features/planes/nuevo/catalogs'
|
||||||
|
|
||||||
|
export function PasoBasicosForm({
|
||||||
|
wizard,
|
||||||
|
onChange,
|
||||||
|
carrerasFiltradas,
|
||||||
|
}: {
|
||||||
|
wizard: NewPlanWizardState
|
||||||
|
onChange: React.Dispatch<React.SetStateAction<NewPlanWizardState>>
|
||||||
|
carrerasFiltradas: typeof CARRERAS
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div className="grid gap-4 sm:grid-cols-2">
|
||||||
|
<div className="grid gap-1 sm:col-span-2">
|
||||||
|
<Label htmlFor="nombrePlan">Nombre del plan</Label>
|
||||||
|
<Input
|
||||||
|
id="nombrePlan"
|
||||||
|
placeholder="Ej. Ingeniería en Sistemas 2026"
|
||||||
|
value={wizard.datosBasicos.nombrePlan}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
|
onChange((w) => ({
|
||||||
|
...w,
|
||||||
|
datosBasicos: { ...w.datosBasicos, nombrePlan: e.target.value },
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-1">
|
||||||
|
<Label htmlFor="facultad">Facultad</Label>
|
||||||
|
<Select
|
||||||
|
value={wizard.datosBasicos.facultadId}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
onChange((w) => ({
|
||||||
|
...w,
|
||||||
|
datosBasicos: {
|
||||||
|
...w.datosBasicos,
|
||||||
|
facultadId: value,
|
||||||
|
carreraId: '',
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger
|
||||||
|
id="facultad"
|
||||||
|
className="w-full min-w-0 [&>span]:block! [&>span]:truncate!"
|
||||||
|
>
|
||||||
|
<SelectValue placeholder="Selecciona facultad…" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{FACULTADES.map((f) => (
|
||||||
|
<SelectItem key={f.id} value={f.id}>
|
||||||
|
{f.nombre}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-1">
|
||||||
|
<Label htmlFor="carrera">Carrera</Label>
|
||||||
|
<Select
|
||||||
|
value={wizard.datosBasicos.carreraId}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
onChange((w) => ({
|
||||||
|
...w,
|
||||||
|
datosBasicos: { ...w.datosBasicos, carreraId: value },
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
disabled={!wizard.datosBasicos.facultadId}
|
||||||
|
>
|
||||||
|
<SelectTrigger
|
||||||
|
id="carrera"
|
||||||
|
className="w-full min-w-0 [&>span]:block! [&>span]:truncate!"
|
||||||
|
>
|
||||||
|
<SelectValue placeholder="Selecciona carrera…" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{carrerasFiltradas.map((c) => (
|
||||||
|
<SelectItem key={c.id} value={c.id}>
|
||||||
|
{c.nombre}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-1">
|
||||||
|
<Label htmlFor="nivel">Nivel</Label>
|
||||||
|
<Select
|
||||||
|
value={wizard.datosBasicos.nivel}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
onChange((w) => ({
|
||||||
|
...w,
|
||||||
|
datosBasicos: { ...w.datosBasicos, nivel: value },
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger
|
||||||
|
id="nivel"
|
||||||
|
className="w-full min-w-0 [&>span]:block! [&>span]:truncate!"
|
||||||
|
>
|
||||||
|
<SelectValue placeholder="Selecciona nivel…" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{NIVELES.map((n) => (
|
||||||
|
<SelectItem key={n} value={n}>
|
||||||
|
{n}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-1">
|
||||||
|
<Label htmlFor="tipoCiclo">Tipo de ciclo</Label>
|
||||||
|
<Select
|
||||||
|
value={wizard.datosBasicos.tipoCiclo}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
onChange((w) => ({
|
||||||
|
...w,
|
||||||
|
datosBasicos: {
|
||||||
|
...w.datosBasicos,
|
||||||
|
tipoCiclo: value as any,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger
|
||||||
|
id="tipoCiclo"
|
||||||
|
className="w-full min-w-0 [&>span]:block! [&>span]:truncate!"
|
||||||
|
>
|
||||||
|
<SelectValue placeholder="Selecciona tipo de ciclo…" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{TIPOS_CICLO.map((t) => (
|
||||||
|
<SelectItem key={t.value} value={t.value}>
|
||||||
|
{t.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-1">
|
||||||
|
<Label htmlFor="numCiclos">Número de ciclos</Label>
|
||||||
|
<Input
|
||||||
|
id="numCiclos"
|
||||||
|
type="number"
|
||||||
|
min={1}
|
||||||
|
value={wizard.datosBasicos.numCiclos}
|
||||||
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
|
onChange((w) => ({
|
||||||
|
...w,
|
||||||
|
datosBasicos: {
|
||||||
|
...w.datosBasicos,
|
||||||
|
numCiclos: Number(e.target.value || 1),
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
placeholder="1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Separator className="my-3" />
|
||||||
|
<div className="grid gap-4 sm:grid-cols-2">
|
||||||
|
<TemplateSelectorCard
|
||||||
|
cardTitle="Plantilla de plan de estudios"
|
||||||
|
cardDescription="Selecciona el Word para tu nuevo plan."
|
||||||
|
templatesData={PLANTILLAS_ANEXO_1}
|
||||||
|
/>
|
||||||
|
<TemplateSelectorCard
|
||||||
|
cardTitle="Mapa curricular"
|
||||||
|
cardDescription="Selecciona el Excel para tu mapa curricular."
|
||||||
|
templatesData={PLANTILLAS_ANEXO_2}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
CardDescription,
|
||||||
|
} from '@/components/ui/card'
|
||||||
|
import { Label } from '@/components/ui/label'
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from '@/components/ui/select'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
type TemplateData = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
versions: Array<string>
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default data (kept for backward compatibility if caller doesn't pass templates)
|
||||||
|
const DEFAULT_TEMPLATES_DATA: Array<TemplateData> = [
|
||||||
|
{
|
||||||
|
id: 'sep-2025',
|
||||||
|
name: 'Licenciatura RVOE SEP',
|
||||||
|
versions: ['v2025.2 (Vigente)', 'v2025.1', 'v2024.Final'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'interno-mix',
|
||||||
|
name: 'Estándar Institucional Mixto',
|
||||||
|
versions: ['v2.0', 'v1.5', 'v1.0-beta'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'conacyt',
|
||||||
|
name: 'Formato Posgrado CONAHCYT',
|
||||||
|
versions: ['v3.0 (2025)', 'v2.8'],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
cardTitle?: string
|
||||||
|
cardDescription?: string
|
||||||
|
templatesData?: Array<TemplateData>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TemplateSelectorCard({
|
||||||
|
cardTitle = 'Configuración del Documento',
|
||||||
|
cardDescription = 'Selecciona la base para tu nuevo plan.',
|
||||||
|
templatesData = DEFAULT_TEMPLATES_DATA,
|
||||||
|
}: Props) {
|
||||||
|
const [selectedTemplate, setSelectedTemplate] = useState<string>('')
|
||||||
|
const [selectedVersion, setSelectedVersion] = useState<string>('')
|
||||||
|
|
||||||
|
// Buscamos las versiones de la plantilla seleccionada
|
||||||
|
const currentTemplateData = templatesData.find(
|
||||||
|
(t) => t.id === selectedTemplate,
|
||||||
|
)
|
||||||
|
const availableVersions = currentTemplateData?.versions || []
|
||||||
|
|
||||||
|
const handleTemplateChange = (value: string) => {
|
||||||
|
setSelectedTemplate(value)
|
||||||
|
// Buscamos los datos de esta plantilla
|
||||||
|
const template = templatesData.find((t) => t.id === value)
|
||||||
|
|
||||||
|
// Si tiene versiones, seleccionamos la primera automáticamente
|
||||||
|
if (template && template.versions.length > 0) {
|
||||||
|
setSelectedVersion(template.versions[0])
|
||||||
|
} else {
|
||||||
|
setSelectedVersion('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="w-full max-w-lg gap-2 overflow-hidden">
|
||||||
|
<CardHeader className="px-4 pb-2 sm:px-6 sm:pb-4">
|
||||||
|
<CardTitle className="text-lg">{cardTitle}</CardTitle>
|
||||||
|
<CardDescription>{cardDescription}</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<CardContent className="flex flex-col gap-4">
|
||||||
|
{/* SELECT 1: PRIMARIO (Llamativo) */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label
|
||||||
|
htmlFor="template-select"
|
||||||
|
className="text-foreground text-base font-semibold"
|
||||||
|
>
|
||||||
|
Plantilla
|
||||||
|
</Label>
|
||||||
|
<Select value={selectedTemplate} onValueChange={handleTemplateChange}>
|
||||||
|
<SelectTrigger
|
||||||
|
id="template-select"
|
||||||
|
className="bg-background border-primary/40 focus:ring-primary/20 focus:border-primary flex h-11 w-full min-w-0 items-center justify-between gap-2 text-base shadow-sm [&>span]:block! [&>span]:truncate! [&>span]:text-left"
|
||||||
|
>
|
||||||
|
<SelectValue placeholder="Selecciona una plantilla..." />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{templatesData.map((t) => (
|
||||||
|
<SelectItem key={t.id} value={t.id} className="font-medium">
|
||||||
|
{t.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* SELECT 2: SECUNDARIO (Sutil) */}
|
||||||
|
<div className="space-y-1.5">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Label
|
||||||
|
htmlFor="version-select"
|
||||||
|
className={cn(
|
||||||
|
'text-xs tracking-wider uppercase transition-colors',
|
||||||
|
!selectedTemplate
|
||||||
|
? 'text-muted-foreground/50'
|
||||||
|
: 'text-muted-foreground',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
Versión
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
value={selectedVersion}
|
||||||
|
onValueChange={setSelectedVersion}
|
||||||
|
disabled={!selectedTemplate}
|
||||||
|
>
|
||||||
|
<SelectTrigger
|
||||||
|
id="version-select"
|
||||||
|
className={cn(
|
||||||
|
'flex h-9 min-w-0 items-center justify-between gap-2 text-sm transition-all duration-300',
|
||||||
|
/* AQUÍ ESTÁ EL CAMBIO DE ANCHO: */
|
||||||
|
'w-full max-w-full sm:w-55',
|
||||||
|
|
||||||
|
/* Las correcciones vitales para truncado que ya teníamos: */
|
||||||
|
'min-w-0 [&>span]:block! [&>span]:truncate! [&>span]:text-left',
|
||||||
|
'[&>span]:block [&>span]:min-w-0 [&>span]:truncate [&>span]:text-left',
|
||||||
|
|
||||||
|
!selectedTemplate
|
||||||
|
? 'bg-muted/50 cursor-not-allowed border-transparent opacity-50'
|
||||||
|
: 'bg-muted/20 border-border hover:bg-background hover:border-primary/30',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={
|
||||||
|
!selectedTemplate
|
||||||
|
? '— Esperando plantilla —'
|
||||||
|
: 'Selecciona versión'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{availableVersions.map((v) => (
|
||||||
|
<SelectItem
|
||||||
|
key={v}
|
||||||
|
value={v}
|
||||||
|
className="text-muted-foreground focus:text-foreground text-sm"
|
||||||
|
>
|
||||||
|
{v}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import ReferenciasParaIA from './PasoDetallesPanel/ReferenciasParaIA'
|
import ReferenciasParaIA from './ReferenciasParaIA'
|
||||||
|
|
||||||
import type { NewPlanWizardState } from '@/features/planes/nuevo/types'
|
import type { NewPlanWizardState } from '@/features/planes/nuevo/types'
|
||||||
|
|
||||||
@@ -3,8 +3,8 @@ import * as Icons from 'lucide-react'
|
|||||||
|
|
||||||
import { useNuevoPlanWizard } from './hooks/useNuevoPlanWizard'
|
import { useNuevoPlanWizard } from './hooks/useNuevoPlanWizard'
|
||||||
|
|
||||||
import { PasoBasicosForm } from '@/components/planes/wizard/PasoBasicosForm'
|
import { PasoBasicosForm } from '@/components/planes/wizard/PasoBasicosForm/PasoBasicosForm'
|
||||||
import { PasoDetallesPanel } from '@/components/planes/wizard/PasoDetallesPanel'
|
import { PasoDetallesPanel } from '@/components/planes/wizard/PasoDetallesPanel/PasoDetallesPanel'
|
||||||
import { PasoModoCardGroup } from '@/components/planes/wizard/PasoModoCardGroup'
|
import { PasoModoCardGroup } from '@/components/planes/wizard/PasoModoCardGroup'
|
||||||
import { PasoResumenCard } from '@/components/planes/wizard/PasoResumenCard'
|
import { PasoResumenCard } from '@/components/planes/wizard/PasoResumenCard'
|
||||||
import { WizardControls } from '@/components/planes/wizard/WizardControls'
|
import { WizardControls } from '@/components/planes/wizard/WizardControls'
|
||||||
|
|||||||
@@ -114,3 +114,53 @@ export const REPOSITORIOS = [
|
|||||||
cantidadArchivos: 23,
|
cantidadArchivos: 23,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const ESTRUCTURAS_PLAN_ESTUDIO = [
|
||||||
|
{
|
||||||
|
id: "estruc-1",
|
||||||
|
nombre: "Estructura RVOE 2017.docx",
|
||||||
|
versiones: ["v1.0", "v1.1", "v2.0"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "estruc-2",
|
||||||
|
nombre: "Estructura RVOE 2026.docx",
|
||||||
|
versiones: ["v1.0", "v1.1"],
|
||||||
|
},
|
||||||
|
{ id: "estruc-3", nombre: "Estructura ULSA 2022.docx", versiones: ["v1.0"] },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const PLANTILLAS_ANEXO_1 = [
|
||||||
|
{
|
||||||
|
id: "sep-2025",
|
||||||
|
name: "Licenciatura RVOE SEP.docx",
|
||||||
|
versions: ["v2025.2 (Vigente)", "v2025.1", "v2024.Final"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "interno-mix",
|
||||||
|
name: "Estándar Institucional Mixto.docx",
|
||||||
|
versions: ["v2.0", "v1.5", "v1.0-beta"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "conacyt",
|
||||||
|
name: "Formato Posgrado CONAHCYT.docx",
|
||||||
|
versions: ["v3.0 (2025)", "v2.8"],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const PLANTILLAS_ANEXO_2 = [
|
||||||
|
{
|
||||||
|
id: "sep-2017-xlsx",
|
||||||
|
name: "Licenciatura RVOE 2017.xlsx",
|
||||||
|
versions: ["v2017.0", "v2018.1", "v2019.2", "v2020.Final"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "interno-mix-xlsx",
|
||||||
|
name: "Estándar Institucional Mixto.xlsx",
|
||||||
|
versions: ["v1.0", "v1.5"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "conacyt-xlsx",
|
||||||
|
name: "Formato Posgrado CONAHCYT.xlsx",
|
||||||
|
versions: ["v1.0", "v2.0"],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user