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 : View Retention in Users Tab After Navigation #9485

Conversation

Mahendar0701
Copy link
Contributor

@Mahendar0701 Mahendar0701 commented Dec 18, 2024

Proposed Changes

Recording.2024-12-18.173555.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

    • Introduced a new useView hook for managing view states across components
    • Added a View component for dynamic view rendering
    • Implemented view cache management utilities
  • Refactor

    • Simplified view management in multiple components
    • Replaced local storage navigation logic with centralized view state management
  • Chores

    • Updated localization strings in English JSON file
    • Improved cache invalidation during login process

@Mahendar0701 Mahendar0701 requested a review from a team as a code owner December 18, 2024 12:10
Copy link
Contributor

coderabbitai bot commented Dec 18, 2024

Walkthrough

The pull request introduces a comprehensive view management system across multiple components. A new custom hook useView is implemented to manage view states persistently using local storage. Components like ManageUsers, ResourceRoutes, ResourceBoard, and ResourceList have been refactored to utilize this hook. A new View component provides a generic way to handle view switching, and a ViewCache utility has been added to manage view preferences. The changes aim to improve view state persistence and provide a more consistent approach to managing component views.

Changes

File Change Summary
src/Utils/useView.ts New custom hook for managing view state with local storage persistence
src/components/Common/View.tsx New generic view component for rendering board/list views
src/Utils/ViewCache.ts New utility for managing view preferences in local storage
src/components/Users/ManageUsers.tsx Updated to use useView for tab management
src/components/Facility/FacilityUsers.tsx Refactored to use useView for active tab state
src/Routers/routes/ResourceRoutes.tsx Replaced Redirect with new View component
src/components/Resource/ResourceBoard.tsx Simplified view management using useView
src/components/Resource/ResourceList.tsx Removed navigation logic, now uses useView
src/components/Auth/Login.tsx Added ViewCache.invalidateAll() on login

Assessment against linked issues

Objective Addressed Explanation
Retain selected view after navigation
Preserve view state after logout

Possibly related PRs

Suggested labels

P1

Suggested reviewers

  • rithviknishad
  • Jacobjeevan

Poem

🐰 A View Hook Hops Along!
Local storage, my new song
Tabs dance with glee
Persistence sets them free
View management, rabbit-strong! 🏠


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 Dec 18, 2024

Deploy Preview for care-ohc ready!

Name Link
🔨 Latest commit 84b32c0
🔍 Latest deploy log https://app.netlify.com/sites/care-ohc/deploys/67739871114efb00087c13c9
😎 Deploy Preview https://deploy-preview-9485--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: 0

🧹 Nitpick comments (2)
src/Routers/routes/UserRoutes.tsx (1)

14-16: Consider adding type safety for view parameter.

While the implementation is clean, consider adding runtime validation for the view parameter to prevent potential routing issues with invalid values.

-  "/users": () => <Redirect to={`/users/${getDefaultUsersView()}`} />,
+  "/users": () => {
+    const view = getDefaultUsersView();
+    if (view !== "list" && view !== "card") {
+      console.error(`Invalid view type: ${view}`);
+      return <Redirect to="/users/card" />;
+    }
+    return <Redirect to={`/users/${view}`} />;
+  },
src/components/Users/ManageUsers.tsx (1)

108-113: Consider adding error handling for navigation failures.

The handleTabChange function looks good but should handle potential navigation failures.

   const handleTabChange = (tab: number) => {
     setActiveTab(tab);
     const newView = tab === 1 ? "list" : "card";
     localStorage.setItem("usersDefaultView", newView);
-    navigate(`/users/${newView}`);
+    navigate(`/users/${newView}`).catch((error) => {
+      console.error("Navigation failed:", error);
+      // Optionally show a user-friendly error notification
+    });
   };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3979b53 and 51a053e.

📒 Files selected for processing (2)
  • src/Routers/routes/UserRoutes.tsx (1 hunks)
  • src/components/Users/ManageUsers.tsx (4 hunks)
🔇 Additional comments (3)
src/Routers/routes/UserRoutes.tsx (1)

10-11: LGTM! Clean implementation of view preference retrieval.

The function is well-focused and provides a good fallback mechanism.

src/components/Users/ManageUsers.tsx (2)

31-31: LGTM! Well-structured component initialization.

The component properly handles the defaultView prop and initializes the state accordingly.

Also applies to: 50-50


