From c992467305a2ec170f0c4641587ce734b615f9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?= <39869096+gwansikk@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:34:36 +0900 Subject: [PATCH 1/8] feat(member): add ArrowButton Component (#91) --- .../common/ArrowButton/ArrowButton.tsx | 26 +++++++++++++++++ .../common/Pagination/Pagination.tsx | 29 +++++++------------ 2 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 apps/member/src/components/common/ArrowButton/ArrowButton.tsx diff --git a/apps/member/src/components/common/ArrowButton/ArrowButton.tsx b/apps/member/src/components/common/ArrowButton/ArrowButton.tsx new file mode 100644 index 00000000..e8315f03 --- /dev/null +++ b/apps/member/src/components/common/ArrowButton/ArrowButton.tsx @@ -0,0 +1,26 @@ +import { cn } from '@utils/string'; +import { ComponentPropsWithRef, forwardRef } from 'react'; +import { MdOutlineNavigateNext } from 'react-icons/md'; + +interface ArrowButtonProps extends ComponentPropsWithRef<'button'> { + direction?: 'prev' | 'next'; +} + +const ArrowButton = forwardRef( + ({ direction = 'prev', className, ...rest }, ref) => { + return ( + + ); + }, +); + +export default ArrowButton; diff --git a/apps/member/src/components/common/Pagination/Pagination.tsx b/apps/member/src/components/common/Pagination/Pagination.tsx index 4eb11bdb..242a1073 100644 --- a/apps/member/src/components/common/Pagination/Pagination.tsx +++ b/apps/member/src/components/common/Pagination/Pagination.tsx @@ -1,5 +1,5 @@ import { cn } from '@utils/string'; -import { MdOutlineNavigateNext } from 'react-icons/md'; +import ArrowButton from '../ArrowButton/ArrowButton'; import type { PaginationOnChange } from '@type/component'; interface PaginationProps { @@ -19,12 +19,12 @@ const Pagination = ({ }: PaginationProps) => { const totalPages = Math.ceil(totalItems / postLimit); - const pageNumber = []; - const startPage = Math.max(1, page - 2); + const startPage = Math.max(1, page - 1); const endPage = Math.min(totalPages, startPage + 4); - for (let i = startPage; i <= endPage; i++) { - pageNumber.push(i); - } + const pageNumber = Array.from( + { length: endPage - startPage + 1 }, + (_, index) => startPage + index, + ); const handleCurrentPageClick = (page: number) => { onChange(Math.max(1, Math.min(page, totalPages))); @@ -32,12 +32,7 @@ const Pagination = ({ return (
- + handleCurrentPageClick(-postLimit)} /> {pageNumber.length === 0 ? ( 1 ) : ( @@ -53,12 +48,10 @@ const Pagination = ({ )) )} - + handleCurrentPageClick(+postLimit)} + />
); }; From 34d7816880e6216ad22606cbb60224bdca826bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?= <39869096+gwansikk@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:36:15 +0900 Subject: [PATCH 2/8] feat(member): add StatusCard Component (#91) --- .../common/StatusCard/StatusCard.tsx | 13 +++++++ .../common/StatusCard/StatusCard.types.ts | 5 +++ .../src/components/common/StatusCard/index.ts | 2 + .../SupportProcedureSection.tsx | 38 ++++++++++--------- 4 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 apps/member/src/components/common/StatusCard/StatusCard.tsx create mode 100644 apps/member/src/components/common/StatusCard/StatusCard.types.ts create mode 100644 apps/member/src/components/common/StatusCard/index.ts diff --git a/apps/member/src/components/common/StatusCard/StatusCard.tsx b/apps/member/src/components/common/StatusCard/StatusCard.tsx new file mode 100644 index 00000000..d596d387 --- /dev/null +++ b/apps/member/src/components/common/StatusCard/StatusCard.tsx @@ -0,0 +1,13 @@ +import type { StatusCardProps } from './StatusCard.types'; + +const StatusCard = ({ icon, label, description }: StatusCardProps) => { + return ( +
+
{icon}
+

{label}

+

{description}

+
+ ); +}; + +export default StatusCard; diff --git a/apps/member/src/components/common/StatusCard/StatusCard.types.ts b/apps/member/src/components/common/StatusCard/StatusCard.types.ts new file mode 100644 index 00000000..ac3b0d85 --- /dev/null +++ b/apps/member/src/components/common/StatusCard/StatusCard.types.ts @@ -0,0 +1,5 @@ +export interface StatusCardProps { + icon: React.ReactNode; + label: string; + description: string; +} diff --git a/apps/member/src/components/common/StatusCard/index.ts b/apps/member/src/components/common/StatusCard/index.ts new file mode 100644 index 00000000..6e3a03be --- /dev/null +++ b/apps/member/src/components/common/StatusCard/index.ts @@ -0,0 +1,2 @@ +export { default as StatusCard } from './StatusCard.tsx'; +export type { StatusCardProps } from './StatusCard.types.ts'; diff --git a/apps/member/src/components/support/SupportProcedureSection/SupportProcedureSection.tsx b/apps/member/src/components/support/SupportProcedureSection/SupportProcedureSection.tsx index 20a57d73..32cb4ce6 100644 --- a/apps/member/src/components/support/SupportProcedureSection/SupportProcedureSection.tsx +++ b/apps/member/src/components/support/SupportProcedureSection/SupportProcedureSection.tsx @@ -1,4 +1,9 @@ import Section from '@components/common/Section/Section'; +import { + StatusCard, + type StatusCardProps, +} from '@components/common/StatusCard'; + import { FcSurvey, FcReading, @@ -6,28 +11,28 @@ import { FcFilingCabinet, } from 'react-icons/fc'; -const stepContents = [ +const stepContents: StatusCardProps[] = [ { - image: , - title: '신청서 작성', + icon: , + label: '신청서 작성', description: '회비 사용과 관련된 정보를 입력하여 제출해 주세요. 누락된 정보가 있을 경우 승인이 반려될 수 있어요.', }, { - image: , - title: '운영진 검토', + icon: , + label: '운영진 검토', description: '운영진이 신청서를 면밀히 검토하여 승인 여부를 결정해요. 24시간 이내에 처리가 되지 않는다면 별도로 문의해 주세요.', }, { - image: , - title: '직접 결제', + icon: , + label: '직접 결제', description: '승인이 되면 결제 대금을 이체 받아요. 이체 받은 결제 대금을 사용하여 직접 결제를 진행해 주세요.', }, { - image: , - title: '사용 후 반납', + icon: , + label: '사용 후 반납', description: '대여기간이 지나면 운영진이 사용 내역을 확인하고 반납 여부를 확인해요.', }, @@ -38,14 +43,13 @@ const SupportProcedureSection = () => {
- {stepContents.map((stepContent, index) => ( -
-
- {stepContent.image} -
-

{stepContent.title}

-

{stepContent.description}

-
+ {stepContents.map(({ icon, label, description }) => ( + ))}
From b8aca54e381ab7361f1ce6e957355ded3d5356ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?= <39869096+gwansikk@users.noreply.github.com> Date: Tue, 9 Apr 2024 23:34:06 +0900 Subject: [PATCH 3/8] =?UTF-8?q?refactor(member):=20=EC=BA=98=EB=A6=B0?= =?UTF-8?q?=EB=8D=94=20UI=20=EA=B0=9C=EC=84=A0=20(#91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/calendar/Calendar/Calendar.tsx | 77 ------------- .../CalendarSchedule/CalendarSchedule.tsx | 38 +++--- .../CalendarSection/CalendarSection.tsx | 99 ++++++++++++++++ apps/member/src/utils/date.ts | 108 ++++++++++++------ 4 files changed, 195 insertions(+), 127 deletions(-) delete mode 100644 apps/member/src/components/calendar/Calendar/Calendar.tsx create mode 100644 apps/member/src/components/calendar/CalendarSection/CalendarSection.tsx diff --git a/apps/member/src/components/calendar/Calendar/Calendar.tsx b/apps/member/src/components/calendar/Calendar/Calendar.tsx deleted file mode 100644 index c463e3a5..00000000 --- a/apps/member/src/components/calendar/Calendar/Calendar.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import dayjs from 'dayjs'; -import classNames from 'classnames'; -import CalendarSchedule from '../CalendarSchedule/CalendarSchedule'; -import { now, transformEvents } from '@utils/date'; -import { useSchedule } from '@hooks/queries/useSchedule'; -import { DATE_FORMAT } from '@constants/state'; - -interface CalendarProps { - date: dayjs.Dayjs; -} - -const Calendar = ({ date }: CalendarProps) => { - const dateElements = []; - const year = date.year(); - const month = date.month() + 1; - const prevDaysInMonth = date.subtract(1, 'month').daysInMonth(); - const toDaysInMonth = date.daysInMonth(); - - const { data } = useSchedule({ - startDate: date.startOf('month').format(DATE_FORMAT.WITH_TIME), - endDate: date.endOf('month').format(DATE_FORMAT.WITH_TIME), - }); - - const events = transformEvents(data.items); - - //전 달 날짜 - for (let i = date.day(); i >= 0; i--) { - const day = date.subtract(1, 'month'); - dateElements.push( -
-

{prevDaysInMonth - i}

-
, - ); - } - - //이번 달 날짜 - for (let i = 1; i <= toDaysInMonth; i++) { - const day = dayjs(`${year}-${month}-${i}`); - const element = day.format('YYYY-MM-DD'); - const event = events[element]; - dateElements.push( -
-

- {i} -

- -
, - ); - } - - const nextDaysInMonth = 7 - (dateElements.length % 7); - - //다음 달 날짜 - for (let i = 1; i <= nextDaysInMonth; i++) { - const day = date.add(1, 'month'); - dateElements.push( -
-

{i}

-
, - ); - } - - return dateElements; -}; - -export default Calendar; diff --git a/apps/member/src/components/calendar/CalendarSchedule/CalendarSchedule.tsx b/apps/member/src/components/calendar/CalendarSchedule/CalendarSchedule.tsx index 8eab441a..486f1227 100644 --- a/apps/member/src/components/calendar/CalendarSchedule/CalendarSchedule.tsx +++ b/apps/member/src/components/calendar/CalendarSchedule/CalendarSchedule.tsx @@ -1,6 +1,9 @@ import useModal from '@hooks/common/useModal'; import { formattedDate } from '@utils/date'; import type { ScheduleItem } from '@type/schedule'; +import { useCallback } from 'react'; +import { cn } from '@utils/string'; +import dayjs from 'dayjs'; const CalendarSchedule = ({ title, @@ -9,28 +12,33 @@ const CalendarSchedule = ({ endDate, }: ScheduleItem) => { const { openModal } = useModal(); + const isSameDate = dayjs(startDate).isSame(endDate, 'date'); - const onClickSchedule = (detail: string, start: string, end: string) => { - let date = `${formattedDate(start)} ~ ${formattedDate(end)}`; - - if (start === end) { + const handleScheduleClick = useCallback( + (detail: string, start: string, end: string) => { // 시작일과 종료일이 같은 경우, 종료일은 표시하지 않는다. - date = `${formattedDate(start)}`; - } + const date = + start === end + ? `${formattedDate(start)}` + : `${formattedDate(start)} ~ ${formattedDate(end)}`; - openModal({ - title: '📆 일정', - content: `내용: ${detail}\n일시: ${date}`, - }); - }; + openModal({ + title: '📆 일정', + content: `일시: ${date}\n내용: ${detail}`, + }); + }, + [openModal], + ); return ( -

onClickSchedule(detail, startDate, endDate)} + ); }; diff --git a/apps/member/src/components/calendar/CalendarSection/CalendarSection.tsx b/apps/member/src/components/calendar/CalendarSection/CalendarSection.tsx new file mode 100644 index 00000000..1f47b18b --- /dev/null +++ b/apps/member/src/components/calendar/CalendarSection/CalendarSection.tsx @@ -0,0 +1,99 @@ +import { startTransition, useCallback, useState } from 'react'; +import ArrowButton from '@components/common/ArrowButton/ArrowButton'; +import Section from '@components/common/Section/Section'; +import { useSchedule } from '@hooks/queries'; +import { now, transformEvents } from '@utils/date'; +import { cn } from '@utils/string'; +import CalendarSchedule from '../CalendarSchedule/CalendarSchedule'; + +const today = now(); + +const CalendarSection = () => { + const [date, setDate] = useState(today); + const { data } = useSchedule({ + startDate: date.startOf('month').format('YYYY-MM-DD'), + endDate: date.endOf('month').format('YYYY-MM-DD'), + }); + + const handleDateClick = useCallback((action: 'prev' | 'next' | 'today') => { + startTransition(() => { + setDate((current) => { + switch (action) { + case 'prev': + return current.subtract(1, 'month'); + case 'next': + return current.add(1, 'month'); + case 'today': + return today; + } + }); + }); + }, []); + + const events = transformEvents(data.items); + const startDay = date.startOf('month').startOf('week'); // 현재 월의 첫 날짜의 주의 시작일 + const endDay = date.endOf('month').endOf('week'); // 현재 월의 마지막 날짜의 주의 마지막일 + + const days = []; + let day = startDay; + + while (day.isBefore(endDay)) { + const isToday = day.isSame(today, 'day'); + + days.push( + +

+

+ {day.format('D')} +

+ {events[day.format('YYYY-MM-DD')]?.map((event) => ( + + ))} +
+ , + ); + day = day.add(1, 'day'); + } + + const weeks = []; + for (let i = 0; i < days.length; i += 7) { + weeks.push({days.slice(i, i + 7)}); + } + + return ( +
+ + handleDateClick('prev')} /> + + handleDateClick('next')} /> + + + + + + + + + + + + + + + {weeks} +
+
+
+ ); +}; + +export default CalendarSection; diff --git a/apps/member/src/utils/date.ts b/apps/member/src/utils/date.ts index 62b11933..34db7d6e 100644 --- a/apps/member/src/utils/date.ts +++ b/apps/member/src/utils/date.ts @@ -1,16 +1,15 @@ import type { ScheduleItem } from '@type/schedule'; import dayjs from 'dayjs'; import 'dayjs/locale/ko'; - dayjs.locale('ko'); - /** * 오늘 날짜를 dayjs 객체로 반환합니다. * * @returns {dayjs.Dayjs} dayjs 객체로 반환합니다. */ -export const now = (): dayjs.Dayjs => dayjs(); - +export function now(): dayjs.Dayjs { + return dayjs(); +} /** * 주어진 날짜 문자열을 'YY.MM.DD' 형식으로 변환합니다. * `dayjs` 라이브러리의 `format` 메서드를 사용하여 날짜 형식을 지정합니다. @@ -19,70 +18,109 @@ export const now = (): dayjs.Dayjs => dayjs(); * @param date 날짜를 나타내는 문자열입니다. 'YYYY-MM-DD', 'YYYY/MM/DD' 등의 형식이 가능합니다. * @returns 변환된 날짜 문자열을 'YY.MM.DD' 형식으로 반환합니다. */ -export const toYYMMDD = (date: string) => dayjs(date).format('YY.MM.DD'); - +export function toYYMMDD(date: string) { + return dayjs(date).format('YY.MM.DD'); +} /** * 주어진 날짜와 오늘 날짜의 차이를 일(day) 단위로 계산하여 반환합니다. * * @param {string} date - 비교할 날짜 (YYYY-MM-DD 형식) * @return {number} 오늘부터 주어진 날짜까지의 일수 차이, 절대값으로 반환됩니다. */ -export const calculateDDay = (date: string): number => - Math.abs(dayjs(date).diff(dayjs(), 'day')); - +export function calculateDDay(date: string): number { + return Math.abs(dayjs(date).diff(dayjs(), 'day')); +} /** * 주어진 날짜를 'YY.MM.DD(dd) HH:mm' 형식으로 포맷합니다. * * @param {Date|string|number} date - 포맷할 날짜. Date 객체, 문자열 또는 타임스탬프일 수 있습니다. * @returns {string} 포맷된 날짜 문자열. */ -export const formattedDate = (date: string | undefined): string => - dayjs(date).format('YY.MM.DD(dd) HH:mm'); - +export function formattedDate(date: string | undefined): string { + return dayjs(date).format('YY.MM.DD(dd) HH:mm'); +} /** * 주어진 초를 'mm:ss' 형식으로 포맷합니다. * * @param {number} seconds - 초 단위의 시간. * @returns {string} 포맷된 시간 문자열. */ -export const formattedTime = (seconds: number): string => - dayjs() +export function formattedTime(seconds: number): string { + return dayjs() .startOf('day') .add(seconds * 1000) .format('mm:ss'); - +} /** * 주어진 이벤트 배열을 받아서, 각 이벤트의 시작 날짜를 기준으로 객체로 변환합니다. * 변환된 객체의 키는 이벤트의 `startDate`에서 추출한 날짜이며, 값은 해당 이벤트 객체입니다. * * @param {ScheduleItem[]} events - 변환할 이벤트 객체 배열. 각 이벤트는 `ScheduleItem` 인터페이스를 따릅니다. - * @returns {Record} - 키가 이벤트의 시작 날짜이고 값이 이벤트 객체인 객체. + * @returns {Record} - 키가 이벤트의 시작 날짜이고 값이 이벤트 객체인 객체. */ export const transformEvents = ( events: ScheduleItem[], -): Record => { +): Record => { return events.reduce( (acc, current) => { - const dateKey = current.startDate.split('T')[0]; - acc[dateKey] = current; + const startDate = new Date(current.startDate.split('T')[0]); // 시작 날짜 객체 생성 + const endDate = new Date(current.endDate.split('T')[0]); // 종료 날짜 객체 생성 + + for ( + let date = new Date(startDate); + date <= endDate; + date.setDate(date.getDate() + 1) + ) { + const dateKey = date.toISOString().split('T')[0]; + + if (!acc[dateKey]) { + acc[dateKey] = []; + } + + acc[dateKey].push(current); + } + return acc; }, - {} as Record, + {} as Record, ); }; +/** + * 가장 가까운 이벤트를 찾습니다. + * + * @param events - 일정 항목 배열 (transformEvents 함수로 변환된 객체) + * @returns 가장 가까운 이벤트 항목 + */ +export function findClosestEvent( + events: Record, +): ScheduleItem | null { + const today = dayjs(); + let closestEvent: ScheduleItem | null = null; + let smallestDiff = Number.MAX_SAFE_INTEGER; + + Object.entries(events).forEach(([date, eventArray]) => { + const eventDate = dayjs(date); + const diff = eventDate.diff(today, 'day'); + + if (diff >= 0 && diff < smallestDiff) { + smallestDiff = diff; + closestEvent = eventArray[0]; + } + }); + return closestEvent; +} /** * 주어진 날짜의 년도와 학기를 반환합니다. * * @param {string} createdAt - 주어진 날짜. * @return {string} 주어진 날짜를 YY년도 1/2학기로 반환. */ -export const getDateSemester = (createdAt: string): string => { +export function getDateSemester(createdAt: string): string { const year = dayjs(createdAt).format('YY'); const semester = dayjs(createdAt).get('month') <= 5 ? 1 : 2; return `${year}년도 ${semester}학기`; -}; - +} /** * 주어진 참조 날짜와 확인하고자 하는 날짜를 비교하여 유효성을 평가합니다. * @@ -90,26 +128,24 @@ export const getDateSemester = (createdAt: string): string => { * @param {string | undefined} referenceDateStr - 유효성 판단의 기준이 되는 날짜를 나타내는 문자열입니다. 'YYYY-MM-DD' 형식이어야 합니다. * @returns {boolean} 확인하고자 하는 날짜가 참조 날짜 이전이거나 같으면 true, 그렇지 않으면 false를 반환합니다. */ -export const isDateValid = ( +export function isDateValid( checkDateStr: string | undefined, referenceDateStr: string | undefined, -): boolean => { +): boolean { const checkDate = dayjs(checkDateStr); const referenceDate = dayjs(referenceDateStr); return checkDate.isBefore(referenceDate) || checkDate.isSame(referenceDate); -}; - +} /** * 14일 기간 기반으로 작업 또는 이벤트의 진행 상황을 백분율로 계산합니다. * * @param {string} date - 작업 또는 이벤트의 시작 날짜 (Day.js와 호환 가능한 형식). * @returns {number} 14일 기간 내 진행 상황을 나타내는 백분율 (0-100). */ -export const checkProgress = (date: string) => { +export function checkProgress(date: string): number { const end = dayjs(date).add(14, 'd'); return (end.diff(now(), 'd') * 100) % 14; -}; - +} /** * 시작 날짜와 종료 날짜 사이의 맞춤 시간 기간 내 진행 상황을 백분율로 계산합니다. * 14일 기간을 넘어서는 작업이나 기간 연장에 유용합니다. @@ -118,20 +154,22 @@ export const checkProgress = (date: string) => { * @param {string} endDate - 작업 또는 이벤트의 종료 날짜. * @returns {number} 지정된 기간 내 진행 상황을 나타내는 백분율 (0-100). */ -export const checkExtendProgress = (startDate: string, endDate: string) => { +export function checkExtendProgress( + startDate: string, + endDate: string, +): number { const end = dayjs(endDate); const start = dayjs(startDate); const gap = end.diff(start, 'd'); // 총 기간 (일 단위) return (end.diff(now(), 'd') * 100) % gap; -}; - +} /** * 기본 14일 유예 기간을 포함한 지정된 마감 날짜까지 남은 일 수를 계산합니다. * * @param {string} date - 작업 또는 이벤트의 마감 날짜. * @returns {number} 남은 일 수. 마감 날짜가 지났으면 음수 값이 반환됩니다. */ -export const checkDueDate = (date: string) => { +export function checkDueDate(date: string): number { const end = dayjs(date).add(14, 'd'); return end.diff(now(), 'd'); -}; +} From 5da0b44d167347b2fae1ba155d798b664de1428c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?= <39869096+gwansikk@users.noreply.github.com> Date: Tue, 9 Apr 2024 23:34:53 +0900 Subject: [PATCH 4/8] =?UTF-8?q?refactor(member):=20useSchedule=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=EA=B0=92=20=EB=B3=80=EA=B2=BD=20(#91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/member/src/hooks/queries/useSchedule.ts | 16 ++++++++-------- apps/member/src/types/api.ts | 7 +++++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/apps/member/src/hooks/queries/useSchedule.ts b/apps/member/src/hooks/queries/useSchedule.ts index 0a8d2680..f6c3303f 100644 --- a/apps/member/src/hooks/queries/useSchedule.ts +++ b/apps/member/src/hooks/queries/useSchedule.ts @@ -2,17 +2,17 @@ import { getSchedule } from '@api/schedule'; import { QUERY_KEY } from '@constants/key'; import { DATE_FORMAT } from '@constants/state'; import { useSuspenseQuery } from '@tanstack/react-query'; -import type { PaginationPramsType } from '@type/api'; +import type { WithPaginationPrams } from '@type/api'; import dayjs from 'dayjs'; -interface UseMainScheduleArgs extends PaginationPramsType { +interface UseMainSchedulePrams extends WithPaginationPrams { startDate?: string; endDate?: string; } -// 오늘 날짜와 3개월 후 날짜를 기본값으로 설정 -const defaultStartDate = dayjs().format(DATE_FORMAT.WITH_TIME); -const defaultEndDate = dayjs().add(3, 'month').format(DATE_FORMAT.WITH_TIME); +// 이번달을 기본값으로 설정 +const defaultStartDate = dayjs().startOf('month').format(DATE_FORMAT.WITH_TIME); +const defaultEndDate = dayjs().endOf('month').format(DATE_FORMAT.WITH_TIME); /** * 동아리 일정을 조회합니다. @@ -21,10 +21,10 @@ export const useSchedule = ({ startDate = defaultStartDate, endDate = defaultEndDate, page = 0, - size = 62, -}: UseMainScheduleArgs) => { + size = 100, +}: UseMainSchedulePrams = {}) => { return useSuspenseQuery({ - queryKey: [QUERY_KEY.SCHEDULE, startDate, endDate, page, size], + queryKey: [QUERY_KEY.SCHEDULE, startDate, endDate], queryFn: () => getSchedule({ startDate, endDate, page, size }), }); }; diff --git a/apps/member/src/types/api.ts b/apps/member/src/types/api.ts index 38eaa20d..a21dcbdd 100644 --- a/apps/member/src/types/api.ts +++ b/apps/member/src/types/api.ts @@ -20,6 +20,13 @@ export interface PaginationPramsType { page?: number; size?: number; } +/** + * `PaginationPramsType`를 대체하기 위한 페이지네이션 파라미터 타입입니다. + */ +export interface WithPaginationPrams { + page?: number; + size?: number; +} export type IDType = string | number; From 63b98d4b8db875550ed865f95cc2e39cc4c460ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?= <39869096+gwansikk@users.noreply.github.com> Date: Wed, 10 Apr 2024 00:44:34 +0900 Subject: [PATCH 5/8] =?UTF-8?q?refactor(member):=20=EC=BA=98=EB=A6=B0?= =?UTF-8?q?=EB=8D=94=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20UI=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0=20(#91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CalendarSchedule/CalendarSchedule.tsx | 30 +++++++++++++++---- .../CalendarSection/CalendarSection.tsx | 2 +- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/apps/member/src/components/calendar/CalendarSchedule/CalendarSchedule.tsx b/apps/member/src/components/calendar/CalendarSchedule/CalendarSchedule.tsx index 486f1227..50ea169a 100644 --- a/apps/member/src/components/calendar/CalendarSchedule/CalendarSchedule.tsx +++ b/apps/member/src/components/calendar/CalendarSchedule/CalendarSchedule.tsx @@ -5,14 +5,19 @@ import { useCallback } from 'react'; import { cn } from '@utils/string'; import dayjs from 'dayjs'; +interface CalendarScheduleProps extends ScheduleItem { + day: dayjs.Dayjs; +} + const CalendarSchedule = ({ + day, title, detail, startDate, endDate, -}: ScheduleItem) => { +}: CalendarScheduleProps) => { const { openModal } = useModal(); - const isSameDate = dayjs(startDate).isSame(endDate, 'date'); + const isDateDiff = dayjs(startDate).diff(endDate, 'd'); const handleScheduleClick = useCallback( (detail: string, start: string, end: string) => { @@ -32,9 +37,24 @@ const CalendarSchedule = ({ return ( - - - - - - - + + + + + + ); }; diff --git a/apps/member/src/types/schedule.ts b/apps/member/src/types/schedule.ts index fefb463b..ca3b039b 100644 --- a/apps/member/src/types/schedule.ts +++ b/apps/member/src/types/schedule.ts @@ -1,3 +1,5 @@ +type SchedulePriority = 'HIGH' | 'MIDDLE' | 'LOW'; + export interface ScheduleItem { id: number; title: string; @@ -5,6 +7,7 @@ export interface ScheduleItem { activityName: string | null; startDate: string; endDate: string; + priority: SchedulePriority; } export interface ScheduleRegisterItem { @@ -15,3 +18,8 @@ export interface ScheduleRegisterItem { endDateTime: string; activityGroupId?: number; } + +export interface ScheduleCollect { + totalScheduleCount: number; + totalEventCount: number; +} From f74f638265f7f37428d79eed73d9a639a7750e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?= <39869096+gwansikk@users.noreply.github.com> Date: Wed, 10 Apr 2024 01:18:21 +0900 Subject: [PATCH 7/8] refactor(member): linker component to make target prop optional (#91) --- apps/member/src/components/common/Linker/Linker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/member/src/components/common/Linker/Linker.tsx b/apps/member/src/components/common/Linker/Linker.tsx index b87625b4..14ce4933 100644 --- a/apps/member/src/components/common/Linker/Linker.tsx +++ b/apps/member/src/components/common/Linker/Linker.tsx @@ -5,7 +5,7 @@ import { Link } from 'react-router-dom'; interface LinkerProps extends PropsWithChildren { to: string | Partial; className?: string; - target: React.HTMLAttributeAnchorTarget; + target?: React.HTMLAttributeAnchorTarget; } const Linker = ({ to, target, className, children }: LinkerProps) => { From dd31e47b19f5be4d7ef716037397eb4d8e245fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B4=80=EC=8B=9D?= <39869096+gwansikk@users.noreply.github.com> Date: Wed, 10 Apr 2024 01:46:26 +0900 Subject: [PATCH 8/8] =?UTF-8?q?fix(member):=20useBoardList=20queryOptions?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EC=B6=94=EB=A1=A0=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=20(#91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/member/src/hooks/queries/useBoardsList.ts | 12 ++++++++++-- apps/member/src/types/api.ts | 2 +- apps/member/src/types/hire.ts | 3 +-- apps/member/src/types/news.ts | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/member/src/hooks/queries/useBoardsList.ts b/apps/member/src/hooks/queries/useBoardsList.ts index 1e9c12e1..615474da 100644 --- a/apps/member/src/hooks/queries/useBoardsList.ts +++ b/apps/member/src/hooks/queries/useBoardsList.ts @@ -3,8 +3,16 @@ import { getNews } from '@api/news'; import { QUERY_KEY } from '@constants/key'; import { useSuspenseQuery } from '@tanstack/react-query'; import { getBoardsList } from '@api/board'; -import { PaginationPramsType } from '@type/api'; +import type { Pagination, PaginationPramsType } from '@type/api'; import type { CommunityCategoryType } from '@type/community'; +import type { PostItem } from '@type/post'; +import type { NewsItem } from '@type/news'; +import type { HireItem } from '@type/hire'; + +interface QueryOptions { + queryKey: string; + queryFn: () => Promise>; +} interface UseBoardsListParams extends PaginationPramsType { category: CommunityCategoryType; @@ -18,7 +26,7 @@ export const useBoardsList = ({ page = 0, size = 6, }: UseBoardsListParams) => { - const queryOptions = { + const queryOptions: QueryOptions = { notice: { queryKey: QUERY_KEY.BORDER_NOTICE, queryFn: () => getBoardsList('notice', page, size), diff --git a/apps/member/src/types/api.ts b/apps/member/src/types/api.ts index a21dcbdd..8fcc8c98 100644 --- a/apps/member/src/types/api.ts +++ b/apps/member/src/types/api.ts @@ -3,7 +3,7 @@ export interface BaseResponse { data: T; } -interface Pagination { +export interface Pagination { currentPage: number; hasPrevious: boolean; hasNext: boolean; diff --git a/apps/member/src/types/hire.ts b/apps/member/src/types/hire.ts index c385206e..f705c0d0 100644 --- a/apps/member/src/types/hire.ts +++ b/apps/member/src/types/hire.ts @@ -16,8 +16,7 @@ export type EmploymentType = | 'ASSISTANT' | 'PART_TIME'; -export interface HireItem - extends Omit { +export interface HireItem extends Omit { careerLevel: CareerLevel; recruitmentPeriod: string; jobPostingUrl: string; diff --git a/apps/member/src/types/news.ts b/apps/member/src/types/news.ts index 511c51d9..2956317f 100644 --- a/apps/member/src/types/news.ts +++ b/apps/member/src/types/news.ts @@ -1,6 +1,6 @@ import { PostItem } from './post'; -export interface NewsItem extends Omit { +export interface NewsItem extends PostItem { articleUrl: string; date: string; source: string;