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(rental-agreement): Project structure & minimal functionality #16214

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

Conversation

addi
Copy link
Contributor

@addi addi commented Sep 30, 2024

Rental-agreement project structure & minimal functionality

This is pretty much just wireframe code around a new application system form.
Locked behind a feature flag created in ConfigCat and added to @island.is/feature-flags package as per instructions in github docs.

Why

We want to get this code in so we can start developing in a better workflow, small PRs, QA and such.

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

  • New Features

    • Introduced a new rental agreement application type that expands your service options.
    • Enhanced user experience with improved form validations, clear instructions, and localized guidance for housing and rental details.
    • Added comprehensive property search functionality to streamline finding rental properties.
    • Implemented detailed summaries for property and rental information to improve clarity and accessibility.
    • Added new components for property search and rental agreement summaries to enhance user interaction.
  • Chores

    • Streamlined configuration and organization to support the new rental agreement functionality.

hebaulf and others added 21 commits September 13, 2024 11:00
Copy link
Contributor

coderabbitai bot commented Sep 30, 2024

Walkthrough

This pull request adds support for a new rental agreement application type. It extends the application template loader to dynamically import the rental agreement template, updates the application types enum and configuration, and introduces a dedicated rental agreement module. New enums, a helper function, a Zod data schema for validation, and internationalized messages for housing condition inspection have been added. Additionally, the module’s exports are consolidated in an index file, and a new CODEOWNERS entry is established.

Changes

