Skip to content
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
17 changes: 14 additions & 3 deletions src/app/(user-page)/my-meeting/_features/CardRightSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ const CardRightSection = ({
}
};

// 맴버 명단 보기
const handleShowMemberList = () => {
queryClient.setQueryData(
['mymeeting', 'memberList', meetingId],
memberList,
);
router.push(
`/my-meeting/my/user-list?meetingId=${meetingId}&type=${showPublicSelect ? 'created' : 'joined'}`,
);
};

const { data: currentUser, isLoading } = useBannerQueries();
if (isLoading || !currentUser) {
return;
Expand Down Expand Up @@ -109,19 +120,19 @@ const CardRightSection = ({
</div>
</div>

{/* <div className="flex flex-1 gap-[16px]"> */}
<Button
variant="outline"
className="flex h-[40px] flex-1 md:h-[46px] lg:hidden"
onClick={() =>
router.push(`/my-meeting/my/user-list?meetingId=${meetingId}`)
}
onClick={handleShowMemberList}
>
맴버 명단 보기
</Button>
{showPublicSelect && (
<PublicSelect isPublic={isPublic} meetingId={meetingId} />
)}
</div>
// </div>
);
};

Expand Down
3 changes: 3 additions & 0 deletions src/app/(user-page)/my-meeting/_features/Created.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
hasNextPage,
isFetchingNextPage,
isLoading,
error,

Check warning on line 20 in src/app/(user-page)/my-meeting/_features/Created.tsx

View workflow job for this annotation

GitHub Actions / check

'error' is assigned a value but never used. Allowed unused vars must match /^_/u
} = useInfiniteMyMeetingManageQueries();

const lastMeetingRef = useInfiniteScroll({
Expand Down Expand Up @@ -67,6 +67,7 @@
isPublic={meeting.isPublic}
className="hidden lg:flex"
meetingId={meeting.meetingId}
showPublicSelect={true}
/>
</HorizonCard>
</div>
Expand Down Expand Up @@ -96,6 +97,7 @@
isPublic={meeting.isPublic}
className="flex lg:hidden"
meetingId={meeting.meetingId}
showPublicSelect={true}
/>
</div>

Expand Down Expand Up @@ -124,6 +126,7 @@
isPublic={meeting.isPublic}
className="flex lg:hidden"
meetingId={meeting.meetingId}
showPublicSelect={true}
/>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(user-page)/my-meeting/_features/ModalUserList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const ModalUserList = ({
<Tag
variant={user.memberStatus}
className="w-[49px] justify-center"
/>
/>
)}
<div>
<Button
Expand Down
14 changes: 14 additions & 0 deletions src/app/(user-page)/my-meeting/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import MeetingTypeTab from './_features/MeetingTypeTab';

export default function layout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<div>
<MeetingTypeTab />
{children}
</div>
);
}
23 changes: 11 additions & 12 deletions src/app/(user-page)/my-meeting/my/@modal/(.)user-list/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,33 @@
import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/navigation';
import { getMyMeetingMemberProfile } from 'service/api/mymeeting';
import { Paginated } from 'types/meeting';

Check warning on line 9 in src/app/(user-page)/my-meeting/my/@modal/(.)user-list/page.tsx

View workflow job for this annotation

GitHub Actions / check

'Paginated' is defined but never used. Allowed unused vars must match /^_/u
import { IMyMeetingManage, Member } from 'types/myMeeting';

Check warning on line 10 in src/app/(user-page)/my-meeting/my/@modal/(.)user-list/page.tsx

View workflow job for this annotation

GitHub Actions / check

'IMyMeetingManage' is defined but never used. Allowed unused vars must match /^_/u

import ModalUserList from '../../../_features/ModalUserList';

