Skip to content

Commit

Permalink
Merge pull request #95 from teamViNO/feature-075
Browse files Browse the repository at this point in the history
feature-075: 카테고리 페이지 스켈레톤 UI 퍼블리싱
  • Loading branch information
whistleJs authored Feb 17, 2024
2 parents 049cd02 + f706fa7 commit 649f9a9
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 57 deletions.
20 changes: 20 additions & 0 deletions src/components/skeleton/CardSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as CardSkeletonStyles from '@/styles/skeleton/CardSkeleton.style';
const CardSkeleton = () => {
return (
<CardSkeletonStyles.Container>
<CardSkeletonStyles.Image />
<CardSkeletonStyles.ContentWrap>
<CardSkeletonStyles.ContentLong />
<CardSkeletonStyles.ContentShort />
<CardSkeletonStyles.ContentShort />
<CardSkeletonStyles.TagWrap>
<CardSkeletonStyles.Tag />
<CardSkeletonStyles.Tag />
<CardSkeletonStyles.Tag />
</CardSkeletonStyles.TagWrap>
</CardSkeletonStyles.ContentWrap>
</CardSkeletonStyles.Container>
);
};

export default CardSkeleton;
34 changes: 34 additions & 0 deletions src/components/skeleton/CategoryPageSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as CategoryPageSkeletonStyles from '@/styles/skeleton/CategoryPageSkeleton.style';
import CardSkeleton from './CardSkeleton';

interface ICategoryPageSkeletonProp {
isSubSkeleton: boolean;
}

const CategoryPageSkeleton = ({ isSubSkeleton }: ICategoryPageSkeletonProp) => {
return (
<CategoryPageSkeletonStyles.Container>
<CategoryPageSkeletonStyles.Title />
<CategoryPageSkeletonStyles.MenuWrap>
<CategoryPageSkeletonStyles.TagWrap>
<CategoryPageSkeletonStyles.Tag
className={`${isSubSkeleton && 'show'}`}
/>
<CategoryPageSkeletonStyles.Tag
className={`${isSubSkeleton && 'show'}`}
/>
</CategoryPageSkeletonStyles.TagWrap>
<CategoryPageSkeletonStyles.Menu />
</CategoryPageSkeletonStyles.MenuWrap>
<CategoryPageSkeletonStyles.CardContainer>
<CardSkeleton />
<CardSkeleton />
<CardSkeleton />
<CardSkeleton />
<CardSkeleton />
</CategoryPageSkeletonStyles.CardContainer>
</CategoryPageSkeletonStyles.Container>
);
};

