Skip to content

Commit

Permalink
Merge pull request #162 from js43o/detail-page-api
Browse files Browse the repository at this point in the history
[Feat] 모각코 상세 게시글 페이지 API 연동
  • Loading branch information
js43o authored Nov 23, 2023
2 parents 0d6c31b + 09331f1 commit ff7e378
Show file tree
Hide file tree
Showing 21 changed files with 213 additions and 251 deletions.
2 changes: 0 additions & 2 deletions app/frontend/src/components/Mogaco/MogacoList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export function MogacoList() {
mogacoList.map(
({
id,
memberId,
groupId,
title,
contents,
Expand All @@ -27,7 +26,6 @@ export function MogacoList() {
<MogacoItem
key={id}
id={id}
memberId={memberId}
title={title}
groupId={groupId}
contents={contents}
Expand Down
7 changes: 0 additions & 7 deletions app/frontend/src/components/MogacoDetail/DetailContents.tsx

This file was deleted.

54 changes: 15 additions & 39 deletions app/frontend/src/components/MogacoDetail/DetailHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,65 +1,41 @@
import { useState, useEffect } from 'react';

import { UserChip } from '@/components';
import { member } from '@/services';
import { sansBold24 } from '@/styles/font.css';
import { UserInfo } from '@/types';
import { Member, Mogaco } from '@/types';

import { DetailHeaderButtons } from './DetailHeaderButtons';
import * as styles from './index.css';

type DetailHeaderProps = {
id: string;
memberId: string;
title: string;
status: '모집 중' | '마감' | '종료';
userHosted: boolean;
userParticipated: boolean;
currentUser: Member;
mogacoData: Mogaco;
participantList: Member[];
};

export function DetailHeader({
id,
memberId,
title,
status,
userHosted,
userParticipated,
currentUser,
mogacoData,
participantList,
}: DetailHeaderProps) {
const [hostUser, setHostUser] = useState<UserInfo | null>(null);

useEffect(() => {
if (hostUser) {
return;
}

const getUser = async () => {
const data = await member.userInfoById(memberId);
setHostUser(data);
};

getUser();
}, [hostUser, memberId]);

return (
<div className={styles.header}>
<div className={styles.title}>
<div className={sansBold24}>{title}</div>
<div className={sansBold24}>{mogacoData.title}</div>
<div className={styles.buttons}>
<DetailHeaderButtons
id={id}
status={status}
userHosted={userHosted}
userParticipated={userParticipated}
currentUser={currentUser}
mogacoData={mogacoData}
participantList={participantList}
/>
</div>
</div>
<div className={styles.hostUser}>
{hostUser && (
<UserChip
username={hostUser.nickname}
profileSrc={hostUser.profilePicture}
/>
)}
<UserChip
username={mogacoData.member.nickname}
profileSrc={mogacoData.member.profilePicture}
/>
<span>부스트캠프 웹·모바일 8기</span>
</div>
</div>
Expand Down
45 changes: 26 additions & 19 deletions app/frontend/src/components/MogacoDetail/DetailHeaderButtons.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,39 @@
import { useNavigate, useParams } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';

import { Button } from '@/components';
import { useDeleteMogacoQuery } from '@/queries/hooks';
import { mogaco } from '@/services';
import {
useDeleteMogacoQuery,
useJoinMogacoQuery,
useQuitMogacoQuery,
} from '@/queries/hooks';
import { Member, Mogaco } from '@/types';

type DetailHeaderButtonsProps = {
id: string;
userHosted: boolean;
userParticipated: boolean;
status: '모집 중' | '마감' | '종료';
currentUser: Member;
mogacoData: Mogaco;
participantList: Member[];
};

export function DetailHeaderButtons({
id,
userHosted,
userParticipated,
status,
currentUser,
mogacoData,
participantList,
}: DetailHeaderButtonsProps) {
const navigate = useNavigate();
const { id: postId } = useParams();
const { mutateAsync } = useDeleteMogacoQuery();

const handleDelete = async () => {
if (!postId) {
return;
}
const deleteMogaco = useDeleteMogacoQuery();
const joinMogaco = useJoinMogacoQuery();
const quitMogaco = useQuitMogacoQuery();

const res = await mutateAsync(id);
const userHosted = mogacoData.member.providerId === currentUser.providerId;
const userParticipated = participantList.find(
(participant) => participant.providerId === currentUser.providerId,
);

const handleDelete = async () => {
const res = await deleteMogaco.mutateAsync(id!);
if (res.status === 200) {
navigate('/mogaco');
}
Expand All @@ -41,11 +48,11 @@ export function DetailHeaderButtons({
};

const onClickJoin = async () => {
await mogaco.join(id);
await joinMogaco.mutateAsync(id!);
};

const onClickQuit = async () => {
await mogaco.quit(id);
await quitMogaco.mutateAsync(id!);
};

if (userHosted) {
Expand All @@ -66,7 +73,7 @@ export function DetailHeaderButtons({
);
}

if (status === '모집 중') {
if (mogacoData.status === '모집 중') {
return userParticipated ? (
<>
<Button theme="primary" shape="fill" size="large">
Expand Down
24 changes: 9 additions & 15 deletions app/frontend/src/components/MogacoDetail/DetailInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,16 @@ import { ReactComponent as People } from '@/assets/icons/people_large.svg';
import { UserChip } from '@/components';
import { MAP_SAMPLE_IMAGE } from '@/constants';
import { vars } from '@/styles';
import { Participant } from '@/types';
import { Member, Mogaco } from '@/types';

import * as styles from './index.css';

type DetailInfoProps = {
participantList: Participant[] | null;
maxHumanCount: number;
date: string;
address: string;
mogacoData: Mogaco;
participantList: Member[];
};

export function DetailInfo({
participantList,
maxHumanCount,
date,
address,
}: DetailInfoProps) {
export function DetailInfo({ mogacoData, participantList }: DetailInfoProps) {
const [participantsShown, setParticipantsShown] = useState(false);

const toggleParticipantsShown = () =>
Expand All @@ -36,7 +29,8 @@ export function DetailInfo({
<div className={styles.infoItem}>
<People fill={vars.color.grayscale200} />
<span>
<span>{participantList?.length}</span>/<span>{maxHumanCount}</span>
<span>{participantList.length}</span>/
<span>{mogacoData.maxHumanCount}</span>
</span>
<button
type="button"
Expand All @@ -56,19 +50,19 @@ export function DetailInfo({
{!!participantList &&
participantList.map((participant) => (
<UserChip
key={participant.id}
key={participant.providerId}
username={participant.nickname}
profileSrc={participant.profilePicture}
/>
))}
</div>
<div className={styles.infoItem}>
<Calendar fill={vars.color.grayscale200} />
<span>{dayjs(date).format('YYYY/MM/DD HH:mm~')}</span>
<span>{dayjs(mogacoData.date).format('YYYY/MM/DD HH:mm~')}</span>
</div>
<div className={styles.infoItem}>
<Map fill={vars.color.grayscale200} />
<span>{address}</span>
<span>{mogacoData.address}</span>
</div>
<img src={MAP_SAMPLE_IMAGE} alt="맵 샘플 이미지" className={styles.map} />
</div>
Expand Down
88 changes: 34 additions & 54 deletions app/frontend/src/components/MogacoDetail/index.tsx
Original file line number Diff line number Diff line change
@@ -1,78 +1,58 @@
import { useState, useEffect } from 'react';
import { useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';

import { mogaco } from '@/services';
import { useUserAtom } from '@/stores';
import { Mogaco, Participant } from '@/types';
import { useQuery } from '@tanstack/react-query';

import { queryKeys } from '@/queries';

import { DetailContents } from './DetailContents';
import { DetailHeader } from './DetailHeader';
import { DetailInfo } from './DetailInfo';
import * as styles from './index.css';

type MogacoDetailProps = Mogaco;
export function MogacoDetailPage() {
const { id } = useParams();
const navigate = useNavigate();

export function MogacoDetailPage({
id,
memberId,
title,
maxHumanCount,
date,
address,
contents,
status,
}: MogacoDetailProps) {
const [participantList, setParticipantList] = useState<Participant[] | null>(
null,
const { data: currentUser, isLoading: currentUserLoading } = useQuery(
queryKeys.member.me(),
);
const { data: mogacoData, isLoading: mogacoDataLoading } = useQuery(
queryKeys.mogaco.detail(id!),
);
const { data: participantList, isLoading: participantListLoading } = useQuery(
queryKeys.mogaco.participants(id!),
);
const [user, setUser] = useUserAtom();

if (!user)
setUser({
providerId: '1',
nickname: '지승',
profilePicture:
'https://avatars.githubusercontent.com/u/50646827?s=40&v=4',
email: '[email protected]',
});

const userHosted = user?.providerId === memberId;
const userParticipated = participantList
? !!participantList.find(
(participant) => participant.id === user?.providerId,
)
: false;

useEffect(() => {
if (participantList) {
return;
if (!currentUser) {
// eslint-disable-next-line no-alert
window.alert('인증 정보가 없습니다.\n로그인해 주세요.');
navigate('/');
}
}, [currentUser, navigate]);

const getParticipantList = async () => {
const data = await mogaco.participants(id);
setParticipantList(data);
};
if (currentUserLoading || mogacoDataLoading || participantListLoading) {
return <div>로딩 중...</div>;
}

getParticipantList();
}, [id, participantList]);
if (!mogacoData) {
return <div>정보를 불러오는 데에 실패했습니다.</div>;
}

return (
<div className={styles.wrapper}>
<div className={styles.container}>
<DetailHeader
id={id}
title={title}
status={status}
memberId={memberId}
userHosted={userHosted}
userParticipated={userParticipated}
id={id!}
currentUser={currentUser!}
mogacoData={mogacoData}
participantList={participantList || []}
/>
<DetailInfo
participantList={participantList}
maxHumanCount={maxHumanCount}
date={date}
address={address}
mogacoData={mogacoData}
participantList={participantList || []}
/>
<DetailContents contents={contents} />
<div>{mogacoData.contents}</div>
<hr className={styles.horizontalLine} />
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/src/components/commons/MogacoItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Mogaco } from '@/types';

import * as styles from './index.css';

type MogacoProps = Mogaco;
type MogacoProps = Omit<Mogaco, 'member'>;

export function MogacoItem({
id,
Expand Down
4 changes: 4 additions & 0 deletions app/frontend/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import ReactDOM from 'react-dom/client';

import App from './App';
import { queryKeys } from './queries';

async function enableMocking() {
if (import.meta.env.MODE !== 'development') {
Expand All @@ -18,6 +19,9 @@ async function enableMocking() {
}

const queryClient = new QueryClient();
queryClient.setQueryDefaults(queryKeys.member.me().queryKey, {
staleTime: Infinity,
});

enableMocking().then(() => {
ReactDOM.createRoot(document.getElementById('root')!).render(
Expand Down
Loading

0 comments on commit ff7e378

Please sign in to comment.