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

[MZO-60] 플레이리스트 마크업 작업 #41

Merged
merged 10 commits into from
Jul 27, 2023
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
11 changes: 11 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ const nextConfig = {
compiler: {
removeConsole: process.env.NODE_ENV !== 'development',
},
images: {
// NOTE: 임시로 작성
remotePatterns: [
{
protocol: 'https',
hostname: 'via.placeholder.com',
port: '',
pathname: '/**',
},
],
},
Comment on lines +38 to +48
Copy link
Author

Choose a reason for hiding this comment

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

next/image에서 외부 src를 가져오기 위해 임시로 설정해둔 코드입니닷

};

module.exports = withPWA(nextConfig);
2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default function RootLayout({
}) {
return (
<html lang="ko" className={`${pretendard.variable}`}>
<body className="bg-gray-500">
<body className="relative m-auto h-screen min-w-[360px] max-w-[480px] bg-gray-500">
Copy link
Author

Choose a reason for hiding this comment

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

모든 페이지에서 기본적으로 적용되어야 하는 사항이여서 상위 태그인 body 태그로 옮겼습니다.

<ReactQueryProvider>
<JotaiAtomProvider>{children}</JotaiAtomProvider>
</ReactQueryProvider>
Expand Down
2 changes: 1 addition & 1 deletion src/app/playing/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PropsWithChildren } from 'react';

const Layout = ({ children }: PropsWithChildren) => {
return (
<main className="w-full min-w-[360px] max-w-[480px] h-screen flex flex-col bg-black drop-shadow-md m-auto overflow-hidden">
<main className="flex flex-col w-full h-screen overflow-hidden bg-black drop-shadow-md">
{children}
</main>
);
Expand Down
10 changes: 7 additions & 3 deletions src/app/playing/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import dynamic from 'next/dynamic';

import { useAtom, useSetAtom } from 'jotai';
import { useAtom } from 'jotai';

import EmojiPicker from '@/components/EmojiPicker';
import BasicButton from '@/components/button/BasicButton';
import Header from '@/components/header/Header';
import MenuButton from '@/components/header/MenuButton';
import PreviousButton from '@/components/header/PreviousButton';
import { Playlist, PlaylistButton, usePlaylist } from '@/components/playlist';
import EmojiVoteList from '@/domains/playing/emoji-list';
import PlayController from '@/domains/playing/play-controller';
import VinylRecordList from '@/domains/playing/vinyl-record';
Expand All @@ -24,6 +24,7 @@ const YoutubePlayer = dynamic(

const PlayingPage = () => {
const { toast } = useToast();
const { isOpenPlaylist } = usePlaylist();
const [isEmojiPickerOpen, setIsEmojiPickerOpen] = useAtom(
controlOpenEmojiPickerAtom,
);
Expand All @@ -37,6 +38,8 @@ const PlayingPage = () => {
toast.success({ title: 'temp title', message: 'temp message' });
};

const PlaylistComponent = isOpenPlaylist ? <Playlist /> : null;

return (
<>
<Header
Expand All @@ -47,7 +50,7 @@ const PlayingPage = () => {
<p className="text-white text-body3">NewJeans</p>
</div>
}
headerRight={<MenuButton onClick={() => {}} className="mb-auto" />}
headerRight={<PlaylistButton className="mb-auto" />}
/>
<div className="flex flex-col py-2 my-auto">
<VinylRecordList />
Expand Down Expand Up @@ -75,6 +78,7 @@ const PlayingPage = () => {
</BasicButton>
</div>
)}
{PlaylistComponent}
<YoutubePlayer />
</>
);
Expand Down
35 changes: 18 additions & 17 deletions src/app/template.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
'use client';

import AppPortal from '@/components/app-portal';
import ToastProvider from '@/components/toast/ToastProvider';

export default function Template({ children }: { children: React.ReactNode }) {
return (
<>
{children}
<AppPortal.Provider portalName="player-portal" />
<AppPortal.Provider portalName="emoji-picker-portal" />
<AppPortal.Provider portalName="toast-portal">
<ToastProvider />
</AppPortal.Provider>
</>
);
}
'use client';

import AppPortal from '@/components/app-portal';
import ToastProvider from '@/components/toast/ToastProvider';

export default function Template({ children }: { children: React.ReactNode }) {
return (
<>
{children}
<AppPortal.Provider portalName="player-portal" />
<AppPortal.Provider portalName="emoji-picker-portal" />
<AppPortal.Provider portalName="modal-portal" />
<AppPortal.Provider portalName="toast-portal">
<ToastProvider />
</AppPortal.Provider>
</>
);
}
10 changes: 5 additions & 5 deletions src/assets/icons/menu.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 0 additions & 6 deletions src/assets/icons/playlist.svg

This file was deleted.

6 changes: 6 additions & 0 deletions src/assets/icons/playlistMenu.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/components/EmojiPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React, { useState } from 'react';
import clsx from 'clsx';
import { useAtomValue, useSetAtom } from 'jotai';

import Close from '@/assets/icons/close.svg';
import CloseIcon from '@/assets/icons/close.svg';
import AppPortal from '@/components/app-portal';
import EmojiButton from '@/components/button/EmojiButton';
import {
Expand Down Expand Up @@ -61,7 +61,7 @@ const EmojiPicker = ({ className }: EmojiPickerProps) => {
</span>
</div>
<button onClick={handleCloseButton}>
<Close className="w-6 h-6" />
<CloseIcon className="w-6 h-6" />
</button>
</div>
<div className="flex items-center justify-center w-full gap-2 pt-5 text-2xl">
Expand Down
1 change: 1 addition & 0 deletions src/components/app-portal/AppPortal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const PortalProvider = ({
return (
<PortalContext.Provider value={portalList}>
<div
className="absolute top-0 left-0 w-full"
Copy link
Contributor

Choose a reason for hiding this comment

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

div 생성 시 바로 스타일링 입혀주는 것도 제가 놓친 부분인데 채워주셔서 감사합니다.

id={portalName}
ref={(element) => {
if (element && !portalContainer) setPortalContainer(element);
Expand Down
39 changes: 19 additions & 20 deletions src/components/bottom-player/BottomMusicPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import ControlNextIcon from '@/assets/icons/controlNext.svg';
import ControlPauseIcon from '@/assets/icons/controlPause.svg';
import ControlPlayIcon from '@/assets/icons/controlPlay.svg';
import ControlPrevIcon from '@/assets/icons/controlPrev.svg';
import PlayListIcon from '@/assets/icons/playlist.svg';
import { PlaylistButton } from '@/components/playlist';
import YoutubePlayer from '@/components/youtube-player';
import {
controlCurrentDurationAtom,
Expand Down Expand Up @@ -55,51 +55,50 @@ const BottomMusicPlayer = () => {

return (
<>
<section className="flex flex-col w-[100%] min-w-[360px] max-w-[480px] mx-auto fixed bottom-0 z-musicPlayer">
<section className="fixed bottom-0 z-musicPlayer mx-auto flex w-[100%] min-w-[360px] max-w-[480px] flex-col">
<progress
ref={progressRef}
value={maxDuration - currentDuration}
max={maxDuration}
className={clsx(styles.progress, 'w-[100%] h-[3px] rotate-180')}
className={clsx(styles.progress, 'h-[3px] w-[100%] rotate-180')}
onClick={handleCurrentDuration}
/>
<div className="bg-gray-900 py-4 px-5 flex gap-[17px] h-20 items-center">
<div className="flex flex-col mr-auto flex-1 overflow-hidden">
<div className="flex h-20 items-center gap-[17px] bg-gray-900 px-5 py-4">
<div className="flex flex-col flex-1 mr-auto overflow-hidden">
{playerInstance ? (
<>
<h4 className="text-white whitespace-nowrap text-ellipsis overflow-hidden">
<h4 className="overflow-hidden text-white text-ellipsis whitespace-nowrap">
{'한 페이지가 될 수 있게 (Time of Our Life)'}
</h4>
<p className="text-body3 text-white whitespace-nowrap text-ellipsis overflow-hidden">
<p className="overflow-hidden text-white text-ellipsis whitespace-nowrap">
DAY6
</p>
</>
) : null}
</div>
<div className="flex gap-8 items-center">
<div className="flex gap-[23px] items-center">
<div className="flex items-center gap-4">
Copy link
Author

Choose a reason for hiding this comment

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

gap, svg크기 등 디자인 시안이 변동된 부분 반영했습니다.

<div className="flex items-center gap-5">
<ControlPrevIcon
width={20}
height={20}
className="text-white my-auto"
width={18}
height={18}
className="my-auto text-white cursor-pointer"
onClick={() => selectPlaylist('prev')}
/>
<PlayingIcon
width={40}
height={40}
width={32}
height={32}
className="text-white cursor-pointer"
onClick={togglePlayingState}
/>
<ControlNextIcon
width={20}
height={20}
className="text-white my-auto"
width={18}
height={18}
className="my-auto text-white cursor-pointer"
onClick={() => selectPlaylist('next')}
/>
</div>
<PlayListIcon
width={40}
height={40}
<PlaylistButton
iconSize={32}
className="text-white cursor-pointer"
/>
</div>
Expand Down
19 changes: 0 additions & 19 deletions src/components/header/MenuButton.tsx

This file was deleted.

116 changes: 116 additions & 0 deletions src/components/playlist/Playlist.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
'use client';

import Image from 'next/image';
import React from 'react';

import CloseIcon from '@/assets/icons/close.svg';
import Menu from '@/assets/icons/menu.svg';
import AppPortal from '@/components/app-portal';
import BottomMusicPlayer from '@/components/bottom-player';
import Header from '@/components/header/Header';
import { usePlaylist } from '@/components/playlist/hooks/usePlaylist';

// FIX: 현재 임시 데이터로 해놓은 상태. 추후 변경 필요
const PLAYLIST = [
{
id: 1,
url: 'https://via.placeholder.com/50',
title: 'Hype Boys',
artist: 'NewJeans',
},
{
id: 2,
url: 'https://via.placeholder.com/50',
title: '예뻤어 (여름날 우리 X 김민석 (멜로망스))',
artist: '김민석 (멜로망스) 예뻤어 (여름날 우리 X 김민석 (멜로망스))2023',
},
{
id: 3,
url: 'https://via.placeholder.com/50',
title: 'Super Shy',
artist: 'NewJeans',
},
{
id: 4,
url: 'https://via.placeholder.com/50',
title: 'Cool With You',
artist: 'NewJeans',
},
{
id: 5,
url: 'https://via.placeholder.com/50',
title: 'Hype Boys',
artist: 'NewJeans',
},
{
id: 6,
url: 'https://via.placeholder.com/50',
title: '예뻤어 (여름날 우리 X 김민석 (멜로망스))',
artist: '김민석 (멜로망스) 예뻤어 (여름날 우리 X 김민석 (멜로망스))2023',
},
{
id: 7,
url: 'https://via.placeholder.com/50',
title: 'Super Shy',
artist: 'NewJeans',
},
{
id: 8,
url: 'https://via.placeholder.com/50',
title: 'Cool With You',
artist: 'NewJeans',
},
];

const Playlist = () => {
const { closePlaylist } = usePlaylist();
return (
<>
<AppPortal.Wrapper portalName="modal-portal">
<div className="flex flex-col h-screen bg-black">
<Header
headerLeft={<h1>Play List</h1>}
headerRight={
<button type="button" onClick={closePlaylist}>
<CloseIcon className="h-[24px] w-[24px] text-white" />
</button>
}
/>
<ul className="overflow-auto">
{PLAYLIST.map((item) => (
<li
key={item.id}
className="flex items-center gap-[24px] px-5 py-4 hover:bg-gray-900"
>
<Image
className="rounded-full"
src={item.url}
alt={item.title}
width="50"
height="50"
/>
<div className="flex flex-col flex-1 mr-auto overflow-hidden whitespace-nowrap">
<span className="overflow-hidden text-ellipsis text-subtitle1">
{item.title}
</span>
<span className="overflow-hidden text-ellipsis text-body3">
{item.artist}
</span>
</div>
<div className="flex gap-2">
<CloseIcon className="h-[20px] w-[20px] cursor-pointer text-gray-700 hover:text-white" />
<Menu className="h-[20px] w-[20px] cursor-pointer text-gray-700 hover:text-white" />
</div>
</li>
))}
</ul>
</div>
</AppPortal.Wrapper>
<AppPortal.Wrapper portalName="modal-portal">
<BottomMusicPlayer />
</AppPortal.Wrapper>
Comment on lines +109 to +111
Copy link
Author

Choose a reason for hiding this comment

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

사실 하단 플레이어의 경우 template으로 빼던가 해야할 것 같습니다. 우선 폴더구조가 명확히 잡혀있지 않아 임시로 플레이리스트에 같이 작성해두었습니다.

Copy link
Contributor

Choose a reason for hiding this comment

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

각 페이지 마다 계속 해당 컴포넌트를 삽입하기 보다는 template으로 분리하는 게 좋아 보이네요. 가능하다면 그렇게 작업하는 것이 좋아 보입니다. 요구사항이 점점 늘어날수록 변수도 많아지네요.

Copy link
Author

Choose a reason for hiding this comment

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

맞습니다 아마 나중에 폴더구조가 잡히면 수정하지 않을까 싶어요. 그런데 고민인 부분은, 여기서 Playlist.tsx 페이지가 아닌 컴포넌트로 만들어서 따로 layout을 사용하기가 애매해질것 같긴합니다.. Playing 페이지에서는 하단 뮤직 플레이어바가 안보이고 플레이리스트에서는 보여져야 하는 상황이여서요

</>
);
};

export default Playlist;
Loading