Skip to content

Add DateRangePicker Component for Date Range Selection #2757

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

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from

Conversation

mralaminahamed
Copy link
Member

@mralaminahamed mralaminahamed commented Jun 2, 2025

All Submissions:

  • My code follow the WordPress' coding standards
  • My code satisfies feature requirements
  • My code is tested
  • My code passes the PHPCS tests
  • My code has proper inline documentation
  • I've included related pull request(s) (optional)
  • I've included developer documentation (optional)
  • I've added proper labels to this pull request

Changes proposed in this Pull Request:

This PR introduces a new DateRangePicker component to the Dokan frontend component library. The component provides a unified, accessible date range selection interface that wraps the WooCommerce DateRange component within a Headless UI Popover for enhanced positioning and user interaction.

Key Features Added:

  • Reusable date range picker component with calendar UI
  • Integration with WooCommerce's existing DateRange component
  • Headless UI Popover implementation for better UX
  • Customizable date validation and formatting
  • Full TypeScript support with proper interface definitions
  • WordPress hooks integration for extensibility
  • Accessible keyboard navigation support
  • Responsive design with proper SCSS styling

Related Pull Request(s)

Closes

  • Closes # (Issue number to be added)

How to test the changes in this Pull Request:

  1. Basic Functionality Test:

    # Navigate to any Dokan admin page that uses date filtering
    # Import and use the DateRangePicker component
  2. Component Integration Test:

    import { DateRangePicker } from '@dokan/components';
    
    // Test with basic props
    <DateRangePicker
      show={isOpen}
      setShow={setIsOpen}
      after="2023-01-01"
      before="2023-01-31"
      onUpdate={(update) => console.log(update)}
    >
      <button>Select Date Range</button>
    </DateRangePicker>
  3. Accessibility Test:

    • Test keyboard navigation (Tab, Enter, Escape keys)
    • Verify screen reader compatibility
    • Test focus management
  4. Date Validation Test:

    // Test with isInvalidDate prop
    isInvalidDate={(date) => new Date(date) > new Date()}
  5. Styling Test:

    • Verify component matches Dokan's design system
    • Test responsive behavior on different screen sizes
    • Check CSS variables integration

Changelog entry

DateRangePicker Component Added

Added a new unified DateRangePicker component that provides a consistent date range selection interface across the Dokan admin. The component wraps WooCommerce's DateRange

Summary by CodeRabbit

  • New Features
    • Introduced a new DateRangePicker component for selecting date ranges with enhanced UI and customization options.
  • Documentation
    • Added comprehensive documentation for the DateRangePicker component, including usage examples, props, customization, and best practices.
  • Style
    • Added custom styles for the DateRangePicker to improve calendar appearance and interaction.
  • Chores
    • Added TypeScript type declarations for the DateRange component to enhance type safety and developer experience.

@mralaminahamed mralaminahamed requested a review from mrabbani June 2, 2025 11:28
@mralaminahamed mralaminahamed self-assigned this Jun 2, 2025
Copy link
Contributor

coderabbitai bot commented Jun 2, 2025

Walkthrough

A new DateRangePicker React component is introduced, along with its SCSS styles and TypeScript typings for dependencies. The component is exported from the main index and thoroughly documented in the frontend components documentation, detailing its usage, props, customization, and best practices. No existing components are modified.

Changes

File(s) Change Summary
src/components/date-range-picker/index.tsx, style.scss Added new DateRangePicker React component and its associated SCSS styles for calendar UI.
src/components/index.tsx Exported the new DateRangePicker component from the main components index.
docs/frontend/components.md Extended documentation to include the new DateRangePicker with usage, props, customization, and best practices.
src/definitions/woocommerce-components.d.ts Added TypeScript declaration for the DateRange component from @woocommerce/components.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DateRangePicker
    participant HeadlessUIPopover
    participant WooDateRange

    User->>DateRangePicker: Interacts (open/close, select dates)
    DateRangePicker->>HeadlessUIPopover: Controls popover visibility
    HeadlessUIPopover->>WooDateRange: Renders date selection UI
    WooDateRange-->>DateRangePicker: Returns selected date range
    DateRangePicker-->>User: Triggers onUpdate callback with new range
