Skip to content

added-dynamic-dropdown-for-country-selection-input#39

Merged
kumawatkaran523 merged 1 commit intoStabilityNexus:mainfrom
ajey35:feat/country-select-dropdown
Dec 30, 2025
Merged

added-dynamic-dropdown-for-country-selection-input#39
kumawatkaran523 merged 1 commit intoStabilityNexus:mainfrom
ajey35:feat/country-select-dropdown

Conversation

@ajey35
Copy link
Copy Markdown
Contributor

@ajey35 ajey35 commented Dec 30, 2025

Hi @kumawatkaran523,

I’ve added dynamic country name and logo fetching to improve the overall user experience.

With this change, users can easily search and select their country with clear visual identification, reducing confusion and improving usability.

Below are the screenshots demonstrating the updated behavior.

Please let me know if you’d like any refinements or changes.
Screenshot From 2025-12-30 11-51-46
Screenshot From 2025-12-30 11-51-34
Screenshot From 2025-12-30 11-51-26
Screenshot From 2025-12-30 11-51-19
Screenshot From 2025-12-30 11-51-12

Summary by CodeRabbit

Release Notes

  • New Features
    • Added searchable country selector to invoice forms with real-time filtering by country name
    • Country selections now display flags for visual reference
    • Improved country selection experience across invoice creation and batch processing workflows

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Dec 30, 2025

📝 Walkthrough

Walkthrough

Introduces a new CountryPicker React component with searchable functionality and flag display, backed by a countries.json dataset. The component is integrated into CreateInvoice and CreateInvoicesBatch pages to replace plain text country input fields.

Changes

Cohort / File(s) Summary
CountryPicker Component
frontend/src/components/CountryPicker.jsx, frontend/src/lib/countries.json
New searchable country selector component with popover, search filtering by name, and flag display via CDN; backed by static JSON dataset of alphabetically-ordered countries with name and code fields.
Page Integration
frontend/src/page/CreateInvoice.jsx, frontend/src/page/CreateInvoicesBatch.jsx
Replaced plain text country input fields with CountryPicker components for userCountry and clientCountry; added local state management and updated form submission logic to incorporate new state values.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A picker so fine, with countries galore,
Searchable flags from shore to shore,
No more plain text, just tap and go,
Countries in list, a colorful show! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: introducing a dynamic dropdown component for country selection. It aligns with the PR objectives and the file changes that implement the CountryPicker component across multiple pages.
✨ 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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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: 0

🧹 Nitpick comments (5)
frontend/src/components/CountryPicker.jsx (5)

8-14: Consider adding onChange validation.

The onChange prop is required but has no default value or validation. If a consumer forgets to pass it, the component will crash at runtime when a country is selected.

