Skip to content

Commit

Permalink
Merge branch 'dev' into feature-058
Browse files Browse the repository at this point in the history
  • Loading branch information
whistleJs committed Feb 13, 2024
2 parents 59cde6a + e37247a commit 5ded347
Show file tree
Hide file tree
Showing 16 changed files with 253 additions and 215 deletions.
7 changes: 5 additions & 2 deletions src/apis/social-account.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { APIResponse } from '@/models/config/axios';
import { LoginResponse } from '@/models/user';

import axios from './config/instance';

export const kakaoLoginAPI = (token: string) => {
return axios.get(`/kakao-login?token=${token}`);
export const kakaoLoginAPI = (code: string) => {
return axios.get<APIResponse<LoginResponse>>(`/kakao-login?code=${code}`);
};
23 changes: 23 additions & 0 deletions src/apis/videos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { APIResponse } from '@/models/config/axios';
import { IVideo, VideoVersionType } from '@/models/video';

import axios from './config/instance';
import axiosInstance from './config/instance';
import { IVideoProps } from 'types/videos';

const PREFIX = '/videos';

Expand All @@ -11,3 +13,24 @@ export const getVideoAPI = (
) => {
return axios.get<APIResponse<IVideo>>(PREFIX + `/${videoId}/${versionId}`);
};

export const deleteVideos = async (videos: number[]) => {
const response = await axiosInstance.delete('/videos/selectDelete', {
data: { videos },
});
return response.data;
};

export const getRecentVideos = async (): Promise<
APIResponse<Record<'videos', IVideoProps[]>>
> => {
const response = await axiosInstance.get('/videos/recent');
return response.data;
};

export const getVideoById = async (
videoId: number,
): Promise<APIResponse<Record<'videos', IVideoProps[]>>> => {
const response = await axiosInstance.get(`/videos/${videoId}`);
return response.data;
};
6 changes: 3 additions & 3 deletions src/components/Home/InsightVideos.tsx
Original file line number Diff line number Diff line change
@@ -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 'types/videos';

interface InsightVideosProps {
username: string;
Expand All @@ -13,8 +13,8 @@ const InsightVideos: React.FC<InsightVideosProps> = ({
popularHashtags,
}) => {
const formattedHashtags = popularHashtags.map((tag) => '#' + tag);
const [categoryItems] = useState<cardDummy[]>([]);
const [checkedItems, setCheckedItems] = useState<boolean[]>([]);
const [categoryItems] = useState<IVideoProps[]>([]);
const [checkedItems, setCheckedItems] = useState<number[]>([]);

return (
<InsightVideosContainer>
Expand Down
98 changes: 30 additions & 68 deletions src/components/category/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,86 +1,48 @@
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 {
video_id: number;
category_id: number;
title: string;
description: string;
image: string;
link: string;
created_at: string;
youtube_created_at: string;
tag: [{ name: string }];
}
import VideoTag from '../common/videoTag';
import { IVideoProps } from 'types/videos';

interface ICardProps {
videos: cardDummy[];
checkedVideos: boolean[];
setCheckedVideos: (value: boolean[]) => void;
videos: IVideoProps[];
checkedVideos: number[];
setCheckedVideos: (value: number[]) => void;
}

const Card: React.FC<ICardProps> = ({
videos,
checkedVideos,
setCheckedVideos,
}) => {
const [isShadow, setIsShadow] = useState<boolean[]>(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));
const handleCheckBox = (videoId: number) => {
if (checkedVideos.includes(videoId)) {
setCheckedVideos(checkedVideos.filter((id) => id !== videoId));
} else {
setCheckedVideos([...checkedVideos, videoId]);
}
}, [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 checkBoxHandler = (id: number) => {
const prev = [...checkedVideos];
prev[id] = !prev[id];
setCheckedVideos(prev);
};
return (
<CardStyles.Container>
{videos.map((video, idx) => (
<CardStyles.Wrap
key={`${video.title}-wrap`}
onMouseEnter={() => handleMouseEnter(idx)}
onMouseLeave={() => handleMouseLeave(idx)}
>
<CardStyles.Image
src={video.image}
alt="썸네일 이미지"
key={`${video.title}-image`}
/>
{isShadow[idx] && (
<CardStyles.CheckBox
type="checkbox"
checked={checkedVideos[idx]}
onChange={() => checkBoxHandler(idx)}
/>
)}
<CardStyles.Content key={`${video.title}-card-content`}>
{videos.map((video) => (
<CardStyles.Wrap key={`${video.title}-wrap`}>
<CardStyles.Image source={video.image}>
<CardStyles.CheckBoxWrap
className={checkedVideos.length > 0 ? 'activated' : ''}
>
<CardStyles.CheckBox
type="checkbox"
checked={checkedVideos.includes(video.video_id)}
onChange={() => handleCheckBox(video.video_id)}
/>
</CardStyles.CheckBoxWrap>
</CardStyles.Image>

<CardStyles.Content
to={`/summary/${video.video_id}`}
key={`${video.title}-card-content`}
>
<CardStyles.Title key={`${video.title}`}>
{video.title}
</CardStyles.Title>
Expand Down
2 changes: 1 addition & 1 deletion src/components/category/EmptyCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const EmptyCard = () => {
관련 영상들을 모아보세요
</EmptyCardStyles.Content>
</EmptyCardStyles.ContentWrap>
<EmptyCardStyles.Button>영상 정리해보기</EmptyCardStyles.Button>
<EmptyCardStyles.Button to="/">영상 정리해보기</EmptyCardStyles.Button>
</EmptyCardStyles.Container>
);
};
Expand Down
1 change: 1 addition & 0 deletions src/components/layout/header/profile/ProfileDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const ProfileDetail = ({ onClose }: Props) => {

const handleClickLogoutButton = () => {
setUserToken(null);
navigate('/');
onClose();
};

Expand Down
17 changes: 12 additions & 5 deletions src/components/layout/sideBar/UserMode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,23 @@ const UserMode = () => {
};

const putCategoryFolder = async () => {
if (grabedCategory.current?.categoryId === dropedCategory.current) return;

let response;
if (grabedCategory.current?.topCategoryId === -1) {
subToTop(topId, grabedCategory, dropedCategory);
response = await subToTop(grabedCategory);
} else if (grabedCategory.current?.topCategoryId === null) {
topToOtherTop(grabedCategory, dropedCategory);
response = await topToOtherTop(grabedCategory, dropedCategory);
} else {
subToOtherTop(topId, grabedCategory);
response = await subToOtherTop(topId, grabedCategory);
}
// 잡은 카테고리, 놓은 카테고리 초기화
grabedCategory.current = undefined;
dropedCategory.current = undefined;
if (response) {
grabedCategory.current = undefined;
dropedCategory.current = undefined;
} else {
alert('카테고리를 옮기는데 오류가 발생했습니다.');
}
};
return (
<>
Expand Down
79 changes: 24 additions & 55 deletions src/hooks/useMoveCategory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,15 @@ import {
putSubToTop,
putTopToOtherTop,
} from '@/apis/category';
import { categoryState } from '@/stores/category';
import handleCategory from '@/utils/handleCategory';
import { useNavigate } from 'react-router-dom';
import { useRecoilState } from 'recoil';
import { ISubFolderProps } from 'types/category';
import useUpdateCategories from './useUpdateCategories';

const useMoveCategory = () => {
const [categories, setCategories] = useRecoilState(categoryState);
const navigate = useNavigate();
const {
deleteSubCategory,
deleteTopCategory,
insertCategory,
insertSubToTopCategory,
} = handleCategory();
const { updateCategories } = useUpdateCategories();

const subToOtherTop = (
const subToOtherTop = async (
topId: number,
grabedCategory: React.MutableRefObject<ISubFolderProps | undefined>,
) => {
Expand All @@ -29,72 +21,49 @@ const useMoveCategory = () => {
}
// 하위에 있는 폴더를 다른 상위 폴더로 이동하는 기능
// 카테고리 이동1
const deleteResponse = deleteSubCategory(
categories,
const res = await putSubToOtherTop(
grabedCategory.current!.categoryId,
topId,
grabedCategory.current?.categoryId,
);
const insertResponse = insertCategory(
deleteResponse,
grabedCategory.current?.topCategoryId,
grabedCategory.current!,
);
putSubToOtherTop(grabedCategory.current!.categoryId, topId);
setCategories([...insertResponse]);
navigate(`/category/${grabedCategory.current?.topCategoryId}`);
console.log(grabedCategory.current?.name);
console.log(res);
if (res.isSuccess) {
await updateCategories();
navigate(`/category/${grabedCategory.current?.topCategoryId}`);
}
return res.isSuccess;
};

const subToTop = (
topId: number,
const subToTop = async (
grabedCategory: React.MutableRefObject<ISubFolderProps | undefined>,
dropedCategory: React.MutableRefObject<number | undefined>,
) => {
if (grabedCategory.current?.name === '기타') {
alert(`'기타' 폴더는 이동할 수 없습니다.`);
return;
}
// 하위에 있는 폴더를 상위로 올리는 기능
// 카테고리 이동2
const deleteResponse = deleteSubCategory(
categories,
topId,
grabedCategory.current?.categoryId,
);
const insertResponse = insertSubToTopCategory(
deleteResponse,
dropedCategory.current,
grabedCategory.current!,
);
putSubToTop(grabedCategory.current!.categoryId);
setCategories([...insertResponse]);
const res = await putSubToTop(grabedCategory.current!.categoryId);
if (res.isSuccess) {
await updateCategories();
}
return res.isSuccess;
};

const topToOtherTop = (
const topToOtherTop = async (
grabedCategory: React.MutableRefObject<ISubFolderProps | undefined>,
dropedCategory: React.MutableRefObject<number | undefined>,
) => {
// 상위에 있는 폴더를 다른 상위 폴더로 넣는 기능
// 카테고리 이동3
const deleteResponse = deleteTopCategory(
categories,
const res = await putTopToOtherTop(
grabedCategory.current!.categoryId,
);
const insertResponse = insertCategory(
deleteResponse,
dropedCategory.current!,
{
categoryId: grabedCategory.current!.categoryId,
name: grabedCategory.current!.name,
topCategoryId: dropedCategory.current!,
},
);
putTopToOtherTop(
grabedCategory.current!.categoryId,
dropedCategory.current!,
);
setCategories(insertResponse);
navigate(`/category/${dropedCategory.current}`);
if (res.isSuccess) {
await updateCategories();
navigate(`/category/${dropedCategory.current}`);
}
return res.isSuccess;
};

return { subToOtherTop, subToTop, topToOtherTop };
Expand Down
Loading

0 comments on commit 5ded347

Please sign in to comment.