Skip to content
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

feat: 트랙 추가하기 기능 구현 #419

Merged
merged 2 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
17 changes: 17 additions & 0 deletions client/src/api/track.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { API } from "./axios";

// 트랙 생성
export const addTrack = async (projectId: string, params: {}) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

params에 빈 객체로 타입을 설정하면 addTrack 호출부에서 params에 key 넣을 때 타입에러가 뜨진 않나요??

Copy link
Member Author

Choose a reason for hiding this comment

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

FormData 타입이 빈 객체로 정의되어 있어서 에러가 발생하지는 않는 것으로 보여요. 이전 프로젝트 생성할 때 작성했던 코드를 재사용하다가 parameter 타입을 놓쳤네요.. 여기선 FormData 타입을 사용하는게 더 정확할 것 같아요!

const url = `/projects/${projectId}/tracks`;
const errorMessage = "트랙이 생성되지 않았습니다. 잠시 후 다시 시도해주세요.";

try {
const res = await API.post(url, params);
return res.data;
} catch (err) {
console.log(err);
alert(errorMessage);
}

return Promise.reject(new Error(errorMessage));
};
29 changes: 17 additions & 12 deletions client/src/components/blocks/TrackSetting/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import UnderPlayBarViewModel from "viewmodel/UnderPlayBarViewModel";
import useAudios from "hooks/useAudios";
import useTrackSetting from "hooks/useTrackSetting";
import useCreateTrack from "hooks/useCreateTrack";
import { NEW_TRACK_ID } from "constants/key";

import "./style.scss";

Expand All @@ -22,20 +23,14 @@ interface ProjectInfoType {
bpmState: number;
trackTags: Track[];
tracks: TrackResponseType[];
onTrackCreate: (title: string, trackTag: Track, audio: HTMLAudioElement) => void;
}

