feat: collapsible sidebar groups with favorites + chat visibility toggle

- Sidebar: collapsible groups (Основное/Цены/Сервис/Управление/Настройки/Разработчикам) with chevron headers, state persisted in localStorage 'sidebarGroups'
- Sidebar: Избранное group at top, star icon on nav item hover to add/remove favorites, stored in localStorage 'sidebarFavorites'
- Sidebar: active route auto-opens its group on navigation
- SettingsPage: 'Скрыть чат' toggle in Внешний вид section, stored in localStorage 'chatHidden'
- AppLayout: conditionally renders ChatWidget based on chatHidden, listens for storage events for reactive updates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-26 10:39:33 +03:00
parent 7f906cb0a3
commit cbddbe6027
3 changed files with 340 additions and 85 deletions

View File

@@ -51,6 +51,18 @@ export function SettingsPage() {
})
}
const [chatHidden, setChatHidden] = useState(
() => localStorage.getItem('chatHidden') === 'true',
)
const toggleChatHidden = () => {
setChatHidden(v => {
const next = !v
localStorage.setItem('chatHidden', String(next))
window.dispatchEvent(new Event('storage'))
return next
})
}
const [form, setForm] = useState({
name: '',
address: '',
@@ -588,6 +600,18 @@ export function SettingsPage() {
<Toggle on={calendarCompact} onChange={toggleCalendarCompact} />
</div>
</div>
{/* Chat widget visibility */}
<div className="pt-3 border-t border-slate-100 dark:border-slate-700">
<p className="text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Чат-виджет</p>
<div className="flex items-center justify-between p-3 rounded-lg bg-slate-50 dark:bg-slate-700/40">
<div>
<p className="text-sm font-medium text-slate-900 dark:text-slate-100">Скрыть чат</p>
<p className="text-xs text-slate-500 dark:text-slate-400">Убрать кнопку чата из интерфейса</p>
</div>
<Toggle on={chatHidden} onChange={toggleChatHidden} />
</div>
</div>
</div>
</>
)}