export default function UserListModal({
searchParams,
}: {
searchParams: { meetingId: string };
searchParams: { meetingId: string; type: string };
}) {
const router = useRouter();
const meetingId = Number(searchParams.meetingId);
const type = searchParams.type;

const queryClient = useQueryClient();

// 캐싱된 데이터 먼저 가져오기
const cachedMeetings = queryClient.getQueryData<{
pages: Paginated<IMyMeetingManage>[];
}>(myMeetingKeys.manage());

// 캐시에서 특정 meetingId의 memberList 찾기
const memberList =
cachedMeetings?.pages
?.flatMap((page) => page.content)
?.find((meeting) => meeting.meetingId === meetingId)?.memberList || [];
const cachedMemberList = queryClient.getQueryData<Member[]>([
'mymeeting',
'memberList',
meetingId,
]);

// 유저 정보 파악
const { data: currentUser, isLoading, error } = useBannerQueries();

Check warning on line 33 in src/app/(user-page)/my-meeting/my/@modal/(.)user-list/page.tsx

View workflow job for this annotation

GitHub Actions / check

'error' is assigned a value but never used. Allowed unused vars must match /^_/u

if (!currentUser || isLoading) return;
if (!currentUser || isLoading || !cachedMemberList) return;

const handlePrefetchProfile = async (member: Member) => {
const queryKey = myMeetingKeys.memberProfile(meetingId, member.userId);
Expand All @@ -60,9 +58,10 @@
>
<ModalUserList
meetingId={meetingId}
memberList={memberList}
memberList={cachedMemberList}
currentUser={currentUser}
handlePrefetchProfile={handlePrefetchProfile}
showPublicSelect={type === 'created' && true}
/>
</ModalPortal>
);
Expand Down
20 changes: 20 additions & 0 deletions src/app/meeting/[category]/(modal)/need-login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client';

import { redirect } from 'next/navigation';

export default function NeedLoginModal({
searchParams,
params,
}: {
searchParams: { category: string; meetingId?: number };
params: { category: string };
}) {
const category = params.category;
const meetingId = searchParams.meetingId || 0;

if (meetingId === 0) {
redirect(`/meeting/${category}`);
} else {
redirect(`/meeting/${category}/${meetingId}`);
}
}
22 changes: 22 additions & 0 deletions src/app/meeting/[category]/@modal/(.)need-login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client';

import ModalPortal from '@/components/ui/modal/ModalPortal';
import { useRouter } from 'next/navigation';

export default function UserListModal() {
const router = useRouter();

return (
<ModalPortal
isOpen={true}
onConfirm={() => router.push('/login')}
confirmText="로그인"
cancelText="취소"
modalClassName="w-96"
>
<div className="text-cg8 typo-head3 flex w-full justify-center">
<p className="text-white">로그인이 필요한 서비스입니다.</p>
</div>
</ModalPortal>
);
}
3 changes: 3 additions & 0 deletions src/app/meeting/[category]/@modal/default.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function DefaultModal() {
return null; // 기본적으로 모달 없음
}
14 changes: 14 additions & 0 deletions src/app/meeting/[category]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default function layout({
children,
modal,
}: Readonly<{
children: React.ReactNode;
modal: React.ReactNode;
}>) {
return (
<div>
{children}
{modal}
</div>
);
}
16 changes: 7 additions & 9 deletions src/components/common/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import Logo from '@/assets/icon/logo.svg';
import { useLogoutMutation } from '@/hooks/mutations/useUserMutation';
import { QUERY_KEYS } from '@/hooks/queries/useMyPageQueries';
import { removeAccessToken } from '@/lib/serverActions';
import { translateCategoryNameToKor } from '@/util/searchFilter';
Expand Down Expand Up @@ -40,6 +41,8 @@ const BeforeLogin = () => {
const AfterLogin = ({ userInfo }: { userInfo: IUserInfo }) => {
const router = useRouter();
const { showToast } = useToast();

const { mutate } = useLogoutMutation();
const menu = [
{
value: 'mymeeting',
Expand All @@ -54,11 +57,7 @@ const AfterLogin = ({ userInfo }: { userInfo: IUserInfo }) => {
{
value: 'logout',
label: '로그아웃',
onSelect: async () => {
await removeAccessToken();
// 로그아웃 관련 토스트바 노출
showToast('로그아웃 되었습니다.', 'success');
},
onSelect: () => mutate(),
},
];
return (
Expand Down Expand Up @@ -119,15 +118,14 @@ const MobileBeforeLogin = () => {

const MobileAfterLogin = ({ userInfo }: { userInfo: IUserInfo }) => {
const { showToast } = useToast();
const { mutate } = useLogoutMutation();

return (
<div className="flex flex-col py-[24px]">
<div className="flex items-center justify-between">
<button
className="typo-head3 p-[16px] text-Cgray500 hover:text-Cgray700"
onClick={async () => {
await removeAccessToken();
showToast('로그아웃 되었습니다.', 'success');
}}
onClick={() => mutate()}
>
로그아웃
</button>
Expand Down
6 changes: 5 additions & 1 deletion src/components/ui/HorizonCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import useLikeHandler from '@/hooks/common/useLikeHandler';
import { getIconComponent } from '@/util/getIconDetail';
import { translateCategoryNameToEng } from '@/util/searchFilter';
import { Heart, Map } from 'lucide-react';
import Image from 'next/image';
import { useParams, useRouter } from 'next/navigation';
Expand Down Expand Up @@ -54,7 +55,10 @@ const HorizonCard = ({
meetingId,
category,
searchQuery,
onAuthRequired: () => setIsLoginModalOpen(true),
onAuthRequired: () =>
router.push(
`/meeting/${translateCategoryNameToEng(category)}/need-login`,
),
});

const handleLikeButton = (e: React.MouseEvent<HTMLButtonElement>) => {
Expand Down
7 changes: 6 additions & 1 deletion src/components/ui/VerticalCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import useLikeHandler from '@/hooks/common/useLikeHandler';
import { getIconComponent } from '@/util/getIconDetail';
import { translateCategoryNameToEng } from '@/util/searchFilter';
import { useQueryClient } from '@tanstack/react-query';
import { Heart, Map } from 'lucide-react';
import Image from 'next/image';
import { useRouter } from 'next/navigation';
Expand Down Expand Up @@ -58,7 +60,10 @@ const VerticalCard = ({
meetingId,
category,
searchQuery,
onAuthRequired: () => setIsLoginModalOpen(true),
onAuthRequired: () =>
router.push(
`/meeting/${translateCategoryNameToEng(category)}/need-login`,
),
});

const handleLikeButton = (e: React.MouseEvent<HTMLButtonElement>) => {
Expand Down
26 changes: 20 additions & 6 deletions src/components/ui/modal/ModalPortal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createPortal } from 'react-dom';

interface AlertModalProps {
isOpen: boolean;
onClose: () => void;
onClose?: () => void;
onConfirm?: () => void;
confirmText?: string;
cancelText?: string;
Expand Down Expand Up @@ -90,7 +90,21 @@ const ModalPortal: React.FC<AlertModalProps> = ({
}
}, []);

if (!isOpen) return null;
const handleClose = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.stopPropagation();
if (onClose) {
onClose();
} else {
router.back();
}
};

const handleConfirm = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>,
) => {
e.stopPropagation();
onConfirm?.();
};

return createPortal(
<div
Expand All @@ -106,24 +120,24 @@ const ModalPortal: React.FC<AlertModalProps> = ({
aria-modal="true"
tabIndex={-1}
ref={dialogRef}
aria-labelledBy="modal-title"
aria-labelledby="modal-title"
aria-describedby="modal-description"
>
<div className={`p-6 ${contentClassName}`}>{children}</div>

{!showOnly && (
<div className={`flex justify-end gap-2 p-4 ${buttonClassName}`}>
{closeOnly ? (
<Button onClick={onClose} type="button" className="w-full">
<Button onClick={handleClose} type="button" className="w-full">
{cancelText}
</Button>
) : (
<>
<Button onClick={onClose} variant={'outline'} type="button">
<Button onClick={handleClose} variant={'outline'} type="button">
{cancelText}
</Button>
<Button
onClick={onConfirm}
onClick={handleConfirm}
type="button"
disabled={disableConfirm}
className={
Expand Down
23 changes: 22 additions & 1 deletion src/hooks/mutations/useUserMutation.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { useToast } from '@/components/common/ToastContext';
import { setAccessToken, setRefreshToken } from '@/lib/serverActions';
import {
removeAccessToken,
removeRefreshToken,
setAccessToken,
setRefreshToken,
} from '@/lib/serverActions';
import {
QueryClient,
useMutation,
useQueryClient,
} from '@tanstack/react-query';
import {
deleteLogout,
getEmailCheck,
getNameCheck,
postLogin,
Expand Down Expand Up @@ -112,9 +118,24 @@ const useSignupMutation = ({
});
};

// 로그아웃
const useLogoutMutation = () => {
const { showToast } = useToast();
return useMutation({
mutationFn: () => deleteLogout(),
onSuccess: async () => {
await removeAccessToken();
await removeRefreshToken();
// 로그아웃 관련 토스트바 노출
showToast('로그아웃 되었습니다.', 'success');
},
});
};

export {
useLoginMutation,
useNameCheckMutation,
useEmailCheckMutation,
useSignupMutation,
useLogoutMutation,
};
Loading
Loading