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-065: 카테고리 페이지 수정 #73

Merged
merged 15 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/apis/category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ export const getCategories = async () => {
return response.data;
};

// 카테고리 별 태그 가져오는 API
export const getCategoryTags = async (categoryId: string) => {
const response = await axiosInstance.get(`/category/${categoryId}/`);
return response.data;
};

// 카테고리 이동1 API
export const putSubToOtherTop = async (
categoryId: number,
Expand Down
4 changes: 2 additions & 2 deletions src/apis/videos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ export const getRecentVideos = async (): Promise<
};

export const getVideoById = async (
videoId: number,
videoId: string,
): Promise<APIResponse<Record<'videos', IVideoProps[]>>> => {
const response = await axiosInstance.get(`/videos/${videoId}`);
const response = await axiosInstance.get(`/videos/${videoId}/get`);
return response.data;
};

Expand Down
38 changes: 18 additions & 20 deletions src/components/Home/RecentVideos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,29 @@ const RecentVideos = ({ videos }: IRecentVideosProp) => {
return (
<RecentVideosContainer>
<div className="container">
<div className='title-container'>
<VideosTitle>최근 읽은 영상</VideosTitle>
{videos.length >= 4 && (
<Link to='/videos/recent'>
<div className='icon-wrapper'>
<MoveIcon width={28} height={28}/>
</div>
</Link>
)}
<div className="title-container">
<VideosTitle>최근 읽은 영상</VideosTitle>
{videos.length >= 4 && (
<Link to="/videos/recent">
<div className="icon-wrapper">
<MoveIcon width={28} height={28} />
</div>
</Link>
)}
</div>

{videos.length === 0 && (
<>
<div className="empty-container">
<div className="empty-video">
<img src={CardImage} alt="비어있는 비디오 이미지" />
</div>
<div className='empty-text'>
<VideosSubtitle>
처음 방문하셨나요? <br /> 아직 정리해본 영상이 없어요!
</VideosSubtitle>
<VideoButton>
<h2 className="button-text">영상 정리해보기</h2>
</VideoButton>
</div>
</>
<VideosSubtitle>
처음 방문하셨나요? <br /> 아직 정리해본 영상이 없어요!
</VideosSubtitle>
<VideoButton>
<h2 className="button-text">영상 정리해보기</h2>
</VideoButton>
</div>
)}
{videos.length > 0 && (
<CardContainer>
Expand Down
3 changes: 2 additions & 1 deletion src/components/category/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CategorySelectBox } from '@/components/SummaryPage/SummaryDetailBox/Cat
import { categoryState } from '@/stores/category';

import * as CardStyles from '@/styles/category/Card.style';
import Chip from '../common/chip/Chip';

interface ICardProps {
mode: 'default' | 'category' | 'recommend';
Expand Down Expand Up @@ -65,7 +66,7 @@ const Card: React.FC<ICardProps> = ({
<CardStyles.Summary>{video.description}</CardStyles.Summary>
<CardStyles.ChipWrap>
{video.tag.map((tag) => (
<CardStyles.Chip key={tag.name}>{`# ${tag.name}`}</CardStyles.Chip>
<Chip key={tag.name} name={tag.name} />
))}
</CardStyles.ChipWrap>
</CardStyles.Content>
Expand Down
68 changes: 68 additions & 0 deletions src/components/category/DefaultMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import * as CategoryPageStyles from '@/styles/category/index.style';
import { ISubFolderProps, ITagProps } from 'types/category';
import Chip from '../common/chip/Chip';
import ChangeBottomSvg from '@/assets/icons/change-bottom.svg?react';
import ChangeTopSvg from '@/assets/icons/change-top.svg?react';

interface IDefaultMenuProps {
menus: ISubFolderProps[] | ITagProps[];
recentRegisterMode: boolean;
selectedTags: string[];
setSelectedTags: React.Dispatch<React.SetStateAction<string[]>>;
toggleRecentRegisterMode: () => void;
}

const DefaultMenu = ({
menus,
recentRegisterMode,
selectedTags,
setSelectedTags,
toggleRecentRegisterMode,
}: IDefaultMenuProps) => {
const onSelectTag = (name: string) => {
if (selectedTags.includes(name)) {
setSelectedTags(selectedTags.filter((tag) => tag !== name));
} else {
setSelectedTags([...selectedTags, name]);
}
};
return (
<>
<div style={{ display: 'flex' }}>
{menus.map((menu: ISubFolderProps | ITagProps) => (
<div key={menu.name}>
{'tag_id' in menu && (
<Chip
key={menu.tag_id}
name={menu.name}
light
selected={selectedTags.includes(menu.name)}
onSelectTag={onSelectTag}
/>
)}
{!('tag_id' in menu) && (
<CategoryPageStyles.Menu
to={`/category/${menu.topCategoryId}/${menu.categoryId}`}
key={`${menu.name}-${menu.categoryId}`}
>
{menu.name}
</CategoryPageStyles.Menu>
)}
</div>
))}
</div>
<CategoryPageStyles.ModeWrap onClick={toggleRecentRegisterMode}>
<CategoryPageStyles.Mode>
{recentRegisterMode ? '최근등록순' : '최근영상순'}
</CategoryPageStyles.Mode>
{recentRegisterMode ? (
<ChangeBottomSvg width={24} height={24} />
) : (
<ChangeTopSvg width={24} height={24} />
)}
</CategoryPageStyles.ModeWrap>
</>
);
};

export default DefaultMenu;
72 changes: 72 additions & 0 deletions src/components/category/VideoSelectMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import * as CategoryPageStyles from '@/styles/category/index.style';
import GarbageSvg from '@/assets/icons/garbage.svg?react';
import CloseSvg from '@/assets/icons/close.svg?react';
import { useState } from 'react';
import { CategorySelectBox } from '../SummaryPage/SummaryDetailBox/CategorySelectBox';
import { IFolderProps } from 'types/category';

interface IVideoSelectMenuProps {
categories: IFolderProps[];
totalVideoCount: number;
checkedVideos: number[];
setCheckedVideos: React.Dispatch<React.SetStateAction<number[]>>;
handleDeleteVideos: () => void;
allCheckBtnHandler: () => void;
}

const VideoSelectMenu = ({
categories,
totalVideoCount,
checkedVideos,
setCheckedVideos,
handleDeleteVideos,
allCheckBtnHandler,
}: IVideoSelectMenuProps) => {
const [selectedCategoryId, setSelectedCategoryId] = useState(
categories.length ? categories[0].categoryId : -1,
);

const handleSelectCategory = (categoryId: number) => {
setSelectedCategoryId(categoryId);
};

const onFileClick = (e: React.MouseEvent) => {
e.stopPropagation();
// 비디오 이동 API 호출 후 모든 비디오 받아오는 API 재호출로 최신화하기
};
return (
<CategoryPageStyles.SelectModeWrap>
<div>
<CategoryPageStyles.AllSelectBtn onClick={allCheckBtnHandler}>
{checkedVideos.length === totalVideoCount ? '모두 삭제' : '모두 선택'}
</CategoryPageStyles.AllSelectBtn>
<CategoryPageStyles.SelectedCount>
{checkedVideos.length}개 선택
</CategoryPageStyles.SelectedCount>
</div>
<CategoryPageStyles.CardManagement>
<CategoryPageStyles.DropdownWrap>
<CategorySelectBox
selectedCategoryId={selectedCategoryId}
onSelect={handleSelectCategory}
onFileClick={onFileClick}
/>
</CategoryPageStyles.DropdownWrap>
<CategoryPageStyles.ManagementBoxGray onClick={handleDeleteVideos}>
<GarbageSvg width={28} height={28} />
</CategoryPageStyles.ManagementBoxGray>
<CategoryPageStyles.ManagementBox>
<CloseSvg
width={28}
height={28}
onClick={() => {
setCheckedVideos([]);
}}
/>
</CategoryPageStyles.ManagementBox>
</CategoryPageStyles.CardManagement>
</CategoryPageStyles.SelectModeWrap>
);
};

export default VideoSelectMenu;
23 changes: 23 additions & 0 deletions src/components/common/chip/Chip.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import theme from '@/styles/theme';
import styled from 'styled-components';

export const ChipContainer = styled.div`
cursor: pointer;
margin-right: 18px;
margin-bottom: 18px;
padding: 3px 9.5px;
background-color: ${theme.color.gray100};
border-radius: 8px;
color: ${theme.color.gray400};
${theme.typography.Caption1};

&.light {
border: 1px solid ${theme.color.gray200};
background-color: ${theme.color.white};
}

&.selected {
border-color: ${theme.color.gray300};
background-color: ${theme.color.gray100};
}
`;
19 changes: 19 additions & 0 deletions src/components/common/chip/Chip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ChipContainer } from './Chip.style';

interface IChipProps {
name: string;
light?: boolean;
selected?: boolean;
onSelectTag?: (name: string) => void;
}

const Chip = ({ name, light, selected, onSelectTag }: IChipProps) => {
return (
<ChipContainer
className={`${light && 'light'} ${selected && 'selected'}`}
onClick={() => onSelectTag && onSelectTag(name)}
>{`# ${name}`}</ChipContainer>
);
};

export default Chip;
1 change: 0 additions & 1 deletion src/hooks/useMoveCategory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const useMoveCategory = () => {
grabedCategory.current!.categoryId,
topId,
);
console.log(res);
if (res.isSuccess) {
await updateCategories();
navigate(`/category/${grabedCategory.current?.topCategoryId}`);
Expand Down
Loading
Loading