Skip to content
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

[Fix] 나의 과제 페이지, 수강 신청 페이지 QA 반영 #133

Merged
merged 50 commits into from
Sep 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
473c397
feat: 큐에이 반영
SeieunYoo Sep 1, 2024
4d96c98
fix: 소문자로 변경
SeieunYoo Sep 2, 2024
0a470e4
refactor: api dto 반영, 이번 주 과제 조회 api 연결
SeieunYoo Sep 2, 2024
15efae9
feat: 히스토리 api 수정된 dto 반영
SeieunYoo Sep 2, 2024
98ca46f
feat: 히스토리 api 수정된 거 반영, 레포지토리 입력 api 반영
SeieunYoo Sep 2, 2024
14e3318
refactor: 레포 모달 창 상태 관리 컴포넌트로 벼녕
SeieunYoo Sep 2, 2024
4a2bdaa
feat: 필요없는 로직 삭제
SeieunYoo Sep 2, 2024
e4e81a7
feat: 이번 주 과제 조회 스터디 추가
SeieunYoo Sep 2, 2024
02ccc06
feat: merge dev
SeieunYoo Sep 2, 2024
c40f35d
feat: 모달 라우팅 삭제
SeieunYoo Sep 2, 2024
3f55541
feat: submissionLink 에서 폴더
SeieunYoo Sep 2, 2024
c535042
chore: 안쓰는 상수 삭제
SeieunYoo Sep 2, 2024
3ba2820
chore: 말줄임 처리, github url 인지 체크
SeieunYoo Sep 3, 2024
30b1482
feat: 스터디 시작 날짜가 현재 날짜인지 확인하고 disabled 처리
SeieunYoo Sep 3, 2024
5300dab
feat: 공통 타입은 common 으로 옮기기, 리뷰 반영
SeieunYoo Sep 3, 2024
2353d51
fix: 빠진 네이밍 수정 반영
SeieunYoo Sep 3, 2024
44b6eae
feat: Button asProp 으로 Link 전달, css 수정
SeieunYoo Sep 4, 2024
87913e4
refactor: NonNullable 처리, Initial 로 관리
SeieunYoo Sep 4, 2024
9e1ec27
feat: github 관련 유틸 분리,css 수정
SeieunYoo Sep 4, 2024
083fd28
chore: 필요없는 프래그먼트 삭제
SeieunYoo Sep 4, 2024
9193df3
chore: cache 속서 추가
SeieunYoo Sep 4, 2024
9807666
feat: currentPath href 매치될 때만 active 되게 navItem 수정
SeieunYoo Sep 4, 2024
70a1a10
chore: myStudy 용 타입 추가
SeieunYoo Sep 4, 2024
2f2237c
chore: EDITING_WITH_WARNING 타입 삭제, 상태 네이밍 변경
SeieunYoo Sep 4, 2024
172f10c
chore: 조건식 간소화
SeieunYoo Sep 4, 2024
329f205
chore: submissionLink null 로 내려오는 부분 우선 삭제
SeieunYoo Sep 4, 2024
2d7b185
feat: 리뷰 반영
SeieunYoo Sep 4, 2024
690e48d
feat: 수강 신청 아이템 width 고정
SeieunYoo Sep 4, 2024
1bacf2d
fix: dev 환경일 때는 dev-onboarding 으로 연결
SeieunYoo Sep 4, 2024
904a648
feat: 부모컴포넌트에서 호출하도록 수정
SeieunYoo Sep 4, 2024
d84dbda
feat: 히스토리 아이템 반응형 처리
SeieunYoo Sep 4, 2024
56225fb
feat: upcoming api 로직 삭제
SeieunYoo Sep 4, 2024
b497266
feat: 부모컴포넌트에서 api 불러오기
SeieunYoo Sep 4, 2024
48c5c45
feat: merge dev
SeieunYoo Sep 5, 2024
e6e19d7
fix: 컴포넌트 호출 위치 수정
SeieunYoo Sep 5, 2024
a1465de
chore: 문구 수정 반영
SeieunYoo Sep 5, 2024
7ec7df3
chore: 헤더 삭제
SeieunYoo Sep 5, 2024
005b1e1
chore: 수강신청 아이템 정렬 수정
SeieunYoo Sep 7, 2024
1cd5a71
chore: repo link 가 있는 지 확인하는 로직 추가
SeieunYoo Sep 7, 2024
3bf13d9
chore: 레포지토리로 네이밍 변경
SeieunYoo Sep 7, 2024
40479c2
chore: 인자명 repositoryLink 로 변경
SeieunYoo Sep 7, 2024
76da218
chore: length 0일때만 확인
SeieunYoo Sep 7, 2024
11de24d
fix: cache no-store 로 설정
SeieunYoo Sep 7, 2024
ac4fcf5
chore: api 호출하지 않고 props 로 전달하는 걸로 수정
SeieunYoo Sep 7, 2024
07d4ca7
chore: 목데이터 삭제
SeieunYoo Sep 7, 2024
863b435
chore: 에러 메시지 문구 해요체로 변경
SeieunYoo Sep 7, 2024
963e8ff
chore: 컬러 변경, 함수 네이밍 변경
SeieunYoo Sep 7, 2024
017758a
feat: unknown 인 케이스 우선 임의로 반영
SeieunYoo Sep 7, 2024
2f614a6
chore: 실패 팝오버 문구 수정
SeieunYoo Sep 7, 2024
b4d1a12
chore: popoverRef 위치 상단으로 변경
SeieunYoo Sep 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 2 additions & 16 deletions apps/client/apis/studyDetailApi.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
import { fetcher } from "@wow-class/utils";
import { apiPath } from "constants/apiPath";
import { tags } from "constants/tags";
import type {
StudyDetailDashboardDto,
UpcomingStudyDto,
} from "types/dtos/studyDetail";
import type { StudyDetailDashboardDto } from "types/dtos/studyDetail";

