feat: version 3.2.0 -- Integracion IA: configuracion y plan de actividades
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
import { Plus, Save, Trash2, ArrowRightLeft, FolderUp, Archive, RotateCcw } from 'lucide-react';
|
||||
import { Plus, Save, Trash2, ArrowRightLeft, FolderUp, Archive, RotateCcw, Sparkles } from 'lucide-react';
|
||||
import { useUi } from '../../context/ui-context.jsx';
|
||||
import { useAuth } from '../../context/auth-context.jsx';
|
||||
import { useAsync, useAction } from '../../hooks/useAsync.js';
|
||||
@@ -20,6 +20,8 @@ import { StatusBadge, ProgressBar, DueBadge } from '../../components/StatusBadge
|
||||
import { dueStatus } from '../../utils/dueStatus.js';
|
||||
import { DetailPopup } from '../../components/DetailPopup.jsx';
|
||||
import ActivityDetailPanel from './ActivityDetailPanel.jsx';
|
||||
import { AiPlanDialog } from './AiPlanDialog.jsx';
|
||||
import { getAiStatus } from '../../services/ai.js';
|
||||
import { DraftNotice } from '../../components/DraftNotice.jsx';
|
||||
import { DraftMark, useGuardedClose } from '../../components/NavigationGuard.jsx';
|
||||
import { useDraftForm, useUserDrafts, hasDraftFor } from '../../hooks/useDraftForm.js';
|
||||
@@ -32,6 +34,9 @@ export default function ProjectActivitiesTab({ project, projectId }) {
|
||||
const navigate = useNavigate();
|
||||
const runAction = useAction();
|
||||
const { data: activities, reload } = useAsync(() => listActivitiesByProject(projectId), [projectId]);
|
||||
// Boton de IA solo si el superadmin configuro la clave; el backend valida permisos al usarlo.
|
||||
const { data: aiStatus } = useAsync(() => getAiStatus().catch(() => ({ enabled: false })), []);
|
||||
const [aiPlanOpen, setAiPlanOpen] = useState(false);
|
||||
const [trashOpen, setTrashOpen] = useState(false);
|
||||
const { data: trashed, reload: reloadTrash } = useAsync(
|
||||
() => (trashOpen ? listActivitiesTrash(projectId) : Promise.resolve([])),
|
||||
@@ -272,9 +277,14 @@ export default function ProjectActivitiesTab({ project, projectId }) {
|
||||
{project?.isOwner && (
|
||||
<Button variant="standard" icon={Archive} onClick={() => setTrashOpen(true)}>{t('activities_trash')}</Button>
|
||||
)}
|
||||
{aiStatus?.enabled && (
|
||||
<Button variant="standard" icon={Sparkles} onClick={() => setAiPlanOpen(true)}>{t('ai_plan_button')}</Button>
|
||||
)}
|
||||
<Button variant="accent" icon={Plus} onClick={() => setCreating(true)}>{t('activity_new')}{pendingNew && !creating && <DraftMark />}</Button>
|
||||
</div>
|
||||
|
||||
<AiPlanDialog open={aiPlanOpen} projectId={projectId} onClose={() => setAiPlanOpen(false)} onCreated={reload} />
|
||||
|
||||
<DetailPopup open={trashOpen} title={t('activities_trash')} onClose={() => setTrashOpen(false)} width={480} height={420}>
|
||||
{(trashed || []).length === 0 && <div className="text-muted" style={{ fontSize: '.82rem' }}>{t('activities_trash_empty')}</div>}
|
||||
{(trashed || []).map((a) => (
|
||||
|
||||
Reference in New Issue
Block a user