Skip to content

Commit

Permalink
#116 fix : v2 2nd sprint fix
Browse files Browse the repository at this point in the history
  • Loading branch information
sinamong0620 committed Nov 28, 2024
1 parent 024bc3d commit 5346804
Show file tree
Hide file tree
Showing 28 changed files with 527 additions and 74 deletions.
10 changes: 9 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useEffect, useState } from 'react';
import { Routes, Route } from 'react-router-dom';
// import MainPage from './pages/MainPage';
import LoginPage from './pages/LoginPage';
import MyPage from './pages/MyPage';
import CreateBoard from './pages/CreateBoardPage';
Expand Down Expand Up @@ -36,6 +35,7 @@ import { useSSE } from './hooks/useSSE';
import FriendsPage from './pages/FriendsPage/FriendsPage';
import FriendsSearchPage from './pages/FriendsSearchPage/FriendsSearchPage';
import RecommendedFriendsPage from './pages/RecommendedFriendsPage/RecommendedFriendsPage';
import FriendPage from './pages/FriendPage';

const queryClient = new QueryClient();

Expand Down Expand Up @@ -196,6 +196,14 @@ const App = () => {
</ProtectedRoute>
}
/>
<Route
path="/friendpage/:id"
element={
<ProtectedRoute>
<FriendPage />
</ProtectedRoute>
}
/>
<Route
path="/mypage/edit"
element={
Expand Down
2 changes: 0 additions & 2 deletions src/api/ChallengeApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ export const getSearchChallenge = async (
export const getChallengeDetail = async (challengeId: string): Promise<Challenge | null> => {
try {
const response = await axiosInstance.get(`/challenges/${challengeId}`);
// console.log(response.data.data);

return response.data.data;
} catch (error) {
console.error('Error fetching data:', error);
Expand Down
37 changes: 34 additions & 3 deletions src/api/MyPageApi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { NotificationResponse, ProfileInfo, ReturnData } from '../types/MyPage';
import {
FriendBlock,
FrinedProfile,
NotificationResponse,
ProfileInfo,
ReturnData,
} from '../types/MyPage';
import { axiosInstance } from '../utils/apiConfig';

// * 마이페이지 프로필 조회
Expand All @@ -20,13 +26,28 @@ export const fetchBlockData = async (
const res = await axiosInstance.get(
`/members/mypage/dashboard-challenges?requestEmail=${email}&page=${pageNum}&size=6`
);
console.log(res);
return res.data as ReturnData;
} catch (error) {
console.error('Error fetching data:', error);
}
};

// * 친구 마이페이지에서 개인,팀,챌린지 블록 데이터 받아오기
export const fetchFriendBlockData = async (
pageNum: number,
friendId: string
): Promise<FriendBlock | undefined> => {
try {
const res = await axiosInstance.get(
`/members/mypage/${friendId}/dashboard-challenges?page=${pageNum}&size=6`
);
console.log(res.data.data);
return res.data.data as FriendBlock;
} catch (error) {
console.error('Error fetching data:', error);
}
};

// * 알람 리스트 전체 조회
export const getAlarmList = async (): Promise<NotificationResponse | undefined> => {
try {
Expand Down Expand Up @@ -63,8 +84,18 @@ export const updateAlarmIsRead = async () => {
export const acceptFriendAlarm = async (followId: string) => {
try {
const response = await axiosInstance.post(`/member/follow/accept/${followId}`);
console.log(response);
} catch (error) {
console.error('Error fetching data :', error);
throw error;
}
};

// * 친구 마이페이지 프로필 조회
export const friendProfile = async (friendId: string) => {
try {
const res = await axiosInstance.get(`/members/mypage/${friendId}`);
return res.data;
} catch (error) {
console.error('Error fetching data:', error);
}
};
8 changes: 8 additions & 0 deletions src/api/PersonalBlockApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,11 @@ export const restoreBlockFunc = async (blockId: string) => {
console.error('Error fetching data:', error);
}
};

export const entireDeleteBlock = async (dashboardId: string) => {
try {
await axiosInstance.delete(`/blocks/permanent?dashboardId=${dashboardId}`);
} catch (error) {
console.error('Error fetching data:', error);
}
};
29 changes: 19 additions & 10 deletions src/components/AlarmBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import { customErrToast } from '../utils/customErrorToast';
import { useAtom } from 'jotai';
import { navbarUpdateTriggerAtom } from '../contexts/atoms';
import { acceptFriendAlarm } from '../api/MyPageApi';
import axios from 'axios';

type Props = {
message: string;
isRead: boolean;
};
const AlarmBlock = ({ message, isRead }: Props) => {
console.log(message);
let modifiedMessage = '';
let followerIdMatch: string = '';

Expand Down Expand Up @@ -44,19 +46,22 @@ const AlarmBlock = ({ message, isRead }: Props) => {
const index = message.indexOf('챌린지 블록이 생성되었습니다');
nameMatch = message.slice(0, index).trim();
description = '챌린지 블록이 생성됐어요';
} else if (message.includes('친구 신청을 보냈습니다.')) {
nameMatch = `${message.split('님')[0]}님이`;
} else if (message.includes('친구 추가 요청')) {
nameMatch = `${message.split(':')[1].split('님')[0].trim()}님이`;
description = `친구 요청을 보냈어요!`;
} else if (message.includes('친구 추가 수락')) {
nameMatch = `${message.split(':')[1].split('님')[0].trim()}님이`;
description = `친구 요청을 수락했어요!`;
} else {
const index = message.indexOf('님');
nameMatch = `반가워요! ${message.slice(message.indexOf(' ') + 5, index)}님이`;
description = `챌린지에 참여했어요`;
}
const numberMatch = modifiedMessage.match(/\d+$/);

const name = nameMatch ? nameMatch : null;
const dashboard = dashboardMatch ? dashboardMatch[0] : null;
const number = numberMatch ? numberMatch[0] : '';

const [, setUpdate] = useAtom(navbarUpdateTriggerAtom);

const onAcceptHandler = async () => {
Expand All @@ -68,8 +73,16 @@ const AlarmBlock = ({ message, isRead }: Props) => {
};

const onAcceptFriend = async () => {
await acceptFriendAlarm(followerIdMatch);
customErrToast(`${message.split('님')[0]}님의 친구요청을 수락했어요!`);
try {
const response = await acceptFriendAlarm(followerIdMatch);
customErrToast(`${message.split('님')[0]}님의 친구요청을 수락했어요!`);
} catch (error) {
if (axios.isAxiosError(error)) {
if (error.response?.status === 403) {
customErrToast(`친구요청을 이미 수락했어요!`);
}
}
}
};

return (
Expand All @@ -80,11 +93,7 @@ const AlarmBlock = ({ message, isRead }: Props) => {
<p>{description}</p>
</UserInfoContainer>
{number !== '' ? <button onClick={onAcceptHandler}>수락</button> : ''}
{message.includes('친구 신청을 보냈습니다.') === true ? (
<button onClick={onAcceptFriend}>수락</button>
) : (
''
)}
{followerIdMatch !== '' ? <button onClick={onAcceptFriend}>수락</button> : ''}
</Flex>
</AlarmContainer>
);
Expand Down
4 changes: 0 additions & 4 deletions src/components/DashBoardLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { Helmet } from 'react-helmet-async';
import Navbar from './Navbar';
import Header from './Header';
import * as S from '../styles/MainPageStyled';
import { DeleteButton } from '@blocknote/react';
import { DragDropContext } from 'react-beautiful-dnd';

interface DashBoardLayoutProps {
children: React.ReactNode; // children의 타입을 명시합니다.
Expand Down
71 changes: 65 additions & 6 deletions src/components/DeleteButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,28 @@ import deleteicon from '../img/delete2.png';
import * as S from '../styles/MainPageStyled';
import { Droppable } from 'react-beautiful-dnd';
import Block from './Block';
import { BlockListResDto, DeletedBlockList } from '../types/PersonalBlock';
import { BlockListResDto } from '../types/PersonalBlock';
import Flex from './Flex';
import useModal from '../hooks/useModal';
import CustomModal from './CustomModal';
import { useLocation } from 'react-router-dom';
import { entireDeleteBlock } from '../api/PersonalBlockApi';
import { useAtom } from 'jotai';
import { fetchTriggerAtom } from '../contexts/atoms';

interface Props {
id: string;
list: BlockListResDto[];
removeValue: boolean;
}
const DeleteButton = ({ id, list, removeValue }: Props) => {
const [isHovering, setIsHovering] = useState(false);
const { isModalOpen, openModal, handleYesClick, handleNoClick } = useModal();
const [value, setValue] = useState(false);
const [blockId, setBlockId] = useState<string>('');
const [, setBlockId] = useState<string>('');
const [, setFetchTrigger] = useAtom(fetchTriggerAtom);
const location = useLocation();
const dashboardId = location.pathname.split('/')[2];

const onValueFunction = () => {
setValue(value => !value);
Expand All @@ -22,13 +34,35 @@ const DeleteButton = ({ id, list, removeValue }: Props) => {
if (num) setBlockId(num);
};

const onEntireDeleteBlock = async () => {
if (dashboardId) await entireDeleteBlock(dashboardId);
setFetchTrigger(prev => prev + 1); // 상태를 변경하여 MainPage에서 데이터를 다시 불러오도록 트리거
};
const onDeleteHandler = () => {
openModal('yes', onEntireDeleteBlock);
};
const onDragEnter = () => {
setIsHovering(true);
console.log('아니 되는거 맞음?');
};

const onDragLeave = () => {
setIsHovering(false);
};
useEffect(() => {
handleNoClick();
}, [location]);

return (
<S.DeleteContainer>
{value && (
<Droppable droppableId={id}>
{provided => (
<S.DeleteDiv ref={provided.innerRef} className="container" {...provided.droppableProps}>
<h1>휴지통</h1>
<Flex alignItems="center" margin="0 0 1rem 0" justifyContent="space-between">
<h1>휴지통</h1>
<button onClick={onDeleteHandler}>전체 삭제</button>
</Flex>
<S.BoxContainer>
{list.map(
(
Expand Down Expand Up @@ -60,9 +94,34 @@ const DeleteButton = ({ id, list, removeValue }: Props) => {
)}
</Droppable>
)}
<S.DeleteIconWrapper onClick={onValueFunction}>
<img src={deleteicon} alt="휴지통아이콘" />
</S.DeleteIconWrapper>
<Droppable droppableId="icon">
{(provided, snapshot) => (
<div>
<S.DeleteIconWrapper
onClick={onValueFunction}
onDragEnter={onDragEnter}
onDragLeave={onDragLeave}
style={{
backgroundColor: snapshot.isDraggingOver ? '#6a6a6a' : '#f4f4f4',
width: snapshot.isDraggingOver ? '5rem' : '3.375rem',
height: snapshot.isDraggingOver ? '5rem' : '3.375rem',
transition: 'background-color 0.3s ease, width 0.3s ease, height 0.3s ease',
}}
>
<img ref={provided.innerRef} src={deleteicon} alt="휴지통아이콘" />
</S.DeleteIconWrapper>
{provided.placeholder}
</div>
)}
</Droppable>
{isModalOpen && (
<CustomModal
title="전체삭제를 하시겠습니까?"
subTitle="전체삭제를 하면 블록은 되돌릴 수 없습니다."
onYesClick={handleYesClick}
onNoClick={handleNoClick}
/>
)}
</S.DeleteContainer>
);
};
Expand Down
10 changes: 7 additions & 3 deletions src/components/Friend/Friend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import CustomModal from '../CustomModal';
import useModal from '../../hooks/useModal';
import { useState } from 'react';
import { useDeleteFollow, usePostFollow } from '../../hooks/useFollowersList';
import { useNavigate } from 'react-router-dom';

interface FriendProps {
follower: FollowInfo;
Expand All @@ -15,25 +16,28 @@ const Friend = ({ follower }: FriendProps) => {

const { mutate: followMutate } = usePostFollow(follower.memberId!, follower.name!);
const { mutate: unFollowMutate } = useDeleteFollow(follower.memberId!, follower.name!);
const navigate = useNavigate();

const follow = async () => {
const follow = async (e: React.MouseEvent) => {
followMutate();
e.stopPropagation();
};

const unFollow = async () => {
unFollowMutate();
};

// 친구 삭제를 모달창으로 확인
const submitUnFollow = () => {
const submitUnFollow = (e: React.MouseEvent) => {
setIsDelModalOpen(true);
const handleModalClose = () => setIsDelModalOpen(false);
openModal('yes', unFollow, handleModalClose);
e.stopPropagation();
};

return (
<>
<S.FriendLayout>
<S.FriendLayout onClick={() => navigate(`/friendpage/${follower.memberId}`)}>
<S.ProfileImageWrapper src={follower.profileImage} />
<S.FriendUserWrapper>
<p className="name">{follower.name}</p>
Expand Down
1 change: 1 addition & 0 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const Navbar = () => {
queryKey: ['userinfo'],
queryFn: userInfoApi,
});

const [nickname, setNickname] = useAtom(nicknameAtom);
const [update] = useAtom(navbarUpdateTriggerAtom);

Expand Down
Loading

0 comments on commit 5346804

Please sign in to comment.