diff --git a/FE/src/App.tsx b/FE/src/App.tsx index 6acad7b..f5dd228 100644 --- a/FE/src/App.tsx +++ b/FE/src/App.tsx @@ -4,6 +4,8 @@ import { GameSetupPage } from './pages/GameSetupPage'; import { GamePage } from './pages/GamePage'; import { QuizSetupPage } from './pages/QuizSetupPage'; import { GameLobbyPage } from './pages/GameLobbyPage'; +import { LoginPage } from './pages/LoginPage'; +import { MyPage } from './pages/MyPage'; function App() { return ( @@ -14,6 +16,8 @@ function App() { } /> } /> } /> + } /> + } /> not found} /> diff --git a/FE/src/components/Chat.tsx b/FE/src/components/Chat.tsx index 4218622..4863a29 100644 --- a/FE/src/components/Chat.tsx +++ b/FE/src/components/Chat.tsx @@ -18,28 +18,38 @@ const Chat = () => { const [isAtBottom, setIsAtBottom] = useState(true); const [newMessage, setNewMessage] = useState(false); const [prevMessageCount, setPrevMessageCount] = useState(messages.length); - const prevScrollTopRef = useRef(0); const scrollToBottom = () => { if (chatBottomRef.current) { - chatBottomRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); - setNewMessage(false); + setTimeout(() => { + chatBottomRef.current?.scrollIntoView({ + behavior: 'instant', + block: 'end' + }); + setNewMessage(false); + }, 0); } }; const handleScroll = () => { const container = chatContainerRef.current; - if (container) { - // const isBottom = container.scrollHeight - container.scrollTop === container.clientHeight; - const isBottom = prevScrollTopRef.current < container.scrollTop && isAtBottom; - prevScrollTopRef.current = container.scrollTop; - setIsAtBottom(isBottom); // 맨 아래에 있으면 true, 아니면 false - if (isBottom) { - setNewMessage(false); - } + if (!container) return; + + const isBottom = + Math.abs(container.scrollHeight - container.scrollTop - container.clientHeight) < 10; + + if (isBottom) { + setIsAtBottom(true); + } else { + setIsAtBottom(false); } }; + const handleScrollToBottomClick = () => { + scrollToBottom(); + setIsAtBottom(true); + }; + const handleInputChange = (e: React.ChangeEvent) => { setInputValue(e.target.value); }; @@ -78,8 +88,8 @@ const Chat = () => { setPrevMessageCount(messages.length); } - if (isAtBottom && chatBottomRef.current) { - scrollToBottom(); + if (isAtBottom) { + requestAnimationFrame(() => scrollToBottom()); } }, [messages, isAtBottom, prevMessageCount]); @@ -127,7 +137,7 @@ const Chat = () => { +

+ + 비밀번호를 잊으셨나요? + +

+ +); + +const SignUpForm = () => ( +
+

회원가입

+
+ +
+
+ +
+
+ +
+ +
+); diff --git a/FE/src/pages/MainPage.tsx b/FE/src/pages/MainPage.tsx index 970b934..f580f2e 100644 --- a/FE/src/pages/MainPage.tsx +++ b/FE/src/pages/MainPage.tsx @@ -23,7 +23,9 @@ export const MainPage = () => { - + diff --git a/FE/src/pages/MyPage.tsx b/FE/src/pages/MyPage.tsx new file mode 100644 index 0000000..b76b5d8 --- /dev/null +++ b/FE/src/pages/MyPage.tsx @@ -0,0 +1,104 @@ +import { HeaderBar } from '@/components/HeaderBar'; +import { useState } from 'react'; + +type QuizListProps = { + title: string; + quizzes: string[]; + activeTab: string; +}; + +export const MyPage: React.FC = () => { + const [activeTab, setActiveTab] = useState<'myQuizzes' | 'solvedQuizzes'>('myQuizzes'); + + const myQuizzes = ['퀴즈 1', '퀴즈 2', '퀴즈 3', '퀴즈 4']; // 예시 데이터 + const solvedQuizzes = ['퀴즈 A', '퀴즈 B', '퀴즈 C', '퀴즈 D']; // 예시 데이터 + + return ( +
+ + +
+
+ Profile +
+

닉네임

+
+ +
+
+ + +
+ + {/* 리스트 */} +
+ {activeTab === 'myQuizzes' ? ( + + ) : ( + + )} +
+
+
+ ); +}; + +// 퀴즈 리스트 컴포넌트 +const QuizList: React.FC = ({ title, quizzes, activeTab }) => { + const handleEdit = (index: number) => { + console.log(index + '수정 클릭'); + }; + const handleDelete = (index: number) => { + console.log(index + '삭제 클릭'); + }; + return ( +
+

{title}

+
    + {quizzes.map((quiz, index) => ( +
  • + {quiz} +
    + {activeTab === 'myQuizzes' && ( + + )} + +
    +
  • + ))} +
+
+ ); +}; diff --git a/FE/src/pages/QuizSetupPage.tsx b/FE/src/pages/QuizSetupPage.tsx index ee4bdd5..fe608ba 100644 --- a/FE/src/pages/QuizSetupPage.tsx +++ b/FE/src/pages/QuizSetupPage.tsx @@ -8,6 +8,7 @@ import { Typography, SelectChangeEvent } from '@mui/material'; +import { HeaderBar } from '@/components/HeaderBar'; /* { title: string, // 퀴즈셋의 제목 @@ -101,97 +102,100 @@ export const QuizSetupPage: React.FC = () => { }; return ( - - - 퀴즈셋 생성하기 - + <> + + + + 퀴즈셋 생성하기 + - + - + - {quizSet.map((quiz, quizIndex) => ( - - - 퀴즈 {quizIndex + 1} - - handleQuizChange(quizIndex, e.target.value)} - /> - handleLimitTimeChange(quizIndex, e.target.value)} - /> - {quiz.choices.map((choice, choiceIndex) => ( - - - handleChoiceChange(quizIndex, choiceIndex, 'content', e.target.value) - } - /> - - - ))} - - - ))} + {quizSet.map((quiz, quizIndex) => ( + + + 퀴즈 {quizIndex + 1} + + handleQuizChange(quizIndex, e.target.value)} + /> + handleLimitTimeChange(quizIndex, e.target.value)} + /> + {quiz.choices.map((choice, choiceIndex) => ( + + + handleChoiceChange(quizIndex, choiceIndex, 'content', e.target.value) + } + /> + + + ))} + + + ))} - - - + + + + ); };