Skip to content
Merged
23 changes: 4 additions & 19 deletions service/app/src/app/create/components/questionList.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
"use client"

import { PrimaryBoxButton } from "@ject-5-fe/design/components/button"
import { StickyActionBar } from "@ject-5-fe/design/components/stickyActionBar"
import { Add } from "@ject-5-fe/design/icons"
import { useRef } from "react"
import { useShallow } from "zustand/react/shallow"

import { useListboxNavigation } from "@/shared/lib/useListBoxNavigation"
import { FloatingAddButton } from "@/shared/ui/floatingAddButton"

import { useCreateGameStore } from "../store/useCreateGameStore"
import { Question } from "./question"
Expand Down Expand Up @@ -35,10 +33,10 @@ export function QuestionList() {
)

return (
<div className="flex h-full min-h-0 w-[420px] flex-col bg-background-tertiary px-[32px] py-[16px]">
<div className="relative flex h-full min-h-0 w-[420px] flex-col bg-background-tertiary px-32 py-16">
<div
ref={listboxRef}
className="flex flex-col gap-24 overflow-y-auto"
className="flex flex-col gap-24 overflow-y-auto pb-[140px]"
role="listbox"
aria-label="문제 목록"
tabIndex={0}
Expand Down Expand Up @@ -75,20 +73,7 @@ export function QuestionList() {
})}
</div>