121-123: Verify the integration with UserListView component.

Ensure that the UserListView component properly handles the tab change callback.

✅ Verification successful

The UserListView component properly handles the tab change callback

The verification shows that:

  • The UserListView component in UserListAndCard.tsx correctly defines the onTabChange prop in its interface as onTabChange: (tab: number) => void
  • The component properly receives and uses the onTabChange prop to handle tab changes
  • The implementation in ManageUsers.tsx correctly passes the handleTabChange callback to the UserListView component
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for UserListView component implementation to verify onTabChange prop handling
ast-grep --pattern 'interface $interface {
  $$$
  onTabChange: $type
  $$$
}'

# Search for actual usage of onTabChange in the component
ast-grep --pattern 'function UserListView($props) {
  $$$
  onTabChange($$$)
  $$$
}'

Length of output: 168


Script:

#!/bin/bash
# Let's try a broader search for UserListView component and its props
rg -A 10 "UserListView" --type typescript

# Also search for any file containing UserListView in its name
fd UserListView

# Search for tab change handling patterns
rg "onTabChange|handleTabChange" --type typescript

Length of output: 182


Script:

#!/bin/bash
# Search for UserListView component and its props without type filter
rg -A 10 "UserListView"

# Search for any file containing UserListView in its name
fd UserListView

# Search for tab change handling patterns
rg "onTabChange|handleTabChange"

Length of output: 6358

src/components/Users/ManageUsers.tsx Outdated Show resolved Hide resolved
@rithviknishad
Copy link
Member

I'd recommend creating a util. function that handles the logic to create an abstraction between the storage, since we have similar use cases in other places.

@rithviknishad
Copy link
Member

Also, let's not have a dedicated route defined for it.

@Jacobjeevan
Copy link
Contributor

I'd recommend creating a util. function that handles the logic to create an abstraction between the storage, since we have similar use cases in other places.

Oh true, resources and shifting if I recall.

@rithviknishad
Copy link
Member

rithviknishad commented Dec 18, 2024

And appointments page in DO Branch, (although the list view is not ready there yet)

@Mahendar0701
Copy link
Contributor Author

Also, let's not have a dedicated route defined for it.

For Users i have done.

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 (1)
src/Routers/routes/ShiftingRoutes.tsx (1)

Line range hint 1-1: Consider centralizing localStorage keys

To improve maintainability and prevent key conflicts, consider creating a central constants file for localStorage keys:

// src/constants/storage.ts
export const STORAGE_KEYS = {
  VIEWS: {
    USERS: 'usersDefaultView',
    RESOURCES: 'resourcesDefaultView',
    SHIFTING: 'shiftingDefaultView'
  }
} as const;

This would provide:

  1. Type safety for keys
  2. Easy discovery of existing keys
  3. Prevention of duplicate keys
  4. Single source of truth for storage keys
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 51a053e and 8af90dd.

📒 Files selected for processing (5)
  • src/Routers/routes/ResourceRoutes.tsx (1 hunks)
  • src/Routers/routes/ShiftingRoutes.tsx (1 hunks)
  • src/Routers/routes/UserRoutes.tsx (1 hunks)
  • src/Utils/viewStorageUtils.ts (1 hunks)
  • src/components/Users/ManageUsers.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Routers/routes/UserRoutes.tsx
  • src/components/Users/ManageUsers.tsx

src/Utils/viewStorageUtils.ts Outdated Show resolved Hide resolved
src/Utils/viewStorageUtils.ts Outdated Show resolved Hide resolved
src/Routers/routes/ResourceRoutes.tsx Outdated Show resolved Hide resolved
src/Routers/routes/ShiftingRoutes.tsx Outdated Show resolved Hide resolved
src/Utils/viewStorageUtils.ts Outdated Show resolved Hide resolved
src/Routers/routes/ShiftingRoutes.tsx Outdated Show resolved Hide resolved
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/Shifting/ShiftingList.tsx (2)

39-39: Consider calling setDefaultView before navigation

For better user experience, consider storing the view preference before navigating to prevent any potential race conditions.

const onBoardViewBtnClick = () => {
+  setDefaultView("defaultShiftView", "board");
  navigate("/shifting/board", { query: qParams });
-  setDefaultView("defaultShiftView", "board");
};

22-22: Consider using constants for view types and storage keys

To maintain consistency and prevent typos, consider extracting the view types and storage keys into constants.

