core v1
This commit is contained in:
@@ -1,65 +1,165 @@
|
||||
import { useState } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { DashboardTab } from './components/DashboardTab';
|
||||
import { ClassesTab } from './components/ClassesTab';
|
||||
import { StudentsTab } from './components/StudentsTab';
|
||||
import { LearningTab } from './components/LearningTab';
|
||||
import { NetworkTab } from './components/NetworkTab';
|
||||
import { ClassWorkspace } from './components/ClassWorkspace';
|
||||
import { NavHistoryBar, useRoute } from './components/NavHistoryBar';
|
||||
import { goBack, navigate, parseRoute, pushNav, TAB_LABELS, type TabId } from './navigation';
|
||||
|
||||
const IconDashboard = () => (
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect x="3" y="3" width="7" height="7" rx="1" /><rect x="14" y="3" width="7" height="7" rx="1" />
|
||||
<rect x="3" y="14" width="7" height="7" rx="1" /><rect x="14" y="14" width="7" height="7" rx="1" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const IconClass = () => (
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
||||
<polyline points="9 22 9 12 15 12 15 22" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const IconStudent = () => (
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
|
||||
<circle cx="9" cy="7" r="4" />
|
||||
<path d="M23 21v-2a4 4 0 0 0-3-3.87" /><path d="M16 3.13a4 4 0 0 1 0 7.75" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const IconLearning = () => (
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" />
|
||||
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const IconNetwork = () => (
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M5 12.55a11 11 0 0 1 14.08 0" />
|
||||
<path d="M1.42 9a16 16 0 0 1 21.16 0" />
|
||||
<path d="M8.53 16.11a6 6 0 0 1 6.95 0" />
|
||||
<circle cx="12" cy="20" r="1" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
function App() {
|
||||
const [activeTab, setActiveTab] = useState<string>('dashboard');
|
||||
const route = useRoute();
|
||||
|
||||
useEffect(() => {
|
||||
const initial = parseRoute();
|
||||
if (initial.classId) {
|
||||
return;
|
||||
}
|
||||
pushNav({ kind: 'tab', tab: initial.tab, label: TAB_LABELS[initial.tab] });
|
||||
}, []);
|
||||
|
||||
const setActiveTab = (tab: string) => {
|
||||
navigate(tab as TabId);
|
||||
};
|
||||
|
||||
const handleBackFromClass = () => {
|
||||
goBack(route.tab);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Sidebar navigation panel */}
|
||||
<aside className="sidebar">
|
||||
<div className="brand">
|
||||
<div className="brand-logo">SC</div>
|
||||
<span className="brand-name">Simple Care</span>
|
||||
<div className="brand-logo">RE</div>
|
||||
<div className="brand-text">
|
||||
<span className="brand-name">Simple Care</span>
|
||||
<span className="brand-sub">Rikkei Education</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<ul className="nav-links">
|
||||
<div className="nav-header">Tổng quan</div>
|
||||
<li className="nav-item">
|
||||
<button
|
||||
className={`nav-btn ${activeTab === 'dashboard' ? 'active' : ''}`}
|
||||
onClick={() => setActiveTab('dashboard')}
|
||||
className={`nav-btn ${route.tab === 'dashboard' && !route.classId ? 'active' : ''}`}
|
||||
onClick={() => navigate('dashboard')}
|
||||
>
|
||||
<span className="nav-icon">📊</span>
|
||||
Tổng Quan
|
||||
<span className="nav-icon"><IconDashboard /></span>
|
||||
Tổng quan
|
||||
</button>
|
||||
</li>
|
||||
|
||||
<div className="nav-header">CSDL liên kết</div>
|
||||
<li className="nav-item">
|
||||
<button
|
||||
className={`nav-btn ${route.tab === 'classes' && !route.classId ? 'active' : ''}`}
|
||||
onClick={() => navigate('classes')}
|
||||
>
|
||||
<span className="nav-icon"><IconClass /></span>
|
||||
Lớp học
|
||||
</button>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<button
|
||||
className={`nav-btn ${activeTab === 'classes' ? 'active' : ''}`}
|
||||
onClick={() => setActiveTab('classes')}
|
||||
className={`nav-btn ${route.tab === 'students' && !route.classId ? 'active' : ''}`}
|
||||
onClick={() => navigate('students')}
|
||||
>
|
||||
<span className="nav-icon">🏫</span>
|
||||
Lớp Học
|
||||
<span className="nav-icon"><IconStudent /></span>
|
||||
Sinh viên
|
||||
</button>
|
||||
</li>
|
||||
|
||||
<div className="nav-header">Quản lý học tập</div>
|
||||
<li className="nav-item">
|
||||
<button
|
||||
className={`nav-btn ${route.tab === 'learning' && !route.classId ? 'active' : ''}`}
|
||||
onClick={() => navigate('learning')}
|
||||
>
|
||||
<span className="nav-icon"><IconLearning /></span>
|
||||
Giám sát & Lịch học
|
||||
</button>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<button
|
||||
className={`nav-btn ${activeTab === 'students' ? 'active' : ''}`}
|
||||
onClick={() => setActiveTab('students')}
|
||||
className={`nav-btn ${route.tab === 'network' && !route.classId ? 'active' : ''}`}
|
||||
onClick={() => navigate('network')}
|
||||
>
|
||||
<span className="nav-icon">🎓</span>
|
||||
Sinh Viên
|
||||
<span className="nav-icon"><IconNetwork /></span>
|
||||
Quản lý mạng
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div className="sidebar-footer">
|
||||
<div style={{ fontSize: '0.8rem', color: 'var(--text-muted)' }}>Cấu hình Token:</div>
|
||||
<div style={{ fontSize: '0.75rem', color: 'var(--text-muted)', fontWeight: 500 }}>Kết nối hệ thống</div>
|
||||
<div className="token-badge" title="Token QLDT_TOKEN load từ server .env">
|
||||
🔑 QLDT_TOKEN (Loaded)
|
||||
QLDT_TOKEN đã kết nối
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{/* Main dashboard content container */}
|
||||
<main className="main-content">
|
||||
{activeTab === 'dashboard' && <DashboardTab onNavigate={setActiveTab} />}
|
||||
{activeTab === 'classes' && <ClassesTab />}
|
||||
{activeTab === 'students' && <StudentsTab />}
|
||||
<div className="page-viewport">
|
||||
{route.classId ? (
|
||||
<ClassWorkspace
|
||||
classId={route.classId}
|
||||
sourceTab={route.tab}
|
||||
onBack={handleBackFromClass}
|
||||
renderNavBar={(className) => (
|
||||
<NavHistoryBar classLabel={className} onBack={handleBackFromClass} />
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{route.tab === 'dashboard' && <DashboardTab onNavigate={setActiveTab} />}
|
||||
{route.tab === 'classes' && <ClassesTab />}
|
||||
{route.tab === 'students' && <StudentsTab />}
|
||||
{route.tab === 'learning' && <LearningTab />}
|
||||
{route.tab === 'network' && <NetworkTab />}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user