Skip to content

Commit

Permalink
Merge pull request #48 from teamViNO/feature-028
Browse files Browse the repository at this point in the history
feature-028: 추천 영상 모달 구현
  • Loading branch information
whistleJs authored Feb 8, 2024
2 parents 08a2b79 + 78e290f commit 1e52b84
Show file tree
Hide file tree
Showing 13 changed files with 289 additions and 33 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
"dependencies": {
"@types/jest": "^29.5.11",
"@types/node": "^20.11.9",
"@types/react-modal": "^3.16.3",
"axios": "^1.6.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-modal": "^3.16.1",
"react-router-dom": "^6.21.2",
"recoil": "^0.7.7",
"recoil-persist": "^5.1.0",
Expand Down
7 changes: 6 additions & 1 deletion src/apis/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
DeleteAlarmRequest,
DeleteAlarmResponse,
} from '@/models/alarm';

import { getNicknameResponse } from '@/models/user';
import axios from './config/instance';

const PREFIX = '/user';
Expand Down Expand Up @@ -53,3 +53,8 @@ export const joinAPI = (data: JoinRequest) => {
export const socialAccountAPI = (code: string) => {
return axios.get(`/sign-up/success?code=${code}`);
};

export const getNicknameAPI = () => {
return axios.get<APIResponse<getNicknameResponse>>(PREFIX + '/myPage/myInfo');
};

Binary file added src/assets/card-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 15 additions & 9 deletions src/components/Home/InsightVideos.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React from 'react';

import React, { useState } from 'react';
import { InsightVideosContainer } from '@/styles/HomepageStyle';
import Card from '../category/Card';
import { cardDummy } from '../category/Card';

interface InsightVideosProps {
username: string;
popularHashtags: string[];
}

const InsightVideos: React.FC<InsightVideosProps> = ({
username,
popularHashtags,
}) => {
const formattedHashtags = popularHashtags.map((tag) => '#' + tag);
const InsightVideos: React.FC<InsightVideosProps> = ({ username, popularHashtags }) => {
const formattedHashtags = popularHashtags.map(tag => '#' + tag);
const [categoryItems] = useState<cardDummy[]>([]);
const [checkedItems, setCheckedItems] = useState<boolean[]>([]);

return (
<InsightVideosContainer>
Expand All @@ -23,10 +23,16 @@ const InsightVideos: React.FC<InsightVideosProps> = ({
콘텐츠에요!
</h4>
</div>
<div className="insight-videos">{/* <Card /> */}</div>
<div className='insight-videos'>
<Card
categoryItems={categoryItems}
checkedItems={checkedItems}
setCheckedItems={setCheckedItems}
/>
</div>
</div>
</InsightVideosContainer>
);
};
};

export default InsightVideos;
11 changes: 2 additions & 9 deletions src/components/Home/RecentVideos.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import React from 'react';
import {
RecentVideosContainer,
VideoButton,
VideosSubtitle,
VideosTitle,
} from '@/styles/HomepageStyle';
import React from 'react'
import { RecentVideosContainer, VideoButton, VideosSubtitle, VideosTitle } from '@/styles/HomepageStyle';
// import Card from '../category/Card';

import CardImage from '@/assets/empty-video.png';

const RecentVideos: React.FC = () => {
return (
<RecentVideosContainer>
Expand Down
24 changes: 14 additions & 10 deletions src/components/Home/SearchYoutube.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { useState, ChangeEvent, FormEvent } from 'react';
import theme from '@/styles/theme';
import ProgressBar from './ProgressBar';
import { useSetRecoilState } from 'recoil';
import { recommendationModalState } from '@/stores/modal';

import {
SearchForm,
Expand All @@ -22,13 +24,16 @@ const SearchYoutube: React.FC<SearchBarProps> = ({ onSearch }) => {
const [isTextValid, setIsTextValid] = useState(true);
const [isConverting, setIsConverting] = useState(false);

const setModalOpen = useSetRecoilState(recommendationModalState);

const handleSubmit = (event: FormEvent) => {
event.preventDefault();
if (isValidYoutubeLink(inputLink)) {
setIsButtonValid(true);
setIsTextValid(true);
setIsConverting(true);
onSearch(inputLink);
setIsButtonValid(true);
setIsTextValid(true);
setIsConverting(true);
onSearch(inputLink);
setModalOpen(true);
} else {
setIsButtonValid(false);
setIsTextValid(false);
Expand Down Expand Up @@ -103,13 +108,12 @@ const SearchYoutube: React.FC<SearchBarProps> = ({ onSearch }) => {
placeholder="https://youtube.com/..."
/>
</div>
<SearchButton
<SearchButton
type="submit"
style={{
color: isButtonValid ? 'white' : theme.color.gray300,
backgroundColor: isButtonValid
? theme.color.gray500
: theme.color.gray100,
// onClick={ handleClick }
style={{
color: isButtonValid ? 'white' : theme.color.gray300,
backgroundColor: isButtonValid ? theme.color.gray500 : theme.color.gray100
}}
>
변환하기
Expand Down
2 changes: 1 addition & 1 deletion src/components/category/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
import VideoTag from '../common/videoTag';
import * as CardStyles from '@/styles/category/Card.style';

interface cardDummy {
export interface cardDummy {
imageURL: string;
title: string;
summary: string;
Expand Down
74 changes: 74 additions & 0 deletions src/components/modals/RecommendationModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { useState, useEffect } from 'react';
import { useRecoilState } from 'recoil';
import { recommendationModalState } from '@/stores/modal';
import useOutsideClick from '@/hooks/useOutsideClick';

import emptyvideoImg from '@/assets/empty-video.png';
import CloseIcon from '@/assets/icons/close.svg?react';
import cardimageImg from '@/assets/card-image.png';

import { RecommendationModalContainer } from '@/styles/modals/RecommendationModal.style';
import { getNicknameAPI } from '@/apis/user';

const RecommendationModal: React.FC = () => {
const [nickname, setNickname] = useState('');
const [modalOpen, setModalOpen] = useRecoilState(recommendationModalState);

const closeModal = () => {
setModalOpen(false);
}

const [modalRef] = useOutsideClick<HTMLDivElement>(closeModal);

useEffect(() => {
async function fetchNickname() {
const response = await getNicknameAPI();
setNickname(response.data.result.nickname);
}

fetchNickname();
}, []);


return (
<RecommendationModalContainer
isOpen={modalOpen}>
<div className='modal-container' ref={modalRef}>
<div className='modal-inform'>
<div className='close-btn' onClick={closeModal}>
<CloseIcon width={28} height={28}/>
</div>
<div className='inform-wrapper'>
<div className='inform'>
<img src={emptyvideoImg} alt="emptyvideoImg" width={56} height={56} />
<div className='inform-text'>
기다리는 동안 이런 영상은 어때요?
</div>
<div className='inform-subtext'>
{nickname}님을 위해 미리 정리 된 영상을 소개해드릴게요
</div>
</div>
</div>
</div>
<div className='modal-card'>
<img src={cardimageImg} alt='card-image' width={290}/>
<div className='card-text'>
<h2 className='card-title'>
우리는 카카오워크로 일해요
</h2>
<div className='hashtag'>
<span className='card-hashtag'>
# 디자인
</span>
<span className='card-hashtag'>
# 진로
</span>
</div>
</div>
</div>
</div>
</RecommendationModalContainer>
);
};

export default RecommendationModal;
5 changes: 5 additions & 0 deletions src/models/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,8 @@ export interface JoinRequest {

export interface JoinResponse {
}


export interface getNicknameResponse {
nickname: string;
}
6 changes: 6 additions & 0 deletions src/pages/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import {
} 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';

export interface Video {
id: string;
Expand All @@ -19,9 +22,12 @@ const HomePage: React.FC = () => {
console.log(value);
};

const isModalOpen = useRecoilValue(recommendationModalState);

return (
<HomePageContainer>
<SearchYoutube onSearch={handleSearch} />
{isModalOpen && <RecommendationModal /> }
<RecentVideos />
<InsightVideos username="여울" popularHashtags={['디자인', '진로', '브랜딩']} />
</HomePageContainer>
Expand Down
5 changes: 5 additions & 0 deletions src/stores/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ export const summaryTransformModalState = atom({
key: 'summary-transform-modal',
default: false,
});

export const recommendationModalState = atom({
key: 'recommendationModal',
default: false,
});
108 changes: 108 additions & 0 deletions src/styles/modals/RecommendationModal.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import styled from 'styled-components';
import theme from '../theme';

export const RecommendationModalContainer = styled.div<{ isOpen: boolean }>`
position: fixed;
z-index: 100;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
.modal-container {
padding: 40px 61px;
display: flex;
flex-direction: column;
align-items: center;
width: 700px;
height: 463.13px;
position: relative;
background: white;
border-radius: 20px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
.close-btn {
width: 600px;
display: flex;
justify-content: flex-end;
cursor: pointer;
}
.inform-wrapper {
width: 600px;
height: 144px;
display: flex;
justify-content: center;
align-items: center;
}
.inform {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.inform-text {
margin-top: 12px;
margin-bottom: 12px;
color: ${theme.color.gray500};
font-size: 24px;
line-height: 1.6em;
}
.inform-subtext {
color: ${theme.color.gray300};
font-size: 16px;
line-height: 1.6em;
}
.modal-card {
width: 578px;
height: 163.13px;
margin-top: 48px;
display: flex;
flex-direction: row;
align-items: flex-start;
cursor: pointer;
}
.modal-card img {
border: none;
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
width: 290px;
height: auto;
}
.card-text {
width: 288px;
padding: 24px 20px;
}
.card-title {
width: 248px;
height: 78px;
font-size: 16px;
font-weight: bold;
text-align: left;
}
.hashtag {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.card-hashtag {
color: ${theme.color.gray400};
padding: 6px 10px;
border-radius: 8px;
background-color: ${theme.color.gray100};
margin-right: 8px;
}
`
Loading

0 comments on commit 1e52b84

Please sign in to comment.