chore: estructura inicial del MVP
Backend (Express + MariaDB) y frontend (React + Vite, identidad Fluent/Windows) con el nucleo funcional: seguridad, organizacion, proyectos, actividades, subtareas, dependencias, dashboard, calendario, gantt, comentarios, adjuntos, notificaciones in-app y catalogos. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { useState } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { ArrowLeft } from 'lucide-react';
|
||||
import { useUi } from '../../context/ui-context.jsx';
|
||||
import { useAsync } from '../../hooks/useAsync.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 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 [tab, setTab] = useState('info');
|
||||
|
||||
const { data: project, loading, reload } = useAsync(() => getProject(projectId), [projectId]);
|
||||
|
||||
if (loading || !project) return <div className="text-muted">{t('common_loading')}</div>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 4 }}>
|
||||
<Button variant="subtle" icon={ArrowLeft} onClick={() => navigate('/proyectos')}>{t('projects_title')}</Button>
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16 }}>
|
||||
<h2 className="page-title mt-0">{project.code} — {project.name}</h2>
|
||||
<StatusBadge name={project.status_name} color={project.status_color} />
|
||||
</div>
|
||||
|
||||
<Tabs
|
||||
tabs={[
|
||||
{ key: 'info', label: t('tab_info') },
|
||||
{ key: 'activities', label: t('tab_activities') },
|
||||
{ key: 'gantt', label: t('tab_gantt') },
|
||||
{ key: 'calendar', label: t('tab_calendar') },
|
||||
{ key: 'comments', label: t('tab_comments') },
|
||||
{ key: 'documents', label: t('tab_documents') },
|
||||
]}
|
||||
active={tab}
|
||||
onChange={setTab}
|
||||
/>
|
||||
|
||||
{tab === 'info' && <ProjectInfoTab project={project} onChanged={reload} />}
|
||||
{tab === 'activities' && <ProjectActivitiesTab projectId={projectId} />}
|
||||
{tab === 'gantt' && <ProjectGanttTab projectId={projectId} />}
|
||||
{tab === 'calendar' && <ProjectCalendarTab projectId={projectId} />}
|
||||
{tab === 'comments' && <CommentsPanel entityType="project" entityId={projectId} />}
|
||||
{tab === 'documents' && <AttachmentsPanel entityType="project" entityId={projectId} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user