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 4 commits into
base: main
Choose a base branch
from

Conversation

birkirkristmunds
Copy link
Member

@birkirkristmunds birkirkristmunds commented Dec 3, 2024

...

Attach a link to issue if relevant

What

Specify what you're trying to achieve

Why

Specify why you need to achieve this

Screenshots / Gifs

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

Checklist:

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

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced new roles and permissions related to municipalities, enhancing access control.
    • Added components for improved navigation and page headers.
    • Implemented new functionality for managing recycling partners, including municipality-specific features.
    • New pages for viewing and adding municipalities have been created.
  • Enhancements

    • Updated localization files to support new functionalities related to municipalities.
    • Improved data fetching logic for recycling partners based on user roles.
    • Enhanced the sidebar navigation and overall layout with new components.
  • Bug Fixes

    • Resolved issues with user role handling and permissions in various components.
  • Documentation

    • Updated documentation to reflect new roles and functionalities.

Copy link
Contributor

coderabbitai bot commented Dec 3, 2024

Walkthrough

The pull request introduces significant changes to the role and permission management within the application. The Page type is modified to remove specific permissions, and new roles are added, including municipality, which has its own set of permitted pages. Additionally, new components for navigation and page headers are introduced, and various existing components are updated to accommodate the new roles and improve the user interface. Localization files are also updated to reflect these changes, enhancing the management of municipalities in the application.

Changes

File Change Summary
apps/skilavottord/web/auth/utils.ts Modified Page type, updated permittedRoutes for roles, added municipality role with its pages.
apps/skilavottord/web/components/NavigationLinks/NavigationLinks.tsx Added new NavigationLinks component for sidebar navigation with role-based visibility.
apps/skilavottord/web/components/PageHeader/PageHeader.tsx Introduced new PageHeader component for displaying titles and info.
apps/skilavottord/web/components/Sidenav/Sidenav.tsx Updated Sidenav to conditionally render sections based on a new hidden property.
apps/skilavottord/web/i18n/locales/en.json Added new localization keys for municipalities and updated existing labels and placeholders.
apps/skilavottord/web/i18n/locales/is.json Similar updates as in the English localization for the Icelandic language.
apps/skilavottord/web/i18n/locales/translation.d.ts Updated Translation interface to include new municipalities property and related interfaces.
apps/skilavottord/web/pages/en/municipalities/[id].tsx Added new page component for updating recycling companies with localization support.
apps/skilavottord/web/pages/en/municipalities/add.tsx Introduced new page for adding recycling companies with localization support.
apps/skilavottord/web/pages/en/municipalities/index.tsx New page component for listing recycling companies with localization support.
apps/skilavottord/web/pages/municipalities/[id].tsx Added new page component for updating recycling companies in Icelandic.
apps/skilavottord/web/pages/municipalities/add.tsx New page for adding recycling companies in Icelandic.
apps/skilavottord/web/pages/municipalities/index.tsx New page for listing recycling companies in Icelandic.
apps/skilavottord/web/screens/AccessControl/AccessControl.tsx Updated to use lazy queries for fetching recycling partners, replaced Sidenav with NavigationLinks.
apps/skilavottord/web/screens/AccessControl/components/AccessControlModal/AccessControlModal.tsx Refined validation logic and cleaned up imports.
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanies.tsx Updated query to accommodate municipalities and replaced Sidenav with NavigationLinks.
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyCreate/RecyclingCompanyCreate.tsx Enhanced logic to differentiate between municipalities and recycling companies.
apps/skilavottord/web/screens/RecyclingCompanies/RecyclingCompanyUpdate/RecyclingCompanyUpdate.tsx Updated to reflect changes in handling municipalities.
apps/skilavottord/web/screens/RecyclingCompanies/components/RecyclingCompanyForm/RecyclingCompanyForm.tsx Added checkbox for isMunicipality and updated submission button.
apps/skilavottord/web/screens/RecyclingFund/Overview/Overview.tsx Updated query to include municipalityId and replaced Sidenav with NavigationLinks.
apps/skilavottord/web/utils/roleUtils.ts Updated getRoleTranslation function to use Role enum values.
apps/skilavottord/ws/migrations/202412013210715-addcolumns-recycling-partners-municipality.js Migration added for new columns in recycling_partner table.
apps/skilavottord/ws/seeders/20201010211010-seed-recycling-request.js Updated vehicle_id values in the recycling_request table.
apps/skilavottord/ws/src/app/modules/accessControl/accessControl.resolver.ts Added Role.municipality to access control logic.
apps/skilavottord/ws/src/app/modules/accessControl/accessControl.service.ts Enhanced findByRecyclingPartner method to retrieve all sub-companies.
apps/skilavottord/ws/src/app/modules/auth/auth.guard.ts Modified Authorize decorator to consistently apply guards.
apps/skilavottord/ws/src/app/modules/auth/user.model.ts Added municipality to Role enum.
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.input.ts Added isMunicipality and municipalityId fields to input classes.
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.model.ts Added isMunicipality and municipalityId fields to model class.
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.resolver.ts Updated methods to include Role.municipality and added new query for recycling partners by type.
apps/skilavottord/ws/src/app/modules/recyclingPartner/recyclingPartner.service.ts Introduced method for finding recycling partners by type.
apps/skilavottord/ws/src/app/modules/vehicle/vehicle.resolver.ts Updated vehicle resolver to include municipalityId in query.
apps/skilavottord/ws/src/app/modules/vehicle/vehicle.service.ts Enhanced filtering logic for vehicle records based on recycling partners.
apps/skilavottord/ws/src/app/modules/AccessControlCompany/AccessControlCompany.tsx Updated role checks to use hasDeveloperRole instead of isDeveloper.

