From 633c7c52c58e685bed08f4539b0a3b0ae2827c12 Mon Sep 17 00:00:00 2001
From: Nathnael
Date: Fri, 3 Jul 2026 06:22:32 +0000
Subject: [PATCH] feat: add viewing existingFiles to smartfileinput
---
.../src/components/SmartFileInput/index.tsx | 68 ++++++++++++++++---
1 file changed, 58 insertions(+), 10 deletions(-)
diff --git a/packages/ui-common/src/components/SmartFileInput/index.tsx b/packages/ui-common/src/components/SmartFileInput/index.tsx
index 978fb5498..d39e431c7 100644
--- a/packages/ui-common/src/components/SmartFileInput/index.tsx
+++ b/packages/ui-common/src/components/SmartFileInput/index.tsx
@@ -27,6 +27,16 @@ export interface SmartFileInputProps {
* no in-memory File is currently selected for them.
*/
uploadedKeys?: string[];
+ /**
+ * Metadata for already-uploaded files, keyed by fileKey. When a field has
+ * entries here, they're listed with view/download links (instead of the
+ * generic placeholder text) and the field counts as uploaded even if it's
+ * not also listed in `uploadedKeys`.
+ */
+ existingFiles?: Record<
+ string,
+ { name: string; url: string; size?: number }[]
+ >;
/** Disabled state for the entire file input group. */
disabled?: boolean;
/** Display variant style. Default is "default" (large dropzone). Minimal renders a compact upload button. */
@@ -76,6 +86,7 @@ export function SmartFileInput({
onChange,
errors,
uploadedKeys,
+ existingFiles,
disabled = false,
variant = "default",
className,
@@ -270,9 +281,11 @@ export function SmartFileInput({
const fieldError =
errors?.[field.fileKey] || localErrors[field.fileKey];
const isDragOver = dragActive[field.fileKey];
+ const existingForField = existingFiles?.[field.fileKey] ?? [];
// Already uploaded server-side and nothing newly picked to replace it.
const isUploaded =
- (uploadedKeys?.includes(field.fileKey) ?? false) &&
+ ((uploadedKeys?.includes(field.fileKey) ?? false) ||
+ existingForField.length > 0) &&
currentFiles.length === 0;
// Format accepted files for the HTML input element
@@ -417,6 +430,21 @@ export function SmartFileInput({
{field.allowedExtensions.join(", ").toUpperCase() ||
"All"}
+ {existingForField.length > 0 && (
+
+ {existingForField.map((f, idx) => (
+
+ {f.name}
+
+ ))}
+
+ )}
) : isUploaded ? (
// Uploaded state: a solid success panel that still doubles as a
@@ -431,7 +459,7 @@ export function SmartFileInput({
? "border-2 border-dashed border-primary bg-primary/5 dark:bg-primary/10"
: "border-emerald-300/70 bg-emerald-50/60 dark:border-emerald-500/30 dark:bg-emerald-500/10",
disabled &&
- "opacity-50 pointer-events-none cursor-not-allowed",
+ "opacity-50 pointer-events-none cursor-not-allowed",
)}
>
{isDragOver ? "Drop to replace" : "Document uploaded"}
-
- {isDragOver
- ? "Release to replace the document on file."
- : "Saved to your application. Drag a new file here or click to replace it."}
-
+ {existingForField.length > 0 ? (
+
+ ) : (
+
+ {isDragOver
+ ? "Release to replace the document on file."
+ : "Saved to your application. Drag a new file here or click to replace it."}
+
+ )}
@@ -480,9 +528,9 @@ export function SmartFileInput({
? "border-primary bg-primary/5 dark:bg-primary/10"
: "border-border hover:border-primary/50 hover:bg-muted/10",
fieldError &&
- "border-destructive hover:border-destructive/80",
+ "border-destructive hover:border-destructive/80",
disabled &&
- "opacity-50 pointer-events-none cursor-not-allowed",
+ "opacity-50 pointer-events-none cursor-not-allowed",
)}
>