optimizations
This commit is contained in:
@@ -28,67 +28,50 @@ export default function Step1FileUpload({
|
||||
// Machine state (passed for potential future use)
|
||||
machine,
|
||||
}) {
|
||||
const fileSelected = Boolean(primaryFile)
|
||||
|
||||
return (
|
||||
<div className="space-y-5 rounded-[28px] border border-white/10 bg-[linear-gradient(180deg,rgba(255,255,255,0.05),rgba(255,255,255,0.02))] p-6 shadow-[0_24px_90px_rgba(2,8,23,0.28)] backdrop-blur sm:p-7">
|
||||
{/* Step header */}
|
||||
<div className="rounded-2xl border border-white/8 bg-white/[0.04] px-5 py-4">
|
||||
<div className="space-y-6 rounded-[28px] border border-white/10 bg-[linear-gradient(180deg,rgba(255,255,255,0.05),rgba(255,255,255,0.02))] p-6 shadow-[0_24px_90px_rgba(2,8,23,0.28)] backdrop-blur sm:p-8">
|
||||
|
||||
{/* ── Hero heading ─────────────────────────────────────────────────── */}
|
||||
<div className="text-center">
|
||||
<span className="inline-flex items-center gap-1.5 rounded-full border border-sky-400/30 bg-sky-400/10 px-3 py-1 text-[11px] uppercase tracking-widest text-sky-300">
|
||||
Step 1 of 3
|
||||
</span>
|
||||
<h2
|
||||
ref={headingRef}
|
||||
tabIndex={-1}
|
||||
className="text-lg font-semibold text-white focus:outline-none"
|
||||
className="mt-4 text-2xl font-bold text-white focus:outline-none"
|
||||
>
|
||||
Upload your artwork
|
||||
</h2>
|
||||
<p className="mt-1 text-sm text-white/60">
|
||||
Drop or browse a file. Validation runs immediately. Upload starts when you click
|
||||
<span className="text-white/80">Start upload</span>.
|
||||
<p className="mx-auto mt-2 max-w-md text-sm text-white/55">
|
||||
Drop an image or an archive pack. We validate the file instantly so you can start uploading straight away.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-3 sm:grid-cols-3">
|
||||
{[
|
||||
{
|
||||
title: '1. Add the file',
|
||||
body: 'Drop an image or archive pack into the upload area.',
|
||||
},
|
||||
{
|
||||
title: '2. Check validation',
|
||||
body: 'We flag unsupported formats, missing screenshots, and basic file issues immediately.',
|
||||
},
|
||||
{
|
||||
title: '3. Start upload',
|
||||
body: 'Once the file is clean, the secure processing pipeline takes over.',
|
||||
},
|
||||
].map((item) => (
|
||||
<div key={item.title} className="rounded-2xl border border-white/8 bg-white/[0.03] p-4">
|
||||
<p className="text-sm font-semibold text-white">{item.title}</p>
|
||||
<p className="mt-2 text-sm leading-6 text-slate-300">{item.body}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Locked notice */}
|
||||
{/* ── Locked notice ────────────────────────────────────────────────── */}
|
||||
{fileSelectionLocked && (
|
||||
<div className="flex items-center gap-2 rounded-2xl bg-amber-500/10 px-4 py-3 text-xs text-amber-100 ring-1 ring-amber-300/30">
|
||||
<svg className="h-3.5 w-3.5 shrink-0" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<div className="flex items-center gap-2.5 rounded-2xl bg-amber-500/10 px-4 py-3 text-sm text-amber-100 ring-1 ring-amber-300/30">
|
||||
<svg className="h-4 w-4 shrink-0" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fillRule="evenodd" d="M10 1a4.5 4.5 0 00-4.5 4.5V9H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-.5V5.5A4.5 4.5 0 0010 1zm3 8V5.5a3 3 0 10-6 0V9h6z" clipRule="evenodd" />
|
||||
</svg>
|
||||
File is locked after upload. Reset to change.
|
||||
File is locked after upload starts. Reset to change the file.
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Primary dropzone */}
|
||||
{/* ── Primary dropzone ─────────────────────────────────────────────── */}
|
||||
<UploadDropzone
|
||||
title="Upload your artwork file"
|
||||
description="Drag & drop or click to browse. Accepted: JPG, PNG, WEBP, ZIP, RAR, 7Z."
|
||||
title="Drop your file here"
|
||||
description="JPG, PNG, WEBP · ZIP, RAR, 7Z · Images up to 50 MB · Archives up to 200 MB"
|
||||
fileName={primaryFile?.name || ''}
|
||||
previewUrl={primaryPreviewUrl}
|
||||
fileMeta={fileMetadata}
|
||||
fileHint="No file selected"
|
||||
invalid={primaryErrors.length > 0}
|
||||
errors={primaryErrors}
|
||||
showLooksGood={Boolean(primaryFile) && primaryErrors.length === 0}
|
||||
looksGoodText="Looks good"
|
||||
showLooksGood={fileSelected && primaryErrors.length === 0}
|
||||
looksGoodText="File looks good — ready to upload"
|
||||
locked={fileSelectionLocked}
|
||||
onPrimaryFileChange={(file) => {
|
||||
if (fileSelectionLocked) return
|
||||
@@ -96,10 +79,10 @@ export default function Step1FileUpload({
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Screenshots (archives only) */}
|
||||
{/* ── Screenshots (archives only) ──────────────────────────────────── */}
|
||||
<ScreenshotUploader
|
||||
title="Archive screenshots"
|
||||
description="We need at least 1 screenshot to generate thumbnails and analyze content."
|
||||
description="Add at least 1 screenshot so we can generate a thumbnail and analyze your content."
|
||||
visible={isArchive}
|
||||
files={screenshots}
|
||||
min={1}
|
||||
@@ -108,9 +91,54 @@ export default function Step1FileUpload({
|
||||
errors={screenshotErrors}
|
||||
invalid={isArchive && screenshotErrors.length > 0}
|
||||
showLooksGood={isArchive && screenshots.length > 0 && screenshotErrors.length === 0}
|
||||
looksGoodText="Looks good"
|
||||
looksGoodText="Screenshots look good"
|
||||
onFilesChange={onScreenshotsChange}
|
||||
/>
|
||||
|
||||
{/* ── Subtle what-happens-next hints (shown only before a file is picked) */}
|
||||
{!fileSelected && (
|
||||
<div className="grid gap-3 sm:grid-cols-3">
|
||||
{[
|
||||
{
|
||||
icon: (
|
||||
<svg className="h-5 w-5 text-sky-300" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
||||
<path d="M21 15v4a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-4" /><path d="M7 10l5-5 5 5" /><path d="M12 5v10" />
|
||||
</svg>
|
||||
),
|
||||
label: 'Add your file',
|
||||
hint: 'Image or archive — drop it in or click to browse.',
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
<svg className="h-5 w-5 text-violet-300" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
||||
<path d="M9 12l2 2 4-4" /><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10z" />
|
||||
</svg>
|
||||
),
|
||||
label: 'Instant validation',
|
||||
hint: 'Format, size, and screenshot checks run immediately.',
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
<svg className="h-5 w-5 text-emerald-300" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
||||
<path d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
),
|
||||
label: 'Start upload',
|
||||
hint: 'One click sends your file through the secure pipeline.',
|
||||
},
|
||||
].map((item) => (
|
||||
<div key={item.label} className="flex items-start gap-3 rounded-2xl border border-white/8 bg-white/[0.03] px-4 py-4">
|
||||
<div className="mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-xl border border-white/10 bg-white/[0.05]">
|
||||
{item.icon}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-white">{item.label}</p>
|
||||
<p className="mt-1 text-xs leading-5 text-slate-400">{item.hint}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user