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
21 changes: 19 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { BrowserRouter, Route, Routes, Navigate } from 'react-router-dom';

import Home from '@pages/Home';
Expand Down Expand Up @@ -28,9 +28,26 @@ import ChatRoom from '@pages/Chats/ChatRoom';
import MatchingRoom from '@pages/Chats/MatchingRoom';

import NotFound from '@pages/NotFound';
import { getUserInfoApi } from '@apis/user';
import { getCurrentUserId } from '@utils/getCurrentUserId';
import Loading from '@components/Loading';

const ProtectedRoute = ({ children }: { children: JSX.Element }) => {
const isAuthenticated = Boolean(localStorage.getItem('new_jwt_token'));
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null);

useEffect(() => {
const checkAuth = async () => {
const currentUserId = getCurrentUserId();
const response = await getUserInfoApi(currentUserId);
setIsAuthenticated(response.isSuccess);
};
checkAuth();
}, []);

if (isAuthenticated === null) {
return <Loading />;
}

return isAuthenticated ? children : <Navigate to="/login" />;
};

Expand Down
29 changes: 0 additions & 29 deletions src/apis/matching/dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { BaseSuccessResponse } from '@apis/core/dto';

type RequestStatusEnum = 'accepted' | 'rejected' | 'pending';

// 매칭 요청
Expand All @@ -10,16 +8,6 @@ export interface CreateMatchingRequest {
message: string;
}

// response
export type CreateMatchingResponse = BaseSuccessResponse<CreateMatchingData>;

export interface CreateMatchingData {
id: number; // matchingId
chatRoomId: number;
requesterId: number;
targetId: number;
}