Possibly related PRs

Suggested labels

automerge, deploy-feature

Suggested reviewers

  • thordurhhh
  • unakb

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. (Experiment)
  • @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

All modified and coverable lines are covered by tests ✅

Project coverage is 35.70%. Comparing base (1a6abd6) to head (d1108ea).
Report is 28 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #17109      +/-   ##
==========================================
- Coverage   35.73%   35.70%   -0.03%     
==========================================
  Files        6926     6950      +24     
  Lines      147681   148060     +379     
  Branches    42062    42108      +46     
==========================================
+ Hits        52776    52871      +95     
- Misses      94905    95189     +284     
Flag Coverage Δ
api 3.33% <ø> (ø)
application-system-api 38.76% <ø> (-0.01%) ⬇️
application-template-api-modules 27.81% <ø> (-0.02%) ⬇️

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

Files with missing lines Coverage Δ
...pp/modules/accessControl/accessControl.resolver.ts 0.00% <ø> (ø)
...app/modules/accessControl/accessControl.service.ts 0.00% <ø> (ø)
...skilavottord/ws/src/app/modules/auth/auth.guard.ts 0.00% <ø> (ø)
...skilavottord/ws/src/app/modules/auth/user.model.ts 0.00% <ø> (ø)
...modules/recyclingPartner/recyclingPartner.input.ts 100.00% <ø> (ø)
...modules/recyclingPartner/recyclingPartner.model.ts 85.00% <ø> (ø)
...ules/recyclingPartner/recyclingPartner.resolver.ts 0.00% <ø> (ø)
...dules/recyclingPartner/recyclingPartner.service.ts 23.52% <ø> (+1.30%) ⬆️
...ord/ws/src/app/modules/vehicle/vehicle.resolver.ts 0.00% <ø> (ø)
...tord/ws/src/app/modules/vehicle/vehicle.service.ts 19.56% <ø> (ø)

... and 276 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 2692a1f...d1108ea. Read the comment docs.

@datadog-island-is
Copy link

datadog-island-is bot commented Dec 3, 2024

Datadog Report

All test runs 8974051 🔗

4 Total Test Services: 0 Failed, 4 Passed
🔻 Test Sessions change in coverage: 1 decreased (-0.08%), 5 no change

Test Services
Service Name Failed Known Flaky New Flaky Passed Skipped Total Time Code Coverage Change Test Service View
api 0 0 0 4 0 2.71s 1 no change Link
application-system-api 0 0 0 46 0 2m 18.21s 1 no change Link
application-template-api-modules 0 0 0 118 0 2m 13.6s 1 no change Link
skilavottord-ws 0 0 0 1 0 13.84s 1 decreased (-0.08%) Link

🔻 Code Coverage Decreases vs Default Branch (1)

  • skilavottord-ws - jest 25.36% (-0.08%) - 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.

Comment on lines +89 to +90
query: SkilavottordAllRecyclingPartnersByTypeQuery,
variables: { isMunicipality, municipalityId: partnerId },
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure refetchQueries variables are correctly set

In the refetchQueries option of the useMutation hook, confirm that the variables passed match the expected parameters of the query.

Verify that SkilavottordAllRecyclingPartnersByTypeQuery accepts isMunicipality and municipalityId as variables and that they are correctly provided.

} = useForm({
mode: 'onChange',
defaultValues: { isMunicipality, municipalityId: partnerId },
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix default values in useForm

The defaultValues object should match the form's field names. Currently, municipalityId is included even when isMunicipality is true, which may cause unexpected behavior.

Apply this diff to conditionally set municipalityId based on isMunicipality:

 useForm({
   mode: 'onChange',
-  defaultValues: { isMunicipality, municipalityId: partnerId },
+  defaultValues: isMunicipality
+    ? { isMunicipality }
+    : { isMunicipality, municipalityId: partnerId },
 })

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 75 to 79
let partnerId = null
if (user?.role === Role.municipality) {
partnerId = user?.partnerId
}

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential misalignment in partner ID assignment

Ensure that partnerId is properly assigned when the user is a municipality to avoid unintended data fetching.

Confirm that user.partnerId is correctly set and used.

Comment on lines +223 to +226
const partners =
recyclingPartnerData?.skilavottordAllRecyclingPartners ||
recyclingPartnerByIdData?.skilavottordAllRecyclingPartnersByType ||
[]
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential confusion with partners data

The merger of data from different queries into partners may lead to inconsistent data structures.

Ensure that the data from recyclingPartnerData and recyclingPartnerByIdData are compatible and properly handled.

Comment on lines +26 to +42
let partnerIds = []

// Get all sub recycling partners of the municipality
// else get all
if (filter.partnerId) {
// Get all sub recycling partners of the municipality
const subRecyclingPartners = await RecyclingPartnerModel.findAll({
where: { municipalityId: filter.partnerId },
})

partnerIds = [
filter.partnerId,
...subRecyclingPartners.map((partner) => partner.companyId),
]
} else {
partnerIds = null
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling and optimize database query

The current implementation has two issues:

  1. Missing error handling for the database query
  2. Potential N+1 query problem when fetching sub-partners

Consider refactoring to:

 if (filter.partnerId) {
-  // Get all sub recycling partners of the municipality
-  const subRecyclingPartners = await RecyclingPartnerModel.findAll({
-    where: { municipalityId: filter.partnerId },
-  })
-
-  partnerIds = [
-    filter.partnerId,
-    ...subRecyclingPartners.map((partner) => partner.companyId),
-  ]
+  try {
+    const subRecyclingPartners = await RecyclingPartnerModel.findAll({
+      where: { municipalityId: filter.partnerId },
+      attributes: ['companyId'],
+    });
+    
+    partnerIds = [
+      filter.partnerId,
+      ...subRecyclingPartners.map((partner) => partner.companyId),
+    ];
+  } catch (error) {
+    this.logger.error('Failed to fetch sub-partners:', error);
+    throw new Error('Failed to process municipality partners');
+  }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +68 to +72

if (user.role === Role.municipality) {
return this.accessControlService.findByRecyclingPartner(user.partnerId)
}

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for municipality access control

The municipality-specific logic lacks error handling for the service call.

Consider adding error handling:

   if (user.role === Role.municipality) {
+    try {
       return this.accessControlService.findByRecyclingPartner(user.partnerId)
+    } catch (error) {
+      throw new ApolloError(
+        'Failed to fetch municipality access controls',
+        'MUNICIPALITY_ACCESS_ERROR'
+      )
+    }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (user.role === Role.municipality) {
return this.accessControlService.findByRecyclingPartner(user.partnerId)
}
if (user.role === Role.municipality) {
try {
return this.accessControlService.findByRecyclingPartner(user.partnerId)
} catch (error) {
throw new ApolloError(
'Failed to fetch municipality access controls',
'MUNICIPALITY_ACCESS_ERROR'
)
}
}

"view": {
"title": "Municipality",
"breadcrumb": "View",
"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.",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix non-English content in English locale file.

These strings are in Icelandic instead of English:

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

Also applies to: 657-657

Comment on lines +486 to 489
"municipality": {
"label": "Sveitarfélag",
"placeholder": "Sveitarfélag"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add validation rules for municipality field.

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

Add validation rules:

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

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

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

Comment on lines +638 to +659
"municipalities": {
"baseRoute": "/municipalities",
"add": "/municipalities/add",
"edit": "/municipalities/[id]"
}
},
"municipalities": {
"title": "Sveitarfélög",
"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.",
"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ð"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ 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"
+           }
+         }
+       }
+     }
    }
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"municipalities": {
"baseRoute": "/municipalities",
"add": "/municipalities/add",
"edit": "/municipalities/[id]"
}
},
"municipalities": {
"title": "Sveitarfélög",
"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.",
"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ð"
}
"municipalities": {
"baseRoute": "/municipalities",
"add": "/municipalities/add",
"edit": "/municipalities/[id]"
}
},
"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 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: 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)
+   }
+ }

Comment on lines 41 to +43
phone
active
municipalityId
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

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.

