Answer the inbox from the panel, with templates
A reply starts from a template filled in the language the person wrote in, is sent by the application when it has a mailer that delivers or handed to the replier's mail program otherwise, and is recorded on the submission. The same is available through the API. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
98
app/Http/Controllers/Api/V1/ApplicationReplyController.php
Normal file
98
app/Http/Controllers/Api/V1/ApplicationReplyController.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationReply;
|
||||
use App\Models\ReplyTemplate;
|
||||
use App\Support\Inbox\Replier;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
/**
|
||||
* Answering the inbox through the API: what was already said, the templates
|
||||
* to start from, and sending an answer — the panel's "Reply".
|
||||
*/
|
||||
class ApplicationReplyController extends Controller
|
||||
{
|
||||
public function index(Application $application): JsonResponse
|
||||
{
|
||||
$this->authorize('view', $application);
|
||||
|
||||
return response()->json([
|
||||
'data' => $application->replies()->get()->map(fn (ApplicationReply $reply) => $this->present($reply))->values(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* `subject` and `body`, or a `template_id` to fill them from — in the
|
||||
* language the person wrote in. Sent when this installation can send
|
||||
* mail; otherwise recorded, with a `mailto` link to send it by hand.
|
||||
*/
|
||||
public function store(Request $request, Application $application): JsonResponse
|
||||
{
|
||||
$this->authorize('update', $application);
|
||||
|
||||
$data = $request->validate([
|
||||
'template_id' => ['sometimes', 'nullable', 'integer', 'exists:reply_templates,id'],
|
||||
'subject' => ['required_without:template_id', 'nullable', 'string', 'max:255'],
|
||||
'body' => ['required_without:template_id', 'nullable', 'string', 'max:20000'],
|
||||
]);
|
||||
|
||||
$text = ['subject' => $data['subject'] ?? null, 'body' => $data['body'] ?? null];
|
||||
|
||||
if (filled($data['template_id'] ?? null)) {
|
||||
$rendered = ReplyTemplate::query()->findOrFail($data['template_id'])->renderFor($application, $request->user());
|
||||
$text = ['subject' => $text['subject'] ?: $rendered['subject'], 'body' => $text['body'] ?: $rendered['body']];
|
||||
}
|
||||
|
||||
if (blank($text['subject']) || blank($text['body'])) {
|
||||
throw ValidationException::withMessages(['template_id' => [__('panel.replies.empty_template')]]);
|
||||
}
|
||||
|
||||
$reply = Replier::reply($application, $text['subject'], $text['body'], $request->user());
|
||||
|
||||
return response()->json([
|
||||
'data' => [
|
||||
...$this->present($reply),
|
||||
'mailto' => $reply->channel === ApplicationReply::MAILTO
|
||||
? Replier::mailto($application, $text['subject'], $text['body'])
|
||||
: null,
|
||||
],
|
||||
], 201);
|
||||
}
|
||||
|
||||
public function templates(Request $request): JsonResponse
|
||||
{
|
||||
$this->authorize('viewAny', ReplyTemplate::class);
|
||||
|
||||
return response()->json([
|
||||
'data' => ReplyTemplate::query()->orderBy('position')->orderBy('name')->get()->map(fn (ReplyTemplate $template) => [
|
||||
'id' => $template->id,
|
||||
'name' => $template->name,
|
||||
'kind' => $template->kind,
|
||||
'subject' => (object) $template->getTranslations('subject'),
|
||||
'body' => (object) $template->getTranslations('body'),
|
||||
])->values(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function present(ApplicationReply $reply): array
|
||||
{
|
||||
return [
|
||||
'id' => $reply->id,
|
||||
'subject' => $reply->subject,
|
||||
'body' => $reply->body,
|
||||
'channel' => $reply->channel,
|
||||
'author' => ['id' => $reply->user_id, 'name' => $reply->user_name],
|
||||
'created_at' => $reply->created_at?->toIso8601String(),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user