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

[ Feature/dev 53 ] 워크북 card list 불러오기 mock api 연결 및 테스트 #130

Merged
merged 55 commits into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
88f2778
feat : workbook list mock api
Happhee Jul 28, 2024
d82a959
Merge branch 'develop' of github.com-A:YAPP-Github/24th-Web-Team-1-FE…
Happhee Jul 31, 2024
342a3fa
feat : category and workbooks and subscription list mock api
Happhee Aug 1, 2024
209325f
bugfix : spec out body data
Happhee Aug 1, 2024
1bbe34c
feat : workbook list and subscription workbook list query options
Happhee Aug 1, 2024
5be5bff
feat : workbooks with subscription route path
Happhee Aug 1, 2024
7744c66
refactor : on click link copy utils
Happhee Aug 1, 2024
5ba7ea7
feat : mock api response workbook subscriptions
Happhee Aug 1, 2024
53739da
bugfix : change category type to client and server
Happhee Aug 1, 2024
6efafe3
feat : workbook card type and badge component in model
Happhee Aug 1, 2024
48f8b7a
feat : categoy with model
Happhee Aug 2, 2024
196d941
bugfix : category with workbookcardlist
Happhee Aug 2, 2024
5599d8e
feat : category field with category model
Happhee Aug 2, 2024
2737f1c
test : get button title , get badgeInfo get workbook card type
Happhee Aug 2, 2024
3788db5
feat : get article id with learn type
Happhee Aug 2, 2024
4cde9b5
feat : article Id in workbook client type
Happhee Aug 2, 2024
8b648f9
feat : custom hook with workbook card bottom button handler
Happhee Aug 2, 2024
6a1ecdd
feat : image wrapper , cardbadge workbook card component
Happhee Aug 2, 2024
45cfbd6
refactor : workbook subscribe hook
Happhee Aug 2, 2024
c593835
feat : useQueries workbook list in main workbook page
Happhee Aug 2, 2024
60654de
bugfix : category list loading state
Happhee Aug 2, 2024
28aa622
style : remove title margin left
Happhee Aug 2, 2024
5db3d98
feat : id, badge , bottom button with click event
Happhee Aug 2, 2024
c79cfd8
test : workbook card wrapper
Happhee Aug 2, 2024
4379640
style : article list in main page
Happhee Aug 2, 2024
fc03bb3
feat : articels category mock api
Happhee Aug 2, 2024
30a970c
test : fix data length
Happhee Aug 2, 2024
371d50d
init : react intersection observer
Happhee Aug 2, 2024
4e171d1
feat : articles with category api
Happhee Aug 2, 2024
863ac2b
feat : articles with category infinite query
Happhee Aug 2, 2024
fba8ac9
feat : articles fetch infinite query params type
Happhee Aug 3, 2024
8294cf0
bugfix : data fetch with scroll
Happhee Aug 3, 2024
3594a15
feat : article card detail root wrapper
Happhee Aug 3, 2024
0edc8d3
bugfix : query params only category code
Happhee Aug 3, 2024
a912e41
feat : remove tag in article content text
Happhee Aug 3, 2024
3d14f78
docs : remove artilce with workbook list component
Happhee Aug 3, 2024
2452500
docs : skeleton few logo
Happhee Aug 3, 2024
a9db4b1
bugfix : image domain config
Happhee Aug 3, 2024
286aafa
docs : remove temp image url
Happhee Aug 3, 2024
d871471
feat : category tab skeleton
Happhee Aug 3, 2024
49ccc23
feat : article card skeleton in component
Happhee Aug 3, 2024
eedd68d
feat : workbookcard skeleton in workbookcard component
Happhee Aug 3, 2024
5484a9e
docs : remove defalut image url
Happhee Aug 3, 2024
e975e50
bugfix : move key props data
Happhee Aug 3, 2024
18d3511
feat : category constant
Happhee Aug 3, 2024
5668754
bugfix : category fetch code
Happhee Aug 3, 2024
13d140f
feat : article card WithWorkbookList component
Happhee Aug 3, 2024
e2525c0
teat : fix test data
Happhee Aug 3, 2024
771c189
test : bugfix mock use toast
Happhee Aug 3, 2024
ed65336
feat : getWithWorkbookList in articlecardmodel
Happhee Aug 3, 2024
a7baf21
Merge pull request #133 from YAPP-Github/feature/DEV-70
Happhee Aug 3, 2024
052c28a
Merge pull request #131 from YAPP-Github/feature/DEV-52
Happhee Aug 3, 2024
155d304
Merge branch 'develop' into feature/DEV-53
Happhee Aug 3, 2024
e7a926f
bugfix : category api controll
Happhee Aug 3, 2024
9da3b93
bugfix : image domain
Happhee Aug 3, 2024
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
6 changes: 6 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ const nextConfig = {
"oopy.lazyrockets.com",
"eehhqckznniu25210545.cdn.ntruss.com",
"storage.mrblog.net",
"d3ex4vlh373syu.cloudfront.net",
"www.fig1.kr",
"cdn.maily.so",
"maily.so",
"pension.inmostadvisor.com",
"localhost",
],
},
webpack: (config, context) => {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"react": "^18",
"react-dom": "^18",
"react-hook-form": "^7.51.5",
"react-intersection-observer": "^9.13.0",
"react-lottie-player": "^2.0.0",
"shadcn-ui": "^0.8.0",
"tailwind-merge": "^2.3.0",
Expand Down
16 changes: 16 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions public/assets/icon/skeletonFewLogo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions src/common/hooks/useSusbscribeWorkbook.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { toast } from "@shared/components/ui/use-toast";
import { SUBSCRIBE_USER_ACTIONS } from "@subscription/constants/subscribe";
import { subscribeWorkbookOptions } from "@subscription/remotes/postSubscriptionQueryOptions";
import { useMutation } from "@tanstack/react-query";

export default function useSusbscribeWorkbook() {
const { mutate: subscribeWorkbook } = useMutation(subscribeWorkbookOptions());
const postSubscribeWorkbook = ({
workbookId,
handleSucess,
}: {
workbookId: string;
handleSucess?: () => void;
}) => {
try {
subscribeWorkbook(
{ workbookId },
{
onSuccess: () => {
toast({
title: SUBSCRIBE_USER_ACTIONS.SUBSCRIBE_SUCCESS,
});
if (handleSucess) handleSucess();
},
onError: (error) => {
let errorMessage = SUBSCRIBE_USER_ACTIONS.SUBSCRIBE_FAIL;
if (error && error.data && error.data.message) {
errorMessage = error.data.message || errorMessage;
}
toast({
title: errorMessage,
});
},
},
);
} catch (error) {
console.error("catch error", error);

toast({
title: SUBSCRIBE_USER_ACTIONS.SUBSCRIBE_FAIL,
});
}
};
return { postSubscribeWorkbook };
}
8 changes: 4 additions & 4 deletions src/common/types/category.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아직 client info 하고 server info 하고 똑같은 상태인가용?? (둘 다 code, name 이길래용!!)

Copy link
Collaborator Author

@Happhee Happhee Aug 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵ㅂ! 추후에 변경될수있어서 모델 만든겁니다!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일단 서버랑 클라가 같더라도 만드는게 좋다고 생각해요

Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export type CategoryInfo = {
export type CategoryServerInfo = {
code: number;
name: string;
};

export type CategoryInfoList = {
categories: CategoryInfo[];
export type CategoryClientInfo = {
code: number;
name: string;
};
6 changes: 4 additions & 2 deletions src/main/components/ArticleCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client";
import { ArticleClientInfo } from "@main/types/article";
import { useRouter } from "next/navigation";
import { title } from "process";
import ArticleCardDetail from "../ArticleCardDetail";

export default function ArticleCard({
Expand All @@ -10,6 +9,7 @@ export default function ArticleCard({
thumbnail,
viewCount,
category,
title,
content,
withWorkbookList,
}: ArticleClientInfo) {
Expand All @@ -28,8 +28,10 @@ export default function ArticleCard({
<ArticleCardDetail.Title title={title} />
<ArticleCardDetail.Description content={content} />
<ArticleCardDetail.Thumbnail thumbnail={thumbnail} />
<ArticleCardDetail.WithWorkbookList
withWorkbookList={withWorkbookList}
/>
</article>
<ArticleCardDetail.WithWorkbookList withWorkbookList={withWorkbookList} />
</section>
);
}
50 changes: 31 additions & 19 deletions src/main/components/ArticleCardDetail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import Link from "next/link";
import EyeIcon from "public/assets/icon/eye.svg";
import { ReactNode } from "react";

const RootComponentWrapper = ({ children }: { children: ReactNode }) => (
<section className="border-b-[0.5px] border-text-gray2 px-[20px] py-[26px]">
{children}
</section>
);
const TopComponentWrapper = ({ children }: { children: ReactNode }) => (
<div className="flex justify-between pb-[6px]">{children}</div>
);
Expand Down Expand Up @@ -36,7 +41,9 @@ const CategoryTag = ({ category }: Pick<ArticleClientInfo, "category">) => (

const Title = ({ title }: Pick<ArticleClientInfo, "title">) => (
<header className="mb-[4px]">
<h3 className="h3-bold text-text-gary1 text-ellipsis">{title}</h3>
<h3 className="h3-bold text-text-gary1 line-clamp-1 text-ellipsis">
{title}
</h3>
</header>
);
const Description = ({ content }: Pick<ArticleClientInfo, "content">) => (
Expand All @@ -58,27 +65,32 @@ const Thumbnail = ({ thumbnail }: Pick<ArticleClientInfo, "thumbnail">) => (
const WithWorkbookList = ({
withWorkbookList,
}: Pick<ArticleClientInfo, "withWorkbookList">) => (
<footer className="grid grid-cols-[130px_1fr] items-center py-[14px]">
<span className="sub3-medium text-text-gray1">
이 아티클이 포함된 학습지
</span>
<ul className="flex justify-end gap-[4px]">
{withWorkbookList.map(({ id, title }) => (
<li
key={`with-workbook-${id}`}
className={cn(
"sub3-semibold bg-background1 px-[5px] py-[2px] text-text-gray1",
"line-clamp-1 rounded border-[0.5px] border-text-gray2",
)}
>
<Link href={`/workbook/${id}`}>{title}</Link>
</li>
))}
</ul>
</footer>
<>
{withWorkbookList && (
<footer className="grid grid-cols-[130px_1fr] items-center py-[14px]">
<span className="sub3-medium text-text-gray1">
이 아티클이 포함된 학습지
</span>
<ul className="flex justify-end gap-[4px]">
{withWorkbookList.map(({ id, title }) => (
<li
key={`with-workbook-${id}`}
className={cn(
"sub3-semibold bg-background1 px-[5px] py-[2px] text-text-gray1",
"line-clamp-1 rounded border-[0.5px] border-text-gray2",
)}
>
<Link href={`/workbook/${id}`}>{title}</Link>
</li>
))}
</ul>
</footer>
)}
</>
);

const ArticleCardDetail = {
RootComponentWrapper,
TopComponentWrapper,
WriterProfile,
ViewCount,
Expand Down
47 changes: 47 additions & 0 deletions src/main/components/ArticleCardDetailSkeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Skeleton } from "@shared/components/ui/skeleton";
import SkeletonFewLogo from "public/assets/icon/skeletonFewLogo.svg";
const WriterProfileSkeleton = () => {
return <Skeleton className="h-[30px] w-[30px] rounded-full" />;
};
const ViewCountSkeleton = () => {
return (
<div className="flex items-center gap-[5px]">
<Skeleton className="h-[9px] w-[40px]" />
</div>
);
};
const CategoryTagSkeleton = () => {
return <Skeleton className="mb-[8px] h-[18px] w-[20%] py-[2px]" />;
};
const TitleSkeleton = () => {
return <Skeleton className="mb-[4px] h-[27px] w-[30%] bg-text-gray3" />;
};

const DescriptionSkeleton = () => {
const skeletonItems = new Array(4).fill(null);
return (
<div className="mb-[20px] flex flex-col gap-[3px]">
{skeletonItems.map((_, index) => (
<Skeleton key={index} className="h-[23px] w-full bg-text-gray3" />
))}
</div>
);
};

const ThumbnailSkeleton = () => {
return (
<Skeleton className="flex h-[170px] w-full items-center justify-center rounded bg-[#C4C4C4]">
<SkeletonFewLogo width={93} height={93} />
</Skeleton>
);
};

const ArticleCardDetailSkeleton = {
WriterProfileSkeleton,
ViewCountSkeleton,
CategoryTagSkeleton,
TitleSkeleton,
DescriptionSkeleton,
ThumbnailSkeleton,
};
export default ArticleCardDetailSkeleton;
99 changes: 32 additions & 67 deletions src/main/components/ArticleCardList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,40 @@
import { CategoryInfo } from "@common/types/category";
import ArticleCardModel from "@main/models/ArticleCardModel";
import { ArticleServerInfo } from "@main/types/article";
import { CategoryClientInfo } from "@common/types/category";
import { ENTIRE_CATEGORY } from "@main/constants";
import { getArticlesWithCategoryInfiniteQueryOptions } from "@main/remotes/getArticlesWithCategoryInfiniteQueryOptions";
import { useInfiniteQuery } from "@tanstack/react-query";
import { useEffect } from "react";
import { useInView } from "react-intersection-observer";
import ArticleCard from "../ArticleCard";
import ArticleCardListSkeleton from "../ArticleCardListSkeleton";
export default function ArticleCardList({ code }: Partial<CategoryClientInfo>) {
const { data, fetchNextPage, isLoading } = useInfiniteQuery({
...getArticlesWithCategoryInfiniteQueryOptions({
code: code !== undefined ? code : ENTIRE_CATEGORY,
}),
});
const { ref, inView } = useInView();

const data: ArticleServerInfo[] = [
{
id: 1,
writer: {
id: 1,
name: "안나포",
url: "https://storage.mrblog.net/files/dosi_draw/a3NgiDGW2H3NhsYp1Qp3RuWNzUx9sg8L2yyooYqF.jpg",
},
title: "ETF(상장 지수 펀드)란? 모르면 손해라고?",
content:
"오늘날 전동 킥보드의 인기는 누가 뭐래도 전동 킥보드 공유 서비스가 등장하면서부터입니다. 공유 서비스가 등장하기 이전 전동 킥보드는 주로 레저용으로 사용되다가 공유형 전동킥보드 서비스가 등장하면서 이동 수단으로 사용되기 시작합니다.Y",
problemIds: [1, 2, 3],
category: "경제",
createdAt: "2024-07-25T14:32:27.310368",
views: 1,
mainImageUrl:
"https://storage.mrblog.net/files/dosi_draw/a3NgiDGW2H3NhsYp1Qp3RuWNzUx9sg8L2yyooYqF.jpg",

includedWorkbooks: [
{
id: 1,
title: "사소한 것들의 역사",
},
{
id: 2,
title: "인모스트 경제레터",
},
],
},
{
id: 2,
writer: {
id: 1,
name: "몰티즈",
url: "https://storage.mrblog.net/files/dosi_draw/a3NgiDGW2H3NhsYp1Qp3RuWNzUx9sg8L2yyooYqF.jpg",
useEffect(
function fetchNextArticles() {
if (inView && !data?.isLast) {
fetchNextPage();
}
},
mainImageUrl:
"https://storage.mrblog.net/files/dosi_draw/a3NgiDGW2H3NhsYp1Qp3RuWNzUx9sg8L2yyooYqF.jpg",
title: "ETF(상장 지수 펀드)란? 모르면 손해라고?",
content: "ECONOMY",
problemIds: [1, 2, 3],
category: "경제",
createdAt: "2024-07-25T14:32:27.310368",
views: 1,
includedWorkbooks: [
{
id: 1,
title: "사소한 것들의 역사",
},
{
id: 2,
title: "인모스트 경제레터",
},
],
},
];

export default function ArticleCardList({ code, name }: CategoryInfo) {
const articleCardModel = new ArticleCardModel({
initArticleCardServerList: data,
});
[inView],
);
if (isLoading || !data?.articles) {
return <ArticleCardListSkeleton />;
}

const lastIdx = data?.articles.length - 1;
return (
<>
{articleCardModel.articleCardList().map((data, idx) => (
<ArticleCard {...data} key={`article-card-${idx}`} />
<section>
{data?.articles.map((data, idx) => (
<div key={`article-card-${idx}`}>
{idx === lastIdx && <div ref={ref} className="h-[2px]" />}
<ArticleCard {...data} />
</div>
))}
</>
</section>
);
}
23 changes: 23 additions & 0 deletions src/main/components/ArticleCardListSkeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import ArticleCardDetail from "../ArticleCardDetail";
import ArticleCardDetailSkeleton from "../ArticleCardDetailSkeleton";

export default function ArticleCardListSkeleton() {
return (
<>
{new Array(2).fill(null).map((_, idx) => (
<ArticleCardDetail.RootComponentWrapper
key={`article-card-skeleton-${idx}`}
>
<ArticleCardDetail.TopComponentWrapper>
<ArticleCardDetailSkeleton.WriterProfileSkeleton />
<ArticleCardDetailSkeleton.ViewCountSkeleton />
</ArticleCardDetail.TopComponentWrapper>
<ArticleCardDetailSkeleton.CategoryTagSkeleton />
<ArticleCardDetailSkeleton.TitleSkeleton />
<ArticleCardDetailSkeleton.DescriptionSkeleton />
<ArticleCardDetailSkeleton.ThumbnailSkeleton />
</ArticleCardDetail.RootComponentWrapper>
))}
</>
);
}
Loading
Loading