Generation::query()->latest()->paginate(20), 'models' => RunwareModel::query()->where('active', true)->orderBy('modality')->orderBy('price_usd')->get()->groupBy('modality'), 'capEur' => $budget->capEur(), 'spentEur' => $budget->spentEurThisMonth(), 'remainingEur' => $budget->remainingEur(), 'warnThresholdReached' => $budget->warnThresholdReached(), ]); } public function store(Request $request, GenerationService $generations): RedirectResponse { $data = $request->validate([ 'type' => ['required', 'in:image,video,text'], 'prompt' => ['required', 'string', 'max:4000'], 'model' => ['nullable', 'string'], 'width' => ['nullable', 'integer', 'min:64', 'max:2048'], 'height' => ['nullable', 'integer', 'min:64', 'max:2048'], 'duration' => ['nullable', 'integer', 'min:1', 'max:30'], ]); $params = array_filter([ 'width' => $data['width'] ?? null, 'height' => $data['height'] ?? null, 'duration' => $data['duration'] ?? null, ], fn ($v) => $v !== null); try { match ($data['type']) { 'image' => $generations->createImage($data['prompt'], $params, $data['model'] ?? null), 'text' => $generations->createText($data['prompt'], $params, $data['model'] ?? null), 'video' => $generations->queueVideo($data['prompt'], $params, $data['model'] ?? null), }; } catch (BudgetExceededException $e) { return back()->withErrors(['budget' => $e->getMessage()])->withInput(); } catch (\Throwable $e) { return back()->withErrors(['generation' => 'Generation failed: '.$e->getMessage()])->withInput(); } return redirect()->route('generations.index'); } }