모바일에서 튜토리얼 버튼 위치 변경

main
김성경 2026-06-01 10:14:17 +09:00
parent 7f1e2b83a9
commit b18dd7aa4d
4 changed files with 81 additions and 4 deletions

View File

@ -931,6 +931,56 @@
font-weight: 700;
}
/* 모바일 전용 사이드바 튜토리얼 토글 */
.sidebar-tutorial-btn {
display: none;
}
@media (max-width: 767px) {
.sidebar-tutorial-btn {
display: flex;
align-items: center;
gap: 0.75rem;
width: 100%;
margin-top: 0.5rem;
padding: 0.75rem;
border-radius: var(--radius-lg);
color: var(--color-text-gray-400);
border: none;
background: none;
cursor: pointer;
font-size: var(--text-sm);
font-weight: 500;
transition: color var(--transition-normal), background-color var(--transition-normal);
}
.sidebar-tutorial-btn:hover {
color: var(--color-text-white);
background-color: rgba(255, 255, 255, 0.05);
}
.sidebar-tutorial-btn.active {
color: var(--color-mint);
}
.sidebar-tutorial-label {
text-align: left;
}
.sidebar-tutorial-badge {
font-size: 11px;
font-weight: 700;
}
.sidebar-tutorial-badge.on {
color: var(--color-mint);
}
.sidebar-tutorial-badge.off {
color: var(--color-text-gray-400);
}
}
/* Mobile Menu Button */
.mobile-menu-btn {
position: fixed;
@ -12301,6 +12351,12 @@
border-color: rgba(166, 255, 234, 0.4);
}
@media (max-width: 767px) {
.tutorial-toggle-fab {
display: none;
}
}
.tutorial-toggle-badge {
font-size: 10px;
font-weight: 700;

View File

@ -41,7 +41,7 @@
</ul>
<h2>제 6 조 (외부 API 연동 및 데이터 활용)</h2>
<p>서비스는 Google, YouTube, Naver 등의 제3자 API를 활용하여 마케팅 자동화 기능을 제공합니다. 특히 YouTube 서비스 연동을 위해 YouTube Data API(<code>youtube.readonly</code>, <code>youtube.upload</code>) 및 YouTube Analytics API(<code>yt-analytics.readonly</code>)를 사용하며, 이를 통해 수집·처리되는 데이터는 <a href="/privacy.html">개인정보처리방침</a>에 따라 관리됩니다. 회원은 각 외부 서비스의 이용약관 및 정책을 준수할 의무가 있으며, 외부 API 제공사의 정책 변경으로 인한 서비스 제한에 대해 회사는 면책됩니다.</p>
<p>서비스는 Google, YouTube, Naver 등의 제3자 API를 활용하여 마케팅 자동화 기능을 제공합니다. 특히 YouTube 서비스 연동을 위해 YouTube Data API 및 YouTube Analytics API를 사용하며, 이를 통해 수집·처리되는 데이터는 <a href="/privacy.html">개인정보처리방침</a>에 따라 관리됩니다. 회원은 각 외부 서비스의 이용약관 및 정책을 준수할 의무가 있으며, 외부 API 제공사의 정책 변경으로 인한 서비스 제한에 대해 회사는 면책됩니다.</p>
<p>YouTube API 서비스 이용과 관련하여 <a href="https://www.youtube.com/t/terms" target="_blank">YouTube 이용약관</a><a href="https://policies.google.com/privacy" target="_blank">Google 개인정보처리방침</a>이 함께 적용됩니다.</p>
<h2>제 7 조 (AI 생성 콘텐츠의 권리)</h2>

View File

@ -38,9 +38,12 @@ interface SidebarProps {
userInfo?: UserMeResponse | null;
onLogout?: () => void;
credits?: number | null;
tutorialAvailable?: boolean;
tutorialEnabled?: boolean;
onToggleTutorial?: () => void;
}
const Sidebar: React.FC<SidebarProps> = ({ activeItem, onNavigate, onHome, userInfo, onLogout, credits }) => {
const Sidebar: React.FC<SidebarProps> = ({ activeItem, onNavigate, onHome, userInfo, onLogout, credits, tutorialAvailable, tutorialEnabled, onToggleTutorial }) => {
const { t } = useTranslation();
const [isCollapsed, setIsCollapsed] = useState(false);
const [isMobileOpen, setIsMobileOpen] = useState(false);
@ -159,6 +162,24 @@ const Sidebar: React.FC<SidebarProps> = ({ activeItem, onNavigate, onHome, userI
</div>
<div className="sidebar-footer">
{/* 모바일 전용 튜토리얼 토글 */}
{tutorialAvailable && (
<button
className={`sidebar-tutorial-btn ${tutorialEnabled ? 'active' : ''}`}
onClick={() => onToggleTutorial?.()}
title={tutorialEnabled ? t('sidebar.tutorialOff') : t('sidebar.tutorialOn')}
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
<circle cx="12" cy="12" r="10"/>
<path d="M12 8v4l3 3"/>
</svg>
<span className="sidebar-tutorial-label">{t('sidebar.tutorial')}</span>
<span className={`sidebar-tutorial-badge ${tutorialEnabled ? 'on' : 'off'}`}>
{tutorialEnabled ? 'ON' : 'OFF'}
</span>
</button>
)}
<div className="sidebar-language-switch">
<LanguageSwitch isCollapsed={isCollapsed} />
</div>

View File

@ -632,7 +632,7 @@ const GenerationFlow: React.FC<GenerationFlowProps> = ({
return (
<div className="analysis-page-wrapper">
{showSidebar && (
<Sidebar activeItem={activeItem} onNavigate={handleNavigate} onHome={handleHome} userInfo={userInfo} onLogout={handleLogout} credits={credits} />
<Sidebar activeItem={activeItem} onNavigate={handleNavigate} onHome={handleHome} userInfo={userInfo} onLogout={handleLogout} credits={credits} tutorialAvailable={!!getCurrentTutorialKey()} tutorialEnabled={tutorial.isEnabled} onToggleTutorial={() => tutorial.toggleTutorial(getCurrentTutorialKey())} />
)}
<main className="analysis-page-main">
{renderContent()}
@ -645,7 +645,7 @@ const GenerationFlow: React.FC<GenerationFlowProps> = ({
return (
<div className={`flex w-full bg-[#002224] text-white ${needsScroll ? 'min-h-[100dvh]' : 'h-[100dvh] overflow-hidden'}`}>
{showSidebar && (
<Sidebar activeItem={activeItem} onNavigate={handleNavigate} onHome={handleHome} userInfo={userInfo} onLogout={handleLogout} credits={credits} />
<Sidebar activeItem={activeItem} onNavigate={handleNavigate} onHome={handleHome} userInfo={userInfo} onLogout={handleLogout} credits={credits} tutorialAvailable={!!getCurrentTutorialKey()} tutorialEnabled={tutorial.isEnabled} onToggleTutorial={() => tutorial.toggleTutorial(getCurrentTutorialKey())} />
)}
{tutorialUI}
<div className={`flex-1 relative pl-0 md:pl-0 ${needsScroll ? 'overflow-auto' : 'h-full overflow-hidden'}`}>