Skip to content
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

Fix: Facility Organization Dropdown #10104

Merged
merged 23 commits into from
Feb 6, 2025

Conversation

Jeffrin2005
Copy link
Contributor

@Jeffrin2005 Jeffrin2005 commented Jan 22, 2025

Proposed Changes

v23.mp4

@ohcnetwork/care-fe-code-reviewers

Merge Checklist

  • Add specs that demonstrate bug / test a new feature.
  • Update product documentation.
  • Ensure that UI text is kept in I18n files.
  • Prep screenshot or demo video for changelog entry, and attach it to issue.
  • Request for Peer Reviews
  • Completion of QA

Summary by CodeRabbit

  • New Features
    • Improved the Autocomplete component for better clarity and functionality, including enhanced visual feedback for selected options.
    • Revamped the organization selection process to support multiple levels, allowing for dynamic querying and improved navigation.
    • Enhanced language support by adding new prompts for sub-department options, providing clearer user interactions.

@Jeffrin2005 Jeffrin2005 requested a review from a team as a code owner January 22, 2025 16:40
Copy link
Contributor

coderabbitai bot commented Jan 22, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request modifies the Autocomplete component to enhance its functionality and clarity by introducing a new selectedOption variable. It updates the rendering logic for button content and improves the visual indication of the selected state. Additionally, it adds two new localization keys in the English locale file. The FacilityOrganizationSelector component is refactored to use useQueries for fetching organization data, renaming variables, and introducing the renderOrganizationLevel function for better organization dropdown rendering.

Changes

File Change Summary
src/components/ui/autocomplete.tsx Introduced selectedOption for improved clarity, updated button title logic, and modified onChange handling.
public/locale/en.json Added two localization keys: "has_sub_departments": "Has sub-departments" and "select_sub_department": "Select sub-department".
src/pages/Facility/settings/organizations/…/FacilityOrganizationSelector.tsx Refactored to use useQueries, renamed variable to rootOrganizations, and added renderOrganizationLevel for improved dropdown rendering.

Assessment against linked issues

