web-client/src/app/(protected)/projects/[slug]/page.tsx
Markov 5a1878ae02
All checks were successful
Deploy Web Client / deploy (push) Successful in 37s
simplify: remove project subscribe, humans get all events
2026-02-23 19:15:28 +01:00

99 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useEffect, useState } from "react";
import { useParams } from "next/navigation";
import { getProjects, Project } from "@/lib/api";
import Sidebar from "@/components/Sidebar";
import KanbanBoard from "@/components/KanbanBoard";
import ChatPanel from "@/components/ChatPanel";
import ProjectFiles from "@/components/ProjectFiles";
import ProjectSettings from "@/components/ProjectSettings";
const TABS = [
{ key: "board", label: "📋 Доска" },
{ key: "chat", label: "💬 Чат" },
{ key: "files", label: "📁 Файлы" },
{ key: "settings", label: "⚙️ Настройки" },
];
export default function ProjectPage() {
const { slug } = useParams<{ slug: string }>();
const [projects, setProjects] = useState<Project[]>([]);
const [loading, setLoading] = useState(true);
const [activeTab, setActiveTab] = useState("board");
useEffect(() => {
getProjects()
.then(setProjects)
.catch(() => {})
.finally(() => setLoading(false));
}, []);
const project = projects.find((p) => p.slug === slug);
const handleProjectUpdated = (updated: Project) => {
setProjects((prev) => prev.map((p) => (p.id === updated.id ? updated : p)));
};
if (loading) {
return <div className="flex h-screen items-center justify-center text-[var(--muted)]">Загрузка...</div>;
}
if (!project) {
return <div className="flex h-screen items-center justify-center text-[var(--muted)]">Проект не найден</div>;
}
return (
<div className="flex h-screen">
<Sidebar projects={projects} activeSlug={slug} />
<main className="flex-1 flex flex-col overflow-hidden">
<header className="border-b border-[var(--border)] px-6 py-3 pl-14 md:pl-6">
<div className="flex items-center justify-between mb-2">
<div>
<h1 className="text-xl font-bold">{project.name}</h1>
{project.description && (
<p className="text-sm text-[var(--muted)]">{project.description}</p>
)}
</div>
</div>
<div className="flex gap-1">
{TABS.map((tab) => (
<button
key={tab.key}
onClick={() => setActiveTab(tab.key)}
className={`px-3 py-1.5 rounded text-sm transition-colors ${
activeTab === tab.key
? "bg-[var(--accent)]/10 text-[var(--accent)]"
: "text-[var(--muted)] hover:bg-white/5 hover:text-[var(--fg)]"
}`}
>
{tab.label}
</button>
))}
</div>
</header>
<div className="flex-1 overflow-hidden">
{activeTab === "board" && (
<KanbanBoard projectId={project.id} projectSlug={project.slug} />
)}
{activeTab === "chat" && project.chat_id && (
<ChatPanel chatId={project.chat_id} fullscreen />
)}
{activeTab === "chat" && !project.chat_id && (
<div className="flex items-center justify-center h-full text-[var(--muted)] text-sm">
Чат недоступен
</div>
)}
{activeTab === "files" && (
<ProjectFiles project={project} />
)}
{activeTab === "settings" && (
<ProjectSettings project={project} onUpdated={handleProjectUpdated} />
)}
</div>
</main>
</div>
);
}