Skip to content

Commit

Permalink
Merge pull request #217 from boostcampwm-2022/feature/skeleton_ui_kmh
Browse files Browse the repository at this point in the history
메인페이지 Skeleton UI 적용
  • Loading branch information
MinHK4 authored Dec 7, 2022
2 parents 96b2e68 + b74853f commit 4530645
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 10 deletions.
38 changes: 38 additions & 0 deletions frontend/components/SkeletonBook/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { FlexColumn, FlexSpaceBetween } from '@styles/layout';

import {
BookWrapper,
BookInfoContainer,
BookTitle,
BookContentsInfo,
BookContents,
BookThumbnail,
BookAuthor,
Bookmark,
} from './styled';

export default function SkeletonBook() {
const bookContentsList = Array.from({ length: 4 }, (_, i) => i + 1);

return (
<BookWrapper>
<BookThumbnail />

<BookInfoContainer>
<FlexSpaceBetween>
<FlexColumn>
<BookTitle />
<BookAuthor />
</FlexColumn>
<Bookmark />
</FlexSpaceBetween>

<BookContentsInfo>
{bookContentsList.map((key) => (
<BookContents key={key} />
))}
</BookContentsInfo>
</BookInfoContainer>
</BookWrapper>
);
}
90 changes: 90 additions & 0 deletions frontend/components/SkeletonBook/styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import Image from 'next/image';

import styled from 'styled-components';

import { FlexColumn } from '@styles/layout';

const SkeletonItem = styled.div`
width: 100%;
height: 30px;
background-color: #f2f2f2;
position: relative;
overflow: hidden;
border-radius: 4px;
@keyframes skeleton-gradient {
0% {
background-color: rgba(165, 165, 165, 0.1);
}
50% {
background-color: rgba(165, 165, 165, 0.3);
}
100% {
background-color: rgba(165, 165, 165, 0.1);
}
}
&:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
animation: skeleton-gradient 1.5s infinite ease-in-out;
}
`;

export const BookWrapper = styled(FlexColumn)`
min-width: 280px;
max-width: 280px;
height: 480px;
margin: 0 10px;
box-sizing: border-box;
background-color: var(--white-color);
border: 1px solid var(--primary-color);
border-radius: 10px;
overflow: hidden;
`;

export const BookThumbnail = styled(SkeletonItem)`
width: 280px;
height: 200px;
min-height: 200px;
`;

export const BookInfoContainer = styled(FlexColumn)`
padding: 15px 24px;
gap: 18px;
`;

export const BookTitle = styled(SkeletonItem)`
height: 30px;
width: 140px;
`;

export const BookAuthor = styled(SkeletonItem)`
height: 20px;
width: 60px;
margin-top: 10px;
`;

export const Bookmark = styled(SkeletonItem)`
height: 30px;
width: 30px;
`;

export const BookmarkIcon = styled(Image)`
cursor: pointer;
`;

export const BookContentsInfo = styled(FlexColumn)`
gap: 8px;
margin-top: 30px;
`;

export const BookContents = styled(SkeletonItem)`
height: 20px;
width: 100%;
`;
14 changes: 9 additions & 5 deletions frontend/components/home/Slider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import LeftArrowIcon from '@assets/ico_arrow_left.svg';
import RightArrowIcon from '@assets/ico_arrow_right.svg';
import ListIcon from '@assets/ico_flower.svg';
import Book from '@components/common/Book';
import SkeletonBook from '@components/SkeletonBook';
import { IBookScraps } from '@interfaces';

import {
Expand All @@ -23,14 +24,17 @@ import {
interface SliderProps {
bookList: IBookScraps[];
title: string;
isLoading: boolean;
}

function Slider({ bookList, title }: SliderProps) {
function Slider({ bookList, title, isLoading }: SliderProps) {
const [curBookIndex, setCurBookIndex] = useState(0);
const [sliderNumber, setSliderNumber] = useState(1);

const numberPerPage = 4;
const sliderIndicatorCount = Math.ceil(bookList.length / numberPerPage);
const SkeletonList = Array.from({ length: 12 }, (_, i) => i + 1);

const sliderIndicatorCount = bookList ? Math.ceil(bookList.length / numberPerPage) : 0;
const sliderIndicatorNumbersList = Array.from({ length: sliderIndicatorCount }, (_, i) => i + 1);

const handleLeftArrowClick = () => {
Expand Down Expand Up @@ -65,9 +69,9 @@ function Slider({ bookList, title }: SliderProps) {
</SliderInfoContainer>

<SliderBookContainer curBookIndex={curBookIndex}>
{bookList.map((book) => (
<Book key={book.id} book={book} />
))}
{isLoading
? SkeletonList.map((key) => <SkeletonBook key={key} />)
: bookList.map((book) => <Book key={book.id} book={book} />)}
</SliderBookContainer>
</SliderContent>

Expand Down
4 changes: 3 additions & 1 deletion frontend/hooks/useFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@ import { toastError } from '@utils/toast';

const useFetch = <T>(api: (...args: any[]) => Promise<T>) => {
const [data, setData] = useState<T>();
const [isLoading, setIsLoading] = useState<boolean>(true);

const execute = useCallback(async (...args: any[]) => {
try {
setData(await api(...args));
setIsLoading(false);
} catch (error: any) {
const { message } = error.response.data;

toastError(message);
}
}, []);

return { data, execute };
return { data, isLoading, execute };
};

export default useFetch;
21 changes: 17 additions & 4 deletions frontend/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,17 @@ import useFetch from '@hooks/useFetch';
import { PageInnerLarge, PageWrapper } from '@styles/layout';

export default function Home() {
const { data: newestBookList, execute: getNewestBookList } = useFetch(getOrderedBookListApi);
const { data: popularBookList, execute: getPopularBookList } = useFetch(getOrderedBookListApi);
const {
data: newestBookList,
isLoading: isNewBookListLoading,
execute: getNewestBookList,
} = useFetch(getOrderedBookListApi);

const {
data: popularBookList,
isLoading: isPopularBookListLoading,
execute: getPopularBookList,
} = useFetch(getOrderedBookListApi);

useEffect(() => {
getNewestBookList('newest');
Expand All @@ -23,8 +32,12 @@ export default function Home() {
<GNB />
<PageWrapper>
<PageInnerLarge>
{newestBookList && <Slider bookList={newestBookList} title="새로 엮은 책" />}
{popularBookList && <Slider bookList={popularBookList} title="가장 인기 있는 책" />}
<Slider bookList={newestBookList} title="새로 엮은 책" isLoading={isNewBookListLoading} />
<Slider
bookList={popularBookList}
title="가장 인기 있는 책"
isLoading={isPopularBookListLoading}
/>
<Footer />
</PageInnerLarge>
</PageWrapper>
Expand Down

0 comments on commit 4530645

Please sign in to comment.