Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions src/components/Atoms/Controls/Input/Input.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { MenuItem } from "@/types";
import { ChangeHandler, FieldErrors, RegisterOptions } from "react-hook-form";

export interface CustomChangeEvent {
target: {
name: string;
value: any;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace any with a union type for common input values.

The value property should have a more specific type based on common input values.

-    value: any;
+    value: string | number | boolean | string[];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
value: any;
value: string | number | boolean | string[];
🧰 Tools
🪛 ESLint

[error] 7-7: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🤖 Prompt for AI Agents
In src/components/Atoms/Controls/Input/Input.types.ts at line 7, replace the
type of the `value` property from `any` to a union type that covers common input
values such as `string | number | readonly string[] | undefined`. This will
provide better type safety and clarity for the input component's value.

type: string;
};
}

export interface InputProps {
onChange: ChangeHandler;
onBlur: ChangeHandler;
name: string;
min?: string | number;
max?: string | number;
maxLength?: number;
minLength?: number;
pattern?: string;
required?: boolean;
disabled?: boolean;
}

export interface CustomInputProps
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange"> {
name: string;
label?: string;
tooltip?: string;
type:
| "text"
| "email"
| "password"
| "number"
| "tel"
| "radio"
| "switch"
| "checkbox"
| "dropdown";
radioOptions?: Array<{ label: string; value: string; disabled?: boolean }>;
required?: boolean;
badge?: string;
dropdownOptions?: Array<MenuItem>;
customValidation?: RegisterOptions;
onChange?: (
event: React.ChangeEvent<HTMLInputElement> | CustomChangeEvent,
) => void;
}

export interface RenderFieldProps {
type:
| "text"
| "email"
| "password"
| "number"
| "tel"
| "radio"
| "switch"
| "checkbox"
| "dropdown";
disabled?: boolean | undefined;
radioOptions?: Array<{ label: string; value: string; disabled?: boolean }>;
dropdownOptions?: Array<MenuItem>;
fieldValue: any;
createCustomEvent: any;
defaultValue?: any;
Comment on lines +64 to +66
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve type safety by replacing any types with specific types.

These properties can have more specific types:

-  fieldValue: any;
-  createCustomEvent: any;
-  defaultValue?: any;
+  fieldValue: string | number | boolean | string[];
+  createCustomEvent: (value: string | number | boolean | string[]) => CustomChangeEvent;
+  defaultValue?: string | number | boolean | string[];
🧰 Tools
🪛 ESLint

[error] 64-64: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 65-65: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 66-66: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🤖 Prompt for AI Agents
In src/components/Atoms/Controls/Input/Input.types.ts around lines 64 to 66, the
properties fieldValue, createCustomEvent, and defaultValue are currently typed
as any, which reduces type safety. Replace these any types with more specific
types based on their expected values or usage in the codebase, such as string,
number, or a custom event type for createCustomEvent, to improve type safety and
maintainability.

placeholder?: string;
className?: string;
errors: FieldErrors;
inputProps: InputProps;
inputRef: (el: HTMLInputElement | null) => void;
handleChange: (
event: React.ChangeEvent<HTMLInputElement> | CustomChangeEvent,
) => void;
name: string;
label: string | undefined;
ref: React.ForwardedRef<HTMLInputElement>;
props?: any;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove or properly type the generic props field.

The props field with any type appears to be a catch-all that reduces type safety. Consider removing it or defining specific additional props that might be needed.

-  props?: any;

If additional props are needed, define them explicitly in the interface or use a generic type parameter.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
props?: any;
// src/components/Atoms/Controls/Input/Input.types.ts
export interface InputProps {
// ... other explicitly typed props
// Removed the generic catch-all to improve type safety:
// props?: any;
}
🧰 Tools
🪛 ESLint

[error] 78-78: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🤖 Prompt for AI Agents
In src/components/Atoms/Controls/Input/Input.types.ts at line 78, the props
field is typed as any, which reduces type safety. Remove the props field if it
is unnecessary, or replace it with a properly typed definition or a generic type
parameter to explicitly specify the expected additional props and improve type
safety.

}
13 changes: 13 additions & 0 deletions src/components/Atoms/Controls/Input/components/Badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
interface IBadge {
badge: string;
}

const Badge = ({ badge }: IBadge) => {
return (
<div className="caption text-white py-1 px-2 rounded-xl bg-white bg-opacity-10">
{badge}
</div>
);
};

export default Badge;
Comment on lines +1 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Consider renaming to avoid conflict with existing Badge component.

