feat: Inertia profile settings page, Studio edit redesign, EGS, Nova UI components\n\n- Redesign /dashboard/profile as Inertia React page (Settings/ProfileEdit)\n with SettingsLayout sidebar, Nova UI components (TextInput, Textarea,\n Toggle, Select, RadioGroup, Modal, Button), avatar drag-and-drop,\n password change, and account deletion sections\n- Redesign Studio artwork edit page with two-column layout, Nova components,\n integrated TagPicker, and version history modal\n- Add shared MarkdownEditor component\n- Add Early-Stage Growth System (EGS): SpotlightEngine, FeedBlender,\n GridFiller, AdaptiveTimeWindow, ActivityLayer, admin panel\n- Fix upload category/tag persistence (V1+V2 paths)\n- Fix tag source enum, category tree display, binding resolution\n- Add settings.jsx Vite entry, settings.blade.php wrapper\n- Update ProfileController with JSON response support for API calls\n- Various route fixes (profile.edit, toolbar settings link)"

This commit is contained in:
2026-03-03 20:57:43 +01:00
parent dc51d65440
commit b9c2d8597d
114 changed files with 8760 additions and 693 deletions

View File

@@ -0,0 +1,102 @@
import React, { useState } from 'react'
import { Link, usePage } from '@inertiajs/react'
const navItems = [
{ label: 'Profile', href: '/dashboard/profile', icon: 'fa-solid fa-user' },
// Future: { label: 'Notifications', href: '/dashboard/notifications', icon: 'fa-solid fa-bell' },
// Future: { label: 'Privacy', href: '/dashboard/privacy', icon: 'fa-solid fa-shield-halved' },
]
function NavLink({ item, active, onClick }) {
return (
<Link
href={item.href}
onClick={onClick}
className={`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'
}`}
>
<i className={`${item.icon} w-5 text-center text-base`} />
<span>{item.label}</span>
</Link>
)
}
function SidebarContent({ isActive, onNavigate }) {
return (
<>
<div className="mb-6">
<h2 className="text-xs font-semibold uppercase tracking-wider text-slate-500 px-4 mb-2">Settings</h2>
</div>
<nav className="space-y-1 flex-1">
{navItems.map((item) => (
<NavLink key={item.href} item={item} active={isActive(item.href)} onClick={onNavigate} />
))}
</nav>
<div className="mt-auto pt-6 space-y-2">
<Link
href="/studio"
className="flex items-center gap-2 px-4 py-2 rounded-xl text-sm text-slate-400 hover:text-white hover:bg-white/5 transition-colors"
onClick={onNavigate}
>
<i className="fa-solid fa-palette w-5 text-center" />
Creator Studio
</Link>
</div>
</>
)
}
export default function SettingsLayout({ children, title }) {
const { url } = usePage()
const [mobileOpen, setMobileOpen] = useState(false)
const isActive = (href) => url.startsWith(href)
return (
<div className="min-h-screen bg-nova-900">
{/* Mobile top bar */}
<div className="lg:hidden flex items-center justify-between px-4 py-3 border-b border-white/10 bg-nova-900/80 backdrop-blur-xl sticky top-16 z-30">
<h1 className="text-lg font-bold text-white">Settings</h1>
<button
onClick={() => setMobileOpen(!mobileOpen)}
className="text-slate-400 hover:text-white p-2"
aria-label="Toggle navigation"
>
<i className={`fa-solid ${mobileOpen ? 'fa-xmark' : 'fa-bars'} text-xl`} />
</button>
</div>
{/* Mobile nav overlay */}
{mobileOpen && (
<div className="lg:hidden fixed inset-0 z-40 bg-black/60 backdrop-blur-sm" onClick={() => setMobileOpen(false)}>
<nav
className="absolute left-0 top-0 bottom-0 w-72 bg-nova-900 border-r border-white/10 p-4 pt-20 space-y-1"
onClick={(e) => e.stopPropagation()}
>
<SidebarContent isActive={isActive} onNavigate={() => setMobileOpen(false)} />
</nav>
</div>
)}
<div className="flex">
{/* 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">
<SidebarContent isActive={isActive} />
</aside>
{/* Main content */}
<main className="flex-1 min-w-0 px-4 lg:px-8 pt-4 pb-8 max-w-4xl">
{title && (
<h1 className="text-2xl font-bold text-white mb-6">{title}</h1>
)}
{children}
</main>
</div>
</div>
)
}