diff --git a/apps/admin/src/components/features/scores/GpaScoreTable.tsx b/apps/admin/src/components/features/scores/GpaScoreTable.tsx index 6d7a9bfd..4ecea310 100644 --- a/apps/admin/src/components/features/scores/GpaScoreTable.tsx +++ b/apps/admin/src/components/features/scores/GpaScoreTable.tsx @@ -90,7 +90,7 @@ export function GpaScoreTable({ verifyFilter }: Props) { }; return ( -
+
@@ -111,27 +111,27 @@ export function GpaScoreTable({ verifyFilter }: Props) {
-
- 로딩중... +
+ 로딩중...
) : scores.length === 0 ? ( - + 데이터가 없습니다 ) : ( scores.map((score) => ( - + {score.gpaScoreStatusResponse.id}
프로필 {score.siteUserResponse.nickname}
@@ -144,7 +144,7 @@ export function GpaScoreTable({ verifyFilter }: Props) { step="0.01" value={editingGpa} onChange={(e) => setEditingGpa(Number.parseFloat(e.target.value))} - className="w-20 rounded border px-2 py-1" + className="w-20 rounded border border-k-200 bg-k-0 px-2 py-1 typo-regular-4 text-k-700" />
) : ( @@ -159,7 +159,7 @@ export function GpaScoreTable({ verifyFilter }: Props) { step="0.01" value={editingGpaCriteria} onChange={(e) => setEditingGpaCriteria(Number.parseFloat(e.target.value))} - className="w-20 rounded border px-2 py-1" + className="w-20 rounded border border-k-200 bg-k-0 px-2 py-1 typo-regular-4 text-k-700" />
{/* 페이지네이션 */} -
+
diff --git a/apps/admin/src/components/features/scores/LanguageScoreTable.tsx b/apps/admin/src/components/features/scores/LanguageScoreTable.tsx index 6ac176b0..344a6a83 100644 --- a/apps/admin/src/components/features/scores/LanguageScoreTable.tsx +++ b/apps/admin/src/components/features/scores/LanguageScoreTable.tsx @@ -105,7 +105,7 @@ export function LanguageScoreTable({ verifyFilter }: Props) { }; return ( -
+
@@ -126,27 +126,27 @@ export function LanguageScoreTable({ verifyFilter }: Props) {
-
- 로딩중... +
+ 로딩중...
) : scores.length === 0 ? ( - + 데이터가 없습니다 ) : ( scores.map((score) => ( - + {score.languageTestScoreStatusResponse.id}
프로필 {score.siteUserResponse.nickname}
@@ -157,7 +157,7 @@ export function LanguageScoreTable({ verifyFilter }: Props) {
-
+
diff --git a/apps/admin/src/components/features/scores/ScoreVerifyButton.tsx b/apps/admin/src/components/features/scores/ScoreVerifyButton.tsx index 583be920..3a12e780 100644 --- a/apps/admin/src/components/features/scores/ScoreVerifyButton.tsx +++ b/apps/admin/src/components/features/scores/ScoreVerifyButton.tsx @@ -33,7 +33,7 @@ export function ScoreVerifyButton({ currentStatus, onVerifyChange }: Props) { @@ -45,12 +45,12 @@ export function ScoreVerifyButton({ currentStatus, onVerifyChange }: Props) { value={rejectReason} onChange={(e) => setRejectReason(e.target.value)} placeholder="거절 사유" - className="rounded border px-2 py-1" + className="rounded border border-k-200 bg-k-0 px-2 py-1 typo-regular-4 text-k-700" /> @@ -59,7 +59,7 @@ export function ScoreVerifyButton({ currentStatus, onVerifyChange }: Props) { diff --git a/apps/admin/src/components/features/scores/StatusBadge.tsx b/apps/admin/src/components/features/scores/StatusBadge.tsx index 434871d5..2949e357 100644 --- a/apps/admin/src/components/features/scores/StatusBadge.tsx +++ b/apps/admin/src/components/features/scores/StatusBadge.tsx @@ -1,9 +1,9 @@ import type { VerifyStatus } from "@/types/scores"; const statusStyles = { - PENDING: "bg-yellow-100 text-yellow-800", - APPROVED: "bg-green-100 text-green-800", - REJECTED: "bg-red-100 text-red-800", + PENDING: "bg-primary-100 text-primary", + APPROVED: "bg-[#E9F7EC] text-[#15A861]", + REJECTED: "bg-[#FFD9D9] text-[#E22A2D]", }; const statusLabels = { @@ -18,7 +18,7 @@ interface StatusBadgeProps { export function StatusBadge({ status }: StatusBadgeProps) { return ( - + {statusLabels[status]} ); diff --git a/apps/admin/src/components/layout/AdminLayout.tsx b/apps/admin/src/components/layout/AdminLayout.tsx index 636cdc12..d60d44a5 100644 --- a/apps/admin/src/components/layout/AdminLayout.tsx +++ b/apps/admin/src/components/layout/AdminLayout.tsx @@ -4,7 +4,7 @@ interface AdminLayoutProps { export function AdminLayout({ children }: AdminLayoutProps) { return ( -
+
{children}
); diff --git a/apps/admin/src/components/ui/button.tsx b/apps/admin/src/components/ui/button.tsx index 502bf39e..bf9301ee 100644 --- a/apps/admin/src/components/ui/button.tsx +++ b/apps/admin/src/components/ui/button.tsx @@ -5,15 +5,15 @@ import * as React from "react"; import { cn } from "@/lib/utils"; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md typo-sb-11 transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", { variants: { variant: { - default: "bg-primary text-primary-foreground shadow hover:bg-primary/90", - destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", - outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", - secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", + default: "bg-primary text-k-0 shadow-sm hover:bg-primary-600", + destructive: "bg-[#E22A2D] text-k-0 shadow-sm hover:bg-[#BA1E21]", + outline: "border border-k-200 bg-k-0 text-k-700 shadow-sm hover:bg-k-50", + secondary: "bg-k-50 text-k-700 shadow-sm hover:bg-k-100", + ghost: "text-k-600 hover:bg-k-50 hover:text-k-800", link: "text-primary underline-offset-4 hover:underline", }, size: { diff --git a/apps/admin/src/components/ui/input.tsx b/apps/admin/src/components/ui/input.tsx index 875315a0..2cc968f4 100644 --- a/apps/admin/src/components/ui/input.tsx +++ b/apps/admin/src/components/ui/input.tsx @@ -8,7 +8,7 @@ const Input = React.forwardRef>( >( ({ className, ...props }, ref) => (
- +
), ); Table.displayName = "Table"; const TableHeader = React.forwardRef>( - ({ className, ...props }, ref) => , + ({ className, ...props }, ref) => ( + + ), ); TableHeader.displayName = "TableHeader"; @@ -34,7 +36,7 @@ const TableRow = React.forwardRef ( ), @@ -46,7 +48,7 @@ const TableHead = React.forwardRef[role=checkbox]]:translate-y-[2px]", + "h-10 px-2 text-left align-middle typo-sb-11 text-k-600 [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className, )} {...props} @@ -59,7 +61,10 @@ const TableCell = React.forwardRef (
[role=checkbox]]:translate-y-[2px]", className)} + className={cn( + "p-2 align-middle typo-regular-4 text-k-700 [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", + className, + )} {...props} /> ), diff --git a/apps/admin/src/components/ui/tabs.tsx b/apps/admin/src/components/ui/tabs.tsx index 6dcfd29e..06516a17 100644 --- a/apps/admin/src/components/ui/tabs.tsx +++ b/apps/admin/src/components/ui/tabs.tsx @@ -11,10 +11,7 @@ const TabsList = React.forwardRef< >(({ className, ...props }, ref) => ( )); @@ -27,7 +24,7 @@ const TabsTrigger = React.forwardRef< , React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( - + )); TabsContent.displayName = TabsPrimitive.Content.displayName; diff --git a/apps/admin/src/routes/scores/index.tsx b/apps/admin/src/routes/scores/index.tsx index 2fc550f1..d37c217f 100644 --- a/apps/admin/src/routes/scores/index.tsx +++ b/apps/admin/src/routes/scores/index.tsx @@ -1,8 +1,12 @@ import { createFileRoute, redirect } from "@tanstack/react-router"; +import { Building2, FileText, Search, SquarePen, UserCircle2 } from "lucide-react"; import { useState } from "react"; import { GpaScoreTable } from "@/components/features/scores/GpaScoreTable"; import { LanguageScoreTable } from "@/components/features/scores/LanguageScoreTable"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { cn } from "@/lib/utils"; import { isTokenExpired } from "@/lib/utils/jwtUtils"; import { loadAccessToken } from "@/lib/utils/localStorage"; import type { VerifyStatus } from "@/types/scores"; @@ -22,37 +26,141 @@ export const Route = createFileRoute("/scores/")({ function ScoresPage() { const [verifyFilter, setVerifyFilter] = useState("PENDING"); + const [searchKeyword, setSearchKeyword] = useState(""); + + const sideMenus = [ + { label: "대학 관리", icon: Building2, active: true }, + { label: "멘토 관리", icon: UserCircle2, active: false }, + { label: "유저 관리", icon: UserCircle2, active: false }, + { label: "성적 관리", icon: FileText, active: false }, + ] as const; + + const topTabs = ["권역/나라", "나라/대학", "대학 지원 정보", "대학 상세 정보"] as const; + + const verifyFilters: Array<{ value: VerifyStatus; label: string }> = [ + { value: "PENDING", label: "대기중" }, + { value: "APPROVED", label: "승인됨" }, + { value: "REJECTED", label: "거절됨" }, + ]; return ( -
-

성적 관리

- -
- -
+
+
+ + +
+
+
+ {topTabs.map((tab) => ( + + ))} +
- - - GPA 성적 - 어학성적 - +
+

권역/나라

- - - +
+ setSearchKeyword(event.target.value)} + placeholder="검색어를 입력한 후 검색할 카테고리를 선택해주세요" + className="h-9 border-k-100 bg-bg-50 pr-10 typo-regular-4 text-k-700" + /> + +
- - - - + +
+ +
+ {verifyFilters.map((option) => ( + + ))} +
+ +
+ + + + GPA 성적 + + + 어학성적 + + + + + + + + + + + +
+
+
+
); } diff --git a/apps/admin/src/styles.css b/apps/admin/src/styles.css index 89be6093..a873aaf3 100644 --- a/apps/admin/src/styles.css +++ b/apps/admin/src/styles.css @@ -2,9 +2,8 @@ body { @apply m-0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: "Pretendard", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } @@ -13,3 +12,165 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } + +@layer utilities { + .bg-primary { + background-color: #5950f6; + } + + .bg-primary-100 { + background-color: #efeeff; + } + + .bg-primary-600 { + background-color: #6259f7; + } + + .text-primary { + color: #5950f6; + } + + .text-primary-700 { + color: #4e46d9; + } + + .bg-k-0 { + background-color: #ffffff; + } + + .bg-k-50 { + background-color: #f5f5f5; + } + + .bg-k-100 { + background-color: #dddddf; + } + + .bg-bg-50 { + background-color: #fafafa; + } + + .bg-bg-100 { + background-color: #f9f9f9; + } + + .text-k-0 { + color: #ffffff; + } + + .text-k-300 { + color: #aaacaf; + } + + .text-k-400 { + color: #919397; + } + + .text-k-500 { + color: #76797d; + } + + .text-k-600 { + color: #5f6268; + } + + .text-k-700 { + color: #484c52; + } + + .text-k-800 { + color: #31353d; + } + + .text-k-900 { + color: #1a1f27; + } + + .border-k-100 { + border-color: #dddddf; + } + + .border-k-200 { + border-color: #c6c7c9; + } + + .border-k-300 { + border-color: #aaacaf; + } + + .shadow-sdw-a { + box-shadow: 0 4px 40px 0 rgba(26, 31, 39, 0.12); + } + + .typo-bold-1 { + font-size: 24px; + line-height: 140%; + font-weight: 700; + } + + .typo-bold-4 { + font-size: 16px; + line-height: 150%; + font-weight: 700; + } + + .typo-bold-5 { + font-size: 14px; + line-height: 1.2; + font-weight: 700; + } + + .typo-sb-7 { + font-size: 16px; + line-height: 1.2; + font-weight: 600; + } + + .typo-sb-9 { + font-size: 14px; + line-height: 150%; + font-weight: 600; + } + + .typo-sb-10 { + font-size: 13px; + line-height: 150%; + font-weight: 600; + } + + .typo-sb-11 { + font-size: 12px; + line-height: 150%; + font-weight: 600; + } + + .typo-medium-3 { + font-size: 13px; + line-height: 150%; + font-weight: 500; + } + + .typo-medium-4 { + font-size: 12px; + line-height: 150%; + font-weight: 500; + } + + .typo-regular-2 { + font-size: 14px; + line-height: 150%; + font-weight: 400; + } + + .typo-regular-3 { + font-size: 13px; + line-height: 150%; + font-weight: 400; + } + + .typo-regular-4 { + font-size: 12px; + line-height: 150%; + font-weight: 400; + } +}