From 74b540cac258253c6ea43724ef99ee92a8d8d002 Mon Sep 17 00:00:00 2001 From: PhuocNTB Date: Tue, 30 Jun 2026 15:53:01 +0700 Subject: [PATCH] clean ui --- management/src/App.tsx | 143 +++-- management/src/api.ts | 32 + management/src/components/AccountsTab.tsx | 60 +- .../src/components/AppTemplatePickerModal.tsx | 131 +++++ .../src/components/AppTemplatesSection.tsx | 210 +++++++ management/src/components/ClassWorkspace.tsx | 40 +- .../src/components/ExamRoomWorkspace.tsx | 28 +- management/src/components/ExamsTab.tsx | 152 +++-- management/src/components/NavHistoryBar.tsx | 19 +- .../{NetworkTab.tsx => NetworkSection.tsx} | 136 ++--- .../src/components/OrganizationSection.tsx | 103 ++++ management/src/components/SystemTab.tsx | 92 +++ management/src/index.css | 546 ++++++++++++++++++ management/src/navigation.ts | 122 +++- management/src/utils/appKeywords.ts | 21 + server/internal/db/db.go | 1 + .../handlers/handlers_app_templates.go | 119 ++++ server/internal/models/models.go | 12 + server/main.go | 4 + 19 files changed, 1719 insertions(+), 252 deletions(-) create mode 100644 management/src/components/AppTemplatePickerModal.tsx create mode 100644 management/src/components/AppTemplatesSection.tsx rename management/src/components/{NetworkTab.tsx => NetworkSection.tsx} (56%) create mode 100644 management/src/components/OrganizationSection.tsx create mode 100644 management/src/components/SystemTab.tsx create mode 100644 management/src/utils/appKeywords.ts create mode 100644 server/internal/handlers/handlers_app_templates.go diff --git a/management/src/App.tsx b/management/src/App.tsx index e12d934..cac98f9 100644 --- a/management/src/App.tsx +++ b/management/src/App.tsx @@ -1,17 +1,27 @@ -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { DashboardTab } from './components/DashboardTab'; import { ClassesTab } from './components/ClassesTab'; import { StudentsTab } from './components/StudentsTab'; import { LearningTab } from './components/LearningTab'; import { ExamsTab } from './components/ExamsTab'; import { ExamRoomWorkspace } from './components/ExamRoomWorkspace'; -import { NetworkTab } from './components/NetworkTab'; -import { EmailDomainsTab, MyAccountTab } from './components/AccountsTab'; +import { SystemTab } from './components/SystemTab'; +import { MyAccountTab } from './components/AccountsTab'; import { ChatWidget } from './components/ChatWidget'; import { StaffChatSocket } from './hooks/useStaffChatSocket'; import { ClassWorkspace } from './components/ClassWorkspace'; import { NavHistoryBar, useRoute } from './components/NavHistoryBar'; -import { goBack, navigate, parseRoute, pushNav, TAB_LABELS, type TabId } from './navigation'; +import { + goBack, + navigate, + navigateSystem, + parseRoute, + pushNav, + SYSTEM_SECTION_LABELS, + TAB_LABELS, + type SystemSection, + type TabId, +} from './navigation'; import { useAuth } from './auth/AuthContext'; const IconDashboard = () => ( @@ -51,36 +61,54 @@ const IconExam = () => ( ); -const IconNetwork = () => ( +const IconSystem = () => ( - - - - + + ); -const IconEmail = () => ( +const IconMenu = () => ( - - + ); +const SYSTEM_NAV: { section: SystemSection }[] = [ + { section: 'organization' }, + { section: 'network' }, + { section: 'templates' }, +]; + function App() { const route = useRoute(); const { staff, logout } = useAuth(); + const [sidebarOpen, setSidebarOpen] = useState(false); useEffect(() => { const initial = parseRoute(); if (initial.classId || initial.examId) { return; } - pushNav({ kind: 'tab', tab: initial.tab, label: TAB_LABELS[initial.tab] }); + const label = + initial.tab === 'system' + ? `Hệ thống · ${SYSTEM_SECTION_LABELS[initial.systemSection]}` + : TAB_LABELS[initial.tab]; + pushNav({ + kind: 'tab', + tab: initial.tab, + systemSection: initial.tab === 'system' ? initial.systemSection : undefined, + label, + }); }, []); + useEffect(() => { + setSidebarOpen(false); + }, [route.tab, route.classId, route.examId, route.systemSection]); + const setActiveTab = (tab: string) => { navigate(tab as TabId); + setSidebarOpen(false); }; const handleBackFromWorkspace = () => { @@ -89,9 +117,39 @@ function App() { const inWorkspace = Boolean(route.classId || route.examId); + const classesActive = route.tab === 'classes'; + const learningActive = route.tab === 'learning'; + const examsActive = route.tab === 'exams' || route.examId != null; + const systemActive = route.tab === 'system' && !inWorkspace; + + const goSystem = (section: SystemSection) => { + navigateSystem(section); + setSidebarOpen(false); + }; + + const navBtn = (active: boolean) => `nav-btn${active ? ' active' : ''}`; + return ( <> -