Skip to content

Commit

Permalink
feat: magazine list page 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
kingyong9169 committed Feb 15, 2025
1 parent 8eca17e commit 78cf5a4
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 52 deletions.
1 change: 1 addition & 0 deletions apps/ziine/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const nextConfig: NextConfig = {
'monthlyart.com',
'slownews.kr',
'www.sakyejul.net',
'velog.velcdn.com',
],
},
};
Expand Down
3 changes: 2 additions & 1 deletion apps/ziine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"react-lottie-player": "^2.1.0",
"react-markdown": "^9.0.3",
"rehype-highlight": "^7.0.2",
"rehype-raw": "^7.0.0"
"rehype-raw": "^7.0.0",
"swiper": "^11.2.4"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
Expand Down
10 changes: 9 additions & 1 deletion apps/ziine/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,13 @@ export default function Home() {

const MainPage = () => {
const { isArtwork } = useDetectNavType();
return isArtwork ? <ArtWorkPage /> : <MagazineListPage />;
return isArtwork ? <ArtWorkPage /> : <ClientMagazineListPage />;
};

const ClientMagazineListPage = () => {
return (
<Suspense>
<MagazineListPage />
</Suspense>
);
};
9 changes: 8 additions & 1 deletion apps/ziine/src/entities/magazine/apis/queries.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import { useSuspenseQuery } from '@tanstack/react-query';
import { getMagazineDetail } from './apis';
import { getMagazineDetail, getMagazineList } from './apis';

const magazineQueryKeys = {
magazine: ['magazine'],
Expand All @@ -14,3 +14,10 @@ export const useSuspenseMagazineDetail = (id: number) => {
queryFn: () => getMagazineDetail(id),
});
};

