({ onCreated }: Props)
| 23 | } |
| 24 | |
| 25 | export function TextToImageForm({ onCreated }: Props) { |
| 26 | const [models, setModels] = useState<GenerationModel[]>([]); |
| 27 | const [modelsError, setModelsError] = useState<string | null>(null); |
| 28 | |
| 29 | const [model, setModel] = useState(""); |
| 30 | const [prompt, setPrompt] = useState(""); |
| 31 | const [resolution, setResolution] = useState(""); |
| 32 | const [aspectRatio, setAspectRatio] = useState(""); |
| 33 | const [referenceImages, setReferenceImages] = useState<File[]>([]); |
| 34 | |
| 35 | const [submitting, setSubmitting] = useState(false); |
| 36 | const [error, setError] = useState<string | null>(null); |
| 37 | |
| 38 | const costs = useActionCosts(); |
| 39 | const fileInputRef = useRef<HTMLInputElement>(null); |
| 40 | |
| 41 | useEffect(() => { |
| 42 | fetchImageModels() |
| 43 | .then((m) => { |
| 44 | setModels(m); |
| 45 | if (m[0]) setModel(m[0].id); |
| 46 | }) |
| 47 | .catch((err) => setModelsError(err.message)); |
| 48 | }, []); |
| 49 | |
| 50 | const selectedModel = useMemo(() => models.find((m) => m.id === model), [models, model]); |
| 51 | const resolutions = selectedModel?.supported_resolutions?.length |
| 52 | ? selectedModel.supported_resolutions |
| 53 | : FALLBACK_RESOLUTIONS; |
| 54 | const aspectRatios = selectedModel?.supported_aspect_ratios?.length |
| 55 | ? selectedModel.supported_aspect_ratios |
| 56 | : FALLBACK_ASPECT_RATIOS; |
| 57 | |
| 58 | async function handleSubmit(e: React.FormEvent) { |
| 59 | e.preventDefault(); |
| 60 | setError(null); |
| 61 | if (!model || !prompt.trim()) { |
| 62 | setError("Model and prompt are required."); |
| 63 | return; |
| 64 | } |
| 65 | setSubmitting(true); |
| 66 | try { |
| 67 | const form = new FormData(); |
| 68 | form.set("model", model); |
| 69 | form.set("prompt", prompt); |
| 70 | if (resolution) form.set("resolution", resolution); |
| 71 | if (aspectRatio) form.set("aspectRatio", aspectRatio); |
| 72 | referenceImages.forEach((f) => form.append("referenceImages", f)); |
| 73 | |
| 74 | const image = await createImage(form); |
| 75 | refreshCredits(); |
| 76 | onCreated(image); |
| 77 | setPrompt(""); |
| 78 | } catch (err) { |
| 79 | setError(err instanceof Error ? err.message : "Failed to generate image"); |
| 80 | } finally { |
| 81 | setSubmitting(false); |
| 82 | } |
nothing calls this directly
no test coverage detected