fix(communications): make email optional and align switches

This commit is contained in:
ochenstarik 2026-09-12 19:46:50 +07:00
parent ac2db590d0
commit 999c1a0c1e
4 changed files with 41 additions and 16 deletions

View file

@ -24,8 +24,15 @@ export function CommunicationsModule() {
const [isAddContactOpen, setIsAddContactOpen] = useState(false); const [isAddContactOpen, setIsAddContactOpen] = useState(false);
const [isConnectChannelOpen, setIsConnectChannelOpen] = useState(false); const [isConnectChannelOpen, setIsConnectChannelOpen] = useState(false);
const [connectMode, setConnectMode] = useState<'messenger' | 'email'>('messenger'); 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 [showChannelsTab, setShowChannelsTab] = useState(() => localStorage.getItem('krona-show-bot-channels') === 'true');
const updateEmailVisibility = (enabled: boolean) => {
setShowEmailTab(enabled);
localStorage.setItem('krona-show-email', String(enabled));
if (!enabled && currentTab === 'email') handleTabChange('settings');
};
const updateChannelsVisibility = (enabled: boolean) => { const updateChannelsVisibility = (enabled: boolean) => {
setShowChannelsTab(enabled); setShowChannelsTab(enabled);
localStorage.setItem('krona-show-bot-channels', String(enabled)); localStorage.setItem('krona-show-bot-channels', String(enabled));
@ -34,9 +41,12 @@ export function CommunicationsModule() {
// Sync tab with URL search param // Sync tab with URL search param
const urlTab = searchParams.get('tab') as CommunicationTab | null; const urlTab = searchParams.get('tab') as CommunicationTab | null;
const currentTab = urlTab && ['messengers', 'email', 'channels', 'contacts', 'settings'].includes(urlTab) const requestedTab = urlTab && ['messengers', 'email', 'channels', 'contacts', 'settings'].includes(urlTab) ? urlTab : activeTab;
? urlTab const currentTab = requestedTab === 'email' && !showEmailTab
: activeTab; ? 'messengers'
: requestedTab === 'channels' && !showChannelsTab
? 'messengers'
: requestedTab;
const handleTabChange = (tab: CommunicationTab) => { const handleTabChange = (tab: CommunicationTab) => {
setActiveTab(tab); setActiveTab(tab);
@ -53,6 +63,7 @@ export function CommunicationsModule() {
unreadChats={48} unreadChats={48}
unreadEmails={10} unreadEmails={10}
unreadChannels={4} unreadChannels={4}
showEmailTab={showEmailTab}
showChannelsTab={showChannelsTab} showChannelsTab={showChannelsTab}
/> />
</div> </div>
@ -74,7 +85,7 @@ export function CommunicationsModule() {
{currentTab === 'contacts' && ( {currentTab === 'contacts' && (
<ContactsView onAddContactModal={() => setIsAddContactOpen(true)} /> <ContactsView onAddContactModal={() => setIsAddContactOpen(true)} />
)} )}
{currentTab === 'settings' && <SettingsView showChannelsTab={showChannelsTab} onShowChannelsTabChange={updateChannelsVisibility} />} {currentTab === 'settings' && <SettingsView showEmailTab={showEmailTab} onShowEmailTabChange={updateEmailVisibility} showChannelsTab={showChannelsTab} onShowChannelsTabChange={updateChannelsVisibility} />}
</main> </main>
{/* Modals */} {/* Modals */}

View file

@ -9,6 +9,7 @@ interface CommunicationsHeaderProps {
unreadChats: number; unreadChats: number;
unreadEmails: number; unreadEmails: number;
unreadChannels: number; unreadChannels: number;
showEmailTab: boolean;
showChannelsTab: boolean; showChannelsTab: boolean;
} }
@ -18,6 +19,7 @@ export function CommunicationsHeader({
unreadChats, unreadChats,
unreadEmails, unreadEmails,
unreadChannels, unreadChannels,
showEmailTab,
showChannelsTab, showChannelsTab,
}: CommunicationsHeaderProps) { }: CommunicationsHeaderProps) {
const tabItems = [ const tabItems = [
@ -49,7 +51,11 @@ export function CommunicationsHeader({
label: 'Настройки', label: 'Настройки',
icon: <Settings className="w-4 h-4" />, icon: <Settings className="w-4 h-4" />,
}, },
].filter((item) => item.id !== 'channels' || showChannelsTab); ].filter((item) => {
if (item.id === 'email') return showEmailTab;
if (item.id === 'channels') return showChannelsTab;
return true;
});
return ( return (
<header className="bg-[var(--krona-surface)] border-b border-[var(--krona-border-subtle)] px-3 sm:px-5 py-1.5 shrink-0 overflow-hidden"> <header className="bg-[var(--krona-surface)] border-b border-[var(--krona-border-subtle)] px-3 sm:px-5 py-1.5 shrink-0 overflow-hidden">

View file

@ -684,13 +684,6 @@ export function MessengersView({ onOpenConnectModal, onOpenAddContactModal }: Me
> >
MAX MAX
</ConnectorPill> </ConnectorPill>
<ConnectorPill
active={activeConnector === 'email'}
onClick={() => setActiveConnector('email')}
count={10}
>
Email
</ConnectorPill>
</div> </div>
{/* Smooth fade-out indicator on the right edge */} {/* Smooth fade-out indicator on the right edge */}
<div className="pointer-events-none absolute right-0 top-0 bottom-0 w-8 bg-gradient-to-l from-[var(--krona-surface)] to-transparent" /> <div className="pointer-events-none absolute right-0 top-0 bottom-0 w-8 bg-gradient-to-l from-[var(--krona-surface)] to-transparent" />

View file

@ -5,11 +5,13 @@ import { Button, Badge } from '@krona/ui';
import { useToast } from '../../../shared/ui'; import { useToast } from '../../../shared/ui';
interface SettingsViewProps { interface SettingsViewProps {
showEmailTab: boolean;
onShowEmailTabChange: (enabled: boolean) => void;
showChannelsTab: boolean; showChannelsTab: boolean;
onShowChannelsTabChange: (enabled: boolean) => void; onShowChannelsTabChange: (enabled: boolean) => void;
} }
export function SettingsView({ showChannelsTab, onShowChannelsTabChange }: SettingsViewProps) { export function SettingsView({ showEmailTab, onShowEmailTabChange, showChannelsTab, onShowChannelsTabChange }: SettingsViewProps) {
const { showToast } = useToast(); const { showToast } = useToast();
const { const {
integrations, integrations,
@ -50,9 +52,21 @@ export function SettingsView({ showChannelsTab, onShowChannelsTabChange }: Setti
return ( return (
<div className="flex-1 min-h-0 flex flex-col p-4 sm:p-6 bg-[var(--krona-bg-workspace)] overflow-y-auto space-y-6"> <div className="flex-1 min-h-0 flex flex-col p-4 sm:p-6 bg-[var(--krona-bg-workspace)] overflow-y-auto space-y-6">
<section className="p-4 sm:p-5 rounded-2xl bg-[var(--krona-surface)] border border-[var(--krona-border-subtle)] shadow-xs"> <section className="p-4 sm:p-5 rounded-2xl bg-[var(--krona-surface)] border border-[var(--krona-border-subtle)] shadow-xs">
<div className="flex items-center justify-between gap-4"> <h3 className="font-bold text-base text-[var(--krona-text-primary)]">Отображение разделов</h3>
<p className="text-xs text-[var(--krona-text-secondary)] mt-0.5 mb-4">Показывайте только те способы связи, которыми пользуется организация</p>
<div className="divide-y divide-[var(--krona-border-subtle)]">
<div className="flex items-center justify-between gap-4 py-3">
<div> <div>
<h3 className="font-bold text-base text-[var(--krona-text-primary)]">Раздел «Каналы»</h3> <div className="font-semibold text-sm text-[var(--krona-text-primary)]">Email</div>
<div className="text-xs text-[var(--krona-text-secondary)]">Почтовые ящики и переписка</div>
</div>
<button type="button" role="switch" aria-checked={showEmailTab} onClick={() => 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">
<span className={`absolute left-1 top-1 w-5 h-5 rounded-full bg-white shadow-sm transition-transform ${showEmailTab ? 'translate-x-5' : 'translate-x-0'}`} />
</button>
</div>
<div className="flex items-center justify-between gap-4 py-3">
<div>
<div className="font-semibold text-sm text-[var(--krona-text-primary)]">Каналы</div>
<p className="text-xs text-[var(--krona-text-secondary)] mt-0.5">Боты и публичные каналы организации</p> <p className="text-xs text-[var(--krona-text-secondary)] mt-0.5">Боты и публичные каналы организации</p>
</div> </div>
<button <button
@ -63,9 +77,10 @@ export function SettingsView({ showChannelsTab, onShowChannelsTabChange }: Setti
className={`relative w-12 h-7 rounded-full transition-colors shrink-0 ${showChannelsTab ? 'bg-[var(--krona-primary)]' : 'bg-[var(--krona-surface-muted)]'}`} className={`relative w-12 h-7 rounded-full transition-colors shrink-0 ${showChannelsTab ? 'bg-[var(--krona-primary)]' : 'bg-[var(--krona-surface-muted)]'}`}
aria-label="Показывать раздел Каналы" aria-label="Показывать раздел Каналы"
> >
<span className={`absolute top-1 w-5 h-5 rounded-full bg-white shadow transition-transform ${showChannelsTab ? 'translate-x-6' : 'translate-x-1'}`} /> <span className={`absolute left-1 top-1 w-5 h-5 rounded-full bg-white shadow-sm transition-transform ${showChannelsTab ? 'translate-x-5' : 'translate-x-0'}`} />
</button> </button>
</div> </div>
</div>
</section> </section>
{/* 1. Connected Messengers & Connectors */} {/* 1. Connected Messengers & Connectors */}
<section className="p-5 rounded-2xl bg-[var(--krona-surface)] border border-[var(--krona-border-subtle)] shadow-xs"> <section className="p-5 rounded-2xl bg-[var(--krona-surface)] border border-[var(--krona-border-subtle)] shadow-xs">