// Add to a constants file
export const VIEW_TYPES = {
  BOARD: 'board',
  LIST: 'list'
} as const;

export const STORAGE_KEYS = {
  SHIFT_VIEW: 'defaultShiftView',
  RESOURCE_VIEW: 'defaultResourceView',
  USER_VIEW: 'defaultUserView'
} as const;

Also applies to: 39-39

src/components/Resource/ResourceBoard.tsx (1)

51-51: Apply consistent view management pattern

Similar to the ShiftingList component, consider:

  1. Moving setDefaultView before navigation
  2. Using constants for view types and storage keys
const onListViewBtnClick = () => {
+  setDefaultView(STORAGE_KEYS.RESOURCE_VIEW, VIEW_TYPES.LIST);
  navigate("/resource/list", { query: qParams });
-  setDefaultView("defaultResourceView", "list");
};
src/components/Shifting/ShiftingBoard.tsx (2)

82-82: Apply consistent view management pattern

Similar to other components, consider:

  1. Moving setDefaultView before navigation
  2. Using constants for view types and storage keys
const onListViewBtnClick = () => {
+  setDefaultView(STORAGE_KEYS.SHIFT_VIEW, VIEW_TYPES.LIST);
  navigate("/shifting/list", { query: qParams });
-  setDefaultView("defaultShiftView", "list");
};

33-33: Consider creating a reusable view switching hook

There's a pattern of duplicated view switching logic across components. Consider creating a custom hook to encapsulate this behavior.

// src/hooks/useViewSwitcher.ts
import { navigate } from "raviger";
import { setDefaultView } from "@/Utils/viewStorageUtils";
import { VIEW_TYPES, STORAGE_KEYS } from "@/common/constants";

type ViewConfig = {
  storageKey: typeof STORAGE_KEYS[keyof typeof STORAGE_KEYS];
  listPath: string;
  boardPath: string;
};

export const useViewSwitcher = (config: ViewConfig) => {
  const switchToListView = (qParams: Record<string, any>) => {
    setDefaultView(config.storageKey, VIEW_TYPES.LIST);
    navigate(config.listPath, { query: qParams });
  };

  const switchToBoardView = (qParams: Record<string, any>) => {
    setDefaultView(config.storageKey, VIEW_TYPES.BOARD);
    navigate(config.boardPath, { query: qParams });
  };

  return { switchToListView, switchToBoardView };
};

// Usage in components:
const { switchToListView } = useViewSwitcher({
  storageKey: STORAGE_KEYS.SHIFT_VIEW,
  listPath: "/shifting/list",
  boardPath: "/shifting/board"
});

// Replace onListViewBtnClick with:
const onListViewBtnClick = () => switchToListView(qParams);

This approach would:

  1. Reduce code duplication
  2. Ensure consistent implementation across components
  3. Make it easier to modify view switching behavior globally
  4. Improve maintainability

Also applies to: 82-82

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8af90dd and db15f8b.

📒 Files selected for processing (6)
  • src/Routers/routes/ShiftingRoutes.tsx (1 hunks)
  • src/components/Resource/ResourceBoard.tsx (2 hunks)
  • src/components/Resource/ResourceList.tsx (2 hunks)
  • src/components/Shifting/ShiftingBoard.tsx (2 hunks)
  • src/components/Shifting/ShiftingList.tsx (2 hunks)
  • src/components/Users/ManageUsers.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Routers/routes/ShiftingRoutes.tsx
🔇 Additional comments (3)
src/components/Resource/ResourceList.tsx (1)

25-25: LGTM: View persistence implementation looks good!

The implementation correctly uses the setDefaultView utility to persist the view preference when switching to board view.

Also applies to: 41-41

src/components/Users/ManageUsers.tsx (2)

51-53: LGTM: Proper initialization of view preference!

The implementation correctly retrieves the stored view preference with a sensible default of "card" view.


111-115: LGTM: Clean implementation of view persistence!

The handleTabChange function properly manages both the local state and persistent storage of the view preference. The implementation is concise and follows the single responsibility principle.

Also applies to: 124-124

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 (4)
src/Utils/useView.ts (1)

11-21: Consider adding immediate state sync across components

The storage event only fires for changes made in other tabs/windows. Components using this hook won't immediately sync if the view is changed elsewhere in the same window.

Consider implementing a pub/sub system or using a state management solution like Redux/Zustand for immediate cross-component synchronization within the same window.

