diff --git a/roadmap.md b/roadmap.md index b441a97..36cf70a 100644 --- a/roadmap.md +++ b/roadmap.md @@ -115,7 +115,6 @@ - [x] **Ecosistema de Integración**: - [x] **SSO (Single Sign-On)**: Soporte completo OIDC (Google, Okta, Azure AD) (Completado) - [x] **LTI 1.3 Tool Provider**: Integración segura con LMS externos como Canvas o Moodle (Completado) -- [ ] **Apps Móviles**: (Postpuesto por ahora) - [ ] **Accesibilidad**: Auditoría y correcciones WCAG 2.1 ## Fase 9: Portabilidad de Cursos ✅ @@ -224,6 +223,6 @@ **Estado Actual**: La plataforma cuenta con un motor de IA avanzado, gestión multi-tenant completa, tutoría inteligente con memoria histórica, una **interfaz 100% responsiva**, flujos de autenticación diferenciados, **sistema de foros de discusión funcional**, **gestión de anuncios segmentados**, **monetización integrada con Mercado Pago**, **Inscripción Masiva de Usuarios**, **Exportación Avanzada de Calificaciones**, **Librerías de Contenido reutilizables**, **Sistema de Rúbricas Avanzado**, **Secuencias de Aprendizaje**, **Gestión de Equipos Docentes**, **Vista Previa de Cursos**, **Dashboard de Progreso Estudiantil**, **Sistema de Marcadores**, **Biblioteca Global de Activos**, **Interoperabilidad LTI 1.3 con soporte para Deep Linking**, **Analíticas Predictivas de Riesgo de Abandono**, **Integración de Videoconferencia (Jitsi)** y **Portafolios con Perfiles Públicos**. **Próximas Prioridades**: -1. **Apps Móviles**: Desarrollo de versiones nativas para iOS y Android. +1. **Accesibilidad Universal**: Auditoría y ajustes de contraste para cumplimiento WCAG 2.1. 2. **Integraciones Empresariales**: Conectividad con HRIS y ERPs externos. 3. **IA Generativa Avanzada**: Generación automática de contenido de video a partir de guiones. diff --git a/web/experience/src/components/AITutor.tsx b/web/experience/src/components/AITutor.tsx index fc5ee42..a6b91e6 100644 --- a/web/experience/src/components/AITutor.tsx +++ b/web/experience/src/components/AITutor.tsx @@ -17,7 +17,7 @@ export default function AITutor({ lessonId }: { lessonId: string }) { const [isLoading, setIsLoading] = useState(false); const [isOpen, setIsOpen] = useState(false); const [sessionId, setSessionId] = useState(null); - const scrollRef = useRef(null); + const scrollRef = useRef(null); useEffect(() => { // Load session from localStorage on mount @@ -62,19 +62,24 @@ export default function AITutor({ lessonId }: { lessonId: string }) { ); } return ( -
+
{/* Header */}
-
+ {/* Messages */} -
{messages.map((msg, i) => ( -
-
+
+ }`} + aria-label={msg.role === 'user' ? 'Tú dijiste' : 'El tutor dijo'} + > {msg.content}
-
+ ))} {isLoading && ( -
+
  • -
    +
    @@ -128,9 +138,9 @@ export default function AITutor({ lessonId }: { lessonId: string }) { El tutor está pensando...
    -
    +
  • )} -
    + {/* Input */}
    @@ -141,14 +151,16 @@ export default function AITutor({ lessonId }: { lessonId: string }) { onChange={(e) => setInput(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSend()} placeholder="Escribe tu duda aquí..." + aria-label="Escribe tu duda para el tutor" className="w-full bg-white/5 border border-white/10 rounded-xl py-3 px-4 pr-12 text-xs font-medium focus:outline-none focus:border-blue-500/50 transition-colors placeholder:text-gray-600" />

    diff --git a/web/experience/src/components/AppHeader.tsx b/web/experience/src/components/AppHeader.tsx index d033d27..524f725 100644 --- a/web/experience/src/components/AppHeader.tsx +++ b/web/experience/src/components/AppHeader.tsx @@ -22,12 +22,12 @@ export default function AppHeader() { return (

    - +
    {branding?.logo_url ? ( {branding.name} ) : ( -
    + )} @@ -62,10 +62,12 @@ export default function AppHeader() {
    - +
    @@ -86,15 +100,23 @@ export default function NotificationCenter() { ) : notifications.length === 0 ? (
    No hay notificaciones
    ) : ( -
    +
      {notifications.map((n) => ( -
      !n.is_read && markAsRead(n.id)} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + !n.is_read && markAsRead(n.id); + } + }} + aria-label={`Notification: ${n.title}. ${n.message}`} >
      -
      {getIcon(n.notification_type)}
      +

      {n.title}

      {n.message}

      @@ -106,7 +128,10 @@ export default function NotificationCenter() { setIsOpen(false)} + onClick={(e) => { + e.stopPropagation(); + setIsOpen(false); + }} > Ver detalles → @@ -114,9 +139,9 @@ export default function NotificationCenter() {
      -
    + ))} -
    + )}
    diff --git a/web/experience/src/components/blocks/QuizPlayer.tsx b/web/experience/src/components/blocks/QuizPlayer.tsx index 176f808..810b8c1 100644 --- a/web/experience/src/components/blocks/QuizPlayer.tsx +++ b/web/experience/src/components/blocks/QuizPlayer.tsx @@ -76,9 +76,13 @@ export default function QuizPlayer({ id, title, quizData, allowRetry = true, max
    {questions.map((q) => ( -
    -

    {q.question}

    -
    +
    + {q.question} +
    {q.options.map((opt, oIdx) => { const isSelected = userAnswers[q.id]?.includes(oIdx); const isCorrect = q.correct?.includes(oIdx); @@ -99,20 +103,27 @@ export default function QuizPlayer({ id, title, quizData, allowRetry = true, max return ( ); })}
    -
    + ))} {allowRetry && (