Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ import { RecoilRoot } from 'recoil';
import { Global, ThemeProvider } from '@emotion/react';
import globalStyle from './styles/globalStyle';
import theme from './styles/theme';

import Feedback from '@pages/Feedback/Feedback';
import Feedback from '@pages/Feedback';

function App() {
return (
<RecoilRoot>
<ThemeProvider theme={theme}>
<div className="App">
<Global styles={globalStyle} />
<Feedback></Feedback>
<Feedback />
</div>
</ThemeProvider>
</RecoilRoot>
Expand Down
23 changes: 13 additions & 10 deletions frontend/src/components/@shared/FeedbackBox/FeedbackBox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { forwardRef } from 'react';

function getContent(children: React.ReactNode[]) {
return children.filter((child) => React.isValidElement(child) && child.type === FbContentType);
Expand All @@ -15,21 +15,24 @@ function getBtns(children: React.ReactNode[]) {
}

// TODO: handler optional 삭제
const FbMain = ({
children,
handleClick,
}: {
children: React.ReactNode;
handleClick?: React.MouseEventHandler<HTMLElement>;
}) => {
const FbMain = (
{
children,
handleClick,
}: {
children: React.ReactNode;
handleClick?: React.MouseEventHandler<HTMLElement>;
},
ref
) => {
const childrenArr = React.Children.toArray(children);

const FbContent = getContent(childrenArr);
const FbStartTime = getStartTime(childrenArr);
const FbBtns = getBtns(childrenArr);

return (
<div onClick={handleClick}>
<div onClick={handleClick} ref={ref}>
<div>{FbStartTime}</div>
<div>{FbContent}</div>
<div>{FbBtns}</div>
Expand Down Expand Up @@ -58,7 +61,7 @@ const FbBtn = ({
};
const FbBtnType = (<FbBtn />).type;

export const FeedbackBox = Object.assign(FbMain, {
export const FeedbackBox = Object.assign(forwardRef(FbMain), {
Content: FbContent,
StartTime: FbStartTime,
Btn: FbBtn,
Expand Down
48 changes: 48 additions & 0 deletions frontend/src/components/FeedbackArea/FeedbackArea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { css } from '@emotion/react';
import React, { Children, ReactNode, isValidElement } from 'react';

const FVAScrollViewStyle = css`
width: 100%;
height: 200px;
background-color: red;
overflow-y: scroll;
`;

const FBAScrollView = ({ children }: { children?: ReactNode }) => {
return <div css={FVAScrollViewStyle}>{children}</div>;
};

const FBAScrollViewType = (<FBAScrollView />).type;

const getFBAScrollView = (childArr: ReactNode[]) => {
return childArr.filter((child) => isValidElement(child) && child.type === FBAScrollViewType);
};

const FBATextArea = () => {
return <textarea></textarea>;
};
const FBATextAreaType = (<FBATextArea />).type;
const getFBATextArea = (childArr: ReactNode[]) => {
return childArr.filter((child) => isValidElement(child) && child.type === FBATextAreaType);
};

const FBAMain = ({ children }: { children: ReactNode }) => {
const childArr = Children.toArray(children);

const FBAScrollView = getFBAScrollView(childArr);
const FBATextArea = getFBATextArea(childArr);

return (
<div>
{FBAScrollView}
{FBATextArea}
</div>
);
};

const FeedbackArea = Object.assign(FBAMain, {
FBAScrollView,
FBATextArea,
});

export default FeedbackArea;
40 changes: 0 additions & 40 deletions frontend/src/components/Timeline/Timeline.tsx

This file was deleted.

82 changes: 82 additions & 0 deletions frontend/src/pages/Feedback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, { useState, useEffect, useRef } from 'react';
import { FeedbackBox } from '@components/@shared/FeedbackBox/FeedbackBox';
import FeedbackArea from '@components/FeedbackArea/FeedbackArea';
import { useRecoilState } from 'recoil';
import { currentTimeState } from '@store/feedbackStore';

const Feedback = () => {
const dummyFeedback = [
{ id: 0, content: '테스트 피드백1', startTime: 3, endTime: 4 },
{ id: 1, content: '테스트 피드백2', startTime: 6, endTime: 9 },
{ id: 2, content: '테스트 피드백3', startTime: 10, endTime: 15 },
{ id: 3, content: '테스트 피드백4', startTime: 16, endTime: 20 },
{ id: 4, content: '테스트 피드백5', startTime: 23, endTime: 30 },
{ id: 5, content: '테스트 피드백6', startTime: 31, endTime: 33 },
{ id: 6, content: '테스트 피드백7', startTime: 34, endTime: 40 },
{ id: 7, content: '테스트 피드백8', startTime: 45, endTime: 50 },
{ id: 8, content: '테스트 피드백9', startTime: 51, endTime: 53 },
{ id: 9, content: '테스트 피드백10', startTime: 56, endTime: 57 },
];

// const [currentTime, setCurrentTime] = useRecoilState(currentTimeState);
const currentTime = 16;
const [focusIndex, setFocusIndex] = useState(0);

const feedbackRef = useRef([]);

const findCurrentFeedback = () => {
let start = 0;
let end = dummyFeedback.length - 1;
let mid;

while (start <= end) {
mid = Math.floor((start + end) / 2);

if (currentTime === dummyFeedback[mid].startTime) {
return mid;
} else {
if (currentTime < dummyFeedback[mid].startTime) {
end = mid - 1;
} else {
start = mid + 1;
}
}
}

return start <= 0 ? 0 : start - 1;
};

useEffect(() => {
const nearestIndex = findCurrentFeedback();
console.log(nearestIndex, dummyFeedback[nearestIndex].startTime);
if (nearestIndex !== focusIndex) setFocusIndex(nearestIndex);
}, [currentTime]);

useEffect(() => {
feedbackRef.current[focusIndex].scrollIntoView({ behavior: 'smooth', block: 'start' });
}, [focusIndex]);

const onClickFeedback = (e) => {
e.target.scrollIntoView({ behavior: 'smooth', block: 'start' });
};

return (
<FeedbackArea>
<FeedbackArea.FBAScrollView>
{dummyFeedback.map((feedback, idx) => (
<FeedbackBox
key={feedback.id}
handleClick={onClickFeedback}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prop key가 onClick이 낫겠네용.. 죄송합니다

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • 감사합니당. 코드 스타일 유지 외에도 props drilling 문제도 저 패턴 쓰니까 해결이 되는 것 같아요. 굳
  • pin 기능 말씀하신건가요?? 그부분은 얘기를 나눠봐야할 것 같아서 보류해놓겠습니다. 오늘 얘기 나눠보시죠

ref={(elem) => (feedbackRef.current[idx] = elem)}
>
<FeedbackBox.StartTime>{feedback.startTime}</FeedbackBox.StartTime>
<FeedbackBox.Content>{feedback.content}</FeedbackBox.Content>
</FeedbackBox>
))}
</FeedbackArea.FBAScrollView>
<FeedbackArea.FBATextArea></FeedbackArea.FBATextArea>
</FeedbackArea>
);
};

export default Feedback;
14 changes: 0 additions & 14 deletions frontend/src/pages/Feedback/Feedback.tsx

This file was deleted.