src/components/Common/View.tsx (2)

16-22: Improve type safety for view keys

Consider using a const assertion to create a type-safe mapping of valid view types.

+  const VIEW_TYPES = ["board", "list"] as const;
+  type ViewType = typeof VIEW_TYPES[number];
+
   const views: Record<
-    "board" | "list",
+    ViewType,
     ComponentType<{ setView: (view: string) => void }>
   > = {
     board,
     list,
   };

24-26: Add runtime validation for view type

The current implementation silently falls back to board view. Consider adding validation and logging.

-  const SelectedView = views[view as keyof typeof views] || board;
+  const SelectedView = views[view as keyof typeof views];
+  if (!SelectedView) {
+    console.warn(`Invalid view type "${view}", falling back to board view`);
+    return <board setView={setView} />;
+  }
 
   return <SelectedView setView={setView} />;
src/components/Resource/ResourceBoard.tsx (1)

38-42: LGTM! Good abstraction of view management.

The component signature change properly implements the view management abstraction, making it reusable and maintainable. The TypeScript typing is well-defined.

Consider documenting the accepted view values ("list", "board") using a TypeScript union type for better type safety and developer experience:

type ViewType = "list" | "board";

interface BoardViewProps {
  setView: (view: ViewType) => void;
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between db15f8b and c7808ad.

📒 Files selected for processing (9)
  • src/Routers/routes/ResourceRoutes.tsx (1 hunks)
  • src/Routers/routes/ShiftingRoutes.tsx (2 hunks)
  • src/Utils/useView.ts (1 hunks)
  • src/components/Common/View.tsx (1 hunks)
  • src/components/Resource/ResourceBoard.tsx (2 hunks)
  • src/components/Resource/ResourceList.tsx (3 hunks)
  • src/components/Shifting/ShiftingBoard.tsx (2 hunks)
  • src/components/Shifting/ShiftingList.tsx (3 hunks)
  • src/components/Users/ManageUsers.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/components/Shifting/ShiftingList.tsx
  • src/Routers/routes/ShiftingRoutes.tsx
  • src/components/Shifting/ShiftingBoard.tsx
  • src/components/Users/ManageUsers.tsx
  • src/components/Resource/ResourceList.tsx
🔇 Additional comments (2)
src/Routers/routes/ResourceRoutes.tsx (1)

10-10: Ensure unique localStorage key for resource view

The View component uses "resourceDefaultView" as the localStorage key, which could conflict with other views.

Consider using a more specific key like "resourcesDefaultView" to avoid conflicts with other features using the View component.

src/components/Resource/ResourceBoard.tsx (1)

97-97: LGTM! Verify integration with useView hook.

The view switching implementation is clean and uses the new abstraction correctly.

Let's verify the integration with the useView hook:

src/Utils/useView.ts Outdated Show resolved Hide resolved
src/Utils/useView.ts Outdated Show resolved Hide resolved
@Mahendar0701
Copy link
Contributor Author

Hey @rithviknishad , @Jacobjeevan can you once check the implementation. Is this correct?

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 (6)
src/Utils/ViewCache.ts (4)

1-3: Consider namespacing for local storage keys.

Currently, getKey just returns the provided name. If multiple modules or features also store keys in local storage using the same literal name, it may cause collisions. Prefixing the returned key, e.g., "VIEW_" + name, can help avoid conflicts.


8-10: Add robustness when local storage is unavailable.

invalidate removes an item from local storage but doesn’t account for scenarios where local storage might not be available or may throw errors in some environments (e.g., private browsing). Wrap this in try/catch if you expect partial or fallback functionality in such edge cases.


15-18: Consider dynamically computing the keys.

The invalidateAll function hardcodes ["users", "resource", "shifting"]. If you add or rename modules in the future, you’ll have to update this function manually. A more dynamic approach or a central constant array might be less error-prone.


20-23: Export getKey for potential reusability.

getKey might be useful in other modules that need consistent naming or read access to the same localStorage keys. Consider exporting it to reduce duplication elsewhere.

src/Utils/useView.ts (2)

7-10: Add validation within updateView for allowed view values.

Currently, any newView string is stored, which might cause unexpected UI states. Verifying that newView is one of the supported views (e.g., "board", "list", etc.) prevents inconsistent data in local storage.


12-21: Ensure polling frequency does not degrade performance.

Calling setInterval every 100ms can become expensive. If the application doesn’t require near-real-time synchronization for the stored view state, consider reducing frequency or using a storage event listener if feasible.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 249be67 and d7f0669.

📒 Files selected for processing (9)
  • src/Utils/ViewCache.ts (1 hunks)
  • src/Utils/useView.ts (1 hunks)
  • src/components/Auth/Login.tsx (2 hunks)
  • src/components/Common/View.tsx (1 hunks)
  • src/components/Resource/ResourceBoard.tsx (3 hunks)
  • src/components/Resource/ResourceList.tsx (3 hunks)
  • src/components/Shifting/ShiftingBoard.tsx (2 hunks)
  • src/components/Shifting/ShiftingList.tsx (3 hunks)
  • src/components/Users/ManageUsers.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/components/Shifting/ShiftingBoard.tsx
  • src/components/Resource/ResourceList.tsx
  • src/components/Shifting/ShiftingList.tsx
  • src/components/Resource/ResourceBoard.tsx
  • src/components/Common/View.tsx
  • src/components/Users/ManageUsers.tsx
🔇 Additional comments (2)
src/components/Auth/Login.tsx (2)

18-18: Import statement looks good.

Importing ViewCache is aligned with the rest of the logic for clearing the user’s view state during login.


103-103: ⚠️ Potential issue

Fix spelling of "invalidateAll" for FiltersCache.

FiltersCache.invaldiateAll() contains a misspelling (“invaldiate”). Please align it with the correct method name: invalidateAll().

- FiltersCache.invaldiateAll();
+ FiltersCache.invalidateAll();

Likely invalid or redundant comment.

@Mahendar0701
Copy link
Contributor Author

@Mahendar0701 The view preferences should be cleared upon user logout. Currently, there is an issue where User A's preferences are retained and applied to User B, which is not the intended behavior.

@nihal467 can you once check. I have done the changes

@Mahendar0701 Mahendar0701 changed the title Fix : View Retention in Users Tab After Navigation and Logout Fix : View Retention in Users Tab After Navigation Dec 26, 2024
@nihal467
Copy link
Member

LGTM

@github-actions github-actions bot added the merge conflict pull requests with merge conflict label Dec 31, 2024
Copy link

👋 Hi, @Mahendar0701,
Conflicts have been detected against the base branch. Please rebase your branch against the base branch.


This message is automatically generated by prince-chrismc/label-merge-conflicts-action so don't hesitate to report issues/improvements there.

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 (2)
src/components/Facility/FacilityUsers.tsx (2)

46-48: Handle potential future expansions for additional view states.

Currently, handleTabChange only toggles between "list" and "card". If more view modes (e.g., "board") are added later, consider using an enumeration or direct string mapping to maintain clarity, prevent confusion, and ease scaling.


68-69: Unify tab-state handling.

You're converting "list" to numeric 1 and everything else to 0, implying an implicit assumption of two states. Consider storing the active tab in the same format (either always numeric or always string) to maintain consistency.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d7f0669 and 1ac3800.

📒 Files selected for processing (1)
  • src/components/Facility/FacilityUsers.tsx (3 hunks)
🔇 Additional comments (2)
src/components/Facility/FacilityUsers.tsx (2)

20-20: Good implementation for storing and reusing view state.

Switching from useState to useView("users") aligns well with the PR objective of persistent view retention.


12-12: Ensure local storage is cleared upon session changes.

Importing and using useView is a good approach to storing user preferences. However, please verify whether the session change logic is handled to avoid applying preferences unintentionally when a new user logs in.

Run a shell script to confirm that useView usage is cleared or updated upon user logout:

✅ Verification successful

Let me gather more information about session handling and local storage clearing.


Let me check how the useView hook is implemented.


Let me try a different approach to find the useView implementation.


Let me check how session and logout are handled in the AuthUserProvider.


No issues with useView and session handling

Based on the code analysis, the concern about session changes is already properly handled:

