+
diff --git a/components/settings-content.tsx b/components/settings-content.tsx
index aebd9cb..4b7c1ee 100644
--- a/components/settings-content.tsx
+++ b/components/settings-content.tsx
@@ -376,7 +376,7 @@ export function SettingsContent() {
@@ -503,7 +503,7 @@ export function SettingsContent() {
@@ -526,7 +526,7 @@ export function SettingsContent() {
diff --git a/components/sidebar.tsx b/components/sidebar.tsx
index b534fc9..0fe8326 100644
--- a/components/sidebar.tsx
+++ b/components/sidebar.tsx
@@ -2,7 +2,7 @@
import { useState } from "react"
import Link from "next/link";
-import { useRouter } from "next/navigation"
+import { usePathname, useRouter } from "next/navigation"
import type React from "react"
import { LayoutDashboard, Users, CalendarClock, Settings, FileCode, List, User, LogOut } from "lucide-react"
@@ -73,11 +73,31 @@ const menuGroupB: MenuItem[] = [
},
]
+function isMasterMenuActive(pathname: string, href: string): boolean {
+ if (href === "/master") {
+ return pathname === "/master" || pathname === "/master/"
+ }
+ return pathname === href || pathname.startsWith(`${href}/`)
+}
+
export function Sidebar({ activeItem, onItemClick }: SidebarProps) {
+ const pathname = usePathname()
const router = useRouter()
const [showLogoutModal, setShowLogoutModal] = useState(false)
const [isLoggingOut, setIsLoggingOut] = useState(false)
+ const menuLinkClassName = (href: string) => {
+ const active = isMasterMenuActive(pathname, href)
+ return `flex items-center gap-3 px-5 py-2.5 rounded-xl border-l-[3px] transition-colors ${
+ active
+ ? "border-app-focus bg-app-sidebar-active font-medium text-app-accent-soft-foreground"
+ : "border-transparent text-muted-foreground hover:bg-app-accent-soft/60 hover:text-foreground"
+ }`
+ }
+
+ const menuLabelClassName = (href: string) =>
+ isMasterMenuActive(pathname, href) ? "text-sm font-semibold" : "text-sm"
+
const handleLogoutClick = () => {
setShowLogoutModal(true)
}
@@ -107,7 +127,7 @@ export function Sidebar({ activeItem, onItemClick }: SidebarProps) {
width: "240px",
minWidth: "240px",
backgroundColor: "#FFFFFF",
- borderRight: "1px solid #E5E5E5",
+ borderRight: "1px solid var(--app-border)",
fontFamily: sidebarFontFamily,
}}
>
@@ -119,7 +139,7 @@ export function Sidebar({ activeItem, onItemClick }: SidebarProps) {
style={{
width: "40px",
height: "40px",
- backgroundColor: "#7C3AED",
+ backgroundColor: "var(--primary)",
}}
>
AI
@@ -140,10 +160,10 @@ export function Sidebar({ activeItem, onItemClick }: SidebarProps) {
style={{
width: "36px",
height: "36px",
- backgroundColor: "#F3E8FF",
+ backgroundColor: "var(--muted)",
}}
>
-
+
{/* Profile Text */}
@@ -169,14 +189,14 @@ export function Sidebar({ activeItem, onItemClick }: SidebarProps) {
onItemClick && onItemClick(item.label)}
>
{item.icon}
-
{item.label}
+
{item.label}
))}
@@ -190,14 +210,14 @@ export function Sidebar({ activeItem, onItemClick }: SidebarProps) {
onItemClick && onItemClick(item.label)}
>
{item.icon}
-
{item.label}
+
{item.label}
))}
@@ -224,7 +244,7 @@ export function Sidebar({ activeItem, onItemClick }: SidebarProps) {
@@ -247,8 +267,8 @@ function MenuItemButton({ item, isActive, onClick }: MenuItemButtonProps) {
onClick={onClick}
className="w-full flex items-center gap-3 px-3 py-2.5 rounded-lg transition-colors duration-150"
style={{
- backgroundColor: isActive ? "#E0EDFF" : "transparent",
- color: isActive ? "#3B82F6" : "#6B7280",
+ backgroundColor: isActive ? "var(--app-accent-muted)" : "transparent",
+ color: isActive ? "var(--foreground)" : "var(--muted-foreground)",
fontFamily: sidebarFontFamily,
fontWeight: isActive ? 500 : 400,
fontSize: "14px",
@@ -257,18 +277,18 @@ function MenuItemButton({ item, isActive, onClick }: MenuItemButtonProps) {
}}
onMouseEnter={(e) => {
if (!isActive) {
- e.currentTarget.style.backgroundColor = "#F0F7FF"
- e.currentTarget.style.color = "#1A1A1A"
+ e.currentTarget.style.backgroundColor = "var(--muted)"
+ e.currentTarget.style.color = "var(--foreground)"
}
}}
onMouseLeave={(e) => {
if (!isActive) {
e.currentTarget.style.backgroundColor = "transparent"
- e.currentTarget.style.color = "#6B7280"
+ e.currentTarget.style.color = "var(--muted-foreground)"
}
}}
>
-
+
{item.icon}
{item.label}
diff --git a/components/test-session-details-content.tsx b/components/test-session-details-content.tsx
index 5d0e9de..b8a780b 100644
--- a/components/test-session-details-content.tsx
+++ b/components/test-session-details-content.tsx
@@ -152,53 +152,117 @@ export default function TestSessionDetailsContent({ examId, onBack }: TestSessio
const getStatusBadge = (label: string) => {
if (label === "진행 중") {
- return 진행 중
+ return (
+
+ 진행 중
+
+ )
}
if (label === "대기 중") {
- return 대기 중
+ return (
+
+ 대기 중
+
+ )
}
if (label === "완료") {
- return 완료
+ return (
+
+ 완료
+
+ )
}
- return {label}
+ return (
+
+ {label}
+
+ )
}
const getExamStatusBadge = (status: string) => {
if (status === "종료됨") {
- return 종료됨
+ return (
+
+ 종료됨
+
+ )
}
if (status === "응시 완료") {
- return 응시 완료
+ return (
+
+ 응시 완료
+
+ )
}
if (status === "응시 중") {
- return 응시 중
+ return (
+
+ 응시 중
+
+ )
}
if (status === "대기 중") {
- return 대기 중
+ return (
+
+ 대기 중
+
+ )
}
- return {status}
+ return (
+
+ {status}
+
+ )
}
const getSubmissionBadge = (label: string) => {
if (label === "시작 안 함") {
- return 시작 안 함
+ return (
+
+ 시작 안 함
+
+ )
}
if (label === "진행 중") {
- return 진행 중
+ return (
+
+ 진행 중
+
+ )
}
if (label === "제출 실패") {
- return 제출 실패
+ return (
+
+ 제출 실패
+
+ )
}
if (label.startsWith("채점 완료")) {
- return {label}
+ return (
+
+ {label}
+
+ )
}
if (label === "제출·채점 중") {
- return {label}
+ return (
+
+ {label}
+
+ )
}
if (label === "제출됨") {
- return 제출됨
+ return (
+
+ 제출됨
+
+ )
}
- return {label}
+ return (
+
+ {label}
+
+ )
}
const getPageNumbers = () => {
@@ -397,8 +461,8 @@ export default function TestSessionDetailsContent({ examId, onBack }: TestSessio
onClick={() => setCurrentPage(page)}
className={`h-8 w-8 p-0 ${
currentPage === page
- ? "bg-blue-600 text-white hover:bg-blue-700"
- : "text-gray-600 hover:bg-gray-100"
+ ? "bg-primary text-primary-foreground hover:bg-primary/90"
+ : "text-muted-foreground hover:bg-muted"
}`}
>
{page}
diff --git a/components/test-sessions-content.tsx b/components/test-sessions-content.tsx
index a9315b7..2e94c4a 100644
--- a/components/test-sessions-content.tsx
+++ b/components/test-sessions-content.tsx
@@ -26,14 +26,42 @@ import {
type TestSessionListItem,
} from "@/lib/master-test-sessions"
+function getMasterSessionStatusBadgeClassName(displayLabel: string, filterStatus?: string): string {
+ if (filterStatus === "Cancelled") {
+ return "border border-red-200 bg-red-50 text-red-700 hover:bg-red-50"
+ }
+ if (displayLabel === "진행 중") {
+ return "border border-emerald-200 bg-emerald-50 font-semibold text-emerald-700 hover:bg-emerald-50"
+ }
+ if (displayLabel === "대기 중") {
+ return "border border-app-ring/40 bg-app-accent-soft font-medium text-app-accent-soft-foreground hover:bg-app-accent-soft"
+ }
+ if (displayLabel === "완료" || displayLabel === "종료" || displayLabel === "종료됨") {
+ return "border border-app-border bg-muted font-medium text-muted-foreground hover:bg-muted"
+ }
+ return "border border-app-border bg-muted font-medium text-muted-foreground hover:bg-muted"
+}
+
function submissionBadgeClassName(label: string): string {
- if (label === "시작 안 함") return "bg-gray-100 text-gray-700 hover:bg-gray-100"
- if (label === "진행 중") return "bg-yellow-100 text-yellow-700 hover:bg-yellow-100"
- if (label === "제출 실패") return "bg-red-100 text-red-700 hover:bg-red-100"
- if (label.startsWith("채점 완료")) return "bg-green-100 text-green-700 hover:bg-green-100"
- if (label === "제출·채점 중") return "bg-amber-100 text-amber-800 hover:bg-amber-100"
- if (label === "제출됨") return "bg-blue-100 text-blue-700 hover:bg-blue-100"
- return "bg-gray-100 text-gray-700 hover:bg-gray-100"
+ if (label === "시작 안 함") {
+ return "border border-app-border bg-muted text-muted-foreground hover:bg-muted"
+ }
+ if (label === "진행 중") {
+ return "border border-amber-200 bg-amber-50 text-amber-700 hover:bg-amber-50"
+ }
+ if (label === "제출 실패") {
+ return "border border-red-200 bg-red-50 text-red-700 hover:bg-red-50"
+ }
+ if (label.startsWith("채점 완료")) {
+ return "border border-emerald-200 bg-emerald-50 text-emerald-800 hover:bg-emerald-50"
+ }
+ if (label === "제출·채점 중") {
+ return "border border-amber-200 bg-amber-50 text-amber-700 hover:bg-amber-50"
+ }
+ if (label === "제출됨") {
+ return "border border-app-border bg-muted text-muted-foreground hover:bg-muted"
+ }
+ return "border border-app-border bg-muted text-muted-foreground hover:bg-muted"
}
/** statusLabel 우선, 없으면 Active/Completed 매핑, 그 외 status 원문 */
@@ -176,9 +204,17 @@ export function TestSessionsContent({ onViewDetails }: TestSessionsContentProps)
const getStatusBadge = (status: string) => {
if (status === "Active") {
- return 진행 중
+ return (
+
+ 진행 중
+
+ )
}
- return 완료
+ return (
+
+ 완료
+
+ )
}
const getPageNumbers = () => {
@@ -344,13 +380,10 @@ export function TestSessionsContent({ onViewDetails }: TestSessionsContentProps)
@@ -674,8 +710,8 @@ export function TestSessionsContent({ onViewDetails }: TestSessionsContentProps)
variant="secondary"
className={
participant.connectionStatus === "Connected"
- ? "bg-green-100 text-green-700 hover:bg-green-100"
- : "bg-red-100 text-red-700 hover:bg-red-100"
+ ? "border border-emerald-200 bg-emerald-50 font-semibold text-emerald-700 hover:bg-emerald-50"
+ : "border border-red-200 bg-red-50 text-red-700 hover:bg-red-50"
}
style={{ fontSize: "12px", fontWeight: 500 }}
>
@@ -698,7 +734,7 @@ export function TestSessionsContent({ onViewDetails }: TestSessionsContentProps)