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

Migrate PaginatedList to useQuery #10350

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

Conversation

rajku-dev
Copy link
Contributor

@rajku-dev rajku-dev commented Feb 1, 2025

Proposed Changes

@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

Summary by CodeRabbit

  • New Features

    • Introduced a custom implementation for fetching and displaying questionnaire responses, enhancing responsiveness and flexibility.
    • Added a new useFilters hook to streamline data handling.
    • Enhanced the encounter history component with improved loading and empty state handling.
    • Implemented a new data fetching mechanism for comments in the comment section, improving user experience during loading states.
  • Refactor

    • Transitioned to using useQuery for data fetching across multiple components, improving performance and maintainability.
    • Updated the structure of the comment model to provide more detailed user information.

@rajku-dev rajku-dev requested a review from a team as a code owner February 1, 2025 09:09
Copy link
Contributor

coderabbitai bot commented Feb 1, 2025

Walkthrough

This pull request updates the PaginatedList component to utilize the useQuery hook from the @tanstack/react-query library, replacing a custom query hook. The changes involve modifying data fetching processes, updating type definitions, and adjusting prop names. The QuestionnaireResponsesList component has removed PaginatedList, implementing its functionality with useQuery and a new useFilters hook, enhancing loading and empty state handling directly within the component. Additionally, the EncounterHistory component has transitioned to using useQuery for fetching encounter data. The CommentModel interface has been adjusted, and the ResourceCommentSection component now uses useQuery for fetching comments.

Changes

File(s) Change Summary
src/CAREUI/misc/PaginatedList.tsx Transitioned from a custom query hook to useQuery from @tanstack/react-query; updated type definitions and Props interface; modified state initialization and loading state checks from loading to isLoading.
src/components/Facility/ConsultationDetails/QuestionnaireResponsesList.tsx Removed PaginatedList and replaced it with a custom implementation using useQuery and useFilters; updated loading and empty state handling with conditional rendering.
src/components/Patient/PatientDetailsTab/EncounterHistory.tsx Replaced the PaginatedList component with direct use of useQuery for fetching encounter data; modified loading and empty state handling.
src/components/Facility/models.tsx Updated CommentModel interface by removing created_by_object and changing created_by from number to UserBareMinimum.
src/components/Resource/ResourceCommentSection.tsx Introduced useQuery for fetching comments; removed PaginatedList and implemented custom fetching logic with pagination; updated rendering logic for loading and empty states.

Possibly related PRs

  • Removed unused feature flag handling and migrated to TanStack's query #9892: The changes in the main PR are related to the modifications in the PaginatedList component, which has been removed and replaced with a custom implementation in the retrieved PR, both utilizing the useQuery hook from @tanstack/react-query.
  • Add pagination and search to OrganizationUsers #9967: The changes in the main PR regarding the PaginatedList component's transition to useQuery are related to the modifications in the retrieved PR, which also involves the use of useQuery and the useFilters hook for managing query parameters in a similar context.
  • Util function for cleaner usage of TanStack useQuery #9395: The changes in the main PR, which involve significant modifications to the PaginatedList component and its transition to using the useQuery hook, are related to the retrieved PR that introduces a utility function for cleaner usage of useQuery, as both focus on the integration and usage of the @tanstack/react-query library for data fetching.

Suggested labels

needs review, tested

Suggested reviewers

  • rithviknishad
  • Jacobjeevan

Poem

I'm a bouncy rabbit, hopping through code,
With new hooks and queries on this joyful road.
From useQuery magic to neat renaming fixes,
My whiskers twitch at all these clever mixes.
Celebrate the changes — it's a coding delight!
Happy hops and bytes to all, day and night!


📜 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 bca1bf5 and b627460.

📒 Files selected for processing (2)
  • src/components/Facility/ConsultationDetails/QuestionnaireResponsesList.tsx (2 hunks)
  • src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: cypress-run (1)
🔇 Additional comments (7)
src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (4)

1-1: LGTM! Clean import organization and hook setup.

The imports are well-organized and the useFilters hook is configured appropriately with a reasonable limit of 5 items per page.

Also applies to: 9-9, 13-26


28-41: LGTM! Well-structured useQuery implementation.

The query setup is robust with:

  • Comprehensive query key including all dependencies
  • Proper debouncing of API calls
  • Correct pagination offset calculation

46-51: LGTM! Appropriate loading state handling.

The loading state uses CardListSkeleton with 5 items, matching the query limit and providing good visual feedback.


