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

feat: 캘린더 구현 #173

Merged
merged 14 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
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
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import clsx from 'clsx';
import { useRouteData, useTheme } from '@/core/hooks';
import timeOption from './core/api/options/time';
import getTimeRange from './core/utils/getTimeRange';
import useCheckAuthRequired from './useCheckAuthRequired';
// import useCheckAuthRequired from './useCheckAuthRequired';
import { Navbar } from './shared/Navbar';
import { UnknownFallback } from './shared/ErrorBoundary';
import 'swiper/css';
Expand All @@ -15,7 +15,7 @@ import 'swiper/css/bundle';
const App = () => {
const { navBarRequired, path } = useRouteData();
const { theme, setTheme } = useTheme();
useCheckAuthRequired();
// useCheckAuthRequired();

const { data, isSuccess } = useQuery({
...timeOption,
Expand Down
142 changes: 87 additions & 55 deletions src/RoomDetail/components/RoomCalendar.tsx
Original file line number Diff line number Diff line change
@@ -1,74 +1,106 @@
import { MouseEvent, useRef, useContext } from 'react';
import clsx from 'clsx';
import { twMerge } from 'tailwind-merge';
import { makeWeekCalendar } from '../utils/utils';
import { DAY_OF_THE_WEEK } from '../constants/constant';
import { DateRoomDetailContext } from './RoomDetailProvider';
import { Icon } from '@/shared/Icon';
import { Toast } from '@/shared/Toast';

const calendar = [
{
day: '월',
date: '8',
bug: true,
point: false
},
{
day: '화',
date: '9',
bug: true,
point: false
},
{
day: '수',
date: '10',
bug: false,
point: false
},
{
day: '목',
date: '11',
bug: true,
point: true
},
{
day: '금',
date: '12',
bug: true,
point: false
},
{
day: '토',
date: '13',
bug: false,
point: false
},
{
day: '일',
date: '14',
bug: true,
point: false
}
];
interface RoomCalendarProps {
certifiedDates: string[];
certifyTime: number;
serverTime: Date;
}

const RoomCalendar = ({
certifiedDates,
certifyTime,
serverTime
}: RoomCalendarProps) => {
const dateRef = useRef<HTMLDivElement>(null);
const { selectDate, date: chooseDate } = useContext(DateRoomDetailContext);

const { thisWeekTimestamp } = makeWeekCalendar(serverTime);
const chooseDateTimestamp = `${chooseDate.getFullYear()}-${
chooseDate.getMonth() + 1
}-${chooseDate.getDate()}`;

const handleDateClick = (e: MouseEvent<HTMLDivElement>) => {
if (e.target !== dateRef.current) {
return;
}

selectDate(new Date());
};

const RoomCalendar = () => {
return (
<div className="mb-[3.19rem] mt-[1.87rem]">
<h4 className="pb-2 text-base text-black dark:text-white">2023년 10월</h4>
<div className="flex justify-between">
{calendar.map(({ day, date, point, bug }) => {
<div
className="flex justify-between"
ref={dateRef}
onClick={handleDateClick}
>
{thisWeekTimestamp.map((thisDate) => {
const date = thisDate.getDate();
const day = thisDate.getDay();
const thisDateTimestamp = `${thisDate.getFullYear()}-${
thisDate.getMonth() + 1
}-${date}`;
const langKoDay = DAY_OF_THE_WEEK[day];
const bug = certifiedDates.find((el) => el === thisDateTimestamp);

const RoomCalendarStyle = {
calendarItem: clsx(
'flex h-[5.87rem] w-[3.12rem] flex-col items-center rounded-[0.62rem] pt-1 text-center ',
{
'border-light-point text-light-point dark:border-dark-point dark:text-dark-point border-[0.06rem]':
point === true,
'text-darkGray': point === false
}
calendarItem: twMerge(
clsx(
'relative flex h-[5.87rem] w-[3.12rem] cursor-default flex-col items-center pt-1 text-center',
{
'text-dark-gray': serverTime.getTime() < thisDate.getTime(),
'text-black': serverTime.getTime() >= thisDate.getTime(),
'rounded-[0.62rem] border-light-point text-light-point dark:border-dark-point dark:text-dark-point border-[0.06rem]':
thisDateTimestamp === chooseDateTimestamp
}
)
)
};

return (
<div
className={RoomCalendarStyle.calendarItem}
key={day}
onClick={() => {
const routineLimitTime = new Date(serverTime);
routineLimitTime.setHours(certifyTime);
routineLimitTime.setMinutes(50);

if (serverTime.getTime() >= thisDate.getTime()) {
selectDate(thisDate);

if (
thisDate.getDate() === routineLimitTime.getDate() &&
serverTime.getTime() < routineLimitTime.getTime()
) {
Toast.show(
{
message: '인증 시간 이후 확인 가능합니다',
status: 'info'
},
2000
);
}
} else {
Toast.show(
{
message: '조회가 가능하지 않은 날짜입니다',
status: 'info'
},
2000
);
}
}}
>
<div className="mb-1 text-sm">{day}</div>
<div className="mb-1 text-sm">{langKoDay}</div>
<div className="mb-2 text-2xl">{date}</div>
<div className="flex justify-center">
{bug && (
Expand Down
47 changes: 47 additions & 0 deletions src/RoomDetail/components/RoomDetailContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useContext } from 'react';
import { useQuery } from '@tanstack/react-query';
import { roomOptions } from '@/core/api/options';
import { DateRoomDetailContext } from './RoomDetailProvider';
import { RoomInfo, RoomWorkspace } from '@/RoomDetail';
import { RoomInfo as RoomInfoType } from '@/core/types/Room';
interface RoomDetailContainerProps {
roomDetailData: RoomInfoType;
serverTime: Date;
}

const RoomDetailContainer = ({
roomDetailData,
serverTime
}: RoomDetailContainerProps) => {
const { date } = useContext(DateRoomDetailContext);
const roomId = '1234';
const chooseDate = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;

const { data: roomDetailDataByDate, status } = useQuery({
...roomOptions.detailByDate(roomId, chooseDate)
});

if (roomDetailDataByDate) {
roomDetailData = roomDetailDataByDate;
}

return (
<>
<div className="h-[20.56rem] bg-[url('/level1.png')] bg-cover bg-no-repeat text-white">
<RoomInfo
{...roomDetailData}
status={status}
/>
</div>
<div className="px-[1.81rem] pb-[1.62rem] pt-[1.88rem]">
<RoomWorkspace
{...roomDetailData}
status={status}
serverTime={serverTime}
/>
</div>
</>
);
};

export default RoomDetailContainer;
38 changes: 38 additions & 0 deletions src/RoomDetail/components/RoomDetailProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ReactNode, useState, createContext } from 'react';

export const DateRoomDetailContext = createContext<{
date: Date;
selectDate: (value: Date) => void;
}>({
date: new Date(),
selectDate: (value: Date) => {
return value;
}
});

interface RoomDetailProviderProps {
children: ReactNode;
serverTime: Date;
}

const RoomDetailProvider = ({
children,
serverTime
}: RoomDetailProviderProps) => {
const [changedDate, setChangeDate] = useState<Date>(serverTime);

return (
<DateRoomDetailContext.Provider
value={{
date: changedDate,
selectDate: (dateValue: Date) => {
setChangeDate(dateValue);
}
}}
>
{children}
</DateRoomDetailContext.Provider>
);
};

export default RoomDetailProvider;
23 changes: 16 additions & 7 deletions src/RoomDetail/components/RoomInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,28 @@ import RoomMemberRank from './RoomMemberRank';
import { ProgressBar } from '@/shared/ProgressBar';
import { RoomInfo as RoomInfoType } from '@/core/types/Room';

interface extendedProps {
status: 'pending' | 'error' | 'success';
}
type RoomInfoProps = extendedProps & RoomInfoType;
const RoomInfo = ({
level,
currentUserCount,
maxUserCount,
todayCertificateRank,
certifyTime
}: RoomInfoType) => {
certifyTime,
status
}: RoomInfoProps) => {
return (
<div className="relative flex h-[20.56rem] items-center justify-center">
<RoomMemberRank
todayCertificateRank={todayCertificateRank}
certifyTime={certifyTime}
/>
<div className="relative h-[20.56rem]">
{status !== 'success' ? (
<div>임시 Loading...</div>
) : (
<RoomMemberRank
todayCertificateRank={todayCertificateRank}
certifyTime={certifyTime}
/>
)}
<div className="absolute inset-x-0 bottom-0">
<div className="mb-2 flex items-end justify-between bg-inherit pl-3.5 pr-7">
<span className="block h-[1.93rem] w-[4.62rem] rounded-[6.25rem] bg-light-point py-[0.16rem] text-center font-IMHyemin-bold text-light-main dark:bg-dark-point">
Expand Down
35 changes: 28 additions & 7 deletions src/RoomDetail/components/RoomWorkspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,22 @@ import { BottomSheet, useBottomSheet } from '@/shared/BottomSheet';
import { Tab, TabItem } from '@/shared/Tab';
import { RoomInfo } from '@/core/types/Room';

interface extendedProps {
status: 'pending' | 'error' | 'success';
serverTime: Date;
}

type RoomWorkspaceProps = extendedProps & RoomInfo;

const RoomWorkspace = ({
completePercentage,
routine,
todayCertificateRank
}: RoomInfo) => {
todayCertificateRank,
certifiedDates,
certifyTime,
status,
serverTime
}: RoomWorkspaceProps) => {
const { bottomSheetProps, toggle, close } = useBottomSheet();

const myCertificationImage = todayCertificateRank.find(
Expand Down Expand Up @@ -45,12 +56,22 @@ const RoomWorkspace = ({
defaultIndex={0}
>
<TabItem title="루틴">
<RoomCalendar />
<CertificationProgress percentage={completePercentage} />
<RoomRoutine
routines={routine}
myCertificationImage={myCertificationImage}
<RoomCalendar
certifiedDates={certifiedDates}
certifyTime={certifyTime}
serverTime={serverTime}
/>
{status !== 'success' ? (
<div>임시 Loading...</div>
) : (
<>
<CertificationProgress percentage={completePercentage} />
<RoomRoutine
routines={routine}
myCertificationImage={myCertificationImage}
/>
</>
)}
<button
className="mt-[1.19rem] text-sm text-black dark:text-white"
onClick={toggle}
Expand Down
1 change: 1 addition & 0 deletions src/RoomDetail/constants/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DAY_OF_THE_WEEK = ['일', '월', '화', '수', '목', '금', '토'];
19 changes: 19 additions & 0 deletions src/RoomDetail/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export const makeWeekCalendar = (serverTime: Date) => {
const weekArray: Date[] = Array.from({ length: 7 });

const todayDate = serverTime.getDate();
const todayDay = serverTime.getDay();

for (let i = 0; i < 7; i++) {
const mondayDate = todayDate - todayDay + 1;
const newDate = new Date(serverTime);

newDate.setFullYear(newDate.getFullYear());
newDate.setMonth(newDate.getMonth());
newDate.setDate(mondayDate + i);

weekArray[i] = newDate;
}

return { thisWeekTimestamp: weekArray };
};
1 change: 0 additions & 1 deletion src/core/api/functions/roomAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
TotalRooms
} from '@/core/types';
import { baseInstance, formDataInstance } from '../instance';

import { MyJoinRoom } from '@/core/types/MyJoinRoom';
import { RoomInfo, RoomInfoBeforeEditing } from '@/core/types/Room';

Expand Down
2 changes: 1 addition & 1 deletion src/core/mocks/datas/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const RoomInfo = {
maxUserCount: 9,
announcement: '2번 연속 인증 안하는 사람은 추방할 예정입니다 ㅅㄱ!',
completePercentage: 66.7,
certifiedDates: ['2023-03-02', '2023-03-03', '2023-03-02'],
certifiedDates: ['2023-11-13', '2023-11-14', '2023-11-16'],
routine: [
{
routineId: 5,
Expand Down
Loading