From 47f48ba12a2e4123053bff3e703b5f9ef8156e38 Mon Sep 17 00:00:00 2001 From: TekH Date: Tue, 6 Oct 2026 10:31:43 +0200 Subject: [PATCH] Add PdfFileDropZone for interactive PDF uploads Replaced static upload message in `CreateEnvelopeWizardPopup.razor` with a new `PdfFileDropZone` component to enhance user experience. The component supports drag-and-drop functionality, file selection, and dynamic states (e.g., disabled, drag-active). Introduced `PdfFileDropZone.razor` with customizable parameters such as `Disabled`, `HasDocument`, `UploadText`, and `DragDropHintText`. Added event handling for drag-and-drop interactions and file selection. Updated `sender-page.css` to include styles for the new component, ensuring seamless integration with the existing layout. Adjusted styles for hover effects, drag-active state, and disabled state. These changes improve usability and make PDF uploads more intuitive. --- .../Sender/CreateEnvelopeWizardPopup.razor | 8 +- .../Components/Sender/PdfFileDropZone.razor | 104 ++++++++++++++++++ .../wwwroot/css/sender-page.css | 64 +++++++++++ 3 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Components/Sender/PdfFileDropZone.razor diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Components/Sender/CreateEnvelopeWizardPopup.razor b/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Components/Sender/CreateEnvelopeWizardPopup.razor index 329a9d93..e7a639ff 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Components/Sender/CreateEnvelopeWizardPopup.razor +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Components/Sender/CreateEnvelopeWizardPopup.razor @@ -245,9 +245,11 @@ } else { -
- @L("SenderWizard_DocumentRequiredHint", "Bitte laden Sie ein PDF-Dokument hoch, um fortzufahren.") -
+ } } diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Components/Sender/PdfFileDropZone.razor b/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Components/Sender/PdfFileDropZone.razor new file mode 100644 index 00000000..1cf0049c --- /dev/null +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Components/Sender/PdfFileDropZone.razor @@ -0,0 +1,104 @@ +@using Microsoft.AspNetCore.Components.Forms + +
+
+
@CurrentActionText
+ @if (!string.IsNullOrWhiteSpace(DragDropHintText)) + { +
@DragDropHintText
+ } +
+ + +
+ +@code { + [Parameter] + public bool Disabled { get; set; } + + [Parameter] + public bool HasDocument { get; set; } + + [Parameter] + public string Accept { get; set; } = ".pdf"; + + [Parameter] + public string UploadText { get; set; } = "PDF hochladen"; + + [Parameter] + public string ReplaceText { get; set; } = "PDF ersetzen"; + + [Parameter] + public string DragDropHintText { get; set; } = "Datei hierhin ziehen oder klicken"; + + [Parameter] + public EventCallback FileSelected { get; set; } + + private int _dragDepth; + private bool _isDragActive; + + private string CurrentActionText => HasDocument ? ReplaceText : UploadText; + + private string DropZoneClass + { + get + { + if (Disabled) + return "sender-pdf-dropzone--disabled"; + + return _isDragActive ? "sender-pdf-dropzone--drag-active" : string.Empty; + } + } + + private void OnDragEnter(DragEventArgs _) + { + if (Disabled) + return; + + _dragDepth++; + _isDragActive = true; + } + + private void OnDragLeave(DragEventArgs _) + { + if (Disabled) + return; + + _dragDepth = Math.Max(0, _dragDepth - 1); + if (_dragDepth == 0) + _isDragActive = false; + } + + private void OnDragOver(DragEventArgs _) + { + if (Disabled) + return; + + _isDragActive = true; + } + + private void OnDrop(DragEventArgs _) + { + _dragDepth = 0; + _isDragActive = false; + } + + private async Task OnFileSelectedAsync(InputFileChangeEventArgs args) + { + _dragDepth = 0; + _isDragActive = false; + + if (Disabled) + return; + + if (FileSelected.HasDelegate) + await FileSelected.InvokeAsync(args); + } +} diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/sender-page.css b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/sender-page.css index 3c78e7ee..3bac4f22 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/sender-page.css +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/sender-page.css @@ -1466,6 +1466,66 @@ display: none; } +.sender-pdf-dropzone { + position: relative; + display: flex; + align-items: center; + justify-content: center; + min-height: 92px; + border: 1px dashed rgba(100, 116, 139, 0.5); + border-radius: 8px; + background: rgba(248, 250, 252, 0.9); + color: #334155; + cursor: pointer; + transition: border-color 120ms ease, background-color 120ms ease, box-shadow 120ms ease; +} + +.sender-pdf-dropzone:hover { + border-color: rgba(126, 34, 206, 0.45); + background: rgba(241, 245, 249, 0.95); +} + +.sender-pdf-dropzone--drag-active { + border-color: rgba(16, 185, 129, 0.75); + background: linear-gradient(180deg, rgba(16, 185, 129, 0.14), rgba(16, 185, 129, 0.08)); + box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.16); +} + +.sender-pdf-dropzone--disabled { + opacity: 0.55; + cursor: not-allowed; +} + +.sender-pdf-dropzone__content { + text-align: center; + display: grid; + gap: 0.2rem; + padding: 0.75rem 0.9rem; +} + +.sender-pdf-dropzone__title { + font-size: 0.86rem; + font-weight: 700; +} + +.sender-pdf-dropzone__hint { + font-size: 0.78rem; + color: #64748b; +} + +.sender-pdf-dropzone__input { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + opacity: 0; + cursor: pointer; +} + +.sender-pdf-dropzone--disabled .sender-pdf-dropzone__input { + cursor: not-allowed; +} + .sender-create-wizard__document-meta { border: 1px solid rgba(16, 185, 129, 0.3); border-radius: 8px; @@ -1524,6 +1584,10 @@ width: 100%; } + .sender-pdf-dropzone { + width: 100%; + } + .sender-create-wizard__upload-btn { width: 100%; }