Skip to content

Commit

Permalink
Merge pull request #530 from depromeet/feat/status-full
Browse files Browse the repository at this point in the history
[Feat] 현황 full 기능 구현
  • Loading branch information
sumi-0011 authored Feb 12, 2024
2 parents 75e15b9 + d1e4d5e commit 708c486
Show file tree
Hide file tree
Showing 30 changed files with 896 additions and 236 deletions.
26 changes: 13 additions & 13 deletions public/assets/result/character-bg-gradient.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/apis/getQueryKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ type QueryList = {
feed: {
memberId: number;
};
missionSummaryList: {
date: string;
};
};

/**
Expand Down
36 changes: 36 additions & 0 deletions src/apis/result.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import getQueryKey from '@/apis/getQueryKey';
import apiInstance from '@/apis/instance.api';
import { type MissionCategory, type MissionStatus } from '@/apis/schema/mission';
import { useQuery, type UseQueryOptions } from '@tanstack/react-query';

interface MissionSummaryType {
missionId: number;
name: string;
category: MissionCategory;
visibility: string;
missionStatus: MissionStatus;
}

interface MissionSummaryListResponse {
missionAllCount: number;
missionCompleteCount: number;
missionNoneCount: number;
missionSummaryItems: MissionSummaryType[];
}

const RESULT_API = {
getMissionSummaryList: async (date: string): Promise<MissionSummaryListResponse> => {
const { data } = await apiInstance.get(`/missions/summary-list?date=${date}`);
return data;
},
};

export default RESULT_API;

export const useGetMissionSummaryList = (date: string, option?: UseQueryOptions<MissionSummaryListResponse>) => {
return useQuery<MissionSummaryListResponse>({
queryKey: getQueryKey('missionSummaryList', { date }),
queryFn: () => RESULT_API.getMissionSummaryList(date),
...option,
});
};
4 changes: 1 addition & 3 deletions src/app/home/FollowList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,9 @@ export default FollowList;

const containerCss = flex({
overflowY: 'auto',
padding: '16px 0',
paddingBottom: '20px',
padding: '16px 16px 20px',
gap: '12px',
alignItems: 'stretch',
margin: '0 16px',
_scrollbar: {
display: 'none',
},
Expand Down
2 changes: 2 additions & 0 deletions src/app/home/ProfileItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { type FollowDataState } from '@/app/page';
import Thumbnail from '@/components/Thumbnail/Thumbnail';
import { oneLineTextCss } from '@/constants/style/text';
import { css, cx } from '@styled-system/css';

interface Props {
Expand Down Expand Up @@ -29,6 +30,7 @@ function ProfileItem(props: Props) {
<span
className={cx(
nameCss,
oneLineTextCss,
css({
color: props.selected ? 'text.primary' : 'text.tertiary',
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ function MissionHistorySkeleton() {
className={cx(
missionHistoryBannerCss,
css({
animation: 'skeleton',
height: '70px',
}),
)}
Expand Down
65 changes: 0 additions & 65 deletions src/app/result/OverallStatus.tsx

This file was deleted.

46 changes: 46 additions & 0 deletions src/app/result/OverallStatus/BannerSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import Banner from '@/components/Banner/Banner';
import { CardBannerSkeleton } from '@/components/Banner/CardBanner';
import MotionDiv from '@/components/Motion/MotionDiv';
import { grid } from '@/styled-system/patterns';

interface Props {
totalTime: string;
totalMissionAttainRate: string;
}

function BannerSection(props: Props) {
return (
<MotionDiv className={bannerSectionCss}>
<Banner
type="card"
description="전체 누적 시간"
iconUrl="/assets/icons/graph/clock.png"
title={props.totalTime}
/>
<Banner
type="card"
description="총 미션 달성률"
iconUrl="/assets/icons/graph/chart.png"
title={props.totalMissionAttainRate}
/>
</MotionDiv>
);
}

export default BannerSection;

export function BannerSectionSkeleton() {
return (
<div className={bannerSectionCss}>
<CardBannerSkeleton />
<CardBannerSkeleton />
</div>
);
}

const bannerSectionCss = grid({
gridTemplateColumns: '1fr 1fr',
padding: '20px 16px',
gap: '10px',
margin: '0 auto',
});
147 changes: 147 additions & 0 deletions src/app/result/OverallStatus/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import CalendarItem from '@/app/result/OverallStatus/CalendarItem';
import Icon from '@/components/Icon';
import { WEEK_DAYS } from '@/components/MissionDetail/MissionCalender/MissionCalendar.constants';
import { EVENT_LOG_CATEGORY, EVENT_LOG_NAME } from '@/constants/eventLog';
import useCalendar from '@/hooks/useCalendar';
import { eventLogger } from '@/utils';
import { css, cx } from '@styled-system/css';
import dayjs, { type Dayjs } from 'dayjs';

interface Props {
selectDate: Dayjs;
setSelectDate: (date: Dayjs) => void;
}

function MissionCalendar({ selectDate, setSelectDate }: Props) {
const currentData = dayjs();

const { date, monthCalendarData, onPrevMonth, onNextMonth, isCurrentMonth } = useCalendar({
currentData,
isQueryParams: true,
});

const currentYear = date.year();
const currentMonth = date.month() + 1;

const handlePrevMonth = () => {
eventLogger.logEvent(EVENT_LOG_CATEGORY.RESULT, EVENT_LOG_NAME.RESULT.CLICK_CALENDER_ARROW, {
direction: 'prev',
});
onPrevMonth();
};

const handleNextMonth = () => {
eventLogger.logEvent(EVENT_LOG_CATEGORY.RESULT, EVENT_LOG_NAME.RESULT.CLICK_CALENDER_ARROW, {
direction: 'next',
});
onNextMonth();
};

return (
<div>
<section>
<div className={dateLabeWrapperCss}>
<button type={'button'} className={buttonCss} onClick={handlePrevMonth}>
<Icon name="arrow-back" size={14} />
</button>
<div className={dateLabelTextCss}>
<span>
{currentYear}{currentMonth}
</span>
{/* TODO : 나중에 넣어도 되려나 */}
{/* <Icon name={'normal-calender'} size={16} /> */}
</div>
<button
type={'button'}
className={cx(buttonCss, css({ visibility: isCurrentMonth ? 'hidden' : '' }))}
onClick={handleNextMonth}
>
<Icon name="arrow-forward" size={14} />
</button>
</div>
<table className={tableCss}>
<thead>
<tr className={calendarHeaderCss}>
{WEEK_DAYS.map((day) => (
<th key={day}>{day}</th>
))}
</tr>
</thead>
<tbody className={calendarBodyCss}>
{monthCalendarData.map((week, i) => (
<tr key={i}>
{week.map((day, index) => {
if (!day) return <td key={'calender-null-' + index} className={missionCalendarTdCss} />;

// const isToday = dayjs().isSame(`${day.year}-${day.month}-${day.date}`, 'day');
const isSelected = selectDate.isSame(`${day.year}-${day.month}-${day.date}`, 'day');
const thisDay = `${day.year}-${day.month}-${day.date}`;

return (
<CalendarItem
key={thisDay}
isSelected={isSelected}
onClick={() => {
setSelectDate(dayjs(thisDay));
}}
>
{day.date}
</CalendarItem>
);
})}
</tr>
))}
</tbody>
</table>
</section>
<section></section>
</div>
);
}

export default MissionCalendar;

const dateLabeWrapperCss = css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '12px',
height: '36px',
});

const buttonCss = css({
padding: '8px',
});

const tableCss = css({
width: '100%',
textAlign: 'center',
borderSpacing: '0 8px',
});

const dateLabelTextCss = css({
textStyle: 'subtitle2',
color: 'text.secondary',
display: 'flex',
alignItems: 'center',
gap: '4px',
});

const missionCalendarTdCss = css({
padding: ' 12px 0',
});

const calendarHeaderCss = css({
width: '100%',
fontSize: '12px',
fontWeight: '400',
lineHeight: '18px',
color: 'text.secondary',
justifyContent: 'space-between',
height: '40px',
});

const calendarBodyCss = css({
textStyle: 'body6',
color: 'text.tertiary',
});
Loading

0 comments on commit 708c486

Please sign in to comment.