-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #530 from depromeet/feat/status-full
[Feat] 현황 full 기능 구현
- Loading branch information
Showing
30 changed files
with
896 additions
and
236 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,9 @@ type QueryList = { | |
feed: { | ||
memberId: number; | ||
}; | ||
missionSummaryList: { | ||
date: string; | ||
}; | ||
}; | ||
|
||
/** | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | ||
}); |
Oops, something went wrong.