diff --git a/EnvelopeGenerator.Application/Common/Dto/EnvelopeReceiver/EnvelopeReceiverDto.cs b/EnvelopeGenerator.Application/Common/Dto/EnvelopeReceiver/EnvelopeReceiverDto.cs
index b75722d9..86153648 100644
--- a/EnvelopeGenerator.Application/Common/Dto/EnvelopeReceiver/EnvelopeReceiverDto.cs
+++ b/EnvelopeGenerator.Application/Common/Dto/EnvelopeReceiver/EnvelopeReceiverDto.cs
@@ -60,6 +60,11 @@ public record EnvelopeReceiverDto
///
public string? PrivateMessage { get; init; }
+ ///
+ ///
+ ///
+ public string? AccessCode { get; init; }
+
///
///
///
@@ -83,4 +88,4 @@ public record EnvelopeReceiverDto
h.Receiver?.Id == ReceiverId &&
h.Status == EnvelopeStatus.DocumentSigned
) ?? false;
-}
\ No newline at end of file
+}
diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor
index 77bdbeaf..20c248ee 100644
--- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor
+++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor
@@ -315,6 +315,8 @@
@{
var isSigned = IsReceiverSigned(envelope, receiver);
+ var accessCode = receiver.AccessCode;
+ var hasAccessCode = !string.IsNullOrWhiteSpace(accessCode);
}
@if (isSigned)
@@ -337,6 +339,24 @@
@receiver.Name
@receiver.Receiver?.EmailAddress
+
+
@L("AccessCode", "Access code")
+
+
+
+
+
}
@@ -840,6 +860,21 @@
return value.ResourceNotFound ? fallback : value.Value;
}
+ async Task CopyAccessCodeAsync(string? accessCode)
+ {
+ if (string.IsNullOrWhiteSpace(accessCode))
+ return;
+
+ try
+ {
+ await JSRuntime.InvokeVoidAsync("navigator.clipboard.writeText", accessCode);
+ }
+ catch
+ {
+ await JSRuntime.InvokeVoidAsync("console.warn", "[Sender] Failed to copy access code to clipboard.");
+ }
+ }
+
void OnCustomizeElement(GridCustomizeElementEventArgs e)
{
// Future: Add custom row coloring based on status if needed
diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/sender-page.css b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/sender-page.css
index e121770a..dce4848c 100644
--- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/sender-page.css
+++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/sender-page.css
@@ -382,6 +382,71 @@
color: #c62828;
}
+.sender-access-code {
+ min-width: 120px;
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+}
+
+.sender-access-code__label {
+ font-size: 0.7rem;
+ font-weight: 700;
+ letter-spacing: 0.02em;
+ text-transform: uppercase;
+ color: #64748b;
+}
+
+.sender-access-code__row {
+ display: flex;
+ align-items: center;
+ gap: 0;
+}
+
+.sender-access-code__value {
+ width: 72px;
+ height: 28px;
+ border: 1px solid rgba(126, 34, 206, 0.22);
+ border-right: none;
+ border-radius: 6px 0 0 6px;
+ padding: 0 0.55rem;
+ font-size: 0.8rem;
+ font-weight: 600;
+ color: #1e293b;
+ background: #f8fafc;
+}
+
+.sender-access-code__value:focus {
+ outline: 2px solid rgba(126, 34, 206, 0.18);
+ border-color: rgba(126, 34, 206, 0.45);
+}
+
+.sender-access-code__copy {
+ height: 28px;
+ border: 1px solid rgba(126, 34, 206, 0.3);
+ border-radius: 0 6px 6px 0;
+ width: 30px;
+ min-width: 30px;
+ padding: 0;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ color: #4c1d95;
+ background: rgba(126, 34, 206, 0.08);
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.sender-access-code__copy:hover:not(:disabled) {
+ border-color: rgba(126, 34, 206, 0.45);
+ background: rgba(126, 34, 206, 0.16);
+}
+
+.sender-access-code__copy:disabled {
+ opacity: 0.45;
+ cursor: not-allowed;
+}
+
.sender-history-list {
display: flex;
flex-direction: column;
@@ -521,6 +586,10 @@
padding: 0.875rem 1rem;
font-size: 0.813rem;
}
+
+ .sender-access-code {
+ min-width: 100%;
+ }
}
@media (max-width: 560px) {