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

[Feature] 나의 스터디 페이지 모달 구현 #39

Merged
merged 19 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c5f8156
feat: client에 wowds-ui 패키지 설치
ghdtjgus76 Aug 20, 2024
33e2a3b
feat: LinkButton 컴포넌트 추가
ghdtjgus76 Aug 20, 2024
f488442
feat: 오늘의 할 일 AssignmentStatusBox 라우팅 기능 추가
ghdtjgus76 Aug 20, 2024
794101d
chore: StudyCurriculum LinkButton으로 변경
ghdtjgus76 Aug 20, 2024
c69b64f
chore: Modal 컴포넌트 내부에서 className, style 커스텀할 수 있도록 변경
ghdtjgus76 Aug 20, 2024
920864d
chore: AttendanceStatusBox 버튼 링크 버튼으로 변경
ghdtjgus76 Aug 20, 2024
a2939bf
feat: 출석체크 모달 기능 추가
ghdtjgus76 Aug 20, 2024
be69e07
feat: 출석체크 완료 모달 기능 추가
ghdtjgus76 Aug 20, 2024
c11492d
chore: 모달 컴포넌트 기본 onClose는 router.back으로 지정하도록 수정
ghdtjgus76 Aug 20, 2024
b4f098b
chore: 모달 컴포넌트 onClose 핸들러 삭제
ghdtjgus76 Aug 20, 2024
cd88bb6
feat: ui 변경사항 반영
ghdtjgus76 Aug 20, 2024
e598f96
chore: 출석 체크 완료 모달 컴포넌트명 변경
ghdtjgus76 Aug 20, 2024
4167b3a
rename: check attendance -> attendance check로 네이밍 변경
ghdtjgus76 Aug 20, 2024
5faca05
refactor: 모달 parallel route 한 폴더에서 관리하도록 수정
ghdtjgus76 Aug 21, 2024
5fbe708
chore: 나의 스터디 페이지 모달 조건부 렌더링 방식으로 변경
ghdtjgus76 Aug 21, 2024
00da8dc
chore: Merge branch 'dev' into feature/my-study-modal
ghdtjgus76 Aug 21, 2024
639a53b
feat: ui 패키지 스타일 변경사항 반영
ghdtjgus76 Aug 21, 2024
5c12da0
fix: 빌드 에러 해결
ghdtjgus76 Aug 21, 2024
7ea2897
fix: 스토리북 appDirectory 설정 추가
ghdtjgus76 Aug 21, 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"use client";

import { css } from "@styled-system/css";
import { Flex } from "@styled-system/jsx";
import { Modal, Text } from "@wow-class/ui";
import { routePath } from "constants/routePath";
import Image from "next/image";
import { useRouter } from "next/navigation";
import { useState } from "react";
import Button from "wowds-ui/Button";
import TextField from "wowds-ui/TextField";

const AttendanceCheckModal = () => {
const [error] = useState(false);
const [attendanceNumber, setAttendanceNumber] = useState("");

const router = useRouter();

const handleChangeAttendanceNumber = (value: string) => {
setAttendanceNumber(value);
};

const handleClickAttendanceCheckButton = () => {
// TODO api 요청 및 에러 처리 필요
ghdtjgus76 marked this conversation as resolved.
Show resolved Hide resolved
router.push(routePath["attendance-complete"]);
};

return (
<Modal>
<Flex alignItems="center" direction="column" gap="sm" marginBottom="40px">
<section
aria-label="attendance-check-title"
className={attendanceCheckTitleStyle}
>
<Text as="h1" typo="h1">
기초 웹스터디
</Text>
ghdtjgus76 marked this conversation as resolved.
Show resolved Hide resolved
<Image
alt="item separator"
height={6}
src="/images/dot.svg"
width={6}
/>
<Text as="h1" typo="h1">
4주차
</Text>
</section>
<section
aria-label="attendance-check-description"
className={attendanceCheckDescriptionStyle}
>
<Text as="p" color="sub" typo="body1">
스터디 시작 후 멘토의 안내에 따라 출결번호를 입력해주세요.
</Text>
<Text as="p" color="error" typo="body1">
2024년 5월 23일 0:00 - 23:59까지
</Text>
</section>
</Flex>
<TextField
error={error}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P4;
출결번호가 최대 4글자까지니까 maxLength props 추가하는게 어때용!?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추가해봤는데 기존 와우 디자인 시스템에 있던 maxLength 관련 디자인이 있어가지고... 피그마상 디자인이랑 동일하게 구현하려면 못 쓸 거 같아요..
이 PR에서 api 연결하면서 validation도 같이 진행 중이에요!
4글자 숫자로 이루어진 문자열인지 validation하도록 해놔서 괜찮을 거 같아요~!

image

helperText={error ? textfieldHelperText : ""}
label="출결번호 입력"
placeholder="Ex. 0000"
style={textfieldStyle}
value={attendanceNumber}
onChange={handleChangeAttendanceNumber}
ghdtjgus76 marked this conversation as resolved.
Show resolved Hide resolved
/>
<Button onClick={handleClickAttendanceCheckButton}>출석 체크하기</Button>
</Modal>
);
};