  1. The useView hook stores preferences in localStorage with proper cleanup:

    • Uses a specific named key for each view preference
    • Updates view state when localStorage changes
    • Defaults to "board" view if no preference exists
  2. Session management is properly implemented in AuthUserProvider:

    • Clears all auth tokens (access and refresh) from localStorage on logout
    • Has cross-tab synchronization to handle logouts from other tabs
    • Redirects to login page after clearing session data

The useView preferences are scoped to specific features using unique keys, and there's no risk of preferences being unintentionally applied across sessions since:

  • Auth tokens are properly cleared on logout
  • New users start with default view preferences
  • View preferences are feature-specific and don't contain sensitive data
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searching for potentially relevant logout or session handling code
rg -A 5 logout
rg -A 5 login
rg -A 5 session

Length of output: 65684


Script:

#!/bin/bash
# Search for session and local storage related code
ast-grep --pattern 'localStorage.clear()'
ast-grep --pattern 'localStorage.removeItem($$$)'
ast-grep --pattern 'localStorage.setItem($$$)'

Length of output: 2566


Script:

#!/bin/bash
# Search for useView implementation
ast-grep --pattern 'export function useView($$$)'
ast-grep --pattern 'export const useView = ($$$)'

Length of output: 103


Script:

#!/bin/bash
# Search for useView file content
cat src/Utils/useView.ts

Length of output: 673


Script:

#!/bin/bash
# Search for AuthUserProvider implementation
cat src/Providers/AuthUserProvider.tsx

Length of output: 3714

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/components/Facility/FacilityUsers.tsx (1)

50-52: Consider abstracting view type conversion logic

The conversion between numeric indices (0/1) and string values ("card"/"list") is duplicated across components. Consider creating a shared utility for this conversion.

+ // src/Utils/viewUtils.ts
+ export const VIEW_TYPES = {
+   CARD: "card",
+   LIST: "list"
+ } as const;
+ 
+ export const viewTypeToIndex = (viewType: string) => 
+   viewType === VIEW_TYPES.LIST ? 1 : 0;
+ 
+ export const indexToViewType = (index: number) =>
+   index === 1 ? VIEW_TYPES.LIST : VIEW_TYPES.CARD;

Then use it in the component:

- const handleTabChange = (tab: number) => {
-   setActiveTab(tab === 1 ? "list" : "card");
- };
+ const handleTabChange = (tab: number) => {
+   setActiveTab(indexToViewType(tab));
+ };