Objective Addressed Explanation
Enhance Facility Organization Dropdown Experience (#10060)

Possibly related PRs

Suggested labels

needs testing

Suggested reviewers

  • Jacobjeevan

Poem

I'm a rabbit in the codeyard, swift and bright,
Hopping through changes with all my might.
Mobile or desktop, the options unwind,
New dropdown paths and logic refined.
With hops of joy and carrot delight,
I celebrate the code that shines so light!


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 25e5b29 and 293d230.

📒 Files selected for processing (1)
  • src/components/ui/autocomplete.tsx (2 hunks)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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.

Copy link

netlify bot commented Jan 22, 2025

Deploy Preview for care-ohc failed.

Name Link
🔨 Latest commit 293d230
🔍 Latest deploy log https://app.netlify.com/sites/care-ohc/deploys/67a4794f6e8924000843f56c

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: 1

🧹 Nitpick comments (1)
src/pages/FacilityOrganization/components/FacilityOrganizationSelector.tsx (1)

115-126: Consider adding ARIA attributes for better accessibility.

The new organization display looks great with the Building icon and clear visual hierarchy. Consider these accessibility improvements:

-          <div className="flex items-center gap-3 rounded-md border border-sky-100 bg-sky-50/50 p-2.5">
+          <div 
+            className="flex items-center gap-3 rounded-md border border-sky-100 bg-sky-50/50 p-2.5"
+            role="status"
+            aria-label={`Selected organization: ${selectedOrganization.name}`}
+          >
             <Building className="h-4 w-4 text-sky-600 flex-shrink-0" aria-hidden="true" />
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 39caada and 2331940.

📒 Files selected for processing (1)
  • src/pages/FacilityOrganization/components/FacilityOrganizationSelector.tsx (2 hunks)
🔇 Additional comments (2)
src/pages/FacilityOrganization/components/FacilityOrganizationSelector.tsx (2)

2-2: LGTM! Good choice of icon library.

The addition of the Building icon from lucide-react aligns with the PR objectives and follows good practices.


172-176: LGTM! Well-implemented dynamic placeholder with i18n support.

The placeholder text implementation provides clear context and properly supports internationalization.

Comment on lines 131 to 150
<div key={org.id} className="flex items-center gap-1.5">
<div className="flex items-center gap-1.5 flex-1">
{index > 0 && (
<CareIcon
icon="l-arrow-right"
className="h-3.5 w-3.5 text-gray-400 flex-shrink-0"
/>
)}
<div
className="flex items-center justify-between flex-1 rounded-md border border-gray-200 bg-white px-2.5 py-1.5 text-sm shadow-sm cursor-pointer hover:bg-gray-50"
onClick={() => handleEdit(index)}
>
<span className="truncate">{org.name}</span>
<CareIcon
icon="l-angle-down"
className="h-3.5 w-3.5 ml-2 flex-shrink-0 text-gray-400"
/>
</div>
</div>
</div>
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

Enhance keyboard accessibility for interactive elements.

The hierarchical display looks clean, but needs accessibility improvements for keyboard users:

               <div
-                  className="flex items-center justify-between flex-1 rounded-md border border-gray-200 bg-white px-2.5 py-1.5 text-sm shadow-sm cursor-pointer hover:bg-gray-50"
+                  className="flex items-center justify-between flex-1 rounded-md border border-gray-200 bg-white px-2.5 py-1.5 text-sm shadow-sm cursor-pointer hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:ring-offset-2"
+                  role="button"
+                  tabIndex={0}
                   onClick={() => handleEdit(index)}
+                  onKeyDown={(e) => e.key === 'Enter' && handleEdit(index)}
+                  aria-label={`Edit ${org.name} level`}
📝 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
<div key={org.id} className="flex items-center gap-1.5">
<div className="flex items-center gap-1.5 flex-1">
{index > 0 && (
<CareIcon
icon="l-arrow-right"
className="h-3.5 w-3.5 text-gray-400 flex-shrink-0"
/>
)}
<div
className="flex items-center justify-between flex-1 rounded-md border border-gray-200 bg-white px-2.5 py-1.5 text-sm shadow-sm cursor-pointer hover:bg-gray-50"
onClick={() => handleEdit(index)}
>
<span className="truncate">{org.name}</span>
<CareIcon
icon="l-angle-down"
className="h-3.5 w-3.5 ml-2 flex-shrink-0 text-gray-400"
/>
</div>
</div>
</div>
<div key={org.id} className="flex items-center gap-1.5">
<div className="flex items-center gap-1.5 flex-1">
{index > 0 && (
<CareIcon
icon="l-arrow-right"
className="h-3.5 w-3.5 text-gray-400 flex-shrink-0"
/>
)}
<div
className="flex items-center justify-between flex-1 rounded-md border border-gray-200 bg-white px-2.5 py-1.5 text-sm shadow-sm cursor-pointer hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:ring-offset-2"
role="button"
tabIndex={0}
onClick={() => handleEdit(index)}
onKeyDown={(e) => e.key === 'Enter' && handleEdit(index)}
aria-label={`Edit ${org.name} level`}
>
<span className="truncate">{org.name}</span>
<CareIcon
icon="l-angle-down"
className="h-3.5 w-3.5 ml-2 flex-shrink-0 text-gray-400"
/>
</div>
</div>
</div>

@nihal467
Copy link
Member

nihal467 commented Jan 23, 2025

image

When you click on the dropdown that already has a value selected, the expected behavior is for the dropdown options to be displayed. Instead, the current behavior is that it closes the entire dropdown and reset it to its initial state, as if no value was previously selected.

@Jeffrin2005 https://www.loom.com/share/8cb97e50e22a45f98702f155c1ae9685?sid=6d2cc770-b044-409c-9801-2e665845b678

@Jeffrin2005
Copy link
Contributor Author

@nihal467

v23.mp4

Any Changes required ?

@github-actions github-actions bot added needs-triage question Further information is requested labels Jan 23, 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

🧹 Nitpick comments (1)
src/components/ui/autocomplete.tsx (1)

Line range hint 33-47: Consider adding controlled open state prop.

To provide more flexibility and better control over the dropdown's behavior, consider making the open state controllable from the parent component.

Add an optional prop for controlled open state:

 interface AutocompleteProps {
   options: AutoCompleteOption[];
   value: string;
   onChange: (value: string) => void;
   onSearch?: (value: string) => void;
   placeholder?: string;
   noOptionsMessage?: string;
   disabled?: boolean;
   align?: "start" | "center" | "end";
   popoverClassName?: string;
   "data-cy"?: string;
+  open?: boolean;
+  onOpenChange?: (open: boolean) => void;
 }

This would allow parent components to have full control over the dropdown's open state when needed.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2331940 and 7e0f0f2.

📒 Files selected for processing (2)
  • src/components/ui/autocomplete.tsx (2 hunks)
  • src/pages/FacilityOrganization/components/FacilityOrganizationSelector.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/FacilityOrganization/components/FacilityOrganizationSelector.tsx
🔇 Additional comments (2)
src/components/ui/autocomplete.tsx (2)

52-52: LGTM! Good optimization.

The introduction of selectedOption improves code readability and reduces repeated lookups.


67-73: LGTM! Clean implementation.

The label display logic is well-structured with good separation of styling and content.

Comment on lines 102 to 104
onChange(currentValue);
setOpen(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

Optimize onSelect handler to prevent unnecessary updates.

The current implementation doesn't check if the selected value is different from the current value, which could lead to unnecessary re-renders and might contribute to the reported dropdown behavior issues.

Apply this optimization:

-  onChange(currentValue);
-  setOpen(false);
+  if (currentValue !== value) {
+    onChange(currentValue);
+    setOpen(false);
+  }
📝 Committable suggestion

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

Suggested change
onChange(currentValue);
setOpen(false);
}}
if (currentValue !== value) {
onChange(currentValue);
setOpen(false);
}

