Implement creator studio and upload updates
This commit is contained in:
@@ -51,7 +51,7 @@ function SidebarContent({ isActive, onNavigate }) {
|
||||
)
|
||||
}
|
||||
|
||||
function SectionSidebar({ sections = [], activeSection, onSectionChange }) {
|
||||
function SectionSidebar({ sections = [], activeSection, onSectionChange, dirtyMap = {} }) {
|
||||
return (
|
||||
<>
|
||||
<div className="mb-6">
|
||||
@@ -61,19 +61,30 @@ function SectionSidebar({ sections = [], activeSection, onSectionChange }) {
|
||||
<nav className="space-y-1 flex-1">
|
||||
{sections.map((section) => {
|
||||
const active = section.key === activeSection
|
||||
const isDirty = !!dirtyMap[section.key]
|
||||
return (
|
||||
<button
|
||||
key={section.key}
|
||||
type="button"
|
||||
onClick={() => onSectionChange?.(section.key)}
|
||||
className={`w-full flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 ${
|
||||
className={`group relative w-full flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 ${
|
||||
active
|
||||
? 'bg-accent/20 text-accent shadow-sm shadow-accent/10'
|
||||
: 'text-slate-400 hover:text-white hover:bg-white/5'
|
||||
}`}
|
||||
>
|
||||
{section.icon ? <i className={`${section.icon} w-5 text-center text-base`} /> : null}
|
||||
<span>{section.label}</span>
|
||||
<span className="flex flex-col items-start gap-0.5">
|
||||
<span className="flex items-center gap-2">
|
||||
{section.label}
|
||||
{isDirty && (
|
||||
<span className="inline-block h-1.5 w-1.5 rounded-full bg-amber-400 animate-pulse" title="Unsaved changes" />
|
||||
)}
|
||||
</span>
|
||||
{section.description && !active ? (
|
||||
<span className="text-[11px] font-normal text-slate-500 leading-tight">{section.description}</span>
|
||||
) : null}
|
||||
</span>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
@@ -82,7 +93,7 @@ function SectionSidebar({ sections = [], activeSection, onSectionChange }) {
|
||||
)
|
||||
}
|
||||
|
||||
export default function SettingsLayout({ children, title, sections = null, activeSection = null, onSectionChange = null }) {
|
||||
export default function SettingsLayout({ children, title, sections = null, activeSection = null, onSectionChange = null, dirtyMap = {} }) {
|
||||
const { url } = usePage()
|
||||
const [mobileOpen, setMobileOpen] = useState(false)
|
||||
const hasSectionMode = Array.isArray(sections) && sections.length > 0 && typeof onSectionChange === 'function'
|
||||
@@ -98,20 +109,27 @@ export default function SettingsLayout({ children, title, sections = null, activ
|
||||
{/* Mobile top bar */}
|
||||
<div className="lg:hidden px-4 py-3 border-b border-white/10 bg-nova-900/80 backdrop-blur-xl sticky top-16 z-30">
|
||||
{hasSectionMode ? (
|
||||
<label className="block">
|
||||
<span className="sr-only">Settings section</span>
|
||||
<select
|
||||
className="w-full rounded-xl border border-white/10 bg-white/5 px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
value={activeSection || ''}
|
||||
onChange={(e) => onSectionChange(e.target.value)}
|
||||
>
|
||||
{sections.map((section) => (
|
||||
<option key={section.key} value={section.key} className="bg-nova-900 text-white">
|
||||
{section.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="block flex-1">
|
||||
<span className="sr-only">Settings section</span>
|
||||
<select
|
||||
className="w-full rounded-xl border border-white/10 bg-white/5 px-3 py-2.5 text-sm text-white focus:outline-none focus:ring-2 focus:ring-accent/50 appearance-none"
|
||||
value={activeSection || ''}
|
||||
onChange={(e) => onSectionChange(e.target.value)}
|
||||
>
|
||||
{sections.map((section) => (
|
||||
<option key={section.key} value={section.key} className="bg-nova-900 text-white">
|
||||
{section.label}{dirtyMap[section.key] ? ' •' : ''}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
{dirtyMap[activeSection] ? (
|
||||
<span className="inline-flex items-center rounded-full bg-amber-400/15 px-2 py-1 text-[10px] font-semibold text-amber-300 border border-amber-400/20">
|
||||
Unsaved
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center justify-between">
|
||||
<h1 className="text-lg font-bold text-white">Settings</h1>
|
||||
@@ -142,7 +160,7 @@ export default function SettingsLayout({ children, title, sections = null, activ
|
||||
{/* Desktop sidebar */}
|
||||
<aside className="hidden lg:flex flex-col w-64 min-h-[calc(100vh-4rem)] border-r border-white/10 bg-nova-900/60 backdrop-blur-xl p-4 pt-6 sticky top-16 self-start">
|
||||
{hasSectionMode ? (
|
||||
<SectionSidebar sections={sections} activeSection={activeSection} onSectionChange={onSectionChange} />
|
||||
<SectionSidebar sections={sections} activeSection={activeSection} onSectionChange={onSectionChange} dirtyMap={dirtyMap} />
|
||||
) : (
|
||||
<SidebarContent isActive={isActive} />
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user