Skip to content

Commit

Permalink
Merge pull request #121 from teamViNO/feature-081
Browse files Browse the repository at this point in the history
feature-081: 영상 변환 시 알림에 추가하기
  • Loading branch information
whistleJs authored Feb 20, 2024
2 parents 15210ee + 276353f commit d749575
Show file tree
Hide file tree
Showing 12 changed files with 213 additions and 101 deletions.
13 changes: 5 additions & 8 deletions src/apis/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
FindEmailRequest,
FindPasswordResponse,
FindPasswordRequest,
CreateVideoAlarmRequest
CreateVideoAlarmRequest,
} from '@/models/user';
import {
AlarmResponse,
Expand Down Expand Up @@ -93,11 +93,8 @@ export const createVideoAlarmAPI = (
PREFIX + `/videoAlarm/${videoId}/${status}`,
data,
);
}
};

export const findPasswordAPI = (data : FindPasswordRequest) => {
return axios.post<FindPasswordResponse>(
PREFIX + '/findPassword',
data
);
}
export const findPasswordAPI = (data: FindPasswordRequest) => {
return axios.post<FindPasswordResponse>(PREFIX + '/findPassword', data);
};
10 changes: 8 additions & 2 deletions src/components/Home/RecentVideos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import { IVideoProps } from 'types/videos';

interface IRecentVideosProp {
videos: IVideoProps[];
searchRef: React.RefObject<HTMLInputElement>;
}