<span
className={cn(
"truncate",
!selectedOption && "text-muted-foreground",
Copy link
Member

Choose a reason for hiding this comment

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

are you sure this is a valid tailwind class?

{selectedOrganization.has_children && (
<Badge variant="outline">Has Sub-departments</Badge>
<p className="text-xs text-sky-600">
{t("Has Sub Departments")}
Copy link
Member

Choose a reason for hiding this comment

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

refer translations guidelines in README. this is not how i18n should be done.

if (level < selectedLevels.length) {
return selectedLevels[level].name;
}
return level === 0 ? t("select_department") : t("select sub department");
Copy link
Member

Choose a reason for hiding this comment

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

please check all translations

@rithviknishad rithviknishad added invalid This doesn't seem right and removed question Further information is requested needs-triage labels Jan 25, 2025
@Jeffrin2005
Copy link
Contributor Author

@rithviknishad Updated all transitions.

<div
className="cursor-pointer p-1 hover:bg-gray-100 rounded-sm opacity-0 group-hover:opacity-100 transition-opacity"
onClick={() => {
const newLevels = selectedLevels.slice(0, level);
Copy link
Contributor

Choose a reason for hiding this comment

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

This logic is what should be in a function called handleEdit 👍

Separate out the concerns, code readability is important (check GovtOrganizationSelector for example for similar logic).

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: 1

🧹 Nitpick comments (2)
src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (1)

64-68: Reduce code duplication when retrieving orgList.

The logic to retrieve orgList from either rootOrganizations or organizationQueries appears in both handleLevelChange and renderOrganizationLevel. Extract this repeated pattern into a shared helper function to conform to DRY principles and improve maintainability.

Also applies to: 107-111

src/components/ui/autocomplete.tsx (1)

125-125: Fix indentation for compliance with lint rules.

Prettier highlights a missing indentation at line 125. Applying the following diff should resolve the linter error:

-const selectedOption = options.find((option) => option.value === value);
+  const selectedOption = options.find((option) => option.value === value);
🧰 Tools
🪛 ESLint

[error] 125-125: Insert ··

(prettier/prettier)

🪛 GitHub Check: cypress-run (1)

[failure] 125-125:
Insert ··

🪛 GitHub Check: lint

[failure] 125-125:
Insert ··

🪛 GitHub Actions: Lint Code Base

[error] 125-125: Insert ··

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7d713a9 and 0825a41.

📒 Files selected for processing (3)
  • public/locale/en.json (2 hunks)
  • src/components/ui/autocomplete.tsx (3 hunks)
  • src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • public/locale/en.json
🧰 Additional context used
🪛 ESLint
src/components/ui/autocomplete.tsx

[error] 125-125: Insert ··

(prettier/prettier)


[error] 149-152: Replace ⏎⏎········<Command>{commandContent}</Command>⏎ with ········<Command>{commandContent}</Command>

(prettier/prettier)

🪛 GitHub Check: cypress-run (1)
src/components/ui/autocomplete.tsx

[failure] 125-125:
Insert ··


[failure] 149-149:
Replace ⏎⏎········<Command>{commandContent}</Command>⏎ with ········<Command>{commandContent}</Command>

🪛 GitHub Check: lint
src/components/ui/autocomplete.tsx

[failure] 125-125:
Insert ··


[failure] 149-149:
Replace ⏎⏎········<Command>{commandContent}</Command>⏎ with ········<Command>{commandContent}</Command>

🪛 GitHub Actions: Lint Code Base
src/components/ui/autocomplete.tsx

[error] 125-125: Insert ··

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: OSSAR-Scan
🔇 Additional comments (3)
src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (1)

157-166: UI enhancement with building icon.

Showing the building icon in a distinct color thoroughly clarifies the currently selected organization. Great job on the user experience design!

src/components/ui/autocomplete.tsx (2)

137-137: Restore dropdown toggle on repeated clicks.

Past feedback highlighted that forcing setOpen(true) prevents toggling the dropdown closed. Switching to setOpen(!open) preserves the ability for users to click the button again to close the menu.


63-63: Reintroduce focus outlines for accessibility.

Previously noted: removing all outlines (via "outline-none border-none ring-0 shadow-none") can hinder keyboard navigation. Preserving or customizing focus indicators helps users relying on tab navigation, for example:

- className="outline-none border-none ring-0 shadow-none"
+ className="focus:ring-2 focus:ring-offset-2 focus:ring-primary"

Comment on lines +50 to +58
const organizationQueries = useQueries({
queries: selectedLevels.map((level, _index) => ({
queryKey: ["organizations", level.id],
queryFn: query(routes.facilityOrganization.list, {
pathParams: { facilityId },
queryParams: { parent: level.id },
}),
enabled: !!level.id,
})),
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

Add error or loading states for sub-organization queries.

If a sub-organization query fails or is still loading, the user has no feedback. Consider displaying a loading indicator or error message for each query, ensuring a smoother user experience when fetching data asynchronously.

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

🔭 Outside diff range comments (2)
src/components/ui/autocomplete.tsx (2)

67-74: Fix dropdown selection behavior.

The current implementation has two issues:

  1. It doesn't properly handle the toggle case, causing the reported issue where "dropdown closes when clicked with a value selected"
  2. It doesn't optimize for unnecessary updates

Apply these fixes:

-              onSelect={(v) => {
-                const currentValue =
-                  options.find(
-                    (option) => option.label.toLowerCase() === v.toLowerCase(),
-                  )?.value || "";
-                onChange(currentValue === value ? "" : currentValue);
-                setOpen(false);
-              }}
+              onSelect={(v) => {
+                const currentValue =
+                  options.find(
+                    (option) => option.label.toLowerCase() === v.toLowerCase(),
+                  )?.value || "";
+                if (currentValue !== value) {
+                  onChange(currentValue);
+                }
+                setOpen(!open);
+              }}

105-105: Fix mobile dropdown toggle behavior.

The mobile implementation has the same toggle issue where clicking doesn't properly toggle the dropdown state.

-          onClick={() => setOpen(true)}
+          onClick={() => setOpen(!open)}
🧹 Nitpick comments (3)
src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (3)

99-142: Consider memoizing the renderOrganizationLevel function.

The function creates new components on each render. Consider using useCallback to memoize the function and useMemo for the dropdown label to optimize performance.

-  const renderOrganizationLevel = (level: number) => {
+  const renderOrganizationLevel = useCallback((level: number) => {
     let orgList: FacilityOrganization[] | undefined;
 
     if (level === 0) {
       orgList = rootOrganizations?.results;
     } else if (level - 1 < organizationQueries.length) {
       orgList = organizationQueries[level - 1].data?.results;
     }
 
-    const getDropdownLabel = () => {
+    const dropdownLabel = useMemo(() => {
       if (level < selectedLevels.length) {
         return selectedLevels[level].name;
       }
       return level === 0 ? t("select_department") : t("select_sub_department");
-    };
+    }, [level, selectedLevels, t]);

     return (
       // ... rest of the render logic
     );
-  };
+  }, [rootOrganizations?.results, organizationQueries, selectedLevels, t]);

152-164: Enhance accessibility for selected organization display.

Consider adding ARIA labels and roles to improve accessibility:

-  <div className="flex items-center gap-3 rounded-md border border-sky-100 bg-sky-50/50 p-2.5">
+  <div 
+    className="flex items-center gap-3 rounded-md border border-sky-100 bg-sky-50/50 p-2.5"
+    role="status"
+    aria-label={`Selected organization: ${selectedOrganization.name}`}
+  >
     <Building className="h-4 w-4 text-sky-600 flex-shrink-0" />
     <div className="flex-1 min-w-0">
       <p className="font-medium text-sm text-sky-900 truncate">

177-177: Add newline at end of file.

Add a newline at the end of the file to comply with ESLint rules.

 }
+
🧰 Tools
🪛 ESLint

[error] 177-177: Insert

(prettier/prettier)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0825a41 and 30253ca.

📒 Files selected for processing (2)
  • src/components/ui/autocomplete.tsx (2 hunks)
  • src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (3 hunks)
🧰 Additional context used
🪛 ESLint
src/components/ui/autocomplete.tsx

[error] 120-120: Replace const·selectedOption·=·options.find((option)·=>·option.value·===·value); with ··const·selectedOption·=·options.find((option)·=>·option.value·===·value);⏎·

(prettier/prettier)


[error] 121-121: Replace ·· with ····

(prettier/prettier)


[error] 122-122: Insert ··

(prettier/prettier)


[error] 123-123: Replace ······ with ········

(prettier/prettier)


[error] 124-124: Insert ··

(prettier/prettier)


[error] 125-125: Insert ··

(prettier/prettier)


[error] 126-126: Insert ··

(prettier/prettier)


[error] 127-127: Insert ··

(prettier/prettier)


[error] 128-128: Insert ··

(prettier/prettier)


[error] 129-129: Insert ··

(prettier/prettier)


[error] 130-130: Replace ········ with ··········

(prettier/prettier)


[error] 131-131: Replace ········onClick={()·=>·setOpen(true)} with ··········onClick={()·=>·setOpen(true)}⏎······

(prettier/prettier)


[error] 132-132: Insert ··

(prettier/prettier)


[error] 133-133: Insert ··

(prettier/prettier)


[error] 134-134: Insert ··

(prettier/prettier)


[error] 135-135: Replace ········ with ··········

(prettier/prettier)


[error] 136-136: Insert ··

(prettier/prettier)


[error] 137-137: Replace ···· with ······

(prettier/prettier)


[error] 138-138: Insert ··

(prettier/prettier)


[error] 139-139: Insert ··

(prettier/prettier)


[error] 140-140: Insert ··

(prettier/prettier)


[error] 141-141: Replace ···· with ······

(prettier/prettier)


[error] 142-142: Insert ····

(prettier/prettier)


[error] 143-144: Replace with ····

(prettier/prettier)


[error] 145-145: Insert ····

(prettier/prettier)


[error] 146-146: Insert ··

(prettier/prettier)


[error] 147-147: Insert

(prettier/prettier)

src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx

[error] 177-177: Insert

(prettier/prettier)

🪛 GitHub Check: cypress-run (1)
src/components/ui/autocomplete.tsx

[failure] 120-120:
Replace const·selectedOption·=·options.find((option)·=>·option.value·===·value); with ··const·selectedOption·=·options.find((option)·=>·option.value·===·value);⏎·


[failure] 121-121:
Replace ·· with ····


[failure] 122-122:
Insert ··


[failure] 123-123:
Replace ······ with ········


[failure] 124-124:
Insert ··


[failure] 125-125:
Insert ··


[failure] 126-126:
Insert ··


[failure] 127-127:
Insert ··

🪛 GitHub Check: lint
src/components/ui/autocomplete.tsx

[failure] 120-120:
Replace const·selectedOption·=·options.find((option)·=>·option.value·===·value); with ··const·selectedOption·=·options.find((option)·=>·option.value·===·value);⏎·


[failure] 121-121:
Replace ·· with ····


[failure] 122-122:
Insert ··


[failure] 123-123:
Replace ······ with ········


[failure] 124-124:
Insert ··


[failure] 125-125:
Insert ··


[failure] 126-126:
Insert ··


[failure] 127-127:
Insert ··

🪛 GitHub Actions: Lint Code Base
src/components/ui/autocomplete.tsx

[error] 3-3: Replace import·{·cn·}·from·"@/lib/utils"; with ⏎import·{·cn·}·from·"@/lib/utils";⏎

🔇 Additional comments (8)
src/components/ui/autocomplete.tsx (5)

58-58: Maintain focus indicators for accessibility.

Removing all focus indicators (outline, border, ring, shadow) may impact keyboard navigation accessibility.


120-120: Good refactoring with selectedOption.

Extracting the selected option logic into a variable improves code readability and reduces duplication.

🧰 Tools
🪛 ESLint

[error] 120-120: Replace const·selectedOption·=·options.find((option)·=>·option.value·===·value); with ··const·selectedOption·=·options.find((option)·=>·option.value·===·value);⏎·

(prettier/prettier)

🪛 GitHub Check: cypress-run (1)

[failure] 120-120:
Replace const·selectedOption·=·options.find((option)·=>·option.value·===·value); with ··const·selectedOption·=·options.find((option)·=>·option.value·===·value);⏎·

🪛 GitHub Check: lint

[failure] 120-120:
Replace const·selectedOption·=·options.find((option)·=>·option.value·===·value); with ··const·selectedOption·=·options.find((option)·=>·option.value·===·value);⏎·


19-19: Verify mobile breakpoint implementation.

The useBreakpoints hook is used with { default: true, sm: false }, which means mobile-first design. Ensure this aligns with your application's breakpoint strategy.

Also applies to: 50-50

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Search for other useBreakpoints implementations to verify consistency
rg "useBreakpoints.*default.*sm" -A 2

Length of output: 483


Mobile breakpoint implementation verified.

The useBreakpoints hook is used consistently in both src/components/ui/autocomplete.tsx and src/components/Questionnaire/ValueSetSelect.tsx with { default: true, sm: false }. This confirms that the mobile-first configuration is applied as intended.

🧰 Tools
🪛 ESLint

[error] 19-19: Replace import·useBreakpoints·from·"@/hooks/useBreakpoints"; with ⏎import·useBreakpoints·from·"@/hooks/useBreakpoints";⏎

(prettier/prettier)

🪛 GitHub Check: cypress-run (1)

[failure] 19-19:
Replace import·useBreakpoints·from·"@/hooks/useBreakpoints"; with ⏎import·useBreakpoints·from·"@/hooks/useBreakpoints";⏎

🪛 GitHub Check: lint

[failure] 19-19:
Replace import·useBreakpoints·from·"@/hooks/useBreakpoints"; with ⏎import·useBreakpoints·from·"@/hooks/useBreakpoints";⏎


131-131: ⚠️ Potential issue

Fix desktop dropdown toggle behavior.

The desktop implementation has the same toggle issue where clicking doesn't properly toggle the dropdown state.

-        onClick={() => setOpen(true)}
+        onClick={() => setOpen(!open)}

Likely invalid or redundant comment.

🧰 Tools
🪛 ESLint

[error] 131-131: Replace ········onClick={()·=>·setOpen(true)} with ··········onClick={()·=>·setOpen(true)}⏎······

(prettier/prettier)


121-121: Verify modal behavior and pointer events.

Two potential issues to verify:

  1. Setting modal={true} on Popover might be too restrictive for a dropdown
  2. The pointer-events-auto class might be unnecessary as popovers handle pointer events by default

Also applies to: 139-139

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Search for other Popover implementations to verify consistency
rg "Popover.*modal.*true" -A 2
rg "PopoverContent.*pointer-events-auto" -A 2

Length of output: 575


Verified Modal and Pointer Events Configuration

  • The modal={true} prop is consistently used in both src/components/ui/autocomplete.tsx and src/components/Common/UserSelector.tsx, indicating intentional behavior across similar dropdown components.
  • There is no evidence of an additional pointer-events-auto class being applied to PopoverContent anywhere in the codebase, which reinforces that the default handling of pointer events is relied upon.
🧰 Tools
🪛 ESLint

[error] 121-121: Replace ·· with ····

(prettier/prettier)

🪛 GitHub Check: cypress-run (1)

[failure] 121-121:
Replace ·· with ····

🪛 GitHub Check: lint

[failure] 121-121:
Replace ·· with ····

src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (3)

1-2: LGTM! Import changes align with PR objectives.

The addition of useQueries and Building icon imports supports the enhanced dropdown functionality and UI improvements.


47-56: Add error and loading states for organization queries.

The queries implementation should handle error and loading states to provide better user feedback.


58-74: ⚠️ Potential issue

Fix dropdown state management issue.

Based on user feedback, the dropdown resets when clicked instead of showing options. This might be related to the level change handling. Consider preserving the dropdown state when the user clicks on a dropdown that already has a value selected.

✅ Verification successful

🌐 Web query:

What are the best practices for handling dropdown state in React to prevent unwanted resets?

Length of output: 6005


Address Dropdown State Persistence in handleLevelChange

  • Prevent Unnecessary Resets: Before updating the selection state, check if the clicked dropdown’s value is already active. For example, if the organization corresponding to the clicked value is already selected, you can avoid reassigning state—which may inadvertently trigger a reset.
  • Separate Dropdown Visibility from Selection: Consider managing the dropdown’s open/close state using its own state variable (e.g., using a dedicated isDropdownOpen managed via useState). This ensures that updating the selected value (or levels) doesn’t force the dropdown to close unexpectedly.
  • Controlled Component Approach: Ensure that the dropdown remains a controlled component with its value and visibility explicitly driven by state. This promotes predictable re-rendering and avoids unintentional resets caused by mismatched or reinitialized states.
  • Event Handling Considerations: If external clicks or event propagation are affecting dropdown behavior, use techniques like e.stopPropagation() to prevent parent handlers from interfering with the dropdown’s state.

Implementing these changes in the handleLevelChange function (and possibly related parts of the dropdown component) should help maintain the state of an already selected dropdown and prevent unwanted resets.

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: 1

🔭 Outside diff range comments (3)
src/components/ui/autocomplete.tsx (3)

58-58: Restore focus indicators for keyboard accessibility.

Removing all focus indicators (outline, border, ring, shadow) impacts keyboard navigation accessibility.

Apply this diff to restore focus indicators while maintaining a clean look:

-  className="outline-none border-none ring-0 shadow-none"
+  className="focus:ring-2 focus:ring-offset-2 focus:ring-primary border-none"

67-74: Fix dropdown behavior when selecting the same value.

The current implementation closes the dropdown even when selecting the same value, which might contribute to the reported issue where "dropdown closes when clicked with a value selected".

Apply this diff to improve the behavior:

-                onChange(currentValue === value ? "" : currentValue);
-                setOpen(false);
+                if (currentValue === value) {
+                  return; // Keep dropdown open when selecting same value
+                }
+                onChange(currentValue);
+                setOpen(false);

105-105: Fix mobile dropdown toggle behavior.

The onClick handler always sets open to true, which doesn't properly handle toggling the dropdown state.

Apply this diff to implement proper toggle behavior:

-  onClick={() => setOpen(true)}
+  onClick={() => setOpen(!open)}
♻️ Duplicate comments (1)
src/components/ui/autocomplete.tsx (1)

131-131: ⚠️ Potential issue

Fix desktop dropdown toggle behavior.

The onClick handler always sets open to true, which doesn't properly handle toggling the dropdown state.

Apply this diff to implement proper toggle behavior:

-  onClick={() => setOpen(true)}
+  onClick={() => setOpen(!open)}
🧰 Tools
🪛 ESLint

[error] 131-131: Replace ········onClick={()·=>·setOpen(true)} with ··········onClick={()·=>·setOpen(true)}⏎······

(prettier/prettier)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0825a41 and 75b8271.

📒 Files selected for processing (2)
  • src/components/ui/autocomplete.tsx (2 hunks)
  • src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (3 hunks)
🧰 Additional context used
🪛 ESLint
src/components/ui/autocomplete.tsx

[error] 120-120: Replace const·selectedOption·=·options.find((option)·=>·option.value·===·value); with ··const·selectedOption·=·options.find((option)·=>·option.value·===·value);⏎·

(prettier/prettier)


[error] 121-121: Replace ·· with ····

(prettier/prettier)


[error] 122-122: Insert ··

(prettier/prettier)


[error] 123-123: Replace ······ with ········

(prettier/prettier)


[error] 124-124: Insert ··

(prettier/prettier)


[error] 125-125: Insert ··

(prettier/prettier)


[error] 126-126: Insert ··

(prettier/prettier)


[error] 127-127: Insert ··

(prettier/prettier)


[error] 128-128: Insert ··

(prettier/prettier)


[error] 129-129: Insert ··

(prettier/prettier)


[error] 130-130: Replace ········ with ··········

(prettier/prettier)


[error] 131-131: Replace ········onClick={()·=>·setOpen(true)} with ··········onClick={()·=>·setOpen(true)}⏎······

(prettier/prettier)


[error] 132-132: Insert ··

(prettier/prettier)


[error] 133-133: Insert ··

(prettier/prettier)


[error] 134-134: Insert ··

(prettier/prettier)


[error] 135-135: Replace ········ with ··········

(prettier/prettier)


[error] 136-136: Insert ··

(prettier/prettier)


[error] 137-137: Replace ···· with ······

(prettier/prettier)


[error] 138-138: Insert ··

(prettier/prettier)


[error] 139-139: Insert ··

(prettier/prettier)


[error] 140-140: Insert ··

(prettier/prettier)


[error] 141-141: Replace ···· with ······

(prettier/prettier)


[error] 142-142: Insert ····

(prettier/prettier)


[error] 143-144: Replace with ····

(prettier/prettier)


[error] 145-145: Insert ····

(prettier/prettier)


[error] 146-146: Insert ··

(prettier/prettier)


[error] 147-147: Insert

(prettier/prettier)

src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx

[error] 177-177: Insert

(prettier/prettier)

🪛 GitHub Check: lint
src/components/ui/autocomplete.tsx

[failure] 120-120:
Replace const·selectedOption·=·options.find((option)·=>·option.value·===·value); with ··const·selectedOption·=·options.find((option)·=>·option.value·===·value);⏎·


[failure] 121-121:
Replace ·· with ····


[failure] 122-122:
Insert ··


[failure] 123-123:
Replace ······ with ········


[failure] 124-124:
Insert ··


[failure] 125-125:
Insert ··


[failure] 126-126:
Insert ··


[failure] 127-127:
Insert ··

🪛 GitHub Check: cypress-run (1)
src/components/ui/autocomplete.tsx

[failure] 120-120:
Replace const·selectedOption·=·options.find((option)·=>·option.value·===·value); with ··const·selectedOption·=·options.find((option)·=>·option.value·===·value);⏎·


[failure] 121-121:
Replace ·· with ····


[failure] 122-122:
Insert ··


[failure] 123-123:
Replace ······ with ········


[failure] 124-124:
Insert ··


[failure] 125-125:
Insert ··


[failure] 126-126:
Insert ··


[failure] 127-127:
Insert ··

🪛 GitHub Actions: Lint Code Base
src/components/ui/autocomplete.tsx

[error] 3-3: Replace import·{·cn·}·from·"@/lib/utils"; with ⏎import·{·cn·}·from·"@/lib/utils";⏎

⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Redirect rules - care-ohc
  • GitHub Check: Header rules - care-ohc
  • GitHub Check: Pages changed - care-ohc
  • GitHub Check: OSSAR-Scan
  • GitHub Check: CodeQL-Build
🔇 Additional comments (2)
src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (2)

152-164: LGTM! Well-implemented organization display.

The implementation nicely displays the selected organization with a blue building icon and appropriate styling, meeting the PR objectives.


47-56: 🛠️ Refactor suggestion

Add loading and error states for organization queries.

The queries implementation doesn't provide feedback during loading or when errors occur.

Add loading and error states to improve user experience:

 const organizationQueries = useQueries({
   queries: selectedLevels.map((level, _index) => ({
     queryKey: ["organizations", level.id],
     queryFn: query(routes.facilityOrganization.list, {
       pathParams: { facilityId },
       queryParams: { parent: level.id },
     }),
     enabled: !!level.id,
   })),
 });
+
+// Add loading and error handling in renderOrganizationLevel
+const isLoading = level > 0 && organizationQueries[level - 1].isLoading;
+const error = level > 0 && organizationQueries[level - 1].error;
+
+if (isLoading) return <div>Loading...</div>;
+if (error) return <div>Error loading organizations</div>;

Likely invalid or redundant comment.

className="cursor-pointer p-1 hover:bg-gray-100 rounded-sm opacity-0 group-hover:opacity-100 transition-opacity"
onClick={() => handleEdit(level)}
>
<CareIcon icon="l-pen" className="h-4 w-4 text-gray-500" />
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

Replace edit pencil with dropdown arrow per PR objectives.

The PR objectives mention replacing the edit pencil with a dropdown arrow, but the implementation still uses the pencil icon.

Apply this diff to align with PR objectives:

-              <CareIcon icon="l-pen" className="h-4 w-4 text-gray-500" />
+              <CareIcon icon="l-chevron-down" className="h-4 w-4 text-gray-500" />
📝 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
<CareIcon icon="l-pen" className="h-4 w-4 text-gray-500" />
<CareIcon icon="l-chevron-down" className="h-4 w-4 text-gray-500" />

@github-actions github-actions bot removed the merge conflict pull requests with merge conflict label Feb 5, 2025
@Jeffrin2005
Copy link
Contributor Author

Jeffrin2005 commented Feb 5, 2025

@nihal467 @rithviknishad @Jacobjeevan Fixed merge conflicts

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

♻️ Duplicate comments (3)
src/components/ui/autocomplete.tsx (1)

141-141: ⚠️ Potential issue

Fix dropdown toggle behavior.

The current onClick implementation doesn't properly handle the toggle case, which explains the reported issue where "dropdown closes when clicked with a value selected".

Apply this fix:

-  onClick={() => setOpen(true)}
+  onClick={() => setOpen(!open)}
src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (2)

50-59: 🛠️ Refactor suggestion

Add loading and error states for organization queries.

The queries lack feedback for loading and error states.

Consider adding loading indicators and error messages for each query:

 const organizationQueries = useQueries({
   queries: selectedLevels.map((level, _index) => ({
     queryKey: ["organizations", level.id],
     queryFn: query(routes.facilityOrganization.list, {
       pathParams: { facilityId },
       queryParams: { parent: level.id },
     }),
     enabled: !!level.id,
+    retry: false,
   })),
 });

Then handle the states in renderOrganizationLevel:

if (level > 0 && organizationQueries[level - 1].isLoading) {
  return <div>Loading...</div>;
}
if (level > 0 && organizationQueries[level - 1].isError) {
  return <div>Error loading organizations</div>;
}

141-141: ⚠️ Potential issue

Replace edit pencil with dropdown arrow per PR objectives.

The PR objectives mention replacing the edit pencil with a dropdown arrow.

Apply this change:

-              <CareIcon icon="l-pen" className="h-4 w-4 text-gray-500" />
+              <CareIcon icon="l-chevron-down" className="h-4 w-4 text-gray-500" />
🧹 Nitpick comments (1)
src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (1)

171-178: Consider adding aria-labels for accessibility.

The nested organization levels could benefit from ARIA labels for better screen reader support.

Add descriptive labels:

-            <div key={org.id}>{renderOrganizationLevel(index)}</div>
+            <div 
+              key={org.id}
+              aria-label={`Organization level ${index + 1}: ${org.name}`}
+            >
+              {renderOrganizationLevel(index)}
+            </div>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 75b8271 and 25e5b29.

📒 Files selected for processing (2)
  • src/components/ui/autocomplete.tsx (2 hunks)
  • src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: cypress-run (1)
🔇 Additional comments (4)
src/components/ui/autocomplete.tsx (3)

64-64: Remove focus-related classes to maintain accessibility.

The removal of focus indicators impacts keyboard navigation accessibility.

Apply this fix to maintain accessibility standards:

-  className="outline-none border-none ring-0 shadow-none"
+  className="focus:ring-2 focus:ring-offset-2 focus:ring-primary"

78-79: Optimize onChange handler to prevent unnecessary updates.

The current implementation might cause unnecessary re-renders.

Apply this optimization:

-  onChange(currentValue === value ? "" : currentValue);
-  setOpen(false);
+  const newValue = currentValue === value ? "" : currentValue;
+  if (newValue !== value) {
+    onChange(newValue);
+    setOpen(false);
+  }

128-129: LGTM! Good refactoring of selectedOption logic.

The introduction of selectedOption variable improves code readability and reduces duplicate logic.

Also applies to: 134-134, 143-144

src/pages/Facility/settings/organizations/components/FacilityOrganizationSelector.tsx (1)

157-169: LGTM! Nice UI improvements with the Building icon.

The addition of the Building icon and improved layout for the selected organization enhances visibility and user experience, aligning with PR objectives.

@nihal467
Copy link
Member

nihal467 commented Feb 6, 2025

LGTM

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@rithviknishad rithviknishad merged commit 6bc04d7 into ohcnetwork:develop Feb 6, 2025
9 of 14 checks passed
Copy link

github-actions bot commented Feb 6, 2025

@Jeffrin2005 Your efforts have helped advance digital healthcare and TeleICU systems. 🚀 Thank you for taking the time out to make CARE better. We hope you continue to innovate and contribute; your impact is immense! 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enhance Facility Organization Dropdown Experience
4 participants