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

#116 fix : v2 2nd sprint fix #117

Merged
merged 1 commit into from
Nov 28, 2024
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
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