"use client" import { useMemo } from "react" import { Gauge, Timer } from "lucide-react" export interface PerformanceData { fpsAvg?: number fpsOnePercentLow?: number fpsLow?: number fpsHigh?: number loadTimeSsd?: number loadTimeSd?: number } interface PerformanceStepProps { value: PerformanceData onChange: (value: PerformanceData) => void } export function PerformanceStep({ value, onChange }: PerformanceStepProps) { const error = useMemo(() => { if (value.fpsAvg !== undefined && value.fpsAvg !== null && (isNaN(value.fpsAvg) || value.fpsAvg <= 0)) { return "FPS Average must be greater than 0" } return null }, [value.fpsAvg]) const update = (field: keyof PerformanceData, val: string) => { const isDecimalField = field === "loadTimeSsd" || field === "loadTimeSd" const cleaned = isDecimalField ? val.replace(/[^0-9.]/g, "").replace(/(\..*)\./g, "$1") : val.replace(/[^0-9]/g, "") const num = cleaned === "" || cleaned === "." ? undefined : Number(cleaned) onChange({ ...value, [field]: num }) } return (
{/* FPS Section */}

Frame Rate

update("fpsAvg", e.target.value)} placeholder="e.g. 45" className="w-full px-4 py-3 rounded-lg border border-border bg-text/5 text-text text-sm placeholder:text-text/40 outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors" />

Required — average framerate during gameplay

update("fpsOnePercentLow", e.target.value)} placeholder="e.g. 32" className="w-full px-4 py-3 rounded-lg border border-border bg-text/5 text-text text-sm placeholder:text-text/40 outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors" />

FPS at the 1st percentile — represents worst 1% of frametimes

update("fpsLow", e.target.value)} placeholder="e.g. 30" className="w-full px-4 py-3 rounded-lg border border-border bg-text/5 text-text text-sm placeholder:text-text/40 outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors" />
update("fpsHigh", e.target.value)} placeholder="e.g. 60" className="w-full px-4 py-3 rounded-lg border border-border bg-text/5 text-text text-sm placeholder:text-text/40 outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors" />
{error && (

{error}

)}
{/* Load Time Section */}

Load Times

update("loadTimeSsd", e.target.value)} placeholder="e.g. 12.5" className="w-full px-4 py-3 rounded-lg border border-border bg-text/5 text-text text-sm placeholder:text-text/40 outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors" />
update("loadTimeSd", e.target.value)} placeholder="e.g. 35.0" className="w-full px-4 py-3 rounded-lg border border-border bg-text/5 text-text text-sm placeholder:text-text/40 outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors" />
) }