-
Notifications
You must be signed in to change notification settings - Fork 4
[Feat] 스터디 기능 구현 | 스터디 시작 및 중지, 질문 넘기기, 사이드바 접기 구현, 진행 중인 세션에 대한 처리 #281
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
Merged
ShipFriend0516
merged 21 commits into
boostcampwm-2024:dev
from
ShipFriend0516:feature/study-in-session
Nov 28, 2024
+606
−175
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
2f2fc18
feat: 질문지 정보에 대한 타입 구현
ShipFriend0516 48814da
chore: pnpm-lock
ShipFriend0516 eb9f7c4
feat: 스터디 웹소켓 API 이벤트명 분리
ShipFriend0516 687c092
feat: 스터디가 진행 중인지 아닌지를 직관적으로 확인할 수 있게 구현
ShipFriend0516 e7f4f52
feat: 질문 넘기기 API 연동 및 스터디 시작 API 연동
ShipFriend0516 619af1d
feat: 현재 질문을 표시하고 이전 질문들의 기록을 사이드바에 남기도록 구현
ShipFriend0516 2ebed38
feat: 스터디 기능 API 핸들러 추가
ShipFriend0516 64ebd53
feat: 스터디 시작버튼과 중지버튼을 누르면 스터디 시작 및 정지 구현
ShipFriend0516 1bfb78b
feat: 사이드바 접기 버튼 추가
ShipFriend0516 b1af3f1
feat: 사이드바를 접을 수 있도록 사이드바를 감싸는 Container 구현
ShipFriend0516 37f234c
chore: 컴포넌트 큰 단위로 폴더로 구분
ShipFriend0516 4834f78
refactor: 호스트만 사용할 수 있는 도구와 일반 유저들도 사용할 수 있는 도구 컴포넌트를 분리
ShipFriend0516 e1c3588
feat: 스터디 시작하면 시작 인디케이터를 띄우기
ShipFriend0516 dde42e0
feat: 다음 질문, 이전 질문 누르고 2초 후에 활성화 되도록 구현
ShipFriend0516 6e96862
fix: 질문 번호가 잘못되어있던 오류 수정
ShipFriend0516 431d9bc
fix: 버튼 프로그레스바가 오버플로우 되던 현상 수정
ShipFriend0516 3902442
Merge branch 'dev' into feature/study-in-session
ShipFriend0516 582171d
refactor: study 관련 함수 useStudy 훅으로 분리
ShipFriend0516 966d140
refactor: uptime 분/초로 표현
ShipFriend0516 cac93ce
refactor: useStudy -> useSession으로 받아온 함수 사용하도록 수정
ShipFriend0516 d950de1
refactor: 이전 질문 버튼과 다음 질문 버튼이 질문지의 양 끝단에서 비활성화되도록 구현
ShipFriend0516 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
177 changes: 177 additions & 0 deletions
177
frontend/src/components/session/Sidebar/SessionSidebar.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| import { FaClipboardList, FaFolder } from "react-icons/fa"; | ||
| import { FaUserGroup } from "react-icons/fa6"; | ||
| import useModalStore from "@stores/useModalStore.ts"; | ||
| import Modal from "../../common/Modal"; | ||
| import { useNavigate } from "react-router-dom"; | ||
| import { Socket } from "socket.io-client"; | ||
| import useToast from "@hooks/useToast.ts"; | ||
| import { TbCrown } from "react-icons/tb"; | ||
| import { SESSION_EMIT_EVENT } from "@/constants/WebSocket/SessionEvent.ts"; | ||
| import { Question } from "@hooks/type/session"; | ||
|
|
||
| interface ParticipantsData { | ||
| nickname: string; | ||
| isHost: boolean; | ||
| } | ||
|
|
||
| interface Props { | ||
| socket: Socket | null; | ||
| questionList: Question[]; | ||
| currentIndex: number; | ||
| participants: ParticipantsData[]; | ||
| roomId: string | undefined; // TODO: sessionId가 입력되지 않았을 때(undefined) 처리 필요 | ||
| isHost: boolean; | ||
| } | ||
|
|
||
| const SessionSidebar = ({ | ||
| socket, | ||
| questionList, | ||
| currentIndex, | ||
| participants, | ||
| roomId, | ||
| isHost, | ||
| }: Props) => { | ||
| const { openModal } = useModalStore(); | ||
| const navigate = useNavigate(); | ||
| const toast = useToast(); | ||
|
|
||
| const existHandler = () => { | ||
| socket?.emit(SESSION_EMIT_EVENT.LEAVE, { roomId }); | ||
| toast.success("메인 화면으로 이동합니다."); | ||
| navigate("/sessions"); | ||
| }; | ||
|
|
||
| const destroyAndExitHandler = () => { | ||
| socket?.off(SESSION_EMIT_EVENT.FINISH); | ||
| socket?.emit(SESSION_EMIT_EVENT.FINISH, { roomId }); | ||
| toast.success("메인 화면으로 이동합니다."); | ||
| navigate("/sessions"); | ||
| }; | ||
|
|
||
| const HostModalData = { | ||
| title: "세션을 종료할까요?", | ||
| subtitle: "세션을 종료하면 참가자들이 모두 나가게 됩니다.", | ||
| leftButton: "방장 양도 후 종료", | ||
| rightButton: "세션 종료", | ||
| type: "red", | ||
| onLeftClick: existHandler, | ||
| onRightClick: destroyAndExitHandler, | ||
| }; | ||
|
|
||
| const ParticipantModalData = { | ||
| title: "지금 나가면 다시 들어올 수 없어요!", | ||
| subtitle: "정말 종료하시겠어요?", | ||
| leftButton: "취소하기", | ||
| rightButton: "종료하기", | ||
| type: "red", | ||
| onLeftClick: () => {}, | ||
| onRightClick: existHandler, | ||
| }; | ||
|
|
||
| return ( | ||
| <div | ||
| className={ | ||
| "flex flex-grow px-4 gap-2 items-stretch w-[440px] bg-white shrink-0" | ||
| } | ||
| > | ||
| <div className={"flex flex-col gap-4 flex-grow justify-between "}> | ||
| <div className={"flex flex-col gap-4 "}> | ||
| <div className={"flex flex-col gap-2 pt-6"}> | ||
| <h2 className={"inline-flex gap-1 items-center text-semibold-m"}> | ||
| <FaClipboardList /> | ||
| 현재 질문 | ||
| </h2> | ||
| <div | ||
| className={ | ||
| "border border-accent-gray p-2 bg-transparent rounded-xl " | ||
| } | ||
| > | ||
| {currentIndex >= 0 ? ( | ||
| <p> | ||
| <span className={"text-bold-s"}> | ||
| Q{questionList[currentIndex].index + 1}.{" "} | ||
| </span> | ||
| {questionList[currentIndex].content} | ||
| </p> | ||
| ) : ( | ||
| <p>질문 로딩 중...</p> | ||
| )} | ||
| </div> | ||
| </div> | ||
| <div className={"flex flex-col gap-2 mt-4"}> | ||
| <h2 className={"inline-flex gap-1 items-center text-semibold-m"}> | ||
| <FaUserGroup /> | ||
| 참가자 | ||
| </h2> | ||
| <ul> | ||
| {participants.map((participant, index) => ( | ||
| <li key={index} className={"flex items-center gap-2"}> | ||
| <span className={"w-4 h-4 bg-point-2 rounded-full"} /> | ||
| <span>{participant.nickname}</span> | ||
| <span className={"text-yellow-400"}> | ||
| {participant.isHost && <TbCrown />} | ||
| </span> | ||
| </li> | ||
| ))} | ||
| </ul> | ||
| </div> | ||
| <div className={"flex flex-col gap-2 mt-4"}> | ||
| <h2 className={"inline-flex gap-1 items-center text-semibold-m"}> | ||
| <FaFolder /> | ||
| 이전 질문 | ||
| </h2> | ||
| <ul> | ||
| {currentIndex <= 0 && ( | ||
| <li className={"text-medium-s"}> | ||
| 여기에 이전 질문이 기록됩니다. | ||
| </li> | ||
| )} | ||
| {questionList.map((question, index) => { | ||
| if (index < currentIndex) | ||
| return ( | ||
| <li key={question.id}> | ||
| Q{index + 1}. {question.content} | ||
| </li> | ||
| ); | ||
| })} | ||
| </ul> | ||
| </div> | ||
| </div> | ||
| <div className={"h-16 items-center flex w-full"}> | ||
| <button | ||
| className={"w-full bg-red-500 text-white rounded-md py-2"} | ||
| onClick={() => { | ||
| openModal(); | ||
| }} | ||
| > | ||
| 종료하기 | ||
| </button> | ||
| </div> | ||
| </div> | ||
|
|
||
| <Modal | ||
| title={isHost ? HostModalData.title : ParticipantModalData.title} | ||
| subtitle={ | ||
| isHost ? HostModalData.subtitle : ParticipantModalData.subtitle | ||
| } | ||
| leftButton={ | ||
| isHost ? HostModalData.leftButton : ParticipantModalData.leftButton | ||
| } | ||
| rightButton={ | ||
| isHost ? HostModalData.rightButton : ParticipantModalData.rightButton | ||
| } | ||
| type={"red"} | ||
| onLeftClick={ | ||
| isHost ? HostModalData.onLeftClick : ParticipantModalData.onLeftClick | ||
| } | ||
| onRightClick={ | ||
| isHost | ||
| ? HostModalData.onRightClick | ||
| : ParticipantModalData.onRightClick | ||
| } | ||
| /> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default SessionSidebar; | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
모달은 modalStore가 아닌 useModal로 modal 인스턴스를 가져와서 사용하면 될거 같습니다. 이전 PR에 사용법을 적어두었습니다. #258
이 PR 참고하시면 좋을거 같아요!