import { useState } from 'react'; import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { ArrowLeft, FileText } from 'lucide-react'; import { ProjectReportDialog } from './ProjectReportDialog.jsx'; import { getAiStatus } from '../../services/ai.js'; import { useUi } from '../../context/ui-context.jsx'; import { useAsync } from '../../hooks/useAsync.js'; import { useUserDrafts } from '../../hooks/useDraftForm.js'; import { getProject } from '../../services/projects.js'; import { Button } from '../../components/Button.jsx'; import { Tabs } from '../../components/Tabs.jsx'; import { StatusBadge } from '../../components/StatusBadge.jsx'; import { CommentsPanel } from '../../components/CommentsPanel.jsx'; import { AttachmentsPanel } from '../../components/AttachmentsPanel.jsx'; import ProjectInfoTab from './ProjectInfoTab.jsx'; import ProjectMembersTab from './ProjectMembersTab.jsx'; import ProjectActivitiesTab from './ProjectActivitiesTab.jsx'; import ProjectGanttTab from './ProjectGanttTab.jsx'; import ProjectCalendarTab from './ProjectCalendarTab.jsx'; export default function ProyectoDetallePage() { const { id } = useParams(); const projectId = Number(id); const { t } = useUi(); const navigate = useNavigate(); const [searchParams, setSearchParams] = useSearchParams(); // La pestaña vive en la URL (?tab=): asi el retorno tras el login (o un F5) vuelve a la misma // pestaña, y el aviso de cambios sin guardar intercepta el cambio de pestaña. // Llegada desde el buscador (Proyectos): ?tab=activities&activity=&activityTab=tasks abre // directo la actividad (y su pestaña de tareas) que coincidio con la busqueda. const tab = searchParams.get('tab') || 'info'; const setTab = (key) => setSearchParams((prev) => { const next = new URLSearchParams(prev); next.set('tab', key); next.delete('activity'); next.delete('activityTab'); return next; }, { replace: true }); // Pestañas con borradores pendientes de este proyecto (el borrador guarda la URL con su ?tab=). const drafts = useUserDrafts(); const dirtyTab = (key) => drafts.some((d) => { if (typeof d.path !== 'string') return false; const [path, query = ''] = d.path.split('?'); return path === `/proyectos/${projectId}` && (new URLSearchParams(query).get('tab') || 'info') === key; }); const deepLinkActivityId = searchParams.get('activity') ? Number(searchParams.get('activity')) : null; const deepLinkActivityTab = searchParams.get('activityTab') || undefined; const { data: project, reload } = useAsync(() => getProject(projectId), [projectId]); // Informe con IA: solo si el superadmin configuro la clave (el backend valida lectura del proyecto). const { data: aiStatus } = useAsync(() => getAiStatus().catch(() => ({ enabled: false })), []); const [reportOpen, setReportOpen] = useState(false); if (!project) return
{t('common_loading')}
; return (

{project.code} — {project.name}

{aiStatus?.enabled && (
)}
setReportOpen(false)} /> {tab === 'info' && } {tab === 'members' && } {tab === 'activities' && ( )} {tab === 'gantt' && } {tab === 'calendar' && } {tab === 'comments' && } {tab === 'documents' && }
); }