Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions src/app/message/chat/[roomId]/ChatRoomPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ const ChatRoomPage = ({ accessToken, roomId, userId }: IProps) => {
<UserList
roomId={roomId}
roomType={chatInfo?.chatType as 'DM' | 'GROUP'}
userId={userId}
onClose={() => setIsUserListOpen(false)}
/>
</div>
Expand Down
20 changes: 12 additions & 8 deletions src/components/pages/chat/chat-user-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,18 @@ interface UserListProps {
onClose: () => void;
roomId: number;
roomType: 'DM' | 'GROUP';
userId: number;
}

export const UserList = ({ onClose, roomId, roomType }: UserListProps) => {
export const UserList = ({ onClose, roomId, roomType, userId }: UserListProps) => {
const [isManaging, setIsManaging] = useState(false);
const { open } = useModal();
const { data } = useGetParticipants(roomId);
console.log(roomType);

const isCurrentUserOwner = data?.participants.some(
(participant) => participant.userId === userId && participant.isOwner,
);

return (
<div className='bg-mono-white flex h-[calc(100vh-112px)] flex-col'>
{/* 헤더 */}
Expand All @@ -32,19 +37,19 @@ export const UserList = ({ onClose, roomId, roomType }: UserListProps) => {
<span className='text-gray-800'>참여자</span>
<span className='text-mint-500'>{data?.totalCount}</span>
</span>
{roomType === 'GROUP' ? (
{roomType === 'GROUP' && isCurrentUserOwner ? (
<button
className='text-text-sm-semibold cursor-pointer'
onClick={() => setIsManaging(!isManaging)}
>
{isManaging ? (
<span className='text-gray-600'>완료</span>
<span className='w-6 text-gray-600'>완료</span>
) : (
<span className='text-mint-600'>관리</span>
<span className='text-mint-600 w-6'>관리</span>
)}
</button>
) : (
<div></div>
<div className='w-6'></div>
)}
</div>

Expand All @@ -70,8 +75,7 @@ export const UserList = ({ onClose, roomId, roomType }: UserListProps) => {
</div>
</div>

{/* 방장이 0번째로 들어온다면 이렇게, 방장이라는걸 알 수 있는 필드가 있다면 수정 */}
{roomType === 'GROUP' && index === 0 ? (
{roomType === 'GROUP' && user.isOwner ? (
<span className='bg-mint-100 text-mint-700 text-text-xs-medium rounded-full px-2.5 py-1'>
방장
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';

import { ModalProvider } from '@/components/ui';
import { ToastProvider } from '@/components/ui/toast/core';
import { useAddFollowers } from '@/hooks/use-follower';

import { FollowingModal } from '.';
Expand All @@ -24,7 +25,9 @@ const renderWithQueryClient = async (component: React.ReactElement) => {
await act(async () => {
renderResult = render(
<QueryClientProvider client={testQueryClient}>
<ModalProvider>{component}</ModalProvider>
<ToastProvider>
<ModalProvider>{component}</ModalProvider>
</ToastProvider>
</QueryClientProvider>,
);
});
Expand All @@ -33,15 +36,14 @@ const renderWithQueryClient = async (component: React.ReactElement) => {
};

describe('FollowingModal 테스트', () => {
const mockMutate = jest.fn();
const mockMutateAsync = jest.fn();
const mockUserId = 123;

beforeEach(() => {
jest.clearAllMocks();

// 기본 mock 설정
(useAddFollowers as jest.Mock).mockReturnValue({
mutate: mockMutate,
mutateAsync: mockMutateAsync,
});
});

Expand All @@ -62,9 +64,7 @@ describe('FollowingModal 테스트', () => {
});

test('Enter 키 입력 시 폼이 제출된다', async () => {
mockMutate.mockImplementation((_data, options) => {
options?.onSuccess?.();
});
mockMutateAsync.mockResolvedValue(undefined);

await renderWithQueryClient(<FollowingModal userId={mockUserId} />);

Expand All @@ -73,7 +73,7 @@ describe('FollowingModal 테스트', () => {
fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });

await waitFor(() => {
expect(mockMutate).toHaveBeenCalledWith({ followNickname: 'test' }, expect.any(Object));
expect(mockMutateAsync).toHaveBeenCalledWith({ followNickname: 'test' });
});
});
});
36 changes: 16 additions & 20 deletions src/components/pages/message/message-following-modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,32 @@ import { useState } from 'react';
import { useForm } from '@tanstack/react-form';

import { Icon } from '@/components/icon';
import { Button, Input, ModalContent, ModalTitle, useModal } from '@/components/ui';
import { Button, Input, ModalContent, ModalTitle, Toast, useModal } from '@/components/ui';
import { useToast } from '@/components/ui/toast/core';
import { useAddFollowers } from '@/hooks/use-follower';

export const FollowingModal = ({ userId }: { userId: number }) => {
const { close } = useModal();
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const { mutate: addFollower } = useAddFollowers({ userId });
const { mutateAsync } = useAddFollowers({ userId });
const { run } = useToast();
const form = useForm({
defaultValues: {
nickname: '',
},
onSubmit: ({ value }) => {
defaultValues: { nickname: '' },
onSubmit: async ({ value }) => {
const { nickname } = value;
setErrorMessage(null);

addFollower(
{
followNickname: nickname,
},
{
onSuccess: () => {
close();
},
onError: (e) => {
setErrorMessage(e.detail.slice(4));
},
},
);
try {
await mutateAsync({ followNickname: nickname });
close();
run(<Toast type='success'>{nickname}님을 팔로우 했어요!</Toast>);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
console.log(error);
setErrorMessage(error.detail.slice(4));
}
},
});

return (
<ModalContent className='max-w-77.75'>
<ModalTitle className='mb-3'>팔로우 할 닉네임을 입력하세요</ModalTitle>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { act, fireEvent, render, screen } from '@testing-library/react';

import { ModalProvider } from '@/components/ui';
import { ToastProvider } from '@/components/ui/toast/core';

import { FollowingSearch } from '.';

Expand All @@ -19,9 +20,11 @@ const renderComponent = async () => {
await act(async () => {
render(
<QueryClientProvider client={queryClient}>
<ModalProvider>
<FollowingSearch userId={0} />
</ModalProvider>
<ToastProvider>
<ModalProvider>
<FollowingSearch userId={0} />
</ModalProvider>
</ToastProvider>
</QueryClientProvider>,
);
});
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/use-follower/use-follower-add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ export const useAddFollowers = (
queryClient.invalidateQueries({ queryKey: ['followers', userId] });
console.log('팔로워 추가 성공');
},
onError: () => {
onError: (error) => {
console.log('팔로워 추가 실패');
throw error;
},
});
return query;
Expand Down
1 change: 1 addition & 0 deletions src/types/service/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface ChatUser {
status: 'ACTIVE' | 'INACTIVE'; // 확인 필요💥💥
userId: number;
profileMessage: string;
isOwner: boolean;
}

export interface GetChatRoomsResponse {
Expand Down