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: Layout update of Asset Page #9466

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

Conversation

AdityaJ2305
Copy link
Contributor

@AdityaJ2305 AdityaJ2305 commented Dec 16, 2024

Proposed Changes

@ohcnetwork/care-fe-code-reviewers

Screenshots

Screenshot 2024-12-23 at 8 50 31 PM Screenshot 2024-12-23 at 8 50 56 PM

Merge Checklist

  • Prep screenshot or demo video for changelog entry, and attach it to issue.
  • Request for Peer Reviews

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a new search interface allowing users to search by multiple criteria.
    • Added a button for scanning asset QR codes and creating new assets.
    • Introduced an advanced filter button for enhanced filtering options.
    • Enhanced dropdown functionality with new components for export options.
    • Added a new type for dropdown item properties to allow for flexible usage.
  • Improvements

    • Enhanced layout and responsiveness of buttons and filters.
    • Updated button styles for better visual representation in export functionality.
    • Improved user experience with a more organized interface for asset management.
  • Bug Fixes

    • Maintained error handling for invalid asset IDs during QR scanning.

@AdityaJ2305 AdityaJ2305 requested a review from a team as a code owner December 16, 2024 17:17
Copy link
Contributor

coderabbitai bot commented Dec 16, 2024

Walkthrough

The pull request updates the AssetsList component in the Assets page by introducing a new SearchByMultipleFields component, enhancing search functionality to allow multiple criteria. It replaces the ButtonV2 with a new Button component, modifies the button layout for improved responsiveness, and enhances the useFilters hook with a clearSearch function. The overall layout and styling are refined while maintaining the core asset management operations, including error handling for QR scanning.

Changes

File Change Summary
src/components/Assets/AssetsList.tsx - Replaced SearchInput with SearchByMultipleFields
- Updated useFilters hook to add clearSearch
- Replaced ButtonV2 with Button
- Modified button layout for responsiveness
- Updated method signature for accessAssetIdFromQR
- Added clearSearch and warrantyAmcValidityChip methods
cypress/pageobject/Asset/AssetCreation.ts - Updated selector in createAsset method from data-testid to #create-asset-button
src/CAREUI/interactive/FiltersSlideover.tsx - Replaced ButtonV2 with Button in AdvancedFilterButton
- Updated button properties and text
src/components/Common/Export.tsx - Replaced ButtonV2 with Button in ExportMenu and ExportButton
- Modified button properties and styles
cypress/pageobject/utils/advanceFilterHelpers.ts - Updated selector and label in clickAdvancedFiltersButton method
src/components/Common/Menu.tsx - Added new type ShadcnMenuDropdownItemProps for dropdown items

Assessment against linked issues

