mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat: add viewing existingFiles to smartfileinput
This commit is contained in:
@@ -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"}
|
||||
</span>
|
||||
{existingForField.length > 0 && (
|
||||
<div className="flex flex-col gap-1 basis-full">
|
||||
{existingForField.map((f, idx) => (
|
||||
<a
|
||||
key={`${f.url}-${idx}`}
|
||||
href={f.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-xs text-primary hover:underline truncate max-w-xs"
|
||||
>
|
||||
{f.name}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : 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",
|
||||
)}
|
||||
>
|
||||
<input
|
||||
@@ -457,11 +485,31 @@ export function SmartFileInput({
|
||||
<p className="text-sm font-semibold text-foreground">
|
||||
{isDragOver ? "Drop to replace" : "Document uploaded"}
|
||||
</p>
|
||||
<p className="mt-0.5 text-xs text-muted-foreground">
|
||||
{isDragOver
|
||||
? "Release to replace the document on file."
|
||||
: "Saved to your application. Drag a new file here or click to replace it."}
|
||||
</p>
|
||||
{existingForField.length > 0 ? (
|
||||
<div className="mt-0.5 flex flex-col gap-0.5">
|
||||
{existingForField.map((f, idx) => (
|
||||
<a
|
||||
key={`${f.url}-${idx}`}
|
||||
href={f.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="relative z-10 text-xs text-primary hover:underline truncate max-w-xs"
|
||||
>
|
||||
{f.name}
|
||||
{typeof f.size === "number"
|
||||
? ` (${formatBytes(f.size)})`
|
||||
: ""}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-0.5 text-xs text-muted-foreground">
|
||||
{isDragOver
|
||||
? "Release to replace the document on file."
|
||||
: "Saved to your application. Drag a new file here or click to replace it."}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<span className="hidden shrink-0 items-center gap-1.5 rounded-md border border-border bg-card px-3 py-1.5 text-xs font-medium text-foreground shadow-2xs transition group-hover:border-primary/50 group-hover:text-primary sm:inline-flex">
|
||||
@@ -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",
|
||||
)}
|
||||
>
|
||||
<input
|
||||
@@ -534,4 +582,4 @@ export function SmartFileInput({
|
||||
);
|
||||
}
|
||||
|
||||
export default SmartFileInput;
|
||||
export default SmartFileInput;
|
||||
|
||||
Reference in New Issue
Block a user