54-88: LGTM! Well-implemented empty and data states.

The component handles both states effectively:

  • Empty state provides clear user guidance with an action button
  • Data state efficiently renders encounters with proper list semantics and pagination
src/components/Facility/ConsultationDetails/QuestionnaireResponsesList.tsx (3)

31-175: LGTM! Well-structured helper components and type definitions.

The code demonstrates good practices:

  • Comprehensive type definitions for response values
  • Clean separation of concerns in helper components
  • Robust value formatting logic

281-305: LGTM! Consistent useQuery implementation.

The query setup follows the established pattern with:

  • Appropriate limit of 15 items
  • Comprehensive query key including encounter.id
  • Correct pagination parameters

308-337: LGTM! Clean and consistent rendering implementation.

The component follows the established pattern with:

  • Appropriate loading state using CardListSkeleton
  • Clear empty state messaging
  • Semantic list structure with proper pagination

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 Feb 1, 2025

Deploy Preview for care-ohc ready!

Name Link
🔨 Latest commit b627460
🔍 Latest deploy log https://app.netlify.com/sites/care-ohc/deploys/679eea6fe06f8300083e39f9
😎 Deploy Preview https://deploy-preview-10350--care-ohc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

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/CAREUI/misc/PaginatedList.tsx (1)

74-84: useQuery usage is correctly keyed and configured.
Consider ensuring queryParams is a stable reference to avoid unintentional re-fetches if the object shape changes.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 66104a8 and 52a3fae.

📒 Files selected for processing (3)
  • src/CAREUI/misc/PaginatedList.tsx (8 hunks)
  • src/components/Facility/ConsultationDetails/QuestionnaireResponsesList.tsx (1 hunks)
  • src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: cypress-run (1)
🔇 Additional comments (14)
src/CAREUI/misc/PaginatedList.tsx (12)

1-1: Well-adopted use of react-query.
No issues found with this import statement.


10-10: Importing apiQuery is consistent with the new data-fetching logic.
No concerns.


11-15: Imported types reflect actual usage.
All imports (ApiRoute, PaginatedResponse, QueryParams) appear necessary and properly utilized.


20-25: Combining UseQueryResult with custom fields is appropriate.
Merging the query result with extra pagination metadata is a neat way to centralize context.


39-52: Props<TItem> interface is well-structured.
All prop definitions align with the new useQuery approach and provide clear optional fields.


60-65: Destructuring is clear and matches the refactored API.
No issues found; parameter naming and defaults look good.


67-67: Initializing currentPage properly.
Using initialPage ?? 1 is a straightforward defaulting approach.


71-71: Optional chaining for onPageChange is safe and concise.
No further concerns.


112-112: WhenEmpty logic is direct and minimalistic.
The condition for skipping render when loading or non-empty is correct for an "empty" placeholder.

Also applies to: 114-114


124-124: WhenLoading gracefully handles the loading state.
Using !isLoading to skip rendering is concise.

Also applies to: 126-126


140-140: Refresh button usage is coherent.
Disabling while loading and the spinner class usage are consistent with best practices.

Also applies to: 147-147, 151-151


203-203: Paginator skip-while-loading is reasonable.
This prevents extraneous UI interactions until data is ready.

Also applies to: 205-205

src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (1)

24-24: Renaming query to queryParams aligns with the updated PaginatedList props.
Good consistency in naming across the codebase.

src/components/Facility/ConsultationDetails/QuestionnaireResponsesList.tsx (1)

285-285: Using queryParams for PaginatedList maintains consistency.
No issues found.

src/CAREUI/misc/PaginatedList.tsx Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

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

let's delete this component altogether and instead directly implement things in the usages instead. building this component in the first place itself was a mistake 😅. so many things feels abstracted away and not very flexible.

Copy link
Contributor Author

@rajku-dev rajku-dev Feb 2, 2025

Choose a reason for hiding this comment

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

Sure, I am working on it.
will do it one by one in this PR itself.

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

🧹 Nitpick comments (1)
src/components/Facility/ConsultationDetails/QuestionnaireResponsesList.tsx (1)

303-331: Consider extracting loading and empty states to reusable components.

The loading and empty states implementation is good, but these patterns might be reused across the application.

Consider creating reusable components:

// src/components/Common/States/LoadingState.tsx
export const LoadingState = ({ count = 3 }) => (
  <div className="grid gap-5">
    <CardListSkeleton count={count} />
  </div>
);