  <UserListView
    users={userListData?.results ?? []}
    onSearch={(username) => updateQuery({ username })}
    searchValue={qParams.username}
-   activeTab={activeTab === "list" ? 1 : 0}
+   activeTab={viewTypeToIndex(activeTab)}
    onTabChange={handleTabChange}
  />

Also applies to: 72-73

src/components/Users/ManageUsers.tsx (1)

101-103: Consider sharing view management logic between components

The view management logic is identical to FacilityUsers. Consider creating a custom hook to encapsulate this common functionality.

+ // src/hooks/useUserView.ts
+ import { useView } from "@/Utils/useView";
+ import { viewTypeToIndex, indexToViewType } from "@/Utils/viewUtils";
+ 
+ export const useUserView = () => {
+   const [activeTab, setActiveTab] = useView("users");
+ 
+   const handleTabChange = (tab: number) => {
+     setActiveTab(indexToViewType(tab));
+   };
+ 
+   return {
+     activeTab: viewTypeToIndex(activeTab),
+     handleTabChange,
+   };
+ };

Then use it in both components:

- const [activeTab, setActiveTab] = useView("users");
- 
- const handleTabChange = (tab: number) => {
-   setActiveTab(tab === 1 ? "list" : "card");
- };
+ const { activeTab, handleTabChange } = useUserView();

  <UserListView
    users={userListData?.results ?? []}
    onSearch={(username) => updateQuery({ username })}
    searchValue={qParams.username}
    activeTab={activeTab}
    onTabChange={handleTabChange}
  />

Also applies to: 111-112

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1ac3800 and 84b32c0.

📒 Files selected for processing (6)
  • public/locale/en.json (3 hunks)
  • src/components/Auth/Login.tsx (2 hunks)
  • src/components/Facility/FacilityUsers.tsx (3 hunks)
  • src/components/Resource/ResourceBoard.tsx (3 hunks)
  • src/components/Resource/ResourceList.tsx (3 hunks)
  • src/components/Users/ManageUsers.tsx (4 hunks)
✅ Files skipped from review due to trivial changes (1)
  • public/locale/en.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/Resource/ResourceList.tsx
  • src/components/Resource/ResourceBoard.tsx
  • src/components/Auth/Login.tsx
🔇 Additional comments (2)
src/components/Facility/FacilityUsers.tsx (1)

22-22: Verify view state key consistency across components

The "users" key is used for view state storage. Since both FacilityUsers and ManageUsers components manage user views, ensure this key doesn't cause conflicts.

✅ Verification successful

View state is properly scoped, no conflicts between components

The useView hook implementation shows that view state is stored in localStorage with the provided key name. From the routes inspection, we can see that ManageUsers and FacilityUsers are rendered on different routes ("/users" and "/facility/:facilityId/users" respectively), meaning they can't be rendered simultaneously. Even though both components use the same "users" key, there won't be any conflicts since:

