Skip to content

Commit

Permalink
feature-064: 카드 컴포넌트 리팩토링
Browse files Browse the repository at this point in the history
  • Loading branch information
gs0428 committed Feb 13, 2024
1 parent 3871879 commit 0d910bb
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 114 deletions.
6 changes: 6 additions & 0 deletions src/components/Home/InsightVideos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ const InsightVideos: React.FC<InsightVideosProps> = ({
const [categoryItems] = useState<IVideoProps[]>([]);
const [checkedItems, setCheckedItems] = useState<number[]>([]);

const onFileClick = (e: React.MouseEvent<HTMLSpanElement>) => {
e.stopPropagation();
// 비디오 카테고리로 저장 API 호출 후 이런 인사이트는 어때요 API 재호출로 최신화하기
};

return (
<InsightVideosContainer>
<div className="insight-container">
Expand All @@ -35,6 +40,7 @@ const InsightVideos: React.FC<InsightVideosProps> = ({
video={video}
checkedVideos={checkedItems}
setCheckedVideos={setCheckedItems}
onFileClick={onFileClick}
/>
))}
</CardContainer>
Expand Down
55 changes: 35 additions & 20 deletions src/components/Home/RecentVideos.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,44 @@
import React from 'react'
import { RecentVideosContainer, VideoButton, VideosSubtitle, VideosTitle } from '@/styles/HomepageStyle';
// import Card from '../category/Card';
import {
RecentVideosContainer,
VideoButton,
VideosSubtitle,
VideosTitle,
} from '@/styles/HomepageStyle';
import CardImage from '@/assets/empty-video.png';
const RecentVideos: React.FC = () => {
import { CardContainer } from '@/styles/category/Card.style';
import Card from '../category/Card';
import { IVideoProps } from 'types/videos';

interface IRecentVideosProp {
videos: IVideoProps[];
}

const RecentVideos = ({ videos }: IRecentVideosProp) => {
return (
<RecentVideosContainer>
<div className="container">
<VideosTitle>최근 읽은 영상</VideosTitle>

{/* 영상 개수 0개일 때 */}
<>
<div className="empty-video">
<img src={CardImage} alt="비어있는 비디오 이미지" />
</div>
<VideosSubtitle>
처음 방문하셨나요? <br /> 아직 정리해본 영상이 없어요!
</VideosSubtitle>
<VideoButton>
<h2 className="button-text">영상 정리해보기</h2>
</VideoButton>
</>

{/* 영상 개수 3개 이하일 때 */}

{/* 영상 개수 4개 이상일 때 '더보기 버튼' 활성화 & 전체 카드 모두 보여짐 */}
{videos.length === 0 && (
<>
<div className="empty-video">
<img src={CardImage} alt="비어있는 비디오 이미지" />
</div>
<VideosSubtitle>
처음 방문하셨나요? <br /> 아직 정리해본 영상이 없어요!
</VideosSubtitle>
<VideoButton>
<h2 className="button-text">영상 정리해보기</h2>
</VideoButton>
</>
)}
{videos.length > 0 && (
<CardContainer>
{videos.map((video) => (
<Card mode="default" video={video} />
))}
</CardContainer>
)}
</div>
</RecentVideosContainer>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import { ISelectedCategoryProps } from 'types/category';
interface ICategorySelectBoxProps {
selectedCategory: ISelectedCategoryProps;
handleSelectCategory: ({ name, categoryId }: ISelectedCategoryProps) => void;
onFileClick?: (e: React.MouseEvent<HTMLSpanElement>) => void;
}

const CategorySelectBox = ({
selectedCategory,
handleSelectCategory,
onFileClick,
}: ICategorySelectBoxProps) => {
const [isLogin] = useState(true);
const [isOpen, setIsOpen] = useState(false);
Expand Down Expand Up @@ -57,6 +59,7 @@ const CategorySelectBox = ({
className={`icon-button ${!isLogin && 'disabled'} ${
selectedCategory.name ? 'selected' : 'not-selected'
}`}
onClick={onFileClick}
>
<OpenFileIcon width={28} height={28} />
</span>
Expand Down
51 changes: 35 additions & 16 deletions src/components/category/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,49 @@
import React, { useState } from 'react';
import * as CardStyles from '@/styles/category/Card.style';
import VideoTag from '../common/videoTag';
import { IVideoProps } from 'types/videos';
import { CategorySelectBox } from '../SummaryPage/SummaryDetailBox/CategorySelectBox';
import { ISelectedCategoryProps } from 'types/category';
import { useRecoilValue } from 'recoil';
import { categoryState } from '@/stores/category';

interface ICardProps {
mode: 'default' | 'category' | 'recommend';
video: IVideoProps;
checkedVideos: number[];
setCheckedVideos: (value: number[]) => void;
checkedVideos?: number[];
setCheckedVideos?: (value: number[]) => void;
onFileClick?: (e: React.MouseEvent<HTMLSpanElement>) => void;
}

const Card: React.FC<ICardProps> = ({
mode = 'default',
video,
checkedVideos,
setCheckedVideos,
onFileClick,
}) => {
const [isOpen, setIsOpen] = useState(false);
const category = useRecoilValue(categoryState);
const [selectedCategory, setSelectedCategory] =
useState<ISelectedCategoryProps>({
name: category[0].name,
categoryId: category[0].categoryId,
});

const handleSelectCategory = ({
name,
categoryId,
}: ISelectedCategoryProps) => {
setSelectedCategory({
name,
categoryId,
});
};

const handleCheckBox = (videoId: number) => {
if (checkedVideos.includes(videoId)) {
setCheckedVideos(checkedVideos.filter((id) => id !== videoId));
if (checkedVideos!.includes(videoId)) {
setCheckedVideos!(checkedVideos!.filter((id) => id !== videoId));
} else {
setCheckedVideos([...checkedVideos, videoId]);
setCheckedVideos!([...checkedVideos!, videoId]);
}
};
return (
Expand All @@ -34,11 +54,11 @@ const Card: React.FC<ICardProps> = ({
<CardStyles.Image source={video.image}>
{mode === 'category' && (
<CardStyles.CheckBoxWrap
className={checkedVideos.length > 0 ? 'activated' : ''}
className={checkedVideos!.length > 0 ? 'activated' : ''}
>
<CardStyles.CheckBox
type="checkbox"
checked={checkedVideos.includes(video.video_id)}
checked={checkedVideos!.includes(video.video_id)}
onChange={() => handleCheckBox(video.video_id)}
/>
</CardStyles.CheckBoxWrap>
Expand All @@ -50,18 +70,17 @@ const Card: React.FC<ICardProps> = ({
<CardStyles.Summary>{video.description}</CardStyles.Summary>
<CardStyles.ChipWrap>
{video.tag.map((tag) => (
<VideoTag
content={`# ${tag.name}`}
color={'gray400'}
typography="Caption1"
key={tag.name}
/>
<CardStyles.Chip key={tag.name}>{`# ${tag.name}`}</CardStyles.Chip>
))}
</CardStyles.ChipWrap>
</CardStyles.Content>
{isOpen && (
{isOpen && mode === 'recommend' && (
<CardStyles.DropdownWrap>
<CategorySelectBox />
<CategorySelectBox
selectedCategory={selectedCategory}
handleSelectCategory={handleSelectCategory}
onFileClick={onFileClick}
/>
</CardStyles.DropdownWrap>
)}
</CardStyles.Wrap>
Expand Down
17 changes: 0 additions & 17 deletions src/components/common/videoTag/VideoTag.style.ts

This file was deleted.

18 changes: 0 additions & 18 deletions src/components/common/videoTag/index.tsx

This file was deleted.

15 changes: 8 additions & 7 deletions src/pages/GuestPage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import React from 'react';
import SearchYoutube from '@/components/Home/SearchYoutube';
import {
HomePageContainer
} from '@/styles/HomepageStyle';
import { HomePageContainer } from '@/styles/HomepageStyle';
import RecentVideos from '@/components/Home/RecentVideos';
import InsightVideos from '@/components/Home/InsightVideos';

Expand All @@ -11,7 +9,7 @@ export interface Video {
title: string;
subtitle: string;
hashtags: string[];
thumbnailUrl: string;
thumbnailUrl: string;
}

const GuestPage: React.FC = () => {
Expand All @@ -22,10 +20,13 @@ const GuestPage: React.FC = () => {
return (
<HomePageContainer>
<SearchYoutube onSearch={handleSearch} />
<InsightVideos username="여울" popularHashtags={['디자인', '진로', '브랜딩']} />
<RecentVideos />
<InsightVideos
username="여울"
popularHashtags={['디자인', '진로', '브랜딩']}
/>
<RecentVideos videos={[]} />
</HomePageContainer>
);
};

export default GuestPage;
export default GuestPage;
31 changes: 22 additions & 9 deletions src/pages/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,50 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import SearchYoutube from '@/components/Home/SearchYoutube';
import {
HomePageContainer
} from '@/styles/HomepageStyle';
import { HomePageContainer } from '@/styles/HomepageStyle';
import RecentVideos from '@/components/Home/RecentVideos';
import InsightVideos from '@/components/Home/InsightVideos';
import { useRecoilValue } from 'recoil';
import { recommendationModalState } from '@/stores/modal';
import RecommendationModal from '@/components/modals/RecommendationModal';
import { getRecentVideos } from '@/apis/videos';
import { userTokenState } from '@/stores/user';
import { IVideoProps } from 'types/videos';

export interface Video {
id: string;
title: string;
subtitle: string;
hashtags: string[];
thumbnailUrl: string;
thumbnailUrl: string;
}

const HomePage: React.FC = () => {
const userToken = useRecoilValue(userTokenState);
const [videos, setVideos] = useState<IVideoProps[]>([]);
const handleSearch = (value: string) => {
console.log(value);
};

const isModalOpen = useRecoilValue(recommendationModalState);

useEffect(() => {
userToken &&
getRecentVideos()
.then((res) => setVideos(res.result.videos))
.catch((err) => console.log(err));
}, [userToken]);

return (
<HomePageContainer>
<SearchYoutube onSearch={handleSearch} />
{isModalOpen && <RecommendationModal /> }
<RecentVideos />
<InsightVideos username="여울" popularHashtags={['디자인', '진로', '브랜딩']} />
{isModalOpen && <RecommendationModal />}
<RecentVideos videos={videos} />
<InsightVideos
username="여울"
popularHashtags={['디자인', '진로', '브랜딩']}
/>
</HomePageContainer>
);
};

export default HomePage;
export default HomePage;
Loading

0 comments on commit 0d910bb

Please sign in to comment.