// 최근 매칭 조회 (채팅방 리스트에서)
export interface LatestMatchingData {
id?: number;
Expand Down Expand Up @@ -56,20 +44,3 @@ export interface PostImageDto {
url: string;
orderNum: number;
}

// 매칭 요청 수락 및 거절
// request
export interface ModifyMatchingStatusRequest {
requestStatus: 'accept' | 'reject';
}

// response
export type ModifyMatchingStatusResponse = BaseSuccessResponse<ModifyMatchingStatusData>;

export interface ModifyMatchingStatusData {
id: number; // matchingId
requesterId: number;
targetId: number;
requestStatus: string;
chatRoomId: number;
}
16 changes: 0 additions & 16 deletions src/apis/matching/index.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/pages/Chats/MatchingRoom/Card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const Card: React.FC<CardProps> = ({ requester }) => {
</ProfileImgBox>
<ProfileInfo>
<StyledText
$textTheme={{ style: 'body1-medium' }}
$textTheme={{ style: 'body2-medium' }}
color={theme.colors.text.primary}
onClick={handleUserClick}
>
Expand All @@ -39,7 +39,7 @@ const Card: React.FC<CardProps> = ({ requester }) => {
<div className="row-flex">
{requester.representativePost.styleTags.map((tag, index) => (
<div className="row-flex" key={tag}>
<StyledText $textTheme={{ style: 'caption2-regular' }} color={theme.colors.gray[200]}>
<StyledText $textTheme={{ style: 'caption2-regular' }} color={theme.colors.gray[600]}>
{tag}
</StyledText>
{index < requester.representativePost.styleTags.length - 1 && (
Expand Down
6 changes: 4 additions & 2 deletions src/pages/Chats/MatchingRoom/MatchingMessage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import dayjs from 'dayjs';

import RcvdMessage from '@pages/Chats/RcvdMessage';

import defaultProfile from '@assets/default/defaultProfile.svg';

import type { MatchingData } from '@apis/matching/dto';
import type { RcvdMessageProps } from '@pages/Chats/RcvdMessage/dto';

Expand All @@ -14,7 +16,7 @@ const MatchingMessage: React.FC<MatchingData> = ({ id, message, createdAt, chatR

const firstMessageProps: RcvdMessageProps = {
fromUserNickname: '오딩이',
profilePictureUrl: '',
profilePictureUrl: defaultProfile,
content: '얘가 너 소개받고 싶대',
isSenderChanged: false,
isProfileImageVisible: true,
Expand All @@ -24,7 +26,7 @@ const MatchingMessage: React.FC<MatchingData> = ({ id, message, createdAt, chatR

const matchingMessageProps: RcvdMessageProps = {
fromUserNickname: '오딩이',
profilePictureUrl: '',
profilePictureUrl: defaultProfile,
content: message,
isSenderChanged: false,
isProfileImageVisible: false,
Expand Down
4 changes: 3 additions & 1 deletion src/pages/Chats/MatchingRoom/NoMatchingMessage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import dayjs from 'dayjs';

import RcvdMessage from '@pages/Chats/RcvdMessage';

import defaultProfile from '@assets/default/defaultProfile.svg';

import type { RcvdMessageProps } from '@pages/Chats/RcvdMessage/dto';

const NoMatchingMessage: React.FC = () => {
const formattedTime = dayjs(new Date()).format('HH:mm');

const messageProps: RcvdMessageProps = {
fromUserNickname: '오딩이',
profilePictureUrl: '',
profilePictureUrl: defaultProfile,
content: '매칭이 들어오면 오딩이가 알려줄게!',
isSenderChanged: true,
isProfileImageVisible: true,
Expand Down
21 changes: 18 additions & 3 deletions src/pages/Chats/MatchingRoom/ResponseMessage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
import { useNavigate } from 'react-router-dom';

import { useRecoilState } from 'recoil';

import theme from '@styles/theme';

import { RequesterDto } from '@apis/matching/dto';
import { useSocket } from '@context/SocketProvider';
import { OtherUserAtom } from '@recoil/util/OtherUser';

import { StyledText } from '@components/Text/StyledText';

import { ResponseButton, ResponseContainer } from './styles';

export interface ResponseMessageProps {
matchingId: number;
chatRoomId: number;
requester: Omit<RequesterDto, 'RepresentativePostDto'>;
requestStatus: 'accepted' | 'rejected' | 'pending';
}

const ResponseMessage: React.FC<ResponseMessageProps> = ({ matchingId, chatRoomId, requestStatus }) => {
const ResponseMessage: React.FC<ResponseMessageProps> = ({ matchingId, chatRoomId, requester, requestStatus }) => {
const socket = useSocket('matching');
const isPending = requestStatus === 'pending';
const nav = useNavigate();
const [, setOtherUser] = useRecoilState(OtherUserAtom);

const handlebuttonClick = (status: 'accept' | 'reject') => {
if (requestStatus !== 'pending') return;
if (socket) {
socket.emit('patchMatching', { id: matchingId, requestStatus: status });
if (status === 'accept') {
setOtherUser(requester);
nav(`/chats/${chatRoomId}`);
}
}
Expand All @@ -29,12 +40,16 @@ const ResponseMessage: React.FC<ResponseMessageProps> = ({ matchingId, chatRoomI
<ResponseContainer>
{(requestStatus === 'pending' || requestStatus === 'rejected') && (
<ResponseButton $isPending={isPending} onClick={() => handlebuttonClick('reject')}>
거절
<StyledText $textTheme={{ style: 'body2-regular' }} color={theme.colors.text.primary}>
거절
</StyledText>
</ResponseButton>
)}
{(requestStatus === 'pending' || requestStatus === 'accepted') && (
<ResponseButton $isPending={isPending} onClick={() => handlebuttonClick('accept')}>
수락
<StyledText $textTheme={{ style: 'body2-regular' }} color={theme.colors.text.primary}>
수락
</StyledText>
</ResponseButton>
)}
</ResponseContainer>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Chats/MatchingRoom/ResponseMessage/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ export const ResponseButton = styled.button<{ $isPending: boolean }>`
padding: 0.4rem 0.8rem;
margin: 0.5rem 0;
background-color: #f2f2f2;
border-radius: 0.5rem;
border-radius: 0.8rem;
overflow-wrap: break-word;
`;
42 changes: 24 additions & 18 deletions src/pages/Chats/MatchingRoom/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const MatchingRoom: React.FC = () => {
useEffect(() => {
// 전체 매칭 불러오기 socket api
const getAllMatchings = ({ matching }: { matching: MatchingData[] }) => {
console.log(matching);
setAllMatchings(matching);
setIsScroll(true);
setIsLoading(false);
Expand All @@ -65,20 +66,28 @@ const MatchingRoom: React.FC = () => {
if (JSON.stringify(data) === '{}') {
setHasNewMatching(false);
} else {
setHasNewMatching(true);
setAllMatchings([...allMatchings, data]);
}
};

const handleError = (data: string) => {
alert(data);
};

if (socket) {
socket.emit('getAllMatchings', { userId: currentUserId });
socket.emit('getMatching', { userId: currentUserId });
socket.on('matchings', getAllMatchings);
socket.on('nextMatching', getNewMatching);
socket.on('error', handleError);
}

return () => {
if (socket) {
socket.off();
socket.off('matchings');
socket.off('nextMatching');
socket.off('error');
}
};
}, [socket]);
Expand All @@ -94,23 +103,20 @@ const MatchingRoom: React.FC = () => {
$withBorder={true}
/>
<MessagesContainer $isLoading={isLoading}>
{allMatchings.length === 0 ? (
<NoMatchingMessage />
) : (
allMatchings.map((matching: MatchingData) => {
console.log(matching);
return (
<div key={matching.id}>
<MatchingMessage {...matching} />
<ResponseMessage
matchingId={matching.id}
chatRoomId={matching.chatRoomId}
requestStatus={matching.requestStatus}
/>
</div>
);
})
)}
{allMatchings.map((matching: MatchingData) => {
console.log(matching);
return (
<div key={matching.id}>
<MatchingMessage {...matching} />
<ResponseMessage
matchingId={matching.id}
chatRoomId={matching.chatRoomId}
requester={matching.requester}
requestStatus={matching.requestStatus}
/>
</div>
);
})}
{!hasNewMatching && <NoMatchingMessage />}
<div ref={chatWindowRef} />
</MessagesContainer>
Expand Down
16 changes: 9 additions & 7 deletions src/pages/Chats/RcvdMessage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,22 @@ const RcvdMessage: React.FC<RcvdMessageProps & { onClickProfile?: () => void; ch
return (
<FirstMessageLayout $isSenderChanged={isSenderChanged}>
<UserImage onClick={onClickProfile} src={profilePictureUrl} alt="프로필 사진" />
<MessageBox>
<div>
<UsernameText
onClick={onClickProfile}
$textTheme={{ style: 'body2-regular' }}
color={theme.colors.text.primary}
>
{fromUserNickname}
</UsernameText>
<Message $textTheme={{ style: 'body2-regular' }} color={theme.colors.text.primary}>
{children}
{content}
</Message>
</MessageBox>
{isTimeVisible && <TimeWrapper>{formattedTime}</TimeWrapper>}
<MessageBox>
<Message $textTheme={{ style: 'body2-regular' }} color={theme.colors.text.primary}>
{children}
{content}
</Message>
{isTimeVisible && <TimeWrapper>{formattedTime}</TimeWrapper>}
</MessageBox>
</div>
</FirstMessageLayout>
);
} else {
Expand Down
3 changes: 1 addition & 2 deletions src/pages/Chats/RcvdMessage/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@ export const UserImage = styled.img`

export const UsernameText = styled(StyledText)`
cursor: pointer;
margin-bottom: 0.2rem;
`;

export const MessageBox = styled.div`
display: flex;
flex-direction: column;
gap: 0.2rem;
/* max-width: 75%; */
margin-right: 0.5rem;
`;

Expand Down
2 changes: 1 addition & 1 deletion src/pages/Chats/RecentChat/ChatRoomItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const ChatRoomItem: React.FC<ChatRoomData> = ({ id, otherUser, latestMessage })
<StyledText $textTheme={{ style: 'body2-medium' }} color={theme.colors.text.primary}>
{otherUser?.nickname || '알수없음'}
</StyledText>
<LatestMessage $textTheme={{ style: 'caption2-regular' }} color={theme.colors.text.primary}>
<LatestMessage $textTheme={{ style: 'caption1-regular' }} color={theme.colors.text.primary}>
{latestMessage.content}
</LatestMessage>
</LeftBox>
Expand Down
6 changes: 4 additions & 2 deletions src/pages/Chats/RecentChat/MatchingRoomItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import theme from '@styles/theme';

import { LatestMatchingData } from '@apis/matching/dto';

import defaultProfile from '@assets/default/defaultProfile.svg';

import { StyledText } from '@components/Text/StyledText';

import { UserImage, MatchingRoomLayout, LeftBox, RightBox, LatestMessage } from './styles';
Expand Down Expand Up @@ -40,12 +42,12 @@ const MatchingRoomItem: React.FC<Partial<LatestMatchingData>> = ({ requestStatus

return (
<MatchingRoomLayout onClick={handleMatchingRoomClick}>
<UserImage src={'오딩이 프로필 이미지'} alt="user" />
<UserImage src={defaultProfile} alt="user" />
<LeftBox>
<StyledText $textTheme={{ style: 'body2-medium' }} color={theme.colors.text.primary}>
오딩이
</StyledText>
<LatestMessage $textTheme={{ style: 'caption2-regular' }} color={theme.colors.text.primary}>
<LatestMessage $textTheme={{ style: 'caption1-regular' }} color={theme.colors.text.primary}>
{requestStatus === 'pending' ? '얘가 너 소개받고 싶대' : '매칭이 들어오면 오딩이가 알려줄게!'}
</LatestMessage>
</LeftBox>
Expand Down
Loading