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 연동 #162

Merged
merged 9 commits into from
Nov 23, 2023
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
Loading