export const studyDetailApi = {
getStudyDetailDashboard: async (studyId: number) => {
const response = await fetcher.get<StudyDetailDashboardDto>(
`${apiPath.studyDetail}/dashboard?studyId=${studyId}`,
{
next: { tags: [tags.studyDetailDashboard] },
cache: "force-cache",
}
);

return response.data;
},
getUpcomingStudy: async (studyId: number) => {
const response = await fetcher.get<UpcomingStudyDto>(
`${apiPath.studyDetail}/upcoming?studyId=${studyId}`,
{
next: { tags: [tags.upcomingStudy] },
cache: "force-cache",
cache: "no-store",
}
);

Expand Down
2 changes: 1 addition & 1 deletion apps/client/apis/studyHistoryApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const studyHistoryApi = {
`${apiPath.studyHistory}/assignments?studyId=${studyId}`,
{
next: { tags: [tags.studyHistory] },
cache: "force-cache",
cache: "no-store",
}
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,61 +1,34 @@
"use client";

import { Space } from "@wow-class/ui";
import { myStudyApi } from "apis/myStudyApi";
import { studyDetailApi } from "apis/studyDetailApi";
import { padWithZero, parseISODate } from "@wow-class/utils";
import { studyHistoryApi } from "apis/studyHistoryApi";
import { tags } from "constants/tags";
import Link from "next/link";
import { useEffect, useState } from "react";
import { toast } from "react-toastify";
import type { Assignment } from "types/dtos/studyDetail";
import type { AssignmentSubmissionStatusType } from "types/entities/common/assignment";
import { getIsAfterStartDate } from "utils/getIsAfterStartDate";
import { isDeadlinePassed } from "utils/isDeadlinePassed";
import { revalidateTagByName } from "utils/revalidateTagByName";
import { Link as LinkIcon, Reload as ReloadIcon } from "wowds-icons";
import Button from "wowds-ui/Button";
interface AssignmentBoxButtonsProps {
assignment: Assignment;
repositoryLink?: string;
buttonsDisabled?: boolean;
}

export const AssignmentBoxButtons = ({
buttonsDisabled: buttonDisabledProp,
buttonsDisabled,
assignment,
repositoryLink,
}: AssignmentBoxButtonsProps) => {
const [startDate, setStartDate] = useState("");

const targetWeek = assignment.week;

useEffect(() => {
const fetchAssignmentStartDate = async () => {
const ongoingStudyInfo = await myStudyApi.getMyOngoingStudyInfo();

if (ongoingStudyInfo?.studyId) {
const curriculumData = await myStudyApi.getStudyCurriculumList(
ongoingStudyInfo.studyId
);

const matchingWeek = curriculumData?.find(
(item) => item.week === targetWeek
);

if (matchingWeek) {
setStartDate(matchingWeek.period.startDate);
}
}
};

fetchAssignmentStartDate();
}, [targetWeek]);

const buttonsDisabled = buttonDisabledProp || !getIsAfterStartDate(startDate);

return (
<>
<PrimaryButton
assignment={assignment}
buttonsDisabled={buttonsDisabled}
repositoryLink={repositoryLink}
/>
<Space height={8} />
<SecondaryButton
Expand All @@ -68,29 +41,8 @@ export const AssignmentBoxButtons = ({
const PrimaryButton = ({
assignment,
buttonsDisabled,
repositoryLink,
}: AssignmentBoxButtonsProps) => {
const [repositoryLink, setRepositoryLink] = useState("");

useEffect(() => {
const fetchStudyDashBoard = async () => {
const ongoingStudyInfo = await myStudyApi.getMyOngoingStudyInfo();
if (!ongoingStudyInfo) {
return;
}
const studyDashboard = await studyDetailApi.getStudyDetailDashboard(
ongoingStudyInfo.studyId
);

if (!studyDashboard) {
return;
} else {
setRepositoryLink(studyDashboard.repositoryLink);
}
};

fetchStudyDashBoard();
}, []);

const { assignmentSubmissionStatus, submissionFailureType, submissionLink } =
assignment;
const { primaryButtonText } =
Expand All @@ -105,14 +57,13 @@ const PrimaryButton = ({
return;
}
const stroke = buttonsDisabled ? "mono100" : "primary";
const link =
assignmentSubmissionStatus === null ? repositoryLink : submissionLink;

const primaryButtonHref =
assignmentSubmissionStatus === "SUCCESS" ? submissionLink : repositoryLink;
return (
<Button
asProp={Link}
disabled={buttonsDisabled}
href={link ?? ""}
href={primaryButtonHref ?? ""}
icon={<LinkIcon height={20} stroke={stroke} width={20} />}
style={buttonStyle}
target="_blank"
Expand All @@ -126,43 +77,43 @@ const PrimaryButton = ({
const SecondaryButton = ({
assignment,
buttonsDisabled,
}: AssignmentBoxButtonsProps) => {
}: Omit<AssignmentBoxButtonsProps, "repositoryLink">) => {
const { assignmentSubmissionStatus, studyDetailId, deadline, committedAt } =
assignment;
if (isDeadlinePassed(deadline)) {
return (
<Button disabled={true} style={buttonStyle}>
마감
</Button>
);
}
const { secondaryButtonText } =
assignmentSubmissionStatus === null
? buttonTextMap.INITIAL
: buttonTextMap[assignmentSubmissionStatus];

const handleClickSubmissionComplete = async () => {
const response = await studyHistoryApi.submitAssignment(studyDetailId);
if (response.success) {
//TODO: 과제 제출 이후에는 과제 상태에 대한 업데이트 필요
//이번주 과제 조회 api, 대시보드 api revaliate
revalidateTagByName(
assignmentSubmissionStatus === null
? tags.studyDetailDashboard
: tags.upcomingStudy
);
revalidateTagByName(tags.studyDetailDashboard);
revalidateTagByName(tags.studyHistory);
toast.success("과제 제출이 완료되었어요.");
}
};

if (isDeadlinePassed(deadline)) {
return (
<Button disabled={true} style={buttonStyle}>
마감
</Button>
);
}
const stroke = buttonsDisabled ? "mono100" : "backgroundNormal";
const { year, month, day, hours, minutes } = parseISODate(
committedAt as string
);
const commitText = `최종 수정일자 ${year}년 ${month}월 ${day}일 ${padWithZero(hours)}:${padWithZero(minutes)}`;
return (
<Button
disabled={buttonsDisabled}
icon={<ReloadIcon height={20} stroke={stroke} width={20} />}
style={buttonStyle}
{...(assignmentSubmissionStatus === "SUCCESS" &&
committedAt && {
subText: `최종 수정일자 ${committedAt}`,
subText: commitText,
})}
onClick={handleClickSubmissionComplete}
>
Expand All @@ -173,7 +124,7 @@ const SecondaryButton = ({

const buttonStyle = {
maxWidth: "100%",
height: "48px !important",
height: "fit-content",
};

const buttonTextMap: Record<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ import { Text } from "@wow-class/ui";
import { padWithZero, parseISODate } from "@wow-class/utils";
import Image from "next/image";
import type { Assignment } from "types/dtos/studyDetail";
import { getAssignmentGithubFolderName } from "utils/getAssignmentGithubFolderName";

import { FailurePopover } from "./FailurePopover";
interface AssignmentBoxInfoProps {
assignment: Assignment;
repositoryLink?: string;
}

export const AssignmentBoxInfo = async ({
assignment,
repositoryLink,
}: AssignmentBoxInfoProps) => {
const {
deadline,
assignmentSubmissionStatus,
submissionFailureType,
submissionLink,
} = assignment;
const { deadline, assignmentSubmissionStatus, submissionFailureType, week } =
assignment;

const { year, month, day, hours, minutes } = parseISODate(deadline);

Expand All @@ -32,16 +31,16 @@ export const AssignmentBoxInfo = async ({
return (
<>
<Text color="sub">{deadlineText}</Text>
{(isSuccess || (isFailure && !isNotSubmitted)) && (
{(isSuccess || (isFailure && !isNotSubmitted)) && repositoryLink && (
<Flex alignItems="center" gap="xs">
<Text as="div" color="sub">
제출한 과제
제출한 과제 :{" "}
<Text as="span" color="textBlack">
과제 이름
{`${getAssignmentGithubFolderName(repositoryLink)}/week${week}`}
</Text>
</Text>
<Image alt="dot" height={6} src="/images/dot.svg" width={6} />
<styled.div color={isFailure ? "error" : "primary"}>
<styled.div color={isFailure ? "red.500" : "primary"}>
{isFailure ? failMapping[submissionFailureType] : "글자수 충족"}
</styled.div>
<FailurePopover submissionFailureType={submissionFailureType} />
Expand All @@ -52,8 +51,9 @@ export const AssignmentBoxInfo = async ({
};

const failMapping: Record<Assignment["submissionFailureType"], string> = {
LOCATION_UNIDENTIFIABLE: "위치 정보 확인 불가",
LOCATION_UNIDENTIFIABLE: "위치 확인 불가",
WORD_COUNT_INSUFFICIENT: "글자수 부족",
NOT_SUBMITTED: "제출 안함",
NONE: "없음",
UNKNOWN: "알 수 없음",
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,24 @@ export const FailurePopover = ({
"Q. 글자수가 부족하다고 나와요."}
{submissionFailureType === "LOCATION_UNIDENTIFIABLE" &&
'Q. "위치 확인 불가" 라고 나와요.'}
{submissionFailureType === "UNKNOWN" &&
'Q. "알 수 없음" 라고 나와요.'}
</Text>
<Text as="div" color="outline" typo="body3">
{submissionFailureType === "LOCATION_UNIDENTIFIABLE" && (
<>
아래 조건에 맞게 wil.md 파일을 제출했는지 확인해주세요. <br />
<br />
<ul style={ulStyle}>
<li>본인의 레포지터리가 맞는지</li>
<li>본인의 레포지토리가 맞는지</li>
<li>제출한 브랜치 이름이 main인지</li>
<li>파일 위치가 `weekn/wil.md` 가 맞는지</li>
<li>커밋 후 원격 저장소에 push까지 완료했는지</li>
</ul>
<br />
<br />
커밋 후 원격 저장소에 push까지 완료했는지 제대로 제출한 후에도
계속 "경로 확인 불가"라고 나온다면,GDSC Hongik 카카오톡 채널로
문의해주세요.
제대로 제출한 후에도 계속 "위치 확인 불가"라고 나온다면,GDSC
Hongik 카카오톡 채널로 문의해주세요.
</>
)}
{submissionFailureType === "WORD_COUNT_INSUFFICIENT" && (
Expand All @@ -53,6 +54,17 @@ export const FailurePopover = ({
GDSC Hongik 카카오톡 채널로 문의해주세요.
</p>
)}
{submissionFailureType === "UNKNOWN" && (
<p>
'위치 확인 불가' 나 '글자 수 부족' 외의 다른 이유로
<br />
제출 실패를 한 경우에요. <br />
<br />
제대로 제출한 후에도 계속 '알 수 없음' 이 뜬다면,
<br />
GDSC Hongik 카카오톡 채널로 문의해주세요.
</p>
)}
</Text>
</Flex>
</Popover>
Expand Down
Loading
Loading