From 36f4d4b8d51f1ef1dd9c8336d4a507899e1e185e Mon Sep 17 00:00:00 2001 From: grabowski Date: Thu, 9 Apr 2026 16:23:30 +0700 Subject: [PATCH] Redesign file uploads: drag-and-drop zones for images and documents New reusable components: - ImageUpload.svelte: drag-and-drop / click / paste zone with file icon, preview of selected filename, caption field, 50MB limit - DocumentUpload.svelte: same pattern for documents with description field instead of caption Applied to both device and component detail pages, replacing the old inline file input forms. Cleaner look matching modern upload UIs. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/lib/components/ui/DocumentUpload.svelte | 101 +++++++++++++++++ src/lib/components/ui/ImageUpload.svelte | 105 ++++++++++++++++++ src/routes/(app)/components/[id]/+page.svelte | 45 ++------ src/routes/(app)/devices/[id]/+page.svelte | 44 +------- 4 files changed, 219 insertions(+), 76 deletions(-) create mode 100644 src/lib/components/ui/DocumentUpload.svelte create mode 100644 src/lib/components/ui/ImageUpload.svelte diff --git a/src/lib/components/ui/DocumentUpload.svelte b/src/lib/components/ui/DocumentUpload.svelte new file mode 100644 index 0000000..3c7dc39 --- /dev/null +++ b/src/lib/components/ui/DocumentUpload.svelte @@ -0,0 +1,101 @@ + + +
{ + return async ({ update, result }) => { + await update(); + if (result.type === 'success') { + selectedFile = null; + if (fileInput) fileInput.value = ''; + } + }; +}}> + + +
fileInput.click()} + ondragover={(e) => { e.preventDefault(); dragging = true; }} + ondragleave={() => { dragging = false; }} + ondrop={handleDrop} + > + + + {#if selectedFile} +
+ + + +

{selectedFile}

+

Click Upload below or select a different file

+
+ {:else} + + + + +

Select Files to Upload

+

or Drag and Drop, Copy and Paste Files

+ {/if} +
+ + {#if selectedFile} +
+ + + +
+ {/if} +
diff --git a/src/lib/components/ui/ImageUpload.svelte b/src/lib/components/ui/ImageUpload.svelte new file mode 100644 index 0000000..eed0418 --- /dev/null +++ b/src/lib/components/ui/ImageUpload.svelte @@ -0,0 +1,105 @@ + + + + +
{ + return async ({ update, result }) => { + await update(); + if (result.type === 'success') { + selectedFile = null; + if (fileInput) fileInput.value = ''; + } + }; +}}> + + +
fileInput.click()} + ondragover={(e) => { e.preventDefault(); dragging = true; }} + ondragleave={() => { dragging = false; }} + ondrop={handleDrop} + > + + + {#if selectedFile} +
+ + + +

{selectedFile}

+

Click Upload below or select a different file

+
+ {:else} + + + + +

Select Files to Upload

+

or Drag and Drop, Copy and Paste Files

+ {/if} +
+ + {#if selectedFile} +
+ + + +
+ {/if} +
diff --git a/src/routes/(app)/components/[id]/+page.svelte b/src/routes/(app)/components/[id]/+page.svelte index 95ef449..f8afa58 100644 --- a/src/routes/(app)/components/[id]/+page.svelte +++ b/src/routes/(app)/components/[id]/+page.svelte @@ -2,6 +2,8 @@ import { enhance } from '$app/forms'; import { COMPONENT_CONDITIONS } from '$lib/constants.js'; import { formatDate, timeAgo } from '$lib/utils/date.js'; + import ImageUpload from '$lib/components/ui/ImageUpload.svelte'; + import DocumentUpload from '$lib/components/ui/DocumentUpload.svelte'; let { data, form } = $props(); const c = $derived(data.component); @@ -88,30 +90,9 @@
-
-

Images

- -
+

Images

- {#if showUploadForm} -
- { - const file = (e.target as HTMLInputElement).files?.[0]; - if (file && file.size > 50 * 1024 * 1024) { - alert('File too large. Maximum size is 50MB.'); - (e.target as HTMLInputElement).value = ''; - } - }} - class="text-sm text-gray-600 dark:text-gray-400" /> - - -
- {/if} + {#if data.images.length === 0}

No images yet.

@@ -330,21 +311,9 @@
-
-

Documents

- -
- {#if showDocForm} -
- - - -
- {/if} +

Documents

+ + {#if data.documents.length === 0}

No documents.

{:else} diff --git a/src/routes/(app)/devices/[id]/+page.svelte b/src/routes/(app)/devices/[id]/+page.svelte index 7cae9e9..641bbf4 100644 --- a/src/routes/(app)/devices/[id]/+page.svelte +++ b/src/routes/(app)/devices/[id]/+page.svelte @@ -1,6 +1,8 @@