-
Notifications
You must be signed in to change notification settings - Fork 10
Refactored components and added chatbot #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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; | ||||||||||||||||||||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve type safety by replacing 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 |
||||||||||||||||||||
| 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; | ||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Remove or properly type the generic The - props?: any;If additional props are needed, define them explicitly in the interface or use a generic type parameter. 📝 Committable suggestion
Suggested change
🧰 Tools🪛 ESLint[error] 78-78: Unexpected any. Specify a different type. (@typescript-eslint/no-explicit-any) 🤖 Prompt for AI Agents |
||||||||||||||||||||
| } | ||||||||||||||||||||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider renaming to avoid conflict with existing Badge component. This creates a naming conflict with the existing
-const Badge = ({ badge }: IBadge) => {
+const InputBadge = ({ badge }: IBadge) => {-export default Badge;
+export default InputBadge;📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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; |
| 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; |
| 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} />; | ||
| } | ||
| } | ||
| }; |
| 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))} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add null safety for value.label access. The - onChange={(value) => handleChange(createCustomEvent(value.label))}
+ onChange={(value) => handleChange(createCustomEvent(value?.label || value))}
🤖 Prompt for AI Agents |
||
| className={className} | ||
| > | ||
| {fieldValue || defaultValue || placeholder} | ||
| </DropdownMenu> | ||
| ); | ||
| }; | ||
|
|
||
| export default DropdownField; | ||
| 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; |
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainFix the TypeScript The static analysis correctly flagged the use of - 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 🏁 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 🏁 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.tsLength of output: 2735 Specify correct Based on the File: src/components/Atoms/Controls/Input/formControls/radio_buttons.tsx - onClick={(opt: { value: any }) =>
+ onClick={(opt: { label: string; value: string; disabled?: boolean }) =>
handleChange({ target: { name, value: opt.value, type } })
}📝 Committable suggestion
Suggested change
🧰 Tools🪛 ESLint[error] 23-23: Unexpected any. Specify a different type. (@typescript-eslint/no-explicit-any) 🤖 Prompt for AI Agents |
||||||||||||||
| size="sm" | ||||||||||||||
| /> | ||||||||||||||
| ); | ||||||||||||||
| }; | ||||||||||||||
|
|
||||||||||||||
| export default RadioButton; | ||||||||||||||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainImport path concern for RenderFieldProps. The import path suggests RenderFieldProps is imported from 🏁 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 2Length of output: 6744 Update RenderFieldProps import in switch.tsx The • 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 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| /> | ||||||||||||||||||
| ); | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| export default SwitchField; | ||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Replace
anywith a union type for common input values.The
valueproperty should have a more specific type based on common input values.📝 Committable suggestion
🧰 Tools
🪛 ESLint
[error] 7-7: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
🤖 Prompt for AI Agents