diff --git a/index.html b/index.html index a2aa25c..361a260 100644 --- a/index.html +++ b/index.html @@ -10,6 +10,7 @@ +
diff --git a/src/components/layout/AppHeader.tsx b/src/components/layout/AppHeader.tsx index 3833725..a45455a 100644 --- a/src/components/layout/AppHeader.tsx +++ b/src/components/layout/AppHeader.tsx @@ -2,30 +2,79 @@ import { useRouterState } from '@tanstack/react-router' import { useTestStore } from '@/store/test-store' import { UserMenu } from '@/components/UserMenu' -const ROUTE_TITLES: Record = { - '/': 'Trang chủ', - '/writing': 'AI Chấm Writing', - '/flash-card': 'Flash Card', - '/toeic': 'Luyện đề TOEIC', - '/toeic/session': '', // dynamic — filled below - '/toeic/result': 'Kết quả bài thi', +const ROUTE_TITLES: Record = { + '/': { eyebrow: 'Học TOEIC cùng AI', title: 'Trang chủ' }, + '/archivement': { eyebrow: 'Thành tích của bạn', title: 'Tôi học', accent: 'học' }, + '/toeic': { eyebrow: 'Luyện đề', title: 'TOEIC Mock Tests', accent: 'Mock' }, + '/writing': { eyebrow: 'AI Coach', title: 'Chấm Writing', accent: 'Writing' }, + '/flash-card': { eyebrow: 'Từ vựng TOEIC', title: 'Flash Card', accent: 'Card' }, + '/settings': { eyebrow: 'Tuỳ chỉnh', title: 'Cài đặt' }, +} + +function matchRouteLabel(pathname: string) { + if (ROUTE_TITLES[pathname]) return ROUTE_TITLES[pathname] + const keys = Object.keys(ROUTE_TITLES).sort((a, b) => b.length - a.length) + for (const k of keys) { + if (k !== '/' && pathname.startsWith(k)) return ROUTE_TITLES[k] + } + return { eyebrow: 'EnglishAI', title: 'EnglishAI' } } export function AppHeader() { const { location } = useRouterState() - const { partId, partName, answers, questions } = useTestStore() + const { testName, parts, answers } = useTestStore() const pathname = location.pathname - let title = ROUTE_TITLES[pathname] ?? 'EnglishAI' - + // In-session mode: show test progress instead of route title if (pathname === '/toeic/session') { - const answered = answers.filter((a) => a !== null).length - title = `Part ${partId} — ${partName} · ${answered}/${questions.length} câu` + const totalQuestions = parts.reduce((sum, p) => sum + p.questions.length, 0) + const answered = Object.values(answers).filter((a) => a !== null).length + return ( +
+
+
Phiên thi
+
+ {testName} · {answered}/{totalQuestions} câu +
+
+ +
+ ) + } + + const { eyebrow, title, accent } = matchRouteLabel(pathname) + const renderTitle = () => { + if (!accent || !title.includes(accent)) return title + const [before, after] = title.split(accent) + return ( + <> + {before} + {accent} + {after} + + ) } return ( -
- {title} +
+
+
{eyebrow}
+
+ {renderTitle()} +
+
) diff --git a/src/components/layout/MobileNav.tsx b/src/components/layout/MobileNav.tsx index 0896c05..30cf5a5 100644 --- a/src/components/layout/MobileNav.tsx +++ b/src/components/layout/MobileNav.tsx @@ -3,7 +3,7 @@ import { cn } from '@/lib/utils' const NAV_ITEMS = [ { to: '/', label: 'Home', icon: 'home', matchPrefix: '/', exact: true }, - { to: '/dashboard', label: 'Thành tích', icon: 'emoji_events', matchPrefix: '/dashboard', exact: false }, + { to: '/archivement', label: 'Thành tích', icon: 'emoji_events', matchPrefix: '/archivement', exact: false }, { to: '/toeic', label: 'Luyện đề', icon: 'assignment', matchPrefix: '/toeic', exact: false }, { to: '/writing', label: 'Writing', icon: 'edit_note', matchPrefix: '/writing', exact: false }, { to: '/settings', label: 'Cài đặt', icon: 'settings', matchPrefix: '/settings', exact: false }, diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index bb59b86..e813442 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -5,7 +5,7 @@ import { useAuthModalStore } from '@/store/auth-modal-store' const NAV_ITEMS = [ { to: '/', label: 'Trang chủ', icon: 'home', matchPrefix: '/', exact: true }, - { to: '/dashboard', label: 'Thành tích', icon: 'emoji_events', matchPrefix: '/dashboard', exact: false }, + { to: '/archivement', label: 'Thành tích', icon: 'emoji_events', matchPrefix: '/archivement', exact: false }, { to: '/toeic', label: 'Luyện đề TOEIC', icon: 'assignment', matchPrefix: '/toeic', exact: false }, { to: '/writing', label: 'AI Writing', icon: 'edit_note', matchPrefix: '/writing', exact: false }, { to: '/flash-card', label: 'Flash Card', icon: 'menu_book', matchPrefix: '/flash-card', exact: false }, @@ -23,60 +23,111 @@ export function Sidebar() { const openModal = useAuthModalStore((s) => s.open) return ( -