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 58 ] 메인 페이지 > 워크북 카드 컴포넌트 ui #126

Merged
merged 13 commits into from
Jul 31, 2024
1 change: 1 addition & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const nextConfig = {
"github.com",
"oopy.lazyrockets.com",
"eehhqckznniu25210545.cdn.ntruss.com",
"storage.mrblog.net",
],
},
webpack: (config, context) => {
Expand Down
6 changes: 6 additions & 0 deletions public/assets/icon/cardFewLogo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@
@apply font-pretendard text-[15px]/[24.75px] font-normal;
}

.body3-bold {
@apply font-pretendard text-[14px]/[23.1px] font-bold;
}
.body3-medium {
@apply font-pretendard text-[14px]/[21px] font-medium;
}
Expand All @@ -119,7 +122,10 @@
@apply font-pretendard text-[16px]/[25.44px] font-medium;
}
.sub3-semibold {
@apply font-pretendard text-[12px] font-semibold
@apply font-pretendard text-[12px] font-semibold;
}
.sub3-medium {
@apply font-pretendard text-[12px]/[18px] font-medium;
}

.scrollbar-hide {
Expand Down
8 changes: 6 additions & 2 deletions src/common/types/category.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
export type CategoryInfo = {
parameterName: string;
displayName: string;
code: number;
name: string;
};

export type CategoryInfoList = {
categories: CategoryInfo[];
};
6 changes: 3 additions & 3 deletions src/main/components/CategoryTabs/category.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ describe("카테고리 리스트 테스트", () => {
await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});
expect(screen.getByText("전체"));
expect(screen.getByText("과학"));
expect(result.current.data?.length === 6).toBeTruthy();
expect(screen.getByText("경제"));
expect(screen.getByText("IT"));
expect(result.current.data?.length === 5).toBeTruthy();
});
});
23 changes: 10 additions & 13 deletions src/main/components/CategoryTabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,32 @@ export default function CategoryTabs({

useEffect(
function setInitCategory() {
if (categoryList) handleCategory(categoryList[0].displayName);
if (categoryList) handleCategory(categoryList[0].name);
},
[categoryList],
);
if (isLoading) return <></>;

if (categoryList)
return (
<Tabs
defaultValue={categoryList[0].displayName}
className="overflow-x-auto"
>
<Tabs defaultValue={categoryList[0].name} className="overflow-x-auto">
<TabsList className="sub2-bold flex gap-3 py-[10px]">
{categoryList.map(({ parameterName, displayName }) => (
{categoryList.map(({ name, code }) => (
<TabsTrigger
key={`${parameterName}-${type}`}
value={displayName}
key={`${code}-${type}`}
value={name}
className={cn(
category !== displayName && "text-text-gray2",
category !== name && "text-text-gray2",
"box-border flex flex-col gap-[10px] pt-[10px]",
"min-w-[48px]",
)}
name={displayName}
onClick={() => handleCategory(displayName)}
name={name}
onClick={() => handleCategory(name)}
>
<span className="flex w-full items-center justify-center">
{displayName}
{name}
</span>
{category === displayName && (
{category === name && (
<span className="w-full border-b-2 border-black"></span>
)}
</TabsTrigger>
Expand Down
26 changes: 26 additions & 0 deletions src/main/components/WorkbookCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { WorkbookClientInfo } from "@main/types/workbook";
import WorkbookCardDetail from "../WorkbookCardDetail";

export default function WorkbookCard({
mainImageUrl,
metaComponent,
title,
writers,
personCourse,
buttonTitle,
}: WorkbookClientInfo) {
return (
<div className="flex h-[390px] min-w-[269px] flex-col">
<WorkbookCardDetail.MainImage mainImageUrl={mainImageUrl} />
<WorkbookCardDetail.WorkbookDetailInfoWrapper>
{metaComponent}
<WorkbookCardDetail.Title title={title} />
<WorkbookCardDetail.WriterList writers={writers} />
<WorkbookCardDetail.PersonCourseWithFewLogo
personCourse={personCourse}
/>
<WorkbookCardDetail.BottomButton buttonTitle={buttonTitle} />
</WorkbookCardDetail.WorkbookDetailInfoWrapper>
</div>
);
}
77 changes: 77 additions & 0 deletions src/main/components/WorkbookCardDetail/index.tsx
Copy link
Collaborator

Choose a reason for hiding this comment

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

compound pattern 으로 구현했군용!! 좋습니다 👍

Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { WorkbookClientInfo } from "@main/types/workbook";
import { Button } from "@shared/components/ui/button";
import { cn } from "@shared/utils/cn";
import Image from "next/image";
import FewLogo from "public/assets/icon/cardFewLogo.svg";

const MainImage = ({
mainImageUrl,
}: Pick<WorkbookClientInfo, "mainImageUrl">) => (
<Image
width={269}
height={172}
src={mainImageUrl}
alt=""
priority
className="h-[172px] w-[269px] rounded-t-lg object-cover"
/>
);
const WorkbookDetailInfoWrapper = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => (
<article
className={cn(
"flex flex-col",
"rounded-b-lg bg-black",
"px-[21px] pb-[25px] pt-[23px]",
)}
>
{children}
</article>
);

const Title = ({ title }: Pick<WorkbookClientInfo, "title">) => (
<p className="body3-bold w-auto truncate py-[2px] text-white">{title}</p>
);

const WriterList = ({ writers }: Pick<WorkbookClientInfo, "writers">) => (
<ul className="sub3-medium flex gap-1 pb-[10px] text-text-gray2">
{writers.map((writer, idx) => (
<li key={`workbook-writer-${idx}`}>{writer}</li>
))}
</ul>
);

const PersonCourseWithFewLogo = ({
personCourse,
}: Pick<WorkbookClientInfo, "personCourse">) => (
<div className="flex justify-between pb-[26px] pt-[10px]">
<span className="sub3-medium text-text-gray3">{personCourse}</span>
<FewLogo width={20} height={20} fill="#264932" />
</div>
);

const BottomButton = ({
buttonTitle,
}: Pick<WorkbookClientInfo, "buttonTitle">) => (
<Button
className={cn(
"sub3-semibold bg-white text-black",
"h-fit rounded py-[4.5px]",
)}
>
{buttonTitle}
</Button>
);
const WorkbookCardDetail = {
MainImage,
WorkbookDetailInfoWrapper,
Title,
WriterList,
PersonCourseWithFewLogo,
BottomButton,
};

export default WorkbookCardDetail;
87 changes: 87 additions & 0 deletions src/main/components/WorkbookCardList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { WorkbookCardModel } from "@main/models/workbookCardModel";
import {
WorkbookServerInfo,
WorkbookSubscriptionInfo,
} from "@main/types/workbook";
import WorkbookCard from "../WorkbookCard";
// TODO : api 연결필요 + mock
const data: WorkbookServerInfo[] = [
{
id: 1,
mainImageUrl:
"https://storage.mrblog.net/files/dosi_draw/a3NgiDGW2H3NhsYp1Qp3RuWNzUx9sg8L2yyooYqF.jpg",
title: "몰티즈는 참지않긔",
description:
"몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔",
category: "경제",
createdAt: "2024-07-25 14:32:35",
writers: [
{
id: 1,
name: "name1",
url: "https://example.com",
},
],
subscriberCount: 1,
},
{
id: 2,
mainImageUrl:
"https://storage.mrblog.net/files/dosi_draw/a3NgiDGW2H3NhsYp1Qp3RuWNzUx9sg8L2yyooYqF.jpg",
title:
"몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔",
description:
"몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔 몰티즈는 참지않긔",
category: "경제",
createdAt: "2024-07-25 14:32:35",
writers: [
{
id: 2,
name: "name2",
url: "https://example.com",
},
],
subscriberCount: 2,
},
];
const subData: WorkbookSubscriptionInfo[] = [
{
id: 1,
status: "ACTIVE",
totalDay: 10,
currentDay: 1,
rank: 0,
totalSubscriber: 100,
articleInfo: "{}",
},
{
id: 2,
status: "DONE",
totalDay: 10,
currentDay: 10,
rank: 22,
totalSubscriber: 100,
articleInfo: "{}",
},
];

interface WorkbookCardListProps {
category: string;
}
export default function WorkbookCardList({ category }: WorkbookCardListProps) {
const workbookCardModel = new WorkbookCardModel({
initWorkbookSeverList: data,
initWorkbookSubscriptionInfoList: subData,
});
return (
<section className="mr-[18px] flex gap-[8px] overflow-x-auto">
{workbookCardModel
.workbookCardList({
workbookCombineList: workbookCardModel.workbookCombineListData,
})
.map((data, idx) => (
<WorkbookCard key={`work-book-card-${idx}`} {...data} />
))}
</section>
);
}
2 changes: 2 additions & 0 deletions src/main/components/WorkbookCardsWrapper/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import useCategory from "@main/hooks/useCategory";
import CategoryTabs from "../CategoryTabs";
import MainContentWrapper from "../MainContentWrapper";
import WorkbookCardList from "../WorkbookCardList";

export default function WorkbookCardsWrapper() {
const { category, handleCategory } = useCategory();
Expand All @@ -13,6 +14,7 @@ export default function WorkbookCardsWrapper() {
handleCategory={handleCategory}
category={category}
/>
<WorkbookCardList category={category} />
</MainContentWrapper>
);
}
Loading
Loading