-
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?
Refactored components and added chatbot #9
Conversation
📝 WalkthroughWalkthroughThis update introduces several new modular components, hooks, and utility functions, primarily for input controls, a floating chatbot widget, a custom date picker, and a shop picker UI. It also refactors existing monolithic components into smaller, reusable pieces, adds TypeScript type definitions, and updates export statements for improved structure and maintainability. Changes
Sequence Diagram(s)Floating Chatbot Widget (High-Level Interaction)sequenceDiagram
participant User
participant ChatBotWidget
participant MessageArea
participant BotLogic
User->>ChatBotWidget: Click open button
ChatBotWidget->>MessageArea: Display initial messages
User->>ChatBotWidget: Type message and send
ChatBotWidget->>MessageArea: Append user message
ChatBotWidget->>BotLogic: Process user message
BotLogic-->>ChatBotWidget: Generate bot reply
ChatBotWidget->>MessageArea: Append bot reply
Custom DatePicker (Preset Selection and Save)sequenceDiagram
participant User
participant DatePicker
participant DateRangePicker
participant ParentComponent
User->>DatePicker: Click trigger button
DatePicker->>DateRangePicker: Open calendar UI
User->>DateRangePicker: Select preset or dates
DateRangePicker->>DatePicker: onChange event
User->>DateRangePicker: Click Save
DateRangePicker->>DatePicker: onSave event
DatePicker->>ParentComponent: Notify with selected dates
ShopPicker (Shop Selection)sequenceDiagram
participant User
participant ShopPicker
participant ShopDropdown
participant ParentComponent
User->>ShopPicker: Click trigger button
ShopPicker->>ShopDropdown: Show dropdown menu
User->>ShopDropdown: Search or select shop
ShopDropdown->>ShopPicker: onChange event
ShopPicker->>ParentComponent: Notify with selected shop
Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 31
🧹 Nitpick comments (21)
src/hooks/useClickOutside.tsx (1)
23-23: Consider memoizing the handler to prevent unnecessary event listener re-registration.The
handlerdependency in theuseEffectcould cause performance issues if the handler function is recreated on every render, leading to frequent re-registration of event listeners.Consider one of these approaches:
Option 1: Use useCallback in the consuming component
const handleClickOutside = useCallback((event: MouseEvent | TouchEvent) => { // handler logic }, [/* dependencies */]);Option 2: Use useRef for the handler (internal optimization)
export function useClickOutside( ref: React.RefObject<HTMLElement>, handler: (event: MouseEvent | TouchEvent) => void, ) { + const handlerRef = useRef(handler); + handlerRef.current = handler; + useEffect(() => { const listener = (event: MouseEvent | TouchEvent) => { if (!ref.current || ref.current.contains(event.target as Node)) { return; } - handler(event); + handlerRef.current(event); }; document.addEventListener("mousedown", listener); document.addEventListener("touchstart", listener); return () => { document.removeEventListener("mousedown", listener); document.removeEventListener("touchstart", listener); }; - }, [ref, handler]); + }, [ref]); }src/components/custom/ShopPicker/components/StatusIndicator.tsx (1)
3-3: Consider using a proper TypeScript interface for consistency.While the inline prop typing works, using a proper interface would be more consistent with TypeScript best practices and other components in the codebase.
+interface StatusIndicatorProps { + isActive: boolean; +} + -export const StatusIndicator = ({ isActive }: { isActive: boolean }) => ( +export const StatusIndicator: React.FC<StatusIndicatorProps> = ({ isActive }) => (src/components/custom/ShopPicker/components/ShopItem/AnimatedChevron.tsx (1)
4-4: Consider using a proper TypeScript interface for consistency.Similar to other components, using a proper interface would improve consistency and type safety.
+interface AnimatedChevronProps { + isOpen: boolean; +} + -export const AnimatedChevron: React.FC<{ isOpen: boolean }> = ({ isOpen }) => ( +export const AnimatedChevron: React.FC<AnimatedChevronProps> = ({ isOpen }) => (src/components/Molecules/Chatbot/components/PreDefinedQuestions.tsx (1)
6-14: Consider using a more stable key for list items.Using array index as the key can cause React reconciliation issues if the questions array changes. Consider using a hash of the question text or a unique identifier if available.
- key={i} + key={q}If questions can be duplicate, consider using a combination approach:
- key={i} + key={`${q}-${i}`}src/utils/presetsToDateRange.ts (1)
4-32: Consider adding JSDoc documentation.The function would benefit from documentation explaining the expected behavior for each preset case.
+/** + * Converts a DatePickerPresets enum value to a date range tuple. + * @param preset - The preset to convert + * @returns A tuple of [startDate, endDate] as Date objects + */ export const presetsToDateRange = (preset: DatePickerPresets): [Date, Date] => {src/components/Molecules/Chatbot/components/ChatInput.tsx (1)
3-7: Consider extracting the props interface for better maintainability.While inline props typing works, extracting to a separate interface would improve readability and reusability.
+interface ChatInputProps { + input: string; + setInput: (val: string) => void; + onSend: () => void; +} + -export const ChatInput: React.FC<{ - input: string; - setInput: (val: string) => void; - onSend: () => void; -}> = ({ input, setInput, onSend }) => ( +export const ChatInput: React.FC<ChatInputProps> = ({ input, setInput, onSend }) => (src/components/Molecules/Chatbot/Chatbot.types.ts (1)
7-11: Consider adding more specific typing for better type safety.The FloatingChatbotWidgetProps interface could benefit from more specific types and default values.
export interface FloatingChatbotWidgetProps { initialMessages?: ChatMessage[]; predefinedQuestions?: string[]; - title?: string; + title?: string; + onMessageSend?: (message: string) => void; + onQuestionSelect?: (question: string) => void; + isOpen?: boolean; + onToggle?: (isOpen: boolean) => void; }Consider adding callback props for better component integration and state management.
src/components/Atoms/Controls/Input/components/Label.tsx (1)
19-19: Consider making CSS classes configurable.The hardcoded CSS classes might not be suitable for all use cases.
-const Label = ({ type, label, name }: LabelProps) => { +const Label = ({ type, label, name, className = "body-2 text-white" }: LabelProps) => {And update the interface:
interface LabelProps { type: // ... existing types label: string; name: string; + className?: string; }src/components/custom/ShopPicker/components/ShopItem/ShopEntryButton.tsx (1)
22-28: Consider extracting the complex className logic for better readability.The conditional className logic in the template literal is hard to read and maintain. Consider using a utility function or the
clsxlibrary for better clarity.+const getButtonClasses = (isSubShop: boolean) => { + const baseClasses = "w-full overflow-hidden text-ellipsis rounded text-left p-2 text-sm bg-white bg-opacity-10 text-white transition-all ease-in-out duration-200 flex items-center justify-between"; + return isSubShop ? `${baseClasses} pl-8` : baseClasses; +}; - className={`w-full overflow-hidden text-ellipsis rounded text-left p-2 text-sm bg-white bg-opacity-10 text-white transition-all ease-in-out duration-200 flex items-center justify-between ${ - isSubShop ? "pl-8" : "" - }`} + className={getButtonClasses(isSubShop)}src/components/custom/ShopPicker/components/ShopTriggerButton.tsx (2)
23-25: Consider extracting the tailwind-variants configuration for reusability.The
tvconfiguration is used inline, which works but could be extracted for better reusability if similar button styles are needed elsewhere.+const triggerButtonStyles = tv({ + base: "bg-white w-full bg-opacity-10 transition-all ease-in-out duration-300 text-white flex items-center justify-between body-3 rounded-xl p-3 gap-6", +}); - className={tv({ - base: "bg-white w-full bg-opacity-10 transition-all ease-in-out duration-300 text-white flex items-center justify-between body-3 rounded-xl p-3 gap-6", - })()} + className={triggerButtonStyles()}
35-37: Consider extracting status text logic for consistency.The status text logic is duplicated here and could be extracted into a utility function or the StatusIndicator component itself for better maintainability.
Consider creating a utility function:
const getStatusText = (isActive: boolean) => ({ text: isActive ? "Active" : "Inactive", className: isActive ? "text-success-500" : "" });Then use it in the component:
- <span className={activeShop.isActive ? "text-success-500" : ""}> - {activeShop.isActive ? "Active" : "Inactive"} - </span> + <span className={getStatusText(activeShop.isActive).className}> + {getStatusText(activeShop.isActive).text} + </span>src/utils/getValidationRules.ts (1)
35-38: Consider making phone number validation more flexible.The current regex only accepts exactly 10 digits, which may be too restrictive for international phone numbers or different formatting preferences.
Consider a more flexible pattern:
- value: /^[0-9]{10}$/, - message: "Invalid phone number (10 digits required)", + value: /^[\+]?[\d\s\-\(\)]{10,}$/, + message: "Invalid phone number format",src/components/Atoms/Controls/Input/formControls/dropdown.tsx (1)
17-17: Consider making the dropdown size configurable.The hardcoded
"lg"size reduces component flexibility. Consider adding asizeprop toRenderFieldPropsor making it configurable throughinputProps.<DropdownMenu disabled={disabled} - size="lg" + size={inputProps?.size || "lg"} menuList={dropdownOptions || []} onChange={(value) => handleChange(createCustomEvent(value.label))} className={className} >src/components/Atoms/Controls/Input/formControls/input.tsx (2)
32-32: Remove debug console.log statement.The console.log statement should be removed before production deployment.
const { showPassword, PasswordToggleIcon } = usePasswordToggle(); - console.log("type", type);
48-51: Ref handling logic can be simplified.The ref handling works correctly but could be more concise using a callback ref pattern.
- ref={(e) => { - if (typeof inputRef === "function") inputRef(e); - if (typeof ref === "function") ref(e); - }} + ref={(e) => { + inputRef?.(e); + ref?.(e); + }}src/components/custom/ShopPicker/components/ShopDropdown.tsx (1)
39-39: Extract long className to improve maintainability.The className string is very long and hard to read. Consider extracting it to a styled component or CSS class.
+const dropdownClass = "top-full right-0 mt-2 py-4 absolute rounded-md shadow-lg bg-tooltip bg-opacity-40 backdrop-blur-3xl z-[2000] w-full min-h-[30vh] max-h-[50vh] overflow-y-auto"; - className="top-full right-0 mt-2 py-4 absolute rounded-md shadow-lg bg-tooltip bg-opacity-40 backdrop-blur-3xl z-[2000] w-full min-h-[30vh] max-h-[50vh] overflow-y-auto" + className={dropdownClass}src/components/custom/ShopPicker/components/ShopItem/SubShopList.tsx (1)
38-38: Consider improving the fallback display for unnamed shops.The fallback text
${subShop.uid} [UNNAMED]might not be user-friendly. Consider a more descriptive fallback or handle this case upstream.- {subShop.name || `${subShop.uid} [UNNAMED]`} + {subShop.name || `Shop ${subShop.uid || 'Unknown'}`}src/components/Molecules/Chatbot/Chatbot.stories.tsx (1)
12-18: Consider extracting inline styles to CSS classes.The inline styles work but could be extracted to CSS classes for better maintainability and reusability.
+const storyDecorator = { + height: "100vh", + width: "100%", + position: "relative" as const, + backgroundColor: "#0a0f1c", + overflow: "hidden" as const, +}; - style={{ - height: "100vh", - width: "100%", - position: "relative", - backgroundColor: "#0a0f1c", - overflow: "hidden", - }} + style={storyDecorator}src/components/custom/ShopPicker/ShopPicker.types.ts (1)
11-11: Consider using a type alias instead of an empty interface extension.Since
SubShopdoesn't add any properties toBaseShop, a type alias would be clearer:-export interface SubShop extends BaseShop {} +export type SubShop = BaseShop;This makes it explicit that
SubShopis just an alias forBaseShop.src/components/custom/DatePicker/index.tsx (2)
23-23: Memoize the click outside handler to prevent unnecessary re-renders.The inline function passed to
useClickOutsidewill cause the hook's effect to re-run on every render, potentially leading to performance issues.+ const handleClickOutside = useCallback(() => setIsOpen(false), []); + - useClickOutside(triggerRef, () => setIsOpen(false)); + useClickOutside(triggerRef, handleClickOutside);
49-55: Consider potential performance impact of preset matching logic.The preset matching logic iterates through all presets on every date change, which could be inefficient with many presets. However, given the typical small number of date presets, this is likely acceptable.
For future optimization, consider memoizing the preset matching logic:
+ const findMatchingPreset = useCallback((dates: [Date | null, Date | null]) => { + const [start, end] = dates; + return Object.values(DatePickerPresets).find((preset) => { + const [presetStart, presetEnd] = presetsToDateRange(preset); + return ( + dayjs(start).isSame(presetStart, "day") && + dayjs(end).isSame(presetEnd, "day") + ); + }); + }, []);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (42)
src/components/Atoms/Controls/Input/Input.types.ts(1 hunks)src/components/Atoms/Controls/Input/components/Badge.tsx(1 hunks)src/components/Atoms/Controls/Input/components/FieldError.tsx(1 hunks)src/components/Atoms/Controls/Input/components/Label.tsx(1 hunks)src/components/Atoms/Controls/Input/components/Tooltip.tsx(1 hunks)src/components/Atoms/Controls/Input/components/renderFieldForInput.tsx(1 hunks)src/components/Atoms/Controls/Input/formControls/dropdown.tsx(1 hunks)src/components/Atoms/Controls/Input/formControls/input.tsx(1 hunks)src/components/Atoms/Controls/Input/formControls/radio_buttons.tsx(1 hunks)src/components/Atoms/Controls/Input/formControls/switch.tsx(1 hunks)src/components/Atoms/Controls/Input/index.tsx(3 hunks)src/components/Molecules/Chatbot/Chatbot.stories.tsx(1 hunks)src/components/Molecules/Chatbot/Chatbot.types.ts(1 hunks)src/components/Molecules/Chatbot/components/ChatBubble.tsx(1 hunks)src/components/Molecules/Chatbot/components/ChatHeader.tsx(1 hunks)src/components/Molecules/Chatbot/components/ChatInput.tsx(1 hunks)src/components/Molecules/Chatbot/components/PreDefinedQuestions.tsx(1 hunks)src/components/Molecules/Chatbot/index.tsx(1 hunks)src/components/Molecules/Datagrid/index.tsx(1 hunks)src/components/custom/DatePicker/DatePicker.stories.tsx(2 hunks)src/components/custom/DatePicker/DatePicker.types.ts(1 hunks)src/components/custom/DatePicker/components/AnimatePresenceWrapper/index.tsx(1 hunks)src/components/custom/DatePicker/components/DataTriggerButton.tsx(1 hunks)src/components/custom/DatePicker/components/DateRangePicker.tsx(1 hunks)src/components/custom/DatePicker/index.tsx(2 hunks)src/components/custom/ShopPicker/ShopPicker.types.ts(1 hunks)src/components/custom/ShopPicker/components/SearchInput.tsx(1 hunks)src/components/custom/ShopPicker/components/ShopDropdown.tsx(1 hunks)src/components/custom/ShopPicker/components/ShopItem/AnimatedChevron.tsx(1 hunks)src/components/custom/ShopPicker/components/ShopItem/ShopEntryButton.tsx(1 hunks)src/components/custom/ShopPicker/components/ShopItem/ShopItem.tsx(1 hunks)src/components/custom/ShopPicker/components/ShopItem/SubShopList.tsx(1 hunks)src/components/custom/ShopPicker/components/ShopLogo.tsx(1 hunks)src/components/custom/ShopPicker/components/ShopTriggerButton.tsx(1 hunks)src/components/custom/ShopPicker/components/StatusIndicator.tsx(1 hunks)src/components/custom/ShopPicker/index.tsx(1 hunks)src/components/index.tsx(1 hunks)src/hooks/useClickOutside.tsx(1 hunks)src/hooks/useFormField.tsx(1 hunks)src/hooks/usePasswordToggle.tsx(1 hunks)src/utils/getValidationRules.ts(1 hunks)src/utils/presetsToDateRange.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (17)
src/components/custom/ShopPicker/components/ShopLogo.tsx (1)
src/components/custom/ShopPicker/ShopPicker.types.ts (1)
ShopType(1-1)
src/components/Atoms/Controls/Input/formControls/switch.tsx (2)
src/components/Atoms/Controls/Input/Input.types.ts (1)
RenderFieldProps(50-79)src/components/Atoms/Controls/Input/Input.stories.tsx (1)
Switch(99-106)
src/components/Molecules/Chatbot/Chatbot.stories.tsx (1)
src/components/Molecules/Chatbot/Chatbot.types.ts (1)
FloatingChatbotWidgetProps(7-11)
src/components/Atoms/Controls/Input/components/Badge.tsx (1)
src/components/Atoms/Misc/Badge/index.tsx (1)
Badge(3-35)
src/components/Molecules/Chatbot/index.tsx (6)
src/components/Molecules/Chatbot/Chatbot.types.ts (2)
FloatingChatbotWidgetProps(7-11)ChatMessage(1-5)src/hooks/useClickOutside.tsx (1)
useClickOutside(3-24)src/components/Molecules/Chatbot/components/ChatHeader.tsx (1)
ChatHeader(3-13)src/components/Molecules/Chatbot/components/ChatBubble.tsx (1)
ChatBubble(3-13)src/components/Molecules/Chatbot/components/PreDefinedQuestions.tsx (1)
PredefinedQuestions(1-16)src/components/Molecules/Chatbot/components/ChatInput.tsx (1)
ChatInput(3-23)
src/components/custom/ShopPicker/components/ShopDropdown.tsx (3)
src/components/custom/ShopPicker/ShopPicker.types.ts (1)
Shop(13-15)src/components/custom/ShopPicker/components/SearchInput.tsx (1)
SearchInput(8-20)src/components/custom/ShopPicker/components/ShopItem/ShopItem.tsx (1)
ShopItem(8-64)
src/components/custom/ShopPicker/components/ShopItem/SubShopList.tsx (3)
src/components/custom/ShopPicker/ShopPicker.types.ts (2)
SubShop(11-11)BaseShop(3-9)src/components/custom/ShopPicker/components/ShopLogo.tsx (1)
ShopLogo(3-9)src/components/custom/ShopPicker/components/StatusIndicator.tsx (1)
StatusIndicator(3-8)
src/components/Atoms/Controls/Input/components/renderFieldForInput.tsx (1)
src/components/Atoms/Controls/Input/Input.types.ts (1)
RenderFieldProps(50-79)
src/components/Atoms/Controls/Input/formControls/dropdown.tsx (1)
src/components/Atoms/Controls/Input/Input.types.ts (1)
RenderFieldProps(50-79)
src/components/Atoms/Controls/Input/Input.types.ts (1)
src/types.ts (1)
MenuItem(32-36)
src/components/custom/ShopPicker/components/ShopItem/ShopItem.tsx (4)
src/components/custom/ShopPicker/ShopPicker.types.ts (3)
Shop(13-15)SubShop(11-11)BaseShop(3-9)src/components/custom/ShopPicker/components/ShopItem/ShopEntryButton.tsx (1)
ShopEntryButton(16-39)src/components/custom/ShopPicker/components/ShopItem/AnimatedChevron.tsx (1)
AnimatedChevron(4-11)src/components/custom/ShopPicker/components/ShopItem/SubShopList.tsx (1)
SubShopList(13-45)
src/components/Molecules/Chatbot/components/ChatBubble.tsx (1)
src/components/Molecules/Chatbot/Chatbot.types.ts (1)
ChatMessage(1-5)
src/components/custom/ShopPicker/components/ShopTriggerButton.tsx (3)
src/components/custom/ShopPicker/ShopPicker.types.ts (1)
Shop(13-15)src/components/custom/ShopPicker/components/ShopLogo.tsx (1)
ShopLogo(3-9)src/components/custom/ShopPicker/components/StatusIndicator.tsx (1)
StatusIndicator(3-8)
src/hooks/useFormField.tsx (1)
src/utils/getValidationRules.ts (1)
getValidationRules(11-70)
src/components/custom/ShopPicker/index.tsx (3)
src/components/custom/ShopPicker/ShopPicker.types.ts (3)
ShopPickerProps(17-25)Shop(13-15)SubShop(11-11)src/components/custom/ShopPicker/components/ShopTriggerButton.tsx (1)
ShopTriggerButton(15-44)src/components/custom/ShopPicker/components/ShopDropdown.tsx (1)
ShopDropdown(21-66)
src/components/Atoms/Controls/Input/index.tsx (3)
src/utils/getValidationRules.ts (1)
getValidationRules(11-70)src/components/Atoms/Controls/Input/Input.types.ts (1)
CustomChangeEvent(4-10)src/components/Atoms/Controls/Input/components/renderFieldForInput.tsx (1)
renderFieldForInput(7-22)
src/components/custom/DatePicker/index.tsx (4)
src/hooks/useClickOutside.tsx (1)
useClickOutside(3-24)src/utils/presetsToDateRange.ts (1)
presetsToDateRange(4-32)src/components/custom/DatePicker/components/AnimatePresenceWrapper/index.tsx (1)
AnimatePresenceWrapper(18-39)src/components/custom/DatePicker/components/DateRangePicker.tsx (1)
DateRangePicker(11-115)
🪛 ESLint
src/components/Atoms/Controls/Input/formControls/radio_buttons.tsx
[error] 23-23: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
src/components/Atoms/Controls/Input/Input.types.ts
[error] 7-7: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
[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)
[error] 78-78: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
src/hooks/useFormField.tsx
[error] 10-10: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
[error] 49-49: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
[error] 58-58: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
src/components/custom/DatePicker/components/DateRangePicker.tsx
[error] 21-21: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
src/components/custom/ShopPicker/ShopPicker.types.ts
[error] 8-8: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
src/components/Atoms/Controls/Input/index.tsx
[error] 50-50: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
🔇 Additional comments (51)
src/components/Molecules/Datagrid/index.tsx (1)
49-54: No-op whitespace change – looks goodOnly an empty line was inserted; no functional impact detected.
src/hooks/useClickOutside.tsx (1)
1-24: Well-implemented click outside detection hook.The implementation correctly handles both mouse and touch events, properly checks element containment, and includes proper cleanup. The type definitions are appropriate.
src/components/custom/ShopPicker/components/StatusIndicator.tsx (1)
1-8: Clean and focused component implementation.The component effectively serves its purpose with appropriate icon choice and conditional styling. The implementation is simple and maintainable.
src/components/custom/ShopPicker/components/ShopItem/AnimatedChevron.tsx (1)
5-11: Well-implemented animated chevron with smooth transitions.The animation duration and rotation values are appropriate for a chevron indicator. The use of framer-motion provides smooth, performant animations.
src/components/custom/DatePicker/DatePicker.stories.tsx (2)
2-4: Import updates align with refactored DatePicker structure.The separate imports for
DatePickerandDatePickerPresetscorrectly reflect the modular refactoring of the component.
349-351: No action needed: simplified onSave in DefaultDatePicker is intentional
TheDefaultDatePickerstory manages the date range via itsonChangehandler and only needs to close the picker on save—the selected dates are already stored in component state. The stripped-downonSave={() => setIsOpen(false)}in
• src/components/custom/DatePicker/DatePicker.stories.tsx lines 349–351
correctly matches the intended story behavior.src/components/Atoms/Controls/Input/components/FieldError.tsx (2)
3-6: Well-defined TypeScript interface.The interface properly defines optional props with appropriate types, making the component flexible and type-safe.
8-12: Excellent conditional rendering logic and error display.The component correctly handles the conditional rendering based on both disabled state and error existence, with appropriate styling for error messages.
src/components/custom/ShopPicker/components/ShopLogo.tsx (1)
1-9: LGTM! Well-structured logo component with proper accessibility.The component follows React best practices with proper TypeScript typing and accessibility considerations. The dynamic path generation and capitalized alt text are well-implemented.
src/components/Atoms/Controls/Input/components/Tooltip.tsx (1)
1-18: LGTM! Clean tooltip component with proper icon styling.The component is well-implemented with appropriate styling and good use of
flex-shrink-0to prevent icon distortion. The interface definition is clear and the component serves its purpose effectively.src/components/Molecules/Chatbot/components/ChatBubble.tsx (1)
1-13: LGTM! Well-designed chat bubble with clear user/bot differentiation.The component effectively uses conditional styling to differentiate between user and bot messages. The
whitespace-pre-lineclass is a good choice for preserving message formatting, and the template literal for className composition is clean and readable.src/components/index.tsx (1)
4-81: LGTM! Export updates align with component modularization.The addition of the
ChatBotexport and removal ofpresetsToDateRangealign well with the refactoring efforts described in the PR. The consistent use of double quotes and improved formatting enhance code readability.src/components/Molecules/Chatbot/components/PreDefinedQuestions.tsx (1)
1-16: Component structure looks good.The component is well-structured with clear prop types and appropriate styling. The hover effects and responsive design with flexbox are well implemented.
src/components/Molecules/Chatbot/components/ChatHeader.tsx (1)
3-13: Clean and well-structured header component.The component effectively provides a chat header with proper spacing, styling, and close functionality. The use of Tailwind classes and the FiX icon from react-icons is appropriate.
src/components/custom/DatePicker/components/DataTriggerButton.tsx (2)
13-18: Good date formatting logic.The conditional display text logic is well-implemented, showing a proper date range format when both dates are selected and a helpful placeholder otherwise.
20-28: Component structure and styling are well-designed.The component properly uses the Button atom with appropriate styling and icon integration. The gap spacing and opacity styling work well for the UI.
src/components/Atoms/Controls/Input/components/renderFieldForInput.tsx (2)
7-22: Excellent factory pattern implementation.The renderFieldForInput function provides a clean abstraction for rendering different input types. The switch statement is well-structured with appropriate cases and a sensible default. The use of spread props allows for maximum flexibility while maintaining type safety.
1-5: Good import organization and TypeScript usage.The imports are well-organized and the use of the RenderFieldProps interface ensures type safety throughout the component.
src/components/custom/ShopPicker/components/SearchInput.tsx (1)
3-6: Well-structured TypeScript interface.The Props interface is clearly defined with appropriate typing for the search functionality.
src/components/Atoms/Controls/Input/formControls/switch.tsx (1)
22-26: Well-implemented ref forwarding logic.The ref forwarding handles both callback refs and object refs correctly, ensuring compatibility with different ref usage patterns.
src/components/Atoms/Controls/Input/components/Label.tsx (3)
1-14: Well-structured TypeScript interface with comprehensive input types.The LabelProps interface properly defines all supported input types and required properties.
16-17: Good conditional rendering logic for specific input types.The logic to exclude labels for switch and radio types is appropriate since these input types typically handle their own labeling.
18-22: Proper accessibility implementation with htmlFor attribute.The label correctly uses the
htmlForattribute pointing to the input name, ensuring proper screen reader support.src/hooks/usePasswordToggle.tsx (2)
5-10: Good use of React hooks and performance optimization.The hook correctly uses
useStatefor state management anduseCallbackto memoize the toggle function, preventing unnecessary re-renders of components that consume this hook.
15-15: Excellent accessibility implementation.The
aria-labelattribute provides clear context about the button's current state and action, making the component accessible to screen readers.src/components/custom/ShopPicker/components/ShopItem/ShopEntryButton.tsx (3)
7-14: Well-structured TypeScript interface with good prop design.The props interface is clear and well-typed, with optional props having sensible defaults. The inclusion of
childrenfor custom indicators provides good extensibility.
32-32: Good fallback handling for unnamed shops.The fallback to
${shop.uid} [UNNAMED]provides a clear indication when shop names are missing, which is helpful for debugging and user experience.
28-28: Good use of framer-motion for user feedback.The
whileTapanimation provides nice tactile feedback for user interactions, enhancing the overall user experience.src/components/custom/ShopPicker/components/ShopTriggerButton.tsx (3)
9-13: Clean and well-typed component interface.The props interface is concise and properly typed, making the component's contract clear and maintainable.
30-30: Good fallback handling for unnamed shops.Consistent with the ShopEntryButton, the fallback to
${activeShop.uid} [UNNAMED]provides clear debugging information when shop names are missing.
39-41: Excellent animated chevron implementation.The smooth rotation animation with proper easing provides great visual feedback for the dropdown state.
src/components/Atoms/Controls/Input/formControls/radio_buttons.tsx (3)
4-11: Good use of TypeScript props interface.The component correctly uses the
RenderFieldPropsinterface, ensuring type safety and consistency with other input components.
14-19: Excellent disabled state propagation logic.The mapping logic correctly combines the individual option's disabled state with the overall component's disabled state, ensuring proper behavior in all scenarios.
20-20: Good type conversion for defaultValue.Converting
defaultValueto a string ensures compatibility with the Radio component's expected prop type.src/utils/getValidationRules.ts (2)
54-63: Comprehensive password validation implementation.The password validation logic correctly checks for all required character types (uppercase, lowercase, numbers, special characters) and provides clear error messaging.
11-17: Well-structured function interface with good defaults.The function parameters are well-typed and provide sensible defaults, making it easy to use while remaining flexible.
src/components/Atoms/Controls/Input/formControls/dropdown.tsx (1)
4-25: Component implementation looks solid.The dropdown field component is well-structured with proper prop destructuring, fallback logic for display values, and integration with the existing input system architecture.
src/components/Atoms/Controls/Input/formControls/input.tsx (1)
5-56: Excellent input component implementation.The component demonstrates good practices with:
- Proper use of tailwind-variants for conditional styling
- Password visibility toggle integration
- Error state handling
- Accessibility considerations with proper input attributes
src/components/custom/ShopPicker/components/ShopDropdown.tsx (1)
21-66: Well-structured dropdown component with smooth animations.The component effectively uses framer-motion for animations, provides good separation of concerns with SearchInput and ShopItem components, and handles the dropdown state properly.
src/components/custom/ShopPicker/components/ShopItem/SubShopList.tsx (1)
13-45: Excellent sub-shop list implementation.The component provides smooth animations, proper filtering, and integrates well with the ShopLogo and StatusIndicator components. The framer-motion animations enhance the user experience.
src/components/Molecules/Chatbot/Chatbot.stories.tsx (1)
5-74: Excellent Storybook story configuration.The story provides comprehensive documentation, proper TypeScript typing, and realistic props that showcase the component's capabilities. The decorator creates an appropriate environment for testing the floating chatbot widget.
src/components/custom/DatePicker/components/AnimatePresenceWrapper/index.tsx (1)
1-40: Well-structured animation wrapper component.This is a clean, reusable component that encapsulates animation logic effectively. The TypeScript interfaces are well-defined, the origin-based positioning is handled elegantly with the map, and the animation configuration is appropriate for dropdown-style UI elements.
src/components/custom/ShopPicker/components/ShopItem/ShopItem.tsx (1)
18-64: Excellent component structure with proper optimization.This component demonstrates good React practices:
- Proper use of
React.memofor performance optimization- Correct
useCallbackimplementation with appropriate dependencies- Clean separation of concerns with delegated rendering to sub-components
- Effective search filtering logic that handles both parent and child shops
- Proper conditional rendering based on search results
The integration with framer-motion for animations is well-implemented, and the component follows the single responsibility principle effectively.
src/components/custom/DatePicker/components/DateRangePicker.tsx (1)
42-114: Well-implemented date range picker with good UX features.The component provides excellent user experience with:
- Dual-month horizontal calendar layout
- Preset date ranges for quick selection
- Proper date formatting and validation
- Conditional rendering of Cancel/Save buttons
- Maximum date restriction to prevent future dates
- 3-month maximum range validation
The integration with dayjs for date formatting and the preset handling logic is well-implemented.
src/components/Molecules/Chatbot/index.tsx (1)
11-95: Excellent chatbot implementation with clean architecture.This component demonstrates excellent React practices:
- Proper state management with logical separation (isOpen, messages, input)
- Good use of custom hooks (
useClickOutside) for behavior encapsulation- Clean component composition with well-separated concerns
- Appropriate animation implementation with framer-motion
- Sensible bot reply logic with keyword matching for demo purposes
- Proper event handling and state updates
The fixed positioning and z-index management for the floating widget is well-implemented, and the integration with sub-components maintains clean separation of concerns.
src/hooks/useFormField.tsx (1)
15-70: Well-designed form field hook with good react-hook-form integration.This hook provides excellent abstraction for form field management:
- Proper integration with react-hook-form using
useFormContext- Good separation of concerns with external validation utilities
- Effective handling of both native and custom events
- Proper field registration and state management
- Useful helper functions for creating custom events
The logic for resetting fields when disabled state changes and the validation triggering on change events are well-implemented.
src/components/custom/DatePicker/DatePicker.types.ts (1)
1-60: Well-structured type definitions with excellent documentation.The type definitions are clean, properly typed, and well-documented with JSDoc comments. Good use of enums for the presets.
src/components/custom/ShopPicker/index.tsx (1)
1-95: Excellent refactoring with improved modularity.The component has been successfully modularized with:
- Clean separation of concerns with extracted subcomponents
- Proper use of React hooks for optimization
- Maintained backward compatibility with the same API
The refactoring improves maintainability and follows React best practices.
src/components/Atoms/Controls/Input/index.tsx (1)
1-119: Excellent modularization of the Input component.The refactoring successfully:
- Extracts reusable UI components (Label, Badge, Tooltip, FieldError)
- Delegates field rendering to specialized components
- Maintains clean integration with react-hook-form
- Improves maintainability and testability
Great job on the component architecture!
src/components/custom/DatePicker/index.tsx (2)
44-60: LGTM! Well-implemented preset matching logic.The
handleRangeChangecallback correctly updates the date range and automatically detects matching presets, providing a smooth user experience. The fallback toDatePickerPresets.customis appropriate when no preset matches.
62-85: Excellent modular composition with proper component separation.The render logic effectively demonstrates the refactoring benefits by composing specialized components (
DateTriggerButton,AnimatePresenceWrapper,DateRangePicker) while maintaining clean prop passing and state management.
| 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; |
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.
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:
- Renaming this to
InputBadgeto indicate its specific use case - Extending the existing
Badgecomponent to support your styling needs - Using the existing
Badgecomponent 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.
| 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.
| @@ -0,0 +1,31 @@ | |||
| import React from "react"; | |||
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.
Fix filename typo.
The filename "DataTriggerButton.tsx" should be "DateTriggerButton.tsx" to match the component name and purpose.
🤖 Prompt for AI Agents
In src/components/custom/DatePicker/components/DataTriggerButton.tsx at line 1,
the filename has a typo and should be renamed from "DataTriggerButton.tsx" to
"DateTriggerButton.tsx" to correctly reflect the component's name and purpose.
Rename the file accordingly to fix this inconsistency.
| case DatePickerPresets.lastThreeMonths: | ||
| return [ | ||
| now.subtract(3, "month").startOf("month").toDate(), | ||
| now.endOf("month").toDate(), | ||
| ]; |
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
Review the lastThreeMonths logic.
The current implementation may not provide exactly 3 months. It starts from 3 months ago at the beginning of that month but ends at the end of the current month, which could be more than 3 months.
Consider this approach for exactly 3 months:
case DatePickerPresets.lastThreeMonths:
return [
- now.subtract(3, "month").startOf("month").toDate(),
- now.endOf("month").toDate(),
+ now.subtract(3, "month").startOf("day").toDate(),
+ now.endOf("day").toDate(),
];Or if you want full months, consider:
case DatePickerPresets.lastThreeMonths:
return [
- now.subtract(3, "month").startOf("month").toDate(),
- now.endOf("month").toDate(),
+ now.subtract(2, "month").startOf("month").toDate(),
+ now.endOf("month").toDate(),
];Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/utils/presetsToDateRange.ts around lines 24 to 28, the lastThreeMonths
case returns a range from the start of the month three months ago to the end of
the current month, which can exceed exactly three months. To fix this, adjust
the end date to be the end of the month two months ago instead of the current
month, so the range covers exactly three full months. Modify the end date
calculation accordingly to ensure the date range spans exactly three months.
| <button | ||
| className="ml-2 p-2 bg-primary-500 rounded-lg text-white hover:bg-primary-600 transition" | ||
| onClick={onSend} | ||
| > | ||
| <FiSend className="w-4 h-4" /> | ||
| </button> |
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
Add accessibility attributes to the send button.
The send button needs proper labeling for screen readers and keyboard navigation support.
<button
+ type="button"
+ aria-label="Send message"
+ disabled={!input.trim()}
className="ml-2 p-2 bg-primary-500 rounded-lg text-white hover:bg-primary-600 transition"
onClick={onSend}
>
<FiSend className="w-4 h-4" />
</button>📝 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.
| <button | |
| className="ml-2 p-2 bg-primary-500 rounded-lg text-white hover:bg-primary-600 transition" | |
| onClick={onSend} | |
| > | |
| <FiSend className="w-4 h-4" /> | |
| </button> | |
| <button | |
| type="button" | |
| aria-label="Send message" | |
| disabled={!input.trim()} | |
| className="ml-2 p-2 bg-primary-500 rounded-lg text-white hover:bg-primary-600 transition" | |
| onClick={onSend} | |
| > | |
| <FiSend className="w-4 h-4" /> | |
| </button> |
🤖 Prompt for AI Agents
In src/components/Molecules/Chatbot/components/ChatInput.tsx between lines 16
and 21, the send button lacks accessibility attributes. Add an aria-label
attribute with a descriptive label like "Send message" to the button element to
improve screen reader support and ensure it is keyboard accessible.
| <input | ||
| className="flex-1 bg-white/10 text-white placeholder-white/50 rounded-lg px-4 py-2 text-sm focus:outline-none" | ||
| placeholder="Type your message..." | ||
| value={input} | ||
| onChange={(e) => setInput(e.target.value)} | ||
| onKeyDown={(e) => e.key === "Enter" && onSend()} | ||
| /> |
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
Add accessibility attributes for better user experience.
The input field is missing important accessibility attributes that would improve screen reader support.
<input
+ id="chat-input"
+ aria-label="Type your message"
+ aria-describedby="chat-input-help"
className="flex-1 bg-white/10 text-white placeholder-white/50 rounded-lg px-4 py-2 text-sm focus:outline-none"
placeholder="Type your message..."
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && onSend()}
/>📝 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.
| <input | |
| className="flex-1 bg-white/10 text-white placeholder-white/50 rounded-lg px-4 py-2 text-sm focus:outline-none" | |
| placeholder="Type your message..." | |
| value={input} | |
| onChange={(e) => setInput(e.target.value)} | |
| onKeyDown={(e) => e.key === "Enter" && onSend()} | |
| /> | |
| <input | |
| id="chat-input" | |
| aria-label="Type your message" | |
| aria-describedby="chat-input-help" | |
| className="flex-1 bg-white/10 text-white placeholder-white/50 rounded-lg px-4 py-2 text-sm focus:outline-none" | |
| placeholder="Type your message..." | |
| value={input} | |
| onChange={(e) => setInput(e.target.value)} | |
| onKeyDown={(e) => e.key === "Enter" && onSend()} | |
| /> |
🤖 Prompt for AI Agents
In src/components/Molecules/Chatbot/components/ChatInput.tsx around lines 9 to
15, the input element lacks accessibility attributes. Add attributes such as
aria-label or aria-labelledby to describe the input's purpose for screen
readers. This will improve accessibility and user experience for assistive
technology users.
| const handleSearchChange = useCallback( | ||
| (e: React.ChangeEvent<HTMLInputElement>) => { | ||
| const newTerm = e.target.value; | ||
| setSearchTerm(newTerm); | ||
| setOpenShops(newTerm ? matchingShops : new Set()); | ||
| }, | ||
| [matchingShops], | ||
| ); |
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.
Potential stale closure issue with matchingShops dependency.
The handleSearchChange callback depends on matchingShops, but since matchingShops is recalculated on every render when shopList or searchTerm changes, this could lead to stale closures.
Consider refactoring to calculate matching shops inline:
const handleSearchChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const newTerm = e.target.value;
setSearchTerm(newTerm);
- setOpenShops(newTerm ? matchingShops : new Set());
+ if (!newTerm) {
+ setOpenShops(new Set());
+ } else {
+ const term = newTerm.toLowerCase();
+ setOpenShops(
+ new Set(
+ shopList
+ .filter(
+ (shop) =>
+ shop.name.toLowerCase().includes(term) ||
+ shop.subShops?.some((subShop) =>
+ subShop.name.toLowerCase().includes(term)
+ )
+ )
+ .map((shop) => shop.name)
+ )
+ );
+ }
},
- [matchingShops],
+ [shopList],
);🤖 Prompt for AI Agents
In src/components/custom/ShopPicker/index.tsx around lines 44 to 51, the
handleSearchChange callback uses matchingShops from the closure, which can
become stale because matchingShops is recalculated on each render. To fix this,
remove matchingShops from the dependency array and instead calculate the
matching shops inside the handleSearchChange function itself based on the
current input value. This ensures the callback always uses the latest matching
shops without stale closure issues.
| const createCustomEvent = (value: any): CustomChangeEvent => ({ | ||
| target: { | ||
| name, | ||
| value, | ||
| type, | ||
| }, | ||
| }); |
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 any with a union type for better type safety.
The value parameter should have a more specific type.
- const createCustomEvent = (value: any): CustomChangeEvent => ({
+ const createCustomEvent = (value: string | number | boolean | string[]): CustomChangeEvent => ({
target: {
name,
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.
| const createCustomEvent = (value: any): CustomChangeEvent => ({ | |
| target: { | |
| name, | |
| value, | |
| type, | |
| }, | |
| }); | |
| const createCustomEvent = ( | |
| value: string | number | boolean | string[] | |
| ): CustomChangeEvent => ({ | |
| target: { | |
| name, | |
| value, | |
| type, | |
| }, | |
| }); |
🧰 Tools
🪛 ESLint
[error] 50-50: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
🤖 Prompt for AI Agents
In src/components/Atoms/Controls/Input/index.tsx around lines 50 to 56, replace
the type of the `value` parameter in the `createCustomEvent` function from `any`
to a union type that accurately reflects the possible types `value` can have
(e.g., string | number | boolean). This will improve type safety by explicitly
specifying the allowed types instead of using `any`.
| React.useEffect(() => { | ||
| renderInput(); | ||
| if (!disabled) resetField(name, { defaultValue: props.defaultValue }); | ||
| if (!disabled) { | ||
| resetField(name, { defaultValue: props.defaultValue }); | ||
| } | ||
| }, [disabled]); |
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.
Add missing dependencies to useEffect.
The effect uses resetField, name, and props.defaultValue but only includes disabled in the dependency array.
React.useEffect(() => {
if (!disabled) {
resetField(name, { defaultValue: props.defaultValue });
}
- }, [disabled]);
+ }, [disabled, name, props.defaultValue, resetField]);📝 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.
| React.useEffect(() => { | |
| renderInput(); | |
| if (!disabled) resetField(name, { defaultValue: props.defaultValue }); | |
| if (!disabled) { | |
| resetField(name, { defaultValue: props.defaultValue }); | |
| } | |
| }, [disabled]); | |
| React.useEffect(() => { | |
| if (!disabled) { | |
| resetField(name, { defaultValue: props.defaultValue }); | |
| } | |
| }, [disabled, name, props.defaultValue, resetField]); |
🤖 Prompt for AI Agents
In src/components/Atoms/Controls/Input/index.tsx around lines 75 to 79, the
useEffect hook depends on resetField, name, and props.defaultValue but only
includes disabled in its dependency array. To fix this, add resetField, name,
and props.defaultValue to the dependency array to ensure the effect runs
correctly when any of these values change.
| {...props} | ||
| selectedPreset={selectedPreset} | ||
| isOpen={isOpen} | ||
| setIsOpen={setIsOpen} |
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
Remove redundant setIsOpen prop to DateRangePicker.
The DateRangePicker component receives both isOpen and setIsOpen props, but the parent component already manages the isOpen state. This creates unnecessary coupling and potential confusion.
<DateRangePicker
{...props}
selectedPreset={selectedPreset}
isOpen={isOpen}
- setIsOpen={setIsOpen}
onCancel={handleCancel}
onSave={handleSave}
onChange={handleRangeChange}
/>📝 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.
| setIsOpen={setIsOpen} | |
| <DateRangePicker | |
| {...props} | |
| selectedPreset={selectedPreset} | |
| isOpen={isOpen} | |
| onCancel={handleCancel} | |
| onSave={handleSave} | |
| onChange={handleRangeChange} | |
| /> |
🤖 Prompt for AI Agents
In src/components/custom/DatePicker/index.tsx at line 77, remove the redundant
setIsOpen prop passed to the DateRangePicker component since the parent already
manages the isOpen state. This will simplify the component interface and reduce
unnecessary coupling by only passing the isOpen prop.
| export const DatePicker: React.FC< | ||
| Omit<DatePickerProps, "isOpen" | "setIsOpen"> | ||
| > = (props) => { | ||
| const [selectedPreset, setSelectedPreset] = useState(props.selectedPreset); |
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
Handle prop changes for selectedPreset to prevent stale state.
The selectedPreset state is initialized with props.selectedPreset but won't update if the parent component changes this prop, potentially causing synchronization issues.
- const [selectedPreset, setSelectedPreset] = useState(props.selectedPreset);
+ const [selectedPreset, setSelectedPreset] = useState(props.selectedPreset);
+
+ useEffect(() => {
+ setSelectedPreset(props.selectedPreset);
+ }, [props.selectedPreset]);Don't forget to import useEffect:
-import { useState, useRef, useCallback } from "react";
+import { useState, useRef, useCallback, useEffect } from "react";📝 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.
| const [selectedPreset, setSelectedPreset] = useState(props.selectedPreset); | |
| // At the top of your file, include useEffect | |
| -import { useState, useRef, useCallback } from "react"; | |
| +import { useState, useRef, useCallback, useEffect } from "react"; | |
| // …inside your component body… | |
| - const [selectedPreset, setSelectedPreset] = useState(props.selectedPreset); | |
| + const [selectedPreset, setSelectedPreset] = useState(props.selectedPreset); | |
| + useEffect(() => { | |
| + setSelectedPreset(props.selectedPreset); | |
| + }, [props.selectedPreset]); | |
| // …the rest of your component… |
🤖 Prompt for AI Agents
In src/components/custom/DatePicker/index.tsx at line 17, the selectedPreset
state is initialized from props but does not update when props.selectedPreset
changes. To fix this, import useEffect and add an effect that listens for
changes to props.selectedPreset and updates the selectedPreset state
accordingly, ensuring the component stays in sync with prop changes.
This PR includes the requested changes as per the frontend task:
Summary by CodeRabbit
New Features
Refactor
Documentation
Style
Chores