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

πŸ”€ 포크레포 -> λ©”μΈλ ˆν¬ #293

Merged
merged 9 commits into from
Sep 29, 2024
30 changes: 30 additions & 0 deletions src/api/music.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,33 @@ export const deleteMusic = async (role: string, musicId: number) => {
return false;
}
};

export const likeMusic = async ({
role,
musicId,
}: {
role: string;
musicId: number;
}) => {
const response = await apiClient.patch(
SongController.likeMusic(role, musicId),
);
return response.data;
};

export const getLikeMusic = async ({
role,
date,
}: {
role: string;
date: string;
}) => {
try {
const { data } = await apiClient.get(SongController.getlikeMusic(role), {
params: {
date: date,
},
});
return data;
} catch (e: any) {}
};
21 changes: 21 additions & 0 deletions src/assets/svg/ArrowDown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const ArrowDown = () => {
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M3.33301 5.6665L7.99967 10.3332L12.6663 5.6665"
stroke="#656B80"
strokeWidth="1.33333"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
};

export default ArrowDown;
31 changes: 31 additions & 0 deletions src/assets/svg/HeartIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Palette } from 'styles/globals';

interface HeartIconProps {
heartState: boolean;
}

const HeartIcon = ({ heartState }: HeartIconProps) => {
const fillColor = heartState ? `${Palette.PRIMARY_P10}` : 'none';
const strokeColor = heartState ? `${Palette.PRIMARY_P10}` : '#656B80';

return (
<svg
width="25"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M21.667 8.25C21.667 5.765 19.568 3.75 16.979 3.75C15.044 3.75 13.382 4.876 12.667 6.483C11.952 4.876 10.29 3.75 8.35399 3.75C5.76699 3.75 3.66699 5.765 3.66699 8.25C3.66699 15.47 12.667 20.25 12.667 20.25C12.667 20.25 21.667 15.47 21.667 8.25Z"
stroke={strokeColor}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill={fillColor}
/>
</svg>
);
};

export default HeartIcon;
32 changes: 0 additions & 32 deletions src/assets/svg/NewPageIcon.tsx

This file was deleted.

3 changes: 2 additions & 1 deletion src/assets/svg/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ export { default as EyeIcon } from './EyeIcon';
export { default as EyeSelectedIcon } from './EyeSelectedIcon';
export { default as MusicalNoteIcon } from './MusicNoteIcon';
export { default as EllipsisVerticalIcon } from './EllipsisVerticalIcon';
export { default as NewPageIcon } from './NewPageIcon';
export { default as TrashcanIcon } from './TrashcanIcon';
export { default as SettingIcon } from './SettingIcon';
export { default as CircleDefaultProfile } from './CircleDefaultProfile';
export { default as BookBenIcon } from './BookBenIcon';
export { default as HeartIcon } from './HeartIcon';
export { default as ArrowDown } from './ArrowDown';
49 changes: 45 additions & 4 deletions src/components/Song/atoms/MusicItemThumbnail/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,52 @@
import Image from 'next/image';
import { preventEvent } from 'utils/Libs/preventEvent';
import { likeMusic } from 'api/music';
import { HeartIcon } from 'assets/svg';
import { toast } from 'react-toastify';
import * as S from './style';