const RecentVideos = ({ videos }: IRecentVideosProp) => {
const RecentVideos = ({ videos, searchRef }: IRecentVideosProp) => {
return (
<RecentVideosContainer>
<div className="container">
Expand All @@ -39,7 +40,12 @@ const RecentVideos = ({ videos }: IRecentVideosProp) => {
<VideoButton
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
>
<h2 className="button-text">영상 정리해보기</h2>
<h2
className="button-text"
onClick={() => searchRef.current?.focus()}
>
영상 정리해보기
</h2>
</VideoButton>
</div>
)}
Expand Down
45 changes: 11 additions & 34 deletions src/components/Home/SearchYoutube.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import React, { useState, FormEvent } from 'react';
import { useNavigate } from 'react-router-dom';
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';

import { createVideoAPI } from '@/apis/videos';
import { useRecoilState, useSetRecoilState } from 'recoil';

import VideoIcon from '@/assets/icons/video.svg?react';
import WarningIcon from '@/assets/icons/warning.svg?react';
Expand All @@ -15,30 +12,31 @@ import {
SearchContainer,
} from '@/styles/HomepageStyle';

import { recommendationModalState, errorModalState } from '@/stores/modal';
import { recommendationModalState } from '@/stores/modal';

import {
modelingDataState,
modelingProgressState,
modelingStatusState,
videoLinkState,
} from '@/stores/model-controller';
import { userTokenState } from '@/stores/user';

import { validateYoutubeLink } from '@/utils/validation';

import ProgressBar from './ProgressBar';
import useCreateVideo from '@/hooks/useCreateVideo';

const SearchYoutube = () => {
const navigate = useNavigate();
type Props = {
searchRef: React.RefObject<HTMLInputElement>;
};

const userToken = useRecoilValue(userTokenState);
const SearchYoutube = ({ searchRef }: Props) => {
const setIsOpenModal = useSetRecoilState(recommendationModalState);
const setIsOpenErrorModal = useSetRecoilState(errorModalState);
const setModelingData = useSetRecoilState(modelingDataState);
const setVideoLink = useSetRecoilState(videoLinkState);
const setProgress = useSetRecoilState(modelingProgressState);
const [status, setStatus] = useRecoilState(modelingStatusState);
const [modelingData, setModelingData] = useRecoilState(modelingDataState);
const { createVideo } = useCreateVideo();

const [inputLink, setInputLink] = useState('');

Expand Down Expand Up @@ -97,28 +95,6 @@ const SearchYoutube = () => {
setModelingData(null);
};

const handleClickCreateVideoButton = async () => {
if (!modelingData) return;

if (userToken) {
try {
const { video_id } = (await createVideoAPI(modelingData)).data.result;

navigate(`/summary/${video_id}`);
setModelingData(null);
} catch (e) {
console.error(e);
setIsOpenErrorModal(true);
}
} else {
navigate('/summary/guest');
}

setVideoLink(null);
setStatus('NONE');
setProgress(0);
};

return (
<>
<SearchContainer className="dark-section">
Expand Down Expand Up @@ -161,6 +137,7 @@ const SearchYoutube = () => {
disabled={status === 'CONTINUE'}
onChange={handleChangeInput}
placeholder="https://youtube.com/..."
ref={searchRef}
/>
</div>

Expand All @@ -171,7 +148,7 @@ const SearchYoutube = () => {
color: theme.color.gray500,
backgroundColor: theme.color.green400,
}}
onClick={handleClickCreateVideoButton}
onClick={createVideo}
>
영상 읽기
</SearchButton>
Expand Down
40 changes: 39 additions & 1 deletion src/components/layout/header/alarm/AlarmItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,32 @@ import ErrorImage from '@/assets/Error.png';
import { Container } from '@/styles/layout/header/alarm/AlarmItem.style';

import { diffTime } from '@/utils/date';
import { useRecoilValue } from 'recoil';
import {
modelingProgressState,
modelingStatusState,
} from '@/stores/model-controller';
import theme from '@/styles/theme';
import { confirmSelectAlarmAPI } from '@/apis/user';

type Props = {
alarm: IAlarm;
selectIdList: number[];
onUpdateSelectIdList: (list: number[]) => void;
onClose: () => void;
onRefresh: () => void;
};

const AlarmItem = ({
alarm,
selectIdList,
onUpdateSelectIdList,
onClose,
onRefresh,
}: Props) => {
const navigate = useNavigate();
const status = useRecoilValue(modelingStatusState);
const progress = useRecoilValue(modelingProgressState);
const isSelected = selectIdList.indexOf(alarm.alarm_id) > -1;

const type = () => {
Expand Down Expand Up @@ -58,11 +69,21 @@ const AlarmItem = ({
return `${second}초`;
};

const handleClick = () => {
const handleClick = async () => {
if (alarm.type === 'notice') {
navigate('/guide');
onClose();
}
if (alarm.type === 'video' && !alarm.is_confirm && alarm.alarm_id !== 999) {
try {
await confirmSelectAlarmAPI({ alarms: [alarm.alarm_id] });
onRefresh();
navigate(`/summary/${alarm.video_id}`);
onClose();
} catch (e) {
console.error(e);
}
}
};

const handleClickRemoveButton: React.MouseEventHandler<HTMLButtonElement> = (
Expand Down Expand Up @@ -110,6 +131,23 @@ const AlarmItem = ({
<span>{alarm.content}</span>
</div>
</div>
{status !== 'NONE' && alarm.alarm_id === 999 && (
<div className="progress-wrap">
<div className="progress-bar">
<div
style={{
width: `${progress}%`,
backgroundColor:
status === 'ERROR' ? theme.color.red : theme.color.green300,
}}
/>
</div>

<span className="progress-text">
{status === 'ERROR' ? '변환 중 오류' : `${progress}%`}
</span>
</div>
)}
</Container>
);
};
Expand Down
1 change: 1 addition & 0 deletions src/components/layout/header/alarm/AlarmList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ const AlarmList = ({ alarmList, onRefresh, onClose }: Props) => {
selectIdList={selectIdList}
onUpdateSelectIdList={setSelectIdList}
onClose={onClose}
onRefresh={onRefresh}
/>
))}
</div>
Expand Down
43 changes: 27 additions & 16 deletions src/components/layout/header/alarm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { useEffect, useState } from 'react';
import { useRecoilValue } from 'recoil';

import { getAlarmAPI } from '@/apis/user';
import { useRecoilState, useRecoilValue } from 'recoil';

import NotifyOffIcon from '@/assets/icons/notify-off.svg?react';
import NotifyOnIcon from '@/assets/icons/notify-on.svg?react';

import useOutsideClick from '@/hooks/useOutsideClick';

import { IAlarm } from '@/models/alarm';

import { modelingStatusState } from '@/stores/model-controller';

import * as HeaderStyle from '@/styles/layout/header';

import AlarmList from './AlarmList';
import { userAlarmState } from '@/stores/user';
import useGetAlarm from '@/hooks/useGetAlarm';

type Props = {
isDark: boolean;
Expand All @@ -23,26 +21,39 @@ type Props = {
const Alarm = ({ isDark }: Props) => {
const status = useRecoilValue(modelingStatusState);
const [isOpen, setIsOpen] = useState(false);
const [alarmList, setAlarmList] = useState<IAlarm[]>([]);
const [alarmList, setAlarmList] = useRecoilState(userAlarmState);
const { getAlarm } = useGetAlarm();

const [alarmRef] = useOutsideClick<HTMLDivElement>(() => setIsOpen(false));

const hasNotReadAlarm = alarmList.find((item) => !item.is_confirm);

const callAPI = async () => {
const { alarms } = (await getAlarmAPI()).data.result;

setAlarmList(alarms);
};

useEffect(() => {
callAPI();
getAlarm();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
if (status === 'ERROR') {
callAPI();
if (status === 'ERROR' || status === 'COMPLETE') {
getAlarm();
}

if (status === 'CONTINUE') {
setAlarmList([
{
state: 'success',
type: 'video',
alarm_id: 999,
title: '열심히 영상을 변환하는 중이에요!',
content: '잠시후 멋진 글을 만날 수 있어요:)',
is_confirm: 0,
created_at: new Date().toString(),
updated_at: new Date().toString(),
},
...alarmList,
]);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [status]);

return (
Expand All @@ -61,7 +72,7 @@ const Alarm = ({ isDark }: Props) => {
{isOpen && (
<AlarmList
alarmList={alarmList}
onRefresh={callAPI}
onRefresh={getAlarm}
onClose={() => setIsOpen(false)}
/>
)}
Expand Down
Loading

0 comments on commit d749575

Please sign in to comment.