function TrackSetting({ projectTitle, bpmState, trackTags, tracks }: ProjectInfoType) {
const {
inputDeviceId,
inputTextDevice,
trackTag,
handleTitleInput,
handleTrackTagSelect,
handleDeviceClick,
handleSettingSubmit,
} = useTrackSetting();
function TrackSetting({ projectTitle, bpmState, trackTags, tracks, onTrackCreate }: ProjectInfoType) {
const { title, inputDeviceId, inputTextDevice, trackTag, handleTitleInput, handleTrackTagSelect, handleDeviceClick } =
useTrackSetting();
Copy link
Collaborator

Choose a reason for hiding this comment

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

prettier가 이렇게 포맷팅 시켜주나요??

Copy link
Member Author

Choose a reason for hiding this comment

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

네! printWidth를 120으로 설정해둬서 그런가봐요..😂


const { setAudios, addAudio, removeAudio } = useAudios();
const { audioList, setAudios, addAudio, removeAudio } = useAudios();

const { isRecording, isRecordSuccess, handleRecordButtonClick, handleTrackRemove } = useCreateTrack({
inputDeviceId,
Expand All @@ -49,6 +44,16 @@ function TrackSetting({ projectTitle, bpmState, trackTags, tracks }: ProjectInfo
},
});

const handleTrackSubmit = () => {
const recordedAudio = audioList.find(({ id }) => id === NEW_TRACK_ID);

if (!title || !trackTag || !recordedAudio) {
return;
}
Comment on lines +50 to +52
Copy link
Collaborator

Choose a reason for hiding this comment

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

제목, 태그, 녹음에 대한 사용자 액션을 유도하는 얼럿을 추가해주는 것은 어떨까요??

Suggested change
if (!title || !trackTag || !recordedAudio) {
return;
}
const requiredProperties = [title, trackTag, recordedAudio];
const errorPropertyIdx = requiredProperties.fineIndex((item) => !item);
if (errorPropertyIdx > -1) {
alert(`${requiredProperties[errorPropertyIdx]}을 채워주세요.`);
return;
}

Copy link
Member Author

Choose a reason for hiding this comment

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

오.. 이렇게 required 요소를 체크하는 방법 좋은 것 같아요! 👍🏻


onTrackCreate(title, trackTag, recordedAudio.audio);
};

useEffect(() => {
if (tracks.length === 0) {
return;
Expand All @@ -72,7 +77,7 @@ function TrackSetting({ projectTitle, bpmState, trackTags, tracks }: ProjectInfo
<RecordDevice onDeviceClick={handleDeviceClick} inputTextDevice={inputTextDevice} />
<TrackTag onTrackClick={handleTrackTagSelect} selectedTrack={trackTag} tracks={trackTags} />
</div>
<Button type="green" onBtnClick={handleSettingSubmit} marginTop="4rem" width="100%">
<Button type="green" onBtnClick={handleTrackSubmit} marginTop="4rem" width="100%">
트랙 추가하기
</Button>
</div>
Expand Down
4 changes: 0 additions & 4 deletions client/src/hooks/useTrackSetting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ const useTrackSetting = () => {
setTrackTag(e.currentTarget.lastChild?.nodeValue as Track);
};

// 프로젝트 생성하기 버튼 클릭
const handleSettingSubmit = () => {};

return {
title,
inputDeviceId,
Expand All @@ -33,7 +30,6 @@ const useTrackSetting = () => {
handleTitleInput,
handleDeviceClick,
handleTrackTagSelect,
handleSettingSubmit,
};
};

Expand Down
29 changes: 27 additions & 2 deletions client/src/viewmodel/CreateTrackViewModel.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,44 @@
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { useNavigate, useParams } from "react-router-dom";

import { ProjectResponseType } from "types/projectType";
import { ProjectResponseType, Track } from "types/projectType";

import { getProject } from "api/project";
import { addTrack } from "api/track";
import { trackList as TrackTags } from "utils/data/track";
import { getAudioBlob } from "utils/audio";

import TrackSetting from "components/blocks/TrackSetting";

function CreateTrackViewModel() {
const { projectId } = useParams();
const navigate = useNavigate();

const [projectInfo, setProjectInfo] = useState<ProjectResponseType>();
const [isLoading, setIsLoading] = useState(false);
const isFetched = !isLoading && projectInfo;

// 트랙 생성하기 버튼 클릭
const handleTrackCreate = (title: string, trackTag: Track, audio: HTMLAudioElement) => {
if (!projectId) {
return;
}

const createTrack = async () => {
const recordedBlob = await getAudioBlob(audio);

const formData = new FormData();
formData.append("trackName", title);
formData.append("trackTag", trackTag);
formData.append("audioFile", recordedBlob);
Comment on lines +28 to +33
Copy link
Collaborator

Choose a reason for hiding this comment

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

인스턴스 생성 구끼리 인접하게 두는게 더 깔끔해보일 것 같아요ㅎㅎ

Suggested change
const recordedBlob = await getAudioBlob(audio);
const formData = new FormData();
formData.append("trackName", title);
formData.append("trackTag", trackTag);
formData.append("audioFile", recordedBlob);
const recordedBlob = await getAudioBlob(audio);
const formData = new FormData();
formData.append("trackName", title);
formData.append("trackTag", trackTag);
formData.append("audioFile", recordedBlob);

Copy link
Member Author

Choose a reason for hiding this comment

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

저는 코드를 읽을 때 formData를 생성하는 부분이 한 블록으로 읽히면 좋을 것 같아서 묶어뒀어요. 저도 변수 선언부가 인접해있으면 깔끔하다는 의견에 동의해요! 👍🏻


await addTrack(projectId, formData);
navigate(`/${projectId}`);
};

createTrack();
};

useEffect(() => {
if (!projectId) {
return;
Expand All @@ -38,6 +62,7 @@ function CreateTrackViewModel() {
projectTitle={projectInfo.projectName}
bpmState={projectInfo.bpm}
tracks={projectInfo.tracks}
onTrackCreate={handleTrackCreate}
/>
) : (
<div>Loading...</div>
Expand Down