// src/components/Common/States/EmptyState.tsx
export const EmptyState = ({ message }: { message: string }) => (
  <Card className="p-6">
    <div className="text-lg font-medium text-gray-500">{message}</div>
  </Card>
);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 52a3fae and 881aadb.

📒 Files selected for processing (1)
  • src/components/Facility/ConsultationDetails/QuestionnaireResponsesList.tsx (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: cypress-run (1)
  • GitHub Check: OSSAR-Scan
🔇 Additional comments (4)
src/components/Facility/ConsultationDetails/QuestionnaireResponsesList.tsx (4)

1-1: LGTM! Import changes align with migration objectives.

The new imports for useQuery and useFilters are appropriate for the component's migration from PaginatedList to a direct useQuery implementation.

Also applies to: 11-14


Line range hint 44-279: LGTM! Helper functions and sub-components are well-structured.

The utility functions and sub-components maintain clear separation of concerns and handle complex data transformations effectively.


286-300: LGTM! Query implementation follows best practices.

The useQuery implementation:

  • Includes all necessary dependencies in queryKey
  • Uses debounced query for performance
  • Correctly calculates pagination offset

281-284: Verify the cache blacklist configuration.

The questionnaire parameter is blacklisted from cache. Please verify if this is intentional and document the reasoning.

✅ Verification successful

Cache Blacklist Configuration Verified

  • The only instance of blacklisting "questionnaire" is found in src/components/Facility/ConsultationDetails/QuestionnaireResponsesList.tsx, suggesting it was intentionally added for this component.
  • This intentional exclusion likely prevents caching of dynamic query parameters to ensure the freshest data is fetched.
  • No similar cache blacklist patterns for "questionnaire" exist elsewhere in the codebase, which further supports the specificity of this configuration.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other instances of cache blacklisting to understand the pattern
rg -A 2 "cacheBlacklist.*questionnaire" --type ts

Length of output: 322

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

🧹 Nitpick comments (1)
src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (1)

44-92: Consider simplifying the render logic.

While the implementation is functional, the render logic could be improved:

  1. Multiple nested div elements could be flattened
  2. Conditional rendering could be simplified
  3. Empty state could be extracted into a reusable component

Here's a suggested refactor:

-    <div className="mt-8">
-      <div>
-        {encountersLoading ? (
-          <div>
-            <div className="grid gap-5">
-              <CardListSkeleton count={3} />
-            </div>
-          </div>
+    <div className="mt-8">
+      {encountersLoading ? (
+        <div className="grid gap-5">
+          <CardListSkeleton count={3} />
+        </div>
+      ) : !encountersFetching && encounterData?.results?.length === 0 ? (
+        <EmptyEncounterState
+          facilityId={facilityId}
+          patientId={patientId}
+        />
+      ) : (
+        <ul className="grid gap-4">
+          {encounterData?.results?.map((encounter) => (
+            <li key={encounter.id} className="w-full">
+              <EncounterCard encounter={encounter} />
+            </li>
+          ))}
+          <div className="flex w-full items-center justify-center">
+            <Pagination totalCount={encounterData?.count || 0} />
+          </div>
+        </ul>
+      )}
+    </div>

And create a new component for the empty state:

const EmptyEncounterState = ({ facilityId, patientId }: { facilityId: string; patientId: string }) => {
  const { t } = useTranslation();
  
  return (
    <div className="p-2">
      <div className="h-full space-y-2 rounded-lg bg-white px-7 py-12 border border-secondary-300">
        <div className="flex w-full items-center justify-center text-lg text-secondary-600">
          {t("no_consultation_history")}
        </div>
        <div className="flex w-full items-center justify-center pt-4">
          <Button variant="outline_primary" asChild>
            <Link href={`/facility/${facilityId}/patient/${patientId}/consultation`}>
              <span className="flex w-full items-center justify-start gap-2">
                <CareIcon icon="l-chat-bubble-user" className="text-xl" />
                {t("add_consultation")}
              </span>
            </Link>
          </Button>
        </div>
      </div>
    </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 881aadb and 6c28f88.

📒 Files selected for processing (1)
  • src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: cypress-run (1)
🔇 Additional comments (3)
src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (3)

1-16: LGTM! Well-organized imports.

The imports are logically grouped and include all necessary dependencies for the new implementation using useQuery.


23-26: Resolve inconsistent limit values.

There's a mismatch between the limit values:

  • useFilters is configured with limit: 15
  • The actual query uses limit: 5 (line 37)

This inconsistency could lead to confusion. Consider aligning these values or documenting why they differ.


28-41: LGTM! Well-implemented query configuration.

The implementation follows React Query best practices:

  • Proper query key structure for cache management
  • Debounced API calls to prevent request spam
  • Comprehensive loading states extraction

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

🧹 Nitpick comments (5)
src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (5)

28-41: Consider these improvements to the query configuration.

  1. The limit value (5) is duplicated in both useFilters and query parameters. Consider extracting it to a constant.
  2. The offset calculation could be moved to a constant for better readability.
  3. Consider adding error handling for the debounced query.

Here's a suggested refactor:

+const ITEMS_PER_PAGE = 5;
+
 const { qParams, Pagination, resultsPerPage } = useFilters({
-  limit: 5,
+  limit: ITEMS_PER_PAGE,
   cacheBlacklist: ["encounterHistory"],
 });

+const currentOffset = ((qParams.page ?? 1) - 1) * resultsPerPage;
+
 const {
   data: encounterData,
   isFetching: encountersFetching,
   isLoading: encountersLoading,
+  error,
 } = useQuery({
   queryKey: ["encountersHistory", patientId, qParams],
   queryFn: query.debounced(routes.encounter.list, {
     queryParams: {
       patient: patientId,
-      limit: 5,
-      offset: ((qParams.page ?? 1) - 1) * resultsPerPage,
+      limit: ITEMS_PER_PAGE,
+      offset: currentOffset,
     },
   }),
+  retry: 2,
 });

44-52: Simplify the nested div structure in the loading state.

The loading state contains unnecessary nested divs that can be simplified.

-<div>
-  <div className="grid gap-5">
+<div className="grid gap-5">
     <CardListSkeleton count={3} />
-  </div>
 </div>

80-82: Remove duplicate key prop in EncounterCard.

The key prop is unnecessarily duplicated on both the li and EncounterCard elements.

 <li key={encounter.id} className="w-full">
-  <EncounterCard key={encounter.id} encounter={encounter} />
+  <EncounterCard encounter={encounter} />
 </li>

54-77: Consider extracting the empty state to a separate component.

The empty state UI logic is quite complex and could be extracted into a reusable component, especially if similar empty states are used elsewhere in the application.

Example:

const EmptyEncounterState = ({ facilityId, patientId }: { facilityId: string; patientId: string }) => {
  const { t } = useTranslation();
  return (
    <div className="p-2">
      <div className="h-full space-y-2 rounded-lg bg-white px-7 py-12 border border-secondary-300">
        {/* ... rest of the empty state JSX ... */}
      </div>
    </div>
  );
};

1-92: Well-implemented migration to useQuery!

The migration from PaginatedList to useQuery has been executed effectively, with proper handling of different states and clean integration with the useFilters hook. The component maintains good separation of concerns and follows React best practices.

Consider these architectural improvements for the future:

  1. Extract reusable UI components for empty and loading states
  2. Implement error boundaries or error states for failed queries
  3. Consider implementing infinite scroll instead of pagination for a better user experience
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6c28f88 and d54168f.

📒 Files selected for processing (1)
  • src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: cypress-run (1)
🔇 Additional comments (1)
src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (1)

1-26: LGTM! Clean imports and hook configuration.

The imports are well-organized and the useFilters hook is properly configured with appropriate pagination limits and cache settings.

@rajku-dev
Copy link
Contributor Author

rajku-dev commented Feb 2, 2025

questionnaire response
image

encounter history
image
image

resource comments
image

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 (4)
src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (3)

23-26: Extract magic number and fix cache key inconsistency.

Two issues to address:

  1. The limit value of 5 is hardcoded and repeated later in the query params. Consider extracting it to a constant.
  2. The cacheBlacklist uses "encounterHistory" while the query key uses "encountersHistory" (plural). This inconsistency might affect caching behavior.
+const ENCOUNTERS_PER_PAGE = 5;
+
 const { qParams, Pagination, resultsPerPage } = useFilters({
-  limit: 5,
-  cacheBlacklist: ["encounterHistory"],
+  limit: ENCOUNTERS_PER_PAGE,
+  cacheBlacklist: ["encountersHistory"],
 });

28-42: Use the extracted constant for consistency.

The query configuration looks good, with proper key structure and debounced API calls. However, the limit value is hardcoded again.

   queryFn: query.debounced(routes.encounter.list, {
     queryParams: {
       patient: patientId,
-      limit: 5,
+      limit: ENCOUNTERS_PER_PAGE,
       offset: ((qParams.page ?? 1) - 1) * resultsPerPage,
     },
   }),

79-83: Remove duplicate key prop.

The key prop is unnecessarily duplicated on both the li and EncounterCard elements.

 {encounterData?.results?.map((encounter) => (
   <li key={encounter.id} className="w-full">
-    <EncounterCard key={encounter.id} encounter={encounter} />
+    <EncounterCard encounter={encounter} />
   </li>
 ))}
src/components/Resource/ResourceCommentSection.tsx (1)

24-43: LGTM! Query configuration follows best practices.

The implementation correctly:

  • Uses array-based query key for proper cache invalidation
  • Implements pagination with offset calculation
  • Uses debounced query function

Consider extracting the magic number 15 into a constant:

+const COMMENTS_PER_PAGE = 15;
+
 const { qParams, Pagination, resultsPerPage } = useFilters({
-  limit: 15,
+  limit: COMMENTS_PER_PAGE,
   cacheBlacklist: ["resourceComments"],
 });

 const {
   data: resourceComments,
   isFetching: commentsFetching,
   isLoading: commentsLoading,
   refetch: refetchComments,
 } = useQuery({
   queryKey: [routes.getResourceComments.path, id, qParams],
   queryFn: query.debounced(routes.getResourceComments, {
     queryParams: {
-      limit: 15,
+      limit: COMMENTS_PER_PAGE,
       offset: ((qParams.page ?? 1) - 1) * resultsPerPage,
     },
     pathParams: { id },
   }),
 });
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d54168f and bca1bf5.

📒 Files selected for processing (3)
  • src/components/Facility/models.tsx (1 hunks)
  • src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (1 hunks)
  • src/components/Resource/ResourceCommentSection.tsx (2 hunks)
🧰 Additional context used
📓 Learnings (1)
src/components/Resource/ResourceCommentSection.tsx (1)
Learnt from: AdityaJ2305
PR: ohcnetwork/care_fe#10345
File: src/components/Resource/ResourceDetailsUpdate.tsx:132-145
Timestamp: 2025-01-31T22:13:06.153Z
Learning: The migration from useTanStackQueryInstead to useQuery in React components requires:
1. Updating types to use UseQueryResult instead of custom hook return type
2. Replacing loading with isLoading property
3. Using queryKey array for cache management
4. Using queryFn with query utility function
🔇 Additional comments (6)
src/components/Patient/PatientDetailsTab/EncounterHistory.tsx (2)

1-17: LGTM! Well-organized imports.

The imports are logically grouped and all dependencies are necessary for the component's functionality.


44-92: LGTM! Well-structured render logic.

The component handles all states effectively:

  • Loading state with skeleton UI
  • Empty state with clear user action
  • List rendering with semantic HTML
  • Proper pagination integration
src/components/Facility/models.tsx (1)

44-44: Verify the impact of CommentModel changes.

The type change from number to UserBareMinimum for created_by is a breaking change that might affect other components using CommentModel.

Run the following script to find all usages of CommentModel:

src/components/Resource/ResourceCommentSection.tsx (3)

1-1: LGTM! Imports and hook usage align with migration requirements.

The changes correctly implement the migration requirements from the learnings:

  1. Using useQuery from @tanstack/react-query
  2. Adding loading state components
  3. Using the useFilters hook for pagination

Also applies to: 10-12


86-111: LGTM! UI states are handled appropriately.

The implementation correctly handles:

  • Loading state with skeleton UI
  • Empty state with user-friendly message
  • List rendering with pagination

120-144: LGTM! Comment component implementation is clean and complete.

The component correctly:

  • Uses the updated CommentModel with UserBareMinimum type
  • Formats comment text and timestamps
  • Displays user information with avatar

Comment on lines +76 to +79
onClick={async () => {
await onSubmitComment();
refetchComments();
}}
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 error handling in comment submission.

The comment submission and refetch operations should be wrapped in a try-catch block to handle potential failures gracefully.

Apply this diff to improve error handling:

-onClick={async () => {
-  await onSubmitComment();
-  refetchComments();
-}}
+onClick={async () => {
+  try {
+    await onSubmitComment();
+    await refetchComments();
+  } catch (error) {
+    toast.error(t("failed_to_update_comments"));
+  }
+}}
📝 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
onClick={async () => {
await onSubmitComment();
refetchComments();
}}
onClick={async () => {
try {
await onSubmitComment();
await refetchComments();
} catch (error) {
toast.error(t("failed_to_update_comments"));
}
}}

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