const MusicItemThumbnail = ({ thumbnail }: { thumbnail: string }) => {
interface MusicItemThumbnailProps {
thumbnail: string;
heartState: boolean;
setHeartState: React.Dispatch<React.SetStateAction<boolean>>;
musicId: number;
role: string;
setLikeCount: React.Dispatch<React.SetStateAction<number>>;
}

const MusicItemThumbnail = ({
thumbnail,
heartState,
setHeartState,
musicId,
role,
setLikeCount,
}: MusicItemThumbnailProps) => {
const handleHeart = async (e: React.MouseEvent<HTMLDivElement>) => {
preventEvent(e);
try {
const data = await likeMusic({ role, musicId });
setLikeCount(data.likeCount);
setHeartState(!heartState);
} catch (error) {
console.error('Error liking music:', error);
toast.error('μŒμ•…μ„ 찾지 λͺ»ν–ˆμŠ΅λ‹ˆλ‹€');
}
};
return (
<S.ImgBox>
<Image src={thumbnail} alt="thumbnail" layout="fill" objectFit="cover" />
</S.ImgBox>
<div>
<S.ImgBox>
<S.HeartContainer onClick={handleHeart}>
<HeartIcon heartState={heartState} />
</S.HeartContainer>
<Image
src={thumbnail}
alt="thumbnail"
layout="fill"
objectFit="cover"
/>
</S.ImgBox>
</div>
);
};

Expand Down
17 changes: 14 additions & 3 deletions src/components/Song/atoms/MusicItemThumbnail/style.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import styled from "@emotion/styled";
import { Palette } from "styles/globals";
import styled from '@emotion/styled';
import { Palette } from 'styles/globals';

export const ImgBox = styled.div`
position: relative;
Expand All @@ -17,4 +17,15 @@ export const ImgBox = styled.div`
span {
min-height: 72px;
}
`;
`;

export const HeartContainer = styled.div`
position: absolute;
top: 4px;
left: 4px;
z-index: 1;

@media (min-width: 420px) {
display: none;
}
`;
2 changes: 1 addition & 1 deletion src/components/Song/atoms/MusicItemTitle/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const Title = styled.h4`

export const Info = styled.div`
display: none;
font-size: 1em;
font-size: 0.75em;
color: ${Palette.NEUTRAL_N20};

@media (max-width: 800px) {
Expand Down
56 changes: 42 additions & 14 deletions src/components/Song/atoms/MusicListButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,63 @@
import { NewPageIcon, TrashcanIcon } from 'assets/svg';
import { preventEvent } from 'utils/Libs/preventEvent';
import { HeartIcon, TrashcanIcon } from 'assets/svg';
import { likeMusic } from 'api/music';
import { toast } from 'react-toastify';
import * as S from './style';

interface MusicListButtonProps {
role: string;
songStuNum: number;
userStuNum?: string;
setDeleteModal: React.Dispatch<React.SetStateAction<boolean>>;
heartState: boolean;
setHeartState: React.Dispatch<React.SetStateAction<boolean>>;
musicId: number;
likeCount: number;
setLikeCount: React.Dispatch<React.SetStateAction<number>>;
}

const MusicListButton = ({
role,
songStuNum,
userStuNum,
setDeleteModal,
heartState,
setHeartState,
musicId,
likeCount,
setLikeCount,
}: MusicListButtonProps) => {
const handleHeart = async (e: React.MouseEvent<HTMLDivElement>) => {
preventEvent(e);
try {
const data = await likeMusic({ role, musicId });
setLikeCount(data.likeCount);
setHeartState(!heartState);
} catch (error) {
console.error('Error liking music:', error);
toast.error('μŒμ•…μ„ 찾지 λͺ»ν–ˆμŠ΅λ‹ˆλ‹€');
}
};
return (
<S.ButtonContainer>
{(role !== 'member' || String(songStuNum) === userStuNum) && (
<button
onClick={(e) => {
preventEvent(e);
setDeleteModal(true);
}}
>
<TrashcanIcon />
</button>
)}
<div>
<NewPageIcon />
</div>
<S.ButtonTestContainer>
{(role !== 'member' || String(songStuNum) === userStuNum) && (
<S.ButtonStyle
onClick={(e) => {
preventEvent(e);
setDeleteModal(true);
}}
>
<TrashcanIcon />
</S.ButtonStyle>
)}
<S.LikeContainer onClick={handleHeart}>
<S.ButtonStyle>
<HeartIcon heartState={heartState} />
</S.ButtonStyle>
<S.LikeNum>{likeCount}</S.LikeNum>
</S.LikeContainer>
</S.ButtonTestContainer>
</S.ButtonContainer>
);
};
Expand Down
55 changes: 36 additions & 19 deletions src/components/Song/atoms/MusicListButton/style.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,51 @@
import styled from "@emotion/styled";
import { Palette } from "styles/globals";
import styled from '@emotion/styled';
import { Palette } from 'styles/globals';

export const ButtonStyle = styled.div`
border: none;
border-radius: 0.5em;
background: ${Palette.BACKGROUND_BG};
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
`;

export const ButtonContainer = styled.div`
display: flex;
height: 100%;
align-items: flex-end;
`;

export const ButtonTestContainer = styled.div`
display: flex;
gap: 1em;
justify-content: end;

button,
div {
border: none;
border-radius: 0.5em;
background: ${Palette.BACKGROUND_BG};
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;

@media (max-width: 800px) {
:last-child {
display: none;
}
}
${ButtonStyle}
}

svg path {
& > div:first-of-type svg path {
stroke: ${Palette.NEUTRAL_N20};
}

@media (max-width: 420px) {
display: none;
}
`;
`;

export const LikeContainer = styled.div`
display: flex;
flex-direction: column;
`;

export const LikeNum = styled.p`
font-family: SUIT;
font-size: 14px;
font-weight: 600;
line-height: 17.47px;
text-align: center;
color: ${Palette.NEUTRAL_N20};
`;
Loading
Loading