Refactor dashboard and upload flows

Remove dead admin UI code, redesign dashboard followers/following and upload experiences, and add schema audit tooling with repair migrations for forum and upload drift.
This commit is contained in:
2026-03-21 11:02:22 +01:00
parent 29c3ff8572
commit 979e011257
55 changed files with 2576 additions and 1923 deletions

View File

@@ -201,14 +201,12 @@ export default function UploadWizard({
const metadataErrors = useMemo(() => {
const errors = {}
if (!String(metadata.title || '').trim()) errors.title = 'Title is required.'
if (!String(metadata.description || '').trim()) errors.description = 'Description is required.'
if (!metadata.contentType) errors.contentType = 'Content type is required.'
if (!metadata.rootCategoryId) errors.category = 'Root category is required.'
if (metadata.rootCategoryId && requiresSubCategory && !metadata.subCategoryId) {
errors.category = 'Subcategory is required for the selected category.'
}
if (!metadata.rightsAccepted) errors.rights = 'Rights confirmation is required.'
if (!Array.isArray(metadata.tags) || metadata.tags.length === 0) errors.tags = 'At least one tag is required.'
return errors
}, [metadata, requiresSubCategory])
@@ -465,7 +463,7 @@ export default function UploadWizard({
return (
<section
ref={stepContentRef}
className="space-y-4 pb-32 text-white lg:pb-6"
className="space-y-5 pb-32 text-white lg:pb-8"
data-is-archive={isArchive ? 'true' : 'false'}
>
{notices.length > 0 && (
@@ -492,7 +490,7 @@ export default function UploadWizard({
{/* Restored draft banner */}
{showRestoredBanner && (
<div className="rounded-xl ring-1 ring-sky-300/25 bg-sky-500/10 px-4 py-2.5 text-sm text-sky-100">
<div className="rounded-2xl border border-sky-300/20 bg-sky-500/10 px-4 py-3 text-sm text-sky-100 shadow-[0_14px_44px_rgba(14,165,233,0.10)]">
<div className="flex items-center justify-between gap-3">
<span>Draft restored. Continue from your previous upload session.</span>
<button
@@ -518,11 +516,11 @@ export default function UploadWizard({
/>
{/* ── Main body: two-column on desktop ─────────────────────────────── */}
<div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:gap-6">
<div className="flex flex-col gap-5 lg:flex-row lg:items-start lg:gap-8">
{/* Left / main column: step content */}
<div className="min-w-0 flex-1">
{/* Step content + floating progress overlay */}
<div className={`relative transition-[padding-bottom] duration-300 ${showOverlay ? 'pb-36' : ''}`}>
{/* Step content + centered progress overlay */}
<div className="relative">
<AnimatePresence mode="wait" initial={false}>
<motion.div
key={`step-${activeStep}`}
@@ -547,7 +545,7 @@ export default function UploadWizard({
{/* Wizard action bar (nav: back/next/start/retry) */}
{machine.state !== machineStates.complete && (
<div className="mt-4">
<div className="mt-5">
<UploadActions
step={activeStep}
canStart={canStartUpload && [machineStates.idle, machineStates.error, machineStates.cancelled].includes(machine.state)}
@@ -585,7 +583,7 @@ export default function UploadWizard({
{/* Right column: PublishPanel (sticky sidebar on lg+) */}
{(primaryFile || resolvedArtworkId) && machine.state !== machineStates.complete && (
<div className="hidden lg:block lg:w-72 xl:w-80 shrink-0 lg:sticky lg:top-20 lg:self-start">
<div className="hidden shrink-0 lg:block lg:w-80 xl:w-[22rem] lg:sticky lg:top-20 lg:self-start">
<PublishPanel
primaryPreviewUrl={primaryPreviewUrl}
isArchive={isArchive}
@@ -600,6 +598,7 @@ export default function UploadWizard({
scheduledAt={scheduledAt}
timezone={userTimezone}
visibility={visibility}
showRightsConfirmation={activeStep === 3}
onPublishModeChange={setPublishMode}
onScheduleAt={setScheduledAt}
onVisibilityChange={setVisibility}
@@ -617,8 +616,9 @@ export default function UploadWizard({
<div className="fixed bottom-4 right-4 z-30 lg:hidden">
<button
type="button"
aria-label="Open publish panel"
onClick={() => setShowMobilePublishPanel((v) => !v)}
className="flex items-center gap-2 rounded-full bg-sky-500 px-4 py-2.5 text-sm font-semibold text-white shadow-lg shadow-sky-900/40 transition hover:bg-sky-400 active:scale-95"
className="flex items-center gap-2 rounded-full border border-sky-300/20 bg-sky-500 px-4 py-2.5 text-sm font-semibold text-white shadow-[0_18px_50px_rgba(14,165,233,0.35)] transition hover:bg-sky-400 active:scale-95"
>
<svg className="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true">
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
@@ -671,6 +671,7 @@ export default function UploadWizard({
scheduledAt={scheduledAt}
timezone={userTimezone}
visibility={visibility}
showRightsConfirmation={activeStep === 3}
onPublishModeChange={setPublishMode}
onScheduleAt={setScheduledAt}
onVisibilityChange={setVisibility}