diff --git a/apps/landing/src/app/test-case/page.tsx b/apps/landing/src/app/test-case/page.tsx
index 94c50d50..26dfb7b5 100644
--- a/apps/landing/src/app/test-case/page.tsx
+++ b/apps/landing/src/app/test-case/page.tsx
@@ -17,12 +17,23 @@ import { TestCaseList } from '@/components/test-case/list/TestCaseList'
import { TestCaseTable } from '@/components/test-case/table/TestCaseTable'
import { TestCaseDisplayBoundary } from '@/components/test-case/TestCaseDisplayBoundary'
import { TestCaseFilterContainer } from '@/components/test-case/TestCaseFilterContainer'
-import { TestCaseProvider } from '@/components/test-case/TestCaseProvider'
+import { TestCaseFilterValue } from '@/components/test-case/TestCaseFilterValue'
+import {
+ FilterTotalMap,
+ TestCaseFilter as TestCaseFilterType,
+ TestCaseProvider,
+} from '@/components/test-case/TestCaseProvider'
import { TestCaseRuleContainer } from '@/components/test-case/TestCaseRuleContainer'
import { TestCaseStat } from '@/components/test-case/TestCaseStat'
+import { TestCaseStatFiltered } from '@/components/test-case/TestCaseStatFiltered'
import { TestCaseTotalBoundary } from '@/components/test-case/TestCaseTotalBoundary'
import { TestCaseTypeToggle } from '@/components/test-case/TestCaseTypeToggle'
-import { createFilterMap, TEST_CASE_FILTERS } from '@/constants'
+import {
+ CATEGORY_PREFIX_MAP,
+ createFilterMap,
+ TEST_CASE_FILTERS,
+ TEST_CASE_FILTERS_MAP,
+} from '@/constants'
import { TestStatusMap } from '@/types'
export const metadata: Metadata = {
@@ -43,13 +54,37 @@ export default async function TestCasePage() {
// Dynamically create filter map based on rule_map keys
const filterMap = createFilterMap(Object.keys(ruleMap))
+
+ const filterTotalMap = Object.fromEntries(
+ Object.entries(filterMap).map(([key]) => [
+ key,
+ {
+ braillify: { total: 0, fail: 0 },
+ world: { total: 0, fail: 0 },
+ jeomsarang: { total: 0, fail: 0 },
+ },
+ ]),
+ ) as FilterTotalMap
+
let totalTest = 0
let totalFail = 0
let totalWorldTest = 0
let totalWorldFail = 0
let totalJeomsarangTest = 0
let totalJeomsarangFail = 0
- const cases = Object.entries(ruleMap).map(([key, value]) => {
+ const cases = Object.entries(ruleMap).map(([key, value], index, self) => {
+ const category = Object.entries(CATEGORY_PREFIX_MAP).find(([prefix]) =>
+ key.startsWith(prefix),
+ )?.[1] as TestCaseFilterType | undefined
+ if (category) {
+ filterTotalMap[category].braillify.total += testStatus[key][0]
+ filterTotalMap[category].braillify.fail += testStatus[key][1]
+ filterTotalMap[category].world.total += testStatus[key][2]
+ filterTotalMap[category].world.fail += testStatus[key][3]
+ filterTotalMap[category].jeomsarang.total += testStatus[key][4]
+ filterTotalMap[category].jeomsarang.fail += testStatus[key][5]
+ }
+
totalTest += testStatus[key][0]
totalFail += testStatus[key][1]
totalWorldTest += testStatus[key][2]
@@ -58,6 +93,8 @@ export default async function TestCasePage() {
totalJeomsarangFail += testStatus[key][5]
const isBut = value.title.includes('다만')
+ const currentClause = key.match(/\d+/)?.[0]
+ const nextClause = self[index + 1]?.[0]?.match(/\d+/)?.[0]
return (
+ {currentClause !== nextClause && (
+
+ )}
)
})
return (
-
+
-
+
- {cases}
+
+
+
+
+
+
+
+
+
+ {cases}
+
-
-
-
+
+
- 접기
+ 목차
-
-
-
-
- 한글 목차
-
+
+
+
+
+
+
-
-
-
+
+
- 접기
+
+ 목차
-
-
-
-
- 한글 목차
-
+
+
+
+
+
+
+}) {
+ const { options } = useTestCase()
+ const selected = options.filters[0]
+ return map[selected]
+}
diff --git a/apps/landing/src/components/test-case/TestCaseProvider.tsx b/apps/landing/src/components/test-case/TestCaseProvider.tsx
index ec87fa71..c43c0071 100644
--- a/apps/landing/src/components/test-case/TestCaseProvider.tsx
+++ b/apps/landing/src/components/test-case/TestCaseProvider.tsx
@@ -22,9 +22,19 @@ export type TestCaseOptions = {
export type FilterMap = Record
+export type FilterTotalMap = Record<
+ TestCaseFilter,
+ {
+ braillify: { total: number; fail: number }
+ world: { total: number; fail: number }
+ jeomsarang: { total: number; fail: number }
+ }
+>
+
const TestCaseContext = createContext<{
testStatusMap: TestStatusMap
filterMap: FilterMap
+ filterTotalMap: FilterTotalMap
options: TestCaseOptions
onChangeOptions: (options: Partial) => void
} | null>(null)
@@ -40,10 +50,12 @@ export function useTestCase() {
export function TestCaseProvider({
testStatusMap,
filterMap,
+ filterTotalMap,
children,
}: {
testStatusMap: TestStatusMap
filterMap: FilterMap
+ filterTotalMap: FilterTotalMap
children: React.ReactNode
}) {
const [options, setOptions] = useState({
@@ -59,6 +71,7 @@ export function TestCaseProvider({
>) {
const { options } = useTestCase()
const isList = options.type === 'list'
return (
@@ -20,6 +21,8 @@ export function TestCaseRuleContainer({
pb={[isList ? '30px' : '40px', null, null, '40px']}
pt={exception ? null : [isList ? '30px' : '40px', null, null, '40px']}
px={['16px', null, null, '60px']}
+ styleOrder={1}
+ {...props}
>
{children}
diff --git a/apps/landing/src/components/test-case/TestCaseStat.tsx b/apps/landing/src/components/test-case/TestCaseStat.tsx
index f66f4f3b..0afa0e6d 100644
--- a/apps/landing/src/components/test-case/TestCaseStat.tsx
+++ b/apps/landing/src/components/test-case/TestCaseStat.tsx
@@ -33,6 +33,7 @@ function CompetitorStat({ label, total, fail }: CompetitorStatProps) {
interface TestCaseStatProps extends ComponentProps> {
showTotal?: boolean
+ colorPercentage?: boolean
total: number
success: number
fail: number
@@ -44,6 +45,7 @@ interface TestCaseStatProps extends ComponentProps> {
export function TestCaseStat({
showTotal = false,
+ colorPercentage = true,
total,
success,
fail,
@@ -60,7 +62,12 @@ export function TestCaseStat({
const hasJeomsarang = jeomsarangTotal != null && jeomsarangTotal > 0
return (
-
+
({braillifyPercent}%)
@@ -110,8 +117,9 @@ export function TestCaseStat({
px: '16px',
bottom: '0',
left: '0',
+ borderRadius: '10px',
})}
- translateY="100%"
+ translateY="calc(100% + 4px)"
>
{hasWorld && (
diff --git a/apps/landing/src/components/test-case/TestCaseStatFiltered.tsx b/apps/landing/src/components/test-case/TestCaseStatFiltered.tsx
new file mode 100644
index 00000000..142b0928
--- /dev/null
+++ b/apps/landing/src/components/test-case/TestCaseStatFiltered.tsx
@@ -0,0 +1,24 @@
+'use client'
+
+import { useTestCase } from './TestCaseProvider'
+import { TestCaseStat } from './TestCaseStat'
+
+export function TestCaseStatFiltered() {
+ const { options, filterTotalMap } = useTestCase()
+ const selected = options.filters[0]
+ return (
+
+ )
+}
diff --git a/apps/landing/src/components/test-case/TestCaseTypeToggle.tsx b/apps/landing/src/components/test-case/TestCaseTypeToggle.tsx
index d4549914..35fbd201 100644
--- a/apps/landing/src/components/test-case/TestCaseTypeToggle.tsx
+++ b/apps/landing/src/components/test-case/TestCaseTypeToggle.tsx
@@ -1,6 +1,7 @@
'use client'
import { Toggle } from '@devup-ui/components'
+import { css } from '@devup-ui/react'
import { ComponentProps } from 'react'
import { useTestCase } from './TestCaseProvider'
@@ -9,6 +10,9 @@ export function TestCaseTypeToggle(props: ComponentProps) {
const { options, onChangeOptions } = useTestCase()
return (
onChangeOptions({ ...options, type: value ? 'table' : 'list' })
}
diff --git a/apps/landing/src/constants/index.ts b/apps/landing/src/constants/index.ts
index 4ece1ab6..e99db926 100644
--- a/apps/landing/src/constants/index.ts
+++ b/apps/landing/src/constants/index.ts
@@ -29,7 +29,11 @@ export const TEST_CASE_FILTERS: { label: string; value: TestCaseFilter }[] = [
},
]
-const CATEGORY_PREFIX_MAP: Record = {
+export const TEST_CASE_FILTERS_MAP = Object.fromEntries(
+ TEST_CASE_FILTERS.map((filter) => [filter.value, filter.label]),
+) as Record
+
+export const CATEGORY_PREFIX_MAP: Record = {
'korean/': 'korean',
'math/': 'math',
'science/': 'science',