151 lines
4.5 KiB
PHP
151 lines
4.5 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Http\Controllers;
|
||
|
|
|
||
|
|
use App\Actions\Prompts\ListPrompts;
|
||
|
|
use App\Exceptions\PromptRenderException;
|
||
|
|
use App\Http\Requests\StorePromptRequest;
|
||
|
|
use App\Http\Requests\UpdatePromptRequest;
|
||
|
|
use App\Models\Prompt;
|
||
|
|
use App\Services\PromptCatalog;
|
||
|
|
use App\Services\PromptRenderer;
|
||
|
|
use App\Services\PromptService;
|
||
|
|
use Illuminate\Http\JsonResponse;
|
||
|
|
use Illuminate\Http\RedirectResponse;
|
||
|
|
use Illuminate\Http\Request;
|
||
|
|
use Inertia\Inertia;
|
||
|
|
use Inertia\Response;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Thin controller: validate → DTO → service/catalog → respond.
|
||
|
|
*/
|
||
|
|
class PromptController extends Controller
|
||
|
|
{
|
||
|
|
public function __construct(
|
||
|
|
private readonly PromptService $service,
|
||
|
|
private readonly PromptCatalog $catalog,
|
||
|
|
private readonly PromptRenderer $renderer,
|
||
|
|
) {}
|
||
|
|
|
||
|
|
public function index(Request $request): Response
|
||
|
|
{
|
||
|
|
$query = new ListPrompts(
|
||
|
|
search: $request->query('search'),
|
||
|
|
tag: $request->query('tag'),
|
||
|
|
favoritesOnly: $request->query('favorites') === '1',
|
||
|
|
sort: (string) $request->query('sort', 'created_at'),
|
||
|
|
direction: (string) $request->query('direction', ''),
|
||
|
|
);
|
||
|
|
|
||
|
|
return Inertia::render('Prompts/Index', [
|
||
|
|
'prompts' => $this->catalog->list($query),
|
||
|
|
'tags' => $this->catalog->tags()->pluck('name')->values(),
|
||
|
|
'filters' => [
|
||
|
|
'search' => $query->search,
|
||
|
|
'tag' => $query->tag,
|
||
|
|
'favorites' => $query->favoritesOnly,
|
||
|
|
],
|
||
|
|
'sort' => $query->normalizedSort(),
|
||
|
|
'direction' => $query->normalizedDirection(),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function create(): Response
|
||
|
|
{
|
||
|
|
return Inertia::render('Prompts/Create', [
|
||
|
|
'initial' => [
|
||
|
|
'name' => old('name'),
|
||
|
|
'description' => old('description'),
|
||
|
|
'body' => old('body'),
|
||
|
|
'tags' => old('tags', []),
|
||
|
|
],
|
||
|
|
'suggestedTags' => $this->catalog->tags()->pluck('name')->values(),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function store(StorePromptRequest $request): RedirectResponse
|
||
|
|
{
|
||
|
|
$prompt = $this->service->store($request->toStorePrompt());
|
||
|
|
|
||
|
|
return redirect()->route('prompts.show', $prompt);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function show(Prompt $prompt): Response
|
||
|
|
{
|
||
|
|
$prompt->loadMissing('tags');
|
||
|
|
|
||
|
|
return Inertia::render('Prompts/Show', [
|
||
|
|
'prompt' => $prompt,
|
||
|
|
'variables' => $this->renderer->extractVariables($prompt->body),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function edit(Prompt $prompt): Response
|
||
|
|
{
|
||
|
|
$prompt->loadMissing('tags');
|
||
|
|
|
||
|
|
return Inertia::render('Prompts/Edit', [
|
||
|
|
'promptId' => $prompt->id,
|
||
|
|
'initial' => [
|
||
|
|
'name' => $prompt->name,
|
||
|
|
'description' => $prompt->description,
|
||
|
|
'body' => $prompt->body,
|
||
|
|
'tags' => $prompt->tags->pluck('name')->values()->all(),
|
||
|
|
],
|
||
|
|
'suggestedTags' => $this->catalog->tags()->pluck('name')->values(),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function update(UpdatePromptRequest $request, Prompt $prompt): RedirectResponse
|
||
|
|
{
|
||
|
|
$this->service->update($request->toUpdatePrompt(), $prompt);
|
||
|
|
|
||
|
|
return redirect()->route('prompts.show', $prompt);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function destroy(Prompt $prompt): RedirectResponse
|
||
|
|
{
|
||
|
|
$this->service->delete($prompt);
|
||
|
|
|
||
|
|
return redirect()->route('prompts.index');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function duplicate(Prompt $prompt): RedirectResponse
|
||
|
|
{
|
||
|
|
$copy = $this->service->duplicate($prompt);
|
||
|
|
|
||
|
|
return redirect()->route('prompts.show', $copy);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function toggleFavorite(Prompt $prompt): RedirectResponse
|
||
|
|
{
|
||
|
|
$this->service->toggleFavorite($prompt);
|
||
|
|
|
||
|
|
return back();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Render the prompt with the given values and record the usage.
|
||
|
|
*/
|
||
|
|
public function use(Request $request, Prompt $prompt): JsonResponse
|
||
|
|
{
|
||
|
|
$validated = $request->validate([
|
||
|
|
'values' => ['required', 'array'],
|
||
|
|
'values.*' => ['string'],
|
||
|
|
]);
|
||
|
|
|
||
|
|
try {
|
||
|
|
$rendered = $this->renderer->render($prompt->body, $validated['values']);
|
||
|
|
} catch (PromptRenderException $exception) {
|
||
|
|
return response()->json([
|
||
|
|
'message' => $exception->getMessage(),
|
||
|
|
'missing' => $exception->missingVariables,
|
||
|
|
], 422);
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->service->recordUsage($prompt);
|
||
|
|
|
||
|
|
return response()->json(['rendered' => $rendered]);
|
||
|
|
}
|
||
|
|
}
|