diff --git a/src/components/Home/InsightVideos.tsx b/src/components/Home/InsightVideos.tsx index 6075a38..254e0d1 100644 --- a/src/components/Home/InsightVideos.tsx +++ b/src/components/Home/InsightVideos.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { InsightVideosContainer } from '@/styles/HomepageStyle'; import Card from '../category/Card'; -import { cardDummy } from '../category/Card'; +import { IVideoProps } from '../category/Card'; interface InsightVideosProps { username: string; @@ -13,8 +13,8 @@ const InsightVideos: React.FC = ({ popularHashtags, }) => { const formattedHashtags = popularHashtags.map((tag) => '#' + tag); - const [categoryItems] = useState([]); - const [checkedItems, setCheckedItems] = useState([]); + const [categoryItems] = useState([]); + const [checkedItems, setCheckedItems] = useState([]); return ( diff --git a/src/components/category/Card.tsx b/src/components/category/Card.tsx index 7239bc4..f07f41c 100644 --- a/src/components/category/Card.tsx +++ b/src/components/category/Card.tsx @@ -1,8 +1,7 @@ -import React, { useEffect, useState } from 'react'; -import VideoTag from '../common/videoTag'; +import React, { useEffect } from 'react'; import * as CardStyles from '@/styles/category/Card.style'; -export interface cardDummy { +export interface IVideoProps { video_id: number; category_id: number; title: string; @@ -15,9 +14,9 @@ export interface cardDummy { } interface ICardProps { - videos: cardDummy[]; - checkedVideos: boolean[]; - setCheckedVideos: (value: boolean[]) => void; + videos: IVideoProps[]; + checkedVideos: number[]; + setCheckedVideos: (value: number[]) => void; } const Card: React.FC = ({ @@ -25,62 +24,35 @@ const Card: React.FC = ({ checkedVideos, setCheckedVideos, }) => { - const [isShadow, setIsShadow] = useState(new Array(6).fill(false)); + useEffect(() => {}, [checkedVideos]); - useEffect(() => { - if (checkedVideos.includes(true)) { - // 1개 이상 클릭 시 모든 hover event 활성화 - setIsShadow(isShadow.map(() => true)); - } else if (!isShadow.includes(false)) { - //모든 hover 활성화, 모든 체크 비활성화 시 모든 hover 활성화 제거 - setIsShadow(isShadow.map(() => false)); - } - }, [checkedVideos]); - - const handleMouseEnter = (id: number) => { - const prev = checkedVideos.includes(true) - ? [...isShadow] - : new Array(isShadow.length).fill(false); - // 체크박스 미선택 이동 시 isshadow 중복 작동으로 인해 방식 변경 - prev[id] = true; - setIsShadow(prev); - }; - - const handleMouseLeave = (id: number) => { - if (!checkedVideos.includes(true)) { - // 선택되면 유지 - const prev = [...isShadow]; - prev[id] = false; - setIsShadow(prev); + const handleCheckBox = (videoId: number) => { + if (checkedVideos.includes(videoId)) { + setCheckedVideos(checkedVideos.filter((id) => id !== videoId)); + } else { + setCheckedVideos([...checkedVideos, videoId]); } }; - - const checkBoxHandler = (id: number) => { - const prev = [...checkedVideos]; - prev[id] = !prev[id]; - setCheckedVideos(prev); - }; return ( - {videos.map((video, idx) => ( - handleMouseEnter(idx)} - onMouseLeave={() => handleMouseLeave(idx)} - > - - {isShadow[idx] && ( - checkBoxHandler(idx)} - /> - )} - + {videos.map((video) => ( + + + 0 ? 'activated' : ''} + > + handleCheckBox(video.video_id)} + /> + + + + {video.title} @@ -88,14 +60,14 @@ const Card: React.FC = ({ {video.description} - {video.tag.map((tag) => ( + {/* {video.tag.map((tag) => ( - ))} + ))} */} diff --git a/src/pages/CategoryPage.tsx b/src/pages/CategoryPage.tsx index eda9aa3..8e8167d 100644 --- a/src/pages/CategoryPage.tsx +++ b/src/pages/CategoryPage.tsx @@ -7,7 +7,7 @@ import GarbageSvg from '@/assets/icons/garbage.svg?react'; import FolderSvg from '@/assets/icons/open-file.svg?react'; import CloseSvg from '@/assets/icons/close.svg?react'; import * as CategoryPageStyles from '@/styles/category/index.style'; -import Card from '@/components/category/Card'; +import Card, { IVideoProps } from '@/components/category/Card'; import axiosInstance from '@/apis/config/instance'; import { useRecoilValue } from 'recoil'; import { categoryState } from '@/stores/category'; @@ -18,9 +18,9 @@ const CategoryPage = () => { const params = useParams(); const [name, setName] = useState(''); const [menus, setMenus] = useState([]); - const [videos, setVideos] = useState([]); + const [videos, setVideos] = useState([]); const [recentRegisterMode, setRecentRegisterMode] = useState(false); - const [checkedVideos, setCheckedVideos] = useState([]); + const [checkedVideos, setCheckedVideos] = useState([]); const categories = useRecoilValue(categoryState); const toggleRecentRegisterMode = () => @@ -47,41 +47,38 @@ const CategoryPage = () => { }, [categories, params.top_folder]); const allCheckBtnHandler = () => { - if (checkedVideos.includes(false)) { - setCheckedVideos(checkedVideos.map(() => true)); + if (checkedVideos.length === videos.length) { + // 삭제 API 요청 + console.log('모두 삭제'); + setCheckedVideos([]); } else { - // 모두 삭제 + console.log('모두 선택'); + setCheckedVideos(videos.map((video) => video.video_id)); } }; const dirMoveHanlder = () => { - checkedVideos.map((value, id) => { - if (value === true) { - console.log('이동해야할 index : ', id); - } - }); + console.log(checkedVideos); }; const garbageHandler = () => { - checkedVideos.map((value, id) => { - if (value === true) { - console.log('삭제해야할 index : ', id); - } - }); + console.log(checkedVideos); }; return ( - {checkedVideos.includes(true) ? ( + {checkedVideos.length > 0 ? ( <>
- {!checkedVideos.includes(false) ? '모두 삭제' : '모두 선택'} + {checkedVideos.length === videos.length + ? '모두 삭제' + : '모두 선택'} - {checkedVideos.filter((bool) => bool === true).length}개 선택 + {checkedVideos.length}개 선택
@@ -101,7 +98,7 @@ const CategoryPage = () => { width={28} height={28} onClick={() => { - setCheckedVideos(checkedVideos.map(() => false)); + setCheckedVideos([]); }} /> diff --git a/src/styles/category/Card.style.ts b/src/styles/category/Card.style.ts index e18abd1..1a0f975 100644 --- a/src/styles/category/Card.style.ts +++ b/src/styles/category/Card.style.ts @@ -2,7 +2,45 @@ import styled from 'styled-components'; import theme from '../theme'; import checkIcon from '@/assets/icons/check.svg'; import checkedIcon from '@/assets/icons/checked.svg'; +import { Link } from 'react-router-dom'; +export const CheckBoxWrap = styled.div` + background-color: rgba(0, 0, 0, 0.5); + display: none; + + flex-direction: row-reverse; + width: 100%; + height: 100%; + + &.activated { + display: flex; + } +`; + +export const CheckBox = styled.input` + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + + width: 24px; + height: 24px; + border-radius: 100%; + background-color: ${theme.color.gray300}; + background-image: url(${checkIcon}); + background-repeat: no-repeat; + background-position: center; + border: 1.5px solid ${theme.color.white}; + color: ${theme.color.white}; + margin: 12px; + + &:checked { + border: 1.5px solid ${theme.color.green300}; + background-color: ${theme.color.green300}; + background-image: url(${checkedIcon}); + background-repeat: no-repeat; + background-position: center; + } +`; export const Container = styled.div` display: grid; grid-template-columns: repeat(3, auto); @@ -17,9 +55,16 @@ export const Wrap = styled.div` border-radius: 16px; overflow: hidden; box-shadow: 0px 4px 40px 0px rgba(0, 0, 0, 0.05); + + &:hover { + ${CheckBoxWrap} { + display: flex; + } + } `; -export const Content = styled.div` +export const Content = styled(Link)` + text-decoration: none; display: flex; flex-direction: column; padding: 24px 20px; @@ -42,36 +87,9 @@ export const ChipWrap = styled.div` flex-wrap: wrap; `; -export const CheckBox = styled.input` - appearance: none; - -webkit-appearance: none; - -moz-appearance: none; - - width: 24px; - height: 24px; - border-radius: 50%; - background-color: ${theme.color.gray300}; - background-image: url(${checkIcon}); - background-repeat: no-repeat; - background-position: center; - border: 1.5px solid ${theme.color.white}; - color: ${theme.color.white}; - - position: absolute; - margin-left: 252px; - margin-top: 13px; - - &:checked { - border: 1.5px solid ${theme.color.green300}; - background-color: ${theme.color.green300}; - background-image: url(${checkedIcon}); - background-repeat: no-repeat; - background-position: center; - } -`; - -export const Image = styled.img` - &:hover { - filter: brightness(50%); - } +export const Image = styled.div<{ source: string }>` + background-image: url(${(props) => props.source}); + width: 290px; + height: 163px; + background-size: 100%; `;