From d26ad30433bee6d86c7f4b051f71b78a2afe42bf Mon Sep 17 00:00:00 2001 From: HotelSync Date: Fri, 17 Apr 2026 12:26:03 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20edit=20user=20modal=20empty=20fields=20(?= =?UTF-8?q?key=20prop);=20refactor:=20sidebar=20concept=20A=20=E2=80=94=20?= =?UTF-8?q?by=20work=20role?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sidebar: 6 groups by daily work role instead of mixed functionality - Фронт-деск: calendar, bookings, guests, pos, room-service, reviews - Номерной фонд: rooms, categories, availability, floor-map, housekeeping, tech tasks - Продажи: tariffs, pricing, discounts, rental, channels, website, widget - Аналитика: reports, loyalty - Персонал: users, schedule, documents - Настройки: settings, modules, billing, equipment, wifi, ttlock, sub-settings Removed: separate 'Разработчикам' group (API docs moved to Настройки) Removed: stale localStorage key sidebarGroups_v2 → v3 Fixed: dynamic modules (pos, room-service, etc) placed in logical groups instead of dumped in 'Сервис' Fixed: UserModal key prop — form now resets correctly when switching between employees Co-Authored-By: Claude Sonnet 4.6 --- src/components/layout/Sidebar.tsx | 385 +++++++++++++----------------- src/pages/UsersPage.tsx | 1 + 2 files changed, 164 insertions(+), 222 deletions(-) diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index bb51e06..8f347ed 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -2,9 +2,13 @@ import { NavLink, useLocation, useNavigate } from 'react-router-dom' import { useState, useEffect } from 'react' import { CalendarDays, BookOpen, BedDouble, Globe, Settings, - FileText, LayoutDashboard, Building2, Users, X, Hotel, Puzzle, CalendarRange, Map, LayoutGrid, UserCog, UsersRound, - TrendingUp, Tag, Award, Wrench, Utensils, CalendarClock, Zap, ChevronRight, Star, CreditCard, Monitor, Wifi, KeyRound, - ListChecks, ShoppingCart, ShieldCheck, + FileText, LayoutDashboard, Building2, Users, X, Hotel, Puzzle, + CalendarRange, Map, LayoutGrid, UserCog, UsersRound, + TrendingUp, Tag, Award, Wrench, CalendarClock, Zap, + ChevronRight, Star, CreditCard, Monitor, Wifi, KeyRound, + ListChecks, ShoppingCart, ShieldCheck, BarChart3, Utensils, + Network, Sparkles, UtensilsCrossed, Star as StarIcon, Globe2, + CalendarCheck2, } from 'lucide-react' import { useAuth } from '../../contexts/AuthContext' import { useModules } from '../../contexts/ModulesContext' @@ -19,50 +23,38 @@ interface SidebarProps { // ── Favorites helpers ────────────────────────────────────────────────────── function loadFavorites(): string[] { - try { - return JSON.parse(localStorage.getItem('sidebarFavorites') || '[]') - } catch { - return [] - } + try { return JSON.parse(localStorage.getItem('sidebarFavorites') || '[]') } + catch { return [] } } - function saveFavorites(favs: string[]) { localStorage.setItem('sidebarFavorites', JSON.stringify(favs)) } // ── Group state helpers ──────────────────────────────────────────────────── -type GroupKey = 'basics' | 'prices' | 'service' | 'management' | 'settingsGroup' | 'devGroup' +type GroupKey = 'frontdesk' | 'rooms' | 'sales' | 'analytics' | 'staff' | 'settingsGroup' const DEFAULT_GROUPS: Record = { - basics: true, - prices: false, - service: false, - management: false, - settingsGroup: false, - devGroup: false, + frontdesk: true, + rooms: false, + sales: false, + analytics: false, + staff: false, + settingsGroup:false, } function loadGroups(): Record { try { - const stored = JSON.parse(localStorage.getItem('sidebarGroups_v2') || '{}') + const stored = JSON.parse(localStorage.getItem('sidebarGroups_v3') || '{}') return { ...DEFAULT_GROUPS, ...stored } - } catch { - return { ...DEFAULT_GROUPS } - } + } catch { return { ...DEFAULT_GROUPS } } } - function saveGroups(groups: Record) { - localStorage.setItem('sidebarGroups_v2', JSON.stringify(groups)) + localStorage.setItem('sidebarGroups_v3', JSON.stringify(groups)) } -// ── NavItem with star ────────────────────────────────────────────────────── +// ── NavItem ──────────────────────────────────────────────────────────────── function NavItem({ - to, - icon: Icon, - label, - onClick, - favorites, - onToggleFavorite, + to, icon: Icon, label, onClick, favorites, onToggleFavorite, }: { to: string icon: React.ElementType @@ -72,7 +64,6 @@ function NavItem({ onToggleFavorite: (path: string) => void }) { const isFav = favorites.includes(to) - return (
{ e.preventDefault(); e.stopPropagation(); onToggleFavorite(to) }} title={isFav ? 'Убрать из избранного' : 'Добавить в избранное'} > - +
) } // ── Group header ─────────────────────────────────────────────────────────── -function GroupHeader({ - label, - isOpen, - onToggle, -}: { - label: string - isOpen: boolean - onToggle: () => void +function GroupHeader({ label, isOpen, onToggle }: { + label: string; isOpen: boolean; onToggle: () => void }) { return (