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(bulk-vehicle-mileage): Fixes #16210

Merged
merged 11 commits into from
Oct 1, 2024
Merged

fix(bulk-vehicle-mileage): Fixes #16210

merged 11 commits into from
Oct 1, 2024

Conversation

thorkellmani
Copy link
Member

@thorkellmani thorkellmani commented Sep 30, 2024

...

Attach a link to issue if relevant

What

Specify what you're trying to achieve

Why

Specify why you need to achieve this

Screenshots / Gifs

Attach Screenshots / Gifs to help reviewers understand the scope of the pull request

Checklist:

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • Formatting passes locally with my changes
  • I have rebased against main before asking for a review

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced new GraphQL mutations and queries for managing vehicle mileage, including functionalities for posting and updating mileage.
    • Added enhanced error handling and user feedback mechanisms in the vehicle mileage registration process.
  • Improvements

    • Simplified vehicle data handling by making certain fields optional, improving flexibility in data responses.
    • Streamlined components by removing unnecessary state management related to vehicle submission statuses.
    • Enhanced the CSV parsing function with improved error handling and validation processes.
  • Bug Fixes

    • Resolved issues with file uploads and error message persistence, ensuring a smoother user experience.
  • Documentation

    • Updated message identifiers for better clarity and organization within the service portal.

@thorkellmani thorkellmani requested a review from a team as a code owner September 30, 2024 11:23
Copy link
Contributor

coderabbitai bot commented Sep 30, 2024

Walkthrough

The pull request introduces several changes across multiple files, primarily focusing on the MileageDetails class and the VehiclesService class. Key modifications include making certain fields optional in the data models, simplifying vehicle data validation logic, and enhancing GraphQL operations related to vehicle mileage management. Additionally, various components have been updated to streamline state management and improve data handling for vehicle mileage entries.

Changes

File Change Summary
libs/api/domains/vehicles/src/lib/models/v3/mileageDetails.model.ts Updated canRegisterMileage and requiresMileageRegistration fields to be optional by changing their definitions from non-nullable to nullable.
libs/api/domains/vehicles/src/lib/services/vehicles.service.ts Simplified getVehiclesListV3 method by removing checks for canRegisterMileage and requiresMileageRegistration, now assigning undefined if these properties are not present.
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql Added new GraphQL mutations for posting and updating vehicle mileage, new queries for retrieving user mileage, and a new fragment for mileage registration.
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.tsx Removed SubmissionState type and submissionStatus property from vehicle objects, simplifying the data structure and removing related state management.
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx Removed onSave prop and integrated GraphQL hooks for mileage data fetching and mutation, enhanced state management for submission status.
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageSaveButton.tsx Renamed submissionState to submissionStatus and updated its type, refined button state logic based on submission status.
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageTable.tsx Removed updateVehicleStatus prop and related logic for handling vehicle statuses, adjusted rendering logic for the table.
libs/service-portal/assets/src/screens/VehicleBulkMileage/types.ts Removed submissionStatus from VehicleProps interface and replaced SubmissionState with SubmissionStatus, simplifying state representation.
libs/service-portal/assets/src/screens/VehicleBulkMileageJobDetail/VehicleBulkMileageJobDetail.tsx Removed useMemo hook for constructing tableArray, integrated logic directly into JSX return statement.
libs/service-portal/assets/src/utils/parseCsvToMileage.ts Enhanced parseCsvToMileageRecord function to validate CSV headers and improve error handling, updated method signature to reflect changes.
libs/service-portal/core/src/lib/messages.ts Renamed message IDs for clarity and added descriptions to certain messages.

Possibly related PRs

Suggested reviewers

  • thorkellmani

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 13b97c2 and 7a86fde.

📒 Files selected for processing (1)
  • libs/api/domains/vehicles/src/lib/services/vehicles.service.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/api/domains/vehicles/src/lib/services/vehicles.service.ts

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 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.

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

codecov bot commented Sep 30, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 36.69%. Comparing base (ff7d751) to head (7a86fde).
Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #16210      +/-   ##
==========================================
- Coverage   36.76%   36.69%   -0.07%     
==========================================
  Files        6785     6779       -6     
  Lines      139900   139596     -304     
  Branches    39772    39693      -79     
==========================================
- Hits        51435    51227     -208     
+ Misses      88465    88369      -96     
Flag Coverage Δ
api 3.39% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
libs/service-portal/core/src/lib/messages.ts 50.00% <ø> (ø)

... and 41 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ff7d751...7a86fde. Read the comment docs.

@datadog-island-is
Copy link

datadog-island-is bot commented Sep 30, 2024

Datadog Report

All test runs b4ee0ce 🔗

