user()?->hasStaffAccess(); } protected function prepareForValidation(): void { $this->merge([ 'featured' => $this->boolean('featured'), 'prompt_of_week' => $this->boolean('prompt_of_week'), 'active' => $this->boolean('active', true), 'new_category_name' => trim((string) $this->input('new_category_name', '')), 'tags' => array_values(array_filter((array) $this->input('tags', []))), 'tool_notes' => collect($this->input('tool_notes', [])) ->filter(static fn ($note): bool => is_array($note) || is_string($note)) ->map(function ($note): array|string { if (is_string($note)) { return $note; } return [ 'provider' => $note['provider'] ?? null, 'model_name' => $note['model_name'] ?? null, 'notes' => $note['notes'] ?? null, 'strengths' => $note['strengths'] ?? null, 'weaknesses' => $note['weaknesses'] ?? null, 'best_for' => $note['best_for'] ?? null, 'image_path' => $note['image_path'] ?? null, 'thumb_path' => $note['thumb_path'] ?? null, 'settings' => $note['settings'] ?? null, 'score' => filled($note['score'] ?? null) ? (int) $note['score'] : null, 'active' => filter_var($note['active'] ?? true, FILTER_VALIDATE_BOOL, FILTER_NULL_ON_FAILURE) ?? true, ]; }) ->values() ->all(), ]); } public function rules(): array { $promptId = $this->route('academyPromptTemplate')?->id; return [ 'category_id' => ['nullable', 'integer', 'exists:academy_categories,id'], 'new_category_name' => ['nullable', 'string', 'max:120'], 'title' => ['required', 'string', 'max:180'], 'slug' => ['required', 'string', 'max:180', Rule::unique('academy_prompt_templates', 'slug')->ignore($promptId)], 'excerpt' => ['nullable', 'string'], 'prompt' => ['required', 'string'], 'negative_prompt' => ['nullable', 'string'], 'usage_notes' => ['nullable', 'string'], 'workflow_notes' => ['nullable', 'string'], 'difficulty' => ['required', 'string', Rule::in((array) config('academy.difficulty_levels', []))], 'access_level' => ['required', 'string', Rule::in(['free', 'creator', 'pro'])], 'aspect_ratio' => ['nullable', 'string', 'max:20'], 'tags' => ['nullable', 'array'], 'tags.*' => ['string', 'max:60'], 'tool_notes' => ['nullable', 'array'], 'tool_notes.*.provider' => ['nullable', 'string', 'max:100'], 'tool_notes.*.model_name' => ['nullable', 'string', 'max:150'], 'tool_notes.*.notes' => ['nullable', 'string'], 'tool_notes.*.strengths' => ['nullable', 'string'], 'tool_notes.*.weaknesses' => ['nullable', 'string'], 'tool_notes.*.best_for' => ['nullable', 'string'], 'tool_notes.*.image_path' => ['nullable', 'string', 'max:500'], 'tool_notes.*.thumb_path' => ['nullable', 'string', 'max:500'], 'tool_notes.*.settings' => ['nullable', 'string'], 'tool_notes.*.score' => ['nullable', 'integer', 'min:1', 'max:10'], 'tool_notes.*.active' => ['nullable', 'boolean'], 'preview_image' => ['nullable', 'string', 'max:2048'], 'preview_image_file' => ['nullable', 'file', 'image', 'mimes:jpg,jpeg,png,webp', 'max:5120'], 'featured' => ['required', 'boolean'], 'prompt_of_week' => ['required', 'boolean'], 'active' => ['required', 'boolean'], 'published_at' => ['nullable', 'date'], 'seo_title' => ['nullable', 'string', 'max:180'], 'seo_description' => ['nullable', 'string', 'max:255'], ]; } }