Skip to content

Commit

Permalink
Merge pull request #190 from FinalDoubleTen/dev
Browse files Browse the repository at this point in the history
Env: 여정 중간배포
  • Loading branch information
LeHiHo authored Jan 18, 2024
2 parents 1ab1146 + 810a1b2 commit 9a3a232
Show file tree
Hide file tree
Showing 25 changed files with 948 additions and 45 deletions.
18 changes: 17 additions & 1 deletion src/api/trips.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,13 @@ export const getTripsLike = async (

// 우리의 관심 목록 등록
export const postTripsLike = async (tripId: number, tourItemIds: number[]) => {
const res = await client.post(`trips/${tripId}/tripLikedTours`, tourItemIds);
const requestBody = {
tourItemIds: tourItemIds,
};
const res = await authClient.post(
`trips/${tripId}/tripLikedTours`,
requestBody,
);
return res;
};

Expand All @@ -68,3 +74,13 @@ export const getTripsSurvey = async (tripId: number) => {
const res = await client.get(`trips/${tripId}/survey`);
return res;
};
// 우리의 여행취향 참여/미참여 회원 조회
export const getTripsSurveyMembers = async (tripId: number) => {
const res = await client.get(`trips/${tripId}/survey/members`);
return res;
};
// 여정을 공유하고 있는 회원 조회
export const getTripsMembers = async (tripId: number) => {
const res = await client.get(`trips/${tripId}/members`);
return res;
};
16 changes: 11 additions & 5 deletions src/components/Trip/PlanTripButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ import { PlanIcon, RightIcon } from '@components/common/icons/Icons';

const PlanTripButton = () => {
return (
<button className="body3 my-6 flex w-full items-center justify-between rounded-[8px] bg-[#F3F4F5] px-[15px] py-[15px] text-gray7 text-main1">
<div className="flex items-center justify-start">
<PlanIcon />
<span className="ml-[3px]">여행 계획하기</span>

<button className="body3 mb-10 mt-6 flex w-full items-center justify-between rounded-[8px] bg-[#F3F4F5] px-[15px] py-[15px] text-gray7 text-main1">
<div className="flex items-center justify-start ">
<div>
<PlanIcon />
</div>
<p className="ml-1.5 text-gray5">여행 계획하기</p>
</div>
<div>
<RightIcon fill="#888888" />

</div>
<RightIcon />
</button>
);
};
Expand Down
134 changes: 117 additions & 17 deletions src/components/Trip/TripInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,128 @@
import { UserIcon } from '@components/common/icons/Icons';
import { socketContext } from '@hooks/useSocket';
import { useContext } from 'react';
import { useRecoilValue, useRecoilState } from 'recoil';
import { isModalOpenState, modalChildrenState } from '@recoil/modal';
import TripSurveyMember from '@components/common/modal/children/TripSurveyMember';
import { Modal } from '@components/common/modal';
import { useQuery } from '@tanstack/react-query';
import { getTripsMembers } from '@api/trips';
import { tripIdState } from '@recoil/socket';
import { ReactComponent as NullUser } from '@assets/images/NullUser.svg';
import { DownIcon } from '@components/common/icons/Icons';
import { useState } from 'react';

const ShareList = () => {
const tripId = Number(useRecoilValue(tripIdState));
const { data: tripsMembers } = useQuery({
queryKey: ['tripsMembers', tripId],
queryFn: () => getTripsMembers(tripId),
});
const members = tripsMembers?.data?.data?.tripMemberSimpleInfos;

return (
<>
<hr className="my-3 border-solid border-gray2" />
<div>
{members.map((member: any, index: number) => {
return (
<div
className={`mb-2 flex cursor-pointer items-center text-gray5`}
key={index}>
{member.profileImageUrl &&
member.profileImageUrl !== 'http://asiduheimage.jpg' ? (
<img
src={member.profileImageUrl}
alt="유저 프로필"
className="h-[32px] w-[32px] rounded-full"
/>
) : (
<NullUser className="h-[32px] w-[32px]" />
)}
<div className="ml-3">{member.nickname}</div>
</div>
);
})}
</div>
</>
);
};

const TripInfo = () => {
const { tripInfo } = useContext(socketContext);
const trip = tripInfo?.data;
const modalChildren = useRecoilValue(modalChildrenState);
const [isModalOpen, setIsModalOpen] = useRecoilState(isModalOpenState);
const tripId = Number(useRecoilValue(tripIdState));
const [isAccordion, setIsAccordion] = useState(false);

const { data: tripsMembers } = useQuery({
queryKey: ['tripsMembers', tripId],
queryFn: () => getTripsMembers(tripId),
});
const members = tripsMembers?.data?.data?.tripMemberSimpleInfos;

const closeModal = () => {
setIsModalOpen(false);
};

const handleClickButton = () => {
setIsAccordion((prev) => !prev);
};

return (
<div className="my-5">
<div className="flex items-center justify-between">
<div className="flex items-center">
<div className="title1 mb-[10px] mr-1">{trip?.tripName}</div>
<div className="flex items-center pb-[10px]">
<UserIcon size={20} fill="#888" color="#888" />
<span className="body4 pt-[1px] text-gray4">
{trip?.numberOfPeople}
</span>
<>
<div className="my-5">
<div className="flex items-center justify-between">
<div className="flex space-x-[-17.5px]">
{members?.map((member: any, index: number) => (
<div key={index}>
{member.profileImageUrl &&
member.profileImageUrl !== 'http://asiduheimage.jpg' ? (
<img
src={member.profileImageUrl}
alt="유저 프로필"
className="h-[32px] w-[32px] rounded-full border-2 border-solid border-white"
/>
) : (
<NullUser className="h-[32px] w-[32px] border-2 border-solid border-white" />
)}
</div>
))}
</div>

<div className="flex items-center gap-1">
<p className="body1 text-[13px] text-gray7">
{members?.length}명과 공유중
</p>
<div
style={{
transform: isAccordion ? 'rotate(180deg)' : 'rotate(0deg)',
transition: 'transform 0.3s ease',
}}
onClick={handleClickButton}
className="pt-0.5">
<DownIcon color="#888888" size={20} />
</div>
</div>
</div>

{isAccordion && <ShareList />}
<hr className="mb-6 mt-3 border-solid border-gray2" />
<div className="flex items-center justify-between">
<div className="flex items-center">
<div className="title1 mb-[10px] mr-1">강릉 여행 일정</div>
<div className="flex items-center pb-[10px]">
<UserIcon size={20} fill="#888" color="#888" />
<span className="body4 pt-[1px] text-gray4">5</span>
</div>
</div>
<button className="body3 rounded-lg border-2 border-solid border-gray2 p-2 text-gray4">
편집
</button>
</div>
<span className="body1 text-gray4">23.12.23 - 23.12.25</span>
</div>
<span className="body1 text-gray4">
{trip?.startDate} ~ {trip?.endDate}
</span>
</div>
<Modal isOpen={isModalOpen} closeModal={closeModal}>
{modalChildren === 'TripSurveyMember' && <TripSurveyMember />}
</Modal>
</>
);
};

Expand Down
51 changes: 51 additions & 0 deletions src/components/Trip/TripParticipant.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { ReactComponent as NullUser } from '@assets/images/NullUser.svg';
import { useRecoilValue } from 'recoil';
import { participantsState } from '@recoil/trip';

interface ParticipantStatusProps {
status: string;
}

const ParticipantList: React.FC<{ infos: any[] }> = ({ infos }) => (
<div className="grid grid-cols-2 gap-3.5">
{infos.map((info: any) => (
<div
key={info.memberId}
className={`flex h-[40px] cursor-pointer items-center text-gray5`}>
{info.thumbnail && info.thumbnail !== 'http://asiduheimage.jpg' ? (
<img
src={info.thumbnail}
alt="유저 프로필"
className="h-[32px] w-[32px] rounded-full"
/>
) : (
<NullUser className="h-[32px] w-[32px]" />
)}
<div className="ml-3">{info.nickname}</div>
</div>
))}
</div>
);

export const ParticipantStatus: React.FC<ParticipantStatusProps> = ({
status,
}) => {
const participants = useRecoilValue(participantsState);

return (
<div className="flex flex-col">
<div className="mb-4 ml-auto mr-2 text-xs text-gray5">
{status == '참여' ? (
<>{participants?.tripSurveyMemberCount}명 참여</>
) : (
<>{participants?.nonTripSurveySetMemberInfos?.length}명 미참여</>
)}
</div>
{status == '참여' ? (
<ParticipantList infos={participants?.tripSurveySetMemberInfos} />
) : (
<ParticipantList infos={participants?.nonTripSurveySetMemberInfos} />
)}
</div>
);
};
48 changes: 38 additions & 10 deletions src/components/Trip/TripPreference.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import React, { useState, useEffect } from 'react';
import { getTripsSurvey } from '@api/trips';
import { useQuery } from '@tanstack/react-query';
import { useParams } from 'react-router-dom';
import { MoreIcon } from '@components/common/icons/Icons';
import { RightIcon } from '@components/common/icons/Icons';
import { MoreIcon, RightIcon, HeartIcon } from '@components/common/icons/Icons';
import {
calculatePercentage,
calculatePercentageRemain,
} from '@utils/calculatePercentage';

import { modalChildrenState, isModalOpenState } from '@recoil/modal';
import { getTripsSurveyMembers } from '@api/trips';
import { tripIdState } from '@recoil/socket';
import { useRecoilValue, useSetRecoilState, useRecoilState } from 'recoil';
import { participantsState } from '@recoil/trip';
interface RatioBarParams {
value: number;
total: number;
Expand All @@ -26,7 +28,12 @@ interface PercentageParams {
const TripPreferenceButton: React.FC = () => {
return (
<button className="mb-[17.5px] mt-[20px] flex w-[335px] items-center rounded-full bg-white px-6 py-4 text-sm">
<div className="text-gray6">내 여행 취향 설정하러 가기</div>
<div className="flex items-center text-gray6">
<div>
<HeartIcon fill="#888888" color="#888888" size={20} />
</div>
<p className="ml-1.5">내 여행 취향 설정하러 가기</p>
</div>
<div className="ml-auto">
<RightIcon fill="#5E5E5E" />
</div>
Expand Down Expand Up @@ -87,13 +94,25 @@ const Percentage = ({ value, total, color }: PercentageParams) => (
);

const TripPreference: React.FC = () => {
const params = useParams();
const tripId = Number(params.id);
const [A, setA] = useState<[number, number]>([0, 0]);
const [B, setB] = useState<[number, number]>([0, 0]);
const [C, setC] = useState<[number, number]>([0, 0]);
const [D, setD] = useState<[number, number]>([0, 0]);
const [E, setE] = useState<[number, number]>([0, 0]);
const setModalChildren = useSetRecoilState(modalChildrenState);
const setIsModalOpen = useSetRecoilState(isModalOpenState);
const tripId = Number(useRecoilValue(tripIdState));
const [participants, setParticipants] = useRecoilState(participantsState);

const { data: tripsSurveyMembers } = useQuery({
queryKey: ['tripsSurveyMembers', tripId],
queryFn: () => getTripsSurveyMembers(tripId),
});

useEffect(() => {
const participants = tripsSurveyMembers?.data?.data;
setParticipants(participants);
}, [tripsSurveyMembers]);

const { data: tripPreference, isLoading } = useQuery({
queryKey: ['tripPreference', tripId],
Expand Down Expand Up @@ -129,11 +148,20 @@ const TripPreference: React.FC = () => {
return <div>Loading...</div>;
}

const handleButtonClick = () => {
setModalChildren('TripSurveyMember');
setIsModalOpen(true);
};

return (
<div className=" mb-[-20px] ml-[-40px] mr-[-40px] mt-[-20px] flex flex-col items-center bg-gray1 ">
<div className=" m-[-20px] flex flex-col items-center bg-gray1 pb-[20px] ">
<TripPreferenceButton />
<div className="mb-[20px] ml-auto mr-[40px] flex items-center text-sm ">
<div>n명 참여</div>
<div
onClick={handleButtonClick}
className="mb-[20px] ml-auto mr-[40px] flex cursor-pointer items-center text-sm ">
<div className="text-gray6">
{participants?.tripSurveyMemberCount}명 참여
</div>
<div className="mt-0.5">
<MoreIcon size={20} color="none" fill="#888888" />
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/common/accordion/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ const Accordion: React.FC<AccordionProps> = ({ title, content }) => {
<accordion.Item value="item-1">
<accordion.Header className="flex">
{title}
<accordion.Trigger className="ml-auto">
<DownIcon size={17} className="rotate-on-open" />
<accordion.Trigger>
<DownIcon size={17} className="rotate-on-open ml-1" />
</accordion.Trigger>
</accordion.Header>
<accordion.Content>{content}</accordion.Content>
Expand Down
Loading

0 comments on commit 9a3a232

Please sign in to comment.