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] 나의 스터디 페이지 UI 구축 #35

Merged
merged 50 commits into from
Aug 20, 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
f995ed1
feat: wowds-icons 패키지 설치
ghdtjgus76 Aug 15, 2024
37abb94
feat: 나의 스터디 페이지 헤더 컴포넌트 레이아웃 구현
ghdtjgus76 Aug 15, 2024
187b71d
feat: 나의 스터디 페이지 스터디 공지 컴포넌트 레이아웃 구현
ghdtjgus76 Aug 15, 2024
385d2e1
feat: 나의 스터디 페이지 스터디 커리큘럼 컴포넌트 레이아웃 구현
ghdtjgus76 Aug 15, 2024
7a66ead
design: Navbar 컴포넌트 최소 너비 지정
ghdtjgus76 Aug 15, 2024
8ab26da
chore: client afterLogin layout 하단 패딩 추가
ghdtjgus76 Aug 16, 2024
285e830
design: 스터디 커리큘럼 css 수정
ghdtjgus76 Aug 16, 2024
c126856
design: 스터디 공지 css 수정
ghdtjgus76 Aug 16, 2024
efb1adc
design: 나의 스터디 페이지 헤더 css 수정
ghdtjgus76 Aug 16, 2024
3b86c66
feat: 나의 스터디 페이지 오늘의 할 일 컴포넌트 추가
ghdtjgus76 Aug 16, 2024
6ba77d1
feat: client afterLogin 배럴 파일 추가
ghdtjgus76 Aug 16, 2024
bdcc646
feat: 나의 스터디 페이지 구현
ghdtjgus76 Aug 16, 2024
6a25012
feat: pnpm lock 파일 변경 사항 반영
ghdtjgus76 Aug 16, 2024
5b7c6db
chore: ui 패키지 스타일 변경사항 반영
ghdtjgus76 Aug 16, 2024
e952f5b
feat: 스터디 신청 api 연결 및 응답 포맷팅 로직 추가
SeieunYoo Aug 17, 2024
d1f57c1
feat: body 추가
SeieunYoo Aug 17, 2024
84c4d29
feat: 헤더 뺀 부분
SeieunYoo Aug 17, 2024
5319023
refactor: parseDate 상단에서 하도록 수정, padWitZero 유틸 추가
SeieunYoo Aug 17, 2024
698130e
feat: padWithZero export
SeieunYoo Aug 17, 2024
cd86cc7
feat: lock 파일 변경사항 반영
ghdtjgus76 Aug 18, 2024
bc1ddaf
design: client layout width 변경
ghdtjgus76 Aug 18, 2024
59bd6e6
feat: useHorizontalScroll 훅 추가
ghdtjgus76 Aug 18, 2024
bc4fd50
feat: arrow-button 이미지 추가
ghdtjgus76 Aug 18, 2024
5278e0e
feat: 오늘의 할 일 캐러셀 기능 추가
ghdtjgus76 Aug 18, 2024
634462d
feat: async await 으로 변경, success 여부만 넘기는 것으로
SeieunYoo Aug 18, 2024
c01b737
refactor: Table.Content 삭제, 핸들러 이름 변경
SeieunYoo Aug 18, 2024
91c1b3b
feat: 에러 페이지 추가, header 제거
SeieunYoo Aug 18, 2024
9156f48
feat: client 및 공통 constants 추가
ghdtjgus76 Aug 18, 2024
291f96d
feat: 나의 스터디 페이지 헤더 목데이터 기반 UI 구축
ghdtjgus76 Aug 18, 2024
1e5de8a
design: 오늘의 할일 자잘한 디자인 수정
ghdtjgus76 Aug 18, 2024
1cea5a5
feat: 스터디 공지 목데이터 기반 UI 구축
ghdtjgus76 Aug 18, 2024
7a1cc2c
design: 클라이언트 레이아웃 오른쪽 패딩 수정
ghdtjgus76 Aug 19, 2024
540bc2b
feat: 스터디 커리큘럼 목데이터 기반 UI 구축
ghdtjgus76 Aug 19, 2024
c7a5696
refactor: 오늘의 할 일 캐러셀 별도 컴포넌트로 분리
ghdtjgus76 Aug 19, 2024
737f905
feat: 나의 스터디 페이지 오늘의 할 일 목데이터 기반 UI 구축
ghdtjgus76 Aug 19, 2024
4cbcfa5
refactor: 공통 상수값 추출
ghdtjgus76 Aug 19, 2024
32abf0a
chore: parseISODate 함수 반환값 수정
ghdtjgus76 Aug 19, 2024
44a57f7
refactor: 타입 types 폴더로 분리
ghdtjgus76 Aug 19, 2024
4ea105d
fix: 빌드 에러 해결
ghdtjgus76 Aug 19, 2024
eb61b2c
chore: 배럴 파일에서 import하도록 수정
ghdtjgus76 Aug 19, 2024
a8719d7
refactor: formatWeekPeriod 함수로 리팩토링
ghdtjgus76 Aug 20, 2024
53af257
chore: Merge branch 'dev' of https://github.com/GDSC-Hongik/wow-class…
ghdtjgus76 Aug 20, 2024
6df88f6
chore: 소개 링크 바로가기 버튼 텍스트 버튼으로 변경
ghdtjgus76 Aug 20, 2024
cd74fc9
refactor: 목데이터 한 파일에서 관리하도록 수정
ghdtjgus76 Aug 20, 2024
bf8daa9
refactor: map 하나의 객체로 관리하도록 수정
ghdtjgus76 Aug 20, 2024
1f21605
chore: map 타입 명확하게 지정하도록 수정
ghdtjgus76 Aug 20, 2024
f0c4a9c
chore: 과제 제출 상태 dto에 맞게 반영
ghdtjgus76 Aug 20, 2024
02bacce
chore: homework 부분 assignment로 네이밍 변경
ghdtjgus76 Aug 20, 2024
a4665fe
feat: 오늘의 할 일 버튼 조건부 활성화 기능 추가
ghdtjgus76 Aug 20, 2024
796c745
feat: ui 스타일 변경사항 반영
ghdtjgus76 Aug 20, 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
2 changes: 1 addition & 1 deletion apps/client/app/(afterLogin)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
return (
<>
<Navbar />
<styled.main paddingTop="3.375rem" paddingX="6.31rem" width="100vw">
<styled.main padding="54px 0 35px 101px" width="calc(100vw - 351px)">
{children}
</styled.main>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
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 { assignmentSubmissionStatusMap } from "constants/assignmentSubmissionStatusMap";
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 {
week: number;
name: string;
assignmentSubmissionStatus: AssignmentSubmissionStatusType;
deadline: string;
}

const AssignmentStatusBox = ({
week,
name,
assignmentSubmissionStatus,
deadline,
}: AssignmentStatusBoxProps) => {
const { year, month, day, hours, minutes } = parseISODate(deadline);

const attendanceDeadline = `${year}년 ${month}월 ${day}일 ${hours}:${minutes}까지`;
const {
label: assignmentSubmissionStatusLabel,
color: assignmentSubmissionStatusColor,
} = assignmentSubmissionStatusMap[assignmentSubmissionStatus];

return (
<Box
style={dailyTaskBoxStyle}
text={
<Flex
className={dailyTaskBoxContentContainerStyle}
direction="column"
justifyContent="space-between"
>
<Flex direction="column" gap="16px">
<Text as="div" color="primary" typo="label2">
과제
</Text>
<Flex direction="column" gap="4px">
<Flex gap="8px">
<Text as="h2" typo="h2">
{week}주차 과제
</Text>
<Tag color={assignmentSubmissionStatusColor} variant="solid2">
{assignmentSubmissionStatusLabel}
</Tag>
</Flex>
<Text as="div" className={assignmentNameStyle} typo="body1">
{name}
</Text>
<Text as="div" color="sub" typo="body1">
{attendanceDeadline}
</Text>
</Flex>
</Flex>
<Button
disabled={assignmentSubmissionStatus !== "SUCCESS"}
size="lg"
style={assignmentButtonStyle}
>
나의 과제 바로가기
</Button>
</Flex>
}
/>
);
};

export default AssignmentStatusBox;

const dailyTaskBoxStyle = {
maxWidth: "376px",
minWidth: "376px",
paddingBottom: "20px",
height: "229px",
};

const dailyTaskBoxContentContainerStyle = css({
height: "185px",
minWidth: "328px !important",
});

const assignmentButtonStyle = {
minWidth: "328px",
};

const assignmentNameStyle = css({
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
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 { attendanceStatusMap } from "constants/attendanceStatusMap";
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 {
week: number;
attendanceStatus: AttendanceStatusType;
period: {
start: string;
end: string;
};
}

const AttendanceStatusBox = ({
week,
attendanceStatus,
period,
}: AttendanceStatusBoxProps) => {
const {
year: startYear,
month: startMonth,
day: startDay,
hours: startHour,
minutes: startMinute,
} = parseISODate(period.start);
const { hours: endHour, minutes: endMinute } = parseISODate(period.end);

const attendancePeriod = `${startYear}년 ${startMonth}월 ${startDay}일 ${startHour}:${startMinute} - ${endHour}:${endMinute}까지`;
const { label: attendanceStatusLabel, color: attendanceStatusColor } =
attendanceStatusMap[attendanceStatus];

return (
<Box
style={dailyTaskBoxStyle}
text={
<Flex
className={dailyTaskBoxContentContainerStyle}
direction="column"
justifyContent="space-between"
>
<Flex direction="column" gap="16px">
<Text as="div" color="primary" typo="label2">
출석
</Text>
<Flex direction="column" gap="4px">
<Flex gap="8px">
<Text as="h2" typo="h2">
{week}주차 출석체크
</Text>
<Tag color={attendanceStatusColor} variant="solid2">
{attendanceStatusLabel}
</Tag>
</Flex>
<Text as="div" color="error" typo="body1">
{attendancePeriod}
</Text>
</Flex>
</Flex>
<Button size="lg" style={attendanceButtonStyle}>
출석 체크하기
</Button>
</Flex>
}
/>
);
};

export default AttendanceStatusBox;

const dailyTaskBoxStyle = {
maxWidth: "376px",
minWidth: "376px",
paddingBottom: "20px",
height: "229px",
};

const dailyTaskBoxContentContainerStyle = css({
height: "185px",
minWidth: "328px !important",
});

const attendanceButtonStyle = {
minWidth: "328px",
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"use client";

import { css } from "@styled-system/css";
import { Flex } from "@styled-system/jsx";
import useHorizontalScroll from "hooks/useHorizontalScroll";
import Image from "next/image";
import { type PropsWithChildren, useEffect, useState } from "react";

const DailyTaskCarousel = ({ children }: PropsWithChildren) => {
const [showRightButton, setShowRightButton] = useState(false);

const itemWidth = 386;

const { containerRef, handleScroll } = useHorizontalScroll();

useEffect(() => {
if (containerRef.current) {
const containerWidth = containerRef.current.offsetWidth;
const totalChildrenWidth = Array.from(containerRef.current.children)
.map((child) => (child as HTMLElement).offsetWidth)
.reduce((acc, width) => acc + width, 0);

if (totalChildrenWidth > containerWidth) {
setShowRightButton(true);
}
}
}, [containerRef]);

const handleClickScrollRightButton = () => {
if (containerRef.current) {
const currentScrollPosition = containerRef.current.scrollLeft;
const newScrollPosition = currentScrollPosition + itemWidth;

handleScroll(newScrollPosition);
}
};

return (
<>
<Flex
aria-live="polite"
className={dailyTaskBoxContainerStyle}
gap="lg"
ref={containerRef}
>
{children}
</Flex>
{showRightButton && (
<button
aria-label="scroll-right-button"
className={scrollRightButtonStyle}
tabIndex={0}
onClick={handleClickScrollRightButton}
>
<Image
alt="scroll-right-button"
height={52}
src="/images/arrow-button.svg"
width={52}
/>
</button>
)}
</>
);
};

export default DailyTaskCarousel;

const dailyTaskBoxContainerStyle = css({
overflowX: "auto",
scrollBehavior: "smooth",
scrollbarWidth: "none",
});

const scrollRightButtonStyle = css({
position: "absolute",
top: "110px",
right: "101px",
cursor: "pointer",
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Flex } from "@styled-system/jsx";
import { Text } from "@wow-class/ui";
import { dailyTaskMockData } from "constants/mockData";

import { AttendanceStatusBox, DailyTaskCarousel } from ".";
import AssignmentStatusBox from "./AssignmentStatusBox";

const DailyTasks = () => {
return (
<section aria-label="daily-tasks">
<Flex direction="column" gap="xl" position="relative">
<Text typo="h2">오늘의 할 일</Text>
<DailyTaskCarousel>
{dailyTaskMockData.map((dailyTask, index) => {
return dailyTask.type === "ATTENDANCE" ? (
<AttendanceStatusBox
attendanceStatus={dailyTask.attendanceStatus}
key={index}
period={dailyTask.period}
week={dailyTask.week}
/>
) : (
<AssignmentStatusBox
deadline={dailyTask.deadline}
key={index}
name={dailyTask.name}
week={dailyTask.week}
assignmentSubmissionStatus={
dailyTask.assignmentSubmissionStatus
}
/>
);
})}
</DailyTaskCarousel>
</Flex>
</section>
);
};

export default DailyTasks;
Loading
Loading