diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c0d089..8b3ed06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog - project.linkedcorp.net +## [4.0.3] - 2026-10-23 +### Fixed +- Las consultas a la IA ("Nuevo con IA" y "Plan con IA") muestran un indicador de proceso con + spinner, mensaje y segundos transcurridos (componente compartido `BusyPanel`); antes parecía + que el botón no hacía nada mientras la IA respondía. + ## [4.0.2] - 2026-10-23 ### Changed - Detección de proyectos duplicados en "Nuevo con IA" ahora la decide la IA, dentro de la misma diff --git a/VERSION b/VERSION index 4d54dad..c4e41f9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.0.2 +4.0.3 diff --git a/backend/package.json b/backend/package.json index f67cbe7..3d45691 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "project-linkedcorp-backend", - "version": "4.0.2", + "version": "4.0.3", "private": true, "type": "module", "main": "src/server.js", diff --git a/frontend/package.json b/frontend/package.json index e07a69b..c1bf081 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "project-linkedcorp-frontend", "private": true, - "version": "4.0.2", + "version": "4.0.3", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/components/BusyPanel.jsx b/frontend/src/components/BusyPanel.jsx new file mode 100644 index 0000000..0d1b271 --- /dev/null +++ b/frontend/src/components/BusyPanel.jsx @@ -0,0 +1,20 @@ +import { useEffect, useState } from 'react'; + +// Indicador de proceso largo (ej. consultas a la IA): spinner, mensaje y segundos transcurridos, +// para que el usuario sepa que el sistema esta trabajando y no colgado. +export function BusyPanel({ message, hint }) { + const [seconds, setSeconds] = useState(0); + useEffect(() => { + const id = setInterval(() => setSeconds((s) => s + 1), 1000); + return () => clearInterval(id); + }, []); + return ( +
+ + ); +} diff --git a/frontend/src/i18n/messages.js b/frontend/src/i18n/messages.js index bad0c39..ac81196 100644 --- a/frontend/src/i18n/messages.js +++ b/frontend/src/i18n/messages.js @@ -26,6 +26,9 @@ export const messages = { ai_plan_generating: 'Generando...', ai_plan_review: 'Desmarca lo que no quieras. Las actividades se crean encadenadas desde hoy, con prioridad media; luego puedes editarlas.', ai_plan_days: 'días', + ai_busy_generating: 'La IA está preparando la propuesta...', + ai_busy_hint: 'Suele tardar entre 5 y 30 segundos. No cierres esta ventana.', + ai_busy_creating: 'Creando actividades y tareas...', ai_plan_day: 'día', ai_plan_apply: 'Crear seleccionadas', ai_plan_creating: 'Creando...', @@ -588,6 +591,9 @@ export const messages = { ai_plan_generating: 'Generating...', ai_plan_review: 'Uncheck what you do not want. Activities are created back to back from today with medium priority; you can edit them later.', ai_plan_days: 'days', + ai_busy_generating: 'AI is preparing the proposal...', + ai_busy_hint: 'It usually takes 5 to 30 seconds. Do not close this window.', + ai_busy_creating: 'Creating activities and tasks...', ai_plan_day: 'day', ai_plan_apply: 'Create selected', ai_plan_creating: 'Creating...', diff --git a/frontend/src/pages/Proyectos/AiPlanDialog.jsx b/frontend/src/pages/Proyectos/AiPlanDialog.jsx index 995c3fb..1959ee4 100644 --- a/frontend/src/pages/Proyectos/AiPlanDialog.jsx +++ b/frontend/src/pages/Proyectos/AiPlanDialog.jsx @@ -4,6 +4,7 @@ import { DetailPopup } from '../../components/DetailPopup.jsx'; import { Button } from '../../components/Button.jsx'; import { Field } from '../../components/Field.jsx'; import { InfoBar } from '../../components/InfoBar.jsx'; +import { BusyPanel } from '../../components/BusyPanel.jsx'; import { useUi } from '../../context/ui-context.jsx'; import { generateProjectPlan, applyProjectPlan } from '../../services/ai.js'; @@ -54,6 +55,7 @@ export function AiPlanDialog({ open, projectId, onClose, onCreated }) { return ( {} : close} width={720} height={620}> {error && {error}} + {busy && } {!plan ? ( <>

{t('ai_plan_hint')}

diff --git a/frontend/src/pages/Proyectos/NewProjectAiDialog.jsx b/frontend/src/pages/Proyectos/NewProjectAiDialog.jsx index faac9ee..246bb12 100644 --- a/frontend/src/pages/Proyectos/NewProjectAiDialog.jsx +++ b/frontend/src/pages/Proyectos/NewProjectAiDialog.jsx @@ -5,6 +5,7 @@ import { Button } from '../../components/Button.jsx'; import { Field, FieldRow } from '../../components/Field.jsx'; import { ComboBox } from '../../components/ComboBox.jsx'; import { InfoBar } from '../../components/InfoBar.jsx'; +import { BusyPanel } from '../../components/BusyPanel.jsx'; import { useUi } from '../../context/ui-context.jsx'; import { useAuth } from '../../context/auth-context.jsx'; import { proposeNewProject, createNewProject } from '../../services/ai.js'; @@ -71,6 +72,7 @@ export function NewProjectAiDialog({ open, deptOptions, minLength = 20, onClose, return ( {error && {error}} + {busy && } {!proposal ? ( <> diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index e3fa47f..c003f7f 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -575,3 +575,9 @@ table.list-table { width: 100%; border-collapse: collapse; font-size: .8rem; } .text-muted { color: rgb(var(--muted)); } .mt-0 { margin-top: 0; } .empty-state { text-align: center; padding: 40px 16px; color: rgb(var(--muted)); } + +/* BusyPanel: proceso largo en curso (consultas a la IA) */ +.busy-panel { display: flex; align-items: center; gap: 14px; padding: 16px; margin: 12px 0; border-radius: 8px; background: rgb(var(--accent) / .08); border: 1px solid rgb(var(--accent) / .3); } +.busy-spinner { width: 28px; height: 28px; flex: none; border-radius: 50%; border: 3px solid rgb(var(--accent) / .25); border-top-color: rgb(var(--accent)); animation: update-spin .9s linear infinite; } +.busy-message { font-weight: 600; } +.busy-hint { font-size: .78rem; margin-top: 2px; }