Skip to content

Commit

Permalink
[Fix] 나의 과제 페이지, 수강 신청 페이지 QA 반영 (#133)
Browse files Browse the repository at this point in the history
* feat: 큐에이 반영

* fix: 소문자로 변경

* refactor: api dto 반영, 이번 주 과제 조회 api 연결

* feat: 히스토리 api 수정된 dto 반영

* feat: 히스토리 api 수정된 거 반영, 레포지토리 입력 api 반영

* refactor: 레포 모달 창 상태 관리 컴포넌트로 벼녕

* feat: 필요없는 로직 삭제

* feat: 이번 주 과제 조회 스터디 추가

* feat: 모달 라우팅 삭제

* feat: submissionLink 에서 폴더

* chore: 안쓰는 상수 삭제

* chore: 말줄임 처리, github url 인지 체크

* feat: 스터디 시작 날짜가 현재 날짜인지 확인하고 disabled 처리

* feat: 공통 타입은 common 으로 옮기기, 리뷰 반영

* fix: 빠진 네이밍 수정 반영

* feat: Button asProp 으로 Link 전달, css 수정

* refactor: NonNullable 처리, Initial 로 관리

* feat: github 관련 유틸 분리,css 수정

* chore: 필요없는 프래그먼트 삭제

* chore: cache 속서 추가

* feat: currentPath href 매치될 때만 active 되게 navItem 수정

* chore: myStudy 용 타입 추가

* chore: EDITING_WITH_WARNING 타입 삭제, 상태 네이밍 변경

* chore: 조건식 간소화

* chore: submissionLink null 로 내려오는 부분 우선 삭제

* feat: 리뷰 반영

* feat: 수강 신청 아이템 width 고정

* fix: dev 환경일 때는 dev-onboarding 으로 연결

* feat: 부모컴포넌트에서 호출하도록 수정

* feat: 히스토리 아이템 반응형 처리

* feat: upcoming api 로직 삭제

* feat: 부모컴포넌트에서 api 불러오기

* fix: 컴포넌트 호출 위치 수정

* chore: 문구 수정 반영

* chore: 헤더 삭제

* chore: 수강신청 아이템 정렬 수정

* chore: repo link 가 있는 지 확인하는 로직 추가

* chore: 레포지토리로 네이밍 변경

* chore: 인자명 repositoryLink 로 변경

* chore: length 0일때만 확인

* fix: cache no-store 로 설정

* chore: api 호출하지 않고 props 로 전달하는 걸로 수정

* chore: 목데이터 삭제

* chore: 에러 메시지 문구 해요체로 변경

* chore: 컬러 변경, 함수 네이밍 변경

* feat: unknown 인 케이스 우선 임의로 반영

* chore: 실패 팝오버 문구 수정

* chore: popoverRef 위치 상단으로 변경
  • Loading branch information
SeieunYoo authored Sep 7, 2024
1 parent 255f06c commit 0e8bbb3
Show file tree
Hide file tree
Showing 19 changed files with 204 additions and 321 deletions.
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

0 comments on commit 0e8bbb3

Please sign in to comment.