export default AttendanceCheckModal;

const textfieldHelperText = <div>• 출석 실패! 출결번호를 확인해주세요.</div>;

const attendanceCheckTitleStyle = css({
display: "flex",
gap: "sm",
});

const attendanceCheckDescriptionStyle = css({
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "xxs",
});

const textfieldStyle = {
height: "89px",
marginBottom: "20px",
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"use client";

import { css } from "@styled-system/css";
import { Flex } from "@styled-system/jsx";
import { Modal, Text } from "@wow-class/ui";
import { routePath } from "constants/routePath";
import Image from "next/image";
import { usePathname, useRouter } from "next/navigation";

const AttendanceCompleteModal = () => {
const pathname = usePathname();
const router = useRouter();

const handleCloseModal = () => {
router.push(routePath["my-study"]);
};
ghdtjgus76 marked this conversation as resolved.
Show resolved Hide resolved

if (pathname === routePath["my-study"]) {
return null;
}
ghdtjgus76 marked this conversation as resolved.
Show resolved Hide resolved

return (
<Modal onClose={handleCloseModal}>
<Flex alignItems="center" direction="column" gap="4px">
<section
aria-label="attendance-complete-title"
className={attendanceCompleteTitleStyle}
>
<Text as="h1" color="primary" typo="h1">
기초 웹스터디
</Text>
<Image
alt="item separator"
height={6}
src="/images/dot.svg"
width={6}
/>
<Text as="h1" color="primary" typo="h1">
4주차
</Text>
</section>
<section aria-label="attendance-complete-description">
<Text as="h1" color="textBlack" typo="h1">
출석이 완료되었어요.
</Text>
</section>
</Flex>
</Modal>
);
};

export default AttendanceCompleteModal;

const attendanceCompleteTitleStyle = css({
display: "flex",
gap: "sm",
});
5 changes: 5 additions & 0 deletions apps/client/app/(afterLogin)/my-study/@modal/default.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Default = () => {
return null;
};

export default Default;
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { css } from "@styled-system/css";
import { Flex } from "@styled-system/jsx";
import { Text } from "@wow-class/ui";
import { parseISODate } from "@wow-class/utils";
import LinkButton from "components/LinkButton";
import { assignmentSubmissionStatusMap } from "constants/assignmentSubmissionStatusMap";
import { routePath } from "constants/routePath";
import type { AssignmentSubmissionStatusType } from "types/entities/myStudy";
import Box from "wowds-ui/Box";
import Button from "wowds-ui/Button";
import Tag from "wowds-ui/Tag";

interface AssignmentStatusBoxProps {
Expand Down Expand Up @@ -59,13 +60,14 @@ const AssignmentStatusBox = ({
</Text>
</Flex>
</Flex>
<Button
<LinkButton
disabled={assignmentSubmissionStatus !== "SUCCESS"}
href={routePath["my-assignment"]}
size="lg"
style={assignmentButtonStyle}
>
나의 과제 바로가기
</Button>
</LinkButton>
</Flex>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { css } from "@styled-system/css";
import { Flex } from "@styled-system/jsx";
import { Text } from "@wow-class/ui";
import { parseISODate } from "@wow-class/utils";
import LinkButton from "components/LinkButton";
import { attendanceStatusMap } from "constants/attendanceStatusMap";
import { routePath } from "constants/routePath";
import type { AttendanceStatusType } from "types/entities/myStudy";
import Box from "wowds-ui/Box";
import Button from "wowds-ui/Button";
import Tag from "wowds-ui/Tag";

interface AttendanceStatusBoxProps {
Expand Down Expand Up @@ -62,9 +63,13 @@ const AttendanceStatusBox = ({
</Text>
</Flex>
</Flex>
<Button size="lg" style={attendanceButtonStyle}>
<LinkButton
href={`${routePath["attendance-check"]}/1`}
size="lg"
style={attendanceButtonStyle}
>
출석 체크하기
</Button>
</LinkButton>
</Flex>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import { css } from "@styled-system/css";
import { Flex } from "@styled-system/jsx";
import { Table, Text } from "@wow-class/ui";
import { padWithZero, parseISODate } from "@wow-class/utils";
import { assignmentSubmissionStatusMap } from "constants/assignmentSubmissionStatusMap";
import LinkButton from "components/LinkButton";
import { attendanceStatusMap } from "constants/attendanceStatusMap";
import { studyCurriculumMockData } from "constants/mockData";
import type { ComponentProps } from "react";
import type { LevelType } from "types/entities/myStudy";
import Button from "wowds-ui/Button";
import Tag from "wowds-ui/Tag";

const formatWeekPeriod = (startDate: string, endDate: string) => {
Expand Down Expand Up @@ -54,8 +53,10 @@ const StudyCurriculum = () => {
label: attendanceStatusLabel,
color: attendanceStatusColor,
} = attendanceStatusMap[attendanceStatus];
const { label: assignmentSubmissionStatusLabel } =
assignmentSubmissionStatusMap[assignmentSubmissionStatus];
const assignmentButtonText =
assignmentSubmissionStatus === "SUCCESS"
? "제출한 과제 확인"
: "과제 제출하기";

return (
<Table key={index}>
Expand Down Expand Up @@ -95,9 +96,10 @@ const StudyCurriculum = () => {
>
{attendanceStatusLabel}
</Tag>
<Button
<LinkButton
aria-label="check-submitted-assignment"
disabled={assignmentSubmissionStatus === "PENDING"}
href=""
size="sm"
style={assignmentButtonStyle}
variant={
Expand All @@ -106,8 +108,8 @@ const StudyCurriculum = () => {
: "solid"
}
>
{assignmentSubmissionStatusLabel}
</Button>
{assignmentButtonText}
</LinkButton>
</Table.Right>
</Table>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { routePath } from "constants/routePath";
import { redirect } from "next/navigation";

const CheckAttendancePage = () => {
return redirect(routePath["my-study"]);
};

export default CheckAttendancePage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { routePath } from "constants/routePath";
import { redirect } from "next/navigation";

const AttendanceCompletePage = () => {
return redirect(routePath["my-study"]);
};

export default AttendanceCompletePage;
5 changes: 5 additions & 0 deletions apps/client/app/(afterLogin)/my-study/default.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Default = () => {
return null;
};

export default Default;
16 changes: 16 additions & 0 deletions apps/client/app/(afterLogin)/my-study/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const Layout = ({
children,
modal,
}: {
children: React.ReactNode;
modal: React.ReactNode;
}) => {
return (
<main>
{children}
{modal}
</main>
);
};

export default Layout;
21 changes: 21 additions & 0 deletions apps/client/components/LinkButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"use client";

import { useRouter } from "next/navigation";
import type { ComponentProps } from "react";
import Button from "wowds-ui/Button";

interface LinkButtonProps extends ComponentProps<typeof Button> {
href: string;
}

const LinkButton = ({ href, ...rest }: LinkButtonProps) => {
const router = useRouter();

const handleClickLinkButton = () => {
router.push(href);
};

return <Button onClick={handleClickLinkButton} {...rest} />;
};

export default LinkButton;
Comment on lines +1 to +21
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p5;
next/link<Link>로 감싸는 것이 아닌 Button 컴포넌트를 확장시켜 쓰신건 뎁스를 줄이려는 의도가 맞을까요? 서버컴포넌트에서의 활용을 생각하면 <Link>가 더 적합하다고 생각합니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 일단 해당 컴포넌트를 구현한 이유가 두 가지입니다.

  1. 페이지 단위로 use client 주석을 선언하게 되면 단순 라우팅 기능이 필요한 부분 이외의 불필요한 부분이 클라이언트 컴포넌트 번들에 포함됩니다.
  2. 버튼 컴포넌트의 디자인은 그대로 사용해야 하는 상황입니다.

위 구현체에서 Button 컴포넌트 대신 Link 컴포넌트를 사용하게 되면 디자인 부분을 다시 다 구현해야 한다는 번거로움이 있어 현재로서는 이 방식이 최선이라고 생각했습니다!

3 changes: 3 additions & 0 deletions apps/client/constants/routePath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ export const routePath = {
auth: "/auth",
landing: "/landing",
["my-study"]: "/my-study",
["my-assignment"]: "/my-study/my-assignment",
["auth-error-during-recruitment"]: "/auth-error-during-recruitment",
["auth-error-after-recruitment"]: "/auth-error-after-recruitment",
["attendance-check"]: "/my-study/attendance-check",
["attendance-complete"]: "/my-study/attendance-complete",
onboarding: "https://onboarding.gdschongik.com",
} as const;
3 changes: 2 additions & 1 deletion apps/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"wowds-icons": "^0.1.3",
"wowds-tokens": "^0.1.1"
"wowds-tokens": "^0.1.1",
"wowds-ui": "^0.1.8"
},
"devDependencies": {
"@types/node": "^20",
Expand Down
Loading