Add Title and Message fields to Envelope editor

Introduced input fields for "Title" and "Message" in the
EnvelopeSenderEditorPage, allowing users to specify metadata
for envelopes. The "Title" field is required and validated,
while the "Message" field is optional with a default value.

Updated the save logic to validate the title and display
appropriate error messages. Persisted the "Title" and
"Message" fields in the session cache via the
`EditorSessionData` record.

Modified the `CreateEnvelopeReceiverCommand` to use the
user-provided "Title" and "Message" values. Adjusted the UI
layout and styling to accommodate the new fields, ensuring
a seamless user experience.
This commit is contained in:
2026-07-02 02:00:14 +02:00
parent 1b2731b4b2
commit 40c95100ff

View File

@@ -28,23 +28,65 @@
<div class="envelope-action-bar__inner"
style="flex-direction: row; align-items: center; padding: 0.35rem 1.5rem; gap: 0.75rem;">
@* Left: Title *@
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: stretch; gap: 0.75rem;">
<div style="display: flex; align-items: center; gap: 0.75rem; min-width: 0; flex-wrap: wrap;">
<div style="font-size: 0.9rem; font-weight: 600; color: #1f2937; white-space: nowrap;">
Neues Dokument
@* Left: Title + meta inputs + receivers *@
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: stretch; gap: 0.5rem;">
@* ── Title & Message inputs ── *@
<div style="display: flex; align-items: flex-start; gap: 0.5rem; flex-wrap: wrap;">
@* Titel *@
<div style="display: flex; flex-direction: column; gap: 0.2rem; flex: 1 1 180px; min-width: 140px;">
<label style="font-size: 0.65rem; font-weight: 600; color: #6b7280;
text-transform: uppercase; letter-spacing: 0.05em;">
Titel <span style="color:#dc2626;">*</span>
</label>
<input type="text"
value="@_envelopeTitle"
@oninput="e => _envelopeTitle = e.Value?.ToString() ?? string.Empty"
placeholder="z.B. Arbeitsvertrag 2025"
maxlength="120"
style="font-size: 0.78rem; font-weight: 500; color: #1f2937;
border: 1px solid #d1d5db; border-radius: 5px;
padding: 0.3rem 0.55rem; outline: none; width: 100%;
background: #fff;
@(_titleTouched && string.IsNullOrWhiteSpace(_envelopeTitle) ? "border-color:#dc2626;" : "")" />
@if (_titleTouched && string.IsNullOrWhiteSpace(_envelopeTitle))
{
<span style="font-size:0.6rem;color:#dc2626;">Pflichtfeld</span>
}
</div>
@* Nachricht *@
<div style="display: flex; flex-direction: column; gap: 0.2rem; flex: 2 1 260px; min-width: 180px;">
<label style="font-size: 0.65rem; font-weight: 600; color: #6b7280;
text-transform: uppercase; letter-spacing: 0.05em;">
Nachricht <span style="color:#6b7280;font-weight:400;">(optional)</span>
</label>
<input type="text"
value="@_envelopeMessage"
@oninput="e => _envelopeMessage = e.Value?.ToString() ?? string.Empty"
placeholder="Bitte unterzeichnen Sie das beigefügte Dokument."
maxlength="500"
style="font-size: 0.78rem; color: #1f2937;
border: 1px solid #d1d5db; border-radius: 5px;
padding: 0.3rem 0.55rem; outline: none; width: 100%;
background: #fff;" />
</div>
@* PDF filename badge *@
@if (_pdfLoaded)
{
<span style="font-size: 0.7rem; color: #6b7280;">@_fileName</span>
@if (_signatureFields.Count > 0)
{
<span style="display: inline-flex; align-items: center; padding: 0.125rem 0.4rem;
background: #ede9fe; border-radius: 0.25rem; color: #6d28d9;
font-weight: 500; font-size: 0.7rem; white-space: nowrap;">
@_signatureFields.Count Signaturfeld@(_signatureFields.Count != 1 ? "er" : "")
</span>
}
<div style="display:flex;align-items:flex-end;gap:0.4rem;padding-bottom:0.05rem;flex-shrink:0;">
<span style="font-size: 0.7rem; color: #6b7280;">@_fileName</span>
@if (_signatureFields.Count > 0)
{
<span style="display: inline-flex; align-items: center; padding: 0.125rem 0.4rem;
background: #ede9fe; border-radius: 0.25rem; color: #6d28d9;
font-weight: 500; font-size: 0.7rem; white-space: nowrap;">
@_signatureFields.Count Signaturfeld@(_signatureFields.Count != 1 ? "er" : "")
</span>
}
</div>
}
</div>
@@ -419,6 +461,11 @@
bool _savePopupVisible = false;
string? _saveErrorMessage = null;
// ── Envelope metadata ──
string _envelopeTitle = string.Empty;
string _envelopeMessage = string.Empty;
bool _titleTouched = false;
List<ReceiverDraft> _receivers = [];
bool _receiverPopupVisible;
string _receiverDraftName = string.Empty;
@@ -469,6 +516,8 @@
_fileName = cached.FileName;
_pdfLoaded = _originalPdfBytes is { Length: > 0 };
_receivers = cached.Receivers;
_envelopeTitle = cached.Title;
_envelopeMessage = cached.Message;
// Redraw placeholders onto the original PDF
if (_pdfLoaded)
@@ -625,12 +674,19 @@
async Task SaveAsync()
{
// ── Validation ──
_titleTouched = true;
if (!_pdfLoaded || _originalPdfBytes is null)
{
_saveErrorMessage = "Bitte laden Sie zuerst ein PDF-Dokument hoch.";
_savePopupVisible = true;
return;
}
if (string.IsNullOrWhiteSpace(_envelopeTitle))
{
_saveErrorMessage = "Bitte geben Sie einen Titel ein.";
_savePopupVisible = true;
return;
}
if (_receivers.Count == 0)
{
_saveErrorMessage = "Bitte fügen Sie mindestens einen Empfänger hinzu.";
@@ -690,8 +746,10 @@
var command = new CreateEnvelopeReceiverCommand
{
Title = "Neuer Umschlag", // placeholder — dedicated field will be added later
Message = "Bitte unterzeichnen Sie das beigefügte Dokument.",
Title = _envelopeTitle.Trim(),
Message = string.IsNullOrWhiteSpace(_envelopeMessage)
? "Bitte unterzeichnen Sie das beigefügte Dokument."
: _envelopeMessage.Trim(),
TFAEnabled = false,
Document = new DocumentCreateCommand { DataAsBase64 = docBase64 },
Receivers = receiversCmd,
@@ -728,7 +786,9 @@
OriginalPdfBytes: _originalPdfBytes ?? [],
Fields: [.. _signatureFields],
FileName: _fileName,
Receivers: [.. _receivers]);
Receivers: [.. _receivers],
Title: _envelopeTitle,
Message: _envelopeMessage);
MemoryCache.Set(SessionKey, data, SessionTtl);
}
@@ -977,7 +1037,9 @@
byte[] OriginalPdfBytes,
List<SignatureFieldDraft> Fields,
string FileName,
List<ReceiverDraft> Receivers);
List<ReceiverDraft> Receivers,
string Title,
string Message);
// ── Receiver colour palette (cycles when > 8 receivers) ──
static readonly string[] ReceiverPalette =