Skip to content

Commit

Permalink
✨ RetroList API 연결 및 스타일 수정 (#167)
Browse files Browse the repository at this point in the history
* ✨ Feat: RetroList API 연결 및 페이지네이션 구현

* 💄 Design: RetroList 페이지 네이션 스타일 수정 및 기타 css 수정
  • Loading branch information
yeneua authored Apr 17, 2024
1 parent 36a960d commit 56c13ac
Show file tree
Hide file tree
Showing 19 changed files with 461 additions and 152 deletions.
5 changes: 3 additions & 2 deletions src/api/@types/@asConst.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
export const Order = {
RECENTLY: 'RECENTLY',
PREVIOUSLY: 'PREVIOUSLY',
NEWEST: 'NEWEST',
OLDEST: 'OLDEST',
} as const;

export const Status = {
ALL: 'ALL',
NOT_STARTED: 'NOT_STARTED',
IN_PROGRESS: 'IN_PROGRESS',
COMPLETED: 'COMPLETED',
Expand Down
36 changes: 31 additions & 5 deletions src/api/@types/Retrospectives.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TRetrospective, TStatus } from './@asConst';
import { TRetrospective, TStatus, TOrder } from './@asConst';

//onlyGet
export interface onlyGetRetrospectiveRequest {
Expand Down Expand Up @@ -26,21 +26,35 @@ export interface RetrospectiveData {
export interface GetRetrospectiveRequest {
page: number;
size: number;
order: keyof TStatus;
order: keyof TOrder;
status: keyof TStatus;
keyword: string;
isBookmarked: boolean;
}

export interface GetRetrospectiveResponseNodes {
// 추가
id: number;
title: string;
userId: number;
teamId: number | null;
templateId: number;
status: keyof TStatus;
isBookmarked: boolean;
thumbnail: string;
startDate: string;
createdDate: string;
updatedDate: string;
}

export interface GetRetrospectiveData {
code: number;
message: string;
data: {
totalCount: number;
nodes: Array<RetrospectiveResponse>;
nodes: Array<GetRetrospectiveResponseNodes>; //RetrospectiveResponse 에서 변경
};
}

//post
export interface PostRetrospectivesRequest {
title: string;
Expand Down Expand Up @@ -85,7 +99,7 @@ export interface RetrospectiveResponse {
id: number;
title: string;
userId: number;
teamId: number;
teamId: number | null;
templateId: number;
status: keyof TStatus;
isBookmarked: boolean;
Expand All @@ -96,10 +110,22 @@ export interface RetrospectiveResponse {
};
}

export interface PatchRetrospectiveRequest {
retrospectiveId: number;
// userId: number;
}

export interface PatchRetrospectiveResponse {
code: number;
message: string;
data: boolean;
}

export interface RetrospectivesClient {
onlyGet(request: onlyGetRetrospectiveRequest): Promise<onlyGetRetrospectiveResponse>;
create(request: PostRetrospectivesRequest): Promise<PostRetrospectivesResponse>;
get(request: GetRetrospectiveRequest): Promise<GetRetrospectiveData>;
delete(request: DeleteRetrospectiveRequest): Promise<void>;
put(request: PutRetrospectiveRequest): Promise<RetrospectiveResponse>;
patch(request: PatchRetrospectiveRequest): Promise<PatchRetrospectiveResponse>;
}
1 change: 0 additions & 1 deletion src/api/__mock__/retrospective.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export const MockRetrospective: RetrospectiveResponse = {
updatedDate: '2024-04-12T04:20:54.835Z',
},
};

export const MockOnlyGetRetrospective: onlyGetRetrospectiveResponse = {
code: 202,
message: 'string',
Expand Down
30 changes: 30 additions & 0 deletions src/api/retrospectivesApi/getRetrospective.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { GetRetrospectiveData, GetRetrospectiveRequest } from '@/api/@types/Retrospectives';
import axiosInstance from '@/api/axiosConfig';

export const queryGetRetrospective = async (requestData: GetRetrospectiveRequest): Promise<GetRetrospectiveData> => {
try {
const { page, size, order, status, keyword, isBookmarked } = requestData;
const params: { [key: string]: any } = {
page,
size,
order,
isBookmarked,
};
if (status !== 'ALL') {
params.status = status;
}
if (keyword !== '') {
params.keyword = keyword;
}

console.log(params);
const response = await axiosInstance.get<GetRetrospectiveData>('/retrospectives', {
params,
});
// console.log('회고 get 성공', response.data);
return response.data;
} catch (error) {
// console.log('회고 get 실패', error);
throw new Error('회고 get 실패');
}
};
17 changes: 17 additions & 0 deletions src/api/retrospectivesApi/patchRetrospective.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { PatchRetrospectiveRequest, PatchRetrospectiveResponse } from '../@types/Retrospectives';
import axiosInstance from '@/api/axiosConfig';

export const patchRetrospective = async (
requestData: PatchRetrospectiveRequest,
): Promise<PatchRetrospectiveResponse> => {
try {
console.log(requestData.retrospectiveId, 'patch 요청');
const response = await axiosInstance.patch<PatchRetrospectiveResponse>(
`/retrospectives/${requestData.retrospectiveId}/bookmark`,
);
console.log('북마크 patch 성공', response.data);
return response.data;
} catch (error) {
throw new Error('북마크 patch 실패');
}
};
3 changes: 3 additions & 0 deletions src/api/services/Retrospectives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,7 @@ export const RetrospectiveService: RetrospectivesClient = {
throw new Error(error as string);
}
},
patch: async (retrospectiveId, ...request) => {
return await mswInstance.patch(`${ROUTE}/${retrospectiveId}/bookmark`, request);
},
};
7 changes: 6 additions & 1 deletion src/components/RetroList/BookmarkButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ import { useState } from 'react';
import BookmarkIcon from '@/assets/BookmarkIcon_Y.png';
import * as S from '@/styles/RetroList/BookmarkButton.styles';

const BookmarkButton: React.FC = () => {
interface BookmarkButtonProps {
handleBookmarkButton: (option: boolean) => void;
}

const BookmarkButton: React.FC<BookmarkButtonProps> = ({ handleBookmarkButton }) => {
const [isBookmarked, setIsBookmarked] = useState<boolean>(false);

const handleBookmark = () => {
setIsBookmarked(!isBookmarked);
handleBookmarkButton(!isBookmarked);
};

return (
Expand Down
89 changes: 77 additions & 12 deletions src/components/RetroList/ContentsList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useRecoilState } from 'recoil';
import { PatchRetrospectiveRequest } from '@/api/@types/Retrospectives';
import { patchRetrospective } from '@/api/retrospectivesApi/patchRetrospective';
import BookmarkIcon_N from '@/assets/BookmarkIcon_N.png';
import BookmarkIcon_Y from '@/assets/BookmarkIcon_Y.png';
import MoreIcon from '@/assets/MoreIcon.png';
Expand All @@ -9,6 +13,9 @@ import ProgressIng from '@/assets/Progress_Ing.png';
import TeamIcon from '@/assets/TeamIcon.png';
import Thumbnail from '@/assets/Thumbnail.png';
import Modal from '@/components/RetroList/Modal';
import UserNickname from '@/components/user/UserNickname';
import { useCustomToast } from '@/hooks/useCustomToast';
import { userNicknameState } from '@/recoil/user/userAtom';
import * as S from '@/styles/RetroList/ContentsList.styles';

interface Content {
Expand All @@ -29,10 +36,28 @@ interface ContentListProps {
data: Content[];
viewMode: string;
searchData: string;
setBookmarkUpdate: React.Dispatch<React.SetStateAction<boolean>>;
}

const ContentList: React.FC<ContentListProps> = ({ data, viewMode, searchData }) => {
const ContentList: React.FC<ContentListProps> = ({ data, viewMode, searchData, setBookmarkUpdate }) => {
// const [contentData, setContentData] = useState<Content[]>(data); 받아온데이터
const [userNickname, setUserNickname] = useRecoilState(userNicknameState);
const [openModalId, setOpenModalId] = useState<number | null>(null);
const toast = useCustomToast();

const handleBookmark = async (itemId: number) => {
try {
const requestData: PatchRetrospectiveRequest = {
retrospectiveId: itemId,
};
const response = await patchRetrospective(requestData);
console.log('북마크 patch 요청 완료', response);
setBookmarkUpdate(prev => !prev);
} catch (error) {
// console.error('북마크 patch 요청 실패:', error);
toast.error(error);
}
};

const openModalForItem = (itemId: number) => {
setOpenModalId(itemId);
Expand All @@ -43,6 +68,8 @@ const ContentList: React.FC<ContentListProps> = ({ data, viewMode, searchData })
};

const filteredData = data.filter(item => item.title.toLowerCase().includes(searchData.toLowerCase()));
console.log('filter', filteredData);
const navigate = useNavigate();

return (
<div>
Expand All @@ -57,16 +84,37 @@ const ContentList: React.FC<ContentListProps> = ({ data, viewMode, searchData })
<S.InfoBox>
<div style={{ display: 'flex', alignItems: 'center' }}>
<S.TeamIcon src={item.teamId ? TeamIcon : PersonalIcon} />
<S.RetroTitle>{item.title}</S.RetroTitle>
<S.RetroTitle onClick={() => navigate(`/section?retrospectiveId=${item.id}&teamId=${item.teamId}`)}>
{item.title}
</S.RetroTitle>
</div>
<div style={{ display: 'flex', alignItems: 'center' }}>
<S.BookmarkIcon src={item.isBookmarked ? BookmarkIcon_Y : BookmarkIcon_N} /> {/* 북마크 patch */}
<S.MoreIcon src={MoreIcon} onClick={() => openModalForItem(item.id)} />
<S.BookmarkIcon
src={item.isBookmarked ? BookmarkIcon_Y : BookmarkIcon_N}
onClick={() => handleBookmark(item.id)}
/>
<S.MoreIcon
src={MoreIcon}
onClick={() => openModalForItem(item.id)}
// onClick={() => {
// if(유저아이디 !== item.id) { // 수정 권한 없을 때(생성자가 아닐 때)
// openModalForItem(item.id)
// } else {
// navigate(`/revise?retrospectiveId=${item.id}&teamId=${item.teamId}`);
// }
// }}
/>
</div>
<S.RetroUser>{item.userId}</S.RetroUser>
<S.RetroUser>
<UserNickname setUserNickname={setUserNickname} /> {/* 생성자 이름(유저 식별 필요) */}
{userNickname}
</S.RetroUser>
<div></div>
<S.RetroDate> {item.createdDate} 수정</S.RetroDate>
{/* 수정하면 수정 시각으로 변경*/}
<S.RetroDate>
{item.updatedDate && item.updatedDate !== item.startDate
? `${item.updatedDate} 수정`
: item.startDate}
</S.RetroDate>
<S.ProgressIcon
src={
item.status === 'NOT_STARTED'
Expand Down Expand Up @@ -96,15 +144,22 @@ const ContentList: React.FC<ContentListProps> = ({ data, viewMode, searchData })
<div>
{filteredData.map(item => (
<S.ItemBox key={item.id}>
<S.ListTitleBox> {item.title}</S.ListTitleBox>
<S.ListTitleBox onClick={() => navigate(`/section?retrospectiveId=${item.id}&teamId=${item.teamId}`)}>
{item.title}
</S.ListTitleBox>
<S.ListUserBox>
<text></text> {/* 생성자 이름 */}
<UserNickname setUserNickname={setUserNickname} /> {/* 생성자이름(유저 식별 필요) */}
{userNickname}
</S.ListUserBox>
<S.ListTimeBox>
{item.createdDate} {/* 수정하면 수정 시각으로 변경*/}
{item.updatedDate && item.updatedDate !== item.startDate ? `${item.updatedDate}` : item.startDate}
</S.ListTimeBox>
<S.ListBookmarkBox>
<S.Icon src={item.isBookmarked ? BookmarkIcon_Y : BookmarkIcon_N} />
<S.Icon
src={item.isBookmarked ? BookmarkIcon_Y : BookmarkIcon_N}
onClick={() => handleBookmark(item.id)}
/>
{/* 북마크 patch */}
</S.ListBookmarkBox>
<S.ListProgressBox>
<S.Icon
Expand All @@ -118,7 +173,17 @@ const ContentList: React.FC<ContentListProps> = ({ data, viewMode, searchData })
/>
</S.ListProgressBox>
<S.ListLinkBox>
<S.MoreIconListView src={MoreIcon} onClick={() => openModalForItem(item.id)} />
<S.MoreIconListView
src={MoreIcon}
onClick={() => openModalForItem(item.id)}
// onClick={() => {
// if(유저아이디 !== item.id) { // 수정 권한 없을 때(생성자가 아닐 때)
// openModalForItem(item.id)
// } else {
// navigate(`/revise?retrospectiveId=${item.id}&teamId=${item.teamId}`);
// }
// }}
/>
<Modal onClose={closeModalForItem} isOpen={openModalId === item.id} />
</S.ListLinkBox>
</S.ItemBox>
Expand Down
17 changes: 0 additions & 17 deletions src/components/RetroList/ControlBar.tsx

This file was deleted.

11 changes: 10 additions & 1 deletion src/components/RetroList/OrderButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import NewestIcon from '@/assets/Newest.png';
import OldestIcon from '@/assets/Oldest.png';
import * as S from '@/styles/RetroList/OrderButton.styles';

const OrderButton: React.FC = () => {
interface OrderButtonProps {
handleOrder: (option: 'NEWEST' | 'OLDEST') => void;
}

const OrderButton: React.FC<OrderButtonProps> = ({ handleOrder }) => {
const order = ['Newest', 'Oldest'];
const [isOpen, setIsOpen] = useState(false);
const [selectedOrder, setSelectedOrder] = useState(order[0]);
Expand All @@ -20,7 +24,12 @@ const OrderButton: React.FC = () => {
};

const handleOptionClick = (option: string) => {
const order: { [key: string]: string } = {
Newest: 'NEWEST',
Oldest: 'OLDEST',
};
setSelectedOrder(option);
handleOrder(order[option] as 'NEWEST' | 'OLDEST');
setIsOpen(false);
};

Expand Down
Loading

0 comments on commit 56c13ac

Please sign in to comment.