export default CategoryPageSkeleton;
124 changes: 67 additions & 57 deletions src/pages/CategoryPage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import CategoryTitle from '@/components/category/CategoryTitle';
import { useEffect, useState } from 'react';
import React, { Suspense, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import * as CategoryPageStyles from '@/styles/category/index.style';
import Card from '@/components/category/Card';
import { useRecoilValue } from 'recoil';
import { categoryState } from '@/stores/category';
import { ISubFolderProps, ITagProps } from 'types/category';
Expand All @@ -12,9 +10,17 @@ import { IVideoProps } from 'types/videos';
import { sortVideos } from '@/utils/sortVideos';
import { CardContainer } from '@/styles/category/Card.style';
import VideoSelectMenu from '@/components/category/VideoSelectMenu';
import DefaultMenu from '@/components/category/DefaultMenu';
import { putVideoToOtherCategory } from '@/apis/category';
import handleVideo from '@/utils/handleVideo';
import CategoryPageSkeleton from '@/components/skeleton/CategoryPageSkeleton';

const CategoryTitle = React.lazy(
() => import('@/components/category/CategoryTitle'),
);
const Card = React.lazy(() => import('@/components/category/Card'));
const DefaultMenu = React.lazy(
() => import('@/components/category/DefaultMenu'),
);

const CategoryPage = () => {
const params = useParams();
Expand Down Expand Up @@ -78,61 +84,65 @@ const CategoryPage = () => {
};

return (
<CategoryPageStyles.Container>
<CategoryTitle name={name} totalVideos={sortedVideos.length} />
<CategoryPageStyles.MenuWrap>
{checkedVideos.length > 0 ? (
<VideoSelectMenu
categories={categories}
totalVideoCount={sortedVideos.length}
checkedVideos={checkedVideos}
setCheckedVideos={setCheckedVideos}
handleDeleteVideos={handleDeleteVideos}
allCheckBtnHandler={allCheckBtnHandler}
onFileClick={onFileClick}
/>
) : (
<DefaultMenu
menus={menus}
recentRegisterMode={recentRegisterMode}
selectedTags={selectedTags}
setSelectedTags={setSelectedTags}
toggleRecentRegisterMode={toggleRecentRegisterMode}
/>
)}
</CategoryPageStyles.MenuWrap>
<Suspense
fallback={<CategoryPageSkeleton isSubSkeleton={!!params.sub_folder} />}
>
<CategoryPageStyles.Container>
<CategoryTitle name={name} totalVideos={sortedVideos.length} />
<CategoryPageStyles.MenuWrap>
{checkedVideos.length > 0 ? (
<VideoSelectMenu
categories={categories}
totalVideoCount={sortedVideos.length}
checkedVideos={checkedVideos}
setCheckedVideos={setCheckedVideos}
handleDeleteVideos={handleDeleteVideos}
allCheckBtnHandler={allCheckBtnHandler}
onFileClick={onFileClick}
/>
) : (
<DefaultMenu
menus={menus}
recentRegisterMode={recentRegisterMode}
selectedTags={selectedTags}
setSelectedTags={setSelectedTags}
toggleRecentRegisterMode={toggleRecentRegisterMode}
/>
)}
</CategoryPageStyles.MenuWrap>

{(sortedVideos.length === 0 || sortedVideos === undefined) && (
<EmptyCard />
)}
{sortedVideos.length > 0 && (
<CardContainer>
{sortedVideos.map((video) => {
// 하위 카테고리에 있을 때 태그 선택된 것에 따라 비디오 보여지게하는 로직
const matchedTagCount = video.tag.reduce((acc, cur) => {
if (selectedTags.includes(cur.name)) return (acc += 1);
return acc;
}, 0);
if (
params.sub_folder &&
selectedTags.length &&
matchedTagCount !== selectedTags.length
)
return;
{(sortedVideos.length === 0 || sortedVideos === undefined) && (
<EmptyCard />
)}
{sortedVideos.length > 0 && (
<CardContainer>
{sortedVideos.map((video) => {
// 하위 카테고리에 있을 때 태그 선택된 것에 따라 비디오 보여지게하는 로직
const matchedTagCount = video.tag.reduce((acc, cur) => {
if (selectedTags.includes(cur.name)) return (acc += 1);
return acc;
}, 0);
if (
params.sub_folder &&
selectedTags.length &&
matchedTagCount !== selectedTags.length
)
return;

return (
<Card
mode="category"
video={video}
checkedVideos={checkedVideos}
setCheckedVideos={setCheckedVideos}
key={video.video_id}
/>
);
})}
</CardContainer>
)}
</CategoryPageStyles.Container>
return (
<Card
mode="category"
video={video}
checkedVideos={checkedVideos}
setCheckedVideos={setCheckedVideos}
key={video.video_id}
/>
);
})}
</CardContainer>
)}
</CategoryPageStyles.Container>
</Suspense>
);
};

Expand Down
35 changes: 35 additions & 0 deletions src/styles/skeleton/CardSkeleton.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import styled from 'styled-components';
import { CommonBackground } from './CategoryPageSkeleton.style';

export const Container = styled.div`
height: 346px;
`;

export const Image = styled(CommonBackground)`
height: 163px;
`;

export const ContentWrap = styled.div`
padding: 26.87px 16px 0;
`;

export const ContentLong = styled(CommonBackground)`
height: 20px;
margin-bottom: 6px;
`;

export const ContentShort = styled(CommonBackground)`
width: 142px;
height: 20px;
margin-bottom: 20px;
`;

export const TagWrap = styled.div`
display: flex;
`;

export const Tag = styled(CommonBackground)`
width: 62px;
height: 31px;
margin-right: 8px;
`;
73 changes: 73 additions & 0 deletions src/styles/skeleton/CategoryPageSkeleton.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import styled, { keyframes } from 'styled-components';
import theme from '../theme';

const gradient = keyframes`
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
`;

export const CommonBackground = styled.div`
background: linear-gradient(
-45deg,
${theme.color.gray100},
${theme.color.gray200},
${theme.color.gray100}
);
background-size: 200% 100%;
animation: ${gradient} 1.5s ease infinite;
border-radius: 4px;
`;

export const Container = styled.div`
padding: 60px 60px 40px 120px;
width: 100%;
margin-inline: auto;
`;

export const Title = styled(CommonBackground)`
height: 40px;
width: 259px;
background-color: ${theme.color.gray100};
`;

export const MenuWrap = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
margin: 32px 0 44px;
`;

export const TagWrap = styled.div`
display: flex;
`;

export const Tag = styled(CommonBackground)`
visibility: hidden;
width: 64px;
height: 20px;
margin-right: 20px;
&.show {
visibility: visible;
}
`;

export const Menu = styled(CommonBackground)`
width: 90px;
height: 20px;
`;

export const CardContainer = styled.div`
display: grid;
grid-template-columns: repeat(3, 290px);
column-gap: 20px;
row-gap: 61px;
`;

0 comments on commit 649f9a9

Please sign in to comment.