From 1351370ce8a23f9759242f70e1d0abbbad2936ee Mon Sep 17 00:00:00 2001 From: hbyang Date: Tue, 13 Jan 2026 17:51:48 +0900 Subject: [PATCH] =?UTF-8?q?0113=20=EC=88=98=EC=A0=95=20=EC=82=AC=ED=95=AD?= =?UTF-8?q?=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.css | 135 +++++++++++++-------- src/components/Sidebar.tsx | 37 ++---- src/pages/Dashboard/SoundStudioContent.tsx | 16 +-- 3 files changed, 104 insertions(+), 84 deletions(-) diff --git a/index.css b/index.css index 31f09c3..343a873 100644 --- a/index.css +++ b/index.css @@ -630,11 +630,17 @@ color: var(--color-text-gray-400); } -.sidebar-item:not(.active):hover { +.sidebar-item:not(.active):not(.disabled):hover { background-color: rgba(255, 255, 255, 0.05); color: var(--color-text-white); } +.sidebar-item.disabled { + opacity: 0.4; + cursor: not-allowed; + pointer-events: none; +} + .sidebar-item-icon { flex-shrink: 0; display: flex; @@ -1436,9 +1442,11 @@ width: calc(100% - 4rem); display: flex; flex-direction: column; - gap: 1rem; + gap: 1.5rem; flex: 1; min-height: 0; + overflow-y: auto; + overflow-x: hidden; } @media (min-width: 1024px) { @@ -1446,6 +1454,7 @@ flex-direction: row; gap: 2rem; max-width: 1400px; + overflow: hidden; } } @@ -1458,6 +1467,7 @@ @media (max-width: 480px) { .completion-container { width: calc(100% - 2rem); + gap: 1.25rem; } } @@ -1474,8 +1484,9 @@ } .completion-column-left { - flex: 1; + width: 100%; min-width: 0; + flex-shrink: 0; } .completion-column-right { @@ -1484,6 +1495,11 @@ } @media (min-width: 1024px) { + .completion-column-left { + flex: 1; + width: auto; + } + .completion-column-right { width: 400px; } @@ -1507,6 +1523,7 @@ display: flex; flex-direction: column; gap: 1.25rem; + flex-shrink: 0; } @media (min-width: 768px) { @@ -1517,6 +1534,12 @@ } @media (min-width: 1024px) { + .video-preview-card { + flex-shrink: 1; + flex: 1; + min-height: 0; + } + .video-preview-card, .sharing-card { padding: 2.5rem; @@ -1525,12 +1548,17 @@ /* Completion Video Wrapper */ .completion-video-wrapper { - flex: 1; - min-height: 0; display: flex; flex-direction: column; } +@media (min-width: 1024px) { + .completion-video-wrapper { + flex: 1; + min-height: 0; + } +} + /* Video Container for Completion - always 16:9 aspect ratio (horizontal letterbox) */ .video-preview-card .video-container { position: relative; @@ -4412,29 +4440,30 @@ /* Sound Studio Columns */ .sound-studio-columns { display: flex; - gap: 2.5rem; + flex-direction: column; + gap: 1.5rem; flex: 1; min-height: 0; - overflow: hidden; + overflow-y: auto; + overflow-x: hidden; } /* Sound Column */ .sound-column { - flex: 1; + width: 100%; display: flex; flex-direction: column; gap: 1.25rem; - min-height: 0; - overflow-y: auto; + flex-shrink: 0; } /* Lyrics Column */ .lyrics-column { - flex: 1; + width: 100%; display: flex; flex-direction: column; gap: 1.25rem; - min-height: 0; + flex-shrink: 0; } /* Column Title */ @@ -4822,10 +4851,10 @@ /* Video Generate Button */ .btn-video-generate { padding: 0.625rem 2.5rem; - background-color: #462E64; + background-color: #AE72F9; border: none; border-radius: var(--radius-full); - color: #8B5BC7; + color: #FFFFFF; font-size: var(--text-sm); font-weight: 600; cursor: pointer; @@ -4840,11 +4869,13 @@ } .btn-video-generate:hover:not(.disabled):not(.generating) { - background-color: #694596; + background-color: #9B5DE5; } .btn-video-generate.disabled { - opacity: 0.5; + background-color: #462E64; + color: #8B5BC7; + opacity: 0.7; cursor: not-allowed; } @@ -4927,15 +4958,6 @@ width: calc(100% - 2rem); } - .sound-studio-columns { - flex-direction: column; - gap: 1.5rem; - } - - .sound-column { - overflow-y: visible; - } - .sound-type-grid { gap: 0.5rem; } @@ -4976,24 +4998,14 @@ } .sound-studio-columns { - flex-direction: column; gap: 2rem; } - - .sound-column { - overflow-y: visible; - } } @media (min-width: 768px) and (max-width: 1023px) { .sound-studio-columns { - flex-direction: column; gap: 2rem; } - - .sound-column { - overflow-y: visible; - } } @media (min-width: 1024px) { @@ -5002,7 +5014,22 @@ } .sound-studio-columns { + flex-direction: row; gap: 3rem; + overflow: hidden; + } + + .sound-column { + flex: 1; + width: auto; + min-height: 0; + overflow-y: auto; + } + + .lyrics-column { + flex: 1; + width: auto; + min-height: 0; } .column-title { @@ -5114,14 +5141,17 @@ width: calc(100% - 4rem); display: flex; flex-direction: column; - gap: 1rem; + gap: 1.5rem; flex: 1; min-height: 0; + overflow-y: auto; + overflow-x: hidden; } @media (min-width: 1024px) { .asset-container { flex-direction: row; + overflow: hidden; } } @@ -5133,10 +5163,9 @@ } .asset-column-left { - flex: 1; + width: 100%; min-width: 0; - min-height: 0; - overflow: hidden; + flex-shrink: 0; } .asset-column-right { @@ -5145,6 +5174,12 @@ } @media (min-width: 1024px) { + .asset-column-left { + flex: 1; + min-height: 0; + overflow: hidden; + } + .asset-column-right { width: 280px; } @@ -5162,8 +5197,8 @@ /* Asset Image List */ .asset-image-list { - flex: 1; - min-height: 0; + min-height: 120px; + max-height: 200px; overflow-y: auto; overscroll-behavior: contain; background-color: #002224; @@ -5171,6 +5206,14 @@ padding: 0.5rem; } +@media (min-width: 1024px) { + .asset-image-list { + flex: 1; + min-height: 0; + max-height: none; + } +} + .asset-image-list::-webkit-scrollbar { width: 6px; } @@ -5389,16 +5432,11 @@ } .asset-container { - flex-direction: column; padding: 1.25rem; width: calc(100% - 2rem); gap: 1.25rem; } - .asset-column-right { - width: 100%; - } - .asset-image-grid { grid-template-columns: repeat(2, 1fr); } @@ -5420,15 +5458,10 @@ } .asset-container { - flex-direction: column; padding: 1.5rem; width: calc(100% - 3rem); } - .asset-column-right { - width: 100%; - } - .asset-bottom { padding: 0 1.5rem 1.25rem 1.5rem; } diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index c670356..884c7de 100755 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -6,14 +6,15 @@ interface SidebarItemProps { label: string; isActive?: boolean; isCollapsed: boolean; + isDisabled?: boolean; onClick?: () => void; } -const SidebarItem: React.FC = ({ icon, label, isActive, isCollapsed, onClick }) => { +const SidebarItem: React.FC = ({ icon, label, isActive, isCollapsed, isDisabled, onClick }) => { return (
@@ -54,13 +55,13 @@ const Sidebar: React.FC = ({ activeItem, onNavigate, onHome }) => }; const menuItems = [ - { id: '대시보드', label: '대시보드', icon: }, - { id: '새 프로젝트 만들기', label: '새 프로젝트 만들기', icon: }, - { id: '내 보관함', label: '내 보관함', icon: }, - { id: '에셋 관리', label: '에셋 관리', icon: }, - { id: '내 펜션', label: '내 펜션', icon: }, - { id: '계정 설정', label: '계정 설정', icon: }, - { id: '비즈니스 설정', label: '비즈니스 설정', icon: }, + { id: '대시보드', label: '대시보드', disabled: true, icon: }, + { id: '새 프로젝트 만들기', label: '새 프로젝트 만들기', disabled: false, icon: }, + { id: '내 보관함', label: '내 보관함', disabled: true, icon: }, + { id: '에셋 관리', label: '에셋 관리', disabled: true, icon: }, + { id: '내 펜션', label: '내 펜션', disabled: true, icon: }, + { id: '계정 설정', label: '계정 설정', disabled: true, icon: }, + { id: '비즈니스 설정', label: '비즈니스 설정', disabled: true, icon: }, ]; return ( @@ -115,27 +116,13 @@ const Sidebar: React.FC = ({ activeItem, onNavigate, onHome }) => label={item.label} isCollapsed={isCollapsed} isActive={activeItem === item.id} + isDisabled={item.disabled} onClick={() => handleNavigate(item.id)} /> ))}
- {!isCollapsed && ( -
-
- Credit - 850 / 1000 -
-
-
-
- -
- )} -
= ({ setShowLyrics(true); } setStatus('polling'); - setStatusMessage('음악을 처리하고 있습니다... (새로고침 후 복구됨)'); + setStatusMessage('작곡을 생성하고 있습니다... (새로고침 후 복구됨)'); resumePolling(savedState.taskId, savedState.sunoTaskId, savedState.lyrics, 0); } }, []); @@ -153,9 +153,9 @@ const SoundStudioContent: React.FC = ({ sunoTaskId, (pollStatus: string) => { if (pollStatus === 'pending') { - setStatusMessage('대기 중...'); + setStatusMessage('작곡을 생성하고 있습니다...'); } else if (pollStatus === 'processing') { - setStatusMessage('음악을 처리하고 있습니다...'); + setStatusMessage('작곡을 생성하고 있습니다...'); } } ); @@ -329,7 +329,7 @@ const SoundStudioContent: React.FC = ({ setStatus('generating_lyric'); setErrorMessage(null); - setStatusMessage('가사를 생성하고 있습니다...'); + setStatusMessage('작사를 생성하고 있습니다...'); try { const language = LANGUAGE_MAP[selectedLang] || 'Korean'; @@ -348,12 +348,12 @@ const SoundStudioContent: React.FC = ({ } // 2. 가사 생성 상태 폴링 → 완료 시 상세 조회 - setStatusMessage('가사를 처리하고 있습니다...'); + setStatusMessage('작사를 생성하고 있습니다...'); const lyricDetailResponse = await waitForLyricComplete( lyricResponse.task_id, (status: string) => { if (status === 'processing') { - setStatusMessage('가사를 처리하고 있습니다...'); + setStatusMessage('작사를 생성하고 있습니다...'); } } ); @@ -371,7 +371,7 @@ const SoundStudioContent: React.FC = ({ setShowLyrics(true); setStatus('generating_song'); - setStatusMessage('음악을 생성하고 있습니다...'); + setStatusMessage('작곡을 생성하고 있습니다...'); const genreMap: Record = { '자동 선택': 'pop', @@ -395,7 +395,7 @@ const SoundStudioContent: React.FC = ({ } setStatus('polling'); - setStatusMessage('음악을 처리하고 있습니다...'); + setStatusMessage('작곡을 생성하고 있습니다...'); saveToStorage(songResponse.task_id, songResponse.suno_task_id, lyricDetailResponse.lyric_result, 'polling'); await resumePolling(songResponse.task_id, songResponse.suno_task_id, lyricDetailResponse.lyric_result, 0);