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: 나눔 상세내역 조회, 나눔 신청자 정보 조회 API 연동 #32

Merged
merged 3 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 27 additions & 0 deletions src/components/organisms/ShareApplicantListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Image from 'next/image';
import React from 'react';
import type { ShareApplicantData } from '@/types/share';
import { returnProfileImg } from '@/utils/returnProfileImg';

const ShareApplicantListItem: React.FC<{
idx: number;
data: ShareApplicantData;
}> = ({ idx, data }) => {
return (
<div className="flex items-center mb-[20px]">
<p className="flex justify-center items-center w-[20px] h-[20px] rounded-full bg-gray0 body2-semibold text-gray5">
{idx}
</p>
<Image
src={returnProfileImg(data.profileImage)}
width={40}
height={40}
className="w-[40px] h-[40px] aspect-square mx-[8px]"
alt="신청자 프로필"
/>
<p className="text-gray7 heading4-semibold">{data.nickname}</p>
</div>
);
};

export default ShareApplicantListItem;
35 changes: 13 additions & 22 deletions src/components/organisms/ShareDetailAuthorBottomWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,20 @@ import {
import { Button, RadioButtonField } from '@/components/atoms';
import React from 'react';
import { type SortLabel } from '@/types/common';
import { useGetShareApplicants } from '@/hooks/queries/share';
import ShareApplicantListItem from './ShareApplicantListItem';

const SHARE_STATUSES = [
{ label: '나눔 신청', value: 'enroll' },
{ label: '나눔 중', value: 'proceeding' },
{ label: '나눔 완료', value: 'complete' },
];

const MOCK_DATA_PARTICIPANTS = [
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
'김지수',
];

const ShareDetailAuthorBottomWrapper: React.FC<{
id: string | string[] | undefined;
curStatus: SortLabel;
onChangeStatus: React.Dispatch<React.SetStateAction<SortLabel>>;
}> = ({ curStatus, onChangeStatus }) => {
}> = ({ id, curStatus, onChangeStatus }) => {
const {
isOpen: isStatusModalOpen,
onOpen: onStatusModalOpen,
Expand All @@ -49,6 +34,8 @@ const ShareDetailAuthorBottomWrapper: React.FC<{
onClose: onParticipantsModalClose,
} = useDisclosure();

const applicants = useGetShareApplicants({ id });

return (
<>
<div className="fixed flex gap-[11px] w-full max-w-[480px] bottom-0 p-[20px] pb-[32px] bg-gray1">
Expand Down Expand Up @@ -117,9 +104,13 @@ const ShareDetailAuthorBottomWrapper: React.FC<{
maxW="lg"
>
<ModalBody>
<div className="max-h-[300px] overflow-scroll px-[20px] py-[40px]">
{MOCK_DATA_PARTICIPANTS.map((ele, idx) => (
<div key={idx}>{ele}</div>
<div className="max-h-[300px] overflow-scroll px-[20px] pt-[40px] py-[20px]">
{applicants?.map((ele, idx) => (
<ShareApplicantListItem
key={ele.nickname}
idx={idx}
data={ele}
/>
))}
</div>
<div className="pt-[20px] pb-[32px]">
Expand Down
3 changes: 2 additions & 1 deletion src/components/organisms/ShareListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DotIcon, LocationIcon } from '@/assets/icons';
import Image from 'next/image';
import Link from 'next/link';
import React from 'react';
import type { ShareData } from '@/types/share';
import dayjs from 'dayjs';

const ShareListItem: React.FC<{
Expand Down Expand Up @@ -43,7 +44,7 @@ const ShareListItem: React.FC<{
className="mx-[4px] mb-1"
/>
</span>
{`${dayjs(data.shareDate).format('MM월 DD일')} ${data.shareTime.hour} : ${data.shareTime.minute}`}
{`${dayjs(data.shareDate).format('MM월 DD일')} ${data.shareTime}`}
</p>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/hooks/queries/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const queryKeys = {
DELETE_FRIENDSHIP: () => ['deleteFriendship'],
MY_INVITE_CODE: () => ['myInviteCode'],
ADD_FRIENDSHIP: () => ['addFriendship'],
SHARE_DETAIL: () => ['shareDetail'],
SHARE_APPLICANTS: () => ['shareApplicants'],
} as const;

export type QueryKeys = (typeof queryKeys)[keyof typeof queryKeys];
2 changes: 2 additions & 0 deletions src/hooks/queries/share/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { default as useGetShares } from './useGetShares';
export { default as useGetShareDetail } from './useGetShareDetail';
export { default as useGetShareApplicants } from './useGetShareApplicants';
21 changes: 21 additions & 0 deletions src/hooks/queries/share/useGetShareApplicants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { ShareApplicantData } from '@/types/share';
import { queryKeys } from '../queryKeys';
import { useBaseQuery } from '../useBaseQuery';

const useGetShareApplicants = ({
id,
}: {
id: string | string[] | undefined;
}) => {
if (typeof id !== 'string') {
return null;
}
const { data } = useBaseQuery<ShareApplicantData[]>(
queryKeys.SHARE_APPLICANTS(),
`/shares/${id}/applies`,
);

return data?.data;
};

export default useGetShareApplicants;
17 changes: 17 additions & 0 deletions src/hooks/queries/share/useGetShareDetail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { ShareDetailData } from '@/types/share';
import { queryKeys } from '../queryKeys';
import { useBaseQuery } from '../useBaseQuery';

const useGetShareDetail = ({ id }: { id: string | string[] | undefined }) => {
if (typeof id !== 'string') {
return null;
}
const { data } = useBaseQuery<ShareDetailData>(
queryKeys.SHARE_DETAIL(),
`/shares/${id}`,
);

return data?.data;
};

export default useGetShareDetail;
4 changes: 3 additions & 1 deletion src/hooks/queries/share/useGetShares.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { type ShareStatusType, type ShareSortType } from '@/types/friendship';
import type { ShareSortType, ShareStatusType } from '@/types/friendship';

import type { ShareData } from '@/types/share';
import { queryKeys } from '../queryKeys';
import { useBaseInfiniteQuery } from '../useBaseInfiniteQuery';

Expand Down
56 changes: 30 additions & 26 deletions src/pages/share/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
import { ClockIcon, DateIcon, LocationIcon } from '@/assets/icons';
import { ShareInfoRowItem, VerticalLabelValue } from '@/components/molecules';
import { Header, ShareDetailAuthorBottomWrapper } from '@/components/organisms';
import { useGetShareDetail } from '@/hooks/queries/share';
import { type SortLabel } from '@/types/common';
import dayjs from 'dayjs';
import { type NextPage } from 'next';
import Image from 'next/image';
import { useRouter } from 'next/router';
import React, { useEffect, useState } from 'react';

const MOCK_DATA = {
shareerName: '김지수',
image: '',
title: '사과받아갈사람선착순12345명',
ingredient: '사과',
fixedNum: 15,
useByDate: dayjs('2024-02-30'),
meetingDate: dayjs('2024-02-20'),
meetingTime: '14:00',
meetingLocation: '디지털시티역 8번출구 뜌레주르앞',
desc: '사과는역시청송사과맛있음은당연보장선착순1명사과는역시청송사과맛있음은당연보장선착순1명사과는역체시청송사과맛있음은당연보장선착순1명사과는역시청송사과맛있음은당연보장선착순1명은당연보장선착순1명사당연',
};
// const MOCK_DATA = {
// shareerName: '김지수',
// image: '',
// title: '사과받아갈사람선착순12345명',
// ingredient: '사과',
// fixedNum: 15,
// useByDate: dayjs('2024-02-30'),
// meetingDate: dayjs('2024-02-20'),
// meetingTime: '14:00',
// meetingLocation: '디지털시티역 8번출구 뜌레주르앞',
// desc: '사과는역시청송사과맛있음은당연보장선착순1명사과는역시청송사과맛있음은당연보장선착순1명사과는역체시청송사과맛있음은당연보장선착순1명사과는역시청송사과맛있음은당연보장선착순1명은당연보장선착순1명사당연',
// };

const MOCK_DATA_IS_AUTHOR: boolean = true;

const MOCK_DATA_SHARE_STATUS = { label: '나눔 신청', value: 'enroll' };

const ShareDetailPage: NextPage = () => {
const router = useRouter();
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
const { id } = router.query;
const [curStatus, setCurStatus] = useState<SortLabel>(MOCK_DATA_SHARE_STATUS);

const data = useGetShareDetail({ id });

useEffect(() => {
if (window) {
console.log(window.innerWidth);
Expand All @@ -41,10 +43,10 @@ const ShareDetailPage: NextPage = () => {
<>
<div className={'min-h-screen mb-[110px]'}>
<Header backgroundColor="transparent" />
{MOCK_DATA.image ? (
{data?.thumbNailImage ? (
<Image
alt="detailImage"
src={''}
src={data?.thumbNailImage}
sizes="100vw"
width={0}
height={0}
Expand All @@ -56,51 +58,53 @@ const ShareDetailPage: NextPage = () => {

<div className="relative mt-[-13px] mx-[20px] px-[16px] py-[24px] bg-white rounded-[12px]">
<p className="text-center body1-semibold text-gray7">
{MOCK_DATA_IS_AUTHOR ? '나의 나눔' : MOCK_DATA.shareerName}
{MOCK_DATA_IS_AUTHOR ? '나의 나눔' : data?.userName}
</p>
<p className="mt-[14px] mb-[20px] text-center heading2-semibold text-black">
{MOCK_DATA.title}
{data?.title}
</p>
<div className="flex p-[16px] mb-[6px] justify-between rounded-[12px] bg-gray1">
<VerticalLabelValue label="식자재" value={MOCK_DATA.ingredient} />
<VerticalLabelValue
label="식자재"
value={data?.itemName as string}
/>
<hr className="w-[1px] h-[36px] mx-[14px] bg-gray2" />
<VerticalLabelValue
label="모집인원"
value={`${MOCK_DATA.fixedNum} 명`}
value={`${data?.limitPerson} 명`}
/>
<hr className="w-[1px] h-[36px] bg-gray2" />
<VerticalLabelValue
label="소비기한"
value={`D-${MOCK_DATA.useByDate.diff(dayjs(), 'day')}`}
value={`D-${dayjs(data?.limitDate).diff(dayjs(), 'day') > 0 ? dayjs(data?.limitDate).diff(dayjs(), 'day') : 0}`}
/>
</div>
<ShareInfoRowItem
icon={DateIcon}
label="약속 날짜"
value={MOCK_DATA.meetingDate.format('YYYY.MM.DD')}
value={dayjs(data?.shareDate).format('YYYY.MM.DD')}
/>
<ShareInfoRowItem
icon={ClockIcon}
label="약속시간"
value={MOCK_DATA.meetingTime}
value={`${data?.shareTime}`}
/>
<ShareInfoRowItem
icon={LocationIcon}
label="약속 장소"
value={MOCK_DATA.meetingLocation}
value={data?.location as string}
/>
<hr className="h-0.5 my-[24px] bg-gray1" />

<div>
<p className="text-center body1-semibold text-primary2">상세설명</p>
<p className="mt-[12px] body1-medium text-gray6">
사과는역시청송사과맛있음은당연보장선착순1명사과는역시청송사과맛있음은당연보장선착순1명사과는역시청송사과맛있음은당연보장선착순1명사과는역시청송사과맛있음은당연보장선착순1명은당연보장선착순1명사당연
</p>
<p className="mt-[12px] body1-medium text-gray6">{data?.content}</p>
</div>
</div>
</div>
{MOCK_DATA_IS_AUTHOR ? (
<ShareDetailAuthorBottomWrapper
id={id}
curStatus={curStatus}
onChangeStatus={setCurStatus}
/>
Expand Down
1 change: 1 addition & 0 deletions src/pages/share/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Header from '@/components/organisms/Header';
import Link from 'next/link';
import type { NextPage } from 'next';
import { PlusIcon } from '@/assets/icons';
import { type ShareData } from '@/types/share';
import ShareListItem from '@/components/organisms/ShareListItem';
import { SuspenseFallback } from '@/components/templates';
import { useGetShares } from '@/hooks/queries/share';
Expand Down
19 changes: 13 additions & 6 deletions src/types/share/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import type { ProfileEnum } from '../common';

interface ShareData {
shareId: number;
title: string;
itemName: string;
content: string;
shareTime: {
hour: number;
minute: number;
second: number;
nano: number;
};
shareTime: string;
shareDate: string;
limitDate: string;
limitPerson: number;
location: string;
status: string;
thumbNailImage: string;
}

interface ShareDetailData extends ShareData {
userName: string;
profileImage: ProfileEnum;
}

interface ShareApplicantData {
nickname: string;
profileImage: ProfileEnum;
}
Loading