-
Notifications
You must be signed in to change notification settings - Fork 2
[FIX] 타이머 화면의 음소거 아이콘 미반영 버그 및 NormalTimer 레이아웃 문제를 수정 #442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
010b836
e61046e
fa32442
2acd567
650f3a3
65b2beb
677f8df
8aa7fed
2dcb5d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,24 +28,29 @@ get_current_branch() { | |
|
|
||
| # For non-git repos, try to find the latest feature directory | ||
| local repo_root=$(get_repo_root) | ||
| local specs_dir="$repo_root/specs/feat" | ||
| local specs_base="$repo_root/specs" | ||
|
|
||
| if [[ -d "$specs_dir" ]]; then | ||
| if [[ -d "$specs_base" ]]; then | ||
| local latest_feature="" | ||
| local highest=0 | ||
|
|
||
| for dir in "$specs_dir"/*; do | ||
| if [[ -d "$dir" ]]; then | ||
| local dirname=$(basename "$dir") | ||
| if [[ "$dirname" =~ ^([0-9]+)- ]]; then | ||
| local number=${BASH_REMATCH[1]} | ||
| number=$((10#$number)) | ||
| if [[ "$number" -gt "$highest" ]]; then | ||
| highest=$number | ||
| latest_feature=$dirname | ||
| for type_dir in "$specs_base"/*/; do | ||
| [[ -d "$type_dir" ]] || continue | ||
| local type_name | ||
| type_name="$(basename "$type_dir")" | ||
| for dir in "$type_dir"*/; do | ||
| if [[ -d "$dir" ]]; then | ||
| local dirname=$(basename "$dir") | ||
| if [[ "$dirname" =~ ^([0-9]+)- ]]; then | ||
| local number=${BASH_REMATCH[1]} | ||
| number=$((10#$number)) | ||
| if [[ "$number" -gt "$highest" ]]; then | ||
| highest=$number | ||
| latest_feature="${type_name}/#${dirname}" | ||
| fi | ||
| fi | ||
| fi | ||
| fi | ||
| done | ||
| done | ||
|
|
||
| if [[ -n "$latest_feature" ]]; then | ||
|
|
@@ -107,29 +112,41 @@ check_feature_branch() { | |
| return 1 | ||
| } | ||
|
|
||
| get_feature_dir() { echo "$1/specs/feat/$2"; } | ||
| get_feature_dir() { | ||
| local repo_root="$1" | ||
| local branch_name="$2" | ||
| find_feature_dir_by_prefix "$repo_root" "$branch_name" | ||
| } | ||
|
|
||
| # Find feature directory by issue number or numeric prefix | ||
| # Supports: feat/#96-social-login → specs/feat/096-* | ||
| # 096-social-login → specs/feat/096-* | ||
| # Supports: fix/#441-slug → specs/fix/441-* | ||
| # feat/#96-social-login → specs/feat/096-* | ||
| # 096-social-login → specs/feat/096-* (legacy) | ||
| find_feature_dir_by_prefix() { | ||
| local repo_root="$1" | ||
| local branch_name="$2" | ||
| local specs_dir="$repo_root/specs/feat" | ||
|
|
||
| # Extract type prefix from branch name (e.g., fix/#441-slug → fix, feat/#96-slug → feat) | ||
| local type_prefix="feat" # default for legacy branches | ||
| if [[ "$branch_name" =~ ^([a-z]+)/#[0-9]+ ]]; then | ||
| type_prefix="${BASH_REMATCH[1]}" | ||
| fi | ||
|
Comment on lines
+130
to
+133
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
|
||
| local specs_dir="$repo_root/specs/$type_prefix" | ||
|
|
||
| # Extract issue number from branch name | ||
| local issue_num=$(extract_issue_number "$branch_name") | ||
|
|
||
| if [[ -z "$issue_num" ]]; then | ||
| # If no issue number found, fall back to exact match under specs/feat/ | ||
| # If no issue number found, fall back to exact match under specs/{type}/ | ||
| echo "$specs_dir/$branch_name" | ||
| return | ||
| fi | ||
|
|
||
| # Zero-pad to 3 digits for matching | ||
| local padded=$(printf "%03d" "$((10#$issue_num))") | ||
|
|
||
| # Search for directories in specs/feat/ that start with this prefix | ||
| # Search for directories in specs/{type}/ that start with this prefix | ||
| local matches=() | ||
| if [[ -d "$specs_dir" ]]; then | ||
| for dir in "$specs_dir"/"$padded"-*; do | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| import { describe, it, expect, beforeEach } from 'vitest'; | ||
| import { fireEvent, render, screen, waitFor } from '@testing-library/react'; | ||
| import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; | ||
| import { MemoryRouter, Route, Routes } from 'react-router-dom'; | ||
| import userEvent from '@testing-library/user-event'; | ||
| import TimerPage from './TimerPage'; | ||
| import { GlobalPortal } from '../../util/GlobalPortal'; | ||
|
|
||
| function renderTimerPage() { | ||
| const queryClient = new QueryClient({ | ||
| defaultOptions: { queries: { retry: false } }, | ||
| }); | ||
| return render( | ||
| <QueryClientProvider client={queryClient}> | ||
| <GlobalPortal.Provider> | ||
| <MemoryRouter initialEntries={['/timer/5']}> | ||
| <Routes> | ||
| <Route path="/timer/:id" element={<TimerPage />} /> | ||
| </Routes> | ||
| </MemoryRouter> | ||
| </GlobalPortal.Provider> | ||
| </QueryClientProvider>, | ||
| ); | ||
| } | ||
|
|
||
| describe('TimerPage - 헤더 음소거 아이콘', () => { | ||
| beforeEach(() => { | ||
| localStorage.clear(); | ||
| // 첫 방문 모달이 테스트를 방해하지 않도록 방문 기록 설정 | ||
| localStorage.setItem('isVisited', 'true'); | ||
| }); | ||
|
|
||
| it('볼륨이 0보다 클 때 일반 볼륨 아이콘이 표시된다', () => { | ||
| localStorage.setItem('timer-volume', '0.5'); | ||
| renderTimerPage(); | ||
|
|
||
| expect(screen.queryByTestId('volume-icon-muted')).not.toBeInTheDocument(); | ||
| expect(screen.getByTestId('volume-icon-normal')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('볼륨이 0일 때 음소거 아이콘이 표시된다', () => { | ||
| localStorage.setItem('timer-volume', '0'); | ||
| renderTimerPage(); | ||
|
|
||
| expect(screen.getByTestId('volume-icon-muted')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('VolumeBar 음소거 버튼 클릭 시 헤더 아이콘이 즉시 음소거로 변경된다', async () => { | ||
| localStorage.setItem('timer-volume', '0.5'); | ||
| renderTimerPage(); | ||
|
|
||
| // VolumeBar 열기 | ||
| const volumeButton = screen.getByRole('button', { name: '볼륨 조절' }); | ||
| await userEvent.click(volumeButton); | ||
|
|
||
| // VolumeBar 음소거 버튼 클릭 (볼륨 > 0이면 title='음소거') | ||
| const muteButton = await screen.findByTitle('음소거'); | ||
| await userEvent.click(muteButton); | ||
|
|
||
| await waitFor(() => { | ||
| expect(screen.getByTestId('volume-icon-muted')).toBeInTheDocument(); | ||
| }); | ||
| }); | ||
|
|
||
| it('VolumeBar 슬라이더를 0으로 내리면 헤더 아이콘이 즉시 음소거로 변경된다', async () => { | ||
| localStorage.setItem('timer-volume', '0.5'); | ||
| renderTimerPage(); | ||
|
|
||
| const volumeButton = screen.getByRole('button', { name: '볼륨 조절' }); | ||
| await userEvent.click(volumeButton); | ||
|
|
||
| const slider = await screen.findByRole('slider'); | ||
| fireEvent.change(slider, { target: { value: '0' } }); | ||
|
|
||
| await waitFor(() => { | ||
| expect(screen.getByTestId('volume-icon-muted')).toBeInTheDocument(); | ||
| }); | ||
| }); | ||
|
|
||
| it('음소거 상태에서 음소거 해제 시 헤더 아이콘이 일반 볼륨으로 복원된다', async () => { | ||
| localStorage.setItem('timer-volume', '0'); | ||
| renderTimerPage(); | ||
|
|
||
| // VolumeBar 열기 | ||
| const volumeButton = screen.getByRole('button', { name: '볼륨 조절' }); | ||
| await userEvent.click(volumeButton); | ||
|
|
||
| // 음소거 해제 버튼 클릭 (볼륨 = 0이면 title='음소거 해제') | ||
| const unmuteButton = await screen.findByTitle('음소거 해제'); | ||
| await userEvent.click(unmuteButton); | ||
|
|
||
| await waitFor(() => { | ||
| expect(screen.queryByTestId('volume-icon-muted')).not.toBeInTheDocument(); | ||
| expect(screen.getByTestId('volume-icon-normal')).toBeInTheDocument(); | ||
| }); | ||
| }); | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| }); | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,103 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { describe, it, expect, vi } from 'vitest'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { render, screen } from '@testing-library/react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import NormalTimer from './NormalTimer'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { TimeBoxInfo } from '../../../type/type'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| const mockNormalTimerInstance = { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| timer: 120, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| isAdditionalTimerOn: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| isRunning: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| handleChangeAdditionalTimer: vi.fn(), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| handleCloseAdditionalTimer: vi.fn(), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| startTimer: vi.fn(), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| pauseTimer: vi.fn(), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| resetTimer: vi.fn(), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| setTimer: vi.fn(), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| const baseItem: TimeBoxInfo = { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| stance: 'PROS', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| speechType: '입론', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| bell: null, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| boxType: 'NORMAL', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| time: 120, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| timePerTeam: null, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| timePerSpeaking: null, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| speaker: null, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| function renderNormalTimer( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| teamName: string | null, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| speaker: string | null, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| speechType = '입론', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const item: TimeBoxInfo = { ...baseItem, speaker, speechType }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return render( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <NormalTimer | ||||||||||||||||||||||||||||||||||||||||||||||||||
| normalTimerInstance={mockNormalTimerInstance} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| isAdditionalTimerAvailable={false} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| item={item} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| teamName={teamName} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| />, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| describe('NormalTimer - 두 줄 레이아웃 (US2)', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| it('팀명만 있을 때 팀명이 표시되고 토론자 줄은 렌더링되지 않는다', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderNormalTimer('찬성', null); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(screen.getByText('찬성 팀')).toBeInTheDocument(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(screen.queryByText(/토론자/)).not.toBeInTheDocument(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| it('토론자만 있을 때 토론자 정보가 표시되고 팀명 줄은 렌더링되지 않는다', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderNormalTimer(null, '발언자 1'); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(screen.getByText('발언자 1 토론자')).toBeInTheDocument(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(screen.queryByText(/찬성/)).not.toBeInTheDocument(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| it('팀명과 토론자 모두 있을 때 각각 독립된 DOM 요소로 렌더링된다', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderNormalTimer('찬성', '발언자 1'); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| const teamEl = screen.getByText('찬성 팀'); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const speakerEl = screen.getByText('발언자 1 토론자'); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(teamEl).toBeInTheDocument(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(speakerEl).toBeInTheDocument(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(teamEl).not.toBe(speakerEl); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| it('팀명과 토론자 모두 없으면 팀 정보 영역이 렌더링되지 않는다', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderNormalTimer(null, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(screen.queryByText(/팀$/)).not.toBeInTheDocument(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(screen.queryByText(/토론자/)).not.toBeInTheDocument(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| it('긴 팀명을 가진 팀의 발언 순서일 때 팀명이 화면에 표시된다', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderNormalTimer('A very long team name', null); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(screen.getByText('A very long team name 팀')).toBeInTheDocument(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| it('토론자 이름이 긴 경우에도 전체 이름이 화면에 표시된다', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderNormalTimer(null, '발언자 1'); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(screen.getByText('발언자 1 토론자')).toBeInTheDocument(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+84
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 긴 토론자 이름 케이스가 실제로는 검증되지 않습니다. 테스트명은 긴 이름을 검증한다고 되어 있지만 입력값이 🧪 제안 수정 it('토론자 이름이 긴 경우에도 전체 이름이 화면에 표시된다', () => {
- renderNormalTimer(null, '발언자 1');
+ const longSpeakerName = '아주 긴 이름의 토론자 1';
- expect(screen.getByText('발언자 1 토론자')).toBeInTheDocument();
+ renderNormalTimer(null, longSpeakerName);
+
+ expect(screen.getByText(`${longSpeakerName} 토론자`)).toBeInTheDocument();
});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| describe('NormalTimer - 순서명 정렬 (US3)', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| it('한글 순서명이 타이머 화면에 표시된다', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderNormalTimer(null, null, '입론'); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent('입론'); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| it('영어 순서명이 타이머 화면에 표시된다', () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| renderNormalTimer(null, null, 'Opening Statement'); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent('Opening Statement'); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+91
to
+101
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 포맷팅 경고를 반영해주세요. 정적 분석 경고대로 긴 matcher 호출을 여러 줄로 나누면 현재 포맷 규칙과 맞습니다. 🧹 제안 수정- expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent('Opening Statement');
+ expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent(
+ 'Opening Statement',
+ );📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Check: test[warning] 101-101: 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,6 @@ import TimerController from './TimerController'; | |
| import { Formatting } from '../../../util/formatting'; | ||
| import CircularTimer from './CircularTimer'; | ||
| import clsx from 'clsx'; | ||
| import DTDebate from '../../../components/icons/Debate'; | ||
| import CompactTimeoutTimer from './CompactTimeoutTimer'; | ||
| import useCircularTimerAnimation from '../hooks/useCircularTimerAnimation'; | ||
| import useBreakpoint from '../../../hooks/useBreakpoint'; | ||
|
|
@@ -76,17 +75,26 @@ export default function NormalTimer({ | |
| <span className="flex w-[360px] flex-shrink-0 flex-col items-center justify-center xl:w-[450px]"> | ||
| <span className="flex w-full flex-col items-center justify-center space-y-[20px] px-[45px] xl:space-y-[36px]"> | ||
| {/* 제목 */} | ||
| <h1 className="text-[52px] font-bold xl:text-[68px]">{titleText}</h1> | ||
| <h1 className="text-center text-[52px] font-bold xl:text-[68px]"> | ||
| {titleText} | ||
| </h1> | ||
|
|
||
| {/* 발언자 및 팀 정보 */} | ||
| {(teamName || item.speaker) && ( | ||
| <span className="flex w-full max-w-[600px] flex-row items-center justify-center space-x-[16px]"> | ||
| <DTDebate className="w-[20px] flex-shrink-0 xl:w-[28px]" /> | ||
| <p className="min-w-0 flex-1 truncate text-[20px] xl:text-[28px]"> | ||
| {teamName && t('{{team}} 팀', { team: t(teamName) })} | ||
| {item.speaker && | ||
| t(' | {{speaker}} 토론자', { speaker: t(item.speaker) })} | ||
| </p> | ||
| <span className="flex w-full max-w-[600px] flex-col items-center justify-center gap-y-[8px] xl:gap-y-[12px]"> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
| {teamName && ( | ||
| <p className="w-full min-w-0 truncate text-center text-[20px] xl:text-[28px]"> | ||
| {t('{{team}} 팀', { team: t(teamName) })} | ||
| </p> | ||
| )} | ||
| {teamName && item.speaker && ( | ||
| <hr className="w-1/3 border-[1.2px] border-current opacity-30" /> | ||
| )} | ||
| {item.speaker && ( | ||
| <p className="w-full min-w-0 text-center text-[20px] xl:text-[28px]"> | ||
| {t('{{speaker}} 토론자', { speaker: t(item.speaker) })} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| </p> | ||
| )} | ||
| </span> | ||
| )} | ||
|
|
||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.