Loading

Suggested labels

QA approved, :+1: Dev Review Done, Upcoming Release

Suggested reviewers

  • mrabbani

Poem

In a meadow of code, a picker appears,
Dates now in range, the UI cheers!
With popovers popping and calendars bright,
Selecting your span is pure delight.
Docs are expanded, the types are just right—
This bunny hops on, with features in sight!
🗓️✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-19T05_44_06_796Z-debug-0.log

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@mralaminahamed mralaminahamed added the In Progress The issues is being worked on label Jun 2, 2025
@mralaminahamed mralaminahamed removed the request for review from mrabbani June 2, 2025 11:31
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
src/components/DateRangePicker/style.scss (1)

1-29: Add missing semicolons for consistency and consider reducing !important usage.

The SCSS implementation looks good overall, but there are some style consistency issues and potential specificity concerns.

Apply this diff to add missing semicolons for consistency:

 .dokan-layout {
     .dokan-date-range-picker {
         .woocommerce-calendar__react-dates .CalendarDay__selected_span {
             background: var(--dokan-button-background-color, #7047EB) !important;
-            border: 1px solid #ccc
+            border: 1px solid #ccc;
         }

         .woocommerce-calendar__react-dates .CalendarDay__selected_span:hover {
             background: var(--dokan-button-hover-background-color, #502BBF) !important;
-            border: 1px solid #f0f0f0
+            border: 1px solid #f0f0f0;
         }

         .woocommerce-calendar__react-dates .CalendarDay__selected {
             background: var(--dokan-button-background-color, #7047EB) !important;
-            border: 1px solid #ccc
+            border: 1px solid #ccc;
         }

         .woocommerce-calendar__react-dates .CalendarDay__selected:hover {
             background: var(--dokan-button-hover-background-color, #502BBF) !important;
-            border: 1px solid #f0f0f0
+            border: 1px solid #f0f0f0;
         }

         .woocommerce-calendar__react-dates .CalendarDay__hovered_span {
             background: var(--dokan-button-hover-background-color, #502BBF) !important;
             border: 1px solid #f0f0f0;
-            color: #fff
+            color: #fff;
         }
     }
 }

Note on !important usage: While the !important declarations are likely necessary to override WooCommerce's calendar styles, consider if the specificity can be increased instead to avoid potential future styling conflicts.

src/components/DateRangePicker/index.tsx (1)

57-57: Use consistent prop source for children.

For consistency, use updatedProps.children since other props use the filtered version.

Apply this diff for consistency:

-                { props.children ?? '' }
+                { updatedProps.children ?? '' }
docs/frontend/components.md (1)

739-740: Fix grammar issues in the best practices section.

Apply the grammar corrections identified by static analysis.

Apply this diff to fix the grammar:

 2. **Date Validation**
-    - Use `isInvalidDate` prop to restrict date selection where needed
-    - Consider business rules when implementing validation logic
+    - Use the `isInvalidDate` prop to restrict date selection where needed
+    - Consider to implement business rules when implementing validation logic
🧰 Tools
🪛 LanguageTool

[uncategorized] ~739-~739: You might be missing the article “the” here.
Context: ...anges 2. Date Validation - Use isInvalidDate prop to restrict date sel...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[grammar] ~740-~740: Did you mean “to Consider”?
Context: ...trict date selection where needed - Consider business rules when implementing valida...

(MISSING_TO_BEFORE_A_VERB)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d02fc8 and 85950d9.

📒 Files selected for processing (4)
  • docs/frontend/components.md (3 hunks)
  • src/components/DateRangePicker/index.tsx (1 hunks)
  • src/components/DateRangePicker/style.scss (1 hunks)
  • src/components/index.tsx (1 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/frontend/components.md

[uncategorized] ~739-~739: You might be missing the article “the” here.
Context: ...anges 2. Date Validation - Use isInvalidDate prop to restrict date sel...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[grammar] ~740-~740: Did you mean “to Consider”?
Context: ...trict date selection where needed - Consider business rules when implementing valida...

(MISSING_TO_BEFORE_A_VERB)

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: e2e tests (1, 3)
  • GitHub Check: e2e tests (2, 3)
  • GitHub Check: e2e tests (3, 3)
  • GitHub Check: api tests (1, 1)
🔇 Additional comments (2)
src/components/index.tsx (1)

27-27: LGTM!

The export addition follows the existing pattern and correctly exposes the DateRangePicker component.

docs/frontend/components.md (1)

573-750: Excellent comprehensive documentation.

The documentation is thorough and well-structured, covering all essential aspects including features, usage examples, props, customization, and best practices. This will be very helpful for developers using the component.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~739-~739: You might be missing the article “the” here.
Context: ...anges 2. Date Validation - Use isInvalidDate prop to restrict date sel...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[grammar] ~740-~740: Did you mean “to Consider”?
Context: ...trict date selection where needed - Consider business rules when implementing valida...

(MISSING_TO_BEFORE_A_VERB)

Comment on lines 47 to 49
const updatedProps: any = applyFilters( 'dokan_date_range_picker_props', {
...props,
} );
Copy link
Contributor

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 avoiding 'any' type.

Consider using a more specific type instead of any for better type safety.

Apply this diff to improve type safety:

-    const updatedProps: any = applyFilters( 'dokan_date_range_picker_props', {
+    const updatedProps: DateRangePickerProps = applyFilters( 'dokan_date_range_picker_props', {
         ...props,
-    } );
+    } ) as DateRangePickerProps;

This provides better TypeScript support while acknowledging that applyFilters returns unknown 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
const updatedProps: any = applyFilters( 'dokan_date_range_picker_props', {
...props,
} );
const updatedProps: DateRangePickerProps = applyFilters( 'dokan_date_range_picker_props', {
...props,
} ) as DateRangePickerProps;
🤖 Prompt for AI Agents
In src/components/DateRangePicker/index.tsx around lines 47 to 49, replace the
use of 'any' type for the variable updatedProps with a more specific type that
matches the expected shape of the props object. You can define or import an
appropriate interface or type for the props and use it instead of 'any' to
improve type safety. If applyFilters returns an unknown type, use a type
assertion or a generic type parameter to cast the result safely to the expected
props type.

Comment on lines 9 to 11
// @ts-ignore
// eslint-disable-next-line import/no-unresolved
import { DateRange } from '@woocommerce/components';
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Address TypeScript import issue for WooCommerce components.

The @ts-ignore comment suggests type definition issues. Consider adding proper type declarations.

Verify if WooCommerce provides official type declarations or if custom types need to be created:


🏁 Script executed:

#!/bin/bash
# Search for any existing type declarations for WooCommerce components
fd -e .d.ts | xargs rg -l "woocommerce.*DateRange|DateRange.*woocommerce" || echo "No existing type declarations found"

# Check if there are any other WooCommerce component imports in the codebase
rg -A 2 -B 2 "@woocommerce/components"

Length of output: 17855


Add custom type declarations for DateRange instead of using @ts-ignore

No .d.ts files were found for the DateRange export in @woocommerce/components. Rather than silencing the import error, please:

  • Create an ambient declaration file (e.g. src/types/woocommerce-components.d.ts) with a module for @woocommerce/components that declares DateRange and its props.
  • Remove the @ts-ignore and eslint-disable-next-line import/no-unresolved comments in src/components/DateRangePicker/index.tsx.

Example src/types/woocommerce-components.d.ts:

declare module '@woocommerce/components' {
  import type { FC } from 'react';

  export interface DateRangeProps {
    /** selected start date */
    startDate: Date;
    /** selected end date */
    endDate: Date;
    onChange: (range: { startDate: Date; endDate: Date }) => void;
    /** add other props as needed */
  }

  export const DateRange: FC<DateRangeProps>;
}

Then update src/components/DateRangePicker/index.tsx:

- // @ts-ignore
- // eslint-disable-next-line import/no-unresolved
  import { DateRange } from '@woocommerce/components';

Removing these comments once the types are declared will restore full type safety.

🤖 Prompt for AI Agents
In src/components/DateRangePicker/index.tsx around lines 9 to 11, the import of
DateRange from '@woocommerce/components' uses @ts-ignore and eslint-disable
comments due to missing type declarations. To fix this, create a new ambient
declaration file, for example src/types/woocommerce-components.d.ts, declaring
the module '@woocommerce/components' and defining the DateRange component and
its props with proper TypeScript types. After adding this declaration file,
remove the @ts-ignore and eslint-disable-next-line comments from the import
statement in index.tsx to restore full type safety and proper linting.

Comment on lines 44 to 45
const ref = useRef( null );
useOnClickOutside( ref, () => props.setShow( ! props.show ) );
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix the useOnClickOutside hook logic.

The current implementation has inverted logic that will toggle the popover state instead of closing it when clicking outside.

Apply this diff to fix the hook logic:

 const DateRangePicker = ( props: DateRangePickerProps ): JSX.Element => {
     const ref = useRef( null );
-    useOnClickOutside( ref, () => props.setShow( ! props.show ) );
+    useOnClickOutside( ref, () => props.setShow( false ) );

The hook should always close the popover when clicking outside, not toggle its current state.

📝 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
const ref = useRef( null );
useOnClickOutside( ref, () => props.setShow( ! props.show ) );
const DateRangePicker = ( props: DateRangePickerProps ): JSX.Element => {
const ref = useRef( null );
- useOnClickOutside( ref, () => props.setShow( ! props.show ) );
+ useOnClickOutside( ref, () => props.setShow( false ) );
// ...rest of implementation
🤖 Prompt for AI Agents
In src/components/DateRangePicker/index.tsx around lines 44 to 45, the
useOnClickOutside hook currently toggles the popover visibility state when
clicking outside, which is incorrect. Change the callback function passed to
useOnClickOutside so that it always sets the popover visibility to false,
ensuring the popover closes on outside clicks instead of toggling.

Comment on lines +590 to +651
```jsx
import {useState} from '@wordpress/element';
import {DateRangePicker} from '@dokan/components';
import {dateI18n, getSettings} from '@wordpress/date';

const ReportFilter = () => {
const [isOpen, setIsOpen] = useState(false);
const [after, setAfter] = useState('2023-01-01');
const [afterText, setAfterText] = useState('');
const [before, setBefore] = useState('2023-01-31');
const [beforeText, setBeforeText] = useState('');
const [focusedInput, setFocusedInput] = useState('startDate');

return (
<DateRangePicker
show={isOpen}
after={after}
setShow={setIsOpen}
afterText={afterText}
before={before}
beforeText={beforeText}
onUpdate={(update) => {
if (update.after) {
setAfter(update.after);
}
if (update.afterText) {
setAfterText(update.afterText);
}
if (update.before) {
setBefore(update.before);
}
if (update.beforeText) {
setBeforeText(update.beforeText);
}
if (update.focusedInput) {
setFocusedInput(update.focusedInput);

if (update.focusedInput !== 'endDate') {
setIsOpen(false);
}

if (update.focusedInput === 'endDate' && after) {
setBefore('');
setBeforeText('');
setIsOpen(true);
}
}
}}
shortDateFormat="MM/DD/YYYY"
focusedInput={focusedInput}
isInvalidDate={(date) => new Date(date) > new Date()}
>
<div className="date-range-button">
<span className="components-button">
<span className="date-range-label">
{dateI18n(getSettings().formats.date, after)} - {dateI18n(getSettings().formats.date, before)}
</span>
</span>
</div>
</DateRangePicker>
);
};
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify the example implementation logic.

The example shows complex state management logic that should be validated for correctness.

Please verify this usage example works correctly, particularly the focusedInput logic in lines 627-636:


🏁 Script executed:

#!/bin/bash
# Check if there are similar patterns in the codebase for reference
ast-grep --pattern $'onUpdate={($$$) => {
  $$$
  if (update.focusedInput) {
    $$$
  }
  $$$
}}'

# Search for other DateRange usage patterns
rg -A 10 "focusedInput.*endDate"

Length of output: 1943


Review and adjust focusedInput logic in ReportFilter example

The current onUpdate handler will immediately close the picker whenever focus changes to anything other than "endDate". On initial open (when focus defaults to "startDate"), this will cause the picker to close instantly, preventing the user from selecting the start date.

To fix:

  • Only close the picker after a date selection, not on every focus change.
  • Remove or guard the setIsOpen(false) call so it only runs when a date has actually been picked.

Suggested patch in docs/frontend/components.md around lines 627–636:

-               if (update.focusedInput) {
-                   setFocusedInput(update.focusedInput);
-
-                   if (update.focusedInput !== 'endDate') {
-                       setIsOpen(false);
-                   }
-
-                   if (update.focusedInput === 'endDate' && after) {
-                       setBefore('');
-                       setBeforeText('');
-                       setIsOpen(true);
-                   }
-               }
+               if (update.focusedInput) {
+                   setFocusedInput(update.focusedInput);
+
+                   // Only close after selecting the start date
+                   if (update.focusedInput === 'endDate' && after) {
+                       // Reset end-date fields when switching to end-date selection
+                       setBefore('');
+                       setBeforeText('');
+                       setIsOpen(true);
+                   }
+               }

Now the picker stays open through the start-date selection and only resets/opens when switching to the end date.

Tagging as a fix required since the existing example logic will immediately close on open.

📝 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
```jsx
import {useState} from '@wordpress/element';
import {DateRangePicker} from '@dokan/components';
import {dateI18n, getSettings} from '@wordpress/date';
const ReportFilter = () => {
const [isOpen, setIsOpen] = useState(false);
const [after, setAfter] = useState('2023-01-01');
const [afterText, setAfterText] = useState('');
const [before, setBefore] = useState('2023-01-31');
const [beforeText, setBeforeText] = useState('');
const [focusedInput, setFocusedInput] = useState('startDate');
return (
<DateRangePicker
show={isOpen}
after={after}
setShow={setIsOpen}
afterText={afterText}
before={before}
beforeText={beforeText}
onUpdate={(update) => {
if (update.after) {
setAfter(update.after);
}
if (update.afterText) {
setAfterText(update.afterText);
}
if (update.before) {
setBefore(update.before);
}
if (update.beforeText) {
setBeforeText(update.beforeText);
}
if (update.focusedInput) {
setFocusedInput(update.focusedInput);
if (update.focusedInput !== 'endDate') {
setIsOpen(false);
}
if (update.focusedInput === 'endDate' && after) {
setBefore('');
setBeforeText('');
setIsOpen(true);
}
}
}}
shortDateFormat="MM/DD/YYYY"
focusedInput={focusedInput}
isInvalidDate={(date) => new Date(date) > new Date()}
>
<div className="date-range-button">
<span className="components-button">
<span className="date-range-label">
{dateI18n(getSettings().formats.date, after)} - {dateI18n(getSettings().formats.date, before)}
</span>
</span>
</div>
</DateRangePicker>
);
};
// … inside your <DateRangePicker> props …
onUpdate={(update) => {
if (update.after) {
setAfter(update.after);
}
if (update.afterText) {
setAfterText(update.afterText);
}
if (update.before) {
setBefore(update.before);
}
if (update.beforeText) {
setBeforeText(update.beforeText);
}
if (update.focusedInput) {
setFocusedInput(update.focusedInput);
// Only keep the picker open when switching to end-date
if (update.focusedInput === 'endDate' && after) {
// Reset end-date fields when entering end-date selection
setBefore('');
setBeforeText('');
setIsOpen(true);
}
}
}}
/>
🤖 Prompt for AI Agents
In docs/frontend/components.md around lines 627 to 636, the onUpdate handler
closes the DateRangePicker immediately when the focusedInput changes to anything
other than "endDate", causing the picker to close on initial open and preventing
start date selection. To fix this, modify the logic so that setIsOpen(false) is
only called after a date has been selected, not on every focus change. Remove or
guard the setIsOpen(false) call to ensure the picker remains open during start
date selection and only closes appropriately after selection.

@mralaminahamed mralaminahamed added Needs: Testing This requires further testing Needs: Dev Review It requires a developer review and approval and removed In Progress The issues is being worked on labels Jun 3, 2025
Copy link
Member

@mrabbani mrabbani left a comment

Choose a reason for hiding this comment

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

Pls check the feedback of coderabbitai.

@mrabbani mrabbani added Needs: Author Reply and removed Needs: Dev Review It requires a developer review and approval labels Jun 13, 2025
@mralaminahamed
Copy link
Member Author

@mrabbani vai, changes made as per coderabbitai feedback

@mralaminahamed mralaminahamed added Needs: Dev Review It requires a developer review and approval and removed Needs: Author Reply labels Jun 19, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85950d9 and 8cf248a.

📒 Files selected for processing (4)
  • src/components/date-range-picker/index.tsx (1 hunks)
  • src/components/date-range-picker/style.scss (1 hunks)
  • src/components/index.tsx (1 hunks)
  • src/definitions/woocommerce-components.d.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • src/components/date-range-picker/style.scss
  • src/definitions/woocommerce-components.d.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: e2e tests (3, 3)
  • GitHub Check: e2e tests (1, 3)
  • GitHub Check: e2e tests (2, 3)
  • GitHub Check: api tests (1, 1)
🔇 Additional comments (3)
src/components/date-range-picker/index.tsx (3)

14-32: Well-structured TypeScript interface.

The interface properly defines all component props with appropriate types and optional markers. The callback signatures are comprehensive and type-safe.


84-84: Standard component export.

Clean default export follows React conventions.


9-10: Verify WooCommerce component import resolution.

The eslint-disable comment suggests there might be module resolution issues with @woocommerce/components. Ensure this package is properly installed and the import path is correct.

#!/bin/bash
# Description: Verify @woocommerce/components package installation and DateRange component existence

# Check if package is installed
if [ -f "package.json" ]; then
    echo "Checking package.json for @woocommerce/components..."
    cat package.json | jq '.dependencies["@woocommerce/components"], .devDependencies["@woocommerce/components"]'
fi

if [ -f "package-lock.json" ]; then
    echo "Checking package-lock.json for @woocommerce/components..."
    cat package-lock.json | jq '.dependencies["@woocommerce/components"] // .packages["node_modules/@woocommerce/components"]'
fi

# Check if there's a TypeScript declaration file for this import
fd -t f -e "d.ts" . | xargs grep -l "woocommerce.*components" 2>/dev/null || echo "No TypeScript declarations found"

*/
const DateRangePicker = ( props: DateRangePickerProps ): JSX.Element => {
const ref = useRef( null );
useOnClickOutside( ref, () => props.setShow( false ) );
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use consistent prop references throughout the component.

The component inconsistently uses props vs updatedProps. After applying WordPress filters, all prop references should use updatedProps to ensure filter modifications are respected.

Apply this diff to fix the inconsistent prop usage:

-    useOnClickOutside( ref, () => props.setShow( false ) );
+    useOnClickOutside( ref, () => updatedProps.setShow( false ) );
-                { props.children ?? '' }
+                { updatedProps.children ?? '' }

Also applies to: 57-57

🤖 Prompt for AI Agents
In src/components/date-range-picker/index.tsx at lines 44 and 57, the code
inconsistently uses `props` instead of `updatedProps` after applying WordPress
filters. To fix this, replace all instances of `props` with `updatedProps` in
these lines to ensure the component respects the filtered prop values
consistently.

Comment on lines +46 to +49
const updatedProps: DateRangePickerProps = applyFilters(
'dokan_date_range_picker_props',
props
) as DateRangePickerProps;
Copy link
Contributor

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 for WordPress filter result.

The type assertion for applyFilters result bypasses TypeScript's type checking and could lead to runtime errors if filters return invalid data.

Consider adding runtime validation or using a type guard:

-    const updatedProps: DateRangePickerProps = applyFilters(
-        'dokan_date_range_picker_props',
-        props
-    ) as DateRangePickerProps;
+    const filteredProps = applyFilters(
+        'dokan_date_range_picker_props',
+        props
+    );
+    
+    // Validate that filtered props maintain required structure
+    const updatedProps: DateRangePickerProps = {
+        ...props,
+        ...(typeof filteredProps === 'object' && filteredProps !== null ? filteredProps : {}),
+    };
📝 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
const updatedProps: DateRangePickerProps = applyFilters(
'dokan_date_range_picker_props',
props
) as DateRangePickerProps;
const filteredProps = applyFilters(
'dokan_date_range_picker_props',
props
);
// Validate that filtered props maintain required structure
const updatedProps: DateRangePickerProps = {
...props,
...(typeof filteredProps === 'object' && filteredProps !== null ? filteredProps : {}),
};
🤖 Prompt for AI Agents
In src/components/date-range-picker/index.tsx around lines 46 to 49, the code
uses a type assertion to cast the result of applyFilters to
DateRangePickerProps, which bypasses TypeScript's type safety and risks runtime
errors if the filter returns invalid data. To fix this, implement a runtime
validation or a type guard function that checks whether the returned object
conforms to DateRangePickerProps before assigning it to updatedProps. This
ensures type safety without relying solely on type assertions.

Copy link
Member

@mrabbani mrabbani left a comment

Choose a reason for hiding this comment

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

Thank you for implementing the DateRangePicker component. The overall implementation looks promising, but there are some important issues that need to be addressed before this can be merged.

Required Changes

  1. Fix Inconsistent Props Usage
// Current implementation has inconsistent prop references
useOnClickOutside(ref, () => props.setShow(false));
{ props.children ?? '' }

// Should consistently use updatedProps after filter application
useOnClickOutside(ref, () => updatedProps.setShow(false));
{ updatedProps.children ?? '' }
  1. Improve Type Safety
// Replace unsafe type assertion with runtime validation
const filteredProps = applyFilters(
    'dokan_date_range_picker_props',
    props
);

// Add proper type validation
const updatedProps: DateRangePickerProps = {
    ...props,
    ...(typeof filteredProps === 'object' && filteredProps !== null ? filteredProps : {}),
};
  1. Resolve WooCommerce Dependencies
// Current:
// eslint-disable-next-line @typescript/no-unused-vars
import { DateRange } from '@woocommerce/components';

// Need to:
// 1. Verify @woocommerce/components is properly installed
// 2. Add proper TypeScript declarations
// 3. Remove eslint-disable if possible
  1. Add Error Handling & Loading States
// Add error boundary
const DateRangePickerWithErrorBoundary: React.FC<DateRangePickerProps> = (props) => (
    <ErrorBoundary fallback={<div>Error loading date picker</div>}>
        <DateRangePicker {...props} />
    </ErrorBoundary>
);

// Add loading state
const [isLoading, setIsLoading] = useState(false);
// Handle loading in onUpdate
const handleUpdate = async (update: any) => {
    setIsLoading(true);
    try {
        await props.onUpdate(update);
    } finally {
        setIsLoading(false);
    }
};

Additional Recommendations

  1. Testing

    • Add unit tests for component logic
    • Add integration tests with WooCommerce DateRange
    • Include accessibility tests (keyboard navigation, screen readers)
    • Test responsive behavior
  2. Documentation

    • Add JSDoc comments for all methods
    • Document available WordPress filters
    • Include usage examples in README
    • Add prop-types documentation
  3. Performance Optimizations

// Memoize callback props
const handleUpdate = useCallback((update: any) => {
    props.onUpdate(update);
}, [props.onUpdate]);

// Add cleanup in effects
useEffect(() => {
    // Setup code
    return () => {
        // Cleanup code
    };
}, []);

The component shows promise but needs these improvements to ensure robustness and maintainability. Please address these issues and let me know if you need any clarification or help implementing the changes.

@mrabbani mrabbani removed the Needs: Dev Review It requires a developer review and approval label Jun 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Testing This requires further testing 👍 Dev Review Done
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants