0113 수정 사항 반영
parent
57377c7d1f
commit
1351370ce8
135
index.css
135
index.css
|
|
@ -630,11 +630,17 @@
|
||||||
color: var(--color-text-gray-400);
|
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);
|
background-color: rgba(255, 255, 255, 0.05);
|
||||||
color: var(--color-text-white);
|
color: var(--color-text-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-item.disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-item-icon {
|
.sidebar-item-icon {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -1436,9 +1442,11 @@
|
||||||
width: calc(100% - 4rem);
|
width: calc(100% - 4rem);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1.5rem;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
|
|
@ -1446,6 +1454,7 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
max-width: 1400px;
|
max-width: 1400px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1458,6 +1467,7 @@
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.completion-container {
|
.completion-container {
|
||||||
width: calc(100% - 2rem);
|
width: calc(100% - 2rem);
|
||||||
|
gap: 1.25rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1474,8 +1484,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.completion-column-left {
|
.completion-column-left {
|
||||||
flex: 1;
|
width: 100%;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.completion-column-right {
|
.completion-column-right {
|
||||||
|
|
@ -1484,6 +1495,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
|
.completion-column-left {
|
||||||
|
flex: 1;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.completion-column-right {
|
.completion-column-right {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
}
|
}
|
||||||
|
|
@ -1507,6 +1523,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
|
|
@ -1517,6 +1534,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
|
.video-preview-card {
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.video-preview-card,
|
.video-preview-card,
|
||||||
.sharing-card {
|
.sharing-card {
|
||||||
padding: 2.5rem;
|
padding: 2.5rem;
|
||||||
|
|
@ -1525,12 +1548,17 @@
|
||||||
|
|
||||||
/* Completion Video Wrapper */
|
/* Completion Video Wrapper */
|
||||||
.completion-video-wrapper {
|
.completion-video-wrapper {
|
||||||
flex: 1;
|
|
||||||
min-height: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
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 Container for Completion - always 16:9 aspect ratio (horizontal letterbox) */
|
||||||
.video-preview-card .video-container {
|
.video-preview-card .video-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -4412,29 +4440,30 @@
|
||||||
/* Sound Studio Columns */
|
/* Sound Studio Columns */
|
||||||
.sound-studio-columns {
|
.sound-studio-columns {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 2.5rem;
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow: hidden;
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sound Column */
|
/* Sound Column */
|
||||||
.sound-column {
|
.sound-column {
|
||||||
flex: 1;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
min-height: 0;
|
flex-shrink: 0;
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lyrics Column */
|
/* Lyrics Column */
|
||||||
.lyrics-column {
|
.lyrics-column {
|
||||||
flex: 1;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
min-height: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Column Title */
|
/* Column Title */
|
||||||
|
|
@ -4822,10 +4851,10 @@
|
||||||
/* Video Generate Button */
|
/* Video Generate Button */
|
||||||
.btn-video-generate {
|
.btn-video-generate {
|
||||||
padding: 0.625rem 2.5rem;
|
padding: 0.625rem 2.5rem;
|
||||||
background-color: #462E64;
|
background-color: #AE72F9;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: var(--radius-full);
|
border-radius: var(--radius-full);
|
||||||
color: #8B5BC7;
|
color: #FFFFFF;
|
||||||
font-size: var(--text-sm);
|
font-size: var(--text-sm);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
@ -4840,11 +4869,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-video-generate:hover:not(.disabled):not(.generating) {
|
.btn-video-generate:hover:not(.disabled):not(.generating) {
|
||||||
background-color: #694596;
|
background-color: #9B5DE5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-video-generate.disabled {
|
.btn-video-generate.disabled {
|
||||||
opacity: 0.5;
|
background-color: #462E64;
|
||||||
|
color: #8B5BC7;
|
||||||
|
opacity: 0.7;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4927,15 +4958,6 @@
|
||||||
width: calc(100% - 2rem);
|
width: calc(100% - 2rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sound-studio-columns {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sound-column {
|
|
||||||
overflow-y: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sound-type-grid {
|
.sound-type-grid {
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
@ -4976,24 +4998,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.sound-studio-columns {
|
.sound-studio-columns {
|
||||||
flex-direction: column;
|
|
||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sound-column {
|
|
||||||
overflow-y: visible;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) and (max-width: 1023px) {
|
@media (min-width: 768px) and (max-width: 1023px) {
|
||||||
.sound-studio-columns {
|
.sound-studio-columns {
|
||||||
flex-direction: column;
|
|
||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sound-column {
|
|
||||||
overflow-y: visible;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
|
|
@ -5002,7 +5014,22 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.sound-studio-columns {
|
.sound-studio-columns {
|
||||||
|
flex-direction: row;
|
||||||
gap: 3rem;
|
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 {
|
.column-title {
|
||||||
|
|
@ -5114,14 +5141,17 @@
|
||||||
width: calc(100% - 4rem);
|
width: calc(100% - 4rem);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1.5rem;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
.asset-container {
|
.asset-container {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5133,10 +5163,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.asset-column-left {
|
.asset-column-left {
|
||||||
flex: 1;
|
width: 100%;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
flex-shrink: 0;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.asset-column-right {
|
.asset-column-right {
|
||||||
|
|
@ -5145,6 +5174,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
|
.asset-column-left {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.asset-column-right {
|
.asset-column-right {
|
||||||
width: 280px;
|
width: 280px;
|
||||||
}
|
}
|
||||||
|
|
@ -5162,8 +5197,8 @@
|
||||||
|
|
||||||
/* Asset Image List */
|
/* Asset Image List */
|
||||||
.asset-image-list {
|
.asset-image-list {
|
||||||
flex: 1;
|
min-height: 120px;
|
||||||
min-height: 0;
|
max-height: 200px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
background-color: #002224;
|
background-color: #002224;
|
||||||
|
|
@ -5171,6 +5206,14 @@
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.asset-image-list {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.asset-image-list::-webkit-scrollbar {
|
.asset-image-list::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
}
|
}
|
||||||
|
|
@ -5389,16 +5432,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.asset-container {
|
.asset-container {
|
||||||
flex-direction: column;
|
|
||||||
padding: 1.25rem;
|
padding: 1.25rem;
|
||||||
width: calc(100% - 2rem);
|
width: calc(100% - 2rem);
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.asset-column-right {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.asset-image-grid {
|
.asset-image-grid {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
|
@ -5420,15 +5458,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.asset-container {
|
.asset-container {
|
||||||
flex-direction: column;
|
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
width: calc(100% - 3rem);
|
width: calc(100% - 3rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.asset-column-right {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.asset-bottom {
|
.asset-bottom {
|
||||||
padding: 0 1.5rem 1.25rem 1.5rem;
|
padding: 0 1.5rem 1.25rem 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,15 @@ interface SidebarItemProps {
|
||||||
label: string;
|
label: string;
|
||||||
isActive?: boolean;
|
isActive?: boolean;
|
||||||
isCollapsed: boolean;
|
isCollapsed: boolean;
|
||||||
|
isDisabled?: boolean;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SidebarItem: React.FC<SidebarItemProps> = ({ icon, label, isActive, isCollapsed, onClick }) => {
|
const SidebarItem: React.FC<SidebarItemProps> = ({ icon, label, isActive, isCollapsed, isDisabled, onClick }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={onClick}
|
onClick={isDisabled ? undefined : onClick}
|
||||||
className={`sidebar-item ${isActive ? 'active' : ''} ${isCollapsed ? 'collapsed' : ''}`}
|
className={`sidebar-item ${isActive ? 'active' : ''} ${isCollapsed ? 'collapsed' : ''} ${isDisabled ? 'disabled' : ''}`}
|
||||||
title={isCollapsed ? label : ""}
|
title={isCollapsed ? label : ""}
|
||||||
>
|
>
|
||||||
<div className="sidebar-item-icon">
|
<div className="sidebar-item-icon">
|
||||||
|
|
@ -54,13 +55,13 @@ const Sidebar: React.FC<SidebarProps> = ({ activeItem, onNavigate, onHome }) =>
|
||||||
};
|
};
|
||||||
|
|
||||||
const menuItems = [
|
const menuItems = [
|
||||||
{ id: '대시보드', label: '대시보드', icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/></svg> },
|
{ id: '대시보드', label: '대시보드', disabled: true, icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/></svg> },
|
||||||
{ id: '새 프로젝트 만들기', label: '새 프로젝트 만들기', icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> },
|
{ id: '새 프로젝트 만들기', label: '새 프로젝트 만들기', disabled: false, icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> },
|
||||||
{ id: '내 보관함', label: '내 보관함', icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg> },
|
{ id: '내 보관함', label: '내 보관함', disabled: true, icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg> },
|
||||||
{ id: '에셋 관리', label: '에셋 관리', icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg> },
|
{ id: '에셋 관리', label: '에셋 관리', disabled: true, icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg> },
|
||||||
{ id: '내 펜션', label: '내 펜션', icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg> },
|
{ id: '내 펜션', label: '내 펜션', disabled: true, icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg> },
|
||||||
{ id: '계정 설정', label: '계정 설정', icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> },
|
{ id: '계정 설정', label: '계정 설정', disabled: true, icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> },
|
||||||
{ id: '비즈니스 설정', label: '비즈니스 설정', icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1-2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg> },
|
{ id: '비즈니스 설정', label: '비즈니스 설정', disabled: true, icon: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1-2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg> },
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -115,27 +116,13 @@ const Sidebar: React.FC<SidebarProps> = ({ activeItem, onNavigate, onHome }) =>
|
||||||
label={item.label}
|
label={item.label}
|
||||||
isCollapsed={isCollapsed}
|
isCollapsed={isCollapsed}
|
||||||
isActive={activeItem === item.id}
|
isActive={activeItem === item.id}
|
||||||
|
isDisabled={item.disabled}
|
||||||
onClick={() => handleNavigate(item.id)}
|
onClick={() => handleNavigate(item.id)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="sidebar-footer">
|
<div className="sidebar-footer">
|
||||||
{!isCollapsed && (
|
|
||||||
<div className="credit-card">
|
|
||||||
<div className="credit-header">
|
|
||||||
<span className="credit-label">Credit</span>
|
|
||||||
<span className="credit-value">850 / 1000</span>
|
|
||||||
</div>
|
|
||||||
<div className="credit-bar">
|
|
||||||
<div className="credit-bar-fill" style={{ width: '85%' }}></div>
|
|
||||||
</div>
|
|
||||||
<button className="credit-upgrade-btn">
|
|
||||||
업그레이드
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className={`profile-section ${isCollapsed ? 'collapsed' : ''}`}>
|
<div className={`profile-section ${isCollapsed ? 'collapsed' : ''}`}>
|
||||||
<img
|
<img
|
||||||
src="https://picsum.photos/seed/user/100/100"
|
src="https://picsum.photos/seed/user/100/100"
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ const SoundStudioContent: React.FC<SoundStudioContentProps> = ({
|
||||||
setShowLyrics(true);
|
setShowLyrics(true);
|
||||||
}
|
}
|
||||||
setStatus('polling');
|
setStatus('polling');
|
||||||
setStatusMessage('음악을 처리하고 있습니다... (새로고침 후 복구됨)');
|
setStatusMessage('작곡을 생성하고 있습니다... (새로고침 후 복구됨)');
|
||||||
resumePolling(savedState.taskId, savedState.sunoTaskId, savedState.lyrics, 0);
|
resumePolling(savedState.taskId, savedState.sunoTaskId, savedState.lyrics, 0);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -153,9 +153,9 @@ const SoundStudioContent: React.FC<SoundStudioContentProps> = ({
|
||||||
sunoTaskId,
|
sunoTaskId,
|
||||||
(pollStatus: string) => {
|
(pollStatus: string) => {
|
||||||
if (pollStatus === 'pending') {
|
if (pollStatus === 'pending') {
|
||||||
setStatusMessage('대기 중...');
|
setStatusMessage('작곡을 생성하고 있습니다...');
|
||||||
} else if (pollStatus === 'processing') {
|
} else if (pollStatus === 'processing') {
|
||||||
setStatusMessage('음악을 처리하고 있습니다...');
|
setStatusMessage('작곡을 생성하고 있습니다...');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
@ -329,7 +329,7 @@ const SoundStudioContent: React.FC<SoundStudioContentProps> = ({
|
||||||
|
|
||||||
setStatus('generating_lyric');
|
setStatus('generating_lyric');
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
setStatusMessage('가사를 생성하고 있습니다...');
|
setStatusMessage('작사를 생성하고 있습니다...');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const language = LANGUAGE_MAP[selectedLang] || 'Korean';
|
const language = LANGUAGE_MAP[selectedLang] || 'Korean';
|
||||||
|
|
@ -348,12 +348,12 @@ const SoundStudioContent: React.FC<SoundStudioContentProps> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 가사 생성 상태 폴링 → 완료 시 상세 조회
|
// 2. 가사 생성 상태 폴링 → 완료 시 상세 조회
|
||||||
setStatusMessage('가사를 처리하고 있습니다...');
|
setStatusMessage('작사를 생성하고 있습니다...');
|
||||||
const lyricDetailResponse = await waitForLyricComplete(
|
const lyricDetailResponse = await waitForLyricComplete(
|
||||||
lyricResponse.task_id,
|
lyricResponse.task_id,
|
||||||
(status: string) => {
|
(status: string) => {
|
||||||
if (status === 'processing') {
|
if (status === 'processing') {
|
||||||
setStatusMessage('가사를 처리하고 있습니다...');
|
setStatusMessage('작사를 생성하고 있습니다...');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
@ -371,7 +371,7 @@ const SoundStudioContent: React.FC<SoundStudioContentProps> = ({
|
||||||
setShowLyrics(true);
|
setShowLyrics(true);
|
||||||
|
|
||||||
setStatus('generating_song');
|
setStatus('generating_song');
|
||||||
setStatusMessage('음악을 생성하고 있습니다...');
|
setStatusMessage('작곡을 생성하고 있습니다...');
|
||||||
|
|
||||||
const genreMap: Record<string, string> = {
|
const genreMap: Record<string, string> = {
|
||||||
'자동 선택': 'pop',
|
'자동 선택': 'pop',
|
||||||
|
|
@ -395,7 +395,7 @@ const SoundStudioContent: React.FC<SoundStudioContentProps> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
setStatus('polling');
|
setStatus('polling');
|
||||||
setStatusMessage('음악을 처리하고 있습니다...');
|
setStatusMessage('작곡을 생성하고 있습니다...');
|
||||||
saveToStorage(songResponse.task_id, songResponse.suno_task_id, lyricDetailResponse.lyric_result, 'polling');
|
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);
|
await resumePolling(songResponse.task_id, songResponse.suno_task_id, lyricDetailResponse.lyric_result, 0);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue