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 all 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,130 @@
"use client";

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

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

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

const handleClickAttendanceCheckButton = () => {
setAttended(true);
};

return (
<Modal>
{attended ? (
<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>
) : (
<>
<Flex
alignItems="center"
direction="column"
gap="sm"
marginBottom="40px"
>
<section
aria-label="attendance-check-title"
className={attendanceCheckTitleStyle}
>
<Text as="h1" typo="h1">
기초 웹스터디
</Text>
<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}
helperText={error ? textfieldHelperText : ""}
label="출결번호 입력"
placeholder="Ex. 0000"
style={textfieldStyle}
value={attendanceNumber}
onChange={handleChangeAttendanceNumber}
/>
<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",
};

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/common/assignment";
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"]}`}
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;
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 컴포넌트를 사용하게 되면 디자인 부분을 다시 다 구현해야 한다는 번거로움이 있어 현재로서는 이 방식이 최선이라고 생각했습니다!

2 changes: 2 additions & 0 deletions apps/client/constants/routePath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ 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",
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
3 changes: 3 additions & 0 deletions packages/ui/.storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ const preview: Preview = {
date: /Date$/i,
},
},
nextjs: {
appDirectory: true,
},
},
};

Expand Down
26 changes: 18 additions & 8 deletions packages/ui/src/components/Modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,44 @@
import { css } from "@styled-system/css";
import { Flex, styled } from "@styled-system/jsx";
import Image from "next/image";
import type { PropsWithChildren } from "react";
import { useRouter } from "next/navigation";
import type { CSSProperties, PropsWithChildren } from "react";

import closeUrl from "../../assets/images/close.svg";
import { useClickOutside } from "../../hooks";

/**
* @description 모달 컴포넌트입니다.
*
* @param {() => void} onClose - 모달 컴포넌트를 닫기 위한 함수.
* @param {() => void} [onClose] - 모달 컴포넌트를 닫기 위한 함수.
* @param {ReactNode} [children] - 모달 컴포넌트에 들어갈 자식 요소.
* @param {CSSProperties} [style] - 커스텀 스타일을 적용하기 위한 객체.
* @param {string} [className] - 커스텀 클래스를 적용하기 위한 문자열.
*/

export interface ModalProps extends PropsWithChildren {
onClose: () => void;
interface ModalProps extends PropsWithChildren {
onClose?: () => void;
style?: CSSProperties;
className?: string;
}

const Modal = ({ children, onClose }: ModalProps) => {
const modal = useClickOutside<HTMLDialogElement>(onClose);
const Modal = ({ children, onClose, ...rest }: ModalProps) => {
const router = useRouter();

const handleClose = onClose || router.back;

const modal = useClickOutside<HTMLDialogElement>(handleClose);
ghdtjgus76 marked this conversation as resolved.
Show resolved Hide resolved

return (
<Flex alignItems="center" className={backDropStyle} justifyContent="center">
<styled.dialog className={dialogStyle} ref={modal}>
<styled.dialog className={dialogStyle} ref={modal} {...rest}>
<Image
alt="close-icon"
className={closeButtonStyle}
height={24}
src={closeUrl}
width={24}
onClick={onClose}
onClick={handleClose}
/>
{children}
</styled.dialog>
Expand All @@ -46,6 +55,7 @@ const dialogStyle = css({
display: "flex",
alignItems: "center",
justifyContent: "center",
flexDirection: "column",

position: "relative",

Expand Down
Loading
Loading