  1. The components exist on different routes, so only one will be active at a time
  2. The view state is synchronized with localStorage, ensuring consistent state when navigating between routes
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other usages of the "users" key in useView hook
rg "useView\(['\"]users['\"]" 

Length of output: 222


Script:

#!/bin/bash
# Let's check the implementation of useView hook to understand how view state is scoped
ast-grep --pattern 'export function useView($_) {
  $$$
}'

# Also check the component hierarchy to see if these components can be rendered simultaneously
rg -B2 -A2 "FacilityUsers|ManageUsers" "src/**/routes.tsx"

Length of output: 179


Script:

#!/bin/bash
# Let's try finding the routes file with a different approach
fd "routes" --type f

# And let's look for the useView hook implementation in common locations
fd "useView" --type f

# Also check if these components are rendered in any parent components
rg -B2 -A2 "<(FacilityUsers|ManageUsers)"

Length of output: 1360


Script:

#!/bin/bash
# Let's check the implementation of useView hook
cat src/Utils/useView.ts

# Let's also verify these components are rendered on different routes
rg -B2 -A2 "path:|route:" src/Routers/routes/UserRoutes.tsx src/Routers/routes/FacilityRoutes.tsx

Length of output: 773

src/components/Users/ManageUsers.tsx (1)

43-43: LGTM! View state implementation matches FacilityUsers

The implementation consistently uses the useView hook with the same "users" key as FacilityUsers.

@@ -19,6 +19,7 @@ import { USER_TYPES } from "@/common/constants";

import routes from "@/Utils/request/api";
import useTanStackQueryInstead from "@/Utils/request/useQuery";
import { useView } from "@/Utils/useView";
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

View preferences should be cleared during logout

The useView hook stores view preferences in localStorage, but these preferences are not cleared during logout. While the auth-related tokens are properly cleared in the signOut function (AuthUserProvider.tsx), the view preferences persist across sessions. To maintain proper session isolation:

  • Add view preference clearing to the signOut function in AuthUserProvider.tsx
  • Consider using the existing ViewCache.ts utility to manage view-related storage operations

Example locations that need attention:

  • src/Providers/AuthUserProvider.tsx: Add view preference clearing to the signOut function
  • src/Utils/ViewCache.ts: Consider adding a clearAll utility if not already present
🔗 Analysis chain

Verify view retention behavior across user sessions

The implementation stores view preferences in localStorage. To prevent view preferences from persisting across different user sessions, ensure the storage is cleared on logout.

Also applies to: 43-43


Let me search for the implementation of the useView hook to understand how it handles storage.


Let me check how the auth state and logout is handled to see if localStorage is properly cleared.


Let me check if there's a utility to clear view preferences and if it's being used during logout.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for logout handling to verify storage clearing
rg -A 5 "logout|signout|clearStorage|clear\(" 

Length of output: 18775


Script:

#!/bin/bash
# Search for useView implementation
ast-grep --pattern 'export function useView($$$) {
  $$$
}'

# Also search for any references to localStorage in the hook
rg -A 5 "localStorage" src/Utils/useView.ts

Length of output: 500


Script:

#!/bin/bash
# Search for auth-related storage handling
rg -A 10 "signOut|logout" src/Providers/AuthUserProvider.tsx

# Search for any localStorage clear operations
rg -A 5 "localStorage\.clear|removeItem" src/

Length of output: 4325


Script:

#!/bin/bash
# Search for view cache clearing utilities
rg -A 5 "clearAll|clearView" src/Utils/ViewCache.ts

# Search for any usage of view cache clearing in auth-related files
rg -l "ViewCache" src/Providers/AuthUserProvider.tsx src/hooks/usePatientSignOut.ts

Length of output: 137

@rithviknishad
Copy link
Member

no longer relevant in new architecture as most of the relevant things are removed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merge conflict pull requests with merge conflict needs review tested
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Selected View in Users Tab Not Retained After Navigation or Logout
4 participants