🔎 Add a default no-op onChange
 const CountryPicker = ({
   value = "",
-  onChange,
+  onChange = () => {},
   placeholder = "Select country",
   className,
   disabled = false,
 }) => {

53-55: External CDN dependency may impact reliability.

The component relies on flagcdn.com for flag images. If this CDN is unavailable or slow, it could degrade user experience. While the onError handler gracefully hides failed images, users won't see country flags during outages.

Consider one of these approaches for production:

  1. Self-host flag images in the project assets
  2. Use a more reliable CDN with SLA guarantees
  3. Add a generic country icon fallback instead of hiding the image entirely
  4. Preload common flag images

For now, the current implementation is acceptable with the graceful error handling.

Also applies to: 74-79, 125-130


44-51: Focus timing could be more robust.

The 100ms setTimeout for focusing the search input is a timing assumption that might not work consistently across devices or when animations are slow.

🔎 Consider using requestAnimationFrame for more reliable timing
   useEffect(() => {
     if (open && searchInputRef.current) {
-      setTimeout(() => {
-        searchInputRef.current?.focus();
-      }, 100);
+      requestAnimationFrame(() => {
+        setTimeout(() => {
+          searchInputRef.current?.focus();
+        }, 0);
+      });
     }
   }, [open]);

This waits for the next render frame before scheduling the focus, which is more reliable with CSS animations.


20-35: LGTM! Search logic is clean and functional.

The case-insensitive search with .includes() works well for most cases. Note that diacritic handling (e.g., searching "Reunion" won't match "Réunion") could be improved with .normalize(), but this is an edge case.

🔎 Optional: Add diacritic-insensitive search
   const filteredCountries = countriesData.filter((country) =>
-    country.name.toLowerCase().includes(searchQuery.toLowerCase())
+    country.name
+      .toLowerCase()
+      .normalize('NFD')
+      .replace(/[\u0300-\u036f]/g, '')
+      .includes(searchQuery.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, ''))
   );

57-140: Consider enhancing accessibility.

The component has basic accessibility (button types, disabled states) but could be improved for keyboard and screen reader users.

Consider adding:

  1. ARIA roles: Add role="listbox" to the country list and role="option" to items
  2. Keyboard navigation: Implement arrow key navigation through the filtered list
  3. Result count announcement: Add aria-live="polite" region to announce filtered result count
  4. Search label: Add aria-label="Search countries" to the search input

These improvements would make the component more usable for assistive technology users.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 160eef1 and 904f058.

📒 Files selected for processing (4)
  • frontend/src/components/CountryPicker.jsx
  • frontend/src/lib/countries.json
  • frontend/src/page/CreateInvoice.jsx
  • frontend/src/page/CreateInvoicesBatch.jsx
🧰 Additional context used
🧬 Code graph analysis (3)
frontend/src/components/CountryPicker.jsx (3)
frontend/src/components/ui/popover.jsx (3)
  • Popover (6-6)
  • PopoverTrigger (8-8)
  • PopoverContent (12-24)
frontend/src/lib/utils.js (1)
  • cn (4-6)
frontend/src/components/ui/input.jsx (1)
  • Input (5-16)
frontend/src/page/CreateInvoicesBatch.jsx (1)
frontend/src/components/CountryPicker.jsx (1)
  • CountryPicker (8-141)
frontend/src/page/CreateInvoice.jsx (1)
frontend/src/components/CountryPicker.jsx (1)
  • CountryPicker (8-141)
🔇 Additional comments (10)
frontend/src/page/CreateInvoice.jsx (5)

48-48: LGTM! Clean import.

The CountryPicker component is properly imported using the project's path alias convention.


62-63: LGTM! State initialization is appropriate.

The country state variables are properly initialized with empty strings, which works well with the CountryPicker's controlled component pattern.


548-561: LGTM! CountryPicker integration is well-implemented.

The implementation correctly uses:

  • Controlled component pattern with value and onChange
  • Hidden input to ensure the country value is included in FormData
  • Disabled state during loading to prevent concurrent modifications

646-659: LGTM! Consistent implementation.

The client country picker follows the same pattern as the user country picker, maintaining consistency across the form.


376-376: LGTM! Defensive data extraction with good fallbacks.

The fallback chain (state → formData → empty string) is a defensive pattern that ensures the country values are always strings, even if state is unexpectedly cleared.

Also applies to: 383-383

frontend/src/page/CreateInvoicesBatch.jsx (3)

56-56: LGTM! Consistent import.

The CountryPicker import follows the same pattern as in CreateInvoice.jsx.


721-734: LGTM! Clean state management.

The implementation properly updates userInfo state using the functional setter pattern with spread operator, preserving other fields while updating userCountry.


1044-1058: LGTM! Consistent with batch form pattern.

The country picker integrates seamlessly with the existing updateInvoiceRow pattern used for other fields in the batch invoice form.

frontend/src/components/CountryPicker.jsx (1)

1-144: Overall: Excellent implementation of country picker component!

The CountryPicker component is well-structured and provides a great user experience with searchable countries and flag display. The integration with consuming pages is clean and consistent.

The minor improvements suggested (onChange validation, CDN reliability, focus timing, accessibility) are all optional refinements that can be addressed in future iterations.

frontend/src/lib/countries.json (1)

1-1002: LGTM! Country dataset is comprehensive and accurate.

The JSON file is properly formatted, contains 250 country entries with no duplicates, and the ISO 3166-1 alpha-2 codes are correct, including Kosovo (XK), Czechia (CZ), Taiwan (TW), and Åland Islands (AX).

@kumawatkaran523
Copy link
Copy Markdown
Contributor

good, Keep it up!

@kumawatkaran523 kumawatkaran523 merged commit b3a42ca into StabilityNexus:main Dec 30, 2025
1 check passed
@ajey35 ajey35 deleted the feat/country-select-dropdown branch January 9, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants