Skip to content

Commit

Permalink
[NDD-240] settingpage 라우터 처리 (1h/2h) (#98)
Browse files Browse the repository at this point in the history
* remove: 폴더 경로 변경

* design: 레이아웃 가장 상위 컴포넌트로 css 병합

* feat: 이전 상태에 따라 다음 페이지에 넘어가지 못하도록 구현

* feat: 페이지가 화면과 소리 설정으로 넘어가야 카메라가 켜지도록 수정

* feat: useMedia hook 수정

* style: rem 제거
  • Loading branch information
Yoon-Hae-Min authored Nov 23, 2023
1 parent 42794e0 commit 5735f4a
Show file tree
Hide file tree
Showing 13 changed files with 73 additions and 66 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Modal from '../../foundation/Modal';
import Modal from '../../../foundation/Modal';
import { css } from '@emotion/react';
import { theme } from '@/styles/theme';
import Typography from '../../foundation/Typography/Typography';
import Typography from '../../../foundation/Typography/Typography';
import useQuestionAnswerQuery from '@/hooks/queries/useQuestionAnswerQuery';
import AnswerScript from './AnswerScript';
import AnswerForm from './AnswerForm';
Expand Down
21 changes: 0 additions & 21 deletions FE/src/components/interviewSettingPage/VideoSettingBox.tsx

This file was deleted.

43 changes: 25 additions & 18 deletions FE/src/hooks/useMedia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,44 @@ import { useState, useEffect, useCallback, useRef } from 'react';
const useMedia = () => {
const [media, setMedia] = useState<MediaStream | null>(null);
const [selectedMimeType, setSelectedMimeType] = useState('');
const [connectStatus, setIsConnectedStatus] = useState<
const [connectStatus, setConnectStatus] = useState<
'connect' | 'fail' | 'pending'
>('pending');
const videoRef = useRef<HTMLVideoElement>(null);

const connectMedia = useCallback(async () => {
const startMedia = useCallback(async () => {
try {
const media = await getMedia();

setMedia(media);
if (media) setIsConnectedStatus('connect');
else setIsConnectedStatus('fail');
if (videoRef.current) videoRef.current.srcObject = media;
const newMedia = await getMedia();
setMedia(newMedia);
setConnectStatus(newMedia ? 'connect' : 'fail');
if (videoRef.current) videoRef.current.srcObject = newMedia;
} catch (e) {
console.log(`현재 마이크와 카메라가 연결되지 않았습니다`);
console.error('현재 마이크와 카메라가 연결되지 않았습니다.');
setConnectStatus('fail');
}
}, []);

useEffect(() => {
if (!media) {
void connectMedia();
const stopMedia = useCallback(() => {
if (media) {
closeMedia(media);
setMedia(null);
setConnectStatus('pending');
}
}, [media]);

useEffect(() => {
const mimeTypes = getSupportedMimeTypes();
if (mimeTypes.length > 0) setSelectedMimeType(mimeTypes[0]);
}, []);

return () => {
closeMedia(media);
};
}, [media, connectMedia]);

return { media, videoRef, connectStatus, selectedMimeType };
return {
media,
videoRef,
connectStatus,
selectedMimeType,
startMedia,
stopMedia,
};
};

export default useMedia;
10 changes: 3 additions & 7 deletions FE/src/page/interviewSettingPage/QuestionSettingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { questionSetting } from '@/atoms/interviewSetting';
import Button from '@/components/foundation/Button/Button';
import Description from '@/components/interviewSettingPage/Description';
import QuestionSelectionBox from '@/components/interviewSettingPage/QuestionSelectionBox/QuestionSelectionBox';
import QuestionSelectionBox from '@/components/interviewSettingPage/QuestionPage/QuestionSelectionBox/QuestionSelectionBox';
import { css } from '@emotion/react';
import { useRecoilValue } from 'recoil';

Expand All @@ -17,11 +17,7 @@ const QuestionSettingPage: React.FC<QuestionSettingPageProps> = ({
const setting = useRecoilValue(questionSetting);

return (
<div
css={css`
padding-top: 3rem;
`}
>
<>
<Description title="문제 선택">
- 주어진 카테고리 중에서 관련 있는 문제를 선택해 주세요.
<br />
Expand Down Expand Up @@ -68,7 +64,7 @@ const QuestionSettingPage: React.FC<QuestionSettingPageProps> = ({
다음
</Button>
</div>
</div>
</>
);
};

Expand Down
8 changes: 2 additions & 6 deletions FE/src/page/interviewSettingPage/RecordSettingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,7 @@ const RecordSettingPage: React.FC<RecordSettingPageProps> = ({
};

return (
<div
css={css`
padding-top: 3rem;
`}
>
<>
<Description title="녹화 설정">
- 면접 시작 전, 사용하시는 장치의 화면 및 소리가 정상적으로 연결되어
있는지 확인해 주세요.
Expand Down Expand Up @@ -111,7 +107,7 @@ const RecordSettingPage: React.FC<RecordSettingPageProps> = ({
다음
</Button>
</div>
</div>
</>
);
};
export default RecordSettingPage;
25 changes: 18 additions & 7 deletions FE/src/page/interviewSettingPage/VideoSettingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,31 @@ import { useRecoilState } from 'recoil';
type VideoSettingPageProps = {
onNextClick?: () => void;
onPrevClick?: () => void;
isCurrentPage: boolean;
};

const VideoSettingPage: React.FC<VideoSettingPageProps> = ({
onNextClick,
onPrevClick,
isCurrentPage,
}) => {
const [videoSettingState, setVideoSettingState] =
useRecoilState(videoSetting);

const { videoRef: mirrorVideoRef, connectStatus } = useMedia();
const {
videoRef: mirrorVideoRef,
connectStatus,
startMedia,
stopMedia,
} = useMedia();

useEffect(() => {
if (isCurrentPage) void startMedia();

return () => {
stopMedia();
};
}, [isCurrentPage]);

useEffect(() => {
if (connectStatus === 'connect') {
Expand All @@ -35,11 +50,7 @@ const VideoSettingPage: React.FC<VideoSettingPageProps> = ({
}, [connectStatus, setVideoSettingState]);

return (
<div
css={css`
padding-top: 3rem;
`}
>
<>
<Description title="문제 선택">
- 면접 시작 전, 사용하시는 장치의 화면 및 소리가 정상적으로 연결되어
있는지 확인해 주세요.
Expand Down Expand Up @@ -111,7 +122,7 @@ const VideoSettingPage: React.FC<VideoSettingPageProps> = ({
다음
</Button>
</div>
</div>
</>
);
};

Expand Down
28 changes: 23 additions & 5 deletions FE/src/page/interviewSettingPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@ import { css } from '@emotion/react';
import RecordSettingPage from './RecordSettingPage';
import VideoSettingPage from './VideoSettingPage';

const FIRST_PAGE_INDEX = 0;
const PREV_PAGE_INDEX = -1;

const InterviewSettingPage: React.FC = () => {
const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams();

const currentPage = searchParams.get('page');

const pageInfo = [
{
name: '문제 선택',
Expand All @@ -33,6 +40,7 @@ const InterviewSettingPage: React.FC = () => {
path: SETTING_PATH.CONNECTION,
page: (
<VideoSettingPage
isCurrentPage={currentPage === SETTING_PATH.CONNECTION}
onPrevClick={() => changeSearchParams(SETTING_PATH.QUESTION)}
onNextClick={() => changeSearchParams(SETTING_PATH.RECORD)}
/>
Expand All @@ -51,9 +59,8 @@ const InterviewSettingPage: React.FC = () => {
state: useRecoilValue(recordSetting),
},
];
const validPagePaths = pageInfo.map((item) => item.path);

const [searchParams, setSearchParams] = useSearchParams();
const currentIndex = pageInfo.findIndex((item) => item.path === currentPage);

const changeSearchParams = (newPage: string) => {
const newSearchParams = new URLSearchParams(searchParams);
Expand All @@ -62,12 +69,23 @@ const InterviewSettingPage: React.FC = () => {
};
// TODO: 로직이 더 길어지면 hook으로 분리해도 나쁘지 않을듯

const currentPage = searchParams.get('page');

if (!currentPage || !validPagePaths.includes(currentPage)) {
const isValidatePath = currentIndex !== -1;
if (!isValidatePath) {
return <Navigate to={`?page=${SETTING_PATH.QUESTION}`} replace />;
}

const prevPageInfo =
currentIndex === FIRST_PAGE_INDEX
? pageInfo[FIRST_PAGE_INDEX]
: pageInfo[currentIndex + PREV_PAGE_INDEX];

const isValidatePrevPageStatus =
currentIndex !== FIRST_PAGE_INDEX && !prevPageInfo.state.isSuccess;

if (isValidatePrevPageStatus) {
return <Navigate to={`?page=${prevPageInfo.path}`} replace />;
}

return (
<InterviewSettingPageLayout>
<div
Expand Down

0 comments on commit 5735f4a

Please sign in to comment.