Objective Addressed Explanation
Update button layout in Assets Page [#9349]
Preserve mobile view responsiveness

Possibly related PRs

Suggested labels

tested

Suggested reviewers

  • rithviknishad
  • Jacobjeevan

Poem

🐰 Hop, hop, through the assets we go,
Buttons aligned in a neat little row
Search now refined, with magic so bright
Our interface dances with pure delight!
Code rabbits rejoice, the layout's just right! 🔍


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 16, 2024

Deploy Preview for care-ohc ready!

Name Link
🔨 Latest commit 8a1d0ff
🔍 Latest deploy log https://app.netlify.com/sites/care-ohc/deploys/676adadf1292100008e9f081
😎 Deploy Preview https://deploy-preview-9466--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 (2)
src/components/Assets/AssetsList.tsx (2)

434-448: Consider utilizing multi-field search capability

While the implementation is functional, the SearchByMultipleFields component is currently used with only one search field despite its capability to handle multiple fields.

Consider adding more search fields to enhance the search functionality:

 <SearchByMultipleFields
   id="asset-search"
   options={[
     {
       key: "Name/ Serial no./ QR code ID",
       label: "name/serial no./QR code ID",
       type: "text" as const,
       placeholder: "Search by name/serial no./QR code ID",
       value: qParams.search || "",
       shortcutKey: "f",
     },
+    {
+      key: "location",
+      label: "Location",
+      type: "text" as const,
+      placeholder: "Search by location",
+      value: qParams.location || "",
+    },
+    {
+      key: "status",
+      label: "Status",
+      type: "select" as const,
+      placeholder: "Filter by status",
+      value: qParams.status || "",
+      options: [
+        { label: "Working", value: "working" },
+        { label: "Not Working", value: "not_working" },
+      ],
+    },
   ]}
   className="w-full"
   onSearch={(key, value) => updateQuery({ [key]: value })}
   clearSearch={clearSearch}
 />

Line range hint 543-595: Enhance warrantyAmcValidityChip implementation

The function logic is sound, but could benefit from some improvements.

Consider these enhancements:

+const WARRANTY_EXPIRY_THRESHOLDS = {
+  CRITICAL: 30,
+  WARNING: 90,
+} as const;
+
+const getDaysDifference = (date1: Date, date2: Date) =>
+  Math.ceil(Math.abs(Number(date1) - Number(date2)) / (1000 * 60 * 60 * 24));
+
 export const warrantyAmcValidityChip = (
   warranty_amc_end_of_validity: string,
 ) => {
   if (warranty_amc_end_of_validity === "" || !warranty_amc_end_of_validity)
     return;
   const today = new Date();
   const warrantyAmcEndDate = new Date(warranty_amc_end_of_validity);
 
-  const days = Math.ceil(
-    Math.abs(Number(warrantyAmcEndDate) - Number(today)) /
-      (1000 * 60 * 60 * 24),
-  );
+  const days = getDaysDifference(today, warrantyAmcEndDate);
 
   if (warrantyAmcEndDate < today) {
     return (
       <Chip
         id="warranty-amc-expired-red"
         variant="danger"
         startIcon="l-times-circle"
         text="AMC/Warranty Expired"
       />
     );
-  } else if (days <= 30) {
+  } else if (days <= WARRANTY_EXPIRY_THRESHOLDS.CRITICAL) {
     return (
       <Chip
         id="warranty-amc-expiring-soon-orange"
         variant="custom"
         className="border-orange-300 bg-orange-100 text-orange-900"
         startIcon="l-exclamation-circle"
         text="AMC/Warranty Expiring Soon"
       />
     );
-  } else if (days <= 90) {
+  } else if (days <= WARRANTY_EXPIRY_THRESHOLDS.WARNING) {
     return (
       <Chip
         id="warranty-amc-expiring-soon-yellow"
         variant="warning"
         startIcon="l-exclamation-triangle"
         text="AMC/Warranty Expiring Soon"
       />
     );
   }
 };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 96bc802 and 35f5e5c.

📒 Files selected for processing (1)
  • src/components/Assets/AssetsList.tsx (4 hunks)
🔇 Additional comments (2)
src/components/Assets/AssetsList.tsx (2)

Line range hint 30-42: LGTM: Clean import additions and hook update

The new imports and hook updates are well-structured and maintain consistency with the codebase.


Line range hint 359-423: LGTM: Well-structured filter and export functionality

The advanced filter and import/export menu implementation is clean, with proper authorization checks and comprehensive export options.

src/components/Assets/AssetsList.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

🔭 Outside diff range comments (1)
src/components/Assets/AssetsList.tsx (1)

Line range hint 533-589: Handle edge cases in warranty validation

The warranty validation logic should handle invalid date formats and consider timezone implications.

 export const warrantyAmcValidityChip = (
   warranty_amc_end_of_validity: string,
 ) => {
   if (warranty_amc_end_of_validity === "" || !warranty_amc_end_of_validity)
     return;
+  
+  // Validate date format
+  const warrantyAmcEndDate = new Date(warranty_amc_end_of_validity);
+  if (isNaN(warrantyAmcEndDate.getTime())) {
+    console.error(`Invalid warranty date format: ${warranty_amc_end_of_validity}`);
+    return;
+  }
+
   const today = new Date();
-  const warrantyAmcEndDate = new Date(warranty_amc_end_of_validity);
+  // Set time to start of day to avoid timezone issues
+  today.setHours(0, 0, 0, 0);
+  warrantyAmcEndDate.setHours(0, 0, 0, 0);

   const days = Math.ceil(
     Math.abs(Number(warrantyAmcEndDate) - Number(today)) /
       (1000 * 60 * 60 * 24),
   );
🧹 Nitpick comments (1)
src/components/Assets/AssetsList.tsx (1)

431-445: Consider expanding search capabilities

While the SearchByMultipleFields component is a good addition, consider adding more commonly searched fields to improve user experience.

 options={[
   {
     key: "Name/ Serial no./ QR code ID",
     label: "name/serial no./QR code ID",
     type: "text" as const,
     placeholder: "Search by name/serial no./QR code ID",
     value: qParams.search || "",
     shortcutKey: "f",
   },
+  {
+    key: "Asset Class",
+    label: "asset class",
+    type: "text" as const,
+    placeholder: "Search by asset class",
+    value: qParams.asset_class || "",
+  },
+  {
+    key: "Status",
+    label: "status",
+    type: "text" as const,
+    placeholder: "Search by status",
+    value: qParams.status || "",
+  },
 ]}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 35f5e5c and 67f8536.

📒 Files selected for processing (1)
  • src/components/Assets/AssetsList.tsx (4 hunks)
🔇 Additional comments (2)
src/components/Assets/AssetsList.tsx (2)

30-31: LGTM: Clean import declarations

The new imports are properly organized and follow the project's import structure.


Line range hint 322-420: Simplify nested layout structure

The button layout still has unnecessary nesting that can be simplified for better maintainability.

Consider this simplified structure:

-<div className="flex flex-wrap items-center gap-3">
-  <div className="mb-2 flex w-full flex-col items-center gap-3 lg:mb-0 lg:w-fit lg:flex-row lg:gap-5">
-    <div className="w-full lg:w-fit">
+<div className="flex flex-wrap items-center gap-3">
+  <div className="flex w-full flex-wrap items-center gap-3 lg:w-fit">
     <Button
       variant="primary"
       size="lg"
       className="w-full p-[10px] md:w-auto"
       onClick={() => setIsScannerActive(true)}
     >
       <CareIcon icon="l-search" className="text-base mr-2" />
       Scan Asset QR
     </Button>
-    </div>

-    <div className="w-full lg:w-fit" data-testid="create-asset-button">
     <Button
       variant="primary"
       size="lg"
       disabled={!NonReadOnlyUsers}
       className="w-full p-[10px] md:w-auto"
+      data-testid="create-asset-button"
       onClick={() => {
         if (qParams.facility) {
           navigate(`/facility/${qParams.facility}/assets/new`);
         } else {
           setShowFacilityDialog(true);
         }
       }}
     >
       <CareIcon icon="l-plus-circle" className="text-lg mr-2" />
       <span>{t("create_asset")}</span>
     </Button>
-    </div>
   </div>

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/Assets/AssetsList.tsx (2)

432-446: LGTM: Well-implemented search functionality with accessibility

The SearchByMultipleFields implementation is solid with proper configuration and accessibility support via shortcut key.

Consider adding an aria-label to improve screen reader support:

 <SearchByMultipleFields
   id="asset-search"
+  aria-label="Search assets by name, serial number, or QR code ID"
   options={[

Line range hint 533-589: LGTM: Well-implemented warranty validity status logic

The warrantyAmcValidityChip function provides clear visual feedback with proper date handling.

Consider memoizing the chip components to prevent unnecessary re-renders:

+const ExpiredChip = memo(() => (
+  <Chip
+    id="warranty-amc-expired-red"
+    variant="danger"
+    startIcon="l-times-circle"
+    text="AMC/Warranty Expired"
+  />
+));

 export const warrantyAmcValidityChip = (
   warranty_amc_end_of_validity: string,
 ) => {
   if (warranty_amc_end_of_validity === "" || !warranty_amc_end_of_validity)
     return;
   const today = new Date();
   const warrantyAmcEndDate = new Date(warranty_amc_end_of_validity);

   const days = Math.ceil(
     Math.abs(Number(warrantyAmcEndDate) - Number(today)) /
       (1000 * 60 * 60 * 24),
   );

   if (warrantyAmcEndDate < today) {
-    return (
-      <Chip
-        id="warranty-amc-expired-red"
-        variant="danger"
-        startIcon="l-times-circle"
-        text="AMC/Warranty Expired"
-      />
-    );
+    return <ExpiredChip />;
   }
   // Similar changes for other chips...
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 67f8536 and ca7cb2e.

📒 Files selected for processing (2)
  • cypress/pageobject/Asset/AssetCreation.ts (1 hunks)
  • src/components/Assets/AssetsList.tsx (4 hunks)
🔇 Additional comments (3)
cypress/pageobject/Asset/AssetCreation.ts (1)

5-5: LGTM: Selector update improves specificity and fixes typo

The change from [data-testid=create-asset-buttom] button to #create-asset-button is an improvement as it:

  • Uses a more specific and performant ID selector
  • Fixes the typo in the old selector ("buttom")
  • Correctly maps to the button's ID in the UI component
✅ Verification successful

LGTM: Selector change is correctly implemented and matches UI component

The ID selector #create-asset-button in the Cypress test correctly corresponds to the button element in src/components/Assets/AssetsList.tsx where the ID is properly implemented. The change improves test reliability by using a unique, specific selector.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the ID selector exists in the codebase
rg -l 'id="create-asset-button"' 

Length of output: 71


Script:

#!/bin/bash
# Let's verify the actual implementation in AssetsList.tsx to ensure the ID is used correctly
rg -A 2 'id="create-asset-button"' src/components/Assets/AssetsList.tsx

Length of output: 213

src/components/Assets/AssetsList.tsx (2)

30-31: LGTM: Clean integration of new components and hooks

The new imports and hook updates properly support the UI enhancements.

Also applies to: 42-42


322-355: Consider simplifying the nested layout structure

The button layout still has unnecessary nesting that could be simplified while maintaining the same functionality.

@AdityaJ2305
Copy link
Contributor Author

I don’t think the Cypress tests failed due to the changes in this PR. Could someone confirm?

@github-actions github-actions bot added needs-triage question Further information is requested labels Dec 16, 2024
@Jacobjeevan Jacobjeevan added needs testing needs review and removed question Further information is requested needs-triage labels Dec 17, 2024
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/Assets/AssetsList.tsx (2)

432-446: Enhance search capabilities

The SearchByMultipleFields component is currently configured with only one search option. Consider adding more relevant search fields to fully utilize its capabilities.

 options={[
   {
     key: "Name/ Serial no./ QR code ID",
     label: "name/serial no./QR code ID",
     type: "text" as const,
     placeholder: "Search by name/serial no./QR code ID",
     value: qParams.search || "",
     shortcutKey: "f",
   },
+  {
+    key: "location",
+    label: "Location",
+    type: "text" as const,
+    placeholder: "Search by location",
+    value: qParams.location || "",
+  },
+  {
+    key: "asset_class",
+    label: "Asset Class",
+    type: "text" as const,
+    placeholder: "Search by asset class",
+    value: qParams.asset_class || "",
+  }
 ]}

Line range hint 533-599: Improve date handling and maintainability

The warrantyAmcValidityChip function could benefit from the following improvements:

  1. Extract magic numbers as named constants
  2. Simplify date difference calculation
  3. Add JSDoc documentation for better maintainability
+const EXPIRY_THRESHOLDS = {
+  CRITICAL: 30,
+  WARNING: 90,
+} as const;
+
+/**
+ * Generates a chip component based on warranty/AMC validity status
+ * @param warranty_amc_end_of_validity - The end date of warranty/AMC
+ * @returns A Chip component indicating the warranty/AMC status
+ */
 export const warrantyAmcValidityChip = (
   warranty_amc_end_of_validity: string,
 ) => {
   if (warranty_amc_end_of_validity === "" || !warranty_amc_end_of_validity)
     return;
   const today = new Date();
   const warrantyAmcEndDate = new Date(warranty_amc_end_of_validity);
 
-  const days = Math.ceil(
-    Math.abs(Number(warrantyAmcEndDate) - Number(today)) /
-      (1000 * 60 * 60 * 24),
-  );
+  const days = Math.ceil((warrantyAmcEndDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24));
 
   if (warrantyAmcEndDate < today) {
     return (
       <Chip
         id="warranty-amc-expired-red"
         variant="danger"
         startIcon="l-times-circle"
         text="AMC/Warranty Expired"
       />
     );
-  } else if (days <= 30) {
+  } else if (days <= EXPIRY_THRESHOLDS.CRITICAL) {
     return (
       <Chip
         id="warranty-amc-expiring-soon-orange"
         variant="custom"
         className="border-orange-300 bg-orange-100 text-orange-900"
         startIcon="l-exclamation-circle"
         text="AMC/Warranty Expiring Soon"
       />
     );
-  } else if (days <= 90) {
+  } else if (days <= EXPIRY_THRESHOLDS.WARNING) {
     return (
       <Chip
         id="warranty-amc-expiring-soon-yellow"
         variant="warning"
         startIcon="l-exclamation-triangle"
         text="AMC/Warranty Expiring Soon"
       />
     );
   }
 };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ca7cb2e and d0fa0c9.

📒 Files selected for processing (1)
  • src/components/Assets/AssetsList.tsx (4 hunks)
🔇 Additional comments (1)
src/components/Assets/AssetsList.tsx (1)

322-363: Simplify nested layout structure

The button layout has unnecessary nesting and duplicate flex containers that can be simplified.

src/components/Assets/AssetsList.tsx Show resolved Hide resolved
@github-actions github-actions bot added the Deploy-Failed Deplyment is not showing preview label Dec 17, 2024
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 (1)
src/components/Assets/AssetsList.tsx (1)

322-363: 🛠️ Refactor suggestion

Simplify nested layout structure

The button layout still has unnecessary nesting that can be simplified. Consider the previous suggestion to reduce the nesting levels.

Apply this diff to simplify the layout:

-        <div className="flex flex-wrap items-center gap-3">
-          <div className="mb-2 flex w-full flex-col items-center gap-3 lg:mb-0 lg:w-fit lg:flex-row lg:gap-5">
-            <div className="w-full lg:w-fit">
+        <div className="flex flex-wrap items-center gap-3">
+          <div className="flex w-full flex-wrap items-center gap-3 lg:w-fit">
               <Button
                 variant="primary"
                 size="lg"
                 className="w-full p-[10px] md:w-auto"
                 onClick={() => setIsScannerActive(true)}
               >
                 <CareIcon icon="l-search" className="text-base mr-2" />
                 Scan Asset QR
               </Button>
-            </div>

-            <div className="w-full lg:w-fit">
               <Button
                 variant="primary"
                 size="lg"
                 id="create-asset-button"
                 disabled={!NonReadOnlyUsers}
                 className="w-full p-[10px] md:w-auto"
                 onClick={() => {
                   if (qParams.facility) {
                     navigate(`/facility/${qParams.facility}/assets/new`);
                   } else {
                     setShowFacilityDialog(true);
                   }
                 }}
               >
                 <CareIcon icon="l-plus-circle" className="text-lg mr-2" />
                 <span>{t("create_asset")}</span>
               </Button>
-            </div>
           </div>
🧹 Nitpick comments (2)
src/components/Assets/AssetsList.tsx (2)

424-431: Improve responsive layout for count block

The count block's empty className prop and the flex layout could be improved for better responsiveness.

Apply this diff:

-      <div className="mt-4 gap-4 lg:gap-16 flex flex-col lg:flex-row lg:items-center">
+      <div className="mt-4 flex flex-col gap-4 lg:flex-row lg:items-center lg:gap-16">
         <CountBlock
           text="Total Assets"
           count={totalCount}
           loading={loading}
           icon="d-folder"
-          className=""
+          className="w-full lg:w-auto"
         />

436-442: Improve search field label clarity

The search field's key and label could be more consistent and clearer.

Apply this diff:

             {
-              key: "Name/ Serial no./ QR code ID",
-              label: "name/serial no./QR code ID",
+              key: "asset_search",
+              label: "Name / Serial No. / QR Code ID",
               type: "text" as const,
-              placeholder: "Search by Name / Serial no. / QR code ID",
+              placeholder: "Search by Name / Serial No. / QR Code ID",
               value: qParams.search || "",
               shortcutKey: "f",
             },
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ca7cb2e and ddcdbf4.

📒 Files selected for processing (1)
  • src/components/Assets/AssetsList.tsx (4 hunks)
🔇 Additional comments (3)
src/components/Assets/AssetsList.tsx (3)

11-12: LGTM: Import changes align with component updates

The new imports for Button and SearchByMultipleFields components are correctly structured and follow the absolute import pattern.

Also applies to: 19-19


Line range hint 530-589: LGTM: Well-structured warranty/AMC validation logic

The warrantyAmcValidityChip function is well-implemented with clear conditions and appropriate visual indicators for different warranty states.


42-42: Verify search functionality regression

The new SearchByMultipleFields component and clearSearch hook integration look good, but we should verify that the search functionality works as expected with the new implementation.

Run the following script to check for any existing tests covering the search functionality:

Also applies to: 432-446

✅ Verification successful

Search functionality is well-tested and implemented correctly

The search functionality has been thoroughly verified through the following findings:

  1. The SearchByMultipleFields component is properly integrated with appropriate props including the clearSearch functionality
  2. The useFilters hook correctly implements the clearSearch state management
  3. Comprehensive Cypress test coverage exists in cypress/e2e/assets_spec/ that specifically tests:
    • Search by asset name
    • Search by QR code
    • Search by serial number
    • Filter badge presence verification
    • Search result verification

The implementation and test coverage indicate that the search functionality is working as expected with the new changes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for search-related test coverage
rg -A 5 "asset-search|SearchByMultipleFields" --type=spec --type=test

Length of output: 100


Script:

#!/bin/bash
# Let's try a broader search for test files first
fd "test|spec" --type f

# Then search for any test files related to assets or search
rg -l "AssetsList|SearchByMultipleFields|clearSearch" --type=typescript

Length of output: 264


Script:

#!/bin/bash
# Search for test files with .test or .spec extensions
fd "\.(test|spec)\.(ts|tsx|js|jsx)$"

# Search for any files containing our search terms without file type restriction
rg -l "AssetsList|SearchByMultipleFields|clearSearch"

# Look for the implementation of SearchByMultipleFields to understand the search functionality
ast-grep --pattern 'const SearchByMultipleFields = $_'

Length of output: 500


Script:

#!/bin/bash
# Let's examine the implementation of SearchByMultipleFields and its usage in AssetsList
rg -A 10 "SearchByMultipleFields" src/components/Common/SearchByMultipleFields.tsx
rg -A 10 "SearchByMultipleFields" src/components/Assets/AssetsList.tsx

# Check the useFilters hook implementation since it's related to clearSearch
rg -A 10 "clearSearch" src/hooks/useFilters.tsx

# Look for any Cypress tests that might cover asset search functionality
rg -A 10 "asset.*search" cypress/e2e --ignore-case

Length of output: 10244

@AdityaJ2305
Copy link
Contributor Author

  • keep the spacing between the button consistent
  • change the remaining advance filter and export button to use shadcn as well
  • rename advanced filter to filters

@nihal467

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 (4)
src/components/Common/Export.tsx (3)

3-3: Prefer consistent import usage throughout the codebase.
You introduced the new Button import, but the file still references ButtonV2. Consider using one button component for clarity.


84-84: Nitpick: Remove extra classes or ensure consistent styling.
The className merges border, text, and hover classes. Confirm that this doesn't conflict with overall theming.


135-135: Move away from inline color naming in class names.
"bg-red" can be replaced with a token-based utility class if your design system supports it.

src/components/Assets/AssetsList.tsx (1)

322-356: Simplify nested containers.
Deeply nested flex containers might be reduced. This also mirrors older feedback suggesting simpler layout structures.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7851d0e and e36eb05.

📒 Files selected for processing (3)
  • src/CAREUI/interactive/FiltersSlideover.tsx (2 hunks)
  • src/components/Assets/AssetsList.tsx (4 hunks)
  • src/components/Common/Export.tsx (5 hunks)
🔇 Additional comments (8)
src/components/Common/Export.tsx (1)

Line range hint 54-74: Style and variant usage look clean.
Thanks for aligning these button props with the new design system. The variant="outline_primary" works well with the "Exporting..." text.

src/CAREUI/interactive/FiltersSlideover.tsx (2)

7-8: Good to see the new Button usage.
This maintains consistency with the rest of the app’s UI library.


63-71: Renaming "advanced_filters" to "filters" is consistent with user feedback.
The reduced wording helps the UI remain concise.

src/components/Assets/AssetsList.tsx (5)

11-19: Excellent substitution of SearchByMultipleFields and the new Button.
Both changes enhance the interface and improve usability.


357-363: “Filters” button usage is a great improvement.
It’s simpler than the old “Advanced Filter” label, matching the naming guidelines suggested in PR comments.


Line range hint 366-421: Tooltip usage.
Check if the tooltip fully references the new design system. Some design tokens might differ for tooltips.

✅ Verification successful

Let me search for tooltip-related implementations and design system references to verify this concern.


Let me check the design system's tooltip implementation specifically.


Tooltip implementation uses current design system tokens

The tooltip implementation in src/style/CAREUI.css already follows the design system's patterns using Tailwind classes and design tokens:

  • Uses @apply directives with design system tokens like bg-black/75, text-white, rounded
  • Implements consistent spacing, transitions, and z-index management
  • Properly handles backdrop blur and opacity

The tooltip in AssetsList.tsx is using this standard implementation from the design system, and no changes are needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for tooltip class usage and implementation
rg -l "className=\"tooltip\"" 

# Search for tooltip-related styles or design tokens
rg "tooltip" -g "*.css" -g "*.scss"

# Search for design system tooltip components
ast-grep --pattern 'import { $_ } from "@care/$_"' 

Length of output: 1226


Script:

#!/bin/bash
# Check the tooltip implementation in CAREUI.css
cat src/style/CAREUI.css | grep -A 10 "\.tooltip"

# Search for any new design system tooltip components
rg -l "Tooltip" --type typescript

# Check if there's a dedicated tooltip component in the design system
fd -e tsx -e ts -p "Tooltip" src/CAREUI/

Length of output: 1211


424-449: Ensure thorough testing of new search capabilities.
With the new “clearSearch” function, confirm each search param is cleared as intended.

✅ Verification successful

Let me gather information about the search functionality and the clearSearch implementation.


Let me search for the implementation of clearSearch and the query parameter handling to understand how the search clearing works.


Let me try to find the useFilters hook implementation which seems to be the core of the search functionality.


Based on the comprehensive code review, I can now provide the final response:

Search functionality is properly implemented with clear parameter handling
The search functionality is well-implemented with proper clearing mechanism:

  • The clearSearch state in useFilters hook properly manages clearing search parameters
  • The SearchByMultipleFields component correctly handles the clearing through useEffect that watches clearSearch changes
  • The search field properly resets when clearSearch is triggered through the removeFilters function
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Find the clearSearch implementation and related search functionality
ast-grep --pattern 'const clearSearch = $_'

# Find any tests related to search functionality
fd "test|spec" -e ts -e tsx -e js -e jsx --exec rg -l "clearSearch|SearchByMultipleFields"

# Look for other usages of SearchByMultipleFields to understand the pattern
rg "SearchByMultipleFields" -A 5 -B 5

Length of output: 9208


Script:

#!/bin/bash
# Find clearSearch implementation in AssetsList.tsx
rg -B 10 -A 2 "clearSearch" src/components/Assets/AssetsList.tsx

# Look for updateQuery implementation which is used in the search
rg -B 5 -A 5 "updateQuery" src/components/Assets/AssetsList.tsx

# Check the useFilters hook implementation since it's imported and likely handles the search state
rg -B 10 -A 10 "useFilters" src/hooks/useFilters.ts

Length of output: 1472


Script:

#!/bin/bash
# Find useFilters hook implementation
fd useFilters -t f --exec rg -l "export.*useFilters"

# Look for the actual implementation
fd useFilters -t f --exec cat {}

# Check SearchByMultipleFields component implementation
cat src/components/Common/SearchByMultipleFields.tsx

Length of output: 17476


42-42: clearSearch
Ensure it resets all fields consistently, including advanced filters.

✅ Verification successful

Let me search for the implementation and usage of clearSearch to verify its behavior.


Let me search for the implementation of advanced filters to verify how they interact with the search clearing mechanism.


Based on the analysis of the codebase, I can now generate the final response:

clearSearch implementation is consistent with advanced filters
The implementation in useFilters hook shows that clearSearch is properly integrated with the filter management system. When clearSearch is triggered:

  1. It's handled by SearchByMultipleFields component which clears the search input
  2. The useFilters hook manages both search and advanced filters separately, ensuring they don't interfere with each other
  3. Advanced filters are managed through the advancedFilter prop and have their own clear mechanism via removeFilters
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Find the implementation of clearSearch
ast-grep --pattern 'clearSearch = $_'

# Also search for any direct assignments or declarations
ast-grep --pattern 'const clearSearch = $_'

# Search for any function declarations
ast-grep --pattern 'function clearSearch($_) { $$$ }'

# Search for any method declarations
ast-grep --pattern 'clearSearch($_) { $$$ }'

# Backup search using ripgrep for any mentions
rg "clearSearch" -A 5

Length of output: 7223


Script:

#!/bin/bash
# Search for AssetFilter implementation
ast-grep --pattern 'const AssetFilter = $_'

# Search for the filter implementation in the Assets directory
rg -A 10 "AssetFilter" src/components/Assets/

# Look for filter-related state management
rg "useFilters" -A 10

Length of output: 30521

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e36eb05 and e3adf77.

📒 Files selected for processing (2)
  • cypress/pageobject/utils/advanceFilterHelpers.ts (1 hunks)
  • src/CAREUI/interactive/FiltersSlideover.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/CAREUI/interactive/FiltersSlideover.tsx

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e3adf77 and c1adae7.

📒 Files selected for processing (2)
  • src/components/Common/Export.tsx (6 hunks)
  • src/components/Common/Menu.tsx (1 hunks)
🧰 Additional context used
🪛 eslint
src/components/Common/Export.tsx

[error] 114-114: React Hook "useIsAuthorized" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.

(react-hooks/rules-of-hooks)

🪛 GitHub Check: lint
src/components/Common/Export.tsx

[failure] 114-114:
React Hook "useIsAuthorized" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function

🔇 Additional comments (5)
src/components/Common/Menu.tsx (1)

79-86: New type definition "ShadcnMenuDropdownItemProps" looks good.
This type provides flexibility for dropdown items, especially with the optional "onClick" and "icon" fields.

src/components/Common/Export.tsx (4)

20-20: Good update to the "ExportItem" interface.
Switching from "DropdownItemProps" to "ShadcnMenuDropdownItemProps" correctly aligns the export menu items with the new dropdown structure.


Line range hint 57-77: Single-item export flow is well handled.
The logic to decide and invoke the export action (if present) is straightforward and consistent with the existing flow.

🧰 Tools
🪛 eslint

[error] 114-114: React Hook "useIsAuthorized" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.

(react-hooks/rules-of-hooks)

🪛 GitHub Check: lint

[failure] 114-114:
React Hook "useIsAuthorized" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function


85-94: Dropdown trigger usage looks clean.
Using "asChild" ensures the Button is rendered properly while avoiding nested button issues. The layout is also consistent, showing the export icon and label.


Line range hint 141-166: ExportButton modifications are consistent.
Replacing "ButtonV2" with the new "Button" while preserving export logic and interface is well executed.

src/components/Common/Export.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: 2

🔭 Outside diff range comments (1)
src/components/Common/Export.tsx (1)

Line range hint 150-194: Refactor duplicate export logic and migrate to shadcn Button

The export handling logic is duplicated between ExportButton and ExportMenu. Additionally, this component still uses ButtonV2 while the rest of the file uses shadcn's Button.

  1. Extract the common export logic into a shared function
  2. Migrate to the shadcn Button component for consistency

Example refactor:

// Extract shared logic
const createExportAction = (action: ExportItem['action'], route?: Route<string | { results: object[] }, unknown>) => {
  if (route) {
    return async () => {
      try {
        const { data } = await request(route);
        return data ?? null;
      } catch (error) {
        console.error('Export request failed:', error);
        return null;
      }
    };
  }
  return action;
};

// Use in ExportButton
<Button
  disabled={isExporting || props.disabled}
  onClick={() => {
    const action = createExportAction(props.action, props.route);
    if (action) {
      exportFile(action, props.filenamePrefix, type, parse);
    }
  }}
  size="icon"
  variant="outline"
  className="mx-2"
>
  {isExporting ? (
    <CareIcon icon="l-spinner-alt" className="animate-spin" />
  ) : (
    <CareIcon icon="l-export" />
  )}
  <span className={`tooltip-text ${tooltipClassName}`}>
    {props.tooltip || "Export"}
  </span>
</Button>
🧹 Nitpick comments (1)
src/components/Common/Export.tsx (1)

Line range hint 99-119: Add error handling for failed export requests

The export functionality makes API requests but doesn't handle potential failures. Consider adding error handling and user feedback.

Example improvement:

 onClick={() => {
   let action = item.action;
   if (item.route) {
     action = async () => {
-      const { data } = await request(item.route!);
-      return data ?? null;
+      try {
+        const { data } = await request(item.route!);
+        return data ?? null;
+      } catch (error) {
+        console.error('Export request failed:', error);
+        // Add toast notification or other user feedback
+        return null;
+      }
     };
   }
   if (action) {
     exportFile(action, item.filePrefix, item.type, item.parse);
   }
 }}

Also applies to: 125-145

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c1adae7 and a1d19d3.

📒 Files selected for processing (1)
  • src/components/Common/Export.tsx (4 hunks)
🧰 Additional context used
🪛 eslint
src/components/Common/Export.tsx

[error] 60-60: React Hook "useIsAuthorized" is called conditionally. React Hooks must be called in the exact same order in every component render.

(react-hooks/rules-of-hooks)

🪛 GitHub Check: lint
src/components/Common/Export.tsx

[failure] 60-60:
React Hook "useIsAuthorized" is called conditionally. React Hooks must be called in the exact same order in every component render

src/components/Common/Export.tsx Outdated Show resolved Hide resolved
src/components/Common/Export.tsx Outdated Show resolved Hide resolved
@AdityaJ2305
Copy link
Contributor Author

Screenshot 2024-12-24 at 8 00 49 AM Screenshot 2024-12-24 at 8 01 03 AM

Copy link
Contributor

@Jacobjeevan Jacobjeevan left a comment

Choose a reason for hiding this comment

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

lgtm otherwise

@@ -4,6 +4,8 @@ import { useTranslation } from "react-i18next";
import CareIcon from "@/CAREUI/icons/CareIcon";
import SlideOver from "@/CAREUI/interactive/SlideOver";

import { Button } from "@/components/ui/button";

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's remove the ButtonV2 import below (and make sure to sub out any uses of ButtonV2).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This file is using ButtonV2 here 👇
Export.tsx - Line 109

Using the Button from Shadcn breaks the UI on other pages like the resource and shifting pages. Here’s an image showing the issue (button beside the title) 👇

Screenshot 2024-12-24 at 4 30 18 PM

src/components/Common/Export.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 (1)
src/components/Common/Export.tsx (1)

Line range hint 99-119: Consider reusing ExportMenuItem logic for consistency.

The single item case could be refactored to reuse the ExportMenuItem logic to maintain consistency and reduce code duplication.

- <Button
-   disabled={isExporting || disabled}
-   size="default"
-   onClick={() => {
-     let action = item.action;
-     if (item.route) {
-       action = async () => {
-         const { data } = await request(item.route!);
-         return data ?? null;
-       };
-     }
-     if (action) {
-       exportFile(action, item.filePrefix, item.type, item.parse);
-     }
-   }}
-   variant="outline_primary"
-   className="py-2.5"
- >
-   <CareIcon icon="l-export" className="mr-1" />
-   {isExporting ? "Exporting..." : label}
- </Button>
+ <Button
+   disabled={isExporting || disabled}
+   size="default"
+   variant="outline_primary"
+   className="py-2.5"
+   onClick={() => {
+     const menuItem = document.createElement('div');
+     const exportMenuItem = <ExportMenuItem item={item} exportFile={exportFile} />;
+     ReactDOM.render(exportMenuItem, menuItem);
+     menuItem.querySelector('button')?.click();
+   }}
+ >
+   <CareIcon icon="l-export" className="mr-1" />
+   {isExporting ? "Exporting..." : label}
+ </Button>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2d721bd and 7278966.

📒 Files selected for processing (1)
  • src/components/Common/Export.tsx (4 hunks)
🔇 Additional comments (5)
src/components/Common/Export.tsx (5)

3-12: LGTM: Import statements follow the absolute import pattern.

The new shadcn UI component imports are correctly structured using absolute imports.


22-22: LGTM: Interface update aligns with the new shadcn components.

The ExportItem interface has been updated to use ShadcnMenuDropdownItemProps.


47-87: LGTM: ExportMenuItem implementation follows React best practices.

The component correctly:

  • Uses hooks at the top level
  • Provides a fallback for authorization
  • Handles both action and onClick scenarios properly

125-145: LGTM: Clean implementation of shadcn dropdown menu.

The dropdown implementation correctly uses shadcn components and properly maps ExportMenuItem components.


Line range hint 151-190: Complete the migration to shadcn Button component.

The ExportButton component still uses ButtonV2. For consistency with the rest of the codebase, migrate it to use the shadcn Button component.

- <ButtonV2
-   disabled={isExporting || props.disabled}
-   onClick={() => {
-     let action = props.action;
-     if (props.route) {
-       action = async () => {
-         const { data } = await request(props.route!);
-         return data ?? null;
-       };
-     }
-     if (action) {
-       exportFile(action, props.filenamePrefix, type, parse);
-     }
-   }}
-   className="tooltip mx-2 p-4 text-lg text-secondary-800 disabled:bg-transparent disabled:text-secondary-500"
-   variant="secondary"
-   ghost
-   circle
- >
+ <Button
+   disabled={isExporting || props.disabled}
+   onClick={() => {
+     let action = props.action;
+     if (props.route) {
+       action = async () => {
+         const { data } = await request(props.route!);
+         return data ?? null;
+       };
+     }
+     if (action) {
+       exportFile(action, props.filenamePrefix, type, parse);
+     }
+   }}
+   className="tooltip mx-2 p-4 text-lg text-secondary-800 disabled:bg-transparent disabled:text-secondary-500"
+   variant="ghost"
+   size="icon"
+ >

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

Successfully merging this pull request may close these issues.

Enhancement: Update the button layout in Assets Page
4 participants