3 Total Test Services: 0 Failed, 2 Passed
➡️ Test Sessions change in coverage: 22 no change

Test Services
Service Name Failed Known Flaky New Flaky Passed Skipped Total Time Code Coverage Change Test Service View
api 0 0 0 4 0 2.6s 1 no change Link
service-portal-core 0 0 0 5 0 1.83s N/A Link
service-portal-health 0 0 0 0 0 502.43ms 1 no change Link

Copy link
Member

@thordurhhh thordurhhh left a comment

Choose a reason for hiding this comment

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

🚂

@thordurhhh thordurhhh self-requested a review September 30, 2024 13:55
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: 8

🧹 Outside diff range and nitpick comments (19)
libs/api/domains/vehicles/src/lib/models/v3/mileageDetails.model.ts (1)

Line range hint 1-15: Overall changes align with coding guidelines and improve flexibility.

The modifications to MileageDetails adhere to the coding guidelines for the libs directory:

  • The class remains reusable across different NextJS apps.
  • TypeScript is used effectively for defining props and exporting types.
  • The changes don't negatively impact tree-shaking or bundling.

The increased flexibility in the data model is a positive change. However, it's crucial to ensure that this flexibility is handled consistently throughout the codebase.

Consider adding documentation comments to explain the scenarios where these fields might be null or undefined. This will help other developers understand and correctly handle these cases in the future.

libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageFileDownloader.tsx (1)

20-24: LGTM! Consider adding a comment for clarity.

The changes to the downloadFile function parameters look good. The updated headers and data format seem more aligned with backend expectations or international standards. The additional data entry provides a more comprehensive example.

Consider adding a brief comment explaining the purpose of these changes, especially the reason for updating the headers and adding an extra data entry. This would improve code maintainability and help future developers understand the rationale behind these modifications.

 downloadFile(
   `magnskraning_kilometrastodu_example`,
+  // Updated headers and added extra entry for better example representation
   ['permno', 'mileage'],
   [
     ['ABC001', 10000],
     ['DEF002', 99999],
   ],
   'csv',
 )
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageSaveButton.tsx (3)

10-10: LGTM: Improved prop naming and type safety

The renaming of submissionState to submissionStatus and updating its type to SubmissionStatus improves clarity and type safety. This change enhances the component's API and makes it more self-descriptive.

For consistency, consider updating the file name to reflect the new terminology, e.g., VehicleBulkMileageStatusButton.tsx.


Line range hint 21-40: LGTM: Improved switch statement logic

The updated switch statement correctly uses the new submissionStatus prop and covers all possible status values, including a default case. This change improves the robustness of the component.

To enhance readability, consider extracting the tag objects into named constants. For example:

const SUCCESS_TAG = {
  text: formatMessage(coreMessages.saved),
  icon: 'checkmarkCircle' as const,
};

const ERROR_TAG = {
  text: formatMessage(coreMessages.errorTitle),
  icon: 'closeCircle' as const,
};

const DEFAULT_TAG = {
  text: formatMessage(coreMessages.save),
  icon: 'pencil' as const,
};

// Then in the switch statement:
switch (submissionStatus) {
  case 'success':
    return SUCCESS_TAG;
  case 'error':
    return ERROR_TAG;
  default:
    return DEFAULT_TAG;
}

This approach would make the code more maintainable and easier to read at a glance.


47-47: LGTM: Added loading state to Button component

The addition of the loading prop to the Button component improves the user experience by providing visual feedback during the submission process. The use of a ternary operator for setting the loading state is concise and appropriate.

For consistency with how other button states are handled, consider moving the loading state logic into the useMemo hook. This would centralize all state-dependent button properties. For example:

const buttonProps = useMemo(() => {
  const tag = // ... existing tag logic ...

  return {
    ...tag,
    loading: submissionStatus === 'loading',
  };
}, [formatMessage, submissionStatus]);

// Then in the Button component:
<Button
  {...buttonProps}
  size="small"
  type="button"
  variant="text"
  onClick={onClick}
  disabled={disabled}
>
  {buttonProps.text}
</Button>

This approach would make it easier to add or modify button properties based on the submission status in the future.

libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageTable.tsx (2)

14-23: LGTM: Component simplification

The removal of form-related logic and the simplification of the VehicleBulkMileageRow props improve the component's focus and potential reusability. This aligns well with the coding guidelines for reusable components.

Consider memoizing the formatMessage function to optimize performance:

const memoizedFormatMessage = useMemo(() => formatMessage, [formatMessage]);

Then use memoizedFormatMessage in the useMemo hook for rows.


Line range hint 29-43: LGTM: Improved rendering logic

