"use client" import { useEffect, useState } from "react" import { motion } from "motion/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" import type { EnvironmentData } from "./environment-step" import { UPSCALER_TYPE_OPTIONS, FRAME_GEN_OPTIONS } from "./environment-step" export interface ReviewData { hardwareSlug: string hardwareName: string gameVersionLabel: string antiCheat: { antiCheatRelevant: boolean antiCheatName: string antiCheatStatus: "none" | "supported" | "unsupported" | "unknown" } performance: PerformanceData settings: SettingCategory[] environment: EnvironmentData } interface ReviewStepProps { data: ReviewData userNotes: string onUserNotesChange: (notes: string) => void 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 }) { return (
{label}
) } function SummaryRow({ label, value }: { label: string; value: React.ReactNode }) { return (
{label} {value}
) } function formatNumber(val: number | undefined): string { if (val === undefined || val === null) return "Not set" return String(val) } export function ReviewStep({ data, userNotes, onUserNotesChange, 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) const base = opt?.label ?? data.environment.upscalerType return data.environment.upscalerVersion ? `${base} ${data.environment.upscalerVersion}` : base })() const frameGenLabel = (() => { if (!environment.frameGenMethod || environment.frameGenMethod === "none") return "None" const opt = FRAME_GEN_OPTIONS.find(o => o.value === environment.frameGenMethod) return opt?.label ?? environment.frameGenMethod })() return (

Review & Submit

Review your submission details below. Add any additional notes and click Submit when ready.

{/* Summary Cards */}
{/* Setup: Hardware + Version + Anti-Cheat */}
{antiCheat.antiCheatRelevant && ( <> )} {!antiCheat.antiCheatRelevant && ( )}
{/* Performance */}
{/* Environment */}
{environment.launchOptions && ( {environment.launchOptions} } /> )}
{/* Settings */}
{settings.length === 0 ? (

No settings configured

) : (
{settings.map((cat) => (

{cat.category}

{cat.settings.map((s) => ( {s.title}: {String(s.value)} ))}
))}
)}
{/* 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 */}
onUserNotesChange(JSON.stringify(json))} placeholder="Add any extra details about your experience..." />
{/* Error */} {error && (

{error}

)} {/* Submit Button */}
) }