Apply this diff to add the missing field:

  mutation updateSkilavottordRecyclingPartnerMutation(
    $input: UpdateRecyclingPartnerInput!
  ) {
    updateSkilavottordRecyclingPartner(input: $input) {
      companyId
      companyName
      nationalId
      email
      address
      postnumber
      city
      website
      phone
      active
+     municipalityId
    }
  }

Also applies to: 47-63

Comment on lines +152 to +154
if (typeof input.municipalityId !== 'string') {
input.municipalityId = input.municipalityId?.value || ''
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve municipalityId type handling

The current type conversion could be more robust with explicit type checking.

Consider this safer approach:

- if (typeof input.municipalityId !== 'string') {
-   input.municipalityId = input.municipalityId?.value || ''
- }
+ const municipalityId = input.municipalityId
+ input.municipalityId = typeof municipalityId === 'object' && municipalityId?.value
+   ? municipalityId.value
+   : (municipalityId as string) || ''
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (typeof input.municipalityId !== 'string') {
input.municipalityId = input.municipalityId?.value || ''
}
const municipalityId = input.municipalityId
input.municipalityId = typeof municipalityId === 'object' && municipalityId?.value
? municipalityId.value
: (municipalityId as string) || ''

Comment on lines +106 to +128
if (typeof input.municipalityId !== 'string') {
input.municipalityId = input.municipalityId?.value || ''
}

const { errors } = await createSkilavottordRecyclingPartner({
variables: { input: { ...input, active: !!input.active } },
variables: {
input: {
...input,
active: !!input.active,
isMunicipality: !!input.isMunicipality,
},
},
})
if (!errors) {
router.push(routes.recyclingCompanies.baseRoute).then(() => {
toast.success(t.recyclingCompany.add.added)
})
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)
})
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor success handling and type conversion

Two improvements could be made:

  1. The success message is duplicated
  2. The type conversion could be more robust
-    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)
-      })
-    }
+    const route = isMunicipality 
+      ? routes.municipalities.baseRoute 
+      : routes.recyclingCompanies.baseRoute;
+    router.push(route).then(() => {
+      toast.success(t.recyclingCompany.add.added)
+    })

Also, consider adding type validation:

-    if (typeof input.municipalityId !== 'string') {
+    if (input.municipalityId && typeof input.municipalityId !== 'string') {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (typeof input.municipalityId !== 'string') {
input.municipalityId = input.municipalityId?.value || ''
}
const { errors } = await createSkilavottordRecyclingPartner({
variables: { input: { ...input, active: !!input.active } },
variables: {
input: {
...input,
active: !!input.active,
isMunicipality: !!input.isMunicipality,
},
},
})
if (!errors) {
router.push(routes.recyclingCompanies.baseRoute).then(() => {
toast.success(t.recyclingCompany.add.added)
})
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)
})
}
if (input.municipalityId && typeof input.municipalityId !== 'string') {
input.municipalityId = input.municipalityId?.value || ''
}
const { errors } = await createSkilavottordRecyclingPartner({
variables: {
input: {
...input,
active: !!input.active,
isMunicipality: !!input.isMunicipality,
},
},
})
if (!errors) {
const route = isMunicipality
? routes.municipalities.baseRoute
: routes.recyclingCompanies.baseRoute;
router.push(route).then(() => {
toast.success(t.recyclingCompany.add.added)
})
}

Comment on lines +198 to +203
recyclingPartnerError || accessControlsError || recyclingPartnerByIdError
const loading =
recyclingPartnerLoading ||
accessControlsLoading ||
recyclingPartnerByIdLoading
const isData = !!recyclingPartnerData || !!accessControlsData
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Include all data sources in isData check

The isData constant currently checks for recyclingPartnerData and accessControlsData. Since recyclingPartnerByIdData is also a potential data source for partners, it should be included in the isData condition to ensure that all necessary data is loaded before rendering.

Apply this diff to include recyclingPartnerByIdData:

- const isData = !!recyclingPartnerData || !!accessControlsData
+ const isData = !!recyclingPartnerData || !!recyclingPartnerByIdData || !!accessControlsData
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
recyclingPartnerError || accessControlsError || recyclingPartnerByIdError
const loading =
recyclingPartnerLoading ||
accessControlsLoading ||
recyclingPartnerByIdLoading
const isData = !!recyclingPartnerData || !!accessControlsData
recyclingPartnerError || accessControlsError || recyclingPartnerByIdError
const loading =
recyclingPartnerLoading ||
accessControlsLoading ||
recyclingPartnerByIdLoading
const isData = !!recyclingPartnerData || !!recyclingPartnerByIdData || !!accessControlsData

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

Successfully merging this pull request may close these issues.

1 participant