The changes to the rendering logic, including conditional rendering based on the loading state and the removal of the last registration column, improve the component's clarity and potentially its performance.

For better code clarity, consider extracting the table rendering into a separate memoized component:

const MileageTable = memo(({ rows, formatMessage }) => (
  <T.Table>
    <ExpandHeader
      data={[
        { value: '', printHidden: true },
        { value: formatMessage(vehicleMessage.type) },
        { value: formatMessage(vehicleMessage.permno) },
        { value: formatMessage(vehicleMessage.odometer) },
        { value: '', printHidden: true },
      ]}
    />
    <T.Body>{rows}</T.Body>
  </T.Table>
));

Then use this component in the main render:

{rows.length > 0 && !loading && <MileageTable rows={rows} formatMessage={formatMessage} />}
libs/service-portal/assets/src/utils/parseCsvToMileage.ts (4)

13-15: Approve the addition of title constants with a suggestion.

The introduction of vehicleIndexTitle and mileageIndexTitle arrays improves code readability and allows for flexible CSV parsing by accepting multiple title variations. This is a good practice for handling user-provided data.

Consider using a Set instead of an array for potentially faster lookup:

const vehicleIndexTitle = new Set(['permno', 'vehicleid', 'ökutæki', 'fastanúmer'])
const mileageIndexTitle = new Set(['kílómetrastaða', 'mileage', 'odometer'])

This change would require updating the includes checks to has method calls.


45-52: Approve the new validation logic for vehicle column header with a suggestion.

The addition of validation for the vehicle column header improves the robustness of the CSV parsing. The error message is informative, providing users with a list of valid options.

For consistency with the mileage index check, consider extracting the error message creation into a separate function:

const createHeaderErrorMessage = (type: string, validTitles: string[]) =>
  `Invalid ${type} column header. Must be one of the following: ${validTitles.join(', ')}`;

// Usage
if (vehicleIndex < 0) {
  return createHeaderErrorMessage('vehicle', vehicleIndexTitle);
}

This would make the code more DRY and easier to maintain.


53-61: Approve the new validation logic for mileage column header with a suggestion.

The addition of validation for the mileage column header is consistent with the vehicle header check and improves the overall robustness of the CSV parsing.

As suggested for the vehicle header check, consider using the same createHeaderErrorMessage function here:

if (mileageIndex < 0) {
  return createHeaderErrorMessage('mileage', mileageIndexTitle);
}

This would further improve consistency and maintainability of the code.


Line range hint 13-62: Overall improvements to CSV parsing and error handling.

The changes in this file significantly enhance the parseCsvToMileageRecord function:

  1. Introduction of constants for valid column titles improves flexibility and maintainability.
  2. The updated function signature provides better type information and error handling.
  3. New validation logic for CSV headers increases robustness and provides informative error messages.

These improvements align well with the PR objectives and demonstrate good practices in TypeScript usage and error handling. The changes should make the bulk vehicle mileage functionality more reliable and user-friendly.

Consider creating a separate configuration file for the valid column titles. This would make it easier to update or localize these titles in the future without modifying the core logic.

libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.tsx (1)

submissionStatus is still used in the following components:

  • VehicleBulkMileageSaveButton.tsx
  • VehicleBulkMileageRow.tsx

Please review and update these components to ensure they function correctly without the submissionStatus property.

🔗 Analysis chain

Line range hint 46-57: Simplified vehicle data structure

The removal of the submissionStatus property from the vehicle objects in the useEffect hook streamlines the data structure. This change aligns with our goal of simplifying state management.

However, to ensure this modification doesn't adversely affect child components, please verify:

  1. That all child components, especially VehicleBulkMileageTable, can function correctly without the submissionStatus property.
  2. That this change doesn't break any existing functionality or UI elements that might have depended on submissionStatus.

Please run the following script to search for any remaining uses of submissionStatus in the relevant components:


Please run the following script to search for any remaining uses of submissionStatus in the relevant .tsx components:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining uses of 'submissionStatus' in related components
rg --type typescript 'submissionStatus' libs/service-portal/assets/src/screens/VehicleBulkMileage

Length of output: 163


Script:

#!/bin/bash
# Search for any remaining uses of 'submissionStatus' in related components
rg --type typescriptreact 'submissionStatus' libs/service-portal/assets/src/screens/VehicleBulkMileage

Length of output: 142


Script:

#!/bin/bash
# Search for any remaining uses of 'submissionStatus' in .tsx files within the VehicleBulkMileage directory
rg 'submissionStatus' libs/service-portal/assets/src/screens/VehicleBulkMileage --glob '*.tsx'

Length of output: 842