export const useSuspenseMagazineList = () => {
return useSuspenseQuery({
queryKey: magazineQueryKeys.magazine,
queryFn: () => getMagazineList(),
});
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { BaseImage } from '@/shared/components/base-image';
import { css, cx } from '@/styled-system/css';
import { Typography } from '@ziine/design';
import Link from 'next/link';
import { CSSProperties } from 'react';

const textEllipsisStyle: CSSProperties = {
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
};

interface Props {
id: number;
className?: string;
style?: CSSProperties;
title: string;
Expand All @@ -14,6 +20,7 @@ interface Props {
}

export const MagazineCard = ({
id,
className,
style,
title,
Expand All @@ -23,41 +30,53 @@ export const MagazineCard = ({
keywords,
}: Props) => {
return (
<div
className={cx(css({ padding: '16px', borderRadius: '18.493px' }), className)}
style={{ ...style, backgroundColor }}
>
<Typography level='heading4'>{title}</Typography>
<div className={css({ margin: '8px 0' })}>
<Typography level='paragraph3'>{summary}</Typography>
</div>
<div className={css({ display: 'flex', gap: '4px', flexWrap: 'wrap', margin: '16px 0 12px' })}>
{keywords.map((keyword) => (
<div
key={keyword}
className={css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: '4px 10px',
borderRadius: '99px',
backgroundColor: 'transparent',
borderWidth: '1px',
borderStyle: 'solid',
borderColor: 'grayscale.900',
})}
>
<Typography level='paragraph4'>#{keyword}</Typography>
</div>
))}
<Link href={`/magazine-webview/${id}`}>
<div
className={cx(css({ padding: '16px', borderRadius: '18.493px' }), className)}
style={{ ...style, backgroundColor }}
>
<Typography
level='heading4'
style={textEllipsisStyle}
className={css({ overflow: 'hidden', textOverflow: 'ellipsis', WebkitLineClamp: 2 })}
>
{title}
</Typography>
<div
style={textEllipsisStyle}
className={css({ margin: '8px 0', overflow: 'hidden', textOverflow: 'ellipsis', WebkitLineClamp: 2 })}
>
<Typography level='paragraph3'>{summary}</Typography>
</div>
<div className={css({ display: 'flex', gap: '4px', flexWrap: 'wrap', margin: '16px 0 12px' })}>
{keywords.map((keyword) => (
<div
key={keyword}
className={css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: '4px 10px',
borderRadius: '99px',
backgroundColor: 'transparent',
borderWidth: '1px',
borderStyle: 'solid',
borderColor: 'grayscale.900',
})}
>
<Typography level='paragraph4'>#{keyword}</Typography>
</div>
))}
</div>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
className={css({ width: '100%', aspectRatio: '1 / 1', borderRadius: '16px' })}
src={thumbnailImageUrl}
alt={title}
width={256}
height={256}
/>
</div>
<BaseImage
className={css({ width: '100%', aspectRatio: '1 / 1', borderRadius: '16px' })}
src={thumbnailImageUrl}
alt={title}
width={256}
height={256}
/>
</div>
</Link>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { cva } from '@/styled-system/css';

export const listItemStyle = cva({
base: {},
variants: {
active: {
true: {
minWidth: '256px',
maxWidth: '256px',
},
false: {
minWidth: '240px',
maxWidth: '240px',
},
},
},
});
60 changes: 49 additions & 11 deletions apps/ziine/src/views/magazine-list-page/magazine-list-page.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,57 @@
import { getMagazineList } from '@/entities/magazine/apis/apis';
'use client';

import { useSuspenseMagazineList } from '@/entities/magazine/apis/queries';
import { MagazineCard } from '@/entities/magazine/components/magazine-card';
import { css } from '@/styled-system/css';
import { Swiper, SwiperSlide } from 'swiper/react';

import 'swiper/css';
import 'swiper/css/pagination';
import { useState } from 'react';
import { Tag } from '@ziine/design';
import { listItemStyle } from './magazine-list-page.styles';

export const MagazineListPage = () => {
const {
data: { magazines },
} = useSuspenseMagazineList();

export const MagazineListPage = async () => {
const data = await getMagazineList();
const [activeIndex, setActiveIndex] = useState(0);

return (
<div className={css({ margin: '24px 0', gap: '16px', display: 'flex' })}>
{data.magazines.map((magazine) => (
<MagazineCard
key={magazine.id}
{...magazine}
className={css({ minWidth: '256px', maxWidth: '256px', height: 'fit-content' })}
/>
))}
<div
className={css({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
margin: '24px 0',
width: '100%',
})}
>
<Swiper
spaceBetween={16}
slidesPerView={3}
centeredSlides={true}
pagination={{ clickable: true, type: 'fraction' }}
observer={true}
observeParents={true}
updateOnWindowResize={true}
className={css({
marginBottom: '48px',
width: '100%',
height: '100%',
})}
onSlideChange={({ activeIndex }) => {
setActiveIndex(activeIndex);
}}
>
{magazines.map((magazine, idx) => (
<SwiperSlide key={magazine.id} className={listItemStyle({ active: activeIndex === idx })}>
<MagazineCard {...magazine} />
</SwiperSlide>
))}
</Swiper>
<Tag variant='orangeOutlined'>{`${activeIndex + 1}/${magazines.length}`}</Tag>
</div>
);
};
4 changes: 2 additions & 2 deletions apps/ziine/src/widgets/magazine-detail/magazine-detail.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { getMagazineDetail } from '@/entities/magazine/apis/apis';
import { BaseImage } from '@/shared/components';
import { css, cx } from '@/styled-system/css';
import { Typography } from '@ziine/design';
import ReactMarkdown from 'react-markdown';
Expand Down Expand Up @@ -43,7 +42,8 @@ const MagazineDetail = async ({ id }: { id: number }) => {
{title}
</Typography>
<div className={css({ margin: '24px 0' })}>
<BaseImage
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
width={343}
height={197}
src={thumbnailImageUrl}
Expand Down
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

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

0 comments on commit 78cf5a4

Please sign in to comment.