Skip to content

Commit 43af69b

Browse files
authored
♻️ Refactoring TopNavbar & SideNavigation by using antd default style
2 parents d78a6f0 + e220b5b commit 43af69b

File tree

4 files changed

+128
-268
lines changed

4 files changed

+128
-268
lines changed

frontend/components/navigation/SideNavigation.tsx

Lines changed: 49 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
} from "lucide-react";
2323
import type { MenuProps } from "antd";
2424
import { useAuth } from "@/hooks/useAuth";
25-
import { HEADER_CONFIG, FOOTER_CONFIG } from "@/const/layoutConstants";
25+
import { HEADER_CONFIG, FOOTER_CONFIG, SIDER_CONFIG } from "@/const/layoutConstants";
2626

2727
const { Sider } = Layout;
2828

@@ -75,10 +75,6 @@ export function SideNavigation({
7575
const pathname = usePathname();
7676
const [collapsed, setCollapsed] = useState(false);
7777
const [selectedKey, setSelectedKey] = useState("0");
78-
const expandedWidth = 277;
79-
const collapsedWidth = 64;
80-
const siderWidth = collapsed ? collapsedWidth : expandedWidth;
81-
8278
// Update selected key when pathname or currentView changes
8379
useEffect(() => {
8480
// If we have a currentView from parent, use it to determine the key
@@ -105,197 +101,61 @@ export function SideNavigation({
105101
}
106102
}, [pathname, currentView]);
107103

104+
// Helper function to create menu item with consistent icon styling
105+
const createMenuItem = (key: string, Icon: any, labelKey: string, view: string, requiresAuth = false, requiresAdmin = false) => ({
106+
key,
107+
icon: <Icon className="w-4 h-4" />,
108+
label: t(labelKey),
109+
onClick: () => {
110+
if (!isSpeedMode && requiresAdmin && user?.role !== "admin") {
111+
onAdminRequired?.();
112+
} else if (!isSpeedMode && requiresAuth && !user) {
113+
onAuthRequired?.();
114+
} else {
115+
onViewChange?.(view);
116+
}
117+
},
118+
});
119+
108120
// Menu items configuration
109121
const menuItems: MenuProps["items"] = [
110-
{
111-
key: "0",
112-
icon: <Home className="h-4 w-4" />,
113-
label: t("sidebar.homePage"),
114-
onClick: () => {
115-
onViewChange?.("home");
116-
},
117-
},
118-
{
119-
key: "1",
120-
icon: <Bot className="h-4 w-4" />,
121-
label: t("sidebar.startChat"),
122-
onClick: () => {
123-
if (!isSpeedMode && !user) {
124-
onAuthRequired?.();
125-
} else {
126-
onViewChange?.("chat");
127-
}
128-
},
129-
},
130-
{
131-
key: "2",
132-
icon: <Zap className="h-4 w-4" />,
133-
label: t("sidebar.quickConfig"),
134-
onClick: () => {
135-
if (!isSpeedMode && user?.role !== "admin") {
136-
onAdminRequired?.();
137-
} else {
138-
onViewChange?.("setup");
139-
}
140-
},
141-
},
142-
{
143-
key: "3",
144-
icon: <Globe className="h-4 w-4" />,
145-
label: t("sidebar.agentSpace"),
146-
onClick: () => {
147-
if (!isSpeedMode && !user) {
148-
onAuthRequired?.();
149-
} else {
150-
onViewChange?.("space");
151-
}
152-
},
153-
},
154-
{
155-
key: "4",
156-
icon: <ShoppingBag className="h-4 w-4" />,
157-
label: t("sidebar.agentMarket"),
158-
onClick: () => {
159-
if (!isSpeedMode && !user) {
160-
onAuthRequired?.();
161-
} else {
162-
onViewChange?.("market");
163-
}
164-
},
165-
},
166-
{
167-
key: "5",
168-
icon: <Code className="h-4 w-4" />,
169-
label: t("sidebar.agentDev"),
170-
onClick: () => {
171-
if (!isSpeedMode && user?.role !== "admin") {
172-
onAdminRequired?.();
173-
} else {
174-
onViewChange?.("agents");
175-
}
176-
},
177-
},
178-
{
179-
key: "6",
180-
icon: <BookOpen className="h-4 w-4" />,
181-
label: t("sidebar.knowledgeBase"),
182-
onClick: () => {
183-
if (!isSpeedMode && !user) {
184-
onAuthRequired?.();
185-
} else {
186-
onViewChange?.("knowledges");
187-
}
188-
},
189-
},
190-
{
191-
key: "10",
192-
icon: <Puzzle className="h-4 w-4" />,
193-
label: t("sidebar.mcpToolsManagement"),
194-
onClick: () => {
195-
if (!isSpeedMode && user?.role !== "admin") {
196-
onAdminRequired?.();
197-
} else {
198-
onViewChange?.("mcpTools");
199-
}
200-
},
201-
},
202-
{
203-
key: "11",
204-
icon: <Activity className="h-4 w-4" />,
205-
label: t("sidebar.monitoringManagement"),
206-
onClick: () => {
207-
if (!isSpeedMode && user?.role !== "admin") {
208-
onAdminRequired?.();
209-
} else {
210-
onViewChange?.("monitoring");
211-
}
212-
},
213-
},
214-
{
215-
key: "7",
216-
icon: <Settings className="h-4 w-4" />,
217-
label: t("sidebar.modelManagement"),
218-
onClick: () => {
219-
if (!isSpeedMode && user?.role !== "admin") {
220-
onAdminRequired?.();
221-
} else {
222-
onViewChange?.("models");
223-
}
224-
},
225-
},
226-
{
227-
key: "8",
228-
icon: <Database className="h-4 w-4" />,
229-
label: t("sidebar.memoryManagement"),
230-
onClick: () => {
231-
if (!isSpeedMode && user?.role !== "admin") {
232-
onAdminRequired?.();
233-
} else {
234-
onViewChange?.("memory");
235-
}
236-
},
237-
},
238-
{
239-
key: "9",
240-
icon: <Users className="h-4 w-4" />,
241-
label: t("sidebar.userManagement"),
242-
onClick: () => {
243-
if (!isSpeedMode && user?.role !== "admin") {
244-
onAdminRequired?.();
245-
} else {
246-
onViewChange?.("users");
247-
}
248-
},
249-
},
122+
createMenuItem("0", Home, "sidebar.homePage", "home"),
123+
createMenuItem("1", Bot, "sidebar.startChat", "chat", true),
124+
createMenuItem("2", Zap, "sidebar.quickConfig", "setup", false, true),
125+
createMenuItem("3", Globe, "sidebar.agentSpace", "space", true),
126+
createMenuItem("4", ShoppingBag, "sidebar.agentMarket", "market", true),
127+
createMenuItem("5", Code, "sidebar.agentDev", "agents", false, true),
128+
createMenuItem("6", BookOpen, "sidebar.knowledgeBase", "knowledges", true),
129+
createMenuItem("10", Puzzle, "sidebar.mcpToolsManagement", "mcpTools", false, true),
130+
createMenuItem("11", Activity, "sidebar.monitoringManagement", "monitoring", false, true),
131+
createMenuItem("7", Settings, "sidebar.modelManagement", "models", false, true),
132+
createMenuItem("8", Database, "sidebar.memoryManagement", "memory", false, true),
133+
createMenuItem("9", Users, "sidebar.userManagement", "users", false, true),
250134
];
251135

252-
// Calculate sidebar height dynamically based on header and footer reserved heights
253-
const headerReservedHeight = parseInt(HEADER_CONFIG.RESERVED_HEIGHT);
254-
const footerReservedHeight = parseInt(FOOTER_CONFIG.RESERVED_HEIGHT);
255-
const sidebarHeight = `calc(100vh - ${headerReservedHeight}px - ${footerReservedHeight}px)`;
256-
const sidebarTop = `${headerReservedHeight}px`;
136+
// Calculate sidebar height and position dynamically
137+
const sidebarHeight = `calc(100vh - ${HEADER_CONFIG.RESERVED_HEIGHT} - ${FOOTER_CONFIG.RESERVED_HEIGHT})`;
138+
const sidebarTop = HEADER_CONFIG.RESERVED_HEIGHT;
257139

258140
return (
259-
<ConfigProvider
260-
theme={{
261-
components: {
262-
Layout: {
263-
siderBg: "rgba(255, 255, 255, 0.95)",
264-
},
265-
Menu: {
266-
itemBg: "transparent",
267-
itemSelectedBg: "#e6f4ff",
268-
itemSelectedColor: "#1677ff",
269-
itemHoverBg: "#f5f5f5",
270-
itemHoverColor: "#1677ff",
271-
itemActiveBg: "#e6f4ff",
272-
itemColor: "#334155",
273-
iconSize: 16,
274-
itemBorderRadius: 6,
275-
itemMarginInline: 6,
276-
itemPaddingInline: 12,
277-
itemHeight: 36,
278-
},
279-
},
280-
}}
281-
>
282-
<div style={{ position: "relative" }}>
283-
<div style={{ width: `${siderWidth}px`, flexShrink: 0 }}>
141+
<ConfigProvider>
142+
<div className="relative">
143+
<div
144+
className="flex-shrink-0"
145+
style={{
146+
width: collapsed ? SIDER_CONFIG.COLLAPSED_WIDTH : SIDER_CONFIG.EXPANDED_WIDTH
147+
}}
148+
>
284149
<Sider
285150
collapsed={collapsed}
286151
trigger={null}
287152
breakpoint="lg"
288-
collapsedWidth={collapsedWidth}
289-
width={expandedWidth}
290-
className="!bg-white/95 dark:!bg-slate-900/95 border-r border-slate-200 dark:border-slate-700 backdrop-blur-sm shadow-sm"
153+
collapsedWidth={SIDER_CONFIG.COLLAPSED_WIDTH}
154+
width={SIDER_CONFIG.EXPANDED_WIDTH}
155+
className="fixed left-0 bg-white/95 dark:bg-slate-900/95 border-r border-slate-200 dark:border-slate-700 backdrop-blur-sm shadow-sm"
291156
style={{
292-
overflow: "auto",
293-
minHeight: sidebarHeight,
294157
height: sidebarHeight,
295-
position: "fixed",
296158
top: sidebarTop,
297-
left: 0,
298-
width: `${siderWidth}px`,
299159
}}
300160
>
301161
<div className="py-2 h-full">
@@ -304,11 +164,7 @@ export function SideNavigation({
304164
selectedKeys={[selectedKey]}
305165
items={menuItems}
306166
onClick={({ key }) => setSelectedKey(key)}
307-
className="!bg-transparent !border-r-0"
308-
style={{
309-
height: "100%",
310-
borderRight: 0,
311-
}}
167+
className="bg-transparent border-r-0 h-full"
312168
/>
313169
</div>
314170
</Sider>
@@ -320,30 +176,14 @@ export function SideNavigation({
320176
shape="circle"
321177
size="small"
322178
onClick={() => setCollapsed(!collapsed)}
323-
className="shadow-md hover:shadow-lg transition-all"
179+
className="fixed top-1/2 -translate-y-1/2 w-6 h-6 min-w-6 p-0 border-2 border-white shadow-md hover:shadow-lg transition-all z-[800]"
324180
style={{
325-
position: "fixed",
326-
left: collapsed ? "52px" : "264px",
327-
top: "50vh",
328-
transform: "translateY(-50%)",
329-
width: "24px",
330-
height: "24px",
331-
minWidth: "24px",
332-
padding: 0,
333-
display: "flex",
334-
alignItems: "center",
335-
justifyContent: "center",
336-
border: "2px solid white",
337-
zIndex: 800,
181+
left: collapsed
182+
? `${SIDER_CONFIG.COLLAPSED_WIDTH - 12}px`
183+
: `${SIDER_CONFIG.EXPANDED_WIDTH - 13}px`,
338184
transition: "left 0.2s ease",
339185
}}
340-
icon={
341-
collapsed ? (
342-
<ChevronRight className="h-3 w-3" />
343-
) : (
344-
<ChevronLeft className="h-3 w-3" />
345-
)
346-
}
186+
icon={collapsed ? <ChevronRight className="w-3 h-3" /> : <ChevronLeft className="w-3 h-3" />}
347187
/>
348188
</div>
349189
</ConfigProvider>

0 commit comments

Comments
 (0)