libs/service-portal/assets/src/screens/VehicleBulkMileageUpload/VehicleBulkMileageUpload.tsx (2)

60-63: LGTM with suggestion: Consider localizing the error message

The addition of this condition improves error handling for cases where parsing fails. However, consider using the formatMessage function to localize the error message for better internationalization support.

Consider updating the code as follows:

 if (typeof records === 'string') {
-  setUploadErrorMessage(records)
+  setUploadErrorMessage(formatMessage(vehicleMessage.parsingError, { error: records }))
   return
 }

This assumes you add a new message to the vehicleMessage object for parsing errors.


Line range hint 138-165: LGTM with suggestion: Consider using a single source of truth for request ID

The adjustment to use requestGuid for rendering the success message aligns well with the new state management approach. However, there's an inconsistency in using both requestGuid and data?.vehicleBulkMileagePost?.requestId within the same block.

Consider refactoring to use a single source of truth for the request ID. You could update the useEffect hook to set requestGuid to null when there's an error, ensuring that requestGuid always reflects the current state accurately. Then, you can use requestGuid consistently throughout this block:

-{requestGuid &&
+{requestGuid && (
   !data?.vehicleBulkMileagePost?.errorMessage &&
   !loading &&
-  !error && (
+  !error) && (
     <AlertMessage
       type="success"
       title={formatMessage(vehicleMessage.uploadSuccess)}
       message={
         <Box>
           <Text variant="small">
             {formatMessage(vehicleMessage.bulkMileageUploadStatus)}
           </Text>
           <Box marginTop="smallGutter">
             <LinkButton
               to={AssetsPaths.AssetsVehiclesBulkMileageJobDetail.replace(
                 ':id',
-                data?.vehicleBulkMileagePost?.requestId ?? '',
+                requestGuid,
               )}
               text={formatMessage(vehicleMessage.openJob)}
               variant="text"
               icon="arrowForward"
             />
           </Box>
         </Box>
       }
     />
   )}

This change would make the code more consistent and easier to maintain.

libs/service-portal/assets/src/screens/VehicleBulkMileageJobDetail/VehicleBulkMileageJobDetail.tsx (1)

121-163: Consider extracting the data transformation logic for better readability.

The removal of useMemo simplifies the component, but the inline logic makes the JSX more complex. Consider extracting this logic into a separate function for better readability and maintainability.

Here's a suggested refactor:

const getTableData = (jobsStatus: VehiclesBulkMileageRegistrationRequestStatus | undefined) => {
  if (!jobsStatus) return [];
  
  const { jobsSubmitted, jobsFinished, jobsRemaining, jobsValid, jobsErrored } = jobsStatus;
  
  return [
    [
      { title: formatMessage(vehicleMessage.totalSubmitted), value: jobsSubmitted?.toString() ?? '0' },
      { title: '', value: '' },
    ],
    [
      { title: formatMessage(vehicleMessage.totalFinished), value: jobsFinished?.toString() ?? '0' },
      { title: formatMessage(vehicleMessage.totalRemaining), value: jobsRemaining?.toString() ?? '0' },
    ],
    [
      { title: formatMessage(vehicleMessage.healthyJobs), value: jobsValid?.toString() ?? '0' },
      { title: formatMessage(vehicleMessage.unhealthyJobs), value: jobsErrored?.toString() ?? '0' },
    ],
  ];
};

// In the JSX:
<TableGrid
  title={formatMessage(vehicleMessage.jobStatus)}
  dataArray={getTableData(data?.vehicleBulkMileageRegistrationRequestStatus)}
/>

This refactor improves readability, reduces repetition, and provides a more appropriate default value (an empty array instead of [[]]).

The use of TypeScript with optional chaining is good, and the component appears to be reusable across different NextJS apps, adhering to the coding guidelines for library files.

libs/api/domains/vehicles/src/lib/services/vehicles.service.ts (1)

Inconsistent Property Naming Detected

The property canRegisterMilage is inconsistently used across the codebase. To maintain consistency and avoid potential bugs, please standardize the property name to canRegisterMileage in all instances.

  • libs/application/templates/car-recycling/src/graphql/queries.ts
  • libs/api/domains/vehicles/src/lib/models/usersVehicles.model.ts
  • libs/api/domains/vehicles/src/lib/services/vehicles.service.ts
🔗 Analysis chain

Line range hint 132-144: Simplification of vehicle data validation and property handling

The changes in the getVehiclesListV3 method improve the handling of vehicle data:

  1. The validation now only checks for essential properties (permno and regno), simplifying the logic.
  2. canRegisterMilage and requiresMileageRegistration are now assigned undefined if not present, which is a good TypeScript practice for handling optional properties.

However, there's a potential typo in the property name canRegisterMilage. Consider changing it to canRegisterMileage for consistency and correctness.

Consider fixing the typo in the property name:

-                canRegisterMileage: d.canRegisterMilage ?? undefined,
+                canRegisterMileage: d.canRegisterMileage ?? undefined,

To ensure consistency across the codebase, let's check for other occurrences of this property name:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for both spellings of the property name
echo "Occurrences of 'canRegisterMilage':"
rg --type typescript 'canRegisterMilage'
echo "Occurrences of 'canRegisterMileage':"
rg --type typescript 'canRegisterMileage'

Length of output: 328


Script:

#!/bin/bash
# Search for both spellings in TypeScript files

echo "Occurrences of 'canRegisterMilage':"
rg 'canRegisterMilage' -g '*.ts'

echo "Occurrences of 'canRegisterMileage':"
rg 'canRegisterMileage' -g '*.ts'

Length of output: 1673

libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql (1)

35-49: Inconsistent casing in query name GetUsersMileage.

The query GetUsersMileage uses PascalCase naming, while other queries like vehiclesList use lowerCamelCase. For consistency, consider renaming the query to getUsersMileage.

libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx (2)

Line range hint 196-225: Ensure validator functions always return a value

In the value validator function of the InputController component, if the validation passes, the function does not return anything. Validator functions should always return either true or an error message to properly validate the input.

Apply this diff to make the return value explicit:

                        value: (value: number) => {
                          // Input number must be higher than the highest known mileage registration value
                          if (mileageData?.vehicleMileageDetails?.data) {
                            // If we're in editing mode, we want to find the highest confirmed registered number, ignoring all Island.is registrations from today.
                            const confirmedRegistrations =
                              mileageData.vehicleMileageDetails.data.filter(
                                (item) => {
                                  if (item.readDate) {
                                    const isIslandIsReadingToday =
                                      item.originCode === ORIGIN_CODE &&
                                      isReadDateToday(new Date(item.readDate))
                                    return !isIslandIsReadingToday
                                  }
                                  return true
                                },
                              )

                            const detailArray = mileageData.vehicleMileageDetails
                              .editing
                              ? confirmedRegistrations
                              : mileageData.vehicleMileageDetails.data

                            const latestRegistration =
                              detailArray[0].mileageNumber ?? 0
                            if (latestRegistration > value) {
                              return formatMessage(
                                vehicleMessage.mileageInputTooLow,
                              )
                            }
                          }
+                         return true
                        },

80-91: Simplify getValueFromForm function return logic

The getValueFromForm function can be simplified by handling the early return cases more efficiently and ensuring consistent return values.

Apply this diff to simplify the function:

  const getValueFromForm = async (
    formFieldId: string,
    skipEmpty = false,
  ): Promise<number | undefined> => {
    const value = getValues(formFieldId)
-   if (!value && skipEmpty) {
+   if ((value === undefined || value === '') && skipEmpty) {
      return undefined
    }
-   if (await trigger(formFieldId)) {
-     return Number(value)
-   }
-   return undefined
+   if (!(await trigger(formFieldId))) {
+     return undefined
+   }
+   return Number(value)
  }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between c23c6d6 and b52ab17.

📒 Files selected for processing (13)
  • libs/api/domains/vehicles/src/lib/models/v3/mileageDetails.model.ts (1 hunks)
  • libs/api/domains/vehicles/src/lib/services/vehicles.service.ts (2 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql (1 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.tsx (2 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageFileDownloader.tsx (1 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx (6 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageSaveButton.tsx (2 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageTable.tsx (1 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/types.ts (1 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileageJobDetail/VehicleBulkMileageJobDetail.tsx (1 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileageUpload/VehicleBulkMileageUpload.tsx (4 hunks)
  • libs/service-portal/assets/src/utils/parseCsvToMileage.ts (2 hunks)
  • libs/service-portal/core/src/lib/messages.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (13)
libs/api/domains/vehicles/src/lib/models/v3/mileageDetails.model.ts (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/api/domains/vehicles/src/lib/services/vehicles.service.ts (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.tsx (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageFileDownloader.tsx (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageSaveButton.tsx (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageTable.tsx (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/screens/VehicleBulkMileage/types.ts (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/screens/VehicleBulkMileageJobDetail/VehicleBulkMileageJobDetail.tsx (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/screens/VehicleBulkMileageUpload/VehicleBulkMileageUpload.tsx (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/utils/parseCsvToMileage.ts (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/core/src/lib/messages.ts (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
🔇 Additional comments (14)
libs/api/domains/vehicles/src/lib/models/v3/mileageDetails.model.ts (1)

9-10: LGTM! Ensure consistent handling in dependent code.

The change to make requiresMileageRegistration optional and nullable is consistent with the previous field modification and improves the model's flexibility.

To maintain system integrity, please verify all components that use this field. Run the following script to identify potential usage:

#!/bin/bash
# Description: Find usages of requiresMileageRegistration in the codebase
rg --type typescript "requiresMileageRegistration" --glob '!**/mileageDetails.model.ts'
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageFileDownloader.tsx (1)

Line range hint 1-46: Adherence to coding guidelines confirmed.

The code in this file adheres well to the specified coding guidelines for the libs directory:

  1. It demonstrates reusability across different NextJS apps by using shared components and utilities.
  2. TypeScript is effectively used for defining props and types.
  3. The component structure supports effective tree-shaking and bundling practices.
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageSaveButton.tsx (2)

5-5: LGTM: Proper type import for better tree-shaking

The addition of the type keyword in the import statement is a good practice. It ensures that only the type information is imported, which can lead to more effective tree-shaking during the build process.


Line range hint 1-55: Overall assessment: Well-implemented changes with minor suggestions for improvement

The changes to the VehicleBulkMileageSaveButton component are well-implemented and align with the coding guidelines for the libs directory. The component remains reusable, makes effective use of TypeScript for type safety, and contributes to good tree-shaking practices. The renaming of props and updating of the submission status logic improve clarity and robustness.

Key improvements:

  1. Better type imports for effective tree-shaking
  2. Improved prop naming and type safety
  3. More comprehensive submission status handling
  4. Addition of a loading state for better user feedback

The suggested minor improvements (file naming, constant extraction, and centralizing button props) would further enhance code readability and maintainability. Overall, these changes represent a solid improvement to the component.

libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageTable.tsx (2)

6-13: LGTM: Import reorganization and Props interface simplification

The changes to the import statements and the Props interface improve code organization and simplify the component's API. This aligns well with the coding guideline of enhancing reusability across different NextJS apps.


Line range hint 1-54: Great job on improving component structure and adherence to guidelines

The changes to this component have significantly improved its structure and adherence to the coding guidelines:

  1. The use of TypeScript for prop definitions enhances type safety.
  2. The simplified component structure allows for better reusability across different NextJS apps.
  3. The current implementation supports effective tree-shaking and bundling.

These improvements align well with the coding guidelines for files in the libs directory.

libs/service-portal/assets/src/utils/parseCsvToMileage.ts (1)

16-18: Approve the updated function signature.

The new function signature async (file: File): Promise<Array<MileageRecord> | string> provides better type information and adheres to TypeScript best practices. It clearly communicates that the function can return either an array of MileageRecord objects or an error message string.

This change improves type safety and makes the function's behavior more predictable for consumers.

libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.tsx (3)

13-13: Improved import management enhances reusability and tree-shaking

The removal of SubmissionState and addition of VehicleType import simplifies the component's dependencies. This change aligns well with our coding guidelines for libs/**/* files, promoting better reusability across different NextJS apps and potentially improving tree-shaking for more efficient bundling.


Line range hint 1-134: Overall assessment: Improved component structure aligns with coding guidelines

The changes made to the VehicleBulkMileage component demonstrate a positive step towards simplifying state management and improving reusability. By removing the SubmissionState type, updateVehicleStatus function, and simplifying the VehicleBulkMileageTable props, the component becomes more focused and potentially easier to maintain.

These modifications align well with our coding guidelines for libs/**/* files:

  1. Improved reusability across different NextJS apps due to simpler component structure.
  2. Better TypeScript usage with more focused prop types.
  3. Potential for more effective tree-shaking and bundling due to removed dependencies.

To fully validate these changes:

  1. Ensure that the removal of submissionStatus and updateVehicleStatus doesn't negatively impact the overall functionality of the vehicle mileage management feature.
  2. Verify that the VehicleBulkMileageTable component has been updated to work with the new prop structure.
  3. Consider adding or updating unit tests to cover the modified behavior.

105-105: Simplified props for VehicleBulkMileageTable component

The removal of the updateVehicleStatus prop from VehicleBulkMileageTable simplifies the component's interface, which is beneficial for maintainability and aligns with our coding guidelines for reusability.

To ensure this change doesn't introduce any issues:

  1. Verify that the VehicleBulkMileageTable component has been updated to function correctly without the updateVehicleStatus prop.
  2. Check if any vehicle status update functionality needs to be handled differently now, or if it has been intentionally removed.
#!/bin/bash
# Check the VehicleBulkMileageTable component for any remaining references to updateVehicleStatus
rg --type typescript 'updateVehicleStatus' libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageTable.tsx
libs/service-portal/assets/src/screens/VehicleBulkMileageUpload/VehicleBulkMileageUpload.tsx (2)

48-50: LGTM: Improved error message handling

The addition of this condition ensures that the uploadErrorMessage is reset when a new request is made. This improves the user experience by preventing stale error messages from persisting.


89-91: LGTM: Improved state management for file uploads

Resetting the requestGuid to null when a new file is uploaded ensures a clean slate for each upload attempt. This is a good practice that prevents potential issues with stale state.

libs/service-portal/core/src/lib/messages.ts (2)

326-328: Improved message ID clarity

The update to the message ID from 'vehicles-bulk-mileage-job-overview' to 'vehicles-bulk-mileage-job-overview-description' enhances clarity and maintains consistency with the naming convention used throughout the file. This change improves code readability and maintainability without affecting functionality.


Line range hint 1508-1512: Enhanced message ID and content for income plan description

The update to the message ID from 'income-plan' to 'income-plan-description' improves clarity and maintains consistency with other message IDs in the file. The significantly expanded defaultMessage provides users with more comprehensive information about income plans, their relationship to various pension types, and the requirement for submitting an income plan when applying for a pension. This change enhances user understanding and the overall quality of the internationalization content.

@thorkellmani thorkellmani added the automerge Merge this PR as soon as all checks pass label Sep 30, 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

🧹 Outside diff range and nitpick comments (5)
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql (2)

31-37: LGTM! Consider using a fragment for consistency.

The putSingleVehicleMileage mutation is well-structured and follows the coding guidelines:

  • It uses TypeScript for input type definition (PutVehicleMileageInput).
  • The specific field selection in the return type supports effective tree-shaking.
  • The naming is clear and descriptive, enhancing reusability across different NextJS apps.

However, for consistency with other operations (e.g., postSingleVehicleMileage), consider using a fragment for the return fields.

Consider creating and using a fragment for the return fields to maintain consistency across mutations:

fragment VehicleMileageFields on VehicleMileage {
  permno
  internalId
  mileageNumber
}

mutation putSingleVehicleMileage($input: PutVehicleMileageInput!) {
  vehicleMileagePut(input: $input) {
    ...VehicleMileageFields
  }
}

39-53: LGTM with suggestions for naming consistency.

The GetUsersMileage query is well-structured and follows most coding guidelines:

  • It uses TypeScript for input type definition (GetVehicleMileageInput).
  • The specific field selection in the return type supports effective tree-shaking.

However, there are a couple of points to consider:

  1. The query name doesn't follow the camelCase convention used in other operations. Consider renaming it to getUsersMileage for consistency.

  2. There's an inconsistency in field naming: mileageNumber is used here, while mileage is used in the mileageRegistration fragment. Standardize this field name across the codebase to improve clarity and maintainability.

Consider the following changes:

  1. Rename the query:
query getUsersMileage($input: GetVehicleMileageInput!) {
  // ... rest of the query
}
  1. Standardize the mileage field name. If mileageNumber is the correct term, update the mileageRegistration fragment accordingly. If mileage is correct, update this query to use mileage instead of mileageNumber.
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx (3)

Line range hint 34-71: LGTM: Enhanced state management and GraphQL integration

The introduction of postError and postSuccess state variables, along with the use of GraphQL hooks, significantly improves error handling and data management. This aligns well with modern React practices.

For consistency, consider using a single state object for post status:

-const [postError, setPostError] = useState<string | null>(null)
-const [postSuccess, setPostSuccess] = useState(false)
+const [postStatus, setPostStatus] = useState<{ error: string | null; success: boolean }>({ error: null, success: false })

This would simplify state updates and potentially reduce re-renders.


80-93: LGTM: Improved form value retrieval and validation

The getValueFromForm function is a well-implemented utility for retrieving and validating form values. It enhances the component's ability to handle form data effectively.

Consider adding error handling for cases where the form field doesn't exist:

 const getValueFromForm = async (
   formFieldId: string,
   skipEmpty = false,
 ): Promise<number | undefined> => {
+  if (!(formFieldId in getValues())) {
+    console.warn(`Form field ${formFieldId} does not exist`);
+    return undefined;
+  }
   const value = getValues(formFieldId)
   if (!value && skipEmpty) {
     return
   }
   if (await trigger(formFieldId)) {
     return Number(value)
   }
   return
 }

This addition would make the function more robust against potential errors.


Line range hint 168-234: LGTM: Enhanced error handling and input validation

The updates to the InputController component significantly improve error handling and input validation. The new validation rules enhance data integrity and provide better user feedback.

To improve readability, consider extracting the complex validation logic into separate functions:

const validateUserAccess = () => {
  if (mileageData?.vehicleMileageDetails?.canUserRegisterVehicleMileage) {
    return true;
  }
  return formatMessage(vehicleMessage.mileageYouAreNotAllowed);
};

const validateReadDate = () => {
  if (
    !mileageData?.vehicleMileageDetails?.editing &&
    !mileageData?.vehicleMileageDetails?.canRegisterMileage
  ) {
    return formatMessage(vehicleMessage.mileageAlreadyRegistered);
  }
  return true;
};

// ... other validation functions ...

rules={{
  validate: {
    userHasPostAccess: validateUserAccess,
    readDate: validateReadDate,
    // ... other validations ...
  },
  // ... other rules ...
}}

This refactoring would make the component more maintainable and easier to test.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b52ab17 and 13b97c2.

📒 Files selected for processing (3)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql (1 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx (6 hunks)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/mocks/propsDummy.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • libs/service-portal/assets/src/screens/VehicleBulkMileage/mocks/propsDummy.ts
🧰 Additional context used
📓 Path-based instructions (2)
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
🔇 Additional comments (6)
libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql (2)

21-29: LGTM! Mutation adheres to coding guidelines.

The postSingleVehicleMileage mutation is well-structured and follows the coding guidelines:

  • It uses TypeScript for input type definition (PostVehicleMileageInput).
  • The specific field selection in the return type supports effective tree-shaking.
  • The naming is clear and descriptive, enhancing reusability across different NextJS apps.

Line range hint 54-71: LGTM! Excellent use of fragment for reusability.

The mileageRegistration fragment and vehicleMileageRegistrationHistory query are well-structured and follow the coding guidelines:

  • They use TypeScript for type definitions.
  • The specific field selection in both the fragment and query supports effective tree-shaking.
  • The naming is clear and descriptive, enhancing reusability across different NextJS apps.
  • The use of the mileageRegistration fragment in the query promotes code reuse and maintainability.

This is a great example of how to structure GraphQL operations for optimal reusability and tree-shaking.

libs/service-portal/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx (4)

247-255: LGTM: Improved VehicleBulkMileageSaveButton state management

The updates to the VehicleBulkMileageSaveButton component provide more granular control over the button's state. The new submissionStatus prop effectively captures various states including error, loading, and success. This aligns well with the component's enhanced functionality and improves the user experience by providing clear feedback on the submission process.


Line range hint 1-290: Overall assessment: Significant improvements with minor suggestions

The changes to the VehicleBulkMileageRow component represent a substantial improvement in functionality, error handling, and data management. The introduction of GraphQL hooks, enhanced state management, and more robust form validation contribute to a more maintainable and user-friendly component.

While the core changes are solid, there are a few areas where minor improvements could further enhance the code:

  1. Consolidating post status state
  2. Adding error handling to the getValueFromForm function
  3. Updating the useEffect hook dependencies
  4. Extracting complex validation logic into separate functions
  5. Exporting the Props interface

These suggestions aim to improve code readability, maintainability, and reusability. Overall, the changes are well-implemented and align with modern React and TypeScript best practices.


28-31: 🛠️ Refactor suggestion

Consider exporting the Props interface

For improved reusability and type checking in other components, consider exporting the Props interface:

 interface Props {
   vehicle: VehicleType
 }
+export type { Props }

This change would allow other components or tests to reuse this interface, enhancing consistency across the codebase.

Likely invalid or redundant comment.


1-32: LGTM: Updated imports and component signature

The changes to the imports and component signature align with the new functionality for mileage data management. The removal of the onSave prop suggests a change in how save actions are handled within the component.

To ensure this change doesn't break existing usage, let's verify other components that might be using VehicleBulkMileageRow:

@kodiakhq kodiakhq bot merged commit 9ef986b into main Oct 1, 2024
40 checks passed
@kodiakhq kodiakhq bot deleted the fix/mileage-bus branch October 1, 2024 09:55
thoreyjona pushed a commit that referenced this pull request Oct 2, 2024
* fix. init

* chore: add loading

* fix: intro

* chore: console

* chore: import

* fix: error state

* fix: single vehicle mileage input

* chore: leftoevers

* chore: coderabbit suggestions

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
@coderabbitai coderabbitai bot mentioned this pull request Oct 3, 2024
6 tasks
thorkellmani added a commit that referenced this pull request Oct 3, 2024
* fix. init

* chore: add loading

* fix: intro

* chore: console

* chore: import

* fix: error state

* fix: single vehicle mileage input

* chore: leftoevers

* chore: coderabbit suggestions

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge Merge this PR as soon as all checks pass
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants