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:
2026-10-01 10:45:47 +02:00
parent 697d333ad4
commit 76d022053b
27 changed files with 1096 additions and 0 deletions

View File

@@ -5,7 +5,9 @@ declare(strict_types=1);
namespace App\Filament\Resources\Applications\Schemas;
use App\Models\Application;
use App\Models\ApplicationReply;
use Filament\Infolists\Components\KeyValueEntry;
use Filament\Infolists\Components\RepeatableEntry;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
@@ -69,6 +71,36 @@ class ApplicationInfolist
->visible(fn (Application $record) => filled($record->links)),
]),
// What was already said, so the next person to open this does not
// say it again.
Section::make(__('panel.replies.history'))
->visible(fn (Application $record) => $record->replies()->exists())
->schema([
RepeatableEntry::make('replies')
->hiddenLabel()
->schema([
TextEntry::make('subject')
->hiddenLabel()
->weight('bold'),
TextEntry::make('created_at')
->hiddenLabel()
->state(fn (ApplicationReply $record) => __('panel.replies.by', [
'name' => $record->user_name ?? '—',
'when' => $record->created_at?->isoFormat('LLL'),
]).' · '.__('panel.replies.channels.'.$record->channel))
->color('gray'),
TextEntry::make('body')
->hiddenLabel()
->prose()
->formatStateUsing(fn (string $state) => nl2br(e($state)))
->html()
->columnSpanFull(),
])
->columns(2),
]),
Section::make(__('panel.applications.sections.internal'))
->description(__('panel.applications.sections.internal_hint'))
->columns(4)