File(s) Changes Summary
libs/application/template-loader/.../templateLoaders.ts Added ApplicationTypes.RENTAL_AGREEMENT with a dynamic import for the rental agreement template.
libs/application/types/.../ApplicationTypes.ts Added RENTAL_AGREEMENT to the enum with value 'RentalAgreement' and its configuration (slug: 'leigusamningur', translation: 'ra.application').
libs/application/templates/rental-agreement/src/lib/{constants.ts, dataSchema.ts, messages/**, index.ts} Introduced the rental agreement module: new enums (States, Roles, various rental housing categories, and a condition inspector), a pruneAfterDays function, a Zod data schema for rental agreement validation, and internationalized messages for housing condition inspections; consolidated exports via an index file.
.github/CODEOWNERS Added new ownership entry for /libs/application/templates/rental-agreement/ assigned to @island-is/kolibri-kotid.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant AL as Application Loader
    participant RA as Rental Agreement Module
    participant DS as Data Schema Validator
    participant IM as Intl Messages

    U->>AL: Request rental agreement application form
    AL->>RA: Dynamically import RENTAL_AGREEMENT template
    RA->>DS: Validate application data using Zod schema
    RA->>IM: Retrieve internationalized housing condition messages
    DS-->>RA: Return validated data
    RA-->>AL: Render and return filled application template
Loading

Suggested labels

automerge

Suggested reviewers

  • magnearun
  • johannaagma
✨ Finishing Touches
  • 📝 Generate Docstrings

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

@datadog-island-is
Copy link

datadog-island-is bot commented Sep 30, 2024

Datadog Report

All test runs ed1531f 🔗

10 Total Test Services: 0 Failed, 10 Passed
🔻 Test Sessions change in coverage: 1 decreased (-0.19%), 29 increased, 156 no change

Test Services
This report shows up to 10 services
Service Name Failed Known Flaky New Flaky Passed Skipped Total Time Code Coverage Change Test Service View
air-discount-scheme-backend 0 0 0 63 0 27.58s N/A Link
air-discount-scheme-web 0 0 0 2 0 6.63s N/A Link
api 0 0 0 4 0 2.73s N/A Link
api-catalogue-services 0 0 0 23 0 9.15s N/A Link
api-domains-air-discount-scheme 0 0 0 6 0 19.73s N/A Link
api-domains-assets 0 0 0 3 0 12.41s N/A Link
api-domains-auth-admin 0 0 0 18 0 13.18s N/A Link
api-domains-communications 0 0 0 5 0 37.27s N/A Link
api-domains-criminal-record 0 0 0 5 0 10.6s N/A Link
api-domains-driving-license 0 0 0 23 0 32.29s N/A Link

🔻 Code Coverage Decreases vs Default Branch (1)

  • clients-middlewares - jest 75.67% (-0.19%) - Details

Copy link

codecov bot commented Sep 30, 2024

Codecov Report

Attention: Patch coverage is 83.33333% with 1 line in your changes missing coverage. Please review.

Project coverage is 30.74%. Comparing base (ff4eb6a) to head (b00bbe2).
Report is 48 commits behind head on main.

Files with missing lines Patch % Lines
...ication/template-loader/src/lib/templateLoaders.ts 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #16214      +/-   ##
==========================================
- Coverage   35.55%   30.74%   -4.81%     
==========================================
  Files        7038     5626    -1412     
  Lines      150799   118279   -32520     
  Branches    43094    33070   -10024     
==========================================
- Hits        53611    36362   -17249     
+ Misses      97188    81917   -15271     
Flag Coverage Δ
air-discount-scheme-backend 48.14% <100.00%> (+0.01%) ⬆️
air-discount-scheme-web 0.00% <ø> (ø)
api 3.33% <ø> (ø)
api-catalogue-services 75.81% <ø> (ø)
api-domains-air-discount-scheme 37.87% <100.00%> (+0.02%) ⬆️
api-domains-assets 26.71% <ø> (ø)
api-domains-auth-admin 48.49% <ø> (ø)
api-domains-communications 39.46% <100.00%> (-0.01%) ⬇️
api-domains-criminal-record 47.77% <100.00%> (+0.03%) ⬆️
api-domains-driving-license 44.75% <100.00%> (+0.01%) ⬆️
api-domains-education 31.06% <100.00%> (+0.03%) ⬆️
api-domains-email-signup 40.16% <100.00%> (?)
api-domains-health-insurance 35.14% <100.00%> (+0.04%) ⬆️
api-domains-license-service ?
api-domains-mortgage-certificate 34.94% <100.00%> (+0.02%) ⬆️
api-domains-payment-schedule 42.01% <100.00%> (+0.02%) ⬆️
application-api-files 61.90% <100.00%> (+0.16%) ⬆️
application-core 75.75% <100.00%> (+0.07%) ⬆️
application-system-api 38.63% <83.33%> (-0.02%) ⬇️
application-template-api-modules ?
application-templates-accident-notification 27.60% <ø> (ø)
application-templates-car-recycling 3.12% <ø> (ø)
application-templates-criminal-record 25.79% <ø> (ø)
application-templates-driving-license 18.15% <ø> (ø)
application-templates-estate 13.58% <ø> (-0.01%) ⬇️
application-templates-example-payment 24.66% <ø> (ø)
application-templates-financial-aid 14.99% <ø> (ø)
application-templates-general-petition 23.11% <ø> (ø)
application-templates-health-insurance ?
application-templates-inheritance-report 6.59% <ø> (ø)
application-templates-marriage-conditions 14.80% <ø> (ø)
application-templates-mortgage-certificate 43.85% <100.00%> (+0.11%) ⬆️
application-templates-new-primary-school 20.60% <ø> (+0.02%) ⬆️
application-templates-no-debt-certificate 51.38% <100.00%> (?)
application-templates-parental-leave 29.80% <ø> (-0.12%) ⬇️
application-types 6.41% <0.00%> (-0.06%) ⬇️
application-ui-components 1.17% <ø> (ø)
application-ui-shell 22.00% <ø> (-0.01%) ⬇️
auth-admin-web 2.43% <ø> (ø)
auth-api-lib ?
auth-nest-tools 31.69% <ø> (ø)
auth-react ?
auth-shared 75.00% <ø> (ø)
clients-charge-fjs-v2 28.88% <ø> (ø)
clients-driving-license 40.64% <100.00%> (+0.03%) ⬆️
clients-driving-license-book 43.72% <100.00%> (+0.02%) ⬆️
clients-financial-statements-inao 49.45% <100.00%> (+0.03%) ⬆️
clients-license-client 1.26% <ø> (ø)
clients-middlewares 72.49% <ø> (-0.33%) ⬇️
clients-regulations 42.71% <100.00%> (+0.04%) ⬆️
clients-rsk-company-registry 31.18% <ø> (ø)
clients-rsk-personal-tax-return 38.32% <ø> (ø)
clients-smartsolutions 12.77% <ø> (ø)
clients-syslumenn 49.16% <100.00%> (+0.02%) ⬆️
clients-zendesk 49.76% <100.00%> (+0.11%) ⬆️
cms 0.38% <ø> (-0.01%) ⬇️
cms-translations 38.81% <100.00%> (+0.01%) ⬆️
consultation-portal ?
content-search-index-manager 95.65% <ø> (ø)
content-search-toolkit 8.16% <ø> (ø)
contentful-apps 4.56% <ø> (ø)
dokobit-signing 61.57% <100.00%> (+0.08%) ⬆️
download-service ?
email-service 59.60% <100.00%> (+0.08%) ⬆️
feature-flags 90.32% <100.00%> (+0.07%) ⬆️
file-storage 45.21% <100.00%> (+0.10%) ⬆️
financial-aid-backend 51.36% <100.00%> (+0.01%) ⬆️
financial-aid-shared 17.88% <ø> (ø)
icelandic-names-registry-backend 55.04% <ø> (+0.60%) ⬆️
infra-nest-server 48.06% <ø> (ø)
infra-tracing 69.94% <ø> (ø)
island-ui-core 30.34% <ø> (ø)
judicial-system-api 20.22% <ø> (+0.14%) ⬆️
judicial-system-audit-trail 68.44% <100.00%> (+0.08%) ⬆️
judicial-system-backend ?
judicial-system-formatters 78.49% <ø> (-0.38%) ⬇️
judicial-system-message 66.22% <100.00%> (+0.06%) ⬆️
judicial-system-message-handler 47.81% <100.00%> (+0.08%) ⬆️
judicial-system-scheduler 71.01% <100.00%> (-0.19%) ⬇️
judicial-system-types 38.69% <ø> (+0.91%) ⬆️
judicial-system-web ?
license-api 42.84% <100.00%> (-0.03%) ⬇️
localization 10.15% <ø> (ø)
logging 58.02% <ø> (ø)
message-queue ?
nest-audit ?
nest-aws ?
nest-config 75.98% <100.00%> (+0.06%) ⬆️
nest-core ?
nest-feature-flags 50.63% <100.00%> (+0.06%) ⬆️
nest-problem ?
nest-sequelize 94.44% <ø> (ø)
nest-swagger 50.63% <ø> (-0.66%) ⬇️
nova-sms 60.86% <100.00%> (+0.09%) ⬆️
portals-admin-regulations-admin 1.80% <ø> (ø)
portals-core 19.62% <ø> (ø)
portals-my-pages-core 0.78% <ø> (?)
react-spa-shared ?
reference-backend ?
regulations ?
residence-history ?
samradsgatt ?
service-portal-core ?
service-portal-health ?
service-portal-information ?
services-auth-admin-api ?
services-auth-delegation-api 58.50% <100.00%> (+0.05%) ⬆️
services-auth-ids-api ?
services-auth-personal-representative ?
services-auth-personal-representative-public ?
services-auth-public-api 49.33% <100.00%> (-0.02%) ⬇️
services-documents ?
services-endorsements-api ?
services-search-indexer ?
services-sessions 65.17% <100.00%> (-0.15%) ⬇️
services-university-gateway 49.38% <100.00%> (+0.01%) ⬆️
services-user-notification ?
services-user-profile 56.87% <100.00%> (-0.05%) ⬇️
shared-components ?
shared-form-fields ?
shared-mocking ?
shared-pii ?
shared-problem ?
shared-utils ?
skilavottord-ws ?
testing-e2e ?
web 2.38% <ø> (-0.01%) ⬇️

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

Files with missing lines Coverage Δ
libs/application/types/src/lib/ApplicationTypes.ts 100.00% <100.00%> (ø)
...lication/types/src/lib/InstitutionContentfulIds.ts 100.00% <100.00%> (ø)
...ibs/application/types/src/lib/InstitutionMapper.ts 100.00% <ø> (ø)
...pplication/types/src/lib/InstitutionNationalIds.ts 100.00% <100.00%> (ø)
libs/application/types/src/lib/InstitutionTypes.ts 100.00% <100.00%> (ø)
libs/feature-flags/src/lib/features.ts 100.00% <100.00%> (ø)
...ication/template-loader/src/lib/templateLoaders.ts 4.76% <0.00%> (-0.06%) ⬇️

... and 1869 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 d72e154...b00bbe2. Read the comment docs.

@addi addi changed the title feat(rental-agreement) Project structure & minimal functionality feat(rental-agreement): Project structure & minimal functionality Oct 1, 2024
…idations (#17519)

* Add validation in dataSchema for fire protection inputs.

* Add validation in dataSchema for other fees.

* Fix dataschema name for signatureInfo.
* Add validation in dataSchema for fire protection inputs.

* Add validation in dataSchema for other fees.

* Add validation for inputs based on payment method chosen.

* Update README.md with info about localization in Contentful.

* Update summary for payment method and format outputs.
@datadog-island-is
Copy link

Datadog Report

All test runs 2adc251 🔗

10 Total Test Services: 0 Failed, 10 Passed
🔻 Test Sessions change in coverage: 1 decreased (-0.05%), 22 increased, 176 no change

Test Services
This report shows up to 10 services
Service Name Failed Known Flaky New Flaky Passed Skipped Total Time Code Coverage Change Test Service View
air-discount-scheme-backend 0 0 0 63 0 20.48s N/A Link
air-discount-scheme-web 0 0 0 2 0 7.12s 1 no change Link
api 0 0 0 4 0 2.26s 1 no change Link
api-domains-air-discount-scheme 0 0 0 6 0 19.54s N/A Link
api-domains-assets 0 0 0 3 0 12.05s 1 no change Link
api-domains-auth-admin 0 0 0 18 0 9.04s 1 no change Link
api-domains-communications 0 0 0 5 0 32.4s N/A Link
api-domains-criminal-record 0 0 0 5 0 8.56s N/A Link
api-domains-driving-license 0 0 0 23 0 27.76s 1 increased (+0.01%) Link
api-domains-education 0 0 0 8 0 18.63s 1 increased (+0.02%) Link

🔻 Code Coverage Decreases vs Default Branch (1)

  • application-types - jest 5.29% (-0.05%) - Details

Copy link

nx-cloud bot commented Feb 3, 2025

View your CI Pipeline Execution ↗ for commit c9cb5ec.

Command Status Duration Result
nx run-many --target=codegen/frontend-client --... ✅ Succeeded 1m 16s View ↗
nx run-many --target=codegen/backend-schema --a... ✅ Succeeded 23s View ↗

☁️ Nx Cloud last updated this comment at 2025-03-04 10:20:32 UTC

* Add property search section and custom component

* Update property search mock data options.

* Update custom search component. Move data to separate file.

* Update mock data, render search results and update info in summary.

* Remove console logs.

* Remove unused definitions

* Replace fetch api(localhost) with local json file.

* Change data from .json to .ts for import.
@hebaulf hebaulf requested a review from a team as a code owner February 4, 2025 15:58
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ff9a101 and 1e89169.

📒 Files selected for processing (1)
  • .github/CODEOWNERS (2 hunks)
🔇 Additional comments (1)
.github/CODEOWNERS (1)

131-132: LGTM!

The ownership entry for the rental agreement module is properly formatted and assigned to the correct team.

@@ -1,3 +1,5 @@
import { application } from "express"
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

Remove the incorrect import statement.

The CODEOWNERS file is a GitHub configuration file and does not support or require JavaScript/TypeScript imports.

-import { application } from "express"
📝 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
import { application } from "express"

…18107)

* Add validation in dataSchema for fire protection inputs.

* Add validation in dataSchema for other fees.

* Add validation for inputs based on payment method chosen.

* Update README.md with info about localization in Contentful.

* Update and add states. Add landlords and tenants as assignees.

* Update states and template flow. Cleanup and rename files.

* Update

* fix .github codeowners

* Filter assignees. Fix change button not appearig in summary.

* Fix lint warnings

* Refetch application after submit on submitFields where required.
* Add validation in dataSchema for fire protection inputs.

* Add validation in dataSchema for other fees.

* Add validation for inputs based on payment method chosen.

* Update README.md with info about localization in Contentful.

* Update and add states. Add landlords and tenants as assignees.

* Update states and template flow. Cleanup and rename files.

* Update

* fix .github codeowners

* Update property search with new data structure. Add table with property search results.

* Filter assignees. Fix change button not appearig in summary.

* Fix lint warnings

* Fix unintentional moved folder. Delete unused data files.

* Update property search results. Add clearOnChange for some radio/checkbox/select forms.

* Remove unused data/schema, other minor lint fixes.
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: 6

♻️ Duplicate comments (3)
libs/application/templates/rental-agreement/src/lib/utils.ts (3)

28-29: 🛠️ Refactor suggestion

Consider handling edge cases in the insertAt function.

The current implementation doesn't handle edge cases such as negative positions or positions greater than the string length. This could lead to unexpected behavior.

-export const insertAt = (str: string, sub: string, pos: number) =>
-  `${str.slice(0, pos)}${sub}${str.slice(pos)}`
+export const insertAt = (str: string, sub: string, pos: number) => {
+  if (pos < 0 || pos > str.length) {
+    return str; // or throw an error, depending on your use case
+  }
+  return `${str.slice(0, pos)}${sub}${str.slice(pos)}`;
+}

31-32: 🛠️ Refactor suggestion

Improve error handling in formatNationalId function.

The current implementation returns '-' for invalid inputs, which might mask errors. Consider throwing an error for invalid inputs or returning the original string.

-export const formatNationalId = (nationalId: string) =>
-  insertAt(nationalId.replace('-', ''), '-', 6) || '-'
+export const formatNationalId = (nationalId: string) => {
+  const cleaned = nationalId.replace('-', '');
+  if (cleaned.length !== 10 || !/^\d+$/.test(cleaned)) {
+    throw new Error('Invalid national ID format');
+  }
+  return insertAt(cleaned, '-', 6);
+}

56-108: 🛠️ Refactor suggestion

Use type guards instead of type assertions in getApplicationAnswers.

Type assertions might be unsafe if the retrieved values don't match the expected types. Consider using type guards for better type safety.

You could implement a simple type guard function to validate the enum values:

function isEnumValue<T extends Record<string, string | number>>(
  value: unknown,
  enumObj: T
): value is T[keyof T] {
  return Object.values(enumObj).includes(value as T[keyof T]);
}

Then validate each value before returning:

if (propertyTypeOptions && !isEnumValue(propertyTypeOptions, RentalHousingCategoryTypes)) {
  throw new Error('Invalid property type option');
}
// Repeat for other enum values
🧹 Nitpick comments (31)
libs/application/templates/rental-agreement/src/assets/IconCircleClose.tsx (1)

1-24: Enhance accessibility and reusability of the SVG icon component.

The component is well-structured but could benefit from the following improvements:

  1. Add accessibility attributes to the SVG:
 <svg
   height="24px"
   width="24px"
   viewBox="0 0 24 24"
   fill="none"
   xmlns="http://www.w3.org/2000/svg"
+  aria-hidden="true"
+  role="img"
+  aria-label="Close"
 >
  1. Consider making the component more reusable by accepting color props:
-const IconCircleClose: FC<React.PropsWithChildren<unknown>> = () => (
+interface IconCircleCloseProps {
+  circleColor?: string;
+  lineColor?: string; 
+}
+
+const IconCircleClose: FC<IconCircleCloseProps> = ({ 
+  circleColor = "#00E4CA", 
+  lineColor = "#00003C" 
+}) => (
   <svg>
     <path
       d="M0 12C0 5.37258 5.37258 0 12 0C18.6274 0 24 5.37258 24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12Z"
-      fill="#00E4CA"
+      fill={circleColor}
     />
     <path
       fillRule="evenodd"
       clipRule="evenodd"
       d="M7 12C7 11.7239 7.22386 11.5 7.5 11.5H16.5C16.7761 11.5 17 11.7239 17 12C17 12.2761 16.7761 12.5 16.5 12.5H7.5C7.22386 12.5 7 12.2761 7 12Z"
-      fill="#00003C"
+      fill={lineColor}
     />
  1. Since you're not using children, use a more appropriate type:
-const IconCircleClose: FC<React.PropsWithChildren<unknown>> = () => (
+const IconCircleClose: FC<IconCircleCloseProps> = ({ 
libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodDetails.ts (1)

13-20: Improve null checking with optional chaining.

The helper function can be improved by using optional chaining as suggested by static analysis:

const rentalPeriodIsDefinite = (answers: FormValue) => {
  const rentalPeriodDefinite = getValueViaPath(
    answers,
    'rentalPeriod.isDefinite',
    [],
  ) as string[]
-  return rentalPeriodDefinite && rentalPeriodDefinite.includes(TRUE)
+  return rentalPeriodDefinite?.includes(TRUE) ?? false
}

This change makes the code more concise and follows modern TypeScript best practices for null/undefined handling.

🧰 Tools
🪛 Biome (1.9.4)

[error] 19-19: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

libs/application/templates/rental-agreement/src/forms/rentalHousing/rentalHousingCondition.ts (1)

69-70: Consider defining file size limits for uploads.

While you've specified accepted file types, adding size limits would prevent excessively large uploads and improve user experience.

  uploadAccept: '.pdf, .doc, .docx, .rtf, .jpg, .jpeg, .png, .heic',
  uploadMultiple: true,
+ maxSize: 10, // Size in MB
  forImageUpload: true,
libs/application/templates/rental-agreement/src/fields/Summary/PropertyInfoSummary.tsx (1)

28-38: Consider grouping route props for better maintainability.

The Props interface has several route-related properties. Consider grouping them into a nested object for better organization and maintainability.

interface Props extends FieldBaseProps {
  goToScreen?: (id: string) => void
- categoryRoute?: Routes
- propertyInfoRoute?: Routes
- propertyDescriptionRoute?: Routes
- specialProvisionsRoute?: Routes
- propertyConditionRoute?: Routes
- fileUploadRoute?: Routes
- fireProtectionsRoute?: Routes
+ routes?: {
+   category?: Routes
+   propertyInfo?: Routes
+   propertyDescription?: Routes
+   specialProvisions?: Routes
+   propertyCondition?: Routes
+   fileUpload?: Routes
+   fireProtections?: Routes
+ }
  hasChangeButton: boolean
}
libs/application/templates/rental-agreement/src/lib/messages/housing/registerProperty.ts (1)

51-56: Message ID inconsistency in error section.

The error message ID contains "category" in its path, but it's located in the "info" section of the object structure.

// Error messages
searchResultsEmptyError: {
-  id: 'ra.application:registerProperty.category.searchResultsEmptyError',
+  id: 'ra.application:registerProperty.info.searchResultsEmptyError',
  defaultMessage:
    'Skráning leiguhúsnæðis þarf að vera til staðar til að halda áfram',
  description: 'Error message when no search results',
},
libs/application/templates/rental-agreement/src/fields/Summary/RentalInfoSummary.tsx (2)

50-55: Simplify security deposit condition variables.

Three similar variables are defined to check security deposit conditions. Consider consolidating these into a single helper object or function for better maintainability.

- const isSecurityDepositRequired =
-   answers.rentalAmount.isPaymentInsuranceRequired?.includes(AnswerOptions.YES)
- const isSecurityDepositAmount =
-   answers.securityDeposit?.securityAmount ||
-   answers.securityDeposit?.securityAmountOther
- const isSecurityDepositType = answers.securityDeposit?.securityType

+ const securityDeposit = {
+   isRequired: answers.rentalAmount.isPaymentInsuranceRequired?.includes(AnswerOptions.YES),
+   hasAmount: answers.securityDeposit?.securityAmount || answers.securityDeposit?.securityAmountOther,
+   hasType: !!answers.securityDeposit?.securityType
+ }

Then update references like:

- {isSecurityDepositRequired && (
+ {securityDeposit.isRequired && (

226-265: Refactor repetitive conditional rendering for security deposit types.

The code contains multiple similar conditional blocks for different security deposit types. Consider extracting this into a mapping function for better maintainability.

- {answers.securityDeposit.securityType ===
-   SecurityDepositTypeOptions.BANK_GUARANTEE && (
-   <KeyValue
-     label={summary.securityTypeInstitutionLabel}
-     value={answers.securityDeposit.bankGuaranteeInfo || '-'}
-   />
- )}
- {answers.securityDeposit.securityType ===
-   SecurityDepositTypeOptions.THIRD_PARTY_GUARANTEE && (
-   <KeyValue
-     label={summary.securityTypeThirdPartyGuaranteeLabel}
-     value={answers.securityDeposit.thirdPartyGuaranteeInfo || '-'}
-   />
- )}
- // ...more similar blocks

+ {(() => {
+   const typeConfig = {
+     [SecurityDepositTypeOptions.BANK_GUARANTEE]: {
+       label: summary.securityTypeInstitutionLabel,
+       value: answers.securityDeposit.bankGuaranteeInfo
+     },
+     [SecurityDepositTypeOptions.THIRD_PARTY_GUARANTEE]: {
+       label: summary.securityTypeThirdPartyGuaranteeLabel,
+       value: answers.securityDeposit.thirdPartyGuaranteeInfo
+     },
+     [SecurityDepositTypeOptions.INSURANCE_COMPANY]: {
+       label: summary.securityTypeInsuranceLabel,
+       value: answers.securityDeposit.insuranceCompanyInfo
+     },
+     [SecurityDepositTypeOptions.LANDLORDS_MUTUAL_FUND]: {
+       label: summary.securityTypeMutualFundLabel,
+       value: answers.securityDeposit.mutualFundInfo
+     },
+     [SecurityDepositTypeOptions.OTHER]: {
+       label: summary.securityTypeOtherLabel,
+       value: answers.securityDeposit.otherInfo
+     }
+   };
+   
+   const config = typeConfig[answers.securityDeposit.securityType];
+   return config ? (
+     <KeyValue
+       label={config.label}
+       value={config.value || '-'}
+     />
+   ) : null;
+ })()}
libs/application/templates/rental-agreement/src/fields/PropertySearch/index.tsx (5)

76-97: Remove console.error in production code

Error logging should use a structured logging system rather than direct console methods. This will help with debugging in production environments where console access might be limited.

- console.error('Error parsing stored value:', error)
+ // Consider using a structured logging library or error tracking service
+ console.error('Error parsing stored value:', error)
+ // TODO: Implement proper error handling/reporting

221-226: Use optional chaining for cleaner code

The nested conditional checks for matseiningByFasteignNr can be simplified using optional chaining.

- const isChecked =
-   matseiningByFasteignNr &&
-   matseiningByFasteignNr[propertyId]?.some((matseiningar) =>
-     matseiningar.matseiningar.some(
-       (matseining) => checkedMatseiningar[matseining.merking] === true,
-     ),
-   )
+ const isChecked = matseiningByFasteignNr?.[propertyId]?.some((matseiningar) =>
+   matseiningar.matseiningar.some(
+     (matseining) => checkedMatseiningar[matseining.merking] === true,
+   ),
+ )
🧰 Tools
🪛 Biome (1.9.4)

[error] 221-226: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


391-407: Use optional chaining for matseiningByFasteignNr checks

Simplify the nested conditional checks with optional chaining for better readability and maintainability.

- {matseiningByFasteignNr &&
-  matseiningByFasteignNr[property.fastnum] &&
-  matseiningByFasteignNr[property.fastnum].length > 0 && (
+ {matseiningByFasteignNr?.[property.fastnum]?.length > 0 && (
🧰 Tools
🪛 Biome (1.9.4)

[error] 391-392: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


438-564: Simplify nested rendering logic with optional chaining and early returns

The deeply nested conditional rendering with Fragments can be simplified for better readability and performance.

- {matseiningByFasteignNr &&
-  matseiningByFasteignNr[property.fastnum] &&
-  matseiningByFasteignNr[property.fastnum].length > 0 && (
-    <>
-      {matseiningByFasteignNr[property.fastnum].map(
-        (matseiningar) => {
+ {matseiningByFasteignNr?.[property.fastnum]?.length > 0 && 
+  matseiningByFasteignNr[property.fastnum].map(
+    (matseiningar) => {

The Fragment (<>...</>) is unnecessary here since you're already returning from a map function.

🧰 Tools
🪛 Biome (1.9.4)

[error] 438-439: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 441-563: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)


113-132: Consider extracting table expansion logic to a custom hook

The useEffect for handling table expansion states based on checked items could be extracted to a custom hook for better reusability and maintainability.

// Example custom hook
function useTableExpansion(checkedItems, itemsData) {
  const [expandedRows, setExpandedRows] = useState({});
  
  useEffect(() => {
    if (itemsData) {
      const newExpandedRows = Object.keys(itemsData).reduce(
        (acc, id) => {
          // Expansion logic
          return acc;
        },
        {}
      );
      setExpandedRows(newExpandedRows);
    }
  }, [checkedItems, itemsData]);
  
  return expandedRows;
}
libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodAmount.ts (2)

27-34: Use optional chaining for more concise code

The code can be simplified with optional chaining to improve readability.

const rentalAmountConnectedToIndex = (answers: FormValue) => {
  const isAmountConnectedToIndex = getValueViaPath(
    answers,
    'rentalAmount.isIndexConnected',
    [],
  ) as string[]
- return isAmountConnectedToIndex && isAmountConnectedToIndex.includes(TRUE)
+ return isAmountConnectedToIndex?.includes(TRUE) ?? false
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 33-33: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


154-161: Consider adding clearer labels for checkbox fields

The checkbox field for payment insurance has an empty title but uses the label from options. For better accessibility and UX, consider adding a descriptive title.

buildCheckboxField({
  id: 'rentalAmount.isPaymentInsuranceRequired',
- title: '',
+ title: rentalAmount.paymentInsuranceTitle,
  options: [
    {
      value: AnswerOptions.YES,
      label: rentalAmount.paymentInsuranceRequiredLabel,
    },
  ],
}),
libs/application/templates/rental-agreement/src/forms/rentalHousing/rentalHousingPropertyInfo.ts (1)

144-150: Simplify condition logic

The condition function can be simplified for better readability and maintainability.

condition: (answers) => {
-  const { propertyClassOptions } = getApplicationAnswers(answers)
-  return (
-    propertyClassOptions === RentalHousingCategoryClass.SPECIAL_GROUPS
-  )
+  return getApplicationAnswers(answers).propertyClassOptions === RentalHousingCategoryClass.SPECIAL_GROUPS
},
libs/application/templates/rental-agreement/src/lib/dataSchema.ts (5)

289-305: Use optional chaining for cleaner code

The isDefiniteChecked condition can be simplified with optional chaining.

- const isDefiniteChecked = data.isDefinite && data.isDefinite.includes(TRUE)
+ const isDefiniteChecked = data.isDefinite?.includes(TRUE)
🧰 Tools
🪛 Biome (1.9.4)

[error] 289-289: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


348-358: Use optional chaining for validation conditions

The conditional check can be simplified with optional chaining.

if (
-  data.paymentDateOptions &&
-  data.paymentDateOptions.includes(RentalAmountPaymentDateOptions.OTHER) &&
+  data.paymentDateOptions?.includes(RentalAmountPaymentDateOptions.OTHER) &&
  !data.paymentDateOther?.trim().length
)
🧰 Tools
🪛 Biome (1.9.4)

[error] 348-349: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


363-403: Simplify conditional checks with optional chaining

The validation for paymentMethodNationalId and paymentMethodBankAccountNumber can be simplified.

- if (
-   data.paymentMethodNationalId &&
-   data.paymentMethodNationalId?.trim().length &&
-   !kennitala.isValid(data.paymentMethodNationalId)
- ) {
+ if (
+   data.paymentMethodNationalId?.trim().length &&
+   !kennitala.isValid(data.paymentMethodNationalId)
+ ) {

Apply similar refactoring to other conditions in this section.

🧰 Tools
🪛 Biome (1.9.4)

[error] 372-373: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 392-393: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


438-452: Consider edge cases in property size validation

The property size validation doesn't handle the case where propertySize might be undefined or an empty string before the replacement operation. Consider adding a fallback.

- const propertySizeString = data.propertySize?.replace(',', '.') || ''
+ const propertySizeString = data.propertySize ? data.propertySize.replace(',', '.') : '0'

27-33: Utilize built-in Math functions instead of custom check

The checkIfNegative function can be simplified using built-in Math functions or direct comparison.

- const checkIfNegative = (inputNumber: string) => {
-   if (Number(inputNumber) < 0) {
-     return false
-   } else {
-     return true
-   }
- }
+ const checkIfNegative = (inputNumber: string) => Number(inputNumber) >= 0
libs/application/templates/rental-agreement/src/lib/types.ts (1)

13-66: Consolidate common property fields.
Multiple interfaces (StadfangProps, FasteignByStadfangNrProps, etc.) share fields like stadfang_nr, landeign_nr, postnumer. Consider extracting common fields into a shared base interface for easier maintainability and reusability.

libs/application/templates/rental-agreement/src/fields/PropertySearch/propertyData.ts (3)

1-243: Avoid hard-coding large datasets in source code.
The stadfangData array is quite extensive. For better maintainability and to reduce bundle size, consider fetching it from an external API or loading it from a static JSON file instead of embedding it in code.


245-715: Refactor repeated fields in fasteignByStadfangNrData.
Many objects share the same structure. If possible, break this data into separate definitions or consider a single typed structure to reduce duplication.


717-971: Validate or mock the large property data set.
While this is helpful for local testing, ensure this data aligns with production-ready APIs, or consider mocking it in your tests rather than committing large, potentially outdated static data.

libs/application/templates/rental-agreement/src/fields/PropertySearch/propertySearch.css.ts (2)

6-13: Extract color tokens.
Consider referencing design system tokens or a shared theme for the border and borderRadius values to ensure consistent styling across the app and facilitate future theming.


60-71: Use a design system or transitions variable.
The inline transition: 'all 0.3s ease-in-out' and hard-coded background color can be replaced by a design system variable or an existing shared transition style, if available, for consistency.

libs/application/templates/rental-agreement/src/lib/constants.ts (3)

6-6: Anticipate more events in Events type.
While SUBMIT and EDIT might suffice now, plan for future expansions such as REJECT or APPROVE to avoid frequent refactoring.


22-35: Ensure route names align with app conventions.
Some routes use dot notation (registerProperty.info), others do not. Standardizing these patterns can improve developer clarity and reduce potential routing confusion.


110-116: Document the pruneAfterDays function.
This life cycle logic is crucial. Provide a short comment explaining the rationale behind pruning and when it should be used, to assist other developers.

libs/application/templates/rental-agreement/src/lib/utils.ts (2)

53-54: Enhance formatCurrency function to handle non-numeric inputs.

The current implementation assumes the input is always a valid numeric string and doesn't handle potential errors.

-export const formatCurrency = (answer: string) =>
-  answer.replace(/\B(?=(\d{3})+(?!\d))/g, '.') + ' ISK'
+export const formatCurrency = (answer: string) => {
+  // Ensure we're working with a numeric string
+  if (!answer || isNaN(Number(answer))) {
+    return '0 ISK';
+  }
+  return answer.replace(/\B(?=(\d{3})+(?!\d))/g, '.') + ' ISK';
+}

289-298: Fix inconsistent naming pattern for getUserRoleOptions.

Unlike other option getters that are functions, getUserRoleOptions is exported as a constant array. This breaks the naming convention established by the other functions.

-export const getUserRoleOptions = [
+export const getUserRoleOptions = () => [
  {
    label: m.userRole.landlordOptionLabel,
    value: UserRole.LANDLORD,
  },
  {
    label: m.userRole.tenantOptionLabel,
    value: UserRole.TENANT,
  },
]
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4769afa and 4f9164c.

📒 Files selected for processing (18)
  • libs/application/templates/rental-agreement/src/assets/IconCircleClose.tsx (1 hunks)
  • libs/application/templates/rental-agreement/src/assets/IconCircleOpen.tsx (1 hunks)
  • libs/application/templates/rental-agreement/src/fields/PropertySearch/index.tsx (1 hunks)
  • libs/application/templates/rental-agreement/src/fields/PropertySearch/propertyData.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/fields/PropertySearch/propertySearch.css.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/fields/Summary/PropertyInfoSummary.tsx (1 hunks)
  • libs/application/templates/rental-agreement/src/fields/Summary/RentalInfoSummary.tsx (1 hunks)
  • libs/application/templates/rental-agreement/src/forms/rentalHousing/rentalHousingCondition.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/forms/rentalHousing/rentalHousingPropertyInfo.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodAmount.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodDetails.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodOtherFees.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodSecurityDeposit.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/lib/constants.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/lib/dataSchema.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/lib/messages/housing/registerProperty.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/lib/types.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/lib/utils.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • libs/application/templates/rental-agreement/src/assets/IconCircleOpen.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`libs/**/*`: "Confirm that the code adheres to the following...

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

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
  • libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodDetails.ts
  • libs/application/templates/rental-agreement/src/forms/rentalHousing/rentalHousingCondition.ts
  • libs/application/templates/rental-agreement/src/forms/rentalHousing/rentalHousingPropertyInfo.ts
  • libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodOtherFees.ts
  • libs/application/templates/rental-agreement/src/assets/IconCircleClose.tsx
  • libs/application/templates/rental-agreement/src/fields/Summary/PropertyInfoSummary.tsx
  • libs/application/templates/rental-agreement/src/lib/messages/housing/registerProperty.ts
  • libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodAmount.ts
  • libs/application/templates/rental-agreement/src/lib/types.ts
  • libs/application/templates/rental-agreement/src/fields/PropertySearch/propertySearch.css.ts
  • libs/application/templates/rental-agreement/src/fields/PropertySearch/propertyData.ts
  • libs/application/templates/rental-agreement/src/fields/Summary/RentalInfoSummary.tsx
  • libs/application/templates/rental-agreement/src/fields/PropertySearch/index.tsx
  • libs/application/templates/rental-agreement/src/lib/utils.ts
  • libs/application/templates/rental-agreement/src/lib/dataSchema.ts
  • libs/application/templates/rental-agreement/src/lib/constants.ts
  • libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodSecurityDeposit.ts
🪛 Biome (1.9.4)
libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodDetails.ts

[error] 19-19: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodAmount.ts

[error] 33-33: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

libs/application/templates/rental-agreement/src/fields/PropertySearch/index.tsx

[error] 221-226: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 391-392: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 438-439: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 441-563: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/application/templates/rental-agreement/src/lib/dataSchema.ts

[error] 289-289: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 348-349: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 372-373: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 392-393: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (20)
libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodSecurityDeposit.ts (1)

1-220: Well-structured and comprehensive security deposit form implementation.

This implementation demonstrates excellent form architecture with:

  1. Strong type safety and proper usage of TypeScript
  2. Comprehensive conditional rendering logic that creates a dynamic user experience
  3. Well-organized field grouping with appropriate clearing behavior
  4. Proper internationalization through message constants
  5. Thorough handling of all security deposit types with specific input fields for each

The form design follows best practices for complex form management, with conditions that appropriately show/hide fields based on user selections, making for an intuitive user flow.

libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodDetails.ts (1)

22-66: Well-structured rental period form section.

The RentalPeriodDetails implementation follows strong form design patterns with:

  1. Clean organization of date fields with proper validation
  2. Effective conditional rendering of the end date based on whether the period is definite
  3. Good use of the checkbox to control related fields
  4. Appropriate field clearing when selections change
  5. Proper internationalization through message constants

This creates an intuitive user experience for entering rental period information.

libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodOtherFees.ts (1)

1-186: Clean implementation with clear structure for future extensibility.

This form section is well-implemented with:

  1. Strong separation of concerns using helper functions for conditional logic
  2. Appropriate field types and validation for different data inputs
  3. Well-structured grouping of related fields
  4. Proper internationalization through message constants

The commented-out code with the TODO for "otherCosts" is handled appropriately - it's clearly marked for future implementation while not interfering with current functionality.

Once you're ready to implement the commented "otherCosts" section (lines 132-182), remember to:

  1. Uncomment the code
  2. Ensure all imports are available (particularly getValueViaPath and TRUE constant)
  3. Update any field identifiers if the data structure has changed
libs/application/templates/rental-agreement/src/forms/rentalHousing/rentalHousingCondition.ts (1)

13-76: Code looks well-structured and follows component architecture patterns.

The RentalHousingCondition form section is properly implemented using the building blocks from the application core. It includes appropriate conditional logic, field types, and organization.

Some observations:

  • Good use of conditional rendering for the inspector name field based on selection
  • Well-organized hierarchy with titles and descriptions
  • Appropriate field types for different input requirements
libs/application/templates/rental-agreement/src/fields/Summary/PropertyInfoSummary.tsx (2)

40-262: Well-structured component with good organization and helper functions.

The PropertyInfoSummary component follows good practices for React components with appropriate typing, helper functions, and conditional rendering. The layout is responsive using GridColumn components.


124-125: Placeholder value for number of rooms.

This line displays a placeholder "-" value, suggesting that real implementation for retrieving number of rooms is not yet complete.

Is this intentional as a placeholder for future implementation? If so, you might want to add a TODO comment to track this.

libs/application/templates/rental-agreement/src/lib/messages/housing/registerProperty.ts (2)

3-209: Well-structured internationalization messages.

The message definitions are well-organized into logical sections and provide comprehensive coverage for the property registration UI elements. The naming is consistent and descriptive.


1-209:

❓ Verification inconclusive

Ensure message IDs match implementation in the codebase.

The file contains a comprehensive set of internationalization messages. To maintain consistency, verify that all message IDs are correctly referenced in the components that use them.


🏁 Script executed:

#!/bin/bash
# Find all files that might be using these messages
echo "Checking for message imports and usages:"
rg -A 3 "import.*registerProperty" --type ts --type tsx
echo "Checking for message id usage patterns:"
rg "ra\.application:registerProperty\." --type ts --type tsx

Length of output: 356


Action Required: Further Manual Verification of Message ID Usage

The internationalization message IDs in the registerProperty messages file appear to be defined correctly. However, our initial automated search encountered file type recognition issues (specifically with tsx) that prevented a complete verification of their usage across the codebase.

Please re-run the following updated shell script to confirm that all message IDs (e.g., those starting with ra.application:registerProperty.) are consistently imported and referenced in your components:

#!/bin/bash
# Add file type definitions for TSX files
rg --type-add 'tsx:*.tsx'
echo "Checking for message imports and usages:"
rg -A 3 "import.*registerProperty" --type ts --type tsx
echo "Checking for message id usage patterns:"
rg "ra\.application:registerProperty\." --type ts --type tsx

Once you verify that the message IDs are being used correctly in the codebase, please update the review accordingly.

libs/application/templates/rental-agreement/src/fields/Summary/RentalInfoSummary.tsx (1)

196-267: Ensure correct handling for undefined securityDeposit in the component.

The component accesses answers.securityDeposit properties directly without checking if the object itself exists. This could cause runtime errors if the securityDeposit object is undefined.

Use optional chaining consistently throughout this section:

- answers.securityDeposit.securityType !==
+ answers.securityDeposit?.securityType !==
libs/application/templates/rental-agreement/src/fields/PropertySearch/index.tsx (1)

313-315: Add error handling for selection casting

The casting of selectedOption to StadfangProps could lead to runtime errors if the types don't match. Consider adding validation or safer type handling.

- setSelectedStadfang(
-   selectedOption as unknown as StadfangProps,
- )
+ // Ensure selectedOption has the required fields before casting
+ if (selectedOption && 'stadfang_nr' in selectedOption) {
+   setSelectedStadfang(selectedOption as unknown as StadfangProps)
+ }
libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodAmount.ts (1)

53-60: Add internationalization to error messages

Following the previous review comments, ensure error messages for validation are included in the message files for proper internationalization.

For example, add input validation error messages to the messages file and reference them here for consistent user experience across languages.

libs/application/templates/rental-agreement/src/lib/dataSchema.ts (2)

38-42: Fix validation logic for nationalId

The validation logic for nationalId appears to be correct now (after previous fixes), ensuring that only valid national IDs are accepted.


134-157: Consider enabling commented validation logic

There are several commented sections of validation logic that appear to be important for ensuring data integrity. Consider enabling these validations when the repeatable table functionality is fixed.

Plan a follow-up task to implement these validations to ensure that:

  1. The landlord table has at least one representative
  2. The landlord table has at least one non-representative
libs/application/templates/rental-agreement/src/lib/types.ts (3)

1-2: Well-structured import.
No concerns here. The import of NationalRegistryIndividual from @island.is/application/types is concise and correctly typed.


3-9: Validate presence of required fields for ExternalData.
Ensure that the upstream implementation always provides valid NationalRegistryIndividual data, especially regarding optional vs. required fields. If fields might be missing, consider making them optional or adding runtime checks.


11-11: Use an enum for StatusProvider.
This matches a previous recommendation to switch from union string literals to an enum for maintainability and clarity.

libs/application/templates/rental-agreement/src/fields/PropertySearch/propertySearch.css.ts (1)

1-5: Clear naming and consistent font sizes.
These constants are straightforward and correctly convey meaning for table cells.

libs/application/templates/rental-agreement/src/lib/utils.ts (3)

20-20: Consider using named imports for better tree-shaking.

Using wildcard imports like import * as m from './messages' can hinder tree-shaking. Named imports would make it clearer which messages are actually used and help with bundle optimization.

-import * as m from './messages'
+import { registerProperty, housingCondition, rentalAmount, securityDeposit, otherFees, userRole } from './messages'

110-123: Consider memoizing option getter functions for React components.

These functions create new arrays on each call, which can lead to unnecessary re-renders in React components.

Convert these functions into custom hooks that use React's useMemo:

import { useMemo } from 'react'

export const usePropertyTypeOptions = () => useMemo(() => [
  // options...
], [])

This ensures the array is only created once and reused across renders.

Also applies to: 125-134, 136-163, 165-174, 176-189, 191-204, 206-231, 233-250, 252-261, 263-272, 274-287


158-162: Address the TODO comment for employee housing option.

The code contains a commented-out option for employee housing with a TODO comment. Either implement this option or remove the comment to maintain cleaner code.

Could you check if the decision has been made regarding the employee housing option and either implement it or remove the comment?

Comment on lines +215 to +217
// TODO: Implement action to open file in new tab
window.open(file.key)
}}
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

Implement proper file opening mechanism.

The TODO comment indicates that the file opening mechanism is incomplete. Consider implementing a proper handler that ensures file URLs are properly sanitized and handled.

- // TODO: Implement action to open file in new tab
- window.open(file.key)
+ const fileUrl = new URL(file.key);
+ if (fileUrl.origin === window.location.origin || process.env.ALLOWED_FILE_DOMAINS?.includes(fileUrl.origin)) {
+   window.open(fileUrl.toString(), '_blank', 'noopener,noreferrer');
+ } else {
+   console.error('Attempted to open file from disallowed origin:', fileUrl.origin);
+ }
📝 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
// TODO: Implement action to open file in new tab
window.open(file.key)
}}
const fileUrl = new URL(file.key);
if (fileUrl.origin === window.location.origin || process.env.ALLOWED_FILE_DOMAINS?.includes(fileUrl.origin)) {
window.open(fileUrl.toString(), '_blank', 'noopener,noreferrer');
} else {
console.error('Attempted to open file from disallowed origin:', fileUrl.origin);
}
}}

Comment on lines +112 to +113
// TODO: Add correct value
<KeyValue
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

Complete the property address implementation.

There's a TODO comment indicating the property address value logic needs to be completed. This should be addressed before final implementation.

Comment on lines +134 to +186
const fetchPropertiesByStadfang = (query = '') => {
if (query.length < 2) {
console.log('No data - query too short')
return
}
setPending(true)

// TODO: Update when actual fetch is implemented
// fetch('http://localhost:3001/properties')
// .then((res) => res.json())
// .then((data: PropertyStadfang[]) => {
// setPending(false)
// const filteredData = data
// .filter((property: PropertyStadfang) =>
// property.stadfang.toLowerCase().includes(query.toLowerCase()),
// )
// .sort((a: PropertyStadfang, b: PropertyStadfang) =>
// a.stadfang.localeCompare(b.stadfang),
// )

// TODO: Update when actual fetch is implemented
setTimeout(() => {
const filteredData = stadfangData
.filter((item: StadfangProps) =>
item.stadfang.toLowerCase().includes(query.toLowerCase()),
)
.sort((a: StadfangProps, b: StadfangProps) =>
a.stadfang.localeCompare(b.stadfang),
)
.slice(0, 10)

setPending(false)

if (filteredData.length) {
setSearchOptions(
filteredData.map((property: StadfangProps) => ({
label: `${property.stadfang}, ${property.postnumer} ${property.sveitarfelag_nafn}`,
value: `${property.stadfang}, ${property.postnumer} ${property.sveitarfelag_nafn}`,
stadfang_nr: property.stadfang_nr,
stadfang: property.stadfang,
sveitarfelag_nafn: property.sveitarfelag_nafn,
sveitarfelag_nr: property.sveitarfelag_nr,
birting_sveitarfelag_nr: property.birting_sveitarfelag_nr,
postnumer: property.postnumer,
landeign_nr: property.landeign_nr,
stadvisir: property.stadvisir,
stadgreinir: property.stadgreinir,
vidskeyti: property.vidskeyti,
})),
)
}
}, 500)
}
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

Replace mock data implementation with actual API calls

The component currently uses mock data with setTimeout to simulate API calls. There are TODO comments indicating this needs to be replaced with actual fetch implementation.

Additionally, consider moving the API call logic to a separate service or custom hook to improve separation of concerns and testability.

Comment on lines +136 to +138
console.log('No data - query too short')
return
}
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

Remove console.log statements before production release

Console logs shouldn't remain in production code as they can impact performance and potentially expose sensitive information.

- console.log('No data - query too short')
+ // No data - query too short
📝 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
console.log('No data - query too short')
return
}
// No data - query too short
return
}

Comment on lines +76 to +106
console.log('searchresults: ', answers.registerProperty)

// const propertyUsageValue = getValueViaPath(
// answers,
// 'answers.registerProperty.searchresults?.adalmatseiningByFasteignNr[2522506].notkun',
// )
// const unitIdValue = getValueViaPath(
// answers,
// 'answers.registerProperty.searchresults?.propertiesByStadfangNr[0].merking',
// )
// const sizeValue = getValueViaPath(
// answers,
// 'answers.registerProperty.searchresults?.propertiesByStadfangNr[0].flatarmal',
// )
// const roomsValue = getValueViaPath(
// answers,
// 'answers.registerProperty.searchresults.numberOfRooms',
// )

return [
[
// propertyUsageValue ? propertyUsageValue : '--',
// unitIdValue ? unitIdValue : '--',
// sizeValue ? `${sizeValue} m²` : '--',
// roomsValue ? roomsValue : '--',
'Íbúð á hæð',
'010303',
'144 m²',
'3',
],
]
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

Remove console.log and uncomment dynamic data loading

The code includes a console.log statement and commented-out code for dynamic data loading. This should be removed or properly implemented before production.

- console.log('searchresults: ', answers.registerProperty)
+ // Get dynamic data from answers

- // const propertyUsageValue = getValueViaPath(
- //   answers,
- //   'answers.registerProperty.searchresults?.adalmatseiningByFasteignNr[2522506].notkun',
- // )
+ const propertyUsageValue = getValueViaPath(
+   answers,
+   'registerProperty.searchresults.adalmatseiningByFasteignNr[2522506].notkun',
+ )

// Continue uncommenting and fixing other property values

Also, hardcoded values should be replaced with dynamic data from the application state.

📝 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
console.log('searchresults: ', answers.registerProperty)
// const propertyUsageValue = getValueViaPath(
// answers,
// 'answers.registerProperty.searchresults?.adalmatseiningByFasteignNr[2522506].notkun',
// )
// const unitIdValue = getValueViaPath(
// answers,
// 'answers.registerProperty.searchresults?.propertiesByStadfangNr[0].merking',
// )
// const sizeValue = getValueViaPath(
// answers,
// 'answers.registerProperty.searchresults?.propertiesByStadfangNr[0].flatarmal',
// )
// const roomsValue = getValueViaPath(
// answers,
// 'answers.registerProperty.searchresults.numberOfRooms',
// )
return [
[
// propertyUsageValue ? propertyUsageValue : '--',
// unitIdValue ? unitIdValue : '--',
// sizeValue ? `${sizeValue} m²` : '--',
// roomsValue ? roomsValue : '--',
'Íbúð á hæð',
'010303',
'144 m²',
'3',
],
]
// Get dynamic data from answers
const propertyUsageValue = getValueViaPath(
answers,
'registerProperty.searchresults.adalmatseiningByFasteignNr[2522506].notkun',
)
// Continue uncommenting and fixing other property values
// const unitIdValue = getValueViaPath(
// answers,
// 'registerProperty.searchresults.propertiesByStadfangNr[0].merking',
// )
// const sizeValue = getValueViaPath(
// answers,
// 'registerProperty.searchresults.propertiesByStadfangNr[0].flatarmal',
// )
// const roomsValue = getValueViaPath(
// answers,
// 'registerProperty.searchresults.numberOfRooms',
// )
return [
[
// Replace the static values below with dynamic values, e.g.:
// propertyUsageValue ? propertyUsageValue : '--',
// unitIdValue ? unitIdValue : '--',
// sizeValue ? `${sizeValue} m²` : '--',
// roomsValue ? roomsValue : '--',
'Íbúð á hæð',
'010303',
'144 m²',
'3',
],
]

Comment on lines +34 to +38
export const formatDate = (date: string) => {
return format(parseISO(date), 'dd.MM.yyyy', {
locale: is,
})
}
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

Add error handling to formatDate function.

The function doesn't handle invalid date strings, which could lead to runtime errors.

export const formatDate = (date: string) => {
+  try {
+    const parsedDate = parseISO(date);
+    if (!isValid(parsedDate)) {
+      throw new Error('Invalid date');
+    }
    return format(parseISO(date), 'dd.MM.yyyy', {
      locale: is,
    })
+  } catch (error) {
+    console.error('Error formatting date:', error);
+    return date; // Or a fallback format
+  }
}

Don't forget to import isValid from date-fns at the top of the file:

import isValid from 'date-fns/isValid'

* Add validation in dataSchema for fire protection inputs.

* Add validation in dataSchema for other fees.

* Add validation for inputs based on payment method chosen.

* Update README.md with info about localization in Contentful.

* Update and add states. Add landlords and tenants as assignees.

* Update states and template flow. Cleanup and rename files.

* Update

* fix .github codeowners

* Update property search with new data structure. Add table with property search results.

* Filter assignees. Fix change button not appearig in summary.

* Fix lint warnings

* Fix unintentional moved folder. Delete unused data files.

* Update property search results. Add clearOnChange for some radio/checkbox/select forms.

* Remove unused data/schema, other minor lint fixes.

* Fix render of summary for assignee view.

* Fix view for summary applicant view after renaming
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (11)
libs/application/templates/rental-agreement/src/lib/RentalAgreementTemplate.ts (2)

43-111: States PREREQUISITES and DRAFT are well-structured.

The transitions, roles, and forms used for these states follow a clear pattern. The pruneAfterDays(30) specification is repeated multiple times across different states—consider extracting it into a shared constant for easier maintenance.


211-229: Remove console logs in production code.

Logging Assignees: ... may cause unnecessary console output. Switching to a proper logging mechanism or removing debug statements altogether helps maintain a clean production environment.

-    console.log('Assignees: ', assignees)
libs/application/templates/rental-agreement/src/fields/Summary/SummaryNoEdit.tsx (1)

18-18: Consider removing the debug console log.

The console.log('applicationAnswers', application.answers) line may clutter production logs or expose sensitive information. Use a logger with the appropriate log level or remove it if it's purely for local debugging.

-  console.log('applicationAnswers', application.answers)
libs/application/templates/rental-agreement/src/forms/summaryNoEditForm.ts (1)

12-53: Form structure looks good, but consider using translated title label

The form is well-structured using the form building utilities. It appropriately disables navigation buttons for a read-only view and organizes the content in a clean hierarchical structure.

I notice that the title of the custom field (line 45) is hardcoded as "Samantekt" rather than using an internationalized string from the messages. Consider using a message from the imported summary messages object for better localization support.

buildCustomField({
  id: 'SummaryNoEdit',
-  title: 'Samantekt',
+  title: summary.sectionName,
  component: 'SummaryNoEdit',
}),
libs/application/templates/rental-agreement/src/forms/summaryForm.ts (3)

15-17: Inconsistent form ID naming convention with SummaryNoEditForm

While the implementation is correct, I noticed that this form uses a camelCase ID (summaryForm) which is inconsistent with the PascalCase ID used in SummaryNoEditForm (SummaryNoEditForm). Consider standardizing the naming convention across all forms for better code consistency.

export const SummaryForm: Form = buildForm({
-  id: 'summaryForm',
+  id: 'SummaryForm',
  title: application.name,

47-50: Custom field ID conflicts with parent multiField ID

Both the custom field and its parent multiField have the same ID ('summary'), which could cause confusion or potential issues with DOM identification. Best practice is to use unique IDs for each field.

buildCustomField({
-  id: 'summary',
+  id: 'summaryEdit',
  title: 'Samantekt',
  component: 'SummaryEdit',
}),

47-50: Consider using localized title for consistency

Similar to the issue in SummaryNoEditForm, the title "Samantekt" is hardcoded rather than using the localization system. For better internationalization support, use the same approach consistently across forms.

buildCustomField({
  id: 'summary',
  title: 'Samantekt',
+  // Or use summary.sectionName for consistency
  component: 'SummaryEdit',
}),
libs/application/templates/rental-agreement/src/fields/Summary/summaryStyles.css.ts (1)

3-6: Use theme variables for consistent spacing

The spacing values (.75rem) are hardcoded. For better maintainability and consistency with the design system, consider using theme spacing variables.

import { style } from '@vanilla-extract/css'
+import { theme } from '@island.is/island-ui/theme'

export const summaryWrap = style({
-  paddingTop: '.75rem',
-  paddingBottom: '.75rem',
+  paddingTop: theme.spacing[2],
+  paddingBottom: theme.spacing[2],
})
libs/application/templates/rental-agreement/src/fields/Summary/SummaryEdit.tsx (3)

30-40: Consider abstracting validation logic for reusability

The validation logic for checking if specific sections are complete is scattered throughout the component. This could be extracted into separate helper functions for better readability and reusability.

+ const isComplete = (section: Record<string, any>, requiredFields: string[]) => {
+   return requiredFields.every(field => Boolean(section[field]));
+ }

- const isFireProtectionsPresent =
-   answers.fireProtections.smokeDetectors &&
-   answers.fireProtections.fireExtinguisher &&
-   answers.fireProtections.emergencyExits
+ const isFireProtectionsPresent = isComplete(
+   answers.fireProtections, 
+   ['smokeDetectors', 'fireExtinguisher', 'emergencyExits']
+ );

- const isConditionPresent = answers.condition.resultsDescription
+ const isConditionPresent = isComplete(
+   answers.condition,
+   ['resultsDescription']
+ );

- const isOtherFeesPresent =
-   answers.otherFees.electricityCost &&
-   answers.otherFees.heatingCost &&
-   answers.otherFees.housingFund
+ const isOtherFeesPresent = isComplete(
+   answers.otherFees,
+   ['electricityCost', 'heatingCost', 'housingFund']
+ );

125-127: Use optional chaining for cleaner syntax

The conditional check before calling setSubmitButtonDisabled can be simplified using optional chaining for more concise and readable code.

<Button
  onClick={() => {
-    setSubmitButtonDisabled &&
-      setSubmitButtonDisabled(false)
+    setSubmitButtonDisabled?.(false)
    goToScreen?.(condition.route)
  }}
  variant="text"
  size="small"
>
🧰 Tools
🪛 Biome (1.9.4)

[error] 125-126: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


112-142: Extract alert message to a separate component for clarity

The conditional rendering of the alert message is quite complex. For better readability and maintenance, consider extracting this logic into a separate component.

You could extract this into a MissingInformationAlert component:

type MissingInformationAlertProps = {
  conditions: Array<{
    isFilled: boolean;
    route: string;
    message: MessageDescriptor;
  }>;
  setSubmitButtonDisabled?: (disabled: boolean) => void;
  goToScreen?: (route: string) => void;
};

const MissingInformationAlert: FC<MissingInformationAlertProps> = ({
  conditions,
  setSubmitButtonDisabled,
  goToScreen,
}) => {
  const { formatMessage } = useLocale();
  const unfilledConditions = conditions.filter(
    (condition) => !condition.isFilled,
  );
  
  if (unfilledConditions.length === 0) {
    return null;
  }
  
  return (
    <Box marginTop={4} marginBottom={4}>
      <AlertMessage
        type="error"
        title={formatMessage(summary.alertMissingInfoTitle)}
        message={
          <BulletList>
            {unfilledConditions.map((condition, index) => (
              <Bullet key={`${index}_${condition.route}`}>
                <Button
                  onClick={() => {
                    setSubmitButtonDisabled?.(false)
                    goToScreen?.(condition.route)
                  }}
                  variant="text"
                  size="small"
                >
                  {formatMessage(condition.message)}
                </Button>
              </Bullet>
            ))}
          </BulletList>
        }
      />
    </Box>
  );
};

Then in your main component, you could simplify to:

<MissingInformationAlert 
  conditions={AlertMessageConditions}
  setSubmitButtonDisabled={setSubmitButtonDisabled}
  goToScreen={goToScreen}
/>
🧰 Tools
🪛 Biome (1.9.4)

[error] 125-126: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4f9164c and c9cb5ec.

📒 Files selected for processing (7)
  • libs/application/templates/rental-agreement/src/fields/Summary/SummaryEdit.tsx (1 hunks)
  • libs/application/templates/rental-agreement/src/fields/Summary/SummaryNoEdit.tsx (1 hunks)
  • libs/application/templates/rental-agreement/src/fields/Summary/summaryStyles.css.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/fields/index.tsx (1 hunks)
  • libs/application/templates/rental-agreement/src/forms/summaryForm.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/forms/summaryNoEditForm.ts (1 hunks)
  • libs/application/templates/rental-agreement/src/lib/RentalAgreementTemplate.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`libs/**/*`: "Confirm that the code adheres to the following...

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

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
  • libs/application/templates/rental-agreement/src/forms/summaryNoEditForm.ts
  • libs/application/templates/rental-agreement/src/fields/index.tsx
  • libs/application/templates/rental-agreement/src/forms/summaryForm.ts
  • libs/application/templates/rental-agreement/src/fields/Summary/SummaryNoEdit.tsx
  • libs/application/templates/rental-agreement/src/lib/RentalAgreementTemplate.ts
  • libs/application/templates/rental-agreement/src/fields/Summary/summaryStyles.css.ts
  • libs/application/templates/rental-agreement/src/fields/Summary/SummaryEdit.tsx
🪛 Biome (1.9.4)
libs/application/templates/rental-agreement/src/fields/Summary/SummaryEdit.tsx

[error] 125-126: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: prepare
  • GitHub Check: prepare / install
  • GitHub Check: GitGuardian Security Checks
🔇 Additional comments (7)
libs/application/templates/rental-agreement/src/lib/RentalAgreementTemplate.ts (4)

1-26: Good use of reusability and typed imports.

The initial imports and type definitions look aligned with best practices for a shared library, ensuring reusability, consistent TypeScript usage, and facilitating effective bundling.


28-42: Feature flag configuration seems properly integrated.

Defining featureFlag: Features.rentalAgreement and referencing ApplicationTypes.RENTAL_AGREEMENT is a clean approach for gating this functionality. This follows the recommended patterns for organizing feature flags in libs.


112-162: Verify entry and exit actions in SUMMARY state.

The usage of assignUsers on entry and clearAssignees on exit is logical if the application requires a fresh assignment approach for each entry into this state. Ensure this matches the intended user flow and that removing assignees upon exit does not discard needed data.


163-210: Check the self-transition under SIGNING.

Lines 182–183 show that a SUBMIT event transitions the state from SIGNING back to itself (SIGNING). If multiple signers are needed, this may be correct. Otherwise, consider introducing a new terminal or next state.

libs/application/templates/rental-agreement/src/fields/index.tsx (1)

1-3: Exports for field components look good.

Bundling these exports in a single index file promotes discoverability and encourages code reuse across the rental agreement application.

libs/application/templates/rental-agreement/src/fields/Summary/SummaryNoEdit.tsx (2)

1-16: Well-typed component properties.

Adopting FC<React.PropsWithChildren<FieldBaseProps>> for SummaryNoEdit aligns with recommended TypeScript patterns.


20-69: Layout and structure look consistent.

By neatly organizing multiple summary sections within a single container, you ensure a cohesive and maintainable approach to rendering read-only application details.

Comment on lines +31 to +37
borderBottom: '1px solid #F2F7FF',

selectors: {
'&:last-child': {
borderColor: '#CCDFFF',
},
},
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

Use theme colors instead of hardcoded values

Hardcoded color values (#F2F7FF, #CCDFFF) make it difficult to maintain consistent styling across the application. Use the theme colors from the island-ui theme for better maintainability and design consistency.

import { style } from '@vanilla-extract/css'
+import { theme } from '@island.is/island-ui/theme'

// ... other styles

export const divider = style({
  marginTop: '.75rem',
  marginBottom: '.75rem',
-  borderBottom: '1px solid #F2F7FF',
+  borderBottom: `1px solid ${theme.color.blue100}`,

  selectors: {
    '&:last-child': {
-      borderColor: '#CCDFFF',
+      borderColor: theme.color.blue200,
    },
  },
})
📝 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
borderBottom: '1px solid #F2F7FF',
selectors: {
'&:last-child': {
borderColor: '#CCDFFF',
},
},
import { style } from '@vanilla-extract/css'
import { theme } from '@island.is/island-ui/theme'
// ... other styles
export const divider = style({
marginTop: '.75rem',
marginBottom: '.75rem',
borderBottom: `1px solid ${theme.color.blue100}`,
selectors: {
'&:last-child': {
borderColor: theme.color.blue200,
},
},
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deploy-feature Deploys features to dev
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants