-
Notifications
You must be signed in to change notification settings - Fork 2
Feat/#140 노래 조회 페이지 구현 #158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다👍👍
킬링파트 감상하기 좋은 페이지네요😊
아직 쿼리 작성은 되지 않은 것인가요?
좀 더 마무리 짓고 approve하면 될 것 같아요 :)
display: flex; | ||
justify-content: center; | ||
width: 100%; | ||
gap: 20px; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💬 common 컴포넌트인데 gap을 미리 지정해준 이유가 있으신가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
외부에서 Spacing으로 스타일링하는 게 좋겠네요
const toggleContext = useContext(ToggleContext); | ||
|
||
if (!toggleContext) { | ||
throw new Error('toggle group 사용 시에 반드시 Context API를 공유해야합니다.'); | ||
} | ||
|
||
const { selected, setSelected, onChangeValue } = toggleContext; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💬 ToggleButton 내에서 하는 일이라기보다 ToggleContext의 역할에 더 가까운 것 같아요.
custom hook으로 만들어서 Button에서 분리해내면 좋을 것 같아요.
const useToggleContext = () => {
const toggleContext = useContext(ToggleContext);
if (!toggleContext) {
throw new Error('toggle group 사용 시에 반드시 Context API를 공유해야합니다.');
}
const { selected, setSelected, onChangeValue } = toggleContext;
return { selected, setSelected, onChangeValue };
};
const ToggleButton = ({ value, children }: ToggleButtonProps) => {
const { selected, setSelected, onChangeValue } = useToggleContext();
...
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
분리완
interface ToggleSwitchProps { | ||
off: () => void; | ||
on: () => void; | ||
defaultToggle?: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💬 개인적인 생각으로는 기본값이니 defaultValue로 해도 괜찮다고 생각하는데
몇 번 곱씹어보니 boolean이니 defaultToggle로 조금 더 시맨틱하게 네이밍해도 좋다고 생각이 들긴 하네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
감샤합니다.
const [toggle, setToggle] = useState(defaultToggle); | ||
|
||
const onToggle = () => { | ||
toggle ? off() : on(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
삼항연산으로 함수를 실행하는 것은 가독성에 안좋다고 생각합니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
간단한 로직은 삼항연산자 사용하는 게 오히려 더 간결하다는 느낌인데 저랑 의견이 다르시군요! 그래도 팀원이 보기 불편하다면 변경할 용기를 갖고 있습니다. 변경완
const getPlayingTime = (startSec: number, endSec: number) => { | ||
const timeList = [secondsToMinSec(startSec), secondsToMinSec(endSec)].flat().map((timeSec) => { | ||
const timeString = timeSec.toString(); | ||
return timeString.length === 1 ? `0${timeString}` : timeString; | ||
}); | ||
return `${timeList[0]}:${timeList[1]} ~ ${timeList[2]}:${timeList[3]}`; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💬 유틸함수로 빠져도 좋을 것 같아요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
동의합니다.
<ToggleGroup.button value="1">{'1st'}</ToggleGroup.button> | ||
<ToggleGroup.button value="2">{'2nd'}</ToggleGroup.button> | ||
<ToggleGroup.button value="3">{'3rd'}</ToggleGroup.button> | ||
<ToggleGroup.button value="4">{'전체'}</ToggleGroup.button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<ToggleGroup.button value="1">{'1st'}</ToggleGroup.button> | |
<ToggleGroup.button value="2">{'2nd'}</ToggleGroup.button> | |
<ToggleGroup.button value="3">{'3rd'}</ToggleGroup.button> | |
<ToggleGroup.button value="4">{'전체'}</ToggleGroup.button> | |
<ToggleGroup.button value="1">1st</ToggleGroup.button> | |
<ToggleGroup.button value="2">2nd</ToggleGroup.button> | |
<ToggleGroup.button value="3">3rd</ToggleGroup.button> | |
<ToggleGroup.button value="4">전체</ToggleGroup.button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋습니다~
const onChangeValue = (value: string) => { | ||
setKillingRank(value); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💬 onChangeKillingRank또는 changeKillingRank 라고 하면 좋을 것 같아요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
어렵지 않죠! 좋은 네이밍있다면 언제든 말씀해주세요
display: flex; | ||
align-items: center; | ||
gap: 12px; | ||
`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 파일에 개행이 안되어있는 곳이 여럿 있는 것 같아요 😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
개행완
const { id } = useParams(); | ||
const [player, setPlayer] = useState<YT.Player | undefined>(); | ||
const [isRepeat, setIsRepeat] = useState(true); | ||
const [killingRank, setKillingRank] = useState(''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💬 꼭 문자열로 관리해야 되는 이유가 있나요? 숫자로 형변환을 자주 시켜주는 것 같은데 숫자형으로 하여도 괜찮을 것 같습니다.
가장 큰 문제는 ToggleGroup에서 지정한 타입 때문인 것 같은데요. 유니온이나 제네릭을 활용하면 해결할 수 있을 것 같아요.
제네릭 컴포넌트
https://medium.com/edonec/creating-a-generic-component-with-react-typescript-2c17f8c4386e
https://ui.toast.com/posts/ko_20210505
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
제네릭 컴포넌트로 구현하려고 했는데, 생각보다 어렵더라고요. contextAPi, toggle group하위에 있는 버튼 컴포넌트도 제네릭으로 모두 같은 타입으로 일괄되게 검사하게끔하는 것에서 막혔습니다. 그리고 형변환하여 접근하는 문제는 다른 방법으로 문제를 해결해보도록 하겠습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생 많으셨습니다~!
오류난 부분도 찾아주셔서 감사해요 ㅎㅎ
코멘트 확인 해주시고 다시 요청주세요!
frontend/src/types/song.ts
Outdated
@@ -7,7 +7,7 @@ export interface SongDetail { | |||
title: string; | |||
singer: string; | |||
videoLength: number; | |||
songVideoUrl: VideoUrl; | |||
videoUrl: VideoUrl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 부분 backend 파트하고 이야기 해봐야겠네요
마지막 기억은 songVideoUrl 로 기억합니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
헉! 알겠습니다.
|
||
const ToggleContext = createContext<ToggleContextValue | null>(null); | ||
|
||
const ToggleGroup = ({ defaultValue, onChangeValue, children }: ToggleGroupProps) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💬 onChangeValue는 사용처에서 넣어주는 것 같은데, 어떤 의도인가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ToggleGroup에서 값이 선택될 때, 사용처에서 선택된 값을 바탕으로 추가 로직을 수행할 수 있도록 열어둔 것입니다.
<Container> | ||
<TimeWrapper> | ||
<Img src={shook} alt="logo" /> | ||
<p>{getPlayingTime(start, end)}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
styled 컴포넌트로 이름이 지어지면 좋을 것 같아요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
컨벤션 정해보아요
</VoteBox> | ||
|
||
<ShareBox onClick={shareUrl}> | ||
<Img src={link} alt="?" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💬 alt가 ? 인 이유가 있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
없어요 변경했습니다.
<Wrapper> | ||
<Container> | ||
<TimeWrapper> | ||
<Img src={shook} alt="logo" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
단순 꾸밈 요소로 쓰인 이미지 태그의 alt 속성은 빈값으로 두는게 좋을 것 같아요.
접근성 측면에서 더 좋을 것 같습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그렇네요! 완전 납득이입니다.
|
||
<RestWrapper> | ||
<VoteBox> | ||
<Img src={people} alt="vote" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 alt 태그도 꾸밈요소로 사용된것 같네요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
굳입니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💬 클립보드 복사는 항상 토스트로 알려준다
라는 가정하에 만든 hook일까요~?
💬 유틸성향의 함수에 인자의 유무에 따라 토스트를 띄워주는 기능만 추가된걸로 보이는데요~!
hook의 의미를 생각해보면 아래 함수는 유틸함수로 분리되고,
사용처에서 클립보드유틸과 토스트훅을 사용하는 핸들러 함수를 만들어 사용하면 될 것 같다고 생각되어요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 네 맞아요.
- 좋은 생가입니다.
@@ -5,6 +5,7 @@ module.exports = { | |||
entry: './src/index.tsx', | |||
output: { | |||
assetModuleFilename: 'assets/[hash][ext]', | |||
publicPath: '/', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 설정 때문이였군요! 감사합니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
react-router의 자식의 자식을 찾지 못하는 오류 개선내용
ex) s-hook.com/child-of/child/do-not/work
if (isRepeat) { | ||
timer.current = window.setInterval( | ||
() => { | ||
player?.seekTo(part.start, true); | ||
}, | ||
(part.end - part.start) * 1000 | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
반복듣기를 위한 로직인것 같아요.
💬 비슷한 로직이 songDetailPage에도 존재하는데 이부분 추후에 통합이 이뤄지면 좋을 것 같아요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저두 그렇게 생각해요! 사실 이전에 만든 페이지와 성격이 비슷해서, 중복되는 로직이나 컴포넌트가 많은데, 이를 함부러 건드렸다가 충돌 날 것 같아서 과감하게 분리하지 못했네요!
const getPlayingTime = (startSec: number, endSec: number) => { | ||
const timeList = [secondsToMinSec(startSec), secondsToMinSec(endSec)].flat().map((timeSec) => { | ||
const timeString = timeSec.toString(); | ||
return timeString.length === 1 ? `0${timeString}` : timeString; | ||
}); | ||
return `${timeList[0]}:${timeList[1]} ~ ${timeList[2]}:${timeList[3]}`; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
변수로 표현해 줄거라면 구조분해 할당을 이용하면 어떨까요?
return 문 라인에서도 각 인덱스 값을 생각하지 않아도 될 것 같아요.
const getPlayingTime = (startSec: number, endSec: number) => { | |
const timeList = [secondsToMinSec(startSec), secondsToMinSec(endSec)].flat().map((timeSec) => { | |
const timeString = timeSec.toString(); | |
return timeString.length === 1 ? `0${timeString}` : timeString; | |
}); | |
return `${timeList[0]}:${timeList[1]} ~ ${timeList[2]}:${timeList[3]}`; | |
}; | |
const getPlayingTime = (startSec: number, endSec: number) => { | |
const [startMinute, startSecond, endMinute, endSecond] = [secondsToMinSec(startSec), secondsToMinSec(endSec)].flat().map((timeSec) => { | |
const timeString = timeSec.toString(); | |
return timeString.length === 1 ? `0${timeString}` : timeString; | |
}); | |
return `${startMinute}:${startSecond} ~ ${endMinute}:${endSecond}`; | |
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
너무 좋네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
리뷰 반영까지 모두 확인했습니다! 고생 많으셨습니다~!!
|
||
if (!killingPart) return; | ||
|
||
const { voteCount, start, end, partVideoUrl } = killingPart; | ||
|
||
const shareUrl = () => { | ||
copyClipboard(partVideoUrl, '클립보드에 영상링크가 복사되었습니다.'); | ||
copyClipboard(partVideoUrl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
너무 좋습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approve 하겠습니다
|
||
export const ToggleContext = createContext<ToggleContextValue | null>(null); | ||
|
||
const useToggleContext = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍👍
}); | ||
return `${timeList[0]}:${timeList[1]} ~ ${timeList[2]}:${timeList[3]}`; | ||
}; | ||
const playingTimeText = getPlayingTimeText(start, end); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍👍
📝작업 내용
노래 조회 페이지 구현
작업내용
리뷰 참고사항
#️⃣연관된 이슈
close #140
close #152