Repository: provectus/kafka-ui
Issue: Disable negative values
Labels: type/enhancement
scope/frontend
status/accepted
status/confirmed

### Is your proposal related to a problem?

<!--
  Provide a clear and concise description of what the problem is.
  For example, "I'm always frustrated when..."
-->

(Write your answer here.)
Negative value offset is available when trying to Reset offsets by Reset type 'Offset'  on the page Consumer Groups/[Consumer group ID]/Reset Offsets
### Describe the solution you'd like

<!--
  Provide a clear and concise description of what you want to happen.
-->

(Describe your proposed solution here.)
Disable the selection of any negative values in Offsets for Reset type 'Offset' in Reset offsets for Consumer group.
### Describe alternatives you've considered

<!--
  Let us know about other solutions you've tried or researched.
-->

(Write your answer here.)

### Additional context

<!--
  Is there anything else you can add about the proposal?
  You might want to link to related issues here, if you haven't already.
-->
![image](https://user-images.githubusercontent.com/92585878/145566841-4871acd3-f045-4412-bc45-d67f48cb9dba.png)

(Write your answer here.)


Issue comments:

Pull request review comments:
We should use `isValid` instead of checking `Object.values(errors).length > 0`
https://react-hook-form.com/api/useform/formstate

Patch that resolved the issue:
diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx
index 8319fac8c4c..913641ad0ce 100644
--- a/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx
+++ b/kafka-ui-react-app/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx
@@ -67,6 +67,7 @@ const ResetOffsets: React.FC = () => {
   );
 
   const methods = useForm<FormType>({
+    mode: 'onChange',
     defaultValues: {
       resetType: ConsumerGroupOffsetsResetType.EARLIEST,
       topic: '',
@@ -80,7 +81,7 @@ const ResetOffsets: React.FC = () => {
     control,
     setError,
     clearErrors,
-    formState: { errors },
+    formState: { errors, isValid },
   } = methods;
   const { fields } = useFieldArray({
     control,
@@ -127,7 +128,7 @@ const ResetOffsets: React.FC = () => {
         partition: number;
       }[],
     };
-    let isValid = true;
+    let isValidAugmentedData = true;
     if (augmentedData.resetType === ConsumerGroupOffsetsResetType.OFFSET) {
       augmentedData.partitionsOffsets.forEach((offset, index) => {
         if (!offset.offset) {
@@ -135,7 +136,7 @@ const ResetOffsets: React.FC = () => {
             type: 'manual',
             message: "This field shouldn't be empty!",
           });
-          isValid = false;
+          isValidAugmentedData = false;
         }
       });
     } else if (
@@ -146,10 +147,10 @@ const ResetOffsets: React.FC = () => {
           type: 'manual',
           message: "This field shouldn't be empty!",
         });
-        isValid = false;
+        isValidAugmentedData = false;
       }
     }
-    if (isValid) {
+    if (isValidAugmentedData) {
       dispatch(
         resetConsumerGroupOffsets({
           clusterName,
@@ -258,7 +259,13 @@ const ResetOffsets: React.FC = () => {
                         id={`partitionsOffsets.${index}.offset`}
                         type="number"
                         name={`partitionsOffsets.${index}.offset` as const}
-                        hookFormOptions={{ shouldUnregister: true }}
+                        hookFormOptions={{
+                          shouldUnregister: true,
+                          min: {
+                            value: 0,
+                            message: 'must be greater than or equal to 0',
+                          },
+                        }}
                         defaultValue={field.offset}
                       />
                       <ErrorMessage
@@ -277,7 +284,7 @@ const ResetOffsets: React.FC = () => {
             buttonSize="M"
             buttonType="primary"
             type="submit"
-            disabled={selectedPartitions.length === 0}
+            disabled={!isValid || selectedPartitions.length === 0}
           >
             Submit
           </Button>


Test patch: