-
Notifications
You must be signed in to change notification settings - Fork 1
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
Feat: #BBB-124 기술 서적 스터디 과제 투표지 및 투표 모달 구현 #34
Changes from all commits
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 |
---|---|---|
|
@@ -37,36 +37,37 @@ export default function Page() { | |
</div> | ||
<form onSubmit={handleSubmit} className="space-y-4"> | ||
<div className="space-y-2"> | ||
<Label htmlFor="id">Username</Label> | ||
<Label htmlFor="id">아이디</Label> | ||
<Input | ||
id="username" | ||
placeholder="username" | ||
placeholder="아이디" | ||
required | ||
type="id" | ||
value={username} | ||
onChange={(e) => setUsername(e.target.value)} | ||
/> | ||
</div> | ||
<div className="space-y-2"> | ||
<Label htmlFor="password">Password</Label> | ||
<Label htmlFor="password">비밀번호</Label> | ||
<Input | ||
id="password" | ||
required | ||
type="password" | ||
placeholder="비밀번호" | ||
value={password} | ||
onChange={(e) => setPassword(e.target.value)} | ||
/> | ||
</div> | ||
<Button className="w-full" type="submit"> | ||
Sign In | ||
로그인 | ||
</Button> | ||
</form> | ||
<div className="flex items-center justify-between text-sm"> | ||
<Link className="underline underline-offset-2" href="#"> | ||
Forgot password? | ||
비밀번호 찾기 | ||
</Link> | ||
<Link className="underline underline-offset-2" href="/users/signup"> | ||
Create account | ||
회원 가입 | ||
</Link> | ||
</div> | ||
</div> | ||
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. 이 코드 패치에 대한 간단한 코드 리뷰를 제공하겠습니다.
개선을 위해서는 유효한 |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,9 +10,9 @@ export default function Home() { | |
const [myData, setMyData] = useRecoilState(userState); | ||
return ( | ||
<> | ||
{/* <div className="text-center"> | ||
<div className="text-center"> | ||
{myData?.username + '로 로그인된 상태입니다.'} | ||
</div> */} | ||
</div> | ||
<div className="flex items-center justify-center min-h-screen bg-gradient-to-b from-white to-gray-300"> | ||
<div className="space-y-12"> | ||
<div className="ml-12 text-5xl grid grid-rows-3 grid-cols-2 gap-x-12 gap-y-3"> | ||
|
@@ -25,7 +25,10 @@ export default function Home() { | |
</div> | ||
<div className="flex flex-col space-y-2 items-center"> | ||
<Button className="w-1/2 bg-gray-900 text-white py-6 px-6 rounded-lg shadow-md hover:bg-gray-600"> | ||
<div className="text-xl flex items-center justify-center space-x-2"> | ||
<div | ||
onClick={() => (location.href = '/study')} | ||
className="text-xl flex items-center justify-center space-x-2" | ||
> | ||
<StudyIcon className="w-7 h-7"></StudyIcon> | ||
<p>스터디 시작하기</p> | ||
</div> | ||
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. 주요 변경 사항:
개선 제안:
잠재적 버그:
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,14 +5,21 @@ import { useParams } from 'next/navigation'; | |
import { useEffect, useState } from 'react'; | ||
|
||
import StudyDashBoard from '@/components/study/dashboard/dashboard'; | ||
import PostBoard from '@/components/study/post-board'; | ||
import JoinStudyDialog from '@/components/study/study-join-dialog'; | ||
import { BookStudyTaskListModal } from '@/components/study/task/book-study-task-list-modal'; | ||
import { BookStudyTaskVoteModal } from '@/components/study/task/book-study-task-vote-modal'; | ||
import { Button } from '@/components/ui/button/button'; | ||
import Spinner from '@/components/ui/spinner/spinner'; | ||
import { StudyType } from '@/constants/study/study'; | ||
import getStudyDetails from '@/lib/api/study/get-details'; | ||
import startStudy from '@/lib/api/study/start'; | ||
import { userState } from '@/recoil/userAtom'; | ||
import { Round, StudyDetails, StudyStatus } from '@/types/study/study-detail'; | ||
import { | ||
BookStudyDetails, | ||
Round, | ||
StudyDetails, | ||
StudyStatus | ||
} from '@/types/study/study-detail'; | ||
import { toast } from 'react-toastify'; | ||
import { useRecoilState } from 'recoil'; | ||
|
||
|
@@ -28,6 +35,11 @@ export default function StudyPage() { | |
const [myData, setMyData] = useRecoilState(userState); | ||
const [trigger, setTrigger] = useState(Date.now()); | ||
const [showPostBoard, setShowPostBoard] = useState(false); | ||
const [showBookStudyTaskListModal, setShowBookStudyTaskListModal] = | ||
useState(false); | ||
const [showBookStudyTaskVoteModal, setShowBookStudyTaskVoteModal] = | ||
useState(false); | ||
const [nextRoundIdx, setNextRoundIdx] = useState(0); | ||
|
||
const handleStart = async () => { | ||
try { | ||
|
@@ -45,6 +57,11 @@ export default function StudyPage() { | |
const studyDetailsAndRound = await getStudyDetails(studyId); | ||
setDetails(studyDetailsAndRound.details); | ||
setRound(studyDetailsAndRound.round); | ||
if (studyDetailsAndRound.details.state === StudyStatus.READY) { | ||
setNextRoundIdx(0); | ||
} else { | ||
setNextRoundIdx(studyDetailsAndRound.round.idx + 1); | ||
} | ||
for (const [userId, user] of Object.entries( | ||
studyDetailsAndRound.round.users | ||
)) { | ||
|
@@ -53,10 +70,9 @@ export default function StudyPage() { | |
break; | ||
} | ||
} | ||
|
||
if ( | ||
studyDetailsAndRound.details.leaderId === myData?.id && | ||
studyDetailsAndRound.details.status === StudyStatus.READY | ||
studyDetailsAndRound.details.leader.id === myData?.id && | ||
studyDetailsAndRound.details.state === StudyStatus.READY | ||
) { | ||
setCanStart(true); | ||
} else { | ||
|
@@ -77,40 +93,59 @@ export default function StudyPage() { | |
} | ||
|
||
return ( | ||
<div className="flex space-x-4 justify-center"> | ||
{showPostBoard ? ( | ||
<PostBoard></PostBoard> | ||
) : ( | ||
<> | ||
<div className="flex space-x-4 justify-center"> | ||
<StudyDashBoard | ||
details={details} | ||
studyId={studyId} | ||
round={round} | ||
setRound={setRound} | ||
/> | ||
)} | ||
<div className="mt-4"> | ||
{isParticipant ? ( | ||
canStart ? ( | ||
<Button onClick={handleStart} className="bg-cyan-300 w-full"> | ||
시작하기 | ||
</Button> | ||
<div className="mt-4"> | ||
{isParticipant ? ( | ||
canStart ? ( | ||
<Button onClick={handleStart} className="bg-cyan-300 w-full"> | ||
시작하기 | ||
</Button> | ||
) : ( | ||
'' | ||
) | ||
) : ( | ||
'' | ||
) | ||
) : ( | ||
<JoinStudyDialog | ||
<JoinStudyDialog | ||
details={details} | ||
studyId={studyId} | ||
refresh={refresh} | ||
/> | ||
)} | ||
<StudyAbout | ||
details={details} | ||
studyId={studyId} | ||
refresh={refresh} | ||
nextRoundIdx={nextRoundIdx} | ||
users={round.users} | ||
showPostBoard={showPostBoard} | ||
setShowPostBoard={setShowPostBoard} | ||
setShowBookStudyTaskListModal={setShowBookStudyTaskListModal} | ||
setShowBookStudyTaskVoteModal={setShowBookStudyTaskVoteModal} | ||
/> | ||
)} | ||
<StudyAbout | ||
details={details} | ||
users={round.users} | ||
showPostBoard={showPostBoard} | ||
setShowPostBoard={setShowPostBoard} | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
{StudyType[details.studyType as keyof typeof StudyType] === | ||
StudyType.BOOK && ( | ||
<> | ||
<BookStudyTaskListModal | ||
isOpen={showBookStudyTaskListModal} | ||
setOpen={setShowBookStudyTaskListModal} | ||
details={details as BookStudyDetails} | ||
refresh={refresh} | ||
nextRoundIdx={nextRoundIdx} | ||
></BookStudyTaskListModal> | ||
<BookStudyTaskVoteModal | ||
details={details as BookStudyDetails} | ||
nextRoundIdx={nextRoundIdx} | ||
isOpen={showBookStudyTaskVoteModal} | ||
openChange={setShowBookStudyTaskVoteModal} | ||
></BookStudyTaskVoteModal> | ||
</> | ||
)} | ||
</> | ||
); | ||
} | ||
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. 이 코드 패치는 다음과 같은 개선점과 버그 리스크가 있습니다:
위의 내용을 참고하여 코드를 보다 안정적이고 유지 보수가 쉬운 상태로 개선할 수 있습니다. 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. 이 코드 패치의 간략한 코드 리뷰입니다: 버그 리스크:
개선 제안:
이외에도 UI/UX 측면에서 개선 사항이 필요할 수 있습니다. 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. 코드 리뷰:
개선 사항의 적용 여부 및 오류 위험이나 보안 문제는 전체 코드 범위와 애플리케이션 동작 방식을 고려하여 판단할 수 있습니다. 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. 이 코드는 다음과 같은 개선 및 버그 위험 사항이 있습니다:
이러한 점들을 고려하여 코드를 개선하고 디버깅할 수 있도록 구조를 개선하는 것이 좋습니다. 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. 이 코드 리뷰에서 다음과 같은 사항을 고려할 수 있습니다: 버그 위험:
개선 제안:
위의 내용들을 고려하여 코드를 개선하고 수정함으로써 프로그램의 안전성을 높일 수 있습니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,8 @@ import { | |
TableHeader, | ||
TableRow | ||
} from '@/components/ui/table/table'; | ||
import { BookSearchTableProps } from '@/types/book/book-result'; | ||
import { setStudyBook } from '@/lib/api/book/search'; | ||
import { BookSearchTableProps } from '@/types/book/book-result'; | ||
import { toast } from 'react-toastify'; | ||
|
||
export default function BookSearchTable({ | ||
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. 코드 리뷰:
위 수정 사항을 고려하여 코드 품질 및 유지보수성을 향상시킬 수 있습니다. 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. 코드 리뷰:
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,18 +10,29 @@ import { | |
LayoutGridIcon | ||
} from '@/components/ui/icon/icon'; | ||
import { StudyType } from '@/constants/study/study'; | ||
import { StudyDetails, StudyMemberInfo } from '@/types/study/study-detail'; | ||
import { | ||
BookStudyDetails, | ||
StudyDetails, | ||
StudyMemberInfo, | ||
VotingProcess | ||
} from '@/types/study/study-detail'; | ||
|
||
export default function StudyAbout({ | ||
details, | ||
users, | ||
showPostBoard, | ||
setShowPostBoard | ||
nextRoundIdx, | ||
setShowPostBoard, | ||
setShowBookStudyTaskListModal, | ||
setShowBookStudyTaskVoteModal | ||
}: { | ||
details: StudyDetails; | ||
users: { [userId: number]: StudyMemberInfo }; | ||
showPostBoard: boolean; | ||
nextRoundIdx: number; | ||
setShowPostBoard: (arg0: boolean) => void; | ||
setShowBookStudyTaskListModal: (value: boolean) => void; | ||
setShowBookStudyTaskVoteModal: (value: boolean) => void; | ||
}) { | ||
const endDate = new Date(details.startDate); | ||
endDate.setDate(endDate.getDate() + details.weeks * 7); | ||
|
@@ -55,9 +66,9 @@ export default function StudyAbout({ | |
<div className="flex items-center space-x-2"> | ||
<ActivityIcon className="w-5 h-5 text-muted-foreground" /> | ||
<b> | ||
{details.status == 'READY' | ||
{details.state == 'READY' | ||
? '시작 대기' | ||
: details.status == 'RUNNING' | ||
: details.state == 'RUNNING' | ||
? '진행 중' | ||
: '종료'} | ||
</b> | ||
|
@@ -71,7 +82,7 @@ export default function StudyAbout({ | |
<b> | ||
{details.startDate.toString() + | ||
' ~ ' + | ||
endDate.toLocaleDateString()} | ||
endDate.toLocaleDateString('fr-CA')} | ||
</b> | ||
</div> | ||
<div className="flex items-center space-x-2"> | ||
|
@@ -91,25 +102,35 @@ export default function StudyAbout({ | |
<> | ||
<div className="flex items-center space-x-2"> | ||
<BookIcon className="w-5 h-5 text-muted-foreground" /> | ||
{/* TODO details.book.title로 변경 */} | ||
<span>자바의 정석</span> | ||
</div> | ||
|
||
<div | ||
onClick={() => {}} | ||
className="group w-fit hover:text-gray-900 text-blue-600 flex items-center space-x-2" | ||
> | ||
<FilePenIcon className="group-hover:stroke-black stroke-blue w-5 h-5 text-muted-foreground"></FilePenIcon> | ||
<b>과제 선택지 수정 </b> | ||
<span>{(details as BookStudyDetails).bookInfo.title}</span> | ||
</div> | ||
|
||
<div | ||
onClick={() => {}} | ||
className="group w-fit hover:text-gray-900 text-blue-600 flex items-center space-x-2" | ||
> | ||
<BoxIcon className="group-hover:stroke-black stroke-blue w-5 h-5 text-muted-foreground"></BoxIcon> | ||
<b>과제 투표 </b> | ||
</div> | ||
{(details as BookStudyDetails).votingProcess === | ||
VotingProcess.READY && | ||
details.weeks !== nextRoundIdx && ( | ||
<div | ||
onClick={() => {}} | ||
className="group w-fit hover:text-gray-900 text-blue-600 flex items-center space-x-2" | ||
> | ||
<FilePenIcon className="group-hover:stroke-black stroke-blue w-5 h-5 text-muted-foreground"></FilePenIcon> | ||
<b onClick={() => setShowBookStudyTaskListModal(true)}> | ||
과제 선택지 수정{' '} | ||
</b> | ||
</div> | ||
)} | ||
{(details as BookStudyDetails).votingProcess === | ||
VotingProcess.ONGOING && | ||
details.weeks !== nextRoundIdx && ( | ||
<div | ||
onClick={() => {}} | ||
className="group w-fit hover:text-gray-900 text-blue-600 flex items-center space-x-2" | ||
> | ||
<BoxIcon className="group-hover:stroke-black stroke-blue w-5 h-5 text-muted-foreground"></BoxIcon> | ||
<b onClick={() => setShowBookStudyTaskVoteModal(true)}> | ||
과제 투표{' '} | ||
</b> | ||
</div> | ||
)} | ||
</> | ||
)} | ||
</div> | ||
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. 이 코드 리뷰에서는 몇 가지 개선 사항과 버그 리스크가 있습니다:
이외에도 코드 반복을 최소화하고 확장성과 가독성을 향상시킬 수 있는 방법을 탐색해보시는 것이 좋겠습니다. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,12 @@ import { PlayIcon, PuzzleIcon, XIcon } from '@/components/ui/icon/icon'; | |
import { TableCell, TableRow } from '@/components/ui/table/table'; | ||
import { | ||
AlgorithmProblemInfo, | ||
BookMemberInfo, | ||
StudyAssignmentInfo | ||
BookMemberInfo | ||
} from '@/types/study/study-detail'; | ||
|
||
import { Button } from '@/components/ui/button/button'; | ||
import { userState } from '@/recoil/userAtom'; | ||
import { BookTaskAssignment } from '@/types/study/book-task-form'; | ||
import { useState } from 'react'; | ||
import { useRecoilState } from 'recoil'; | ||
|
||
|
@@ -21,7 +21,7 @@ export function BookRow({ | |
studyId: number; | ||
roundIdx: number; | ||
userId: number; | ||
assignment: StudyAssignmentInfo; | ||
assignment: BookTaskAssignment; | ||
user: BookMemberInfo; | ||
}) { | ||
const [isLoading, setIsLoading] = useState(false); | ||
|
@@ -32,14 +32,14 @@ export function BookRow({ | |
<p className="text-center">{user.username}</p> | ||
</TableCell> | ||
<TableCell className="text-center"> | ||
<p className="text-center">{assignment.title}</p> | ||
<p className="text-center">{assignment?.title}</p> | ||
</TableCell> | ||
<TableCell className="text-center"> | ||
<p className="text-center">{assignment.content}</p> | ||
<p className="text-center">{assignment?.description}</p> | ||
</TableCell> | ||
<TableCell className="text-center"> | ||
<p className="text-center"> | ||
{assignment.page.left} - {assignment.page.right} | ||
{assignment?.pageStart} - {assignment?.pageEnd} | ||
</p> | ||
</TableCell> | ||
<TableCell className="text-center"> | ||
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.
이 코드 리뷰 참고 사항은 코드 안정성 및 유지보수에 도움이 될 수 있습니다. |
||
|
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.
코드 리뷰:
오타 수정:
type="id"
가 아닌type="text"
가 되어야 함id="username"
는id="아이디"
로,placeholder="아이디"
는placeholder="아이디를 입력하세요"
와 같이 더 구체적인 내용이 좋을 수 있음보안 상 고려:
UX 향상을 위한 제안:
문구 변경:
UI/UX 디자인 개선:
i18n(Internationalization)과 l10n(Localization):
코드 리뷰가 끝나셨습니다. 위의 제안 사항 중 필요한 것을 선택하여 코드를 개선해 보십시오.