import React, { useEffect, useState } from 'react' import { Link, usePage } from '@inertiajs/react' import { studioModule, studioSurface, trackStudioEvent } from '../utils/studioEvents' const baseNavGroups = [ { label: 'Creator Studio', items: [ { label: 'Overview', href: '/studio', icon: 'fa-solid fa-chart-line' }, { label: 'Search', href: '/studio/search', icon: 'fa-solid fa-magnifying-glass' }, { label: 'Groups', href: '/studio/groups', icon: 'fa-solid fa-people-group' }, ], }, { label: 'Create', items: [ { label: 'New Artwork', href: '/upload', icon: 'fa-solid fa-cloud-arrow-up' }, { label: 'New Card', href: '/studio/cards/create', icon: 'fa-solid fa-id-card' }, { label: 'New Story', href: '/creator/stories/create', icon: 'fa-solid fa-feather-pointed' }, { label: 'New Collection', href: '/settings/collections/create', icon: 'fa-solid fa-layer-group' }, ], }, { label: 'Content', items: [ { label: 'All Content', href: '/studio/content', icon: 'fa-solid fa-table-cells-large' }, { label: 'Artworks', href: '/studio/artworks', icon: 'fa-solid fa-images' }, { label: 'Cards', href: '/studio/cards', icon: 'fa-solid fa-id-card' }, { label: 'Collections', href: '/studio/collections', icon: 'fa-solid fa-layer-group' }, { label: 'Stories', href: '/studio/stories', icon: 'fa-solid fa-feather-pointed' }, ], }, { label: 'Library', items: [ { label: 'Drafts', href: '/studio/drafts', icon: 'fa-solid fa-file-pen' }, { label: 'Scheduled', href: '/studio/scheduled', icon: 'fa-solid fa-calendar-days' }, { label: 'Calendar', href: '/studio/calendar', icon: 'fa-solid fa-calendar-range' }, { label: 'Archived', href: '/studio/archived', icon: 'fa-solid fa-box-archive' }, { label: 'Assets', href: '/studio/assets', icon: 'fa-solid fa-photo-film' }, ], }, { label: 'Engagement', items: [ { label: 'Inbox', href: '/studio/inbox', icon: 'fa-solid fa-inbox' }, { label: 'Activity', href: '/studio/activity', icon: 'fa-solid fa-bell' }, { label: 'Comments', href: '/studio/comments', icon: 'fa-solid fa-comments' }, { label: 'Followers', href: '/studio/followers', icon: 'fa-solid fa-user-group' }, { label: 'Challenges', href: '/studio/challenges', icon: 'fa-solid fa-trophy' }, ], }, { label: 'Insights', items: [ { label: 'Analytics', href: '/studio/analytics', icon: 'fa-solid fa-chart-pie' }, { label: 'Growth', href: '/studio/growth', icon: 'fa-solid fa-chart-line' }, ], }, { label: 'Creator', items: [ { label: 'Profile', href: '/studio/profile', icon: 'fa-solid fa-id-card' }, { label: 'Featured Content', href: '/studio/featured', icon: 'fa-solid fa-wand-magic-sparkles' }, { label: 'Preferences', href: '/studio/preferences', icon: 'fa-solid fa-sliders' }, { label: 'Studio Settings', href: '/studio/settings', icon: 'fa-solid fa-gear' }, ], }, ] const baseQuickCreateItems = [ { label: 'Artwork', href: '/upload', icon: 'fa-solid fa-cloud-arrow-up' }, { label: 'Card', href: '/studio/cards/create', icon: 'fa-solid fa-id-card' }, { label: 'Story', href: '/creator/stories/create', icon: 'fa-solid fa-feather-pointed' }, { label: 'Collection', href: '/settings/collections/create', icon: 'fa-solid fa-layer-group' }, ] const STUDIO_CONTEXT_STORAGE_KEY = 'sb.studio.last-context' const RESTORABLE_STUDIO_PATHS = ['/studio', '/studio/artworks', '/studio/collections', '/studio/settings'] function supportsStudioContextRestore(pathname) { return RESTORABLE_STUDIO_PATHS.includes(pathname) } function studioRouteKeyForPath(pathname) { if (pathname === '/studio/artworks' || pathname.endsWith('/artworks')) return 'studio_artworks_url' if (pathname === '/studio/collections' || pathname.endsWith('/collections')) return 'studio_collections_url' if (pathname === '/studio/settings' || pathname.endsWith('/settings')) return 'studio_settings_url' if (pathname.endsWith('/members')) return 'studio_members_url' if (pathname.endsWith('/invitations')) return 'studio_invitations_url' return 'studio_url' } function nestedRouteKeyFor(topLevelRouteKey) { return topLevelRouteKey.replace(/_url$/, '') } function groupStudioUrlForPath(group, pathname) { if (!group) return '/studio' const routeKey = studioRouteKeyForPath(pathname) const nestedRouteKey = nestedRouteKeyFor(routeKey) return group[routeKey] || group.urls?.[nestedRouteKey] || group.studio_url || group.urls?.studio || '/studio' } function personalStudioUrlForPath(pathname) { if (pathname === '/studio/artworks' || pathname.endsWith('/artworks')) return '/studio/artworks' if (pathname === '/studio/collections' || pathname.endsWith('/collections')) return '/studio/collections' if (pathname === '/studio/settings' || pathname.endsWith('/settings')) return '/studio/settings' return '/studio' } function persistStudioContext(slug) { if (typeof window === 'undefined') return try { window.sessionStorage.setItem(STUDIO_CONTEXT_STORAGE_KEY, slug || '') } catch { // Ignore storage failures so Studio navigation keeps working. } } function readPersistedStudioContext() { if (typeof window === 'undefined') return null try { return window.sessionStorage.getItem(STUDIO_CONTEXT_STORAGE_KEY) } catch { return null } } function navigateToStudioUrl(targetUrl) { if (typeof window === 'undefined' || !targetUrl) return if (typeof window.location?.assign === 'function') { window.location.assign(targetUrl) return } window.location.href = targetUrl } function NavLink({ item, active }) { return ( {item.label} ) } export default function StudioLayout({ children, title, subtitle, actions }) { const { url, props } = usePage() const [mobileOpen, setMobileOpen] = useState(false) const [createOpen, setCreateOpen] = useState(false) const pathname = url.split('?')[0] const studioGroups = Array.isArray(props.studio_groups) ? props.studio_groups : [] const currentGroup = props.studioGroup || null const canManageNews = Boolean(props.auth?.user?.is_admin || props.auth?.user?.is_moderator) const navGroups = baseNavGroups.map((group) => { if (!canManageNews || group.label !== 'Content') { return group } return { ...group, items: [ ...group.items, { label: 'News', href: '/studio/news', icon: 'fa-solid fa-newspaper' }, ], } }) const quickCreateItems = (canManageNews ? [...baseQuickCreateItems, { label: 'News Article', href: '/studio/news/create', icon: 'fa-solid fa-newspaper' }] : baseQuickCreateItems ).map((item) => { if (currentGroup?.urls && item.label === 'Artwork') { return { ...item, href: currentGroup.urls?.studio_artworks ? `/upload?group=${currentGroup.slug}` : item.href } } if (currentGroup?.urls && item.label === 'Collection') { return { ...item, href: `/settings/collections/create?group=${currentGroup.slug}` } } return item }) useEffect(() => { const moduleKey = studioModule(pathname) const surface = studioSurface(pathname) trackStudioEvent('studio_opened', { surface, module: moduleKey, }) trackStudioEvent('studio_module_opened', { surface, module: moduleKey, }) }, [pathname]) useEffect(() => { if (!currentGroup?.slug) return persistStudioContext(currentGroup.slug) }, [currentGroup?.slug]) useEffect(() => { if (currentGroup || !supportsStudioContextRestore(pathname)) return const storedSlug = readPersistedStudioContext() if (!storedSlug) return const nextGroup = studioGroups.find((group) => group.slug === storedSlug) if (!nextGroup) { persistStudioContext('') return } const targetUrl = groupStudioUrlForPath(nextGroup, pathname) if (targetUrl && targetUrl !== pathname) { navigateToStudioUrl(targetUrl) } }, [currentGroup, pathname, studioGroups]) const isActive = (href) => { if (href === '/studio') return pathname === '/studio' return pathname.startsWith(href) } const handleQuickCreateClick = (item) => { trackStudioEvent('studio_quick_create_used', { surface: studioSurface(pathname), module: item.label.toLowerCase(), meta: { href: item.href, label: item.label, }, }) } const handleContextChange = (nextSlug) => { persistStudioContext(nextSlug) const nextGroup = studioGroups.find((group) => group.slug === nextSlug) const targetUrl = nextGroup ? groupStudioUrlForPath(nextGroup, pathname) : personalStudioUrlForPath(pathname) if (targetUrl !== pathname) { navigateToStudioUrl(targetUrl) } } return (

Creator Studio

{title || 'Creator Studio'}

{mobileOpen && (
setMobileOpen(false)}>
)}

Creator Studio

{title &&

{title}

} {subtitle &&

{subtitle}

} {currentGroup ?

Group context: {currentGroup.name}

: null}
{studioGroups.length > 0 ? : null} {actions}
{createOpen && ( )}
{children}
) } function ContextSwitcher({ currentGroup, studioGroups, onContextChange }) { return ( ) } function StudioSidebarContent({ currentGroup, studioGroups, navGroups, quickCreateItems, isActive, onNavigate, onQuickCreate, onContextChange }) { return ( <>

Skinbase Nova

Creator Studio

Create, manage, and grow from one modular workspace built for every creator surface.

{studioGroups.length > 0 ? (

Context

) : null}

Quick create

) }