From d07e77857047576671d39a034dfb1ef657566e3e Mon Sep 17 00:00:00 2001 From: Anuarbek Zhakhangir Date: Thu, 31 Jul 2025 02:00:09 +0900 Subject: [PATCH] feat: implement Fight registration form with input validation and file upload --- src/components/form/Checkbox.tsx | 2 +- src/components/form/Fileupload.tsx | 72 +++++++++++--- src/components/form/Input.tsx | 2 +- src/components/form/Radio.tsx | 2 +- src/components/form/Select.tsx | 2 +- src/components/form/Textarea.tsx | 2 +- src/pages/forms/exhibition.tsx | 146 +++++++++++++++-------------- src/pages/forms/fight.tsx | 144 ++++++++++++++++++++++++++++ 8 files changed, 285 insertions(+), 87 deletions(-) create mode 100644 src/pages/forms/fight.tsx diff --git a/src/components/form/Checkbox.tsx b/src/components/form/Checkbox.tsx index 9c8785c..bc4bee5 100644 --- a/src/components/form/Checkbox.tsx +++ b/src/components/form/Checkbox.tsx @@ -47,7 +47,7 @@ export default function Checkbox({ }; return ( -
+
void; acceptedTypes?: string[]; maxFileSize?: number; // in MB + maxFiles?: number; // maximum number of files multiple?: boolean; disabled?: boolean; placeholder?: string; @@ -19,6 +20,7 @@ function Fileupload({ onFileSelect, acceptedTypes = ["image/*", "application/pdf", ".doc", ".docx"], maxFileSize = 10, + maxFiles = 5, multiple = false, disabled = false, placeholder = "Файл в формате jpg или png до N мб", @@ -67,15 +69,41 @@ function Fileupload({ if (!files) return; const fileArray = Array.from(files); - const { valid, errors } = validateFiles(fileArray); - - setErrors(errors); + const { valid, errors: validationErrors } = validateFiles(fileArray); + const allErrors = [...validationErrors]; if (valid.length > 0) { - const newFiles = multiple ? [...selectedFiles, ...valid] : valid; + let newFiles: File[]; + + if (multiple) { + // Check if adding new files would exceed maxFiles limit + const totalFiles = selectedFiles.length + valid.length; + if (totalFiles > maxFiles) { + const allowedCount = maxFiles - selectedFiles.length; + if (allowedCount <= 0) { + allErrors.push( + `Maximum ${maxFiles} files allowed. Remove some files first.` + ); + setErrors(allErrors); + return; + } else { + allErrors.push( + `Only ${allowedCount} more files can be added (max ${maxFiles} total).` + ); + newFiles = [...selectedFiles, ...valid.slice(0, allowedCount)]; + } + } else { + newFiles = [...selectedFiles, ...valid]; + } + } else { + newFiles = valid; + } + setSelectedFiles(newFiles); onFileSelect?.(newFiles); } + + setErrors(allErrors); }; const handleDrag = (e: DragEvent) => { @@ -116,6 +144,10 @@ function Fileupload({ } }; + // Check if upload button should be disabled + const isUploadDisabled = + disabled || (multiple && selectedFiles.length >= maxFiles); + return (
{label && ( @@ -131,10 +163,12 @@ function Fileupload({ {/* Upload Area */}
@@ -158,8 +192,8 @@ function Fileupload({ @@ -167,9 +201,14 @@ function Fileupload({ {/* File Display Area */}
{selectedFiles.length > 0 ? ( -
+
{selectedFiles[0].name} + {multiple && selectedFiles.length > 1 && ( + + and {selectedFiles.length - 1} more + + )}
) : ( - + {placeholder.replace("N", maxFileSize.toString())} )}
+ {/* File count indicator for multiple files */} + {multiple && selectedFiles.length > 0 && ( +
+ {selectedFiles.length} of {maxFiles} files selected +
+ )} + {/* Error Messages */} {errors.length > 0 && (
diff --git a/src/components/form/Input.tsx b/src/components/form/Input.tsx index 2ef5c5a..bd98e4d 100644 --- a/src/components/form/Input.tsx +++ b/src/components/form/Input.tsx @@ -32,7 +32,7 @@ function Input({ name, }: InputProps) { return ( -
+
{label && (