feat(communications): align navigation with unified communication workspace

This commit is contained in:
ochenstarik 2026-09-11 13:41:22 +07:00
parent 0c479f568c
commit 9dbe9b7735
2 changed files with 11 additions and 6 deletions

View file

@ -115,11 +115,10 @@ export const SYSTEM_MODULES: ModuleDefinition[] = [
requiredCapability: 'communications', requiredCapability: 'communications',
badge: '3', badge: '3',
sections: [ sections: [
{ id: 'inbox', label: 'Единый Inbox', route: '/communications' }, { id: 'messengers', label: 'Мессенджеры', route: '/communications?section=messengers' },
{ id: 'telegram', label: 'Telegram Bot & Чат', route: '/communications?channel=telegram' }, { id: 'email', label: 'Почта', route: '/communications?section=email' },
{ id: 'whatsapp', label: 'WhatsApp', route: '/communications?channel=whatsapp' }, { id: 'channels', label: 'Каналы', route: '/communications?section=channels' },
{ id: 'team', label: 'Командный чат', route: '/communications?channel=team' }, { id: 'settings', label: 'Настройки', route: '/communications?section=settings' },
{ id: 'channels', label: 'Подключенные каналы', route: '/communications/channels' },
], ],
}, },
{ {

View file

@ -4,6 +4,7 @@ import {
Mail, MessageCircleMore, Paperclip, Plus, Search, Send, Settings2, ShieldCheck, UsersRound, Mail, MessageCircleMore, Paperclip, Plus, Search, Send, Settings2, ShieldCheck, UsersRound,
} from 'lucide-react'; } from 'lucide-react';
import { Button, useToast } from '../../shared/ui'; import { Button, useToast } from '../../shared/ui';
import { useSearchParams } from 'react-router-dom';
type Section = 'messengers' | 'email' | 'channels' | 'settings'; type Section = 'messengers' | 'email' | 'channels' | 'settings';
type Message = { id: string; mine?: boolean; text: string; time: string }; type Message = { id: string; mine?: boolean; text: string; time: string };
@ -112,6 +113,11 @@ function Settings() {
} }
export const CommunicationsModule: React.FC = () => { export const CommunicationsModule: React.FC = () => {
const [section, setSection] = useState<Section>('messengers'); const [searchParams, setSearchParams] = useSearchParams();
const requestedSection = searchParams.get('section');
const section: Section = requestedSection && sections.some((item) => item.id === requestedSection)
? requestedSection as Section
: 'messengers';
const setSection = (nextSection: Section) => setSearchParams({ section: nextSection });
return <div className="h-[calc(100dvh-10.5rem)] md:h-[calc(100vh-8.5rem)] min-h-[560px] flex flex-col bg-krona-surface border border-krona-border rounded-2xl overflow-hidden shadow-krona-soft animate-fade-in"><header className="px-3 sm:px-5 pt-3 sm:pt-4 border-b border-krona-border shrink-0"><div className="flex items-center justify-between gap-3 mb-3"><div><h1 className="text-base sm:text-lg font-bold">Коммуникации</h1><p className="hidden sm:block text-xs text-krona-secondary mt-0.5">Личные мессенджеры, почта и рабочие каналы в одном окне</p></div><span className="text-xs text-emerald-600 flex items-center gap-1.5"><span className="w-2 h-2 rounded-full bg-emerald-500" />Подключено</span></div><nav className="flex gap-1 overflow-x-auto -mb-px" aria-label="Разделы коммуникаций">{sections.map((item) => { const Icon = item.icon; return <button key={item.id} onClick={() => setSection(item.id)} className={`h-12 px-3 sm:px-4 flex items-center gap-2 border-b-2 text-sm font-medium whitespace-nowrap ${section === item.id ? 'border-krona-green text-krona-green' : 'border-transparent text-krona-secondary'}`}><Icon className="w-4 h-4" />{item.label}{item.count ? <Count value={item.count} /> : null}</button>; })}</nav></header><main className="flex-1 min-h-0">{section === 'messengers' && <Messengers />}{section === 'email' && <Email />}{section === 'channels' && <Channels />}{section === 'settings' && <Settings />}</main></div>; return <div className="h-[calc(100dvh-10.5rem)] md:h-[calc(100vh-8.5rem)] min-h-[560px] flex flex-col bg-krona-surface border border-krona-border rounded-2xl overflow-hidden shadow-krona-soft animate-fade-in"><header className="px-3 sm:px-5 pt-3 sm:pt-4 border-b border-krona-border shrink-0"><div className="flex items-center justify-between gap-3 mb-3"><div><h1 className="text-base sm:text-lg font-bold">Коммуникации</h1><p className="hidden sm:block text-xs text-krona-secondary mt-0.5">Личные мессенджеры, почта и рабочие каналы в одном окне</p></div><span className="text-xs text-emerald-600 flex items-center gap-1.5"><span className="w-2 h-2 rounded-full bg-emerald-500" />Подключено</span></div><nav className="flex gap-1 overflow-x-auto -mb-px" aria-label="Разделы коммуникаций">{sections.map((item) => { const Icon = item.icon; return <button key={item.id} onClick={() => setSection(item.id)} className={`h-12 px-3 sm:px-4 flex items-center gap-2 border-b-2 text-sm font-medium whitespace-nowrap ${section === item.id ? 'border-krona-green text-krona-green' : 'border-transparent text-krona-secondary'}`}><Icon className="w-4 h-4" />{item.label}{item.count ? <Count value={item.count} /> : null}</button>; })}</nav></header><main className="flex-1 min-h-0">{section === 'messengers' && <Messengers />}{section === 'email' && <Email />}{section === 'channels' && <Channels />}{section === 'settings' && <Settings />}</main></div>;
}; };