From 7560cca4e64c7ccd46597d6147dae4ca26eefdaa Mon Sep 17 00:00:00 2001 From: Adrian Bonpin Date: Sun, 10 May 2026 04:57:02 +0800 Subject: [PATCH] feat: add screenshot upload UI to ReviewStep (Task 2.1) --- components/wizard/steps/review-step.tsx | 103 +++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/components/wizard/steps/review-step.tsx b/components/wizard/steps/review-step.tsx index 6af11c9..2ae03ab 100644 --- a/components/wizard/steps/review-step.tsx +++ b/components/wizard/steps/review-step.tsx @@ -1,7 +1,8 @@ "use client" +import { useEffect, useState } from "react" import { motion } from "motion/react" -import { Send, Loader2, AlertCircle, Monitor, Gauge, SlidersHorizontal, Terminal, FileText } from "lucide-react" +import { Send, Loader2, AlertCircle, Monitor, Gauge, SlidersHorizontal, Terminal, FileText, ImagePlus, X } from "lucide-react" import { TiptapEditor } from "@/components/tiptap-editor" import type { SettingCategory } from "@/components/wizard/settings-editor" import type { PerformanceData } from "./performance-step" @@ -29,6 +30,10 @@ interface ReviewStepProps { onSubmit: () => void isSubmitting: boolean error: string | null + screenshotFiles?: File[] + onScreenshotFilesChange?: (files: File[]) => void + screenshotUploading?: boolean + screenshotError?: string | null } function SectionHeader({ icon: Icon, label }: { icon: React.ElementType; label: string }) { @@ -61,9 +66,27 @@ export function ReviewStep({ onSubmit, isSubmitting, error, + screenshotFiles, + onScreenshotFilesChange, + screenshotUploading, + screenshotError, }: ReviewStepProps) { const { hardwareName, gameVersionLabel, antiCheat, performance, environment, settings } = data + const [previews, setPreviews] = useState<{ file: File; url: string }[]>([]) + + useEffect(() => { + if (!screenshotFiles?.length) { + setPreviews([]) + return + } + const next = screenshotFiles.map((file) => ({ file, url: URL.createObjectURL(file) })) + setPreviews(next) + return () => { + next.forEach((p) => URL.revokeObjectURL(p.url)) + } + }, [screenshotFiles]) + const upscalerLabel = (() => { if (!data.environment.upscalerType || data.environment.upscalerType === "none") return "None" const opt = UPSCALER_TYPE_OPTIONS.find(o => o.value === data.environment.upscalerType) @@ -172,6 +195,84 @@ export function ReviewStep({ + {/* Screenshots */} +
+ + {data.settings.length === 0 ? ( +
+

Add game settings to enable screenshot upload

+
+ ) : ( +
+ {screenshotUploading && ( +
+ + Uploading... +
+ )} + + {previews.length > 0 && ( +
+ {previews.map((preview) => ( +
+ {preview.file.name} + +
+ ))} +
+ )} + + {(!screenshotFiles || screenshotFiles.length < 2) && !screenshotUploading && ( + + )} + + {screenshotFiles && screenshotFiles.length >= 2 && ( +

Maximum 2 screenshots reached

+ )} + + {screenshotError && ( +

{screenshotError}

+ )} +
+ )} +
+ {/* User Notes */}