This creates a naming conflict with the existing Badge component at src/components/Atoms/Misc/Badge/index.tsx. The existing component is more feature-rich with variants and better styling utilities. Consider either:

  1. Renaming this to InputBadge to indicate its specific use case
  2. Extending the existing Badge component to support your styling needs
  3. Using the existing Badge component with appropriate props
-const Badge = ({ badge }: IBadge) => {
+const InputBadge = ({ badge }: IBadge) => {
-export default Badge;
+export default InputBadge;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
interface IBadge {
badge: string;
}
const Badge = ({ badge }: IBadge) => {
return (
<div className="caption text-white py-1 px-2 rounded-xl bg-white bg-opacity-10">
{badge}
</div>
);
};
export default Badge;
interface IBadge {
badge: string;
}
const InputBadge = ({ badge }: IBadge) => {
return (
<div className="caption text-white py-1 px-2 rounded-xl bg-white bg-opacity-10">
{badge}
</div>
);
};
export default InputBadge;
🤖 Prompt for AI Agents
In src/components/Atoms/Controls/Input/components/Badge.tsx lines 1 to 13, the
component named Badge conflicts with an existing Badge component in
src/components/Atoms/Misc/Badge/index.tsx. To fix this, rename this component to
InputBadge to clarify its specific use case and avoid naming collisions.
Alternatively, consider extending or using the existing Badge component with
appropriate props to maintain consistency and reuse styling.

14 changes: 14 additions & 0 deletions src/components/Atoms/Controls/Input/components/FieldError.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";

interface FieldErrorProps {
error?: { message?: string };
disabled?: boolean;
}

const FieldError: React.FC<FieldErrorProps> = ({ error, disabled }) => {
if (disabled || !error?.message) return null;

return <span className="text-error-600 text-xs">{error.message}</span>;
};

export default FieldError;
25 changes: 25 additions & 0 deletions src/components/Atoms/Controls/Input/components/Label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
interface LabelProps {
type:
| "text"
| "email"
| "password"
| "number"
| "tel"
| "radio"
| "switch"
| "checkbox"
| "dropdown";
label: string;
name: string;
}

const Label = ({ type, label, name }: LabelProps) => {
if (type === "switch" || type === "radio") return null;
return (
<label htmlFor={name} className="body-2 text-white">
{label}
</label>
);
};

export default Label;
18 changes: 18 additions & 0 deletions src/components/Atoms/Controls/Input/components/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Tooltip } from "@/components/Atoms/Misc/Tooltip";
import { AiOutlineInfoCircle } from "react-icons/ai";

interface ITooltip {
text: string;
}

const InfoTooltip = ({ text }: ITooltip) => {
return (
<Tooltip content={text}>
<div>
<AiOutlineInfoCircle className="text-white flex-shrink-0" size={16} />
</div>
</Tooltip>
);
};

export default InfoTooltip;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Input from "../formControls/input";
import DropdownField from "../formControls/dropdown";
import SwitchField from "../formControls/switch";
import RadioButton from "../formControls/radio_buttons";
import { RenderFieldProps } from "../Input.types";

export const renderFieldForInput = ({ ...props }: RenderFieldProps) => {
switch (props.type) {
case "radio":
return <RadioButton {...props} />;

case "switch":
return <SwitchField {...props} />;

case "dropdown":
return <DropdownField {...props} />;

default: {
return <Input {...props} />;
}
}
};
27 changes: 27 additions & 0 deletions src/components/Atoms/Controls/Input/formControls/dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import DropdownMenu from "@/components/Molecules/Dropdowns";
import { RenderFieldProps } from "../components/renderFieldForInput";

const DropdownField = ({
disabled,
dropdownOptions,
fieldValue,
createCustomEvent,
defaultValue,
placeholder,
className,
handleChange,
}: RenderFieldProps) => {
return (
<DropdownMenu
disabled={disabled}
size="lg"
menuList={dropdownOptions || []}
onChange={(value) => handleChange(createCustomEvent(value.label))}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null safety for value.label access.

The value.label access could throw an error if the selected value doesn't have a label property. Consider adding null safety checks.

-       onChange={(value) => handleChange(createCustomEvent(value.label))}
+       onChange={(value) => handleChange(createCustomEvent(value?.label || value))}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/components/Atoms/Controls/Input/formControls/dropdown.tsx at line 19, the
code accesses value.label without checking if value or value.label is null or
undefined, which can cause runtime errors. Update the onChange handler to safely
access value.label by adding a null check or optional chaining before passing it
to createCustomEvent, ensuring it handles cases where value or value.label might
be missing.

className={className}
>
{fieldValue || defaultValue || placeholder}
</DropdownMenu>
);
};

export default DropdownField;
58 changes: 58 additions & 0 deletions src/components/Atoms/Controls/Input/formControls/input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { tv } from "tailwind-variants";
import { RenderFieldProps } from "../Input.types";
import { usePasswordToggle } from "@/hooks/usePasswordToggle";

const inputClass = tv({
base: "body-3 w-full rounded-xl p-4 bg-white bg-opacity-10 ring-0 outline-0 focus:ring-1 active:ring-1 focus:ring-white active:ring-white transition-all ease-in-out duration-300 text-white",
variants: {
error: {
true: "border border-error-600",
false: "",
},
withIcon: {
true: "pr-12", // Add padding to the right to accommodate the icon
},
},
});

const Input = ({
type,
disabled,
className,
errors,
inputProps,
inputRef,
handleChange,
defaultValue,
name,
ref,
props,
}: RenderFieldProps) => {
const { showPassword, PasswordToggleIcon } = usePasswordToggle();
console.log("type", type);
return (
<div className="relative w-full">
<input
defaultValue={defaultValue}
className={inputClass({
error: !disabled && errors[name] !== undefined,
withIcon: type === "password",
className,
})}
disabled={disabled}
id={name}
type={type === "password" && showPassword ? "text" : type}
{...inputProps}
onChange={handleChange}
{...props}
ref={(e) => {
if (typeof inputRef === "function") inputRef(e);
if (typeof ref === "function") ref(e);
}}
/>
{type === "password" && PasswordToggleIcon}
</div>
);
};

export default Input;
31 changes: 31 additions & 0 deletions src/components/Atoms/Controls/Input/formControls/radio_buttons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Radio from "../../RadioButton";
import { RenderFieldProps } from "../components/renderFieldForInput";

const RadioButton = ({
type,
disabled,
radioOptions,
defaultValue,
handleChange,
name,
}: RenderFieldProps) => {
return (
<Radio
options={
radioOptions?.map((opt) => ({
...opt,
disabled: opt.disabled || disabled,
})) || []
}
defaultValue={String(defaultValue)}
className="space-y-2"
labelClassName="body-2 text-white ml-3"
onClick={(opt: { value: any }) =>
handleChange({ target: { name, value: opt.value, type } })
}
Comment on lines +23 to +25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Fix the TypeScript any type violation.

The static analysis correctly flagged the use of any type, which reduces type safety. The opt parameter should be properly typed based on the radio options structure.

-      onClick={(opt: { value: any }) =>
+      onClick={(opt: { value: string | number }) =>
         handleChange({ target: { name, value: opt.value, type } })
       }

Please verify the expected type for radio option values by checking the RadioOptions type definition:


🏁 Script executed:

#!/bin/bash
# Search for RadioOptions type definition
ast-grep --pattern 'interface RadioOptions {
  $$$
}' || ast-grep --pattern 'type RadioOptions = {
  $$$
}'

Length of output: 55


We’ll need to inspect the radio_buttons component to find the correct option type. Let’s locate and print its top section (including props and any related type imports):


🏁 Script executed:

#!/bin/bash
# Find the radio_buttons component file
file=$(fd --full-path radio_buttons.tsx)

# Print its imports, props interface, and any RadioOptions/type usage
sed -n '1,200p' "$file"

Length of output: 884


Let’s locate and inspect the RenderFieldProps to confirm the radioOptions type:


🏁 Script executed:

#!/bin/bash
# Find the file and print its top section to see RenderFieldProps and radioOptions definition
file=$(rg -l "RenderFieldProps" -n src/components/Atoms/Controls/Input)
echo "Found in: $file"
sed -n '1,200p' "$file"

Length of output: 2013


Let’s pull in the RenderFieldProps definition and the shared types to confirm the exact shape of radioOptions:


🏁 Script executed:

#!/bin/bash
echo "===== renderFieldForInput.tsx ====="
sed -n '1,200p' src/components/Atoms/Controls/Input/components/renderFieldForInput.tsx
echo
echo "===== Input.types.ts ====="
sed -n '1,200p' src/components/Atoms/Controls/Input/Input.types.ts

Length of output: 2735


Specify correct opt type in the onClick handler

Based on the RenderFieldProps definition, each radioOptions item is typed as { label: string; value: string; disabled?: boolean }. Update the inline opt parameter to match that shape:

File: src/components/Atoms/Controls/Input/formControls/radio_buttons.tsx
Lines: 23–25

-      onClick={(opt: { value: any }) =>
+      onClick={(opt: { label: string; value: string; disabled?: boolean }) =>
         handleChange({ target: { name, value: opt.value, type } })
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onClick={(opt: { value: any }) =>
handleChange({ target: { name, value: opt.value, type } })
}
onClick={(opt: { label: string; value: string; disabled?: boolean }) =>
handleChange({ target: { name, value: opt.value, type } })
}
🧰 Tools
🪛 ESLint

[error] 23-23: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🤖 Prompt for AI Agents
In src/components/Atoms/Controls/Input/formControls/radio_buttons.tsx around
lines 23 to 25, the onClick handler's parameter `opt` is currently typed as `{
value: any }`, which is incorrect. Update the type of `opt` to `{ label: string;
value: string; disabled?: boolean }` to match the `radioOptions` item type
defined in `RenderFieldProps`. This ensures type correctness and better code
clarity.

size="sm"
/>
);
};

export default RadioButton;
34 changes: 34 additions & 0 deletions src/components/Atoms/Controls/Input/formControls/switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Switch from "../../Switch";
import { RenderFieldProps } from "../components/renderFieldForInput";
Comment on lines +1 to +2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Import path concern for RenderFieldProps.

The import path suggests RenderFieldProps is imported from ../components/renderFieldForInput, but based on the relevant code snippets, it should be imported from the types file.


🏁 Script executed:

#!/bin/bash
# Description: Verify the correct import path for RenderFieldProps
# Expected: RenderFieldProps should be imported from Input.types.ts

# Check if RenderFieldProps is defined in Input.types.ts
ast-grep --pattern 'export interface RenderFieldProps {
  $$$
}'

# Check current import in switch.tsx
rg "RenderFieldProps" -A 2 -B 2

Length of output: 6744


Update RenderFieldProps import in switch.tsx

The RenderFieldProps type is defined in Input.types.ts, not in the render helper. Please update the import in your switch field component:

• File: src/components/Atoms/Controls/Input/formControls/switch.tsx

- import { RenderFieldProps } from "../components/renderFieldForInput";
+ import { RenderFieldProps } from "../Input.types";

Also verify and correct the same import in any other form controls (e.g. radio_buttons.tsx, dropdown.tsx) to ensure they all pull RenderFieldProps from Input.types.ts.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import Switch from "../../Switch";
import { RenderFieldProps } from "../components/renderFieldForInput";
import Switch from "../../Switch";
-import { RenderFieldProps } from "../components/renderFieldForInput";
+import { RenderFieldProps } from "../Input.types";
🤖 Prompt for AI Agents
In src/components/Atoms/Controls/Input/formControls/switch.tsx at lines 1 to 2,
the import of RenderFieldProps is incorrectly from
"../components/renderFieldForInput". Change this import to come from
"Input.types.ts" instead. Also, check other form control files like
radio_buttons.tsx and dropdown.tsx to ensure their RenderFieldProps imports are
updated similarly to import from "Input.types.ts".


const SwitchField = ({
type,
disabled,
className,
inputRef,
handleChange,
name,
label,
ref,
props,
}: RenderFieldProps) => {
return (
<Switch
disabled={disabled}
name={name}
label={label}
className={className}
{...props}
ref={(e: HTMLInputElement | null) => {
if (typeof inputRef === "function") inputRef(e);
if (typeof ref === "function") ref(e);
else if (ref) ref.current = e;
}}
onChange={(checked: unknown) =>
handleChange({ target: { name, value: checked, type } })
}
Comment on lines +27 to +29
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Review the custom event structure for type safety.

The custom event creation should ensure proper typing and structure consistency.

      onChange={(checked: unknown) =>
-        handleChange({ target: { name, value: checked, type } })
+        handleChange({ 
+          target: { name, value: checked, type } 
+        } as React.ChangeEvent<HTMLInputElement>)
      }

Consider adding proper TypeScript casting to ensure the event structure matches the expected CustomChangeEvent type.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onChange={(checked: unknown) =>
handleChange({ target: { name, value: checked, type } })
}
onChange={(checked: unknown) =>
handleChange({
target: { name, value: checked, type }
} as React.ChangeEvent<HTMLInputElement>)
}
🤖 Prompt for AI Agents
In src/components/Atoms/Controls/Input/formControls/switch.tsx around lines 27
to 29, the custom event object passed to handleChange lacks explicit TypeScript
typing, risking type safety issues. Fix this by casting the event object to the
expected CustomChangeEvent type, ensuring the structure matches the defined
interface and TypeScript can properly validate the event's shape.

/>
);
};

export default SwitchField;
Loading