<StickyActionBar
position="sticky"
edge="bottom"
className="mt-auto px-[32px] pb-[16px]"
contentClassName="w-full"
>
<PrimaryBoxButton
className="aspect-square size-64 rounded-full"
onClick={addQuestion}
aria-label="문제 추가"
>
<Add className="size-full" />
</PrimaryBoxButton>
</StickyActionBar>
<FloatingAddButton onClick={addQuestion} ariaLabel="문제 추가" />
</div>
)
}
2 changes: 1 addition & 1 deletion service/app/src/app/game/[gameId]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default async function GameLayout({

return (
<GameProvider initialGameDetail={gameDetail.data}>
<div className="flex h-screen w-screen flex-col bg-background-primary">
<div className="relative flex h-screen w-screen flex-col bg-background-primary pt-[90px]">
{children}
</div>
</GameProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@

- **URL**: `/game/[gameId]/play`
- **핵심 기능**: 게임 진행, 문제 네비게이션, 점수 관리, 정답 확인
- **조작 방식**: 버튼 클릭 또는 키보드 (Enter, →, ←)

## 테스트 시나리오

### 1. 초기 렌더링 및 기본 UI

- **홈 로고**: 클릭 시 나가기 다이얼로그 표시 → "네" 클릭 시 홈 이동
- **프로그레스바**: 현재 라운드/전체 라운드 비율로 진행률 표시
- **이전 문제 버튼**: 첫 번째 문제에서는 숨김 처리
- **다음 문제 버튼**: 항상 표시
- **게임 종료 버튼**: Cross 아이콘, 클릭 시 나가기 다이얼로그
- **문제 텍스트**: 현재 라운드의 질문 표시
- **문제 이미지**: 이미지가 있는 경우 표시, 없는 경우 숨김
- **정답 보기 버튼**: 기본 상태에서 표시
- **"정답은?" 버튼**: 정답 숨김 상태에서 표시
- **"다음" 버튼**: 정답 공개 상태에서 표시

### 2. 점수판 기능

Expand All @@ -33,33 +33,37 @@
- **점수 범위 제한**: -100점 ~ +100점 범위 내에서만 조정 가능
- **점수 표시**: "X점" 형태로 표시

### 3. 문제 네비게이션
### 3. 정답 공개 및 문제 이동

#### 3.1 이전 문제
#### 3.1 버튼 클릭 조작

- **첫 번째 문제**: "이전 문제" 버튼 숨김
- **두 번째 문제 이상**: "이전 문제" 버튼 표시
- **이전 문제 이동**: 클릭 시 이전 라운드로 이동, 프로그레스바 감소
- **정답 상태 초기화**: 이전 문제 이동 시 정답 숨김 상태로 리셋
- **"정답은?" 버튼 클릭**: 정답 공개, URL에 `answer=true` 추가, "다음" 버튼 표시
- **"다음" 버튼 클릭**: 다음 문제로 이동, 정답 숨김 상태로 시작

#### 3.2 다음 문제
#### 3.2 키보드 조작

- **중간 문제**: "다음 문제" 버튼 클릭 시 다음 라운드로 이동
- **마지막 문제**: "다음 문제" 버튼 클릭 시 결과 페이지(`/game/[gameId]/result`)로 이동
- **정답 상태 초기화**: 다음 문제 이동 시 정답 숨김 상태로 리셋
| 키 | 정답 숨김 상태 | 정답 공개 상태 |
|---|---|---|
| Enter | 정답 공개 | 다음 문제 (정답 숨김) |
| → (ArrowRight) | 정답 공개 | 다음 문제 (정답 숨김) |
| ← (ArrowLeft) | 이전 문제 (정답 숨김) | 이전 문제 (정답 숨김) |

### 4. 정답 확인 기능
- **1번 문제에서 ← 키**: 무반응 (이전 문제 없음)
- **마지막 문제 정답 공개 후 Enter/→**: 결과 페이지(`/game/[gameId]/result`)로 이동

#### 4.1 정답 보기
### 4. 문제 네비게이션

- **정답 보기 버튼**: 클릭 시 정답 텍스트 표시
- **정답 숨기기 버튼**: 정답이 표시된 상태에서 클릭 시 정답 숨김
- **정답 텍스트**: `currentQuestion.questionAnswer` 표시
#### 4.1 이전 문제

#### 4.2 정답 상태 유지
- **1번 문제**: ← 키 입력 시 무반응
- **2번 문제 이상**: ← 키 입력 시 이전 라운드로 이동
- **정답 상태 초기화**: 이전 문제 이동 시 정답 숨김 상태로 시작

- **라운드 변경 시**: 이전/다음 문제 이동 시 정답 상태 초기화
- **페이지 새로고침**: 정답 상태 유지 (Zustand persist)
#### 4.2 다음 문제

- **중간 문제**: Enter/→ 키 또는 "다음" 버튼으로 다음 라운드 이동
- **마지막 문제**: 결과 페이지로 이동
- **정답 상태 초기화**: 다음 문제 이동 시 정답 숨김 상태로 시작

### 5. 나가기 기능

Expand All @@ -77,15 +81,15 @@
### 6. 프로그레스바 동작

- **진행률 계산**: `(currentRound / totalRounds) * 100`
- **첫 번째 문제**: 0% 또는 최소값
- **마지막 문제**: 100% 또는 최대값
- **중간 문제**: 해당 라운드에 맞는 진행률 표시
- **다음 문제 이동**: 진행률 증가
- **이전 문제 이동**: 진행률 감소

### 7. URL 파라미터 동작

- **라운드 변경 시**: `?q=${newRound}` 형태로 URL 업데이트
- **이전 문제**: `router.replace()` 사용하여 히스토리 스택에 추가하지 않음
- **다음 문제**: `router.replace()` 사용하여 히스토리 스택에 추가하지 않음
- **라운드 변경**: `?q=${round}` 형태로 URL 업데이트
- **정답 공개**: `?q=${round}&answer=true` 형태로 URL 업데이트
- **정답 숨김**: `answer` 파라미터 제거
- **초기 상태**: query parameter 없음 (1번 문제, 정답 숨김)

### 8. 게임 상태 관리

Expand All @@ -94,15 +98,41 @@
- **게임 상세 정보**: 문제 목록과 질문/답변 데이터 관리
- **상태 지속성**: 페이지 새로고침 시에도 상태 유지 (팀 구성은 reload 후에도 유지, 점수는 이탈/종료 시 초기화됨)

## 구현된 테스트 목록

### 게임 진행 - 기본 UI
- [x] 1번 문제: '정답은?' 버튼이 표시되어야 한다
- [x] 홈 로고 클릭 시 나가기 다이얼로그가 뜨고, '아니요' 클릭 시 페이지에 머문다
- [x] 게임 종료 아이콘 클릭 시 나가기 다이얼로그가 뜬다
- [x] 점수판을 접고 다시 펼칠 수 있어야 한다
- [x] 팀 점수를 클릭 당 +1, -1씩 조정할 수 있다

### 게임 진행 - 버튼 클릭 조작
- [x] '정답은?' 버튼 클릭 시 정답이 공개되고 '다음' 버튼이 표시된다
- [x] 정답 공개 후 '다음' 버튼 클릭 시 다음 문제로 이동한다

### 게임 진행 - 키보드 조작
- [x] Enter 키로 정답을 공개할 수 있다
- [x] → 키로 정답을 공개할 수 있다
- [x] 정답 공개 후 Enter 키로 다음 문제로 이동할 수 있다
- [x] 정답 공개 후 → 키로 다음 문제로 이동할 수 있다
- [x] ← 키로 이전 문제로 이동할 수 있다 (2번 문제에서)
- [x] 1번 문제에서 ← 키는 무반응이다
- [x] 이전 문제로 돌아가면 정답 숨김 상태로 시작한다

### 게임 진행 - 문제 이동 및 진행률
- [x] 다음 문제로 이동하면 진행률이 증가한다
- [x] 이전 문제로 이동하면 진행률이 감소한다

## 우선순위

- **Critical**: 문제 네비게이션, 정답 확인, 나가기 기능
- **Critical**: 정답 공개/숨김, 문제 네비게이션, 키보드 조작, 나가기 기능
- **High**: 점수 관리, 프로그레스바, 기본 UI 렌더링
- **Medium**: 점수판 펼침/접음, URL 파라미터

## 테스트 데이터 요구사항

- **최소 2개 이상의 문제가 있는 게임**
- **최소 3개 이상의 문제가 있는 게임** (진행률 테스트를 위해)
- **이미지가 있는 문제와 없는 문제 혼재**
- **기본 A팀, B팀 설정**
- **다양한 점수 범위 테스트 (-100 ~ +100)**
Loading
Loading