diff --git a/src/features/communications/CommunicationsModule.tsx b/src/features/communications/CommunicationsModule.tsx
index cb00d71..20671b2 100644
--- a/src/features/communications/CommunicationsModule.tsx
+++ b/src/features/communications/CommunicationsModule.tsx
@@ -26,6 +26,9 @@ export function CommunicationsModule() {
const [connectMode, setConnectMode] = useState<'messenger' | 'email'>('messenger');
const [showEmailTab, setShowEmailTab] = useState(() => localStorage.getItem('krona-show-email') === 'true');
const [showChannelsTab, setShowChannelsTab] = useState(() => localStorage.getItem('krona-show-bot-channels') === 'true');
+ const [orgEmailAllowed, setOrgEmailAllowed] = useState(() => localStorage.getItem('krona-org-email-allowed') !== 'false');
+ const [orgChannelsAllowed, setOrgChannelsAllowed] = useState(() => localStorage.getItem('krona-org-channels-allowed') !== 'false');
+ const [canConnectAccounts, setCanConnectAccounts] = useState(() => localStorage.getItem('krona-org-connect-accounts') !== 'false');
const updateEmailVisibility = (enabled: boolean) => {
setShowEmailTab(enabled);
@@ -39,6 +42,23 @@ export function CommunicationsModule() {
if (!enabled && currentTab === 'channels') handleTabChange('settings');
};
+ const updateOrgEmailAllowed = (enabled: boolean) => {
+ setOrgEmailAllowed(enabled);
+ localStorage.setItem('krona-org-email-allowed', String(enabled));
+ if (!enabled) updateEmailVisibility(false);
+ };
+
+ const updateOrgChannelsAllowed = (enabled: boolean) => {
+ setOrgChannelsAllowed(enabled);
+ localStorage.setItem('krona-org-channels-allowed', String(enabled));
+ if (!enabled) updateChannelsVisibility(false);
+ };
+
+ const updateCanConnectAccounts = (enabled: boolean) => {
+ setCanConnectAccounts(enabled);
+ localStorage.setItem('krona-org-connect-accounts', String(enabled));
+ };
+
// Sync tab with URL search param
const urlTab = searchParams.get('tab') as CommunicationTab | null;
const requestedTab = urlTab && ['messengers', 'email', 'channels', 'contacts', 'settings'].includes(urlTab) ? urlTab : activeTab;
@@ -62,9 +82,9 @@ export function CommunicationsModule() {
onTabChange={handleTabChange}
unreadChats={48}
unreadEmails={10}
- unreadChannels={4}
- showEmailTab={showEmailTab}
- showChannelsTab={showChannelsTab}
+ unreadChannels={4}
+ showEmailTab={showEmailTab && orgEmailAllowed}
+ showChannelsTab={showChannelsTab && orgChannelsAllowed}
/>
@@ -72,12 +92,12 @@ export function CommunicationsModule() {
{currentTab === 'messengers' && (
{ setConnectMode('messenger'); setIsConnectChannelOpen(true); }}
+ onOpenConnectModal={canConnectAccounts ? () => { setConnectMode('messenger'); setIsConnectChannelOpen(true); } : undefined}
onOpenAddContactModal={() => setIsAddContactOpen(true)}
/>
)}
{currentTab === 'email' && (
- setIsComposeEmailOpen(true)} onAddMailbox={() => { setConnectMode('email'); setIsConnectChannelOpen(true); }} />
+ setIsComposeEmailOpen(true)} onAddMailbox={canConnectAccounts ? () => { setConnectMode('email'); setIsConnectChannelOpen(true); } : undefined} />
)}
{currentTab === 'channels' && (
setIsCreateChannelOpen(true)} />
@@ -85,7 +105,7 @@ export function CommunicationsModule() {
{currentTab === 'contacts' && (
setIsAddContactOpen(true)} />
)}
- {currentTab === 'settings' && }
+ {currentTab === 'settings' && }
{/* Modals */}
diff --git a/src/features/communications/components/EmailView.tsx b/src/features/communications/components/EmailView.tsx
index b1178d2..14703c2 100644
--- a/src/features/communications/components/EmailView.tsx
+++ b/src/features/communications/components/EmailView.tsx
@@ -9,7 +9,7 @@ import { useToast } from '../../../shared/ui';
interface EmailViewProps {
onComposeEmail: () => void;
- onAddMailbox: () => void;
+ onAddMailbox?: () => void;
}
export function EmailView({ onComposeEmail, onAddMailbox }: EmailViewProps) {
@@ -61,9 +61,9 @@ export function EmailView({ onComposeEmail, onAddMailbox }: EmailViewProps) {
Почтовые ящики
-
+ {onAddMailbox &&
+ Добавить
-
+ }
{mailboxes.map((mb) => (
diff --git a/src/features/communications/components/MessengersView.tsx b/src/features/communications/components/MessengersView.tsx
index a2d7618..d1d403b 100644
--- a/src/features/communications/components/MessengersView.tsx
+++ b/src/features/communications/components/MessengersView.tsx
@@ -11,7 +11,7 @@ import { Avatar, Badge, Button, ConnectorPill } from '@krona/ui';
import { useToast, Drawer } from '../../../shared/ui';
interface MessengersViewProps {
- onOpenConnectModal: () => void;
+ onOpenConnectModal?: () => void;
onOpenAddContactModal: () => void;
}
@@ -690,7 +690,7 @@ export function MessengersView({ onOpenConnectModal, onOpenAddContactModal }: Me
-
Добавить мессенджер
-
-
}
+ {onOpenConnectModal &&
-
+ }
}
diff --git a/src/features/communications/components/SettingsView.tsx b/src/features/communications/components/SettingsView.tsx
index aa566f7..820eb6c 100644
--- a/src/features/communications/components/SettingsView.tsx
+++ b/src/features/communications/components/SettingsView.tsx
@@ -1,5 +1,5 @@
import { useState } from 'react';
-import { RefreshCw, Trash2, Globe } from 'lucide-react';
+import { RefreshCw, Trash2, Globe, UserCog, Bell, Volume2, PanelTop } from 'lucide-react';
import { useCommunicationsStore } from '../services/communicationsService';
import { Button, Badge } from '@krona/ui';
import { useToast } from '../../../shared/ui';
@@ -9,9 +9,15 @@ interface SettingsViewProps {
onShowEmailTabChange: (enabled: boolean) => void;
showChannelsTab: boolean;
onShowChannelsTabChange: (enabled: boolean) => void;
+ orgEmailAllowed: boolean;
+ onOrgEmailAllowedChange: (enabled: boolean) => void;
+ orgChannelsAllowed: boolean;
+ onOrgChannelsAllowedChange: (enabled: boolean) => void;
+ canConnectAccounts: boolean;
+ onCanConnectAccountsChange: (enabled: boolean) => void;
}
-export function SettingsView({ showEmailTab, onShowEmailTabChange, showChannelsTab, onShowChannelsTabChange }: SettingsViewProps) {
+export function SettingsView({ showEmailTab, onShowEmailTabChange, showChannelsTab, onShowChannelsTabChange, orgEmailAllowed, onOrgEmailAllowedChange, orgChannelsAllowed, onOrgChannelsAllowedChange, canConnectAccounts, onCanConnectAccountsChange }: SettingsViewProps) {
const { showToast } = useToast();
const {
integrations,
@@ -25,6 +31,13 @@ export function SettingsView({ showEmailTab, onShowEmailTabChange, showChannelsT
const [newTemplateText, setNewTemplateText] = useState('');
const [testingId, setTestingId] = useState(null);
+ const [settingsScope, setSettingsScope] = useState<'personal' | 'organization'>('personal');
+ const [notificationsEnabled, setNotificationsEnabled] = useState(() => localStorage.getItem('krona-user-notifications') !== 'false');
+ const [soundsEnabled, setSoundsEnabled] = useState(() => localStorage.getItem('krona-user-sounds') !== 'false');
+ const [compactMode, setCompactMode] = useState(() => localStorage.getItem('krona-user-compact') !== 'false');
+
+ const switchClass = (enabled: boolean) => `relative w-12 h-7 rounded-full transition-colors shrink-0 ${enabled ? 'bg-[var(--krona-primary)]' : 'bg-[var(--krona-surface-muted)]'}`;
+ const switchKnobClass = (enabled: boolean) => `absolute left-1 top-1 w-5 h-5 rounded-full bg-white shadow-sm transition-transform ${enabled ? 'translate-x-5' : 'translate-x-0'}`;
const handleTest = async (id: string) => {
setTestingId(id);
@@ -51,6 +64,12 @@ export function SettingsView({ showEmailTab, onShowEmailTabChange, showChannelsT
return (
+
+ setSettingsScope('personal')} className={`px-4 py-2 rounded-lg text-sm font-semibold transition-colors ${settingsScope === 'personal' ? 'bg-[var(--krona-surface)] text-[var(--krona-primary)] shadow-xs' : 'text-[var(--krona-text-secondary)]'}`}>Мои настройки
+ setSettingsScope('organization')} className={`px-4 py-2 rounded-lg text-sm font-semibold transition-colors ${settingsScope === 'organization' ? 'bg-[var(--krona-surface)] text-[var(--krona-primary)] shadow-xs' : 'text-[var(--krona-text-secondary)]'}`}>Организация
+
+
+ {settingsScope === 'personal' ? <>
Отображение разделов
Показывайте только те способы связи, которыми пользуется организация
@@ -60,8 +79,8 @@ export function SettingsView({ showEmailTab, onShowEmailTabChange, showChannelsT
Email
Почтовые ящики и переписка
- onShowEmailTabChange(!showEmailTab)} className={`relative w-12 h-7 rounded-full transition-colors shrink-0 ${showEmailTab ? 'bg-[var(--krona-primary)]' : 'bg-[var(--krona-surface-muted)]'}`} aria-label="Показывать раздел Email">
-
+ onShowEmailTabChange(!showEmailTab)} className={`${switchClass(showEmailTab)} disabled:opacity-40`} aria-label="Показывать раздел Email">
+
@@ -74,14 +93,37 @@ export function SettingsView({ showEmailTab, onShowEmailTabChange, showChannelsT
role="switch"
aria-checked={showChannelsTab}
onClick={() => onShowChannelsTabChange(!showChannelsTab)}
- className={`relative w-12 h-7 rounded-full transition-colors shrink-0 ${showChannelsTab ? 'bg-[var(--krona-primary)]' : 'bg-[var(--krona-surface-muted)]'}`}
+ disabled={!orgChannelsAllowed}
+ className={`${switchClass(showChannelsTab)} disabled:opacity-40`}
aria-label="Показывать раздел Каналы"
>
-
+
+
+ Поведение и уведомления
+ {[
+ { label: 'Уведомления', hint: 'Новые сообщения и упоминания', icon: Bell, value: notificationsEnabled, set: setNotificationsEnabled, key: 'krona-user-notifications' },
+ { label: 'Звуки', hint: 'Звуковой сигнал новых сообщений', icon: Volume2, value: soundsEnabled, set: setSoundsEnabled, key: 'krona-user-sounds' },
+ { label: 'Компактный интерфейс', hint: 'Больше диалогов и сообщений на экране', icon: PanelTop, value: compactMode, set: setCompactMode, key: 'krona-user-compact' },
+ ].map((item) => { const next = !item.value; item.set(next); localStorage.setItem(item.key, String(next)); }} className={switchClass(item.value)} aria-label={item.label}> )}
+
+ > : <>
+
+
Доступ организации
+ Разрешения действуют для всех пользователей организации
+
+
Разрешить Email
Пользователи смогут подключать и показывать свои ящики
onOrgEmailAllowedChange(!orgEmailAllowed)} className={switchClass(orgEmailAllowed)} aria-label="Разрешить Email организации">
+
Разрешить Каналы
Боты и публичные каналы организации
onOrgChannelsAllowedChange(!orgChannelsAllowed)} className={switchClass(orgChannelsAllowed)} aria-label="Разрешить Каналы организации">
+
Пользователи подключают аккаунты
Разрешить добавление личных мессенджеров и почты
onCanConnectAccountsChange(!canConnectAccounts)} className={switchClass(canConnectAccounts)} aria-label="Разрешить подключение аккаунтов">
+
+
+
+ Пользователи и роли Кто принимает сообщения и управляет подключениями
showToast({ title: 'Добавление пользователя', message: 'Форма приглашения пользователя будет открыта здесь', type: 'info' })}>Добавить пользователя
+ Виктор Владелец Все права
Мария К. Менеджер Чаты и почта
+
{/* 1. Connected Messengers & Connectors */}
@@ -159,9 +201,7 @@ export function SettingsView({ showEmailTab, onShowEmailTabChange, showChannelsT
Обеспечение бесперебойного доступа к международным API Telegram и WhatsApp
-
- Туннель активен (14 ms)
-
+ Туннель активен (14 ms) showToast({ title: 'Настройка VPN', message: 'Открыта настройка единого шлюза организации', type: 'info' })}>Настроить VPN
@@ -268,6 +308,7 @@ export function SettingsView({ showEmailTab, onShowEmailTabChange, showChannelsT
+ >}
);
}