-
Notifications
You must be signed in to change notification settings - Fork 1
Api(client): Dashboard article 전체 조회 API 연결 #82
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
Changes from all commits
e85bb00
ab903be
ff723d9
d255a18
1db4d82
a7ef5cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import apiRequest from '@shared/apis/setting/axiosInstance'; | ||
|
|
||
| export const getBookmarkArticles = async (page: number, size: number) => { | ||
| const { data } = await apiRequest.get( | ||
| `/api/v1/articles?page=${page}&size=${size}` | ||
| ); | ||
| return data.data; | ||
| }; | ||
|
|
||
| export const getBookmarkUnreadArticles = async (page: number, size: number) => { | ||
| const { data } = await apiRequest.get( | ||
| `/api/v1/articles/unread?page=${page}&size=${size}` | ||
| ); | ||
| return data.data; | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import { useQuery, UseQueryResult } from '@tanstack/react-query'; | ||
| import { AxiosError } from 'axios'; | ||
| import { getBookmarkArticles, getBookmarkUnreadArticles } from './axios'; | ||
| import { | ||
| BookmarkArticleResponse, | ||
| UnreadBookmarkArticleResponse, | ||
| } from '@pages/myBookmark/types/api'; | ||
|
|
||
| export const useGetBookmarkArticles = ( | ||
| page: number, | ||
| size: number | ||
| ): UseQueryResult<BookmarkArticleResponse, AxiosError> => { | ||
| return useQuery({ | ||
| queryKey: ['bookmarkReadArticles', page, size], | ||
| queryFn: () => getBookmarkArticles(page, size), | ||
| }); | ||
| }; | ||
|
|
||
| export const useGetBookmarkUnreadArticles = ( | ||
| page: number, | ||
| size: number | ||
| ): UseQueryResult<UnreadBookmarkArticleResponse, AxiosError> => { | ||
| return useQuery({ | ||
| queryKey: ['bookmarkUnreadArticles', page, size], | ||
| queryFn: () => getBookmarkUnreadArticles(page, size), | ||
| }); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| interface BookmarkArticle { | ||
| articleId: number; | ||
| url: string; | ||
| memo: string; | ||
| createdAt: string; | ||
| isRead: boolean; | ||
| } | ||
|
|
||
| // 북마크 전체 조회 | ||
| export interface BookmarkArticleResponse { | ||
| totalArticle: number; | ||
| totalUnreadArticle: number; | ||
| articles: BookmarkArticle[]; | ||
| } | ||
|
|
||
| // 북마크 안 읽음 조회 | ||
| export interface UnreadBookmarkArticleResponse { | ||
| totalUnreadArticle: number; | ||
| articles: BookmarkArticle[]; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,42 +1,51 @@ | ||
| import { Badge, Card } from '@pinback/design-system/ui'; | ||
| import { useState } from 'react'; | ||
| import { REMIND_MOCK_DATA } from './constants'; | ||
| import { useGetRemindArticles } from './apis/queries'; | ||
| import { formatLocalDateTime } from '@shared/utils/formatDateTime'; | ||
|
|
||
| const Remind = () => { | ||
| const [activeBadge, setActiveBadge] = useState('notRead'); | ||
| const formattedDate = formatLocalDateTime(); | ||
|
|
||
| const { data } = useGetRemindArticles( | ||
| formattedDate, | ||
| activeBadge === 'read', | ||
| 1, | ||
| 10 | ||
| ); | ||
|
Comment on lines
+8
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 쿼리 키가 매 렌더마다 바뀌어 재요청/루프 위험: nowDate를 한 번만 고정하세요. formatLocalDateTime()가 초 단위까지 포함한 현재시각 문자열을 매 렌더마다 생성합니다. 이 값이 queryKey에 들어가 재렌더마다 키가 바뀌고, 불필요한 재요청이나 갱신 루프를 유발할 수 있습니다. useRef로 컴포넌트 수명 동안 고정하세요. - import { useState } from 'react';
+ import { useState, useRef } from 'react';
- const formattedDate = formatLocalDateTime();
+ const nowRef = useRef(formatLocalDateTime());
+ const formattedDate = nowRef.current;Also applies to: 2-2 🤖 Prompt for AI Agents |
||
|
|
||
| const handleBadgeClick = (badgeType: string) => { | ||
| setActiveBadge(badgeType); | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="flex flex-col pl-[8rem] py-[5.2rem]"> | ||
| <div className="flex flex-col py-[5.2rem] pl-[8rem]"> | ||
| <p className="head3">리마인드</p> | ||
| <div className="mt-[3rem] flex gap-[2.4rem]"> | ||
| <Badge | ||
| text="안 읽음" | ||
| countNum={5} | ||
| countNum={data?.unreadArticleCount || 0} | ||
| onClick={() => handleBadgeClick('notRead')} | ||
| isActive={activeBadge === 'notRead'} | ||
| /> | ||
| <Badge | ||
| text="읽음" | ||
| countNum={10} | ||
| countNum={data?.readArticleCount || 0} | ||
| onClick={() => handleBadgeClick('read')} | ||
| isActive={activeBadge === 'read'} | ||
| /> | ||
| </div> | ||
|
|
||
| <div className="scrollbar-hide mt-[2.6rem] flex flex-wrap gap-[1.6rem] overflow-y-auto scroll-smooth max-w-[104rem]"> | ||
| <div className="scrollbar-hide mt-[2.6rem] flex max-w-[104rem] flex-wrap gap-[1.6rem] overflow-y-auto scroll-smooth"> | ||
| {/* TODO: API 연결 후 수정 */} | ||
| {REMIND_MOCK_DATA.map((data) => ( | ||
| {data?.articles?.map((article) => ( | ||
| <Card | ||
| key={data.id} | ||
| key={article.articleId} | ||
| type="remind" | ||
| title={data.title} | ||
| content={data.content} | ||
| timeRemaining={data.timeRemaining} | ||
| category={data.category} | ||
| title={article.url} | ||
| content={article.memo} | ||
| timeRemaining={article.remindAt} | ||
| category={article.category.categoryName} | ||
| /> | ||
| ))} | ||
| </div> | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,13 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import apiRequest from '@shared/apis/setting/axiosInstance'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const getRemindArticles = async ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nowDate: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| readStatus: boolean, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| page: number, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| size: number | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { data } = await apiRequest.get( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `/api/v1/articles/remind?now=${nowDate}&readStatus=${readStatus}&page=${page}&size=${size}` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return data.data; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 쿼리 문자열 직접 합성 지양하고 axios params 사용 + 반환 타입 명시 직접 문자열 합성은 인코딩 이슈(nowDate에 +import { ArticleListResponse } from '@pages/remind/types/api';
+
+type ApiResponse<T> = { data: T };
+
export const getRemindArticles = async (
nowDate: string,
readStatus: boolean,
page: number,
size: number
-) => {
- const { data } = await apiRequest.get(
- `/api/v1/articles/remind?now=${nowDate}&readStatus=${readStatus}&page=${page}&size=${size}`
- );
+) : Promise<ArticleListResponse> => {
+ const { data } = await apiRequest.get<ApiResponse<ArticleListResponse>>(
+ '/api/v1/articles/remind',
+ { params: { now: nowDate, readStatus, page, size } }
+ );
return data.data;
};📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import { useQuery, UseQueryResult } from '@tanstack/react-query'; | ||
| import { AxiosError } from 'axios'; | ||
| import { getRemindArticles } from './axios'; | ||
| import { ArticleListResponse } from '@pages/remind/types/api'; | ||
|
|
||
| export const useGetRemindArticles = ( | ||
| nowDate: string, | ||
| readStatus: boolean, | ||
| page: number, | ||
| size: number | ||
| ): UseQueryResult<ArticleListResponse, AxiosError> => { | ||
| return useQuery({ | ||
| queryKey: ['remindArticles', nowDate, readStatus, page, size], | ||
| queryFn: () => getRemindArticles(nowDate, readStatus, page, size), | ||
| }); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // 리마인드 전체 조회 | ||
| interface Category { | ||
| categoryId: number; | ||
| categoryName: string; | ||
| categoryColor: string; | ||
| } | ||
|
Comment on lines
+2
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 공유 Category 타입과의 혼동 방지(이름 충돌 회피)
-interface Category {
+interface RemindCategory {
categoryId: number;
categoryName: string;
categoryColor: string;
}그리고 Line 15의 참조를 함께 갱신하세요: - category: Category;
+ category: RemindCategory;🤖 Prompt for AI Agents |
||
|
|
||
| interface ArticleWithCategory { | ||
| articleId: number; | ||
| url: string; | ||
| memo: string; | ||
| createdAt: string; | ||
| isRead: boolean; | ||
| remindAt: string; | ||
| category: Category; | ||
| } | ||
|
|
||
| export interface ArticleListResponse { | ||
| readArticleCount: number; | ||
| unreadArticleCount: number; | ||
| articles: ArticleWithCategory[]; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
axios params 사용 및 반환 타입 명시
동일하게 params 사용과 제네릭으로 안전성을 높여주세요.
📝 Committable suggestion
🤖 Prompt for AI Agents