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

feat(skilavottord): Add municipality #17109

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

birkirkristmunds
Copy link
Member

@birkirkristmunds birkirkristmunds commented Dec 3, 2024

TS-936

What

Adding CRU for municipality so recycling companies can be put under a municipality
Add now municipality role
Handle the what municipality user with municipality role can do and see

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 roles and permissions for municipalities, enhancing access control.
    • Added new components for managing municipalities, including navigation links and page headers.
    • Implemented new utility functions to streamline partner ID retrieval based on user roles.
  • Enhancements

    • Updated localization files to support municipality-related features in both English and Icelandic.
    • Improved the AccessControl component to handle dynamic role checks and visibility.
    • Enhanced the RecyclingCompanies component to differentiate between municipalities and recycling companies.
  • Bug Fixes

    • Corrected variable names and improved error handling in various services and components.
  • Documentation

    • Updated README to reflect changes in role descriptions and frontend sections.

Copy link
Contributor

coderabbitai bot commented Dec 3, 2024

Walkthrough

This pull request introduces a comprehensive update to the Skilavottord application, focusing on adding municipality-related functionality. The changes span multiple components and modules, introducing a new municipality role, updating authorization mechanisms, and enhancing the application's ability to manage recycling partners and access controls. Key modifications include adding new GraphQL models, updating translation files, refactoring authentication utilities, and implementing new routes and components for municipality management.

Changes

File/Group Change Summary
apps/skilavottord/web/auth/utils.ts Removed 'deregisterVehicleKM' from Page type, updated role checking functions
apps/skilavottord/web/components/* Added new components like NavigationLinks, PageHeader, updated Sidenav
apps/skilavottord/web/i18n/locales/* Updated English and Icelandic translation files with municipality-related keys
apps/skilavottord/ws/src/app/modules/auth/* Added municipality role to the Role enum
apps/skilavottord/ws/src/app/modules/recyclingPartner/* Added isMunicipality and municipalityId fields to models and inputs
Backend Resolvers and Services Updated to support municipality-specific queries and permissions

Sequence Diagram

sequenceDiagram
    participant User
    participant AuthSystem
    participant RecyclingPartnerService
    participant AccessControlService

    User->>AuthSystem: Login with role
    AuthSystem->>User: Validate role
    alt Municipality Role
        User->>RecyclingPartnerService: Request Partners
        RecyclingPartnerService->>User: Return Municipality Partners
    else Other Roles
        User->>RecyclingPartnerService: Request Partners
        RecyclingPartnerService->>User: Return Authorized Partners
    end
    User->>AccessControlService: Request Access Control
    AccessControlService->>User: Return Permitted Actions
Loading

Possibly related PRs

Suggested reviewers

  • thordurhhh

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


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.

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

Codecov Report

Attention: Patch coverage is 24.05063% with 60 lines in your changes missing coverage. Please review.

Project coverage is 35.58%. Comparing base (7fe9be5) to head (7cb4964).
Report is 31 commits behind head on main.

Files with missing lines Patch % Lines
...ules/recyclingPartner/recyclingPartner.resolver.ts 0.00% 14 Missing ⚠️
...dules/recyclingPartner/recyclingPartner.service.ts 7.14% 13 Missing ⚠️
...tord/ws/src/app/modules/vehicle/vehicle.service.ts 28.57% 10 Missing ⚠️
...app/modules/accessControl/accessControl.service.ts 0.00% 9 Missing ⚠️
...pp/modules/accessControl/accessControl.resolver.ts 0.00% 4 Missing ⚠️
...modules/recyclingPartner/recyclingPartner.model.ts 66.66% 2 Missing ⚠️
...dules/recyclingRequest/recyclingRequest.service.ts 33.33% 2 Missing ⚠️
...ord/ws/src/app/modules/vehicle/vehicle.resolver.ts 0.00% 2 Missing ⚠️
...skilavottord/ws/src/app/modules/auth/user.model.ts 0.00% 1 Missing ⚠️
...lavottord/ws/src/app/modules/municipality/index.ts 0.00% 1 Missing ⚠️
... and 2 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #17109      +/-   ##
==========================================
- Coverage   35.72%   35.58%   -0.15%     
==========================================
  Files        6946     6932      -14     
  Lines      148584   149166     +582     
  Branches    42415    42703     +288     
==========================================
- Hits        53085    53080       -5     
- Misses      95499    96086     +587     
Flag Coverage Δ
air-discount-scheme-backend 48.24% <ø> (+0.04%) ⬆️
air-discount-scheme-web 0.00% <ø> (ø)
api 3.33% <ø> (ø)
api-catalogue-services 75.81% <ø> (ø)
api-domains-air-discount-scheme 37.99% <ø> (+0.08%) ⬆️
api-domains-assets 26.71% <ø> (ø)
api-domains-auth-admin 48.49% <ø> (ø)
api-domains-communications 39.42% <ø> (+<0.01%) ⬆️
api-domains-criminal-record 48.03% <ø> (+0.11%) ⬆️
api-domains-driving-license 44.86% <ø> (+0.04%) ⬆️
api-domains-education 31.27% <ø> (+0.09%) ⬆️
api-domains-health-insurance 35.47% <ø> (+0.14%) ⬆️
api-domains-mortgage-certificate 35.24% <ø> (+0.08%) ⬆️
api-domains-payment-schedule 42.12% <ø> (+0.08%) ⬆️
application-api-files 61.90% <ø> (+0.03%) ⬆️
application-core 75.72% <ø> (ø)
application-system-api 38.73% <ø> (-0.07%) ⬇️
application-template-api-modules 27.68% <ø> (-0.13%) ⬇️
application-templates-accident-notification 27.61% <ø> (-1.20%) ⬇️
application-templates-car-recycling 3.12% <ø> (ø)
application-templates-criminal-record 25.83% <ø> (+0.08%) ⬆️
application-templates-driving-license 18.15% <ø> (ø)
application-templates-estate 13.66% <ø> (-0.03%) ⬇️
application-templates-example-payment 24.69% <ø> (ø)
application-templates-financial-aid 14.45% <ø> (ø)
application-templates-general-petition 23.12% <ø> (ø)
application-templates-inheritance-report 6.59% <ø> (ø)
application-templates-marriage-conditions 15.18% <ø> (ø)
application-templates-mortgage-certificate 43.68% <ø> (+0.05%) ⬆️
application-templates-parental-leave 30.02% <ø> (+0.08%) ⬆️
application-types 6.51% <ø> (ø)
application-ui-components 1.22% <ø> (ø)
application-ui-shell 22.26% <ø> (-0.06%) ⬇️
auth-admin-web 2.43% <ø> (ø)
auth-nest-tools 31.52% <ø> (ø)
clients-charge-fjs-v2 28.88% <ø> (+0.53%) ⬆️
clients-driving-license 40.91% <ø> (+0.11%) ⬆️
clients-driving-license-book 43.92% <ø> (+0.08%) ⬆️
clients-financial-statements-inao 49.70% <ø> (+0.11%) ⬆️
clients-license-client 1.26% <ø> (ø)
clients-middlewares 73.26% <ø> (+0.12%) ⬆️
clients-regulations 43.00% <ø> (+0.12%) ⬆️
clients-rsk-company-registry 31.18% <ø> (+0.14%) ⬆️
clients-rsk-personal-tax-return 38.32% <ø> (ø)
clients-smartsolutions 12.77% <ø> (ø)
clients-syslumenn 49.47% <ø> (+0.06%) ⬆️
clients-zendesk 50.58% <ø> (+0.11%) ⬆️
cms 0.39% <ø> (-0.01%) ⬇️
cms-translations 38.75% <ø> (+<0.01%) ⬆️
content-search-toolkit 8.16% <ø> (ø)
contentful-apps 4.71% <ø> (-0.01%) ⬇️
dokobit-signing 62.18% <ø> (+0.08%) ⬆️
email-service 60.15% <ø> (+0.07%) ⬆️
file-storage 45.97% <ø> (+0.10%) ⬆️
financial-aid-backend 51.42% <ø> (+0.01%) ⬆️
financial-aid-shared 17.88% <ø> (ø)
icelandic-names-registry-backend 54.33% <ø> (ø)
infra-nest-server 48.06% <ø> (ø)
infra-tracing 69.94% <ø> (+0.31%) ⬆️
island-ui-core 30.42% <ø> (+0.01%) ⬆️
judicial-system-api 20.20% <ø> (-0.01%) ⬇️
judicial-system-audit-trail 69.02% <ø> (+0.08%) ⬆️
judicial-system-message 66.60% <ø> (+0.12%) ⬆️
judicial-system-message-handler 48.33% <ø> (+0.17%) ⬆️
judicial-system-scheduler 71.15% <ø> (+0.06%) ⬆️
judicial-system-web 27.72% <ø> (-0.05%) ⬇️
license-api 42.93% <ø> (-0.05%) ⬇️
localization 10.15% <ø> (ø)
logging 58.02% <ø> (ø)
message-queue 67.05% <ø> (-0.71%) ⬇️
nest-audit 65.78% <ø> (ø)
nest-aws 51.93% <ø> (ø)
nest-config 76.45% <ø> (+0.06%) ⬆️
nest-core 53.16% <ø> (ø)
nest-feature-flags 51.06% <ø> (+0.06%) ⬆️
nest-problem 45.64% <ø> (ø)
nest-sequelize 94.44% <ø> (ø)
nest-swagger 51.13% <ø> (ø)
nova-sms 61.52% <ø> (+0.09%) ⬆️
portals-admin-regulations-admin 1.80% <ø> (ø)
portals-core 19.58% <ø> (-0.04%) ⬇️
services-auth-admin-api 52.54% <ø> (-0.02%) ⬇️
services-auth-delegation-api 58.46% <ø> (-0.07%) ⬇️
services-auth-ids-api 52.58% <ø> (+0.02%) ⬆️
services-auth-public-api 49.41% <ø> (+0.01%) ⬆️
services-sessions 65.32% <ø> (-0.03%) ⬇️
services-university-gateway 49.55% <ø> (+0.07%) ⬆️
services-user-notification 46.54% <ø> (-0.01%) ⬇️
services-user-profile 56.97% <ø> (+0.11%) ⬆️
shared-components 29.49% <ø> (-0.15%) ⬇️
shared-form-fields 33.38% <ø> (+0.01%) ⬆️
shared-utils 27.69% <ø> (ø)
skilavottord-ws 24.32% <24.05%> (+0.05%) ⬆️
web 2.40% <ø> (+<0.01%) ⬆️

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

Files with missing lines Coverage Δ
...c/app/modules/accessControl/accessControl.model.ts 0.00% <ø> (ø)
...skilavottord/ws/src/app/modules/auth/auth.guard.ts 0.00% <ø> (ø)
...modules/recyclingPartner/recyclingPartner.input.ts 100.00% <100.00%> (ø)
...skilavottord/ws/src/app/modules/auth/user.model.ts 0.00% <0.00%> (ø)
...lavottord/ws/src/app/modules/municipality/index.ts 0.00% <0.00%> (ø)
...src/app/modules/municipality/municipality.model.ts 83.33% <83.33%> (ø)
...odules/recyclingPartner/recyclingPartner.module.ts 0.00% <0.00%> (ø)
...modules/recyclingPartner/recyclingPartner.model.ts 84.00% <66.66%> (-1.00%) ⬇️
...dules/recyclingRequest/recyclingRequest.service.ts 8.92% <33.33%> (-0.05%) ⬇️
...ord/ws/src/app/modules/vehicle/vehicle.resolver.ts 0.00% <0.00%> (ø)
... and 5 more

... and 118 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 7fe9be5...7cb4964. Read the comment docs.

@datadog-island-is
Copy link

datadog-island-is bot commented Dec 3, 2024

Datadog Report

All test runs dd6fb23 🔗

10 Total Test Services: 0 Failed, 10 Passed
🔻 Test Sessions change in coverage: 2 decreased, 4 increased, 188 no change

Test Services
This report shows up to 10 services
Service Name Failed Known Flaky New Flaky Passed Skipped Total Time Code Coverage Change Test Service View
air-discount-scheme-backend 0 0 0 63 0 29.1s N/A Link
air-discount-scheme-web 0 0 0 2 0 7.69s N/A Link
api 0 0 0 4 0 2.94s N/A Link
api-catalogue-services 0 0 0 23 0 11.48s N/A Link
api-domains-air-discount-scheme 0 0 0 6 0 18.9s N/A Link
api-domains-assets 0 0 0 3 0 11.84s N/A Link
api-domains-auth-admin 0 0 0 18 0 12.89s N/A Link
api-domains-communications 0 0 0 5 0 33.14s N/A Link
api-domains-criminal-record 0 0 0 5 0 10.69s N/A Link
services-auth-delegation-api 0 0 0 270 0 3m 7.67s 1 decreased (-0.03%) Link

🔻 Code Coverage Decreases vs Default Branch (2)

  • services-auth-delegation-api - jest 50.45% (-0.03%) - Details
  • services-university-gateway - jest 45.26% (-0.02%) - Details

@birkirkristmunds birkirkristmunds marked this pull request as ready for review December 10, 2024 14:44
@birkirkristmunds birkirkristmunds requested a review from a team as a code owner December 10, 2024 14:44
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: 20

🧹 Outside diff range and nitpick comments (34)
apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx (5)

7-7: Remove duplicate Option import

The Option type is imported individually and also as part of the destructured import from '@island.is/island-ui/core'.

-import { Box, Button, Option, Select, Stack } from '@island.is/island-ui/core'
+import { Box, Button, Select, Stack } from '@island.is/island-ui/core'

Line range hint 52-56: Clarify the empty onContinue handler

The empty onContinue handler in the Modal component could be confusing. Consider removing it if not needed, as the form submission is handled by the onSubmit prop.

-      onContinue={() => {
-        // Intentionally left empty
-      }}
+      onContinue={undefined}

Line range hint 124-131: Simplify email validation pattern

The current email validation regex is complex and might miss some valid email formats. Consider using a simpler pattern or a dedicated email validation library.

               pattern: {
-                value:
-                  /^[\w!#$%&'*+/=?`{|}~^-]+(?:\.[\w!#$%&'*+/=?`{|}~^-]+)*@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$/i,
+                value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
                 message: t.modal.inputs.email.rules?.validate,
               },

Line range hint 196-207: Improve responsive design implementation

The Box component uses hardcoded padding values which might not scale well across different screen sizes. Consider using theme-based spacing values for better maintainability.

-          <Box paddingX={[3, 3, 3, 15]}></Box>
+          <Box paddingX={[2, 3, 4, 5]}></Box>

Line range hint 30-209: Add loading state handling

The form submission lacks loading state handling, which could lead to multiple submissions. Consider adding a loading state to disable the form during submission.

You could:

  1. Add a loading prop to the component
  2. Disable the submit button and form inputs during submission
  3. Show a loading indicator

Would you like me to provide a detailed implementation?

apps/skilavottord/ws/seeders/20201010211010-seed-recycling-request.js (1)

Line range hint 1-96: Consider adding documentation for test data scenarios

The seeder file contains various test scenarios (different request_types and recycling_partner_id states) but lacks documentation explaining the purpose of each scenario. Consider adding comments to explain:

  1. The significance of null vs non-null recycling_partner_id
  2. The progression of request_types
  3. The relationship between dates and states
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (3)

55-70: Simplify conditional logic for route variables

The logic setting breadcrumbTitle, title, info, activeSection, and route can be simplified for better readability and maintainability.

Consider refactoring as follows:

 const isMunicipality = router.route === routes.municipalities.add

 const {
   t: { recyclingCompanies: t, municipalities: mt, routes },
 } = useI18n()

 const breadcrumbTitle = isMunicipality ? mt.title : t.title
 const title = isMunicipality ? mt.municipality.add.title : t.recyclingCompany.add.title
 const info = isMunicipality ? mt.municipality.add.info : t.recyclingCompany.add.info
 const activeSection = isMunicipality ? 1 : 2
 const route = isMunicipality ? routes.municipalities.baseRoute : routes.recyclingCompanies.baseRoute

117-125: Duplicate code in navigation after creation

The routing logic after a successful creation is duplicated for municipalities and recycling companies.

Refactor to eliminate duplication:

 if (!errors) {
-  if (isMunicipality) {
-    router.push(routes.municipalities.baseRoute).then(() => {
-      toast.success(t.recyclingCompany.add.added)
-    })
-  } else {
-    router.push(routes.recyclingCompanies.baseRoute).then(() => {
-      toast.success(t.recyclingCompany.add.added)
-    })
-  }
+  router.push(route).then(() => {
+    toast.success(t.recyclingCompany.add.added)
+  })
 }

129-135: Simplify handleCancel routing logic

The handleCancel function contains duplicated routing logic based on isMunicipality.

Refactor to use the route variable:

 const handleCancel = () => {
-  if (isMunicipality) {
-    router.push(routes.municipalities.baseRoute)
-  } else {
-    router.push(routes.recyclingCompanies.baseRoute)
-  }
+  router.push(route)
 }
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx (2)

59-72: Simplify context-based variables

The variables isMunicipality, buttonText, activeSection, title, and info can be consolidated for clearer logic.

Consider refactoring:

 const isMunicipality = router.route === routes.municipalities.baseRoute

 const buttonText = isMunicipality ? t.buttons.addMunicipality : t.buttons.add
 const activeSection = isMunicipality ? 1 : 2
 const title = isMunicipality ? mt.title : t.title
 const info = isMunicipality ? '' : t.info

101-109: Duplicate code in handleCreate function

The handleCreate function contains duplicated routing logic.

Refactor to use the routes object based on isMunicipality:

 const handleCreate = () => {
   router.push({
-    pathname: isMunicipality ? routes.municipalities.add : routes.recyclingCompanies.add,
+    pathname: route.add,
   })
 }

Ensure you define route similarly to how it's done in other components.

apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (3)

53-57: Avoid unnecessary default assignment

The default assignment || [] is unnecessary when using skip in the query.

Remove the redundant assignment.

 const { data } =
-  useQuery<Query>(SkilavottordAllRecyclingPartnersByTypeQuery, {
+  useQuery<Query>(SkilavottordAllRecyclingPartnersByTypeQuery, {
     skip: isMunicipality,
     variables: { isMunicipality: true },
   })
-  || []

278-311: Conditional rendering might cause layout shift

Conditional rendering of the Select component may cause layout shifts. Consider rendering the component but disabling it or hiding it with CSS to maintain consistent layout.

Alternatively, adjust the layout to accommodate the dynamic content.


374-375: Button icon mismatch

The Button component's icon has been changed to save. Ensure this aligns with the action, and consider using the arrowForward icon for consistency unless saving is appropriate here.

apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (1)

125-147: Unused imports and variables

There are unused imports and variables, such as municipalities, use from 'dd-trace', and potentially others.

Remove unused imports and variables to clean up the code.

apps/skilavottord/web/pages/en/municipalities/index.tsx (1)

1-5: Consider improving type safety and import paths

While the implementation is functional, consider these improvements:

  1. Define the Screen type explicitly on the RecyclingCompanies component instead of using type casting
  2. Consider using path aliases for imports to improve maintainability

Example implementation:

- import { Screen } from '@island.is/skilavottord-web/types'
+ import { Screen } from '@types'
- import { withLocale } from '@island.is/skilavottord-web/i18n'
+ import { withLocale } from '@i18n'
- import { RecyclingCompanies } from '@island.is/skilavottord-web/screens'
+ import { RecyclingCompanies } from '@screens'

- export default withLocale('en')(RecyclingCompanies as Screen)
+ export default withLocale('en')<Screen>(RecyclingCompanies)
apps/skilavottord/web/pages/en/municipalities/add.tsx (1)

1-5: Apply consistent type safety improvements

Similar to the index page, consider improving type safety and import paths:

Example implementation:

- import { Screen } from '@island.is/skilavottord-web/types'
+ import { Screen } from '@types'
- import { withLocale } from '@island.is/skilavottord-web/i18n'
+ import { withLocale } from '@i18n'
- import { RecyclingCompanyCreate } from '@island.is/skilavottord-web/screens/RecyclingCompanies/RecyclingCompanyCreate'
+ import { RecyclingCompanyCreate } from '@screens/RecyclingCompanies/Create'

- export default withLocale('en')(RecyclingCompanyCreate as Screen)
+ export default withLocale('en')<Screen>(RecyclingCompanyCreate)
apps/skilavottord/web/pages/en/municipalities/[id].tsx (1)

1-5: Consider creating a shared page component

The code is identical to the Icelandic version except for the locale parameter. Consider creating a shared page component to reduce duplication:

+ // shared/MunicipalityPage.tsx
+ import { Screen } from '@island.is/skilavottord-web/types'
+ import { withLocale } from '@island.is/skilavottord-web/i18n'
+ import { RecyclingCompanyUpdate } from '@island.is/skilavottord-web/screens/RecyclingCompanies/RecyclingCompanyUpdate'
+
+ export const createMunicipalityPage = (locale: string) =>
+   withLocale(locale)(RecyclingCompanyUpdate as Screen)

Then both locale pages could simply import and use this shared component:

import { createMunicipalityPage } from '../shared/MunicipalityPage'
export default createMunicipalityPage('en') // or 'is'
apps/skilavottord/ws/src/app/modules/auth/user.model.ts (1)

Line range hint 1-28: Consider adding role documentation

The Role enum would benefit from JSDoc comments describing the permissions and responsibilities of each role, especially the newly added municipality role.

 export enum Role {
+  /** System administrator with full access */
   developer = 'developer',
+  /** Company that processes recycled vehicles */
   recyclingCompany = 'recyclingCompany',
+  /** Administrative user for recycling companies */
   recyclingCompanyAdmin = 'recyclingCompanyAdmin',
+  /** Recycling fund administrator */
   recyclingFund = 'recyclingFund',
+  /** Regular user accessing the system */
   citizen = 'citizen',
+  /** Municipality administrator with specific access rights */
   municipality = 'municipality',
 }
apps/skilavottord/web/components/PageHeader/PageHeader.tsx (2)

11-14: Consider enhancing props interface documentation

The props interface could be more descriptive to improve maintainability.

-export const PageHeader: FC<{ title: string; info: string }> = ({
+interface PageHeaderProps {
+  /** Main heading text for the page */
+  title: string;
+  /** Additional information to display in tooltip */
+  info: string;
+}
+
+export const PageHeader: FC<PageHeaderProps> = ({
   title,
   info,
 }) => {

17-26: Consider layout shift optimization

The current order switching between mobile and desktop might cause layout shift during page load.

Consider using CSS Grid's grid-template-areas instead of order properties for a more stable layout that doesn't cause Content Layout Shift (CLS).

apps/skilavottord/web/utils/roleUtils.ts (2)

18-19: Enhance default case handling

The default case using startCase might not be ideal for all future role values.

-    default:
-      return startCase(role)
+    default: {
+      console.warn(`Translation missing for role: ${role}`);
+      return startCase(role);
+    }

Missing test coverage for role translations

The codebase lacks dedicated test coverage for the getRoleTranslation utility function. While there is a test file in the web directory (locales.spec.ts), it doesn't cover the role translations. The function handles critical UI text for different user roles, including the newly added municipality role, and should be properly tested for both Icelandic and English translations.

Suggested actions:

  • Create a new test file roleUtils.spec.ts in apps/skilavottord/web/utils/
  • Add test cases covering all role translations in both languages
  • Include specific test cases for the new municipality role translations ('Sveitarfélag'/'Municipality')
🔗 Analysis chain

Line range hint 6-20: Verify test coverage for new role translation

The new municipality role translation needs test coverage to ensure correct behavior.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for existing test files and their coverage
fd -e test.ts -e spec.ts roleUtils apps/skilavottord/web/utils/

Length of output: 65


Script:

#!/bin/bash
# Let's try a broader search for test files in the web directory
fd -e test.ts -e spec.ts apps/skilavottord/web

# Also search for any usage of getRoleTranslation in test files
rg "getRoleTranslation" -t ts --glob "*test*" --glob "*spec*"

# Search for any test files containing "role" or "Role" to ensure we don't miss any
rg "role|Role" -t ts --glob "*test*" --glob "*spec*" apps/skilavottord/web

Length of output: 577


Script:

#!/bin/bash
# Search for test files in the correct way
fd . apps/skilavottord/web -e test.ts -e spec.ts

# Look for any test files containing Role enum
ast-grep --pattern 'enum Role {
  $$$
}'

# Search for any files importing roleUtils to see test coverage
rg -l "from ['|\"].*roleUtils" 

Length of output: 1261

apps/skilavottord/web/components/NavigationLinks/NavigationLinks.tsx (2)

29-30: Remove unnecessary template literals

Template literals are used unnecessarily for static string values. Since these strings don't contain any interpolation, they can be simplified.

-          title: `${sidenavText.recycled}`,
-          link: `${routes.recycledVehicles}`,
+          title: sidenavText.recycled,
+          link: routes.recycledVehicles,

Apply similar changes to other occurrences.

Also applies to: 34-35, 40-41, 45-46


7-11: Define interface for component props

Consider extracting the props interface for better type documentation and reusability.

+interface NavigationLinksProps {
+  activeSection: number;
+}
+
-export const NavigationLinks = ({
-  activeSection,
-}: {
-  activeSection: number
-}) => {
+export const NavigationLinks = ({ activeSection }: NavigationLinksProps) => {
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.model.ts (2)

108-108: Standardize comment style

The inline comment style differs from the rest of the file. Consider removing it since the @Field decorator with nullable: true is self-documenting.

-  @Field({ nullable: true }) // Ensure this field is nullable in GraphQL
+  @Field({ nullable: true })

101-115: Consider grouping related fields

The new municipality-related fields could be grouped with other identifying fields at the top of the model for better organization.

Consider moving these fields after the companyId field to keep related identifying fields together.

apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (1)

32-32: Remove redundant comment

The comment restates what's evident from the code and parameter names.

-    // If Role.municipality, return all recycling partners that are not municipalities
apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts (1)

21-32: Consider improving role-based filtering logic

While the role-based filtering is functionally correct, the logic could be more explicit and maintainable.

Consider refactoring to:

-  partnerId: user.role === Role.municipality ? user.partnerId : null,
+  partnerId: user.role === Role.municipality 
+    ? user.partnerId 
+    : (user.role === Role.recyclingFund ? null : user.partnerId),

This makes the intent clearer for each role and improves maintainability.

apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts (1)

Line range hint 43-65: Consider implementing pagination optimization

The current implementation might face performance issues with large datasets, especially when filtering across multiple partners.

Consider these optimizations:

  1. Add database indexes for frequently filtered columns
  2. Implement cursor-based pagination instead of offset-based
  3. Consider caching frequently accessed partner relationships
apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts (1)

20-25: Consider organizing roles by privilege level

The roles array would be more maintainable if organized by privilege level.

Consider reorganizing roles:

   roles: [
     Role.developer,
     Role.recyclingFund,
+    Role.municipality,
     Role.recyclingCompanyAdmin,
-    Role.municipality,
   ],
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (1)

149-151: Add type validation for municipalityId.

The current type checking could be more robust.

-    if (typeof input.municipalityId !== 'string') {
-      input.municipalityId = input.municipalityId?.value || ''
-    }
+    input.municipalityId = typeof input.municipalityId === 'string' 
+      ? input.municipalityId 
+      : input.municipalityId?.value || ''
apps/skilavottord/web/i18n/locales/is.json (2)

368-372: Ensure consistent navigation structure.

The new municipality-related entries in the sidenav section should maintain hierarchy consistency with other sections.

Consider this structure for better consistency:

  "recyclingFundSidenav": {
    "title": "Úrvinnslusjóður",
-   "municipalityTitle": "Sveitarfélag",
    "recycled": "Meðhöndluð ökutæki",
    "companies": "Móttökuaðilar",
    "accessControl": "Aðgangsstýring",
    "municipalities": "Sveitarfélög"
+   "municipality": {
+     "title": "Sveitarfélag"
+   }
  }

415-425: Improve form field labels and placeholders.

The form input labels and placeholders for company ID and name could be more descriptive.

Consider these improvements:

  "companyId": {
-   "label": "Auðkenni (ID)",
-   "placeholder": "Auðkenni",
+   "label": "Auðkenni fyrirtækis (ID)",
+   "placeholder": "Sláðu inn einkvæmt auðkenni",
    "rules": {
      "required": "Skylda er að fylla út auðkenni"
    }
  },
  "companyName": {
-   "label": "Nafn",
-   "placeholder": "Nafn",
+   "label": "Nafn fyrirtækis",
+   "placeholder": "Sláðu inn nafn fyrirtækis",
    "rules": {
      "required": "Skylda er að fylla út nafn"
    }
  }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 2692a1f and 525e7f7.

📒 Files selected for processing (33)
  • apps/skilavottord/web/auth/utils.ts (1 hunks)
  • apps/skilavottord/web/components/NavigationLinks/NavigationLinks.tsx (1 hunks)
  • apps/skilavottord/web/components/PageHeader/PageHeader.tsx (1 hunks)
  • apps/skilavottord/web/components/Sidenav/Sidenav.tsx (3 hunks)
  • apps/skilavottord/web/i18n/locales/en.json (5 hunks)
  • apps/skilavottord/web/i18n/locales/is.json (5 hunks)
  • apps/skilavottord/web/i18n/locales/translation.d.ts (6 hunks)
  • apps/skilavottord/web/pages/en/municipalities/[id].tsx (1 hunks)
  • apps/skilavottord/web/pages/en/municipalities/add.tsx (1 hunks)
  • apps/skilavottord/web/pages/en/municipalities/index.tsx (1 hunks)
  • apps/skilavottord/web/pages/municipalities/[id].tsx (1 hunks)
  • apps/skilavottord/web/pages/municipalities/add.tsx (1 hunks)
  • apps/skilavottord/web/pages/municipalities/index.tsx (1 hunks)
  • apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (8 hunks)
  • apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx (1 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx (3 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (5 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (8 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (5 hunks)
  • apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (4 hunks)
  • apps/skilavottord/web/utils/roleUtils.ts (1 hunks)
  • apps/skilavottord/ws/migrations/202412013210715-addcolumns-recycling-partners-municipality.js (1 hunks)
  • apps/skilavottord/ws/seeders/20201010211010-seed-recycling-request.js (6 hunks)
  • apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts (2 hunks)
  • apps/skilavottord/ws/src/app/modules/accessControl/accessControl.service.ts (2 hunks)
  • apps/skilavottord/ws/src/app/modules/auth/auth.guard.ts (1 hunks)
  • apps/skilavottord/ws/src/app/modules/auth/user.model.ts (1 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts (2 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.model.ts (1 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (4 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (2 hunks)
  • apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts (1 hunks)
  • apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (33)
apps/skilavottord/web/pages/en/municipalities/index.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/pages/municipalities/index.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/pages/municipalities/[id].tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/pages/en/municipalities/[id].tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/pages/en/municipalities/add.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/components/PageHeader/PageHeader.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/auth/user.model.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/components/NavigationLinks/NavigationLinks.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/accessControl/accessControl.service.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/pages/municipalities/add.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/migrations/202412013210715-addcolumns-recycling-partners-municipality.js (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.model.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/auth/auth.guard.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/utils/roleUtils.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/components/Sidenav/Sidenav.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/seeders/20201010211010-seed-recycling-request.js (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/auth/utils.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/is.json (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/en.json (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/translation.d.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
🔇 Additional comments (32)
apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx (1)

Line range hint 13-28: Well-structured interface definition

The interface follows TypeScript best practices with proper type safety, clear prop definitions, and appropriate use of generics and utility types.

apps/skilavottord/ws/seeders/20201010211010-seed-recycling-request.js (2)

10-10: Verify the new vehicle ID format against validation rules

The vehicle ID format has been changed from lowercase with hyphens (e.g., 'ftm-522') to uppercase without hyphens (e.g., 'VM006', 'LT579'). Please ensure this new format:

  1. Matches any validation rules in the application
  2. Aligns with the actual vehicle registration number format in Iceland

Also applies to: 19-19, 28-28, 46-46, 55-55, 64-64

✅ Verification successful

Based on the search results, I can see that:

  1. The codebase has both old and new vehicle ID formats:

    • Old format: lowercase with hyphens (e.g., 'jfk-433', 'ftm-522', 'mhs-583')
    • New format: uppercase without hyphens (e.g., 'VM006', 'LT579', 'AE135')
  2. The database schema and indexes support both formats as they use VARCHAR type.

  3. There are no explicit validation rules found for vehicle ID format in the codebase.

Let me generate the final response:

Vehicle ID format change appears safe to proceed

The new uppercase format without hyphens is consistent with other vehicle IDs in the seeder files and is supported by the database schema. No explicit validation rules were found that would conflict with this format change.

  • The database uses VARCHAR type for vehicle_id columns, which accommodates both formats
  • Indexes are format-agnostic: idx_vehicle_id and idx_request_vehicle_id
  • The repeated use of 'AE135' appears intentional for testing scenarios
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for vehicle ID validation patterns in the codebase
rg -g '!*.{json,md,lock}' -i 'vehicle.*validation|vehicle.*pattern|vehicle.*format' 

# Look for any existing vehicle ID usage to confirm format consistency
rg -g '!*/seeders/*' 'vehicle_id.*[A-Z0-9]{2,}' 

Length of output: 43261


28-28: Confirm if repeated vehicle ID 'AE135' is intentional

The vehicle ID 'AE135' is used in three different recycling requests with different states:

  1. Line 28: Default state
  2. Line 46: 'pendingRecycle' state
  3. Line 55: 'handOver' state

This might be intentional for testing different states of the same vehicle, but please verify if this accurately represents your test scenarios.

Also applies to: 46-46, 55-55

✅ Verification successful

Multiple recycling requests for vehicle 'AE135' are intentionally seeded for testing state transitions

Looking at the seeder and migration files, this is a deliberate test data setup:

  • The vehicle 'AE135' exists in the vehicle table (as 'aes-135')
  • The recycling_request table has a foreign key constraint to vehicle table
  • Multiple requests for the same vehicle show the progression through different states:
    1. Default state (initial request)
    2. 'pendingRecycle' state (in progress)
    3. 'handOver' state (completed)

This pattern is also seen with vehicle 'FZG90' which has both 'pendingRecycle' and 'handOver' states, confirming this is an intentional testing pattern.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if multiple requests for the same vehicle are handled in the application
ast-grep --pattern 'function $FUNC($PARAMS) {
  $$$
  vehicle_id
  $$$
}'

Length of output: 75


Script:

#!/bin/bash
# Search for files that handle recycling requests and vehicle IDs
rg -l "vehicle_id" --type js

# Check the content of relevant files for vehicle ID handling
rg "vehicle_id" -A 3 -B 3 --type js

# Look for any unique constraints or validations on vehicle_id
rg "unique.*vehicle_id|vehicle_id.*unique" --type js

Length of output: 15593

apps/skilavottord/web/pages/municipalities/index.tsx (2)

1-3: LGTM! Clean and well-structured imports.

The imports are properly organized using absolute paths, which is good for maintainability.


5-5: 🛠️ Refactor suggestion

⚠️ Potential issue

Component name inconsistency and missing NextJS page structure.

  1. The component name RecyclingCompanies seems inconsistent with the page's purpose (municipalities).
  2. The page lacks proper NextJS structure:
    • Missing static or server-side data fetching methods
    • Missing TypeScript interface for page props
    • Type casting might indicate potential type safety issues

Consider refactoring to follow NextJS best practices:

 import { Screen } from '@island.is/skilavottord-web/types'
 import { withLocale } from '@island.is/skilavottord-web/i18n'
-import { RecyclingCompanies } from '@island.is/skilavottord-web/screens'
+import { Municipalities } from '@island.is/skilavottord-web/screens'
+
+interface MunicipalitiesPageProps {
+  // Add required props here
+}
+
+export const getServerSideProps = async () => {
+  // Fetch required data
+  return {
+    props: {
+      // Return fetched data
+    },
+  }
+}
 
-export default withLocale('is')(RecyclingCompanies as Screen)
+const MunicipalitiesPage: Screen<MunicipalitiesPageProps> = (props) => {
+  return <Municipalities {...props} />
+}
+
+export default withLocale('is')(MunicipalitiesPage)

Let's verify the component naming consistency and type safety:

apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (1)

36-37: Verify server-side handling of new mutation fields

The new fields isMunicipality and municipalityId have been added to the GraphQL mutation. Ensure that the server-side schema and resolvers are updated accordingly to handle these fields.

Run the following script to verify that the server-side schema includes the new fields:

✅ Verification successful

Server-side schema and resolvers are properly updated for new mutation fields

The server-side implementation correctly handles the new fields isMunicipality and municipalityId:

  • The fields are properly defined in the database model (RecyclingPartnerModel)
  • They are included in the mutation input type (CreateRecyclingPartnerInput)
  • The resolver (RecyclingPartnerResolver) is configured to handle these fields in the create mutation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the server-side GraphQL schema includes 'isMunicipality' and 'municipalityId' in the 'createSkilavottordRecyclingPartner' mutation.

# Fetch the GraphQL schema and search for the fields in the mutation input type.
curl -s http://localhost:3333/api/graphql -H "Content-Type: application/json" \
  -d '{"query": "query { __type(name: \"CreateRecyclingPartnerInput\") { inputFields { name } } }"}' \
  | jq '.data.__type.inputFields[].name' \
  | grep -E 'isMunicipality|municipalityId'

Length of output: 259


Script:

#!/bin/bash
# Let's search for GraphQL schema files and mutations related to recycling partners
fd -e graphql -e gql | xargs cat

# Also search for TypeScript files that might contain the schema definition
rg -l "createSkilavottordRecyclingPartner|CreateRecyclingPartnerInput" --type=typescript

# Search for resolver implementations
ast-grep --pattern 'class $_ {
  $$$
  createSkilavottordRecyclingPartner($_) {
    $$$
  }
  $$$
}'

Length of output: 69739


Script:

#!/bin/bash
# Let's try a different approach to find the schema and resolver files
fd -e ts | xargs rg -l "createSkilavottordRecyclingPartner|CreateRecyclingPartnerInput|isMunicipality|municipalityId"

# Also search for any GraphQL schema files
fd -e graphql | xargs rg "createSkilavottordRecyclingPartner|CreateRecyclingPartnerInput|isMunicipality|municipalityId"

Length of output: 4163


Script:

#!/bin/bash
# Let's examine the relevant files in the skilavottord app
cat apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.model.ts
cat apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts
cat apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts

Length of output: 6657

apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx (1)

80-88: ⚠️ Potential issue

Handle potential undefined user role

When accessing user.role, ensure that user is defined to prevent potential runtime errors.

Apply this diff to add a null check for user:

 const { data, error, loading } = useQuery<Query>(
   SkilavottordAllRecyclingPartnersByTypeQuery,
   {
     variables: {
       isMunicipality,
       municipalityId: partnerId,
     },
+    skip: !user,
   },
 )

Likely invalid or redundant comment.

apps/skilavottord/web/pages/municipalities/add.tsx (1)

1-5: Verify language switching and apply consistent improvements

Similar improvements needed as the English version, plus ensure proper language switching is configured:

Example implementation:

- import { Screen } from '@island.is/skilavottord-web/types'
+ import { Screen } from '@types'
- import { withLocale } from '@island.is/skilavottord-web/i18n'
+ import { withLocale } from '@i18n'
- import { RecyclingCompanyCreate } from '@island.is/skilavottord-web/screens/RecyclingCompanies/RecyclingCompanyCreate'
+ import { RecyclingCompanyCreate } from '@screens/RecyclingCompanies/Create'

- export default withLocale('is')(RecyclingCompanyCreate as Screen)
+ export default withLocale('is')<Screen>(RecyclingCompanyCreate)

Let's verify the language switching configuration:

✅ Verification successful

Language switching is properly configured, but import paths can be improved

The language switching implementation is correctly set up:

  • Both English and Icelandic versions exist with proper locale configuration
  • The withLocale HOC is correctly implemented and used
  • Both versions use the same component with different locale parameters

The suggested import path improvements are valid and can be applied:

  • @island.is/skilavottord-web/types@types
  • @island.is/skilavottord-web/i18n@i18n
  • @island.is/skilavottord-web/screens/RecyclingCompanies/RecyclingCompanyCreate@screens/RecyclingCompanies/Create

The TypeScript generic syntax improvement (withLocale('is')<Screen>(RecyclingCompanyCreate)) is also valid and would provide better type safety.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if language switching is properly configured in next.config.js
echo "Checking Next.js i18n configuration..."
cat next.config.js | grep -A 10 "i18n:"

# Verify that both language versions are properly linked
echo "Checking for language switcher component usage..."
rg -l "LanguageSwitcher" apps/skilavottord/web/

Length of output: 330


Script:

#!/bin/bash
# Let's try to find the Next.js config file with different possible names and locations
echo "Searching for Next.js config files..."
fd -t f "next.config" apps/skilavottord/web/

# Check for i18n configuration in package.json as an alternative
echo "Checking package.json for i18n config..."
fd -t f "package.json" apps/skilavottord/web/ -x cat {} | jq -r '.i18n'

# Let's check for language-related components and configurations
echo "Checking for language-related files..."
rg -l "i18n|locale|language" apps/skilavottord/web/

# Check for the English version of the same page
echo "Checking for English version of municipalities/add..."
fd -t f "add.tsx" apps/skilavottord/web/pages/en/

Length of output: 5243


Script:

#!/bin/bash
# Let's check the Next.js config content for i18n settings
echo "Checking Next.js config content..."
cat apps/skilavottord/web/next.config.js

# Let's examine the i18n implementation
echo "Checking i18n implementation..."
cat apps/skilavottord/web/i18n/withLocale.tsx

# Compare both language versions of the add page
echo "Comparing both language versions..."
echo "=== Icelandic version ==="
cat apps/skilavottord/web/pages/municipalities/add.tsx
echo "=== English version ==="
cat apps/skilavottord/web/pages/en/municipalities/add.tsx

Length of output: 3552

apps/skilavottord/web/pages/municipalities/[id].tsx (1)

1-5: Verify the reuse of RecyclingCompanyUpdate component

While the code follows NextJS conventions, we should verify if reusing the RecyclingCompanyUpdate component for municipalities is intentional and handles municipality-specific requirements correctly.

Additionally, consider adding error boundaries and loading states for better user experience.

✅ Verification successful

Let me gather more information about the RecyclingCompanyUpdate component to verify its usage.


Let me try a different approach to locate and verify the component usage.


Let me check the actual implementation of the RecyclingCompanyUpdate component.


Reuse of RecyclingCompanyUpdate component is intentional and properly implemented

The component is correctly designed to handle both recycling companies and municipalities through the isMunicipality flag. It includes:

  • Proper route detection (router.route === routes.municipalities.edit)
  • Municipality-specific UI adaptations (titles, breadcrumbs, navigation)
  • Correct data handling for municipality role
  • Proper permission checks

The component safely handles both use cases with appropriate conditional logic and type checking. No architectural changes are needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if RecyclingCompanyUpdate component handles municipality role
ast-grep --pattern 'interface $_ {
  $$$
  municipality?: $_
  $$$
}'

Length of output: 5527


Script:

#!/bin/bash
# Check RecyclingCompanyUpdate component implementation
ast-grep --pattern 'export const RecyclingCompanyUpdate = $_'

# Search for municipality-related props or types in the component
rg -A 5 "RecyclingCompanyUpdate" apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate.tsx

# Check if there are other municipality-specific components
fd "Municipality" apps/skilavottord/web

Length of output: 328


Script:

#!/bin/bash
# Find all files containing RecyclingCompanyUpdate
rg -l "RecyclingCompanyUpdate"

# Find municipality-related components and pages
fd -e tsx -e ts "municipality" -i

# Check imports in the municipality page
cat apps/skilavottord/web/pages/municipalities/[id].tsx

Length of output: 3650


Script:

#!/bin/bash
# Check the implementation of RecyclingCompanyUpdate component
cat apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx

# Check if there are separate components for municipalities
cat apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/index.tsx

Length of output: 6021

apps/skilavottord/ws/src/app/modules/auth/user.model.ts (1)

9-9: Verify role-based access control implementation

The addition of the municipality role needs careful verification of access control implementation across the application.

✅ Verification successful

Let me gather more specific information about the RBAC implementation.


Let me check the specific roles guard implementation for the skilavottord application.


Role-based access control is properly implemented for the municipality role

The municipality role is correctly integrated into the existing RBAC system:

  • The RolesGuard implementation properly validates user roles
  • The role is used consistently in @authorize decorators alongside other administrative roles (developer, recyclingFund)
  • All recycling partner operations (queries and mutations) properly include the municipality role in their access control
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for proper RBAC implementation for municipality role
echo "Checking resolvers for municipality role authorization..."
rg -l "Role.municipality" --type ts

echo "\nChecking guards and decorators..."
ast-grep --pattern '@$_($$$)
export class $_ {
  $$$
  @$_([Role.municipality])
  $$$
}'

Length of output: 1081


Script:

#!/bin/bash
# Check resolver implementations for municipality role
echo "Checking vehicle resolver implementation..."
rg -B 2 -A 5 "Role\.municipality" apps/skilavortord/ws/src/app/modules/vehicle/vehicle.resolver.ts

echo "\nChecking access control resolver implementation..."
rg -B 2 -A 5 "Role\.municipality" apps/skilavortord/ws/src/app/modules/accessControl/accessControl.resolver.ts

echo "\nChecking for role-based guards..."
rg -l "RolesGuard" --type ts

echo "\nChecking guard implementations..."
ast-grep --pattern 'class $_ implements CanActivate {
  $$$
  canActivate($$$) {
    $$$
  }
}'

Length of output: 9011


Script:

#!/bin/bash
# Check roles guard implementation in skilavottord
echo "Checking roles guard implementation..."
rg -B 2 -A 10 "class RolesGuard" apps/skilavottord/ws/src/app/modules/auth/roles.guard.ts

echo "\nChecking for roles decorator usage..."
rg -B 2 -A 5 "@Roles" apps/skilavottord/ws/src/app/modules/

echo "\nChecking recycling partner resolver for role checks..."
rg -B 2 -A 5 "Role\.municipality" apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts

Length of output: 2185

apps/skilavottord/ws/migrations/202412013210715-addcolumns-recycling-partners-municipality.js (1)

4-10: Consider adding foreign key constraint

The municipality_id column appears to reference municipalities but lacks a foreign key constraint.

Consider adding a foreign key constraint to ensure referential integrity:

ALTER TABLE recycling_partner 
ADD CONSTRAINT fk_recycling_partner_municipality 
FOREIGN KEY (municipality_id) 
REFERENCES municipality(id);

Let's verify if the municipality table exists:

apps/skilavottord/web/auth/utils.ts (3)

21-28: LGTM: Permission updates for recycling company roles

The removal of 'deregisterVehicleKM' from recycling company roles while maintaining essential permissions follows the principle of least privilege.


34-34: LGTM: New municipality role with appropriate permissions

The new municipality role has been granted appropriate permissions for viewing recycled vehicles, recycling companies, and access control.


28-34: Verify the impact of adding 'municipalities' permission

The addition of 'municipalities' to recyclingFund role's permissions needs verification to ensure all related UI components handle this new permission correctly.

✅ Verification successful

The addition of 'municipalities' permission is properly handled in the codebase

The codebase already has comprehensive support for the 'municipalities' permission:

  • The permission is correctly added to the recyclingFund role in auth/utils.ts
  • The UI components handling municipalities are properly implemented with permission checks:
    • Navigation links in NavigationLinks.tsx handle municipality-related routes
    • Dedicated screens for municipalities exist with proper permission checks
    • Form components in RecyclingCompanyForm handle municipality-specific fields
    • Role-based access control is implemented throughout the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for UI components that might need updates for the new 'municipalities' permission
rg -t tsx -t ts "municipalities" apps/skilavottord/web/

Length of output: 83


Script:

#!/bin/bash
# Search for UI components that might need updates for the new 'municipalities' permission
# Using ripgrep without file type restrictions and checking the entire web directory
rg "municipalities" apps/skilavottord/web/

# Also search for any components or code handling permissions
rg -A 3 "hasPermission|usePermissions" apps/skilavottord/web/

# Check for any routes or components related to municipalities
rg -i "municipality|municipalities" apps/skilavottord/web/

Length of output: 29796

apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts (1)

44-45: LGTM: Nullable configuration for municipalityId

The municipalityId field is correctly configured as nullable in both the decorator and type.

apps/skilavottord/web/components/Sidenav/Sidenav.tsx (3)

3-7: LGTM: Clean interface extension

The addition of the optional hidden property to SidenavSection interface follows TypeScript best practices.


16-16: LGTM: Type extension for municipality icon

The SidenavIcon type has been correctly extended to include the new municipality icon.


26-26: LGTM: Clean conditional rendering

The section rendering logic has been updated to handle the new hidden property while maintaining readability.

apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (1)

28-52: Verify the handling of null values

The current implementation might need additional validation for edge cases.

✅ Verification successful

Null handling is properly implemented in the codebase

The code correctly handles null values for both isMunicipality and municipalityId fields:

  • The model definition explicitly marks municipalityId as nullable with allowNull: true
  • The GraphQL schema properly defines nullable fields with @Field({ nullable: true })
  • The service method correctly handles the OR condition for isMunicipality: null
  • The resolver properly defines nullable arguments with nullable: true
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential null handling issues in the codebase

# Check for explicit null checks in similar service methods
rg -A 2 "findAll.*null" apps/skilavottord/ws/src/app/modules

# Check for related model validations
ast-grep --pattern 'allowNull: true' apps/skilavottord/ws/src/app/modules

Length of output: 138


Script:

#!/bin/bash
# Let's check the model definition and related files for null handling

# Find the recycling partner model definition
fd "recyclingPartner.*model" apps/skilavottord/ws/src

# Check for null handling in the model and related files
rg -g "*.ts" "isMunicipality.*null|municipalityId.*null" apps/skilavottord/ws/src/app/modules

# Check for any validation or type definitions
rg -g "*.ts" "interface.*RecyclingPartner|type.*RecyclingPartner" apps/skilavottord/ws/src

Length of output: 1598


Script:

#!/bin/bash
# Let's examine the model definition and input types

# Check the model definition
cat apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.model.ts

# Check the input types
rg -g "*.ts" -A 5 "RecyclingPartnerInput|CreateRecyclingPartnerInput|UpdateRecyclingPartnerInput" apps/skilavottord/ws/src/app/modules/recyclingPartner/

Length of output: 10114

apps/skilavottord/ws/src/app/modules/auth/auth.guard.ts (1)

80-80: ⚠️ Potential issue

Verify security implications of removing IdsUserGuard

The removal of IdsUserGuard from the UseGuards decorator could potentially impact authentication security. Please ensure this change aligns with the application's security requirements.

Consider keeping IdsUserGuard for additional security layer or document why it's safe to remove.

apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (1)

20-20: Verify role-based access control implementation

The addition of Role.municipality to multiple methods needs verification:

  1. Ensure proper access restrictions
  2. Verify that municipality users can only access their own data

Also applies to: 55-55, 66-66, 87-87

✅ Verification successful

Let me gather more information about the access control implementation specific to municipality role.


Let me check the recycling partner service implementation to understand how municipality data access is restricted.


Role-based access control is properly implemented for municipality users

The codebase shows appropriate access restrictions for municipality users:

  • Municipality users can only access recycling partners that are not municipalities and belong to their municipality (filtered by municipalityId)
  • Vehicle queries are restricted by partnerId when the user has municipality role
  • The @authorize decorator properly enforces role-based access across resolvers
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for role checks in the codebase
rg "Role\.municipality" --type ts

# Look for access control implementations
ast-grep --pattern 'class $_ implements CanActivate {
  $$$
  canActivate($_) {
    $$$
  }
}'

Length of output: 4745


Script:

#!/bin/bash
# Check how municipality access is restricted in services
rg "Role\.municipality.*partnerId" -A 5 --type ts

# Look for partnerId checks in resolvers
ast-grep --pattern 'if ($user.role === Role.municipality) {
  $$$
}'

# Check authorization decorator implementation
rg "@Authorize" -A 3 --type ts

Length of output: 9492


Script:

#!/bin/bash
# Check recycling partner service implementation
rg -A 10 "class RecyclingPartnerService" --type ts

# Look for municipality-specific filtering in the service
rg -A 10 "Role\.municipality.*return" --type ts

# Check how partnerId is used in queries
ast-grep --pattern 'findOne({
  $$$
  partnerId: $user.partnerId
  $$$
})'

Length of output: 2637

apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts (1)

Line range hint 1-24: Verify access control implications of new municipality role

The addition of the municipality role requires verification of access control boundaries.

✅ Verification successful

Let me gather more information about the authorization patterns in the codebase.


Municipality role access control implementation is properly bounded

The municipality role has been consistently implemented with appropriate access controls across the codebase:

  • Access to skilavottordAllDeregisteredVehicles is properly restricted to [Role.developer, Role.recyclingFund, Role.municipality]
  • Municipality role access is limited to specific endpoints in recycling partner operations
  • The role's access is properly filtered using partnerId when querying vehicle data
  • No security implications found as the role follows the same authorization patterns as other roles in the system
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for potential security implications of municipality role
# Look for other endpoints that might need municipality role

# Search for @Authorize decorators
rg -B 2 -A 2 "@Authorize\({" 

# Search for role-based checks
rg "user\.role === " 

Length of output: 4935


Script:

#!/bin/bash
# Search for Authorize decorators with better regex
rg "@Authorize\(" -A 2

# Search for municipality role usage
rg "Role\.municipality"

# Search for role-based mutations/queries in vehicle resolver
ast-grep --pattern $'@Authorize({ roles: [$$$] })
@$_($$$) $$$'

Length of output: 9010

apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (2)

27-28: LGTM: Component modernization improves maintainability.

The replacement of Sidenav with NavigationLinks and Box with PageHeader aligns with modern component architecture, improving code maintainability and reusability.

Also applies to: 121-121, 141-141


31-36: Verify the impact of the required municipalityId parameter.

The GraphQL query now requires a municipalityId parameter. This change could affect existing query implementations.

apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (2)

122-124: 🛠️ Refactor suggestion

Consider using useEffect dependency array properly.

The useEffect hook should include all dependencies it uses.

-  React.useEffect(() => {
-    setValue('isMunicipality', isMunicipality)
-  }, [isMunicipality, setValue])
+  React.useEffect(() => {
+    setValue('isMunicipality', isMunicipality)
+  }, [isMunicipality, setValue])

Likely invalid or redundant comment.


81-87: Verify role-based access control for municipality users.

The component now handles municipality-specific logic. Ensure proper access control is maintained.

✅ Verification successful

Let me analyze the role-based access control implementation for municipality users based on the search results. I can see comprehensive evidence of proper RBAC implementation across the codebase, but let me verify the specific authorization checks for recycling company operations.


Role-based access control for municipality users is properly implemented

The verification shows comprehensive and consistent RBAC implementation:

  • Backend authorization is properly enforced through @Authorize decorators that explicitly include Role.municipality for relevant recycling partner operations
  • Frontend components correctly handle municipality-specific logic by:
    • Filtering recycling companies based on partnerId
    • Implementing proper role checks before rendering components
    • Maintaining proper access control in navigation and views

The implementation in RecyclingCompanyUpdate.tsx aligns with the overall RBAC architecture of the system.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for proper role definitions and access control
rg -A 5 "Role.municipality"

Length of output: 12054


Script:

#!/bin/bash
# Check for authorization decorators and role checks in recycling partner related files
ast-grep --pattern 'Authorize({ roles: [$$$] })'

Length of output: 5015

apps/skilavottord/web/i18n/locales/en.json (1)

638-642: LGTM: Well-structured route definitions.

The new municipality routes are properly structured and consistent with existing patterns.

apps/skilavottord/web/i18n/locales/translation.d.ts (5)

33-33: LGTM! Proper type definition for municipalities.

The municipalities property is correctly added to the Translation interface.


477-492: LGTM! Well-structured municipality interfaces.

The Municipalities and Municipality interfaces are properly defined with all necessary properties and follow the existing pattern.


517-517: LGTM! Optional municipality field in form inputs.

The municipality field is correctly added to the FormInputs interface as an optional field.


560-564: LGTM! Proper sidenav type definitions.

The municipalityTitle and municipalities properties are correctly added to the RecyclingFundSidenav interface.


577-577: LGTM! Route type definition for municipalities.

The municipalities property is correctly added to the Routes interface using the existing RecyclingCompaniesClass type.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (8)
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (3)

84-90: Consider a more robust route check

The current route check for isMunicipality is tightly coupled to the exact route path. Consider using a more maintainable approach.

Consider this alternative:

- const isMunicipality = router.route === routes.municipalities.edit
+ const isMunicipality = router.route.startsWith(routes.municipalities.baseRoute)

119-124: Move string literals to translation constants

Consider moving the hardcoded section number and route to translation constants for better maintainability.

Example approach:

const SECTIONS = {
  RECYCLING_COMPANIES: 2,
  MUNICIPALITIES: 1,
} as const

Line range hint 156-164: Enhance error handling in mutation response

The current error handling doesn't provide user feedback when the mutation fails.

Add error handling:

  const { errors } = await updateSkilavottordRecyclingPartner({
    variables: { input },
  })
  if (!errors) {
    router.push(routes.recyclingCompanies.baseRoute).then(() => {
      toast.success(t.recyclingCompany.view.updated)
    })
+ } else {
+   toast.error(t.recyclingCompany.view.updateError)
  }
🧰 Tools
🪛 Biome (1.9.4)

[error] 150-150: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

apps/skilavottord/web/components/NavigationLinks/NavigationLinks.tsx (2)

12-21: Consider adding null safety to role check

The role check could be made more robust by adding null safety:

-  if (hasMunicipalityRole(user?.role)) {
+  if (user?.role && hasMunicipalityRole(user.role)) {

23-52: Remove unnecessary template literals

Template literals are used unnecessarily for static strings in the sections array.

-          title: `${sidenavText.recycled}`,
-          link: `${routes.recycledVehicles}`,
+          title: sidenavText.recycled,
+          link: routes.recycledVehicles,
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (1)

58-73: Consider extracting route comparison logic

The route comparison could be made more maintainable by using a constant.

+const MUNICIPALITY_ROUTE = routes.municipalities.add;
+
-const isMunicipality = router.route === routes.municipalities.add
+const isMunicipality = router.route === MUNICIPALITY_ROUTE
apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (2)

123-145: Consolidate data fetching logic for recycling partners

The current implementation uses two separate useLazyQuery hooks (getAllRecyclingPartner and getAllRecyclingPartnersByMunicipality) to fetch recycling partner data based on the user's role. This can be simplified by combining the logic into a single hook or function that handles the condition internally. This will reduce code duplication and improve maintainability.

Consider refactoring as follows:

- const [
-   getAllRecyclingPartner,
-   {
-     data: recyclingPartnerData,
-     error: recyclingPartnerError,
-     loading: recyclingPartnerLoading,
-   },
- ] = useLazyQuery<Query>(SkilavottordAllRecyclingPartnersQuery, {
-   ssr: false,
- })
- 
- const [
-   getAllRecyclingPartnersByMunicipality,
-   {
-     data: recyclingPartnerByIdData,
-     error: recyclingPartnerByIdError,
-     loading: recyclingPartnerByIdLoading,
-   },
- ] = useLazyQuery<Query>(SkilavottordAllRecyclingPartnersByTypeQuery, {
-   ssr: false,
-   variables: { isMunicipality: false, municipalityId: user?.partnerId },
- })
+ const [
+   getRecyclingPartners,
+   {
+     data: recyclingPartnerData,
+     error: recyclingPartnerError,
+     loading: recyclingPartnerLoading,
+   },
+ ] = useLazyQuery<Query>(
+   user.role === Role.municipality
+     ? SkilavottordAllRecyclingPartnersByTypeQuery
+     : SkilavottordAllRecyclingPartnersQuery,
+   {
+     ssr: false,
+     variables:
+       user.role === Role.municipality
+         ? { isMunicipality: false, municipalityId: user?.partnerId }
+         : {},
+   },
+ )

226-228: Handle undefined municipalityId safely in labels

In constructing the label for recyclingPartners, the ternary check on partner.municipalityId should ensure that undefined or null values are handled properly to avoid displaying undefined - companyName.

Consider using a more robust nullish coalescing operator:

- label: partner.municipalityId
+ label: partner.municipalityId ?? ''

Or adjust the ternary condition:

- label: partner.municipalityId
+ label: partner.municipalityId
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 525e7f7 and d1108ea.

📒 Files selected for processing (9)
  • apps/skilavottord/web/auth/utils.ts (1 hunks)
  • apps/skilavottord/web/components/NavigationLinks/NavigationLinks.tsx (1 hunks)
  • apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (9 hunks)
  • apps/skilavottord/web/screens/AccessControlCompany/AccessControlCompany.tsx (2 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx (3 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (5 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (8 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (5 hunks)
  • apps/skilavottord/ws/src/app/modules/accessControl/accessControl.service.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/skilavottord/web/auth/utils.ts
👮 Files not reviewed due to content moderation or server errors (2)
  • apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx
  • apps/skilavottord/web/screens/AccessControlCompany/AccessControlCompany.tsx
🧰 Additional context used
📓 Path-based instructions (8)
apps/skilavottord/web/components/NavigationLinks/NavigationLinks.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/accessControl/accessControl.service.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControlCompany/AccessControlCompany.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
📓 Learnings (1)
apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (1)
Learnt from: birkirkristmunds
PR: island-is/island.is#17109
File: apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx:336-360
Timestamp: 2024-12-10T15:10:49.998Z
Learning: In the `RecyclingCompanyForm` component (`apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx`), the `isMunicipality` checkbox must remain in the DOM for all users since its value is stored in the database. However, only users with the developer role can manipulate it through the UI. This ensures that the checkbox value is maintained correctly while restricting interaction to authorized users.
🔇 Additional comments (12)
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (2)

Line range hint 169-205: Well-structured component rendering

The component rendering follows NextJS best practices with:

  • Proper loading state handling
  • Consistent layout structure
  • Clear component composition

112-114: Add null check for partnerId in refetchQueries

The partnerId could be undefined when passed to the refetch query, which might cause unexpected behavior.

Let's verify the handling of undefined partnerId in the codebase:

apps/skilavottord/web/components/NavigationLinks/NavigationLinks.tsx (1)

1-11: LGTM! Clean imports and well-typed props.

apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (1)

39-40: LGTM! Proper mutation field additions

The new fields isMunicipality and municipalityId are correctly added to the mutation response type.

apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx (3)

33-49: LGTM! Well-structured GraphQL query

The new query properly handles type-specific filtering with correct variable types.


77-81: Add null check for municipality role handling

This addresses a previously identified issue with partner ID assignment.

-  if (hasMunicipalityRole(user?.role)) {
+  if (user?.role && hasMunicipalityRole(user.role)) {

104-126: 🛠️ Refactor suggestion

Refactor routing logic and investigate BASE-PATH issue

  1. The routing logic is duplicated between handleCreate and handleUpdate
  2. There's a comment about BASE-PATH duplication that needs investigation

Suggested refactor:

+  const getRoutePath = (type: 'create' | 'edit', id?: string) => {
+    const base = isMunicipality ? routes.municipalities : routes.recyclingCompanies;
+    const path = type === 'create' ? base.add : base.edit;
+    return id ? { pathname: path, query: { id } } : { pathname: path };
+  }

   const handleCreate = () => {
-    if (isMunicipality) {
-      router.push({
-        pathname: routes.municipalities.add,
-      })
-    } else {
-      router.push({
-        pathname: routes.recyclingCompanies.add,
-      })
-    }
+    router.push(getRoutePath('create'));
   }

   const handleUpdate = (id: string) => {
-    if (isMunicipality) {
-      router.push({
-        pathname: routes.municipalities.edit,
-        query: { id },
-      })
-    } else {
-      router.push({
-        pathname: routes.recyclingCompanies.edit,
-        query: { id },
-      })
-    }
+    router.push(getRoutePath('edit', id));
   }
apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (3)

221-224: Ensure consistency of partners data structure

Merging data from recyclingPartnerData and recyclingPartnerByIdData into partners may lead to inconsistent data structures if the returned data differs. Verify that both data sources return data in the same format and handle any discrepancies to prevent runtime errors.


234-247: Simplify roles filtering logic for better readability

The current roles filtering logic involves multiple filters and conditions, which can be simplified to enhance readability and maintainability.

Consider refactoring:

const roles = Object.keys(AccessControlRole)
  .filter((role) => {
    if (!hasDeveloperRole(user?.role) && role === Role.developer) {
      return false
    }
    if (user.role === Role.municipality) {
      return [Role.recyclingCompany, Role.recyclingCompanyAdmin, Role.municipality].includes(role)
    }
    return true
  })
  .map((role) => ({
    label: getRoleTranslation(role as Role, activeLocale),
    value: role,
  }))

255-263: Ensure partners data is fetched before opening modal

When opening the create access control modal, ensure that the partners data is fetched before rendering the modal to prevent potential undefined data issues.

Consider adding a loading state or disabling the button until data is ready.

apps/skilavottord/ws/src/app/modules/accessControl/accessControl.service.ts (2)

68-69: Optimize database query for large partnerIds arrays

Using the IN operator with a potentially large partnerIds array can lead to performance issues. Consider implementing pagination, batching, or alternative querying strategies for handling large datasets.


37-66: ⚠️ Potential issue

Add safeguards to recursive getAllCompanyIds function

The recursive getAllCompanyIds function lacks protection against circular references and unchecked recursion depth, which could lead to stack overflows or performance issues.

Implement safeguards by tracking visited partnerIds and limiting recursion depth:

- const getAllCompanyIds = async (partnerId: string) => {
-   partnerIds.push(partnerId)
-   const subCompanies = await RecyclingPartnerModel.findAll({
-     where: { municipalityId: partnerId },
-   })
-   for (const subCompany of subCompanies) {
-     await getAllCompanyIds(subCompany.companyId)
-   }
- }
+ const getAllCompanyIds = async (
+   partnerId: string,
+   visited = new Set<string>(),
+   depth = 0,
+ ) => {
+   const MAX_DEPTH = 100
+   if (depth > MAX_DEPTH || visited.has(partnerId)) return
+   visited.add(partnerId)
+   partnerIds.push(partnerId)
+   const subCompanies = await RecyclingPartnerModel.findAll({
+     where: { municipalityId: partnerId },
+   })
+   for (const subCompany of subCompanies) {
+     await getAllCompanyIds(subCompany.companyId, visited, depth + 1)
+   }
+ }

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

🧹 Outside diff range and nitpick comments (12)
apps/skilavottord/ws/src/app/modules/accessControl/accessControl.model.ts (1)

Line range hint 66-73: LGTM! The new partnerId field is well-structured.

The implementation follows TypeScript, GraphQL, and Sequelize best practices with proper decorators and type safety.

Consider adding a JSDoc comment to document the purpose of this field and its relationship with RecyclingPartnerModel:

+ /**
+  * ID of the associated recycling partner. Used to establish relationship
+  * between access control entries and recycling partners for municipality management.
+  */
  @Field({ nullable: true })
  @ForeignKey(() => RecyclingPartnerModel)
  @Column({
    type: DataType.STRING,
    field: 'partner_id',
    allowNull: true,
  })
  partnerId?: string
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (2)

112-116: Add TypeScript types for query variables

Consider adding explicit TypeScript types for the query variables to improve type safety and maintainability.

+ interface RecyclingPartnersQueryVars {
+   isMunicipalityPage: boolean
+   municipalityId: string | null
+ }

  refetchQueries: [
    {
      query: SkilavottordRecyclingPartnerQuery,
      variables: { input: { companyId: id } },
    },
    {
      query: SkilavottordRecyclingPartnersQuery,
-     variables: {
-       isMunicipalityPage: isMunicipalityPage,
-       municipalityId: partnerId,
-     },
+     variables: {
+       isMunicipalityPage,
+       municipalityId: partnerId,
+     } as RecyclingPartnersQueryVars,
    },
  ],

128-130: Add cleanup function to useEffect

Consider adding a cleanup function to handle component unmounting, following React best practices.

  React.useEffect(() => {
    setValue('isMunicipality', isMunicipalityPage)
+   return () => {
+     // Reset the form value on unmount if needed
+     setValue('isMunicipality', false)
+   }
  }, [isMunicipalityPage, setValue])
apps/skilavottord/web/screens/DeregisterVehicle/Overview/Overview.tsx (1)

Line range hint 52-195: Excellent implementation following NextJS and TypeScript best practices.

The component demonstrates:

  • Proper error handling and loading states
  • Type-safe implementation
  • Efficient data fetching with pagination
  • Clean and maintainable structure

Consider implementing React Query or SWR for better cache management and automatic revalidation of data in future iterations.

apps/skilavottord/web/i18n/locales/translation.d.ts (1)

478-493: Consider enhancing type safety for municipality interfaces.

The new Municipalities and Municipality interfaces reuse existing patterns, which is good. However, consider adding more specific types for municipality-specific fields that might have unique validation requirements.

Example enhancement:

 export interface Municipality {
   view: View
   add: Add
-  form: RecyclingCompanyForm
+  form: {
+    inputs: MunicipalityFormInputs
+    buttons: FormButtons
+  }
 }

+export interface MunicipalityFormInputs extends FormInputs {
+  // Add municipality-specific fields with appropriate validation rules
+  region?: {
+    label: string
+    placeholder: string
+    rules: {
+      required: string
+    }
+  }
+}
apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx (2)

68-71: Initialize component states in useEffect

The useEffect hook initializes the visibility of company and municipality selection inputs. Confirm that this aligns with the intended initial state when the modal is opened.

Consider whether the useEffect is necessary here, as the initial state values are already set in the useState declarations.


73-91: Simplify handleRoleOnChange logic

The handleRoleOnChange function has nested conditions that could be refactored for clarity and maintainability. Consider simplifying the logic to reduce complexity.

Here's a possible refactor:

 const handleRoleOnChange = (e: Option) => {
-  if (hasMunicipalityRole(user?.role)) {
-    if (e && e.value === Role.municipality) {
-      setShowCompaniesSelection(false)
-    } else {
-      setShowCompaniesSelection(true)
-    }
-    setShowMunicipalitiesSelection(false)
-  } else if (hasRecyclingFundRole(user?.role)) {
-    if (e && e.value === Role.municipality) {
-      setShowCompaniesSelection(false)
-      setShowMunicipalitiesSelection(true)
-    } else {
-      setShowMunicipalitiesSelection(false)
-      setShowCompaniesSelection(true)
-    }
-  }
+  const isMunicipalityRoleSelected = e && e.value === Role.municipality
+  if (hasMunicipalityRole(user?.role)) {
+    setShowCompaniesSelection(!isMunicipalityRoleSelected)
+    setShowMunicipalitiesSelection(false)
+  } else if (hasRecyclingFundRole(user?.role)) {
+    setShowCompaniesSelection(!isMunicipalityRoleSelected)
+    setShowMunicipalitiesSelection(isMunicipalityRoleSelected)
+  }
 }
apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (2)

75-78: Consider extracting role-based logic

The inline role check creates tight coupling. Consider extracting this logic to a utility function for better maintainability.

- partnerId:
-   role.value === Role.municipality
-     ? municipalityId?.value
-     : partnerId?.value || null,
+ partnerId: getPartnerId(role.value, municipalityId?.value, partnerId?.value),

94-97: Simplify partner ID requirement check

The current check could be simplified using array inclusion.

- partnerIdRequired={
-   watch('role')?.value === Role.recyclingCompanyAdmin ||
-   watch('role')?.value === Role.recyclingCompany
- }
+ partnerIdRequired={[Role.recyclingCompanyAdmin, Role.recyclingCompany].includes(watch('role')?.value)}
apps/skilavottord/web/screens/CompanyInfo/CompanyInfo.tsx (1)

28-28: Consider prop type validation

The PageHeader component is used without TypeScript prop validation. Ensure proper type checking.

Add prop types validation:

interface PageHeaderProps {
  title: string;
  info?: string;
}

Also applies to: 105-105

apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (1)

278-311: Consider enhancing error handling for municipality selection.

While the implementation is clean, consider adding more specific error messages for municipality selection failures.

 <Select
   name={name}
   label={t.recyclingCompany.form.inputs.municipality.label}
   placeholder={t.recyclingCompany.form.inputs.municipality.placeholder}
   size="md"
   value={municipalities?.find((option) => option.value === value)}
   hasError={!!errors?.municipality?.message}
-  errorMessage={errors?.municipality?.message}
+  errorMessage={errors?.municipality?.message || t.recyclingCompany.form.inputs.municipality.error}
   backgroundColor="blue"
   options={municipalities}
   onChange={onChange}
   isCreatable
 />
apps/skilavottord/ws/src/app/modules/recyclingRequest/recyclingRequest.service.ts (1)

46-48: Consider enhancing error handling for disposalStationId retrieval.

While the addition of disposalStationId retrieval is good, consider adding specific error handling for cases where the ID cannot be retrieved.

 const disposalStationId =
-  await this.recyclingPartnerService.getGetPayingPartnerId(disposalStation)
+  await this.recyclingPartnerService.getGetPayingPartnerId(disposalStation)
+    .catch((error) => {
+      this.logger.error('Failed to retrieve disposal station ID', { error, disposalStation })
+      throw new Error(`Invalid disposal station: ${disposalStation}`)
+    })
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1108ea and a2ce8ec.

📒 Files selected for processing (21)
  • apps/skilavottord/web/auth/utils.ts (1 hunks)
  • apps/skilavottord/web/i18n/locales/en.json (5 hunks)
  • apps/skilavottord/web/i18n/locales/is.json (6 hunks)
  • apps/skilavottord/web/i18n/locales/translation.d.ts (7 hunks)
  • apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (12 hunks)
  • apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (5 hunks)
  • apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx (4 hunks)
  • apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (6 hunks)
  • apps/skilavottord/web/screens/AccessControlCompany/AccessControlCompany.tsx (3 hunks)
  • apps/skilavottord/web/screens/CompanyInfo/CompanyInfo.tsx (2 hunks)
  • apps/skilavottord/web/screens/DeregisterVehicle/Overview/Overview.tsx (2 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx (3 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (5 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (7 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (5 hunks)
  • apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (4 hunks)
  • apps/skilavottord/ws/src/app/modules/accessControl/accessControl.model.ts (1 hunks)
  • apps/skilavottord/ws/src/app/modules/accessControl/accessControl.service.ts (2 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (4 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (3 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingRequest/recyclingRequest.service.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/skilavottord/ws/src/app/modules/accessControl/accessControl.service.ts
  • apps/skilavottord/web/screens/AccessControlCompany/AccessControlCompany.tsx
🧰 Additional context used
📓 Path-based instructions (19)
apps/skilavottord/ws/src/app/modules/accessControl/accessControl.model.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/CompanyInfo/CompanyInfo.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/DeregisterVehicle/Overview/Overview.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingRequest/recyclingRequest.service.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/is.json (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/en.json (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/auth/utils.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/translation.d.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
📓 Learnings (1)
apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (1)
Learnt from: birkirkristmunds
PR: island-is/island.is#17109
File: apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx:336-360
Timestamp: 2024-12-10T15:10:49.998Z
Learning: In the `RecyclingCompanyForm` component (`apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx`), the `isMunicipality` checkbox must remain in the DOM for all users since its value is stored in the database. However, only users with the developer role can manipulate it through the UI. This ensures that the checkbox value is maintained correctly while restricting interaction to authorized users.
🔇 Additional comments (52)
apps/skilavottord/ws/src/app/modules/accessControl/accessControl.model.ts (1)

Line range hint 66-77: Verify database migration for the new partnerId field.

The model changes look correct, but we should ensure there's a corresponding database migration for this new field.

apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (1)

43-43: Add municipalityId to the mutation response

The municipalityId field is included in the query response but missing in the mutation response. This inconsistency could lead to stale data after updates.

Also applies to: 47-63

apps/skilavottord/web/screens/DeregisterVehicle/Overview/Overview.tsx (2)

3-4: LGTM! Well-organized imports following NextJS best practices.

The imports are logically grouped by source/type, enhancing code readability and maintainability.

Also applies to: 13-14, 21-21, 23-23, 27-27, 29-29, 32-32


171-171: Good refactoring to use the shared PageHeader component.

The change improves component reusability and standardizes header presentation across the application.

Let's verify the PageHeader component implementation:

✅ Verification successful

Let me gather more information about the PageHeader component implementation.


PageHeader component is well-implemented and consistently used

The PageHeader component is properly implemented using Island UI components and is consistently used across multiple screens in the application. It:

  • Accepts required title and info props
  • Uses appropriate layout components (Box, GridRow, GridColumn)
  • Implements consistent styling with Text variant="h1" and Tooltip
  • Shows consistent usage pattern across 7 different screens
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify PageHeader component implementation and usage

# Check PageHeader component implementation
ast-grep --pattern 'export const PageHeader = ({ title, info }: Props) => {
  $$$
}'

# Check for consistent usage across the application
rg -A 2 '<PageHeader.*title=.*info=.*>'

Length of output: 2545


Script:

#!/bin/bash
# Search for PageHeader component definition
fd PageHeader.tsx --exec cat {}

Length of output: 974

apps/skilavottord/web/i18n/locales/translation.d.ts (5)

33-33: LGTM: Translation interface updated correctly.

The addition of the municipalities property to the Translation interface is consistent with the existing pattern and properly typed.


75-75: LGTM: ModalInputs interface updated correctly.

The addition of the municipality property to the ModalInputs interface follows the existing pattern by reusing the Name type.


469-469: LGTM: RecyclingCompaniesButtons interface updated correctly.

The addition of the addMunicipality property to the RecyclingCompaniesButtons interface maintains consistency with existing button properties.


561-561: LGTM: RecyclingFundSidenav interface updated correctly.

The addition of municipalityTitle and municipalities properties to the RecyclingFundSidenav interface follows the existing naming pattern.

Also applies to: 565-565


578-578: Verify the route configuration.

The addition of the municipalities property to the Routes interface using RecyclingCompaniesClass type is consistent. However, verify that the route structure matches the actual routing implementation.

✅ Verification successful

Route configuration is correctly implemented and matches the type definition

The route configuration for municipalities is properly implemented and used consistently throughout the codebase:

  • The type definition in translation.d.ts correctly uses RecyclingCompaniesClass type for the municipalities route
  • The route is actively used in components:
    • RecyclingCompanies.tsx uses routes.municipalities.baseRoute, routes.municipalities.add, and routes.municipalities.edit
    • NavigationLinks.tsx implements the navigation using routes.municipalities.baseRoute
    • Route checks are properly implemented in components like RecyclingCompanyUpdate and RecyclingCompanyCreate
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify route configuration matches implementation
# Test: Search for municipality route definitions in the codebase
rg -t typescript -t javascript "municipalities.*route" ./apps/skilavottord/web

Length of output: 115


Script:

#!/bin/bash
# Search for route configurations and usages of municipalities
rg -g '*.{ts,tsx,js,jsx}' 'municipalities' ./apps/skilavottord/web

Length of output: 5320


Script:

#!/bin/bash
# Look for route definitions in common routing files
fd -e ts -e tsx -e js -e jsx "routes|router" ./apps/skilavottord/web --exec cat {}

Length of output: 1152


Script:

#!/bin/bash
# Check the type definition and its usage
ast-grep --pattern 'interface $_ {
  $$$
  municipalities: $_
  $$$
}'

Length of output: 3776

apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (2)

9-9: LGTM!

The Op import from sequelize is correctly added and is necessary for the query conditions.


28-52: 🛠️ Refactor suggestion

Improve method implementation and add error handling

  1. The comment on line 32 is misleading as it doesn't match the actual logic
  2. The method could be simplified to use a single query with dynamic conditions
  3. Error handling should be added

Apply this diff to improve the implementation:

 async findRecyclingPartners(
   isMunicipalityPage: boolean,
   municipalityId: string | null,
 ): Promise<RecyclingPartnerModel[]> {
-  // If Role.municipality, return all recycling partners that are not municipalities
-  if (municipalityId) {
-    return await this.recyclingPartnerModel.findAll({
-      where: {
-        isMunicipality: false,
-        municipalityId: municipalityId,
-      },
-    })
-  }
-
-  if (isMunicipalityPage) {
-    return await this.recyclingPartnerModel.findAll({
-      where: { isMunicipality: true },
-    })
-  }
-  return await this.recyclingPartnerModel.findAll({
-    where: {
-      [Op.or]: [{ isMunicipality: false }, { isMunicipality: null }],
-    },
-  })
+  try {
+    const whereCondition = municipalityId
+      ? { isMunicipality: false, municipalityId }
+      : isMunicipalityPage
+      ? { isMunicipality: true }
+      : {
+          [Op.or]: [{ isMunicipality: false }, { isMunicipality: null }],
+        };
+
+    return await this.recyclingPartnerModel.findAll({
+      where: whereCondition,
+    });
+  } catch (error) {
+    throw new Error(`Failed to fetch recycling partners: ${error.message}`);
+  }
 }
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (2)

20-20: LGTM!

The addition of Role.municipality to the authorization roles is consistent across all methods and aligns with the PR objectives.

Also applies to: 30-30, 55-55, 66-66, 87-87


22-27: 🛠️ Refactor suggestion

Align method name with GraphQL query name

The method name should match the GraphQL query name for consistency and clarity.

Apply this diff to fix the naming:

 @Query(() => [RecyclingPartnerModel], {
   name: 'skilavottordAllRecyclingPartners',
 })
-async getAllRecyclingPartners(): Promise<RecyclingPartnerModel[]> {
+async skilavottordAllRecyclingPartners(): Promise<RecyclingPartnerModel[]> {
   return this.recyclingPartnerService.findAll()
 }
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (2)

123-131: Simplify success handling logic

The success handling code is duplicated and can be simplified.

Apply this diff to simplify the code:

-      if (isMunicipalityPage) {
-        router.push(routes.municipalities.baseRoute).then(() => {
-          toast.success(t.recyclingCompany.add.added)
-        })
-      } else {
-        router.push(routes.recyclingCompanies.baseRoute).then(() => {
-          toast.success(t.recyclingCompany.add.added)
-        })
-      }
+      const route = isMunicipalityPage
+        ? routes.municipalities.baseRoute
+        : routes.recyclingCompanies.baseRoute
+      router.push(route).then(() => {
+        toast.success(t.recyclingCompany.add.added)
+      })

75-85: 🛠️ Refactor suggestion

Improve form initialization and validation

The form initialization could be improved to handle null values and add validation.

Apply this diff to improve the form handling:

 const {
   control,
   handleSubmit,
   formState: { errors },
 } = useForm({
   mode: 'onChange',
-  defaultValues: {
-    isMunicipality: isMunicipalityPage,
-    municipalityId: partnerId,
-  },
+  defaultValues: isMunicipalityPage
+    ? { isMunicipality: true }
+    : { isMunicipality: false, municipalityId: partnerId || '' },
 })
apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (6)

1-1: Imports are correctly added

The addition of useContext, useEffect, UserContext, and hasMunicipalityRole imports is appropriate for the new functionality related to municipalities and user roles.

Also applies to: 12-13


23-23: Include municipalities in props interface

Adding municipalities to the AccessControlCreateProps interface ensures that the component can receive and utilize the list of municipalities.


38-38: Retrieve user data using useContext

Using const { user } = useContext(UserContext) correctly accesses the user information from the context for role-based logic within the component.


65-73: Ensure all required fields are submitted

In the handleOnSubmit function, verify that all required fields, especially the newly added municipalityId, are correctly included in the submission data and validated.


77-80: Reset form state when modal visibility changes

The useEffect hook resets the form whenever the show prop changes, ensuring that the form is cleared when the modal is reopened. This enhances the user experience by preventing residual data from previous entries.


90-90: Pass municipalities prop to AccessControlModal

Providing the municipalities prop to AccessControlModal allows the modal to display municipality options, aligning with the new feature requirements.

apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx (6)

1-8: Imports are correctly updated

The inclusion of useContext, useEffect, useState, and kennitala imports supports the added functionality for role handling and national ID validation.


13-21: Update interface to include new props

Adding municipalities and currentPartner to AccessControlModalProps enables the component to handle municipalities and existing partner data effectively.


64-67: Retrieve user context and initialize state

Using useContext(UserContext) to access user, and initializing showCompanies and showMunicipalities states, sets up the component for dynamic rendering based on user roles.


208-211: Ensure handleRoleOnChange is called correctly

In the Select component for role, the onChange handler correctly updates the form value and triggers handleRoleOnChange to adjust the form based on the selected role.


216-249: Conditional rendering of partnerId selection

The partnerId selection is conditionally rendered based on showCompanies. Ensure that this logic accurately reflects when a user should select a recycling partner.


250-279: Add municipalityId selection for relevant roles

Introducing the municipalityId selection when showMunicipalities is true allows users with certain roles to select a municipality. Ensure that the validation rules and error handling for this field are correctly implemented.

apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (6)

127-153: Optimize data fetching with useLazyQuery hooks

Replacing useQuery with useLazyQuery for fetching recycling partner data allows more controlled and efficient data retrieval based on user interactions and roles.


224-227: Ensure correct retrieval of accessControls data

The accessControls variable consolidates data from different queries. Verify that it correctly handles data from all potential sources to prevent missing or inconsistent access control entries.


255-267: Simplify roles filtering logic

The roles filtering logic can be simplified and made more readable.

Apply this diff to improve the filtering logic:

 const roles = Object.keys(AccessControlRole)
-  .filter((role) =>
-    !hasDeveloperRole(user?.role) ? role !== Role.developer : role,
-  )
-  .filter((role) => {
-    if (hasMunicipalityRole(Role.municipality)) {
-      return (
-        role === Role.recyclingCompany ||
-        role === Role.recyclingCompanyAdmin ||
-        role === Role.municipality
-      )
-    }
-    return role
-  })
+  .filter((role) => {
+    if (!hasDeveloperRole(user?.role) && role === Role.developer) {
+      return false
+    }
+    if (hasMunicipalityRole(user?.role)) {
+      return [
+        Role.recyclingCompany,
+        Role.recyclingCompanyAdmin,
+        Role.municipality,
+      ].includes(role as Role)
+    }
+    return true
+  })
   .map((role) => ({
     label: getRoleTranslation(role as Role, activeLocale),
     value: role,
   }))

This suggestion aligns with a previous review comment.


276-284: Ensure partners data is fetched before rendering modal

When opening the create access control modal, ensure that the partners data is fetched based on the user's role to prevent any potential data issues.


339-347: Update layout components and pass new props

Replacing Sidenav with NavigationLinks and updating the PageHeader enhances the UI. Passing municipalities to AccessControlCreate aligns with the new feature implementation.


205-211: ⚠️ Potential issue

Include all data sources in error and loading states

Ensure that the error, loading, and isData variables include all relevant data sources (recyclingPartnerData, recyclingPartnerByIdData, and accessControlsData) to accurately reflect the component's state.

Apply this diff to include all data sources:

 const error =
-  recyclingPartnerError || accessControlsError || recyclingPartnerByIdError
 const loading =
-  recyclingPartnerLoading || accessControlsLoading || recyclingPartnerByIdLoading
 const isData = 
-  !!recyclingPartnerData || !!accessControlsData
+  recyclingPartnerError || accessControlsError || recyclingPartnerByIdError
+  recyclingPartnerLoading || accessControlsLoading || recyclingPartnerByIdLoading
+  !!recyclingPartnerData || !!recyclingPartnerByIdData || !!accessControlsData

This comment addresses a similar concern mentioned in previous reviews.

apps/skilavottord/web/auth/utils.ts (3)

13-19: Introduce role-checking utility functions

Adding hasDeveloperRole, hasMunicipalityRole, and hasRecyclingFundRole functions improves code readability and reusability when checking user roles throughout the application.


27-40: Update hasPermission function with new roles and pages

Modifying the permittedRoutes object to include the municipality role and updating permitted pages for existing roles ensures that access control aligns with the application's updated role definitions.


13-16: Potential impact of removing 'deregisterVehicleKM'

Removing 'deregisterVehicleKM' from the Page type might affect parts of the application that rely on this page. Ensure that this page is deprecated and no longer in use.

Run the following script to check for any remaining references to 'deregisterVehicleKM':

✅ Verification successful

No references to deregisterVehicleKM found in the codebase

Since no references to deregisterVehicleKM were found in any form (camelCase, kebab-case, or case-insensitive variations) across the entire codebase, it appears that this page has been completely removed and is no longer in use. The removal of this value from the Page type is safe.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for any usages of 'deregisterVehicleKM' in the codebase.

# Test: Find all occurrences of 'deregisterVehicleKM'
rg 'deregisterVehicleKM'

Length of output: 24


Script:

#!/bin/bash
# Let's try a case-insensitive search and also look for kebab-case variations
rg -i "deregister.*vehicle.*km|deregister-vehicle-km"

# Also search for any files with similar naming patterns
fd -i "deregister.*vehicle.*km"

Length of output: 89

apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (1)

60-63: Verify municipality ID mapping logic

The code assumes that municipality's companyId matches the recyclingPartner's companyId. This assumption might lead to incorrect mappings.

✅ Verification successful

Based on the codebase analysis, I can now provide a final response regarding the municipality ID mapping concern:

The municipality ID mapping is correctly implemented

The code is working as intended because:

  1. The municipalities array is populated from recycling partners that have isMunicipality flag set to true
  2. The companyId is used consistently as the value field for both municipalities and recycling partners
  3. The mapping between municipality and recycling partner is done through the companyId field, which serves as a common identifier
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if municipality IDs match company IDs in the codebase
rg -A 5 "companyId.*municipality" 

Length of output: 35


Script:

#!/bin/bash
# Let's check the schema/types and usages to understand the relationship
# First, let's find type definitions related to municipalities and recycling partners
ast-grep --pattern 'interface $_Municipality {
  $$$
}'

# Also check for any type with companyId
ast-grep --pattern 'interface $_ {
  companyId: $_
  $$$
}'

# And check how municipalities are used with recycling partners
rg -B 3 -A 3 "municipalities.*recyclingPartner" 

Length of output: 2088


Script:

#!/bin/bash
# Let's check the component's props and the municipalities type
ast-grep --pattern 'type $_Props = {
  $$$
  municipalities: $_
  $$$
}'

# Check how municipalities are structured
rg -B 2 -A 2 "municipalities.*value.*label"

# Look for recyclingPartner type definition
ast-grep --pattern 'type $_RecyclingPartner = {
  $$$
}'

Length of output: 179


Script:

#!/bin/bash
# Let's check the interface definitions and type declarations
ast-grep --pattern 'interface $_ {
  municipalities: $_
  $$$
}'

# Look for municipality option type definitions
rg -B 3 -A 3 "type.*Municipality"

# Check how the municipalities array is populated
rg -B 3 -A 3 "municipalities.*=" 

Length of output: 34477

apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (1)

119-119: Verify component integration

The replacement of Sidenav with NavigationLinks and addition of PageHeader needs verification for proper role-based access.

Also applies to: 139-139

✅ Verification successful

Let me check the NavigationLinks component implementation and its role-based access control to complete the verification.


Let me check the implementation of the role-based utility function and the user context to complete the verification.


NavigationLinks component properly handles role-based access

The NavigationLinks component correctly implements role-based access control:

  • It uses UserContext to access the user's role
  • Implements proper role checks using hasMunicipalityRole utility
  • Conditionally renders navigation items based on user roles
  • Maintains the same role-based access control as the previous Sidenav implementation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check NavigationLinks usage across the codebase
rg -A 5 "NavigationLinks.*activeSection"

Length of output: 3591


Script:

#!/bin/bash
# Check NavigationLinks implementation
ast-grep --pattern 'const NavigationLinks = $_'

# Check for any auth/role checks in the component
rg -A 5 "auth|role|permission" apps/skilavottord/web/components/NavigationLinks

Length of output: 6366


Script:

#!/bin/bash
# Check role utility implementation
ast-grep --pattern 'export const hasMunicipalityRole = $_'

# Check UserContext implementation
ast-grep --pattern 'export const UserContext = $_'

# Check if there are any other role-based checks
rg "user?.role" apps/skilavottord/web

Length of output: 639

apps/skilavottord/web/screens/CompanyInfo/CompanyInfo.tsx (1)

105-105: Verify PageHeader accessibility

The PageHeader component replaces direct Text components. Ensure it maintains proper heading hierarchy and accessibility.

✅ Verification successful

PageHeader component maintains proper heading hierarchy and accessibility

The PageHeader component in apps/skilavottord/web/components/PageHeader/PageHeader.tsx correctly implements heading hierarchy by using:

  • Text component with variant="h1" and as="h1" props
  • Proper semantic structure with GridRow/GridColumn for layout
  • Tooltip for additional information accessibility
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check PageHeader implementation for accessibility attributes
ast-grep --pattern 'export const PageHeader = $_ => {
  $$$
  return (
    $$$
    <h1 $_>$$$</h1>
    $$$
  )
}'

Length of output: 115


Script:

#!/bin/bash
# Let's try a broader search for PageHeader component
fd PageHeader --type f --exec cat {}

# Also search for any h1 tags in the codebase to understand heading hierarchy
ast-grep --pattern '<h1 $_>$$$</h1>'

# Search for PageHeader usage patterns
rg "PageHeader" -A 2

Length of output: 57260

apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx (3)

4-31: LGTM! Clean import organization.

The new imports for municipality support and UI components are well-structured and properly organized.


Line range hint 133-152: LGTM! Clean UI component integration.

The NavigationLinks and PageHeader components are well-integrated and improve the overall UI consistency.


80-84: Verify partnerId assignment for municipality users.

The partnerId assignment logic for municipality users should be verified to ensure it correctly handles all edge cases.

✅ Verification successful

Let me check the implementation of hasMunicipalityRole and related role checks to ensure the partnerId assignment is consistent.


Let me check for the implementation of hasMunicipalityRole and the Role enum specifically for the skilavottord application.


Let me check the complete Role enum definition and the usage of municipality role in the codebase.


The partnerId assignment for municipality users is correctly implemented.

The code is consistent with the rest of the codebase. The implementation shows:

  1. hasMunicipalityRole is properly defined in auth/utils.ts and checks for Role.municipality
  2. The Role enum in user.model.ts includes the municipality role
  3. The partnerId assignment pattern is used consistently across the codebase:
    • In vehicle resolver: partnerId: user.role === Role.municipality ? user.partnerId : null
    • In recycling company screens: if (hasMunicipalityRole(user?.role)) { partnerId = user?.partnerId }
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for other instances of partnerId assignment for municipalities
rg "partnerId.*municipality" -A 3

Length of output: 1966


Script:

#!/bin/bash
# Check implementation of hasMunicipalityRole and related role checks
ast-grep --pattern 'function hasMunicipalityRole($_) { $$$ }'

# Check Role enum definition
rg "enum.*Role" -A 10

# Check other usages of user?.role with municipality
rg "user\?\.role.*municipality" -A 2

Length of output: 66127


Script:

#!/bin/bash
# Search for Role enum in skilavottord
rg "enum.*Role" -A 5 apps/skilavottord/

# Search for hasMunicipalityRole implementation
ast-grep --pattern 'const hasMunicipalityRole = $_' apps/skilavottord/web/

# Check other role-related functions in the same context
rg "Role\." -A 2 apps/skilavottord/web/screens/RecyclingCompanies/

Length of output: 889


Script:

#!/bin/bash
# Get complete Role enum definition
rg -A 10 "export enum Role" apps/skilavottord/

# Check all usages of municipality role
rg "Role\.municipality" apps/skilavottord/

# Check implementation of hasMunicipalityRole and its imports
rg -A 3 "hasMunicipalityRole" apps/skilavottord/

Length of output: 12227

apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (2)

Line range hint 25-45: LGTM! Well-typed interface changes.

The interface updates properly accommodate the new municipality functionality with appropriate typing.


336-361: LGTM! Proper implementation of developer-only UI control.

The implementation correctly maintains the checkbox in the DOM while restricting UI manipulation to developers, as per the established pattern.

apps/skilavottord/ws/src/app/modules/recyclingRequest/recyclingRequest.service.ts (1)

Line range hint 257-267: LGTM! Proper partner validation implementation.

The partner validation logic is well-implemented with clear error messages and proper logging.

apps/skilavottord/web/i18n/locales/en.json (4)

368-372: LGTM: Navigation and titles are properly translated.

The translations for municipality-related navigation items and titles are correctly implemented in English.


Line range hint 376-396: LGTM: Recycling companies section translations are accurate.

The translations for recycling companies section, including the new municipality-related buttons and status indicators, are properly implemented in English.


Line range hint 647-667: Add missing translations in municipality section.

The municipality section is missing essential translations such as table headers, status indicators, and action buttons.

Add the following translations:

  "municipalities": {
    "title": "Municipalities",
+   "info": "Information about registered municipalities.",
+   "tableHeaders": {
+     "name": "Name",
+     "address": "Address",
+     "postnumber": "Postal Code",
+     "email": "Email",
+     "status": "Status"
+   },
+   "status": {
+     "active": "Active",
+     "inactive": "Inactive"
+   },
+   "buttons": {
+     "add": "Add Municipality",
+     "edit": "Edit",
+     "delete": "Delete"
+   },
    "municipality": {
      "view": {
        "title": "Municipality",
        "breadcrumb": "View",
        "updated": "Updated",
        "deleted": "Deleted"
      },
      "add": {
        "title": "Add Municipality",
        "breadcrumb": "Add",
        "added": "Added"
      }
    }
  }

653-653: ⚠️ Potential issue

Fix non-English content in English locale file.

These strings are in Icelandic instead of English:

  • Line 653: "Þú getur annaðhvort uppfært eða eytt móttökuaðila..."
  • Line 657-660: "Þegar nýju sveitarfélagi er bætt við..."

Apply this diff to fix the translations:

-        "info": "Þú getur annaðhvort uppfært eða eytt móttökuaðila. Vinsamlegast staðfestið að upplýsingar fyrirtækis séu rétt slegnar inn.",
+        "info": "You can either update or delete a municipality. Please verify that the municipality information is correct.",
-        "info": "Þegar nýju sveitarfélagi er bætt við, verður hann aðgengilegur í aðgangsstýringu. Vinsamlegast staðfestið að upplýsingar fyrirtækis séu rétt slegnar inn.",
+        "info": "When a new municipality is added, it will be available in access control. Please verify that the municipality information is correct.",

Also applies to: 657-660

apps/skilavottord/web/i18n/locales/is.json (3)

368-372: LGTM: Navigation and titles are properly translated.

The translations for municipality-related navigation items and titles are correctly implemented in Icelandic.


486-489: ⚠️ Potential issue

Add validation rules for municipality field.

The municipality field in the recycling company form lacks validation rules, unlike other required fields.

Apply this diff to add validation rules:

  "municipality": {
    "label": "Sveitarfélag",
-   "placeholder": "Sveitarfélag"
+   "placeholder": "Sveitarfélag",
+   "rules": {
+     "required": "Skylda er að fylla út sveitarfélag"
+   }
  }

651-667: ⚠️ Potential issue

Complete the municipality management section.

The municipality section is missing several essential elements:

  1. Table headers for the municipality list view
  2. Status indicators
  3. Action button translations
  4. Form input definitions

Add the missing translations:

  "municipalities": {
    "title": "Sveitarfélög",
+   "info": "Upplýsingar um skráð sveitarfélög.",
    "empty": "Ekkert sveitarfélag fannst",
+   "tableHeaders": {
+     "name": "Nafn",
+     "address": "Heimilisfang",
+     "postnumber": "Póstnúmer",
+     "email": "Netfang",
+     "status": "Staða"
+   },
+   "status": {
+     "active": "Virkt",
+     "inactive": "Óvirkt"
+   },
+   "buttons": {
+     "add": "Bæta við sveitarfélagi",
+     "edit": "Breyta",
+     "delete": "Eyða"
+   },
    "municipality": {
      "view": {
        "title": "Sveitarfélag",
        "breadcrumb": "Skoða",
-       "info": "Þú getur annaðhvort uppfært eða eytt móttökuaðila. Vinsamlegast staðfestið að upplýsingar fyrirtækis séu rétt slegnar inn.",
+       "info": "Þú getur annaðhvort uppfært eða eytt sveitarfélagi. Vinsamlegast staðfestið að upplýsingar sveitarfélags séu rétt slegnar inn.",
        "updated": "Uppfært",
        "deleted": "Eytt"
      },
      "add": {
        "title": "Bæta við sveitarfélagi",
        "breadcrumb": "Bæta við",
        "info": "Þegar nýju sveitarfélagi er bætt við, verður það aðgengilegt í aðgangsstýringu. Vinsamlegast staðfestið að upplýsingar sveitarfélags séu rétt slegnar inn.",
        "added": "Bætt við"
-     }
+     },
+     "form": {
+       "inputs": {
+         "name": {
+           "label": "Nafn",
+           "placeholder": "Nafn sveitarfélags",
+           "rules": {
+             "required": "Skylda er að fylla út nafn"
+           }
+         },
+         "email": {
+           "label": "Netfang",
+           "placeholder": "Netfang",
+           "rules": {
+             "required": "Skylda er að fylla út netfang",
+             "validate": "Netfang er ekki á réttu formi"
+           }
+         }
+       }
+     }
    }
  }

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

🧹 Nitpick comments (4)
apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (3)

55-66: Add error handling for the data transformation

The municipality data transformation could be more robust by handling potential undefined values and empty arrays.

Consider updating the transformation:

- const municipalities = data?.skilavottordRecyclingPartners.map(
+ const municipalities = data?.skilavottordRecyclingPartners?.map(
    (municipality) => ({
      label: municipality.companyName,
      value: municipality.companyId,
    }),
-  )
+  ) ?? []

281-315: Enhance accessibility for the municipality select component

While the implementation is functionally correct, consider adding ARIA attributes for better accessibility.

Add these attributes to the Select component:

 <Select
   name={name}
   label={t.recyclingCompany.form.inputs.municipality.label}
   placeholder={t.recyclingCompany.form.inputs.municipality.placeholder}
+  aria-label={t.recyclingCompany.form.inputs.municipality.label}
+  aria-required="true"
   size="md"
   value={municipalities?.find((option) => option.value === value)}
   hasError={!!errors?.municipality?.message}
   errorMessage={errors?.municipality?.message}
   backgroundColor="blue"
   options={municipalities}
   onChange={onChange}
   isCreatable
   isDisabled={hasMunicipalityRole(user?.role)}
 />

340-365: Consider using styled components instead of inline styles

While the implementation correctly maintains the checkbox in the DOM as required, the visibility control could be improved.

Consider using styled components or CSS classes:

- <div
-   style={{
-     display: user?.role && hasDeveloperRole(user.role) ? 'block' : 'none',
-   }}
- >
+ <Box
+   display={user?.role && hasDeveloperRole(user.role) ? 'block' : 'none'}
+ >
apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (1)

81-84: Consider preserving form state on modal close

The current implementation clears the form whenever the modal is reopened. Consider if this is the desired behavior or if form state should be preserved in certain scenarios.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2ce8ec and 7e4ddbb.

📒 Files selected for processing (4)
  • apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (5 hunks)
  • apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (5 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (5 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
📓 Learnings (1)
apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (1)
Learnt from: birkirkristmunds
PR: island-is/island.is#17109
File: apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx:336-360
Timestamp: 2024-12-10T15:10:49.998Z
Learning: In the `RecyclingCompanyForm` component (`apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx`), the `isMunicipality` checkbox must remain in the DOM for all users since its value is stored in the database. However, only users with the developer role can manipulate it through the UI. This ensures that the checkbox value is maintained correctly while restricting interaction to authorized users.
🔇 Additional comments (8)
apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx (2)

Line range hint 1-48: LGTM! Well-structured imports and interface updates

The new imports and interface changes are well-organized and properly typed. The optional isMunicipalityPage property with its default value follows TypeScript best practices.


379-380: LGTM! Improved button semantics

The button changes from 'arrowForward' to 'save' icon and updated text provide better clarity about the action being performed.

apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (3)

22-27: Method name should match GraphQL query name

The method name getAllRecyclingPartners doesn't match the GraphQL query name skilavottordAllRecyclingPartners. This can lead to confusion during maintenance.

 @Query(() => [RecyclingPartnerModel], {
   name: 'skilavottordAllRecyclingPartners',
 })
-async getAllRecyclingPartners(): Promise<RecyclingPartnerModel[]> {
+async skilavottordAllRecyclingPartners(): Promise<RecyclingPartnerModel[]> {
   return this.recyclingPartnerService.findAll()
 }

32-45: Add input validation and error handling

The method should validate inputs and include proper error handling.

 async getRecyclingPartners(
   @Args('isMunicipalityPage', { type: () => Boolean, nullable: true })
   isMunicipalityPage: boolean,
   @Args('municipalityId', { type: () => String, nullable: true })
   municipalityId: string | null,
 ): Promise<RecyclingPartnerModel[]> {
+  if (municipalityId && !municipalityId.trim()) {
+    throw new BadRequestException('municipalityId cannot be empty')
+  }
+  try {
     return this.recyclingPartnerService.findRecyclingPartners(
       isMunicipalityPage,
       municipalityId,
     )
+  } catch (error) {
+    throw new InternalServerErrorException(
+      `Failed to fetch recycling partners: ${error.message}`,
+    )
+  }
 }

20-20: Verify the municipality role permissions across the application

The addition of Role.municipality to multiple endpoints needs verification to ensure proper access control implementation.

Also applies to: 30-30, 55-55, 66-66, 87-87

✅ Verification successful

Let me gather more information about the authorization implementation to ensure proper role handling.


Let me check the authorization guard implementation to verify how the municipality role is handled.


Role.municipality authorization is properly implemented

The municipality role has been consistently implemented across the application:

  • Correctly defined in the Role enum (apps/skilavottord/ws/src/app/modules/auth/user.model.ts)
  • Properly used in @authorize decorators across multiple resolvers
  • Specific handling in the recyclingPartner service for municipality-specific queries
  • Access control is consistently applied in related modules (vehicle, recyclingPartner, accessControl)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent role implementation and guard usage

# Check for Role.municipality usage
rg -A 2 "Role\.municipality" 

# Check for proper guard implementation
ast-grep --pattern 'class $_ implements CanActivate {
  $$$
  Role.municipality
  $$$
}'

Length of output: 5947


Script:

#!/bin/bash
# Check for the authorization guard implementation
ast-grep --pattern 'class AuthorizeGuard implements CanActivate {
  $$$
}'

# Check for role enum definition
rg -A 5 "export enum Role"

# Check for any custom municipality-specific guards
rg -l "municipality.*guard"

Length of output: 30419


Script:

#!/bin/bash
# Check for the authorization guard implementation
rg -A 10 "class.*Authorize.*Guard" 

# Check for municipality-specific authorization logic
rg -A 5 "canActivate.*municipality"

# Check for the Authorize decorator implementation
ast-grep --pattern '@Authorize({
  $$$
})'

Length of output: 5084

apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (2)

91-94: Duplicate: Handle potential undefined role in partnerIdRequired

When using watch('role')?.value, ensure that watch('role') doesn't return undefined before accessing .value. Consider setting a default value or adding additional null checks.


57-60: Verify municipality mapping logic

The code assumes that municipality's companyId matches the recyclingPartner's companyId. This might lead to incorrect municipality assignments if the IDs don't match.

✅ Verification successful

Let me gather more information about the municipality and recycling partner data structures to verify this relationship.


Let me check one more thing to understand how the recycling partners are structured and their relationship with municipalities.


Based on the gathered evidence, I can now provide the final response:

The municipality mapping logic is correct and safe

The code correctly maps recycling partners to municipalities. The evidence shows that:

  1. The skilavottordRecyclingPartners query includes municipality relationships and is used consistently across the codebase
  2. The mapping between companyId and municipalities is handled properly in the RecyclingCompanyForm component, establishing the correct relationship
  3. The same pattern is used in both AccessControl components, ensuring consistency
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if municipality and recycling partner IDs match the assumed pattern
ast-grep --pattern 'companyId: string' # Search for company ID type definitions
rg -A 2 'municipality.*companyId|recyclingPartner.*companyId' # Search for ID usage patterns

Length of output: 2324


Script:

#!/bin/bash
# Check municipality and recycling partner type definitions and data transformations
ast-grep --pattern 'interface Municipality {
  $$$
}'

ast-grep --pattern 'interface RecyclingPartner {
  $$$
}'

# Check how municipalities are mapped in the codebase
rg -A 3 'municipalities.*map' 

Length of output: 4958


Script:

#!/bin/bash
# Check recycling partner data structure and municipality relationships
ast-grep --pattern 'type RecyclingPartnerDTO = {
  $$$
}'

# Look for municipality-recycling partner relationship definitions
rg -A 3 'skilavottordRecyclingPartners'

Length of output: 2896

apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (1)

50-62: ⚠️ Potential issue

Improve error handling in getPartnerId function

The function needs additional safeguards:

  1. Missing null check for user?.partnerId
  2. No error handling for invalid role combinations
 const getPartnerId = (
-  municipalityId: string,
-  partnerId: string,
+  municipalityId: string | null | undefined,
+  partnerId: string | null | undefined,
   role: Role,
 ) => {
+  if (!user) {
+    throw new Error('User context is required')
+  }
+
   // If the user has municipality role, then he can only create a new access under the same municipality
   if (hasMunicipalityRole(user?.role) && hasMunicipalityRole(role)) {
-    return user.partnerId
+    return user.partnerId ?? null
   }

   // If selected role is municipality, use municipalityId, else use partnerId
-  return hasMunicipalityRole(role) ? municipalityId : partnerId || null
+  return hasMunicipalityRole(role) ? municipalityId ?? null : partnerId ?? null
 }

Likely invalid or redundant comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (1)

97-100: ⚠️ Potential issue

Add null check for role value

The role value check should handle undefined cases.

       partnerIdRequired={
-        watch('role')?.value === Role.recyclingCompanyAdmin ||
-        watch('role')?.value === Role.recyclingCompany
+        (watch('role')?.value === Role.recyclingCompanyAdmin ||
+         watch('role')?.value === Role.recyclingCompany) ?? false
       }
🧹 Nitpick comments (15)
apps/skilavottord/web/utils/accessUtils.ts (3)

4-9: Add JSDoc documentation for better type information and usage guidance.

The function signature is well-typed, but adding JSDoc would improve developer experience by documenting parameter requirements and return values.

+/**
+ * Determines the appropriate partner ID based on user role and provided parameters
+ * @param user - The current user object
+ * @param municipalityId - The ID of the municipality if applicable
+ * @param partnerId - The partner ID if applicable
+ * @param role - The role being evaluated
+ * @returns The determined partner ID or null
+ */
 export const getPartnerId = (
   user: SkilavottordUser | undefined,
   municipalityId: string | null,
   partnerId: string | null,
   role: Role,
 ) => {

10-13: Consider making the role check more explicit.

The conditional logic is correct, but the comment could be more precise about the business rule being enforced.

-  // If the user has municipality role, then he can only create a new access under the same municipality
+  // Municipality users can only create access within their assigned municipality
   if (hasMunicipalityRole(user?.role) && hasMunicipalityRole(role)) {
     return user.partnerId
   }

15-17: Consider making null coalescing more explicit with early returns.

The ternary with null coalescing could be more readable with explicit conditions.

-  return hasMunicipalityRole(role) ? municipalityId ?? null : partnerId ?? null
+  if (hasMunicipalityRole(role)) {
+    return municipalityId ?? null
+  }
+  return partnerId ?? null
apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (1)

85-89: Simplify the partnerIdRequired logic

The current implementation can be made more concise and readable.

-      partnerIdRequired={
-        (watch('role')?.value === Role.recyclingCompanyAdmin ||
-          watch('role')?.value === Role.recyclingCompany) ??
-        false
-      }
+      partnerIdRequired={[Role.recyclingCompanyAdmin, Role.recyclingCompany].includes(watch('role')?.value ?? '')}
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (1)

81-96: Enhance JSDoc documentation

While the implementation is good, the JSDoc comments could be more descriptive.

   /**
    * Get the id of the municipality or recyclingpartner that is paying for the recycling request
-   * @param companyId
-   * @returns
+   * @param {string} companyId - The unique identifier of the company
+   * @returns {Promise<string>} The ID of the paying partner (municipality or recycling partner)
+   * @throws {Error} When no partner is found for the given company ID
    */
apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (1)

61-64: Simplify municipality ID lookup

The find logic can be made more concise.

-      municipalityId: municipalities.find(
-        (option) =>
-          option.value === currentPartner?.recyclingPartner?.companyId,
-      ),
+      municipalityId: municipalities.find(option => option.value === currentPartner?.recyclingPartner?.companyId),
apps/skilavottord/web/i18n/locales/en.json (2)

395-396: Consider more descriptive button labels.

The "view" label could be more descriptive. Consider using "View details" or "View company" to provide more context to users.


647-662: Enhance descriptive text for municipality management.

Consider adding more context to the following strings:

  • Add a description of what municipalities are used for in the system
  • Clarify the impact of adding/updating municipalities
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (1)

37-56: Add parameter documentation and validation

While the implementation looks good, consider these improvements:

  1. Add JSDoc comments to document the parameters and their relationship
  2. Add validation for the case when municipalityId is provided
 @Query(() => [RecyclingPartnerModel], {
   name: 'skilavottordRecyclingPartners',
 })
+/**
+ * Retrieves recycling partners based on municipality page status and ID
+ * @param isMunicipalityPage - Whether to fetch municipality-specific partners
+ * @param municipalityId - Optional municipality ID, can be null for recyclingFund role
+ */
 async skilavottordRecyclingPartners(
   @Args('isMunicipalityPage', { type: () => Boolean, nullable: true })
   isMunicipalityPage: boolean,
   @Args('municipalityId', { type: () => String, nullable: true })
   municipalityId: string | null,
 ): Promise<RecyclingPartnerModel[]> {
   try {
+    if (municipalityId && !isMunicipalityPage) {
+      throw new BadRequestException(
+        'municipalityId can only be provided when isMunicipalityPage is true',
+      )
+    }
     return this.recyclingPartnerService.findRecyclingPartners(
       isMunicipalityPage,
       municipalityId,
     )
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (2)

15-19: Consider grouping related auth imports

The auth-related imports (hasPermission, hasMunicipalityRole) could be combined into a single import statement for better organization.

-import {
-  hasPermission,
-  hasMunicipalityRole,
-} from '@island.is/skilavottord-web/auth/utils'
+import { hasPermission, hasMunicipalityRole } from '@island.is/skilavottord-web/auth/utils'

161-161: Consider alternative to delete operator

Using the delete operator can impact performance. Consider using undefined assignment instead.

-delete input.__typename
+input.__typename = undefined
🧰 Tools
🪛 Biome (1.9.4)

[error] 161-161: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts (3)

26-27: Add explicit type annotation for better type safety

The partnerIds variable should have an explicit type annotation to prevent potential type-related issues.

-    let partnerIds = []
+    let partnerIds: string[] | null = []

28-48: Improve comment clarity for municipality partner handling

The implementation looks good with proper error handling and query optimization. However, the comments could be more descriptive.

-    // Get all sub recycling partners of the municipality
-    // else get all
+    // If partnerId is provided, fetch all sub-recycling partners associated with the municipality
+    // Otherwise, return null to fetch all partners

61-64: Fix indentation for better readability

The object spread operator's indentation is inconsistent with the surrounding code.

             ...(partnerIds
               ? {
-                  recyclingPartnerId: partnerIds,
+                recyclingPartnerId: partnerIds,
                }
               : {}),
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (1)

122-130: Refactor duplicated success handling

The success handling contains duplicated toast message code.

Apply this diff to reduce code duplication:

if (!errors) {
-  if (isMunicipalityPage) {
-    router.push(routes.municipalities.baseRoute).then(() => {
-      toast.success(t.recyclingCompany.add.added)
-    })
-  } else {
-    router.push(routes.recyclingCompanies.baseRoute).then(() => {
-      toast.success(t.recyclingCompany.add.added)
-    })
-  }
+  const route = isMunicipalityPage
+    ? routes.municipalities.baseRoute
+    : routes.recyclingCompanies.baseRoute
+  router.push(route).then(() => {
+    toast.success(t.recyclingCompany.add.added)
+  })
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e4ddbb and 4336424.

📒 Files selected for processing (21)
  • apps/skilavottord/web/i18n/locales/en.json (5 hunks)
  • apps/skilavottord/web/i18n/locales/is.json (6 hunks)
  • apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (12 hunks)
  • apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (5 hunks)
  • apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx (4 hunks)
  • apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (6 hunks)
  • apps/skilavottord/web/screens/Overview/Overview.tsx (1 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (5 hunks)
  • apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (7 hunks)
  • apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (4 hunks)
  • apps/skilavottord/web/utils/accessUtils.ts (1 hunks)
  • apps/skilavottord/web/utils/index.ts (1 hunks)
  • apps/skilavottord/web/utils/roleUtils.ts (1 hunks)
  • apps/skilavottord/ws/migrations/202412013210715-addcolumns-recycling-partners-municipality.js (1 hunks)
  • apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts (2 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts (2 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (4 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (3 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingRequest/recyclingRequest.service.ts (4 hunks)
  • apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts (1 hunks)
  • apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/skilavottord/web/screens/Overview/Overview.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/skilavottord/ws/migrations/202412013210715-addcolumns-recycling-partners-municipality.js
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts
  • apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx
  • apps/skilavottord/ws/src/app/modules/recyclingRequest/recyclingRequest.service.ts
  • apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts
👮 Files not reviewed due to content moderation or server errors (3)
  • apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts
  • apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx
  • apps/skilavottord/web/screens/AccessControl/AccessControl.tsx
🧰 Additional context used
📓 Path-based instructions (15)
apps/skilavottord/web/utils/index.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/utils/accessUtils.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/utils/roleUtils.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/AccessControl.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/en.json (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/AccessControl/components/AccessControlUpdate/AccessControlUpdate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/is.json (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
📓 Learnings (2)
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (1)
Learnt from: birkirkristmunds
PR: island-is/island.is#17109
File: apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts:32-45
Timestamp: 2024-12-16T12:25:52.236Z
Learning: In `apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts`, the `municipalityId` parameter in `getRecyclingPartners` can be `null` for users with the `recyclingFund` role.
apps/skilavottord/web/i18n/locales/is.json (1)
Learnt from: birkirkristmunds
PR: island-is/island.is#17109
File: apps/skilavottord/web/i18n/locales/is.json:0-0
Timestamp: 2024-12-16T12:38:27.802Z
Learning: In the Skilavottord web application, the form for recycling partners is reused for municipalities. Therefore, specific translations for municipalities' form inputs are not needed in `apps/skilavottord/web/i18n/locales/is.json`.
🪛 Biome (1.9.4)
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx

[error] 161-161: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

🔇 Additional comments (21)
apps/skilavottord/web/utils/index.ts (1)

5-5: LGTM! Export statement follows established pattern.

The new export follows the same pattern as other utility exports and maintains consistency in the barrel file structure.

apps/skilavottord/web/utils/roleUtils.ts (1)

18-19: Verify translation completeness across the application.

The municipality role translations are properly added. However, we should verify that these translations are consistently used across all relevant components.

✅ Verification successful

Translations for municipality role are consistent across the application

The verification shows that:

  • All necessary translations for "Municipality"/"Sveitarfélag" are properly defined in both English (en.json) and Icelandic (is.json) locale files
  • The Role.municipality usage is consistent across components, particularly in:
    • AccessControl components for role checks
    • AccessControlModal for role-specific logic
    • roleUtils.ts for translation handling
    • auth/utils.ts for role verification
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistency in municipality translations across the application

# Search for municipality-related translations in locale files
echo "Checking locale files for municipality translations..."
rg -i "municipality|sveitarfélag" apps/skilavottord/web/i18n/locales/

# Search for municipality role usage in components
echo "Checking components for municipality role usage..."
rg "Role\.municipality" apps/skilavottord/web/

Length of output: 4368

apps/skilavottord/web/screens/AccessControl/components/AccessControlCreate/AccessControlCreate.tsx (1)

68-71: LGTM! Good form reset implementation

The useEffect hook correctly resets the form when the modal is re-opened, with proper dependency array.

apps/skilavottord/web/i18n/locales/en.json (2)

368-372: LGTM: Navigation items for municipality management added correctly.

The new navigation items for municipality management are properly structured and consistent with the application's navigation pattern.


641-645: LGTM: Municipality routes added with consistent pattern.

The new routes for municipality management follow the established pattern used for other sections.

apps/skilavottord/web/i18n/locales/is.json (4)

368-372: LGTM: Municipality navigation items properly translated.

The Icelandic translations for municipality navigation items are accurate and consistent with the English version.


587-592: LGTM: Municipality field properly added to access control.

The municipality field in the access control section is properly structured with consistent validation rules.


646-650: LGTM: Municipality routes properly added.

The routes for municipality management are properly structured and consistent with other sections.


659-659: ⚠️ Potential issue

Fix incorrect entity reference in municipality view.

The info text incorrectly refers to "móttökuaðila" (recycling company) instead of "sveitarfélag" (municipality).

Apply this fix:

-"info": "Þú getur annaðhvort uppfært eða eytt móttökuaðila. Vinsamlegast staðfestið að upplýsingar fyrirtækis séu rétt slegnar inn.",
+"info": "Þú getur annaðhvort uppfært eða eytt sveitarfélagi. Vinsamlegast staðfestið að upplýsingar sveitarfélags séu rétt slegnar inn.",

Likely invalid or redundant comment.

apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts (3)

1-6: LGTM: Appropriate error handling imports

The added imports from @nestjs/common provide the necessary error types for proper error handling throughout the resolver.


27-31: Maintain consistent method naming convention

The method name doesn't match the GraphQL query name pattern. The query uses the 'skilavottord' prefix while the method name doesn't.

 @Query(() => [RecyclingPartnerModel], {
   name: 'skilavottordAllRecyclingPartners',
 })
-async getAllRecyclingPartners(): Promise<RecyclingPartnerModel[]> {
+async skilavottordAllRecyclingPartners(): Promise<RecyclingPartnerModel[]> {

25-25: Verify role-based access control implementation

The addition of Role.municipality to authorized roles is consistent across all methods. However, we should verify the implementation of this role in the auth module and any UI components that use these endpoints.

Also applies to: 66-66, 77-77, 98-98

✅ Verification successful

Role.municipality implementation is properly integrated

The verification shows that the Role.municipality is:

  • Correctly defined in the Role enum
  • Consistently applied across all methods in recyclingPartner.resolver.ts
  • Properly integrated in other resolvers and services with appropriate access controls
  • Used in logical branching for specific municipality-related functionality

The implementation is complete and consistent with the codebase's role-based access control system.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify role implementation and usage

# Check role definition
echo "Checking Role enum definition..."
rg -A 5 "export enum Role" apps/skilavottord/ws/src/app

# Check auth guard implementation
echo "Checking auth guard implementation..."
rg -A 10 "canActivate.*Role.municipality" apps/skilavottord/ws/src/app

# Check UI components using these endpoints
echo "Checking UI components..."
rg -A 5 "skilavottordRecyclingPartners|skilavottordAllRecyclingPartners" apps/skilavottord/web/src

Length of output: 1050


Script:

#!/bin/bash
# Let's verify the role implementation more thoroughly

# Check if municipality role is defined in the Role enum
echo "Checking Role enum for municipality..."
rg -p "municipality.*=.*'municipality'" apps/skilavottord/ws/src/app

# Check all usages of Role.municipality in the codebase
echo "Checking Role.municipality usage..."
rg -p "Role\.municipality" apps/skilavottord/ws/src/app

# Check auth guards and decorators
echo "Checking auth guards and decorators..."
rg -p "@UseGuards|@Roles" apps/skilavottord/ws/src/app/modules

# Check recyclingPartner resolver for role consistency
echo "Checking recyclingPartner resolver..."
rg -p "roles.*:.*\[.*\]" apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts

Length of output: 2450

apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx (3)

152-157: LGTM! Clean implementation of navigation logic

The extracted navigation function improves code maintainability by removing duplication, as suggested in previous reviews.


163-167: LGTM! Robust type handling for municipalityId

The implementation follows the suggested approach from previous reviews for safer type handling.


87-91: Verify role-based access control implementation

The municipality role check is crucial for security. Let's verify that this implementation correctly restricts access.

✅ Verification successful

Let me analyze the role-based access control implementation further by checking the actual implementation of hasMunicipalityRole.


Based on the analysis of the code, I can now provide a final response:

Role-based access control implementation is correctly implemented

The implementation is secure and properly restricts access based on municipality roles:

  • The hasMunicipalityRole function is a simple, clear comparison that checks if the user's role exactly matches Role.municipality
  • The Role enum is properly defined with distinct values for different roles including 'municipality'
  • The role check is used consistently across the codebase to restrict access to municipality-specific functionality
  • The partnerId assignment is properly guarded by the role check, ensuring only municipality users can access their specific data
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other instances of hasMunicipalityRole to ensure consistent usage
rg "hasMunicipalityRole" --type ts

# Search for role-based access patterns
ast-grep --pattern 'if ($CONDITION) { $PARTNER_ID = $USER.$FIELD }'

Length of output: 44435


Script:

#!/bin/bash
# Check the implementation of hasMunicipalityRole
ast-grep --pattern 'export const hasMunicipalityRole = $_'

# Check the Role enum definition
rg "enum Role" -A 10 --type ts

Length of output: 65785

apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts (1)

33-36: Verify database index for optimal query performance

The query filtering on municipalityId could benefit from an index to improve performance, especially with large datasets.

✅ Verification successful

Database query performance is adequately optimized

While there isn't a direct index on municipality_id, the current query pattern doesn't require one for optimal performance because:

  1. The table has an index on is_municipality which helps filter recycling partners efficiently
  2. The municipality_id column was recently added (December 2024) and is used in a simple equality filter
  3. The result set is limited to only the companyId attribute, reducing data transfer

The current implementation is sufficient for the expected data volume and query pattern.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if an index exists on the municipalityId column

# Search for index definitions in migration files
fd -e ts -e js . | xargs rg -A 5 "CREATE.*INDEX.*municipalityId"

# Search for Sequelize index definitions
ast-grep --pattern 'index: {
  $$$
  fields: [$$$"municipalityId"$$$]
  $$$
}'

Length of output: 147


Script:

#!/bin/bash
# Let's try a broader search to understand the database schema and existing indexes

# Search for the RecyclingPartner model definition
ast-grep --pattern 'class RecyclingPartnerModel extends Model {
  $$$
}'

# Search for any migrations related to recycling partners
fd -e ts -e js . | xargs rg -B 2 -A 5 "createTable.*recycling.*partner"

# Look for any index definitions in a case-insensitive way
fd -e ts -e js . | xargs rg -i "index.*municipality"

Length of output: 11049


Script:

#!/bin/bash
# Let's check for any migrations related to municipalityId specifically
fd -e ts -e js . | xargs rg -B 2 -A 5 "municipality_id"

# Look for the specific migration file that added the municipality_id column
fd "202412013210715-addcolumns-recycling-partners-municipality.js" . | xargs cat

Length of output: 20304

apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx (5)

19-20: LGTM: New components properly imported

The NavigationLinks and PageHeader components are correctly imported from their respective paths.


58-73: LGTM: Clean separation of municipality logic

The code clearly differentiates between municipality and regular recycling company contexts, with proper variable assignments based on the route.


94-95: LGTM: Proper refetch query configuration

The refetch query is correctly configured with the necessary variables for municipality filtering.


143-143: LGTM: Clean component structure and proper prop handling

The component follows NextJS best practices with:

  • Proper layout structure using PartnerPageLayout
  • Clean implementation of PageHeader
  • Correct prop passing to RecyclingCompanyForm

Also applies to: 167-167, 175-175


39-40: Verify GraphQL schema compatibility

The mutation has been updated to include municipality-related fields. Ensure these fields are properly defined in the GraphQL schema.

✅ Verification successful

GraphQL schema compatibility verified

The fields isMunicipality and municipalityId are properly defined in the GraphQL schema through the RecyclingPartnerModel class using @Field decorators. The model shows:

  • isMunicipality is defined as a non-nullable Boolean field
  • municipalityId is defined as a nullable String field

Both fields are properly mapped to the database schema and exposed through GraphQL.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the new fields are defined in the GraphQL schema
ast-grep --pattern 'type RecyclingPartner {
  $$$
  isMunicipality: Boolean
  municipalityId: String
  $$$
}'

Length of output: 111


Script:

#!/bin/bash
# Let's search for GraphQL schema files and check their content
fd -e graphql -x cat {}

# Also search for type definitions in TypeScript files as they might be using code-first approach
ast-grep --pattern 'type RecyclingPartner'

Length of output: 81450


Script:

#!/bin/bash
# Let's search for RecyclingPartner type definition in TypeScript files
ast-grep --pattern 'interface RecyclingPartner {
  $$$
}'

# Also search for any GraphQL type definitions in .graphql files
fd -e graphql -e ts -x grep -l "RecyclingPartner" {}

# Let's also check for any mutation types that might use these fields
ast-grep --pattern 'mutation $_ {
  $$$
  RecyclingPartner {
    $$$
    isMunicipality
    municipalityId
    $$$
  }
  $$$
}'

Length of output: 2315


Script:

#!/bin/bash
# Let's check the recyclingPartner model and resolver for these fields
cat apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.model.ts
cat apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts

Length of output: 5681

@birkirkristmunds birkirkristmunds added automerge Merge this PR as soon as all checks pass deploy-feature Deploys features to dev labels Dec 16, 2024
Copy link
Contributor

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 (3)
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (3)

33-33: Update comment to match parameter names

The comment references Role.municipality but the parameter is named isMunicipalityPage. Update the comment to match the actual parameter names for better clarity.

-      // If Role.municipality, return all recycling partners that are not municipalities
+      // If municipalityId is provided, return all recycling partners that are not municipalities

28-56: Add input validation and improve error handling

While the implementation is generally good, consider adding input validation and more specific error handling.

   async findRecyclingPartners(
     isMunicipalityPage: boolean,
     municipalityId: string | null | undefined,
   ): Promise<RecyclingPartnerModel[]> {
     try {
+      // Validate municipalityId format if provided
+      if (municipalityId && !/^[A-Za-z0-9-]+$/.test(municipalityId)) {
+        throw new Error('Invalid municipality ID format');
+      }
+
       if (municipalityId) {
         return await this.recyclingPartnerModel.findAll({
           where: {
@@ -53,6 +58,8 @@
         },
       })
     } catch (error) {
+      if (error.name === 'SequelizeConnectionError')
+        throw new Error('Database connection error');
       throw new Error(`Failed to fetch recycling partners: ${error.message}`)
     }
   }

85-100: Enhance type safety with type narrowing

The implementation is good, but we can improve type safety.

   async getPayingPartnerId(companyId: string): Promise<string> {
+    if (!companyId?.trim()) {
+      throw new Error('Company ID is required');
+    }
+
     const partner = await this.recyclingPartnerModel.findOne({
       where: { companyId },
     })

     if (!partner) {
       throw new Error(`Partner not found for company ID: ${companyId}`)
     }

+    // Ensure both values are strings before using nullish coalescing
+    const municipalityId = partner.municipalityId?.toString();
+    const partnerCompanyId = partner.companyId?.toString();
+
+    if (!municipalityId && !partnerCompanyId) {
+      throw new Error('Invalid partner data: missing both municipalityId and companyId');
+    }
+
-    return partner.municipalityId ?? partner.companyId
+    return municipalityId ?? partnerCompanyId;
   }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5985196 and 3eb50de.

📒 Files selected for processing (4)
  • apps/skilavottord/README.md (2 hunks)
  • apps/skilavottord/web/i18n/locales/is.json (6 hunks)
  • apps/skilavottord/web/i18n/locales/locales.spec.ts (2 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (3 hunks)
✅ Files skipped from review due to trivial changes (2)
  • apps/skilavottord/web/i18n/locales/locales.spec.ts
  • apps/skilavottord/README.md
🧰 Additional context used
📓 Path-based instructions (2)
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/is.json (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
📓 Learnings (1)
apps/skilavottord/web/i18n/locales/is.json (1)
Learnt from: birkirkristmunds
PR: island-is/island.is#17109
File: apps/skilavottord/web/i18n/locales/is.json:0-0
Timestamp: 2024-12-16T12:38:27.802Z
Learning: In the Skilavottord web application, the form for recycling partners is reused for municipalities. Therefore, specific translations for municipalities' form inputs are not needed in `apps/skilavottord/web/i18n/locales/is.json`.
🔇 Additional comments (5)
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts (1)

9-9: LGTM!

The Sequelize Op import is correctly placed and necessary for the logical operations in the new methods.

apps/skilavottord/web/i18n/locales/is.json (4)

368-372: LGTM! Navigation translations are well-structured.

The new municipality-related navigation items are properly integrated into the existing structure.


587-592: LGTM! Access control translations are complete and consistent.

The municipality field in the access control modal follows the established pattern for validation rules and translations.


646-650: LGTM! Route definitions are well-structured.

The municipality routes follow the established pattern and include all necessary paths.


486-489: ⚠️ Potential issue

Fix validation message format inconsistency.

The validation message format for the municipality field is inconsistent with other fields.

Apply this fix:

  "municipality": {
    "label": "Sveitarfélag",
    "placeholder": "Sveitarfélag",
-   "required": "Skylda er að fylla út sveitarfélag"
+   "rules": {
+     "required": "Skylda er að fylla út sveitarfélag"
+   }
  }

Likely invalid or redundant comment.

apps/skilavottord/web/i18n/locales/is.json 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

♻️ Duplicate comments (1)
apps/skilavottord/web/i18n/locales/is.json (1)

486-489: ⚠️ Potential issue

Fix validation message format inconsistency.

The validation message format for the municipality field is inconsistent with other fields.

  "municipality": {
    "label": "Sveitarfélag",
    "placeholder": "Sveitarfélag",
-   "required": "Skylda er að fylla út sveitarfélag"
+   "rules": {
+     "required": "Skylda er að fylla út sveitarfélag"
+   }
  }
🧹 Nitpick comments (1)
apps/skilavottord/web/i18n/locales/is.json (1)

376-376: Consider improving button accessibility.

The buttons section could benefit from additional ARIA labels for better screen reader support.

  "buttons": {
-   "add": "Bæta við móttökuaðila",
-   "view": "Skoða",
-   "addMunicipality": "Bæta við sveitarfélagi"
+   "add": {
+     "text": "Bæta við móttökuaðila",
+     "ariaLabel": "Bæta við nýjum móttökuaðila"
+   },
+   "view": {
+     "text": "Skoða",
+     "ariaLabel": "Skoða upplýsingar"
+   },
+   "addMunicipality": {
+     "text": "Bæta við sveitarfélagi",
+     "ariaLabel": "Bæta við nýju sveitarfélagi"
+   }
  }

Also applies to: 395-396

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3eb50de and 00bb7f3.

📒 Files selected for processing (1)
  • apps/skilavottord/web/i18n/locales/is.json (6 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
apps/skilavottord/web/i18n/locales/is.json (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
📓 Learnings (1)
apps/skilavottord/web/i18n/locales/is.json (1)
Learnt from: birkirkristmunds
PR: island-is/island.is#17109
File: apps/skilavottord/web/i18n/locales/is.json:0-0
Timestamp: 2024-12-16T12:38:27.802Z
Learning: In the Skilavottord web application, the form for recycling partners is reused for municipalities. Therefore, specific translations for municipalities' form inputs are not needed in `apps/skilavottord/web/i18n/locales/is.json`.
🔇 Additional comments (3)
apps/skilavottord/web/i18n/locales/is.json (3)

368-372: LGTM: Navigation structure is well-organized.

The navigation items are logically grouped and consistently named, with clear separation between municipalities and companies.


587-592: LGTM: Access control validation is properly structured.

The municipality field in access control follows the correct validation pattern.


646-668: LGTM: Municipality section is well-structured.

The municipality section follows the established pattern for entity management, with proper breadcrumbs, actions, and status messages.

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)
apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (1)

Line range hint 65-70: Add error handling for GraphQL query failures.

The query implementation should handle potential GraphQL errors to provide better user feedback.

 const { data, loading, fetchMore } = useQuery<Query>(
   SkilavottordVehiclesQuery,
   {
     notifyOnNetworkStatusChange: true,
     variables: { after: '' },
+    onError: (error) => {
+      // Handle error appropriately
+      console.error('Failed to fetch vehicles:', error);
+    }
   },
 )
🧹 Nitpick comments (4)
apps/skilavottord/web/i18n/locales/is.json (1)

383-383: Consider enhancing the info text description.

While the translations are correct, the info text "Skráðir móttökuaðilar" could be more descriptive to match the English version's context about helping customers.

-    "info": "Skráðir móttökuaðilar",
+    "info": "Upplýsingar um skráða móttökuaðila sem hjálpa viðskiptavinum að nýta sér þjónustuna.",

Also applies to: 402-403

apps/skilavottord/ws/src/app/modules/municipality/municipality.model.ts (1)

7-20: Model definition looks good.

The model aligns with Sequelize best practices. Ensure indices in the underlying table optimize lookups by ID or other unique fields.

apps/skilavottord/web/screens/RecyclingFund/Overview/components/CarsTable/CarsTable.tsx (2)

Line range hint 6-9: Consider using a more specific type for table titles.

The titles array could benefit from a literal type that matches the exact columns being displayed, improving type safety and making the component more maintainable.

+type TableColumn = 'vehicleId' | 'vehicleType' | 'modelYear' | 'nameOfRequestor' | 'municipality' | 'deregistrationDate'
 interface TableProps {
-  titles: string[]
+  titles: TableColumn[]
   vehicles: Vehicle[]
 }

30-50: Consider optimizing the nested mapping for performance.

The double mapping operation (vehicles → recyclingRequests) could impact performance with large datasets.

Consider flattening the data structure before rendering:

const flattenedData = vehicles.flatMap((vehicle) =>
  (vehicle.recyclingRequests ?? []).map((request) => ({
    ...vehicle,
    request,
  }))
);

// Then map over flattenedData instead of the nested mapping
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9921511 and abd46a4.

📒 Files selected for processing (10)
  • apps/skilavottord/web/i18n/locales/en.json (5 hunks)
  • apps/skilavottord/web/i18n/locales/is.json (6 hunks)
  • apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (5 hunks)
  • apps/skilavottord/web/screens/RecyclingFund/Overview/components/CarsTable/CarsTable.tsx (2 hunks)
  • apps/skilavottord/ws/migrations/202412013210715-add-view-municipality.js (1 hunks)
  • apps/skilavottord/ws/src/app/modules/municipality/index.ts (1 hunks)
  • apps/skilavottord/ws/src/app/modules/municipality/municipality.model.ts (1 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.model.ts (2 hunks)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.module.ts (1 hunks)
  • apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/skilavottord/ws/src/app/modules/municipality/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.model.ts
🧰 Additional context used
📓 Path-based instructions (8)
apps/skilavottord/web/screens/RecyclingFund/Overview/components/CarsTable/CarsTable.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/municipality/municipality.model.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/migrations/202412013210715-add-view-municipality.js (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.module.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/en.json (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/web/i18n/locales/is.json (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
📓 Learnings (1)
apps/skilavottord/web/i18n/locales/is.json (1)
Learnt from: birkirkristmunds
PR: island-is/island.is#17109
File: apps/skilavottord/web/i18n/locales/is.json:0-0
Timestamp: 2024-12-16T12:38:27.802Z
Learning: In the Skilavottord web application, the form for recycling partners is reused for municipalities. Therefore, specific translations for municipalities' form inputs are not needed in `apps/skilavottord/web/i18n/locales/is.json`.
🪛 Biome (1.9.4)
apps/skilavottord/ws/migrations/202412013210715-add-view-municipality.js

[error] 1-1: Redundant use strict directive.

The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.
Safe fix: Remove the redundant use strict directive.

(lint/suspicious/noRedundantUseStrict)

🔇 Additional comments (23)
apps/skilavottord/web/i18n/locales/en.json (5)

364-371: LGTM! Table columns updated to include municipality.

The addition of the "Municipality" column in the recycled vehicles table aligns with the new municipality management feature.


375-375: LGTM! Navigation items added for municipality management.

The addition of municipality-related navigation items provides access to the new municipality management features.

Also applies to: 378-379


402-403: LGTM! Buttons added for municipality management.

The addition of the "Add municipality" button enables associating municipalities with recycling companies.


648-652: LGTM! Routes added for municipality management.

The addition of municipality routes enables Create, Read, and Update operations for municipalities.


Line range hint 654-675: LGTM! Municipality management translations added.

Complete set of translations added for municipality management features, including views, forms, and status messages.

apps/skilavottord/web/i18n/locales/is.json (6)

364-371: LGTM! Table columns updated with municipality translation.

The Icelandic translation "Sveitarfélag" is correctly added to the table columns.


375-375: LGTM! Municipality navigation items translated correctly.

The translations "Sveitarfélag" and "Sveitarfélög" are appropriate for the navigation items.

Also applies to: 378-379


594-599: LGTM! Municipality field added to access control.

The municipality field is correctly implemented with proper validation rules and translations.


653-657: LGTM! Municipality routes added correctly.

The routes for municipality management are properly defined and consistent with the English version.


659-675: LGTM! Municipality management translations are complete and accurate.

The translations provide comprehensive coverage for all municipality management features, with clear and appropriate Icelandic text.


493-496: 🛠️ Refactor suggestion

Fix validation rules format for municipality field.

The validation rules format for the municipality field is inconsistent with other fields in the form.

   "municipality": {
     "label": "Sveitarfélag",
     "placeholder": "Sveitarfélag",
-    "required": "Skylda er að fylla út sveitarfélag"
+    "rules": {
+      "required": "Skylda er að fylla út sveitarfélag"
+    }
   }

Likely invalid or redundant comment.

apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx (4)

24-25: LGTM: Component imports align with the new navigation structure.

The new imports for NavigationLinks and PageHeader components align with the PR's objective of improving the municipality management interface.


124-124: LGTM: UI changes improve consistency and maintainability.

The replacement of custom navigation with reusable NavigationLinks and PageHeader components improves the overall consistency of the application's UI.

Also applies to: 144-144


Line range hint 1-170: Add test coverage for municipality-related functionality.

The PR description indicates that tests haven't been added yet. Given the importance of municipality management features, please add tests covering:

  • Permission checks for municipality roles
  • Municipality data retrieval and display
  • Error scenarios

Would you like me to help create a test suite for this component?


46-53: Verify the completeness of municipality data retrieval.

The GraphQL query has been expanded to include municipality-related fields, but there might be missing fields that could be useful for municipality management (e.g., contact information, address).

apps/skilavottord/ws/migrations/202412013210715-add-view-municipality.js (1)

5-10: SQL view creation looks correct.

The migration creates a new view to fetch municipality partners. Be sure to verify that any dependent code references the new view name properly.

apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.module.ts (1)

10-13: Correct inclusion of MunicipalityModel.

By adding MunicipalityModel to SequelizeModule.forFeature, you ensure that the recyclingPartner module is aware of municipality data. This aligns with NestJS module design.

apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts (3)

32-48: Robust error handling for municipality sub-partners.

Your try-catch block properly logs and throws an error upon failure. The approach is reasonable. Confirm that upstream callers handle the error gracefully.


27-28: Use array initialization sparingly.

You initialize an empty array here and conditionally set it to null later. Make sure your calling logic can handle both states (null vs. array).

✅ Verification successful

Let me verify how this array is being used in the codebase by checking the implementation.


Let me check the complete context of how this variable is used in the function.


Array initialization is correctly handled in this context

The code shows a clear and intentional pattern where partnerIds is initialized as an empty array and then either:

  1. Populated with municipality partner IDs if filter.partnerId exists
  2. Explicitly set to null if filter.partnerId doesn't exist

This is a valid pattern as it provides a clear distinction between "no partners" (empty array) and "all partners" (null) states, and the code handles both cases appropriately.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# First, let's see the full context of this file
rg -A 10 "let partnerIds = \[\]" apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts

# Let's also check where this variable is being used
ast-grep --pattern 'partnerIds'

Length of output: 1401


Script:

#!/bin/bash
# Get more context around the usage of partnerIds in vehicle.service.ts
rg -B 20 -A 30 "let partnerIds = \[\]" apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts

Length of output: 1539


72-81: Verify model associations for performance.

You are including MunicipalityModel under a left join. This typically avoids an N+1 pattern, but confirm that repeated queries won't degrade performance at scale or if you join additional relationships in the future.

✅ Verification successful

Let me gather information about the model associations and query patterns to verify the performance concerns.


Let me search for more specific information about the model definitions and query patterns.


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

Left join with MunicipalityModel is appropriately implemented and optimized

The implementation shows that:

  1. The MunicipalityModel is used sparingly with minimal attributes selected (companyName only)
  2. The left join is properly configured with required: false
  3. No evidence of N+1 query patterns or nested relationships that could cause performance issues
  4. The model is consistently used across the codebase with similar join patterns
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for MunicipalityModel definition and its associations
ast-grep --pattern 'class MunicipalityModel extends $_'

# Search for other places where MunicipalityModel is included in queries
rg "MunicipalityModel.*include" -A 5

# Look for other complex joins or relationships with MunicipalityModel
rg "model: MunicipalityModel" -A 5

Length of output: 717


Script:

#!/bin/bash
# Find the MunicipalityModel definition file
fd "municipality.model.ts"

# Look for the model definition and its relationships
rg "MunicipalityModel" -A 10

# Search for any query implementations using this model
ast-grep --pattern 'findAll({
  $$$
  include: [{
    model: MunicipalityModel,
    $$$
  }]
  $$$
})'

Length of output: 50597

apps/skilavottord/web/screens/RecyclingFund/Overview/components/CarsTable/CarsTable.tsx (3)

1-4: LGTM! Imports are well-organized and properly typed.

The imports follow TypeScript best practices and are appropriately scoped for the component's needs.


Line range hint 11-29: LGTM! Component structure follows React best practices.

The component is well-structured with proper TypeScript typing and clean table header implementation.


42-45: Verify municipality data flow and error states.

The new municipality display aligns with the PR objectives, but we should ensure proper error handling for various data states.

Run the following script to check for proper typing of the municipality field in the GraphQL schema:

✅ Verification successful

Optional chaining is correctly used for handling nullable data

The code follows proper error handling practices by using optional chaining (?.) for both recyclingPartner?.municipality?.companyName and recyclingRequests?.map. The fallback to nameOfRequestor using the nullish coalescing operator (??) provides a sensible default when municipality data is not available. This implementation safely handles various data states and follows React/TypeScript best practices.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check GraphQL schema for municipality field definition
ast-grep --pattern 'type Municipality {
  $$$
  companyName: String
  $$$
}'

# Check for proper typing in the Vehicle type
ast-grep --pattern 'type Vehicle {
  $$$
  recyclingRequests: [RecyclingRequest]
  $$$
}'

Length of output: 170


Script:

#!/bin/bash
# Let's try to find GraphQL schema files and type definitions
fd -e graphql -e gql . --exec cat {}

# Also search for type definitions in TypeScript files
rg -t typescript "type\s+(Municipality|RecyclingPartner|Vehicle|RecyclingRequest)" -A 5

Length of output: 65759


Script:

#!/bin/bash
# Let's search for type definitions in TypeScript files using a different approach
fd -e ts -e tsx . --exec rg "type\s+(Municipality|RecyclingPartner|Vehicle|RecyclingRequest)" -A 5 {}

# Also search for the specific component's usage of municipality
rg -l "recyclingPartner\?\.municipality" .

Length of output: 2930


Script:

#!/bin/bash
# Let's look for the interface or type definition of RecyclingPartner and Municipality
rg "interface.*Municipality|type.*Municipality|interface.*RecyclingPartner|type.*RecyclingPartner" -A 5 .

# Also search for the specific file's imports to understand the types
rg -l "CarsTable" . | xargs rg "^import|^export"

Length of output: 28926


Script:

#!/bin/bash
# Let's check the Vehicle type definition in the GraphQL schema
rg "type\s+Vehicle\s*{" -A 10 .

# Also check the specific component's imports and type definitions
cat ./apps/skilavottord/web/screens/RecyclingFund/Overview/components/CarsTable/CarsTable.tsx

Length of output: 1976

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
apps/skilavottord/web/screens/RecyclingFund/Overview/components/CarsTable/CarsTable.tsx (1)

30-50: Consider optimizing nested map operations.

While the implementation has been improved with proper key uniqueness and null handling, the nested map operations could impact performance with large datasets.

Consider these optimizations:

+ const memoizedRequests = useMemo(() => 
    vehicles.flatMap(({ vehicleId, vehicleType, newregDate, recyclingRequests }) =>
      recyclingRequests?.map(({ createdAt, nameOfRequestor, recyclingPartner }, index) => ({
        key: `${vehicleId}-${index}`,
        vehicleId,
        vehicleType,
        modelYear: getYear(newregDate),
        deregistrationDate: getDate(createdAt),
        nameOfRequestor,
        companyName: recyclingPartner?.municipality?.companyName ?? nameOfRequestor
      })) ?? []
    ),
+  [vehicles]
+ )

  return (
    <Table>
      <Head>{/* ... */}</Head>
      <Body>
-       {vehicles.map(
-         ({ vehicleId, vehicleType, newregDate, recyclingRequests }) => {
-           return recyclingRequests?.map(
-             ({ createdAt, nameOfRequestor, recyclingPartner }, index) => {
-               const modelYear = getYear(newregDate)
-               const deregistrationDate = getDate(createdAt)
+       {memoizedRequests.map(({
+         key,
+         vehicleId,
+         vehicleType,
+         modelYear,
+         deregistrationDate,
+         nameOfRequestor,
+         companyName
+       }) => (
                return (
-                 <Row key={`${vehicleId}-${index}`}>
+                 <Row key={key}>
                    <Data>
                      <Text variant="eyebrow">{vehicleId}</Text>
                    </Data>
                    <Data>{vehicleType}</Data>
                    <Data>{modelYear ?? ''}</Data>
                    <Data>{nameOfRequestor}</Data>
                    <Data>
-                     {recyclingPartner?.municipality?.companyName ??
-                       nameOfRequestor}
+                     {companyName}
                    </Data>
                    <Data>{deregistrationDate ?? ''}</Data>
                  </Row>
                )
-             },
-           )
-         },
-       )}
+       ))}
      </Body>
    </Table>
  )

This optimization:

  1. Flattens the nested maps into a single operation
  2. Memoizes the data transformation
  3. Simplifies the JSX rendering logic
  4. Maintains all the null checks and fallbacks
apps/skilavottord/ws/migrations/202412230017109-add-view-municipality.js (1)

2-9: Consider using "CREATE OR REPLACE VIEW" for seamless updates and versioning.

Currently, you are using "CREATE VIEW" to introduce the municipality_view, which will fail if the view already exists. If you expect to update or modify this view in future migrations or if the view might exist from earlier iterations, you could use "CREATE OR REPLACE VIEW" to avoid errors during deployment.

apps/skilavottord/ws/migrations/202412010017109-addcolumns-recycling-partners-municipality.js (2)

5-9: Column addition for is_municipality seems correct.

The column name, type, and default value are suitably configured. Consider verifying if “is_municipality” follows your naming conventions for boolean fields throughout your codebase.


10-13: Consider foreign key constraints.

Adding the “municipality_id” column as a string is fine, but if you have a separate municipality table, a foreign key constraint could help maintain referential integrity.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between abd46a4 and 7cb4964.

📒 Files selected for processing (3)
  • apps/skilavottord/web/screens/RecyclingFund/Overview/components/CarsTable/CarsTable.tsx (2 hunks)
  • apps/skilavottord/ws/migrations/202412010017109-addcolumns-recycling-partners-municipality.js (1 hunks)
  • apps/skilavottord/ws/migrations/202412230017109-add-view-municipality.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
apps/skilavottord/web/screens/RecyclingFund/Overview/components/CarsTable/CarsTable.tsx (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/migrations/202412010017109-addcolumns-recycling-partners-municipality.js (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/skilavottord/ws/migrations/202412230017109-add-view-municipality.js (1)

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

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
🔇 Additional comments (7)
apps/skilavottord/web/screens/RecyclingFund/Overview/components/CarsTable/CarsTable.tsx (3)

1-4: LGTM! Clean and well-organized imports.

The imports follow NextJS best practices and include proper TypeScript types.


Line range hint 6-9: LGTM! Well-defined TypeScript interface.

The interface is clear, properly typed, and follows TypeScript best practices.


Line range hint 11-29: LGTM! Clean component structure.

The component follows React and TypeScript best practices, with proper typing and efficient table header implementation.

apps/skilavottord/ws/migrations/202412230017109-add-view-municipality.js (1)

11-15: Migration reversal logic looks good.

Using "DROP VIEW IF EXISTS" is a safe approach to avoid breaking migrations if the view has already been removed, or does not exist. This is a recommended way to gracefully handle reversals. No further action needed.

apps/skilavottord/ws/migrations/202412010017109-addcolumns-recycling-partners-municipality.js (3)

1-2: Looks good.

Importing DataTypes from sequelize is standard for defining column types in a migration.


3-4: Module export is coherent.

Exporting the up/down methods aligns with typical Sequelize migration patterns.


14-16: Index creation is sensible.

Indexing “is_municipality” may improve query performance. Verify usage patterns to ensure this index is beneficial.

✅ Verification successful

Let me search for usage patterns of the is_municipality column to verify if the index would be beneficial.


Let me search for any queries or service methods that might be filtering or searching by this column to better understand its usage patterns.


Based on the search results, I can now provide a final response about the index's usefulness:

Index on is_municipality is beneficial for query performance

The codebase shows frequent filtering on the is_municipality column in several critical scenarios:

  • Used in a dedicated view municipality_view that filters by is_municipality = true
  • Frequently used in service layer queries to filter recycling partners:
    • To find all municipalities (where: { isMunicipality: true })
    • To find non-municipality partners (where: { isMunicipality: false })
    • In complex OR conditions ([Op.or]: [{ isMunicipality: false }, { isMunicipality: null }])
  • Used in UI components to separate municipality and non-municipality partners
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for SQL queries or ORM operations involving is_municipality
rg -i "is_municipality" --type sql --type js --type ts -A 3 -B 3

Length of output: 4498


Script:

#!/bin/bash
# Search for any service methods or queries using isMunicipality
rg -i "isMunicipality|where.*municipality" --type ts --type js -A 5 -B 5

Length of output: 57679

Comment on lines +19 to +26
down: async (queryInterface) => {
/* await queryInterface.removeIndex(
'recycling_partner',
'idx_recycling_partner_is_municipality',
)
await queryInterface.removeColumn('recycling_partner', 'is_municipality')
await queryInterface.removeColumn('recycling_partner', 'municipality_id')*/
},
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 23, 2024

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reinstate the “down” method for reliable rollbacks.

Re-enable the code that removes the index and columns to allow proper reversal of this migration if necessary.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is how I wan't it to be. I dont want to loose data if when migrate undo

Copy link
Contributor

Choose a reason for hiding this comment

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

@birkirkristmunds Understood. We’ll leave the "down" method commented out so that the columns remain and no data is lost on rollback, as per your preference.

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 deploy-feature Deploys features to dev
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant