diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e65bec113f42..20fb631210df 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,5 @@ +import { application } from "express" + # Add new projects here. Project folders are usually owned by the team assigned. # Order is important; the last matching pattern takes the most precedence. @@ -126,6 +128,8 @@ codemagic.yaml /libs/api/domains/municipalities-financial-aid @island-is/kolibri-robin-hood /libs/clients/municipalities-financial-aid @island-is/kolibri-robin-hood +/libs/application/templates/rental-agreement/ @island-is/kolibri-kotid + /apps/download-service/ @island-is/hugsmidjan /apps/portals/my-pages*/ @island-is/hugsmidjan /apps/services/regulations-admin-backend/ @island-is/hugsmidjan diff --git a/libs/application/template-loader/src/lib/templateLoaders.ts b/libs/application/template-loader/src/lib/templateLoaders.ts index 57553b1b1de3..1d9989545323 100644 --- a/libs/application/template-loader/src/lib/templateLoaders.ts +++ b/libs/application/template-loader/src/lib/templateLoaders.ts @@ -209,6 +209,8 @@ const templates: Record Promise> = { import('@island.is/application/templates/new-primary-school'), [ApplicationTypes.MACHINE_REGISTRATION]: () => import('@island.is/application/templates/aosh/register-new-machine'), + [ApplicationTypes.RENTAL_AGREEMENT]: () => + import('@island.is/application/templates/rental-agreement'), [ApplicationTypes.SECONDARY_SCHOOL]: () => import('@island.is/application/templates/secondary-school'), } diff --git a/libs/application/templates/rental-agreement/.babelrc b/libs/application/templates/rental-agreement/.babelrc new file mode 100644 index 000000000000..e05c199e361e --- /dev/null +++ b/libs/application/templates/rental-agreement/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@nx/react/babel"], + "plugins": [] +} diff --git a/libs/application/templates/rental-agreement/.eslintrc.json b/libs/application/templates/rental-agreement/.eslintrc.json new file mode 100644 index 000000000000..97a68cca0c27 --- /dev/null +++ b/libs/application/templates/rental-agreement/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["plugin:@nx/react", "../../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "rules": {}, + "overrides": [ + { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": {} }, + { "files": ["*.ts", "*.tsx"], "rules": {} }, + { "files": ["*.js", "*.jsx"], "rules": {} } + ] +} diff --git a/libs/application/templates/rental-agreement/README.md b/libs/application/templates/rental-agreement/README.md new file mode 100644 index 000000000000..87aa9ab1e3ce --- /dev/null +++ b/libs/application/templates/rental-agreement/README.md @@ -0,0 +1,21 @@ +# application-templates-rental-agreement + +This library was generated with [Nx](https://nx.dev). + +### Localisation + +All localisation can be found on Contentful. + +- [Rental Agreement application translations](https://app.contentful.com/spaces/...) +- [Application system translations](https://app.contentful.com/spaces/...) + +{% hint style="warning" %} +When creating new text strings or making changes in the messages.ts file for the application, be sure to update Contentful by running this command: +`yarn nx run application-templates-rental-agreement:extract-strings` + +For more info see [message extraction](../../../localization/README.md#message-extraction). +{% endhint %} + +## Running unit tests + +Run `nx test application-templates-rental-agreement` to execute the unit tests via [Vitest](https://vitest.dev/). diff --git a/libs/application/templates/rental-agreement/babel-jest.config.json b/libs/application/templates/rental-agreement/babel-jest.config.json new file mode 100644 index 000000000000..bf04d5f81f7c --- /dev/null +++ b/libs/application/templates/rental-agreement/babel-jest.config.json @@ -0,0 +1,14 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "node": "current" + } + } + ], + "@babel/preset-typescript", + "@babel/preset-react" + ] +} diff --git a/libs/application/templates/rental-agreement/jest.config.ts b/libs/application/templates/rental-agreement/jest.config.ts new file mode 100644 index 000000000000..f6973d3decd4 --- /dev/null +++ b/libs/application/templates/rental-agreement/jest.config.ts @@ -0,0 +1,16 @@ +/* eslint-disable */ +export default { + preset: './jest.preset.js', + rootDir: '../../../..', + roots: [__dirname], + transform: { + '^.+\\.[tj]sx?$': [ + 'babel-jest', + { cwd: __dirname, configFile: `${__dirname}/babel-jest.config.json` }, + ], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: + '/coverage/libs/application/templates/rental-agreement', + displayName: 'application-templates-rental-agreement', +} diff --git a/libs/application/templates/rental-agreement/project.json b/libs/application/templates/rental-agreement/project.json new file mode 100644 index 000000000000..c299df3519c6 --- /dev/null +++ b/libs/application/templates/rental-agreement/project.json @@ -0,0 +1,28 @@ +{ + "name": "application-templates-rental-agreement", + "$schema": "../../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/application/templates/rental-agreement/src", + "projectType": "library", + "tags": ["scope:application-system", "lib:application-system"], + "generators": {}, + "targets": { + "lint": { + "executor": "@nx/eslint:lint" + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "jestConfig": "libs/application/templates/rental-agreement/jest.config.ts" + }, + "outputs": [ + "{workspaceRoot}/coverage/libs/application/templates/rental-agreement" + ] + }, + "extract-strings": { + "executor": "nx:run-commands", + "options": { + "command": "yarn ts-node -P libs/localization/tsconfig.lib.json libs/localization/scripts/extract libs/application/templates/rental-agreement/src/lib/messages.ts" + } + } + } +} diff --git a/libs/application/templates/rental-agreement/src/assets/Logo.tsx b/libs/application/templates/rental-agreement/src/assets/Logo.tsx new file mode 100644 index 000000000000..eadea3ee3aaa --- /dev/null +++ b/libs/application/templates/rental-agreement/src/assets/Logo.tsx @@ -0,0 +1,20 @@ +import React, { FC } from 'react' + +const Logo: FC> = () => ( + + + + + +) + +export default Logo diff --git a/libs/application/templates/rental-agreement/src/assets/RA.tsx b/libs/application/templates/rental-agreement/src/assets/RA.tsx new file mode 100644 index 000000000000..827196055f3f --- /dev/null +++ b/libs/application/templates/rental-agreement/src/assets/RA.tsx @@ -0,0 +1,3826 @@ +import React from 'react' + +const RA: React.FC> = () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default RA diff --git a/libs/application/templates/rental-agreement/src/dataProviders/index.ts b/libs/application/templates/rental-agreement/src/dataProviders/index.ts new file mode 100644 index 000000000000..800e4a6a51a9 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/dataProviders/index.ts @@ -0,0 +1,5 @@ +export { + UserProfileApi, + NationalRegistryUserApi, + NationalRegistrySpouseApi, +} from '@island.is/application/types' diff --git a/libs/application/templates/rental-agreement/src/fields/PropertySearch/index.tsx b/libs/application/templates/rental-agreement/src/fields/PropertySearch/index.tsx new file mode 100644 index 000000000000..2820792e839e --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/PropertySearch/index.tsx @@ -0,0 +1,193 @@ +import { FC, useEffect, useState } from 'react' +import { Controller, useFormContext } from 'react-hook-form' +import { CustomField, FieldBaseProps } from '@island.is/application/types' +import { + AsyncSearch, + AsyncSearchOption, + Box, + Text, +} from '@island.is/island-ui/core' + +import propertiesData from './properties' + +interface Props extends FieldBaseProps { + field: CustomField +} + +interface Unit { + unitId: string + markingNr: string + unitType: string + size: string + numberOfRooms: string +} + +interface PropertyId { + propertyId: string + marking: string + propertySize: string + units: Unit[] +} + +interface Property { + streetAddress: string + regionNumber: string + cityName: string + propertyIds: PropertyId[] +} + +export const PropertySearch: FC> = ({ + field, +}) => { + const { clearErrors, setValue, getValues } = useFormContext() + const { id } = field + const [query, setQuery] = useState('') + const [options, setOptions] = useState([]) + const [pending, setPending] = useState(false) + const [selectedProperty, setSelectedProperty] = useState< + | { + streetAddress: string + regionNumber: string + cityName: string + propertyIds: PropertyId[] + } + | undefined + >(undefined) + + useEffect(() => { + const storedValue = getValues(id) + if (storedValue) { + try { + setSelectedProperty(storedValue) + setQuery(storedValue.label) + } catch (error) { + console.error('Error parsing stored value:', error) + } + } + }, [getValues, id]) + + // Mock data - replace with actual fetch + + const fetchProperties = (query = '') => { + if (query.length < 2) { + console.log('No data') + return + } + setPending(true) + // fetch('http://localhost:3001/properties') + // .then((res) => res.json()) + // .then((data: Property[]) => { + // setPending(false) + // const filteredData = data + // .filter((property: Property) => + // property.streetAddress.toLowerCase().includes(query.toLowerCase()), + // ) + // .sort((a: Property, b: Property) => + // a.streetAddress.localeCompare(b.streetAddress), + // ) + // .slice(0, 10) + setTimeout(() => { + const filteredData = propertiesData + .filter((property: Property) => + property.streetAddress.toLowerCase().includes(query.toLowerCase()), + ) + .sort((a: Property, b: Property) => + a.streetAddress.localeCompare(b.streetAddress), + ) + .slice(0, 10) + + setPending(false) + + if (filteredData.length) { + setOptions( + filteredData.map((property: Property) => ({ + label: `${property.streetAddress}, ${property.regionNumber} ${property.cityName}`, + value: `${property.streetAddress}, ${property.regionNumber} ${property.cityName}`, + propertyIds: property.propertyIds, + propertyId: property.propertyIds[0].propertyId, + streetAddress: property.streetAddress, + regionNumber: property.regionNumber, + cityName: property.cityName, + marking: property.propertyIds[0].marking, + size: property.propertyIds[0].units[0].size, + numberOfRooms: property.propertyIds[0].units[0].numberOfRooms, + })), + ) + } + }, 500) + } + + return ( + <> + + { + return ( + { + clearErrors(id) + const selectedValue = + selection === null ? undefined : selection.value + const selectedOption = options.find( + (option) => option.value === selectedValue, + ) + setSelectedProperty(selectedOption as unknown as Property) + onChange(selection ? selection : undefined) + setValue(id, selection ? selection : undefined) + setQuery(selection ? selection.value : '') + }} + onInputValueChange={(newValue) => { + setQuery(newValue) + fetchProperties(newValue) + }} + loading={pending} + /> + ) + }} + /> + + + {selectedProperty && ( + + + Selected Property: + + + {selectedProperty.streetAddress}, {selectedProperty.regionNumber}{' '} + {selectedProperty.cityName} + + {selectedProperty.propertyIds.map((propertyId) => ( + + + {`Fasteignanúmer: ${propertyId.propertyId}, Merking: ${propertyId.marking}, Stærð fasteignar: ${propertyId.propertySize}m²`} + + {propertyId.units.map((unit) => ( + + {`Unit ID: ${unit.unitId}, Merking: ${unit.markingNr}, Stærð: ${unit.size}, Fjöldi herbergja: ${unit.numberOfRooms}`} + + ))} + + ))} + + )} + + ) +} diff --git a/libs/application/templates/rental-agreement/src/fields/PropertySearch/properties.ts b/libs/application/templates/rental-agreement/src/fields/PropertySearch/properties.ts new file mode 100644 index 000000000000..0c6247dcc1d1 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/PropertySearch/properties.ts @@ -0,0 +1,697 @@ +const propertiesData = [ + { + streetAddress: 'Jöklafold 5', + regionNumber: '112', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2042190', + marking: '040101', + propertySize: '175.6', + units: [ + { + unitId: '2042191', + markingNr: '0101', + unitType: 'Raðhús', + size: '175.6', + numberOfRooms: '7', + }, + ], + }, + ], + }, + { + streetAddress: 'Reyrengi 55', + regionNumber: '112', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2039395', + marking: '020101', + propertySize: '190.8', + units: [ + { + unitId: '2039395', + markingNr: '0101', + unitType: 'Einbýli', + size: '190.8', + numberOfRooms: '5', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 3b', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034939', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034939', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 1a', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034934', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034934', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 3a', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034972', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034972', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 3c', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034973', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034973', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 5a', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034974', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034974', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 5b', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034975', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034975', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 7a', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034988', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034988', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 7b', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034989', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034989', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 7c', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034990', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034990', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 7d', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034991', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034991', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 7e', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034992', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034992', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 9', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034993', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034993', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 11a', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034994', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034994', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 11b', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034995', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034995', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Hæðargarður 1b', + regionNumber: '108', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2034935', + marking: '020201', + propertySize: '86.2', + units: [ + { + unitId: '2034939', + markingNr: '0201', + unitType: 'Íbúð', + size: '86.2', + numberOfRooms: '3', + }, + ], + }, + ], + }, + { + streetAddress: 'Engimýri 3', + regionNumber: '210', + cityName: 'Garðabær', + propertyIds: [ + { + propertyId: '2069889', + marking: '010101', + propertySize: '244.9', + units: [ + { + unitId: '2069889', + markingNr: '0101', + unitType: 'Einbýli', + size: '244.9', + numberOfRooms: '6', + }, + ], + }, + ], + }, + { + streetAddress: 'Valshlíð 6', + regionNumber: '102', + cityName: 'Reykjavik', + propertyIds: [ + { + propertyId: '2507085', + marking: '020101', + propertySize: '67.3', + units: [ + { + unitId: '2383972', + markingNr: '0101', + unitType: 'Íbúð', + size: '67.3', + numberOfRooms: '2', + }, + { + unitId: '2374580', + markingNr: 'E035', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + { + propertyId: '2507086', + marking: '020102', + propertySize: '57.2', + units: [ + { + unitId: '2383973', + markingNr: '0102', + unitType: 'Íbúð', + size: '57.2', + numberOfRooms: '2', + }, + { + unitId: '2374581', + markingNr: 'E036', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + { + propertyId: '2507087', + marking: '020103', + propertySize: '117.3', + units: [ + { + unitId: '2383974', + markingNr: '0103', + unitType: 'Íbúð', + size: '117.3', + numberOfRooms: '3', + }, + { + unitId: '2374570', + markingNr: 'E025', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + { + propertyId: '2507404', + marking: '020201', + propertySize: '99.4', + units: [ + { + unitId: '2383978', + markingNr: '0201', + unitType: 'Íbúð', + size: '99.4', + numberOfRooms: '3', + }, + { + unitId: '2374582', + markingNr: 'E037', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + { + propertyId: '2507405', + marking: '020202', + propertySize: '54.3', + units: [ + { + unitId: '2383979', + markingNr: '0202', + unitType: 'Íbúð', + size: '54.3', + numberOfRooms: '2', + }, + { + unitId: '2374571', + markingNr: 'E026', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + { + propertyId: '2507406', + marking: '020203', + propertySize: '119.3', + units: [ + { + unitId: '2383980', + markingNr: '0203', + unitType: 'Íbúð', + size: '119.3', + numberOfRooms: '2', + }, + { + unitId: '2374583', + markingNr: 'E038', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + ], + }, + { + streetAddress: 'Valshlíð 2', + regionNumber: '102', + cityName: 'Reykjavik', + propertyIds: [ + { + propertyId: '2507424', + marking: '020101', + propertySize: '121.9', + units: [ + { + unitId: '2384031', + markingNr: '0101', + unitType: 'Íbúð', + size: '121.9', + numberOfRooms: '4', + }, + { + unitId: '2374651', + markingNr: 'N014', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + { + propertyId: '2507425', + marking: '020102', + propertySize: '103.1', + units: [ + { + unitId: '2384032', + markingNr: '0102', + unitType: 'Íbúð', + size: '103.1', + numberOfRooms: '4', + }, + { + unitId: '2374650', + markingNr: 'N013', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + { + propertyId: '2507426', + marking: '020103', + propertySize: '60.2', + units: [ + { + unitId: '2384033', + markingNr: '0103', + unitType: 'Íbúð', + size: '60.2', + numberOfRooms: '3', + }, + { + unitId: '2374649', + markingNr: 'N012', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + { + propertyId: '2507427', + marking: '020104', + propertySize: '77.5', + units: [ + { + unitId: '2384034', + markingNr: '0104', + unitType: 'Íbúð', + size: '77.5', + numberOfRooms: '3', + }, + { + unitId: '2374648', + markingNr: 'N011', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + { + propertyId: '2507432', + marking: '020202', + propertySize: '119.3', + units: [ + { + unitId: '2384039', + markingNr: '0201', + unitType: 'Íbúð', + size: '119.3', + numberOfRooms: '3', + }, + { + unitId: '2374670', + markingNr: 'N033', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + { + propertyId: '2507433', + propertySize: '104', + marking: '020202', + units: [ + { + unitId: '2384040', + markingNr: '0202', + unitType: 'Íbúð', + size: '104', + numberOfRooms: '2', + }, + { + unitId: '2374647', + markingNr: 'N010', + unitType: 'Stæði í bílageymslu', + size: '0', + numberOfRooms: '0', + }, + ], + }, + ], + }, + { + streetAddress: 'Eggertsgata 22', + regionNumber: '112', + cityName: 'Reykjavík', + propertyIds: [ + { + propertyId: '2507433', + marking: '160003', + propertySize: '952.8', + units: [ + { + unitId: '2215526', + markingNr: '0004', + unitType: 'íbúð', + size: '36.1', + numberOfRooms: '1', + }, + { + unitId: '2215527', + markingNr: '0005', + unitType: 'íbúð', + size: '52', + numberOfRooms: '2', + }, + { + unitId: '2215528', + markingNr: '0006', + unitType: 'íbúð', + size: '36.3', + numberOfRooms: '1', + }, + { + unitId: '2215529', + markingNr: '0007', + unitType: 'íbúð', + size: '52', + numberOfRooms: '2', + }, + { + unitId: '2215530', + markingNr: '0008', + unitType: 'íbúð', + size: '64', + numberOfRooms: '3', + }, + ], + }, + ], + }, +] + +export default propertiesData diff --git a/libs/application/templates/rental-agreement/src/fields/PropertySearch/propertySearch.css.ts b/libs/application/templates/rental-agreement/src/fields/PropertySearch/propertySearch.css.ts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/ApplicantsRepresentativesSummary.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/ApplicantsRepresentativesSummary.tsx new file mode 100644 index 000000000000..322132de0876 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/ApplicantsRepresentativesSummary.tsx @@ -0,0 +1,136 @@ +import { FC } from 'react' +import { GridColumn } from '@island.is/island-ui/core' +import { useLocale } from '@island.is/localization' +import { FieldBaseProps } from '@island.is/application/types' +import { RentalAgreement } from '../../lib/dataSchema' +import { summary } from '../../lib/messages' +import { Routes } from '../../lib/constants' +import { formatNationalId, formatPhoneNumber } from '../../lib/utils' +import { KeyValue } from './components/KeyValue' +import { SummaryCardRow } from './components/SummaryCardRow' +import { SummaryCard } from './components/SummaryCard' + +interface Props extends FieldBaseProps { + goToScreen?: (id: string) => void + landlordsRoute?: Routes + tenantsRoute?: Routes +} + +export const ApplicantsRepresentativesSummary: FC = ({ ...props }) => { + const { formatMessage } = useLocale() + const { application, goToScreen, landlordsRoute, tenantsRoute } = props + const answers = application.answers as RentalAgreement + + const landlordListHasRepresentatives = answers.landlordInfo.table.some( + (landlord) => + landlord.isRepresentative && landlord.isRepresentative.length > 0, + ) + const tenantListHasRepresentatives = answers.tenantInfo.table.some( + (tenant) => tenant.isRepresentative && tenant.isRepresentative.length > 0, + ) + + const landlordRepresentatives = answers.landlordInfo.table?.filter( + (landlordRep) => + landlordRep.isRepresentative && landlordRep.isRepresentative.length > 0, + ) + const tenantRepresentatives = answers.tenantInfo.table.filter( + (tenantRep) => + tenantRep.isRepresentative && tenantRep.isRepresentative.length > 0, + ) + + if (landlordListHasRepresentatives || tenantListHasRepresentatives) { + return ( + <> + {landlordListHasRepresentatives ? ( + + {landlordRepresentatives?.map((landlordRep) => { + return ( + + + + + + + + + + + + + ) + })} + + ) : ( + '' + )} + {tenantListHasRepresentatives ? ( + + {tenantRepresentatives.map((tenantRep) => { + return ( + + + + + + + + + + + + ) + })} + + ) : ( + '' + )} + + ) + } else { + return '' + } +} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/ApplicantsSummary.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/ApplicantsSummary.tsx new file mode 100644 index 000000000000..cbafb43d77b1 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/ApplicantsSummary.tsx @@ -0,0 +1,128 @@ +import { GridColumn } from '@island.is/island-ui/core' +import { useLocale } from '@island.is/localization' +import { RentalAgreement } from '../../lib/dataSchema' +import { Routes } from '../../lib/constants' +import { formatNationalId, formatPhoneNumber } from '../../lib/utils' +import { KeyValue } from './components/KeyValue' +import { SummaryCard } from './components/SummaryCard' +import { SummaryCardRow } from './components/SummaryCardRow' +import { summary } from '../../lib/messages' + +type Props = { + answers: RentalAgreement + goToScreen?: (id: string) => void + landlordsRoute?: Routes + tenantsRoute?: Routes +} + +export const ApplicantsSummary = ({ + answers, + goToScreen, + landlordsRoute, + tenantsRoute, +}: Props) => { + const { formatMessage } = useLocale() + + const landlordListWithoutRepresentatives = answers.landlordInfo.table.filter( + (landlord) => + !landlord.isRepresentative || landlord.isRepresentative.length === 0, + ) + + const tenantListWithoutRepresentatives = answers.tenantInfo.table.filter( + (tenant) => + !tenant.isRepresentative || tenant.isRepresentative.length === 0, + ) + + return ( + <> + 1 + ? formatMessage(summary.landlordsHeaderPlural) + : formatMessage(summary.landlordsHeader) + } + > + {landlordListWithoutRepresentatives?.map((landlord) => { + return ( + + + + + + + + + + + + ) + })} + + + 1 + ? formatMessage(summary.tenantsHeaderPlural) + : formatMessage(summary.tenantsHeader) + } + > + {tenantListWithoutRepresentatives.map((tenant) => { + return ( + + + + + + + + + + + + ) + })} + + + ) +} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/OtherFeesSummary.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/OtherFeesSummary.tsx new file mode 100644 index 000000000000..8cdd096d62a9 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/OtherFeesSummary.tsx @@ -0,0 +1,162 @@ +import { GridColumn } from '@island.is/island-ui/core' +import { useLocale } from '@island.is/localization' +import { RentalAgreement } from '../../lib/dataSchema' +import { OtherFeesPayeeOptions, Routes } from '../../lib/constants' +import { + formatCurrency, + formatDate, + getOtherFeesHousingFundPayeeOptions, + getOtherFeesPayeeOptions, +} from '../../lib/utils' +import { KeyValue } from './components/KeyValue' +import { SummaryCardRow } from './components/SummaryCardRow' +import { SummaryCard } from './components/SummaryCard' +import { summary } from '../../lib/messages' + +type Props = { + answers: RentalAgreement + goToScreen?: (id: string) => void + route?: Routes +} + +export const OtherFeesSummary = ({ answers, goToScreen, route }: Props) => { + const { formatMessage } = useLocale() + + const otherFeesPayee = (answer: string) => { + const options = getOtherFeesPayeeOptions() + const matchingOption = options.find((option) => option.value === answer) + return matchingOption ? matchingOption.label : '-' + } + + const otherFeesHousingFundPayee = (answer: string) => { + const options = getOtherFeesHousingFundPayeeOptions() + const matchingOption = options.find((option) => option.value === answer) + return matchingOption ? matchingOption.label : '-' + } + + const tenantPaysHouseFund = + answers.otherFees.housingFund === OtherFeesPayeeOptions.TENANT + const tenantPaysElectricity = + answers.otherFees.electricityCost === OtherFeesPayeeOptions.TENANT + const tenantPaysHeating = + answers.otherFees.heatingCost === OtherFeesPayeeOptions.TENANT + + return ( + + + + + + + + + + + + + + {tenantPaysElectricity && ( + + + + + + + + + + + + )} + + {tenantPaysHeating && ( + + + + + + + + + + + + )} + + {tenantPaysHouseFund && ( + + + + + + )} + + ) +} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/PropertyInfoSummary.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/PropertyInfoSummary.tsx new file mode 100644 index 000000000000..93ffbcc9297a --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/PropertyInfoSummary.tsx @@ -0,0 +1,248 @@ +import { + Box, + Button, + GridColumn, + Text, + UploadFile, +} from '@island.is/island-ui/core' +import { useLocale } from '@island.is/localization' +import { RentalAgreement } from '../../lib/dataSchema' +import { + RentalHousingCategoryClass, + RentalHousingConditionInspector, + Routes, +} from '../../lib/constants' +import { + getPropertyTypeOptions, + getPropertyClassOptions, + getPropertyClassGroupOptions, +} from '../../lib/utils' +import { KeyValue } from './components/KeyValue' +import { SummaryCardRow } from './components/SummaryCardRow' +import { SummaryCard } from './components/SummaryCard' + +import { fileLink, fileLinksList } from './summaryStyles.css' +import { summary } from '../../lib/messages' + +interface Props { + answers: RentalAgreement + goToScreen?: (id: string) => void + categoryRoute?: Routes + propertyInfoRoute?: Routes + propertyDescriptionRoute?: Routes + specialProvisionsRoute?: Routes + propertyConditionRoute?: Routes + fileUploadRoute?: Routes + fireProtectionsRoute?: Routes +} + +export const PropertyInfoSummary = ({ + answers, + goToScreen, + categoryRoute, + propertyInfoRoute, + propertyDescriptionRoute, + specialProvisionsRoute, + propertyConditionRoute, + fileUploadRoute, + fireProtectionsRoute, +}: Props) => { + const { formatMessage } = useLocale() + + const propertyType = (answer: string) => { + const options = getPropertyTypeOptions() + const matchingOption = options.find((option) => option.value === answer) + return matchingOption ? matchingOption.label : '-' + } + + const propertyClass = (answer: string) => { + const options = getPropertyClassOptions() + const matchingOption = options.find((option) => option.value === answer) + return matchingOption ? matchingOption.label : '-' + } + + const propertyClassGroup = (answer: string) => { + const options = getPropertyClassGroupOptions() + const matchingOption = options.find((option) => option.value === answer) + return matchingOption ? matchingOption.label : '-' + } + + const uploadFiles = answers.condition.resultsFiles as UploadFile[] + + return ( + + + + + + + + + {answers.registerProperty.categoryClass === + RentalHousingCategoryClass.SPECIAL_GROUPS && + answers.registerProperty.categoryClassGroup && ( + + + + )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {uploadFiles.length > 0 && ( + + + + + {formatMessage(summary.fileUploadLabel)} + +
    + {uploadFiles.map((file) => ( +
  • + +
  • + ))} +
+
+
+
+ )} + + + + + + + + + + + + + + + +
+ ) +} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/RentalInfoSummary.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/RentalInfoSummary.tsx new file mode 100644 index 000000000000..2fcdd860be14 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/RentalInfoSummary.tsx @@ -0,0 +1,298 @@ +import { GridColumn } from '@island.is/island-ui/core' +import { useLocale } from '@island.is/localization' +import { RentalAgreement } from '../../lib/dataSchema' +import { + AnswerOptions, + RentalPaymentMethodOptions, + Routes, + SecurityDepositAmountOptions, + SecurityDepositTypeOptions, + TRUE, +} from '../../lib/constants' +import { + formatBankInfo, + formatCurrency, + formatDate, + formatNationalId, + getPaymentMethodOptions, + getRentalAmountIndexTypes, + getRentalAmountPaymentDateOptions, + getSecurityAmountOptions, + getSecurityDepositTypeOptions, +} from '../../lib/utils' +import { SummaryCard } from './components/SummaryCard' +import { SummaryCardRow } from './components/SummaryCardRow' +import { KeyValue } from './components/KeyValue' +import { summary } from '../../lib/messages' + +type Props = { + answers: RentalAgreement + goToScreen?: (id: string) => void + rentalPeriodRoute?: Routes + rentalAmountRoute?: Routes + securityDepositRoute?: Routes +} + +export const RentalInfoSummary = ({ + answers, + goToScreen, + rentalAmountRoute, + rentalPeriodRoute, + securityDepositRoute, +}: Props) => { + const { formatMessage } = useLocale() + + const isSecurityDepositRequired = + answers.rentalAmount.isPaymentInsuranceRequired?.includes(AnswerOptions.YES) + const isSecurityDepositAmount = + answers.securityDeposit?.securityAmount || + answers.securityDeposit?.securityAmountOther + const isSecurityDepositType = answers.securityDeposit?.securityType + + const securityDepositType = (answer: string) => { + const options = getSecurityDepositTypeOptions() + const matchingOption = options.find((option) => option.value === answer) + return matchingOption ? matchingOption.label : '-' + } + + const paymentDate = (answer: string) => { + const options = getRentalAmountPaymentDateOptions() + const matchingOption = options.find((option) => option.value === answer) + return matchingOption ? matchingOption.label : '-' + } + + const indexType = (answer: string) => { + const options = getRentalAmountIndexTypes() + const matchingOption = options.find((option) => option.value === answer) + return matchingOption ? matchingOption.label : '-' + } + + const securityDepositAmount = (answer: string | undefined) => { + const options = getSecurityAmountOptions() + const rentalAmount = Number(answers.rentalAmount.amount) + const matchingOption = options.find((option) => option.value === answer) + + if (!matchingOption) { + return '-' + } + + switch (matchingOption.value) { + case SecurityDepositAmountOptions.ONE_MONTH: + return formatCurrency(answers.rentalAmount.amount) + case SecurityDepositAmountOptions.TWO_MONTHS: + return formatCurrency((rentalAmount * 2).toString()) + case SecurityDepositAmountOptions.THREE_MONTHS: + return formatCurrency((rentalAmount * 3).toString()) + case SecurityDepositAmountOptions.OTHER: + return answers.securityDeposit.securityAmountOther + ? formatCurrency(answers.securityDeposit.securityAmountOther) + : '-' + default: + return '-' + } + } + + const paymentMethodType = (answer: string) => { + const options = getPaymentMethodOptions() + const matchingOption = options.find((option) => option.value === answer) + return matchingOption ? matchingOption.label : '-' + } + + return ( + + {/* Property Address */} + + + {answers.registerProperty.searchResults && ( + + )} + + + + {/* Rental period */} + + + + + + + + + + {/* Rental amount */} + + + + + + + + {answers.rentalAmount.isIndexConnected?.includes(TRUE) && + answers.rentalAmount.indexTypes && ( + + + + )} + + + {/* Security deposit */} + {isSecurityDepositRequired && ( + + + + + + + + {answers.securityDeposit.securityType !== + SecurityDepositTypeOptions.CAPITAL && ( + + {answers.securityDeposit.securityType === + SecurityDepositTypeOptions.BANK_GUARANTEE && ( + + )} + {answers.securityDeposit.securityType === + SecurityDepositTypeOptions.THIRD_PARTY_GUARANTEE && ( + + )} + {answers.securityDeposit.securityType === + SecurityDepositTypeOptions.INSURANCE_COMPANY && ( + + )} + {answers.securityDeposit.securityType === + SecurityDepositTypeOptions.MUTUAL_FUND && ( + + )} + {answers.securityDeposit.securityType === + SecurityDepositTypeOptions.OTHER && ( + + )} + + )} + + )} + + {/* Payment method */} + + + + + {answers.rentalAmount.paymentMethodOptions === + RentalPaymentMethodOptions.BANK_TRANSFER && ( + <> + + + + + + + + + )} + + + ) +} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/components/Divider.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/components/Divider.tsx new file mode 100644 index 000000000000..17bb9550fe2c --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/components/Divider.tsx @@ -0,0 +1,5 @@ +import { divider } from '../summaryStyles.css' + +export const Divider = () => { + return
+} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/components/KeyValue.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/components/KeyValue.tsx new file mode 100644 index 000000000000..73bd28c7fb42 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/components/KeyValue.tsx @@ -0,0 +1,71 @@ +import { Box, ResponsiveSpace, Text } from '@island.is/island-ui/core' +import { useLocale } from '@island.is/localization' +import { MessageDescriptor } from 'react-intl' + +type TextVariants = + | 'default' + | 'small' + | 'medium' + | 'h1' + | 'h2' + | 'h3' + | 'h4' + | 'h5' + | 'intro' + | 'eyebrow' + +type TextElements = + | 'h1' + | 'h2' + | 'h3' + | 'h4' + | 'h5' + | 'p' + | 'span' + | 'div' + | 'label' + | 'caption' + | 'pre' + +type Props = { + label: string | MessageDescriptor + value: string | MessageDescriptor + isTotal?: boolean + labelVariant?: TextVariants + labelAs?: TextElements + valueVariant?: TextVariants + valueAs?: TextElements + gap?: ResponsiveSpace +} + +export const KeyValue = ({ + label, + value, + isTotal = false, + labelVariant = 'small', + labelAs = 'label', + gap = 1, +}: Props) => { + const { formatMessage } = useLocale() + + return ( + + + {formatMessage(label)} + + + + {formatMessage(value)} + + + ) +} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/components/SummaryCard.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/components/SummaryCard.tsx new file mode 100644 index 000000000000..36329e891b67 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/components/SummaryCard.tsx @@ -0,0 +1,35 @@ +import { Box, Text, Tooltip } from '@island.is/island-ui/core' + +type Props = { + cardLabel?: string + tooltipText?: string + children: React.ReactNode + noBorder?: boolean +} + +export const SummaryCard = ({ + cardLabel, + tooltipText, + children, + noBorder = false, +}: Props) => { + return ( + + {cardLabel && ( + + {cardLabel} {tooltipText && } + + )} + + {children} + + + ) +} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/components/SummaryCardRow.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/components/SummaryCardRow.tsx new file mode 100644 index 000000000000..bae6b583d28a --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/components/SummaryCardRow.tsx @@ -0,0 +1,45 @@ +import { ReactNode } from 'react' +import { useLocale } from '@island.is/localization' +import { Button, GridRow } from '@island.is/island-ui/core' +import { summary } from '../../../lib/messages' +import { Routes } from '../../../lib/constants' +import { Divider } from './Divider' +import { gridRow, changeButton } from '../summaryStyles.css' + +interface SummaryCardProps { + children: ReactNode + editAction?: (id: string) => void + route?: Routes + isChangeButton?: boolean + isLast?: boolean +} + +export const SummaryCardRow = ({ + children, + isChangeButton = true, + editAction, + route, + isLast = false, +}: SummaryCardProps) => { + const { formatMessage } = useLocale() + + return ( + <> + + {children} + {isChangeButton && editAction && route && ( +
+ +
+ )} +
+ {!isLast && } + + ) +} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/components/SummarySection.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/components/SummarySection.tsx new file mode 100644 index 000000000000..82ca7b251597 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/components/SummarySection.tsx @@ -0,0 +1,35 @@ +import { Box, Text, Tooltip } from '@island.is/island-ui/core' + +type Props = { + sectionLabel?: string + tooltipText?: string + children: React.ReactNode + noBorder?: boolean +} + +export const SummarySection = ({ + sectionLabel, + tooltipText, + children, + noBorder = false, +}: Props) => { + return ( + + {sectionLabel && ( + + {sectionLabel} {tooltipText && } + + )} + + {children} + + + ) +} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/index.tsx b/libs/application/templates/rental-agreement/src/fields/Summary/index.tsx new file mode 100644 index 000000000000..89d88af9efdb --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/index.tsx @@ -0,0 +1,170 @@ +import { FC, useEffect } from 'react' +import { useLocale } from '@island.is/localization' +import { + ApplicationConfigurations, + FieldBaseProps, +} from '@island.is/application/types' +import { + AlertMessage, + Box, + Bullet, + BulletList, + Button, + Text, +} from '@island.is/island-ui/core' +import { CopyLink } from '@island.is/application/ui-components' +import { RentalAgreement } from '../../lib/dataSchema' +import { Routes } from '../../lib/constants' +import { ApplicantsRepresentativesSummary } from './ApplicantsRepresentativesSummary' +import { ApplicantsSummary } from './ApplicantsSummary' +import { OtherFeesSummary } from './OtherFeesSummary' +import { PropertyInfoSummary } from './PropertyInfoSummary' +import { RentalInfoSummary } from './RentalInfoSummary' +import { SummaryCard } from './components/SummaryCard' + +import { summaryWrap } from './summaryStyles.css' +import { summary } from '../../lib/messages' + +export const Summary: FC> = ({ + ...props +}) => { + const { application, field, goToScreen, setSubmitButtonDisabled } = props + const { formatMessage } = useLocale() + + const answers = application.answers as RentalAgreement + + const isFireProtectionsPresent = + answers.fireProtections.smokeDetectors && + answers.fireProtections.fireExtinguisher && + answers.fireProtections.emergencyExits + + const isConditionPresent = answers.condition.resultsDescription + + const isOtherFeesPresent = + answers.otherFees.electricityCost && + answers.otherFees.heatingCost && + answers.otherFees.housingFund + + const AlertMessageConditions = [ + { + isFilled: isFireProtectionsPresent, + route: Routes.FIREPROTECTIONS, + message: summary.alertMissingInfoFireProtections, + }, + { + isFilled: isConditionPresent, + route: Routes.CONDITION, + message: summary.alertMissingInfoCondition, + }, + { + isFilled: isOtherFeesPresent, + route: Routes.OTHERFEES, + message: summary.alertMissingInfoOtherFees, + }, + ] + + const unfilledConditions = AlertMessageConditions.filter( + (condition) => !condition.isFilled, + ) + + useEffect(() => { + if (unfilledConditions && unfilledConditions.length > 0) { + setSubmitButtonDisabled && setSubmitButtonDisabled(true) + } else { + setSubmitButtonDisabled && setSubmitButtonDisabled(false) + } + + return () => { + setSubmitButtonDisabled && setSubmitButtonDisabled(false) + } + }, [unfilledConditions, setSubmitButtonDisabled]) + + return ( + + + + {formatMessage(summary.pageTitle)} + + {formatMessage(summary.pageDescription)} + + + + + + + + + + + {!isFireProtectionsPresent || + !isConditionPresent || + !isOtherFeesPresent ? ( + + + {unfilledConditions.map((condition, index) => ( + + + + ))} + + } + /> + + ) : ( + '' + )} + + ) +} diff --git a/libs/application/templates/rental-agreement/src/fields/Summary/summaryStyles.css.ts b/libs/application/templates/rental-agreement/src/fields/Summary/summaryStyles.css.ts new file mode 100644 index 000000000000..0e8d8c39ec53 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/Summary/summaryStyles.css.ts @@ -0,0 +1,47 @@ +import { style } from '@vanilla-extract/css' + +export const summaryWrap = style({ + paddingTop: '.75rem', + paddingBottom: '.75rem', +}) + +export const summaryNoBorder = style({ + border: 'none', + padding: '0', +}) + +export const gridRow = style({ + position: 'relative', + display: 'flex', + paddingRight: '100px', +}) + +export const divider = style({ + marginTop: '.75rem', + marginBottom: '.75rem', + borderBottom: '1px solid #F2F7FF', + + selectors: { + '&:last-child': { + display: 'none', + }, + }, +}) + +export const changeButton = style({ + position: 'absolute', + top: '18px', + right: '12px', +}) + +export const fileLinksList = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + gap: '.4rem', + paddingTop: '.4rem', +}) + +export const fileLink = style({ + fontSize: '.8rem', +}) diff --git a/libs/application/templates/rental-agreement/src/fields/index.tsx b/libs/application/templates/rental-agreement/src/fields/index.tsx new file mode 100644 index 000000000000..2d8935ea98f0 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/fields/index.tsx @@ -0,0 +1,2 @@ +export { PropertySearch } from './PropertySearch' +export { Summary } from './Summary' diff --git a/libs/application/templates/rental-agreement/src/forms/RentalHousingInfo.ts b/libs/application/templates/rental-agreement/src/forms/RentalHousingInfo.ts new file mode 100644 index 000000000000..d1e3e29fd484 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/RentalHousingInfo.ts @@ -0,0 +1,22 @@ +import { buildSection } from '@island.is/application/core' +import { RentalHousingPropertyInfo } from './rentalHousingInfo/rentalHousingPropertyInfo' +import { RentalHousingLandlordInfo } from './rentalHousingInfo/rentalHousingLandlordInfo' +import { RentalHousingTenantInfo } from './rentalHousingInfo/rentalHousingTenantInfo' +import { RentalHousingSpecialProvisions } from './rentalHousingInfo/rentalHousingSpecialProvisions' +import { RentalHousingCondition } from './rentalHousingInfo/rentalHousingCondition' +import { RentalHousingFireProtections } from './rentalHousingInfo/rentalHousingFireProtections' + +import { application } from '../lib/messages' + +export const RentalHousingInfo = buildSection({ + id: 'rentalHousingInfo', + title: application.housingSectionName, + children: [ + RentalHousingLandlordInfo, + RentalHousingTenantInfo, + RentalHousingPropertyInfo, + RentalHousingSpecialProvisions, + RentalHousingCondition, + RentalHousingFireProtections, + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/prerequisites/externalData.ts b/libs/application/templates/rental-agreement/src/forms/prerequisites/externalData.ts new file mode 100644 index 000000000000..1a4959da219c --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/prerequisites/externalData.ts @@ -0,0 +1,46 @@ +import { + buildDataProviderItem, + buildExternalDataProvider, + buildSection, + buildSubmitField, +} from '@island.is/application/core' +import { DefaultEvents } from '@island.is/application/types' +import { UserProfileApi, NationalRegistryUserApi } from '../../dataProviders' +import { prerequisites } from '../../lib/messages' + +export const externalData = buildSection({ + id: 'externalData', + title: prerequisites.externalData.sectionTitle, + children: [ + buildExternalDataProvider({ + id: 'approveExternalData', + title: prerequisites.externalData.pageTitle, + subTitle: prerequisites.externalData.subTitle, + checkboxLabel: prerequisites.externalData.checkboxLabel, + submitField: buildSubmitField({ + id: 'toDraft', + title: '', + refetchApplicationAfterSubmit: true, + actions: [ + { + event: DefaultEvents.SUBMIT, + name: 'Hefja umsókn', + type: 'primary', + }, + ], + }), + dataProviders: [ + buildDataProviderItem({ + provider: UserProfileApi, + title: prerequisites.externalData.currentApplicationTitle, + subTitle: prerequisites.externalData.currentApplicationSubTitle, + }), + buildDataProviderItem({ + provider: NationalRegistryUserApi, + title: prerequisites.externalData.nationalRegistryTitle, + subTitle: prerequisites.externalData.nationalRegistrySubTitle, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/prerequisites/intro.ts b/libs/application/templates/rental-agreement/src/forms/prerequisites/intro.ts new file mode 100644 index 000000000000..5919a49e463b --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/prerequisites/intro.ts @@ -0,0 +1,33 @@ +import { + buildDescriptionField, + buildMultiField, + buildSection, +} from '@island.is/application/core' + +import { prerequisites } from '../../lib/messages' + +const messages = prerequisites.intro + +export const intro = buildSection({ + id: 'prerequisitesIntro', + title: messages.subSectionTitle, + children: [ + buildMultiField({ + id: 'prerequisitesIntroTitle', + title: messages.pageTitle, + children: [ + buildDescriptionField({ + id: 'prerequisitesIntroText', + title: '', + description: messages.text, + marginBottom: 3, + }), + buildDescriptionField({ + id: 'prerequisitesIntroBullets', + title: '', + description: messages.bullets, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/prerequisitesForm.ts b/libs/application/templates/rental-agreement/src/forms/prerequisitesForm.ts new file mode 100644 index 000000000000..75da69b6f6a4 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/prerequisitesForm.ts @@ -0,0 +1,17 @@ +import { buildForm } from '@island.is/application/core' +import { Form, FormModes } from '@island.is/application/types' +import { intro } from './prerequisites/intro' +import { externalData } from './prerequisites/externalData' +import Logo from '../assets/Logo' + +import { prerequisites } from '../lib/messages' + +export const PrerequisitesForm: Form = buildForm({ + id: 'PrerequisitesForm', + title: prerequisites.intro.sectionTitle, + logo: Logo, + mode: FormModes.NOT_STARTED, + renderLastScreenButton: true, + renderLastScreenBackButton: true, + children: [intro, externalData], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalAgreementForm.ts b/libs/application/templates/rental-agreement/src/forms/rentalAgreementForm.ts new file mode 100644 index 000000000000..a95d9defd0d6 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalAgreementForm.ts @@ -0,0 +1,21 @@ +import { buildForm } from '@island.is/application/core' +import { Form, FormModes } from '@island.is/application/types' + +import Logo from '../assets/Logo' +import { RentalHousingInfo } from './RentalHousingInfo' +import { RentalPeriod } from './rentalPeriod' +import { Summary } from './summary/summary' + +import { application } from '../lib/messages' +import { SignatureInfo } from './signatureInfo/signatureInfo' +import { Signing } from './signing/signing' + +export const RentalAgreementForm: Form = buildForm({ + id: 'RentalAgreementApplication', + title: application.name, + logo: Logo, + mode: FormModes.DRAFT, + renderLastScreenButton: true, + renderLastScreenBackButton: true, + children: [RentalHousingInfo, RentalPeriod, Summary, SignatureInfo, Signing], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingCondition.ts b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingCondition.ts new file mode 100644 index 000000000000..584c9dcac42e --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingCondition.ts @@ -0,0 +1,75 @@ +import { + buildSubSection, + buildMultiField, + buildRadioField, + buildDescriptionField, + buildTextField, + buildFileUploadField, +} from '@island.is/application/core' +import { getApplicationAnswers, getInspectorOptions } from '../../lib/utils' +import { RentalHousingConditionInspector, Routes } from '../../lib/constants' +import { housingCondition } from '../../lib/messages' + +export const RentalHousingCondition = buildSubSection({ + id: Routes.CONDITION, + title: housingCondition.subSectionName, + children: [ + buildMultiField({ + id: Routes.CONDITION, + title: housingCondition.pageTitle, + description: housingCondition.pageDescription, + children: [ + buildDescriptionField({ + id: 'condition.inspectorTitle', + title: housingCondition.inspectorTitle, + titleVariant: 'h3', + space: 1, + }), + buildRadioField({ + id: 'condition.inspector', + title: '', + description: housingCondition.inspectorDescription, + options: getInspectorOptions(), + defaultValue: RentalHousingConditionInspector.CONTRACT_PARTIES, + width: 'half', + }), + buildTextField({ + id: 'condition.inspectorName', + title: housingCondition.independentInspectorNameLabel, + placeholder: housingCondition.independentInspectorNamePlaceholder, + condition: (answers) => { + const { inspectorOptions } = getApplicationAnswers(answers) + return ( + inspectorOptions === + RentalHousingConditionInspector.INDEPENDENT_PARTY + ) + }, + required: true, + }), + buildDescriptionField({ + id: 'condition.resultsTitle', + title: housingCondition.inspectionResultsTitle, + titleVariant: 'h3', + space: 6, + }), + buildTextField({ + id: 'condition.resultsDescription', + title: housingCondition.inspectionResultsInputLabel, + description: housingCondition.inspectionResultsDescription, + placeholder: housingCondition.inspectionResultsInputPlaceholder, + variant: 'textarea', + rows: 8, + }), + buildFileUploadField({ + id: 'condition.resultsFiles', + title: housingCondition.fileUploadTitle, + uploadHeader: housingCondition.fileUploadTitle, + uploadDescription: housingCondition.fileUploadDescription, + uploadAccept: '.pdf, .doc, .docx, .rtf, .jpg, .jpeg, .png, .heic', + uploadMultiple: true, + forImageUpload: true, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingFireProtections.ts b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingFireProtections.ts new file mode 100644 index 000000000000..0fca33d94940 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingFireProtections.ts @@ -0,0 +1,68 @@ +import { + buildSubSection, + buildMultiField, + buildDescriptionField, + buildTextField, + buildHiddenInputWithWatchedValue, +} from '@island.is/application/core' +import { Routes } from '../../lib/constants' +import { housingFireProtections } from '../../lib/messages' + +export const RentalHousingFireProtections = buildSubSection({ + id: Routes.FIREPROTECTIONS, + title: housingFireProtections.subSectionName, + children: [ + buildMultiField({ + id: Routes.FIREPROTECTIONS, + title: housingFireProtections.pageTitle, + description: housingFireProtections.pageDescription, + children: [ + buildDescriptionField({ + id: 'fireProtections.smokeDetectorsFireExtinguisherRequirements', + title: '', + description: + housingFireProtections.smokeDetectorsFireExtinguisherRequirements, + space: 0, + }), + buildTextField({ + id: 'fireProtections.smokeDetectors', + title: housingFireProtections.smokeDetectorsLabel, + placeholder: '0', + width: 'half', + variant: 'number', + }), + buildTextField({ + id: 'fireProtections.fireExtinguisher', + title: housingFireProtections.fireExtinguisherLabel, + placeholder: '0', + width: 'half', + variant: 'number', + }), + buildDescriptionField({ + id: 'fireProtections.exitFireBlanketRequirements', + title: '', + description: housingFireProtections.exitFireBlanketRequirements, + space: 4, + }), + buildTextField({ + id: 'fireProtections.emergencyExits', + title: housingFireProtections.exitsLabel, + placeholder: '0', + width: 'half', + variant: 'number', + }), + buildTextField({ + id: 'fireProtections.fireBlanket', + title: housingFireProtections.fireBlanketLabel, + placeholder: '0', + width: 'half', + variant: 'number', + }), + buildHiddenInputWithWatchedValue({ + id: 'fireProtections.propertySize', + watchValue: 'registerProperty.size', + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingLandlordInfo.ts b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingLandlordInfo.ts new file mode 100644 index 000000000000..79f034d400d1 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingLandlordInfo.ts @@ -0,0 +1,81 @@ +import { + buildSubSection, + buildMultiField, + buildTableRepeaterField, +} from '@island.is/application/core' +import { formatNationalId, formatPhoneNumber } from '../../lib/utils' +import { IS_REPRESENTATIVE } from '../../lib/constants' +import { Routes } from '../../lib/constants' +import { landlordDetails } from '../../lib/messages' + +export const RentalHousingLandlordInfo = buildSubSection({ + id: Routes.LANDLORDINFORMATION, + title: landlordDetails.subSectionName, + children: [ + buildMultiField({ + id: Routes.LANDLORDINFORMATION, + title: landlordDetails.pageTitle, + description: landlordDetails.pageDescription, + children: [ + buildTableRepeaterField({ + id: 'landlordInfo.table', + title: '', + editField: true, + marginTop: 1, + maxRows: 10, + fields: { + nationalIdWithName: { + component: 'nationalIdWithName', + required: true, + searchCompanies: true, + }, + phone: { + component: 'phone', + required: true, + label: landlordDetails.phoneInputLabel, + enableCountrySelector: true, + width: 'half', + }, + email: { + component: 'input', + required: true, + label: landlordDetails.emailInputLabel, + type: 'email', + width: 'half', + }, + address: { + component: 'input', + required: true, + label: landlordDetails.addressInputLabel, + maxLength: 100, + }, + isRepresentative: { + component: 'checkbox', + large: true, + options: [ + { + label: landlordDetails.representativeLabel, + value: IS_REPRESENTATIVE, + }, + ], + }, + }, + table: { + format: { + name: (value) => value, + phone: (value) => value && formatPhoneNumber(value), + nationalId: (value) => value && formatNationalId(value), + }, + header: [ + landlordDetails.nameInputLabel, + landlordDetails.phoneInputLabel, + landlordDetails.nationalIdHeaderLabel, + landlordDetails.emailInputLabel, + ], + rows: ['name', 'phone', 'nationalId', 'email'], + }, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingPropertyInfo.ts b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingPropertyInfo.ts new file mode 100644 index 000000000000..e98618407f68 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingPropertyInfo.ts @@ -0,0 +1,150 @@ +import { + buildCustomField, + buildDescriptionField, + buildMultiField, + buildRadioField, + buildSelectField, + buildStaticTableField, + buildSubSection, + getValueViaPath, +} from '@island.is/application/core' +import { SubSection } from '@island.is/application/types' +import { + RentalHousingCategoryClass, + RentalHousingCategoryTypes, + Routes, +} from '../../lib/constants' +import { + getApplicationAnswers, + getPropertyTypeOptions, + getPropertyClassOptions, + getPropertyClassGroupOptions, +} from '../../lib/utils' +import { registerProperty } from '../../lib/messages' + +const messagesInfo = registerProperty.info +const messagesSummary = registerProperty.infoSummary +const messagesCategory = registerProperty.category + +export const RentalHousingPropertyInfo: SubSection = buildSubSection({ + id: Routes.PROPERTYINFORMATION, + title: registerProperty.subsection.name, + children: [ + buildMultiField({ + id: Routes.PROPERTYINFORMATION_SERCH, + title: messagesInfo.pageTitle, + description: messagesInfo.pageDescription, + children: [ + buildCustomField({ + id: 'registerProperty.searchresults', + title: '', + component: 'PropertySearch', + }), + ], + }), + + buildMultiField({ + id: 'registerProperty.summary', + title: '', + condition: (answers) => Boolean(answers.registerProperty), + children: [ + buildStaticTableField({ + title: messagesSummary.pageTitle, + description: messagesSummary.pageDescription, + header: [ + messagesSummary.tableHeaderPropertyId, + messagesSummary.tableHeaderAddress, + messagesSummary.tableHeaderUnitId, + messagesSummary.tableHeaderSize, + messagesSummary.tableHeaderNumOfRooms, + ], + rows({ answers }) { + const propertyId = getValueViaPath( + answers, + 'registerProperty.searchresults.propertyId', + ) + const address = getValueViaPath( + answers, + 'registerProperty.searchresults.streetAddress', + ) + const postalCode = getValueViaPath( + answers, + 'registerProperty.searchresults.regionNumber', + ) + const municipality = getValueViaPath( + answers, + 'registerProperty.searchresults.cityName', + ) + const unitId = getValueViaPath( + answers, + 'registerProperty.searchresults.marking', + ) + const size = getValueViaPath( + answers, + 'registerProperty.searchresults.size', + ) + const numOfRooms = getValueViaPath( + answers, + 'registerProperty.searchresults.numberOfRooms', + ) + return [ + [ + propertyId ? `F${propertyId}` : '--', + address + ? `${address}, ${postalCode && postalCode} ${ + municipality && municipality + }` + : '--', + unitId ? unitId : '--', + size ? `${size} m²` : '--', + numOfRooms ? numOfRooms : '--', + ], + ] + }, + }), + ], + }), + buildMultiField({ + id: Routes.PROPERTYCATEGORY, + title: messagesCategory.pageTitle, + description: messagesCategory.pageDescription, + children: [ + buildDescriptionField({ + id: 'registerProperty.categoryTitle', + title: messagesCategory.typeTitle, + titleVariant: 'h4', + }), + buildSelectField({ + id: 'registerProperty.categoryType', + title: messagesCategory.typeTitle, + description: messagesCategory.typeDescription, + options: getPropertyTypeOptions(), + defaultValue: RentalHousingCategoryTypes.ENTIRE_HOME, + required: true, + }), + buildRadioField({ + id: 'registerProperty.categoryClass', + title: messagesCategory.classTitle, + description: messagesCategory.classDescription, + options: getPropertyClassOptions(), + defaultValue: RentalHousingCategoryClass.GENERAL_MARKET, + required: true, + width: 'half', + space: 5, + }), + buildSelectField({ + id: 'registerProperty.categoryClassGroup', + title: messagesCategory.classGroupLabel, + placeholder: messagesCategory.classGroupPlaceholder, + condition: (answers) => { + const { propertyClassOptions } = getApplicationAnswers(answers) + return ( + propertyClassOptions === RentalHousingCategoryClass.SPECIAL_GROUPS + ) + }, + options: getPropertyClassGroupOptions(), + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingSpecialProvisions.ts b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingSpecialProvisions.ts new file mode 100644 index 000000000000..6ab6c7a26923 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingSpecialProvisions.ts @@ -0,0 +1,50 @@ +import { + buildSubSection, + buildMultiField, + buildDescriptionField, + buildTextField, +} from '@island.is/application/core' +import { Routes } from '../../lib/constants' +import { specialProvisions } from '../../lib/messages' + +export const RentalHousingSpecialProvisions = buildSubSection({ + id: Routes.SPECIALPROVISIONS, + title: specialProvisions.subsection.name, + children: [ + buildMultiField({ + id: Routes.SPECIALPROVISIONS, + title: specialProvisions.subsection.pageTitle, + description: specialProvisions.subsection.pageDescription, + children: [ + buildDescriptionField({ + id: 'specialProvisions.descriptionTitle', + title: specialProvisions.housingInfo.title, + titleTooltip: specialProvisions.housingInfo.tooltip, + titleVariant: 'h3', + }), + buildTextField({ + id: 'specialProvisions.descriptionInput', + title: specialProvisions.housingInfo.inputLabel, + maxLength: 1500, + placeholder: specialProvisions.housingInfo.inputPlaceholder, + variant: 'textarea', + rows: 8, + }), + buildDescriptionField({ + id: 'specialProvisions.rulesTitle', + title: specialProvisions.housingRules.title, + titleTooltip: specialProvisions.housingRules.tooltip, + titleVariant: 'h3', + marginTop: 6, + }), + buildTextField({ + id: 'specialProvisions.rulesInput', + title: specialProvisions.housingRules.inputLabel, + placeholder: specialProvisions.housingRules.inputPlaceholder, + variant: 'textarea', + rows: 8, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingTenantInfo.ts b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingTenantInfo.ts new file mode 100644 index 000000000000..2436b76dbc13 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingTenantInfo.ts @@ -0,0 +1,81 @@ +import { + buildSubSection, + buildMultiField, + buildTableRepeaterField, +} from '@island.is/application/core' +import { formatNationalId, formatPhoneNumber } from '../../lib/utils' +import { IS_REPRESENTATIVE } from '../../lib/constants' +import { Routes } from '../../lib/constants' +import { tenantDetails } from '../../lib/messages' + +export const RentalHousingTenantInfo = buildSubSection({ + id: Routes.TENANTINFORMATION, + title: tenantDetails.subSectionName, + children: [ + buildMultiField({ + id: Routes.TENANTINFORMATION, + title: tenantDetails.pageTitle, + description: tenantDetails.pageDescription, + children: [ + buildTableRepeaterField({ + id: 'tenantInfo.table', + title: '', + editField: true, + marginTop: 1, + fields: { + nationalIdWithName: { + component: 'nationalIdWithName', + required: true, + searchCompanies: true, + }, + phone: { + component: 'phone', + required: true, + label: tenantDetails.phoneInputLabel, + enableCountrySelector: true, + width: 'half', + }, + email: { + component: 'input', + required: true, + label: tenantDetails.emailInputLabel, + type: 'email', + width: 'half', + }, + address: { + component: 'input', + required: true, + label: tenantDetails.addressInputLabel, + maxLength: 100, + }, + isRepresentative: { + component: 'checkbox', + label: tenantDetails.representativeLabel, + large: true, + options: [ + { + label: tenantDetails.representativeLabel, + value: IS_REPRESENTATIVE, + }, + ], + }, + }, + table: { + format: { + name: (value) => value, + phone: (value) => value && formatPhoneNumber(value), + nationalId: (value) => value && formatNationalId(value), + }, + header: [ + tenantDetails.nameInputLabel, + tenantDetails.phoneInputLabel, + tenantDetails.nationalIdHeaderLabel, + tenantDetails.emailInputLabel, + ], + rows: ['name', 'phone', 'nationalId', 'email'], + }, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingUserRole.ts b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingUserRole.ts new file mode 100644 index 000000000000..6ccee848c559 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalHousingInfo/rentalHousingUserRole.ts @@ -0,0 +1,26 @@ +import { + buildSubSection, + buildMultiField, + buildRadioField, +} from '@island.is/application/core' +import { getUserRoleOptions } from '../../lib/utils' +import { userRole } from '../../lib/messages' + +export const RentalHousingUserRole = buildSubSection({ + id: 'userRole', + title: userRole.subSectionName, + children: [ + buildMultiField({ + id: 'userRole.multiField', + title: userRole.pageTitle, + description: userRole.pageDescription, + children: [ + buildRadioField({ + id: 'userRole.type', + title: '', + options: getUserRoleOptions, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalPeriod.ts b/libs/application/templates/rental-agreement/src/forms/rentalPeriod.ts new file mode 100644 index 000000000000..b9e908b45ccd --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalPeriod.ts @@ -0,0 +1,19 @@ +import { buildSection } from '@island.is/application/core' + +import { RentalPeriodDetails } from './rentalPeriod/rentalPeriodDetails' +import { RentalPeriodAmount } from './rentalPeriod/rentalPeriodAmount' +import { RentalPeriodSecurityDeposit } from './rentalPeriod/rentalPeriodSecurityDeposit' +import { RentalPeriodOtherFees } from './rentalPeriod/rentalPeriodOtherFees' + +import { application } from '../lib/messages' + +export const RentalPeriod = buildSection({ + id: 'rentalPeriod', + title: application.rentalPeriodSectionName, + children: [ + RentalPeriodDetails, + RentalPeriodAmount, + RentalPeriodSecurityDeposit, + RentalPeriodOtherFees, + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodAmount.ts b/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodAmount.ts new file mode 100644 index 000000000000..c330cfdcd496 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodAmount.ts @@ -0,0 +1,174 @@ +import { + buildSubSection, + buildMultiField, + buildTextField, + buildDescriptionField, + buildCheckboxField, + buildSelectField, + getValueViaPath, + buildHiddenInput, +} from '@island.is/application/core' +import { FormValue } from '@island.is/application/types' +import { + AnswerOptions, + RentalAmountIndexTypes, + RentalAmountPaymentDateOptions, + RentalPaymentMethodOptions, + Routes, + TRUE, +} from '../../lib/constants' +import { + getPaymentMethodOptions, + getRentalAmountIndexTypes, + getRentalAmountPaymentDateOptions, +} from '../../lib/utils' +import { rentalAmount } from '../../lib/messages' + +const rentalAmountConnectedToIndex = (answers: FormValue) => { + const isAmountConnectedToIndex = getValueViaPath( + answers, + 'rentalAmount.isIndexConnected', + [], + ) as string[] + return isAmountConnectedToIndex && isAmountConnectedToIndex.includes(TRUE) +} + +export const RentalPeriodAmount = buildSubSection({ + id: Routes.RENTALAMOUNT, + title: rentalAmount.subSectionName, + children: [ + buildMultiField({ + id: Routes.RENTALAMOUNT, + title: rentalAmount.pageTitle, + description: rentalAmount.pageDescription, + children: [ + buildDescriptionField({ + id: 'rentalAmount.detailsTitle', + title: rentalAmount.infoTitle, + titleVariant: 'h3', + space: 1, + }), + + // Monthly rental amount and indexation + buildTextField({ + id: 'rentalAmount.amount', + title: rentalAmount.inputLabel, + placeholder: rentalAmount.inputPlaceholder, + variant: 'currency', + maxLength: 15, + required: true, + }), + buildSelectField({ + id: 'rentalAmount.indexTypes', + title: rentalAmount.indexOptionsLabel, + options: getRentalAmountIndexTypes(), + defaultValue: RentalAmountIndexTypes.CONSUMER_PRICE_INDEX, + condition: rentalAmountConnectedToIndex, + }), + buildCheckboxField({ + id: 'rentalAmount.isIndexConnected', + title: '', + options: [ + { + value: TRUE, + label: rentalAmount.priceIndexLabel, + }, + ], + spacing: 0, + }), + + // Payment details + buildDescriptionField({ + id: 'rentalAmount.paymentDateDetails', + title: rentalAmount.paymentDateTitle, + titleVariant: 'h4', + description: rentalAmount.paymentDateDescription, + space: 6, + }), + buildSelectField({ + id: 'rentalAmount.paymentDateOptions', + title: rentalAmount.paymentDateOptionsLabel, + options: getRentalAmountPaymentDateOptions(), + defaultValue: RentalAmountPaymentDateOptions.FIRST_DAY, + }), + buildTextField({ + id: 'rentalAmount.paymentDateOther', + title: rentalAmount.paymentDateOtherOptionLabel, + placeholder: rentalAmount.paymentDateOtherOptionPlaceholder, + maxLength: 100, + condition: (answers) => + getValueViaPath(answers, 'rentalAmount.paymentDateOptions') === + RentalAmountPaymentDateOptions.OTHER, + }), + + // Payment method + buildDescriptionField({ + id: 'rentalAmount.paymentMethodTitle', + title: rentalAmount.paymentMethodTitle, + titleVariant: 'h4', + space: 6, + }), + buildSelectField({ + id: 'rentalAmount.paymentMethodOptions', + title: rentalAmount.paymentMethodOptionsLabel, + options: getPaymentMethodOptions(), + defaultValue: RentalPaymentMethodOptions.BANK_TRANSFER, + }), + buildTextField({ + id: 'rentalAmount.paymentMethodNationalId', + title: rentalAmount.paymentMethodNationalIdLabel, + format: '######-####', + width: 'half', + condition: (answers) => + getValueViaPath(answers, 'rentalAmount.paymentMethodOptions') === + RentalPaymentMethodOptions.BANK_TRANSFER, + }), + buildTextField({ + id: 'rentalAmount.paymentMethodBankAccountNumber', + title: rentalAmount.paymentMethodBankAccountNumberLabel, + format: '####-##-######', + width: 'half', + condition: (answers) => + getValueViaPath(answers, 'rentalAmount.paymentMethodOptions') === + RentalPaymentMethodOptions.BANK_TRANSFER, + }), + buildTextField({ + id: 'rentalAmount.paymentMethodOtherTextField', + title: rentalAmount.paymentMethodOtherTextFieldLabel, + maxLength: 50, + condition: (answers) => + getValueViaPath(answers, 'rentalAmount.paymentMethodOptions') === + RentalPaymentMethodOptions.OTHER, + }), + + // Payment insurance + buildDescriptionField({ + id: 'rentalAmount.paymentInsuranceTitle', + title: rentalAmount.paymentInsuranceTitle, + titleVariant: 'h4', + space: 6, + }), + buildCheckboxField({ + id: 'rentalAmount.isPaymentInsuranceRequired', + title: '', + options: [ + { + value: AnswerOptions.YES, + label: rentalAmount.paymentInsuranceRequiredLabel, + }, + ], + }), + buildHiddenInput({ + id: 'rentalAmount.paymentInsuranceDetails', + condition: (answers) => { + const checkbox = getValueViaPath>( + answers, + 'rentalAmount.isPaymentInsuranceRequired', + ) + return checkbox?.includes(AnswerOptions.YES) || false + }, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodDetails.ts b/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodDetails.ts new file mode 100644 index 000000000000..148523227e07 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodDetails.ts @@ -0,0 +1,65 @@ +import { + buildSubSection, + buildMultiField, + buildDescriptionField, + buildDateField, + buildCheckboxField, + getValueViaPath, +} from '@island.is/application/core' +import { FormValue } from '@island.is/application/types' +import { Routes, TRUE } from '../../lib/constants' +import { rentalPeriod } from '../../lib/messages' + +const rentalPeriodIsDefinite = (answers: FormValue) => { + const rentalPeriodDefinite = getValueViaPath( + answers, + 'rentalPeriod.isDefinite', + [], + ) as string[] + return rentalPeriodDefinite && rentalPeriodDefinite.includes(TRUE) +} + +export const RentalPeriodDetails = buildSubSection({ + id: Routes.RENTALPERIOD, + title: rentalPeriod.subSectionName, + children: [ + buildMultiField({ + id: Routes.RENTALPERIOD, + title: rentalPeriod.pageTitle, + description: rentalPeriod.pageDescription, + children: [ + buildDateField({ + id: 'rentalPeriod.startDate', + title: rentalPeriod.startDateTitle, + placeholder: rentalPeriod.startDatePlaceholder, + required: true, + }), + buildDateField({ + id: 'rentalPeriod.endDate', + title: rentalPeriod.endDateTitle, + placeholder: rentalPeriod.endDatePlaceholder, + required: true, + condition: rentalPeriodIsDefinite, + }), + buildCheckboxField({ + id: 'rentalPeriod.isDefinite', + title: '', + options: [ + { + value: TRUE, + label: rentalPeriod.rentalPeriodDefiniteLabel, + }, + ], + spacing: 0, + }), + buildDescriptionField({ + id: 'rentalPeriod.termination', + title: rentalPeriod.terminationLabel, + titleVariant: 'h3', + space: 3, + description: rentalPeriod.terminationDescription, + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodOtherFees.ts b/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodOtherFees.ts new file mode 100644 index 000000000000..76e57247b013 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodOtherFees.ts @@ -0,0 +1,175 @@ +import { + buildSubSection, + buildMultiField, + buildTextField, + buildRadioField, + buildDateField, +} from '@island.is/application/core' +import { FormValue } from '@island.is/application/types' +import { + getApplicationAnswers, + getOtherFeesHousingFundPayeeOptions, + getOtherFeesPayeeOptions, +} from '../../lib/utils' +import { OtherFeesPayeeOptions, Routes } from '../../lib/constants' +import { otherFees } from '../../lib/messages' + +const housingFundAmountPayedByTenant = (answers: FormValue) => { + const { otherFeesHousingFund } = getApplicationAnswers(answers) + return otherFeesHousingFund === OtherFeesPayeeOptions.TENANT +} + +const electricityCostPayedByTenant = (answers: FormValue) => { + const { otherFeesElectricityCost } = getApplicationAnswers(answers) + return otherFeesElectricityCost === OtherFeesPayeeOptions.TENANT +} + +const heatingCostPayedByTenant = (answers: FormValue) => { + const { otherFeesHeatingCost } = getApplicationAnswers(answers) + return otherFeesHeatingCost === OtherFeesPayeeOptions.TENANT +} + +export const RentalPeriodOtherFees = buildSubSection({ + id: Routes.OTHERFEES, + title: otherFees.subSectionName, + children: [ + buildMultiField({ + id: Routes.OTHERFEES, + title: otherFees.pageTitle, + description: otherFees.pageDescription, + children: [ + buildRadioField({ + id: 'otherFees.housingFund', + title: otherFees.housingFundTitle, + options: getOtherFeesHousingFundPayeeOptions, + width: 'half', + space: 1, + }), + buildTextField({ + id: 'otherFees.housingFundAmount', + title: otherFees.housingFundAmountLabel, + placeholder: otherFees.housingFundAmountPlaceholder, + variant: 'currency', + maxLength: 13, + condition: housingFundAmountPayedByTenant, + }), + + // Electricity cost fields + buildRadioField({ + id: 'otherFees.electricityCost', + title: otherFees.electricityCostTitle, + options: getOtherFeesPayeeOptions, + width: 'half', + space: 6, + }), + buildTextField({ + id: 'otherFees.electricityCostMeterNumber', + title: otherFees.electricityCostMeterNumberLabel, + placeholder: otherFees.electricityCostMeterNumberPlaceholder, + width: 'half', + maxLength: 20, + condition: electricityCostPayedByTenant, + }), + buildTextField({ + id: 'otherFees.electricityCostMeterStatus', + title: otherFees.electricityCostMeterStatusLabel, + placeholder: otherFees.electricityCostMeterStatusPlaceholder, + width: 'half', + maxLength: 10, + condition: electricityCostPayedByTenant, + }), + buildDateField({ + id: 'otherFees.electricityCostMeterStatusDate', + title: otherFees.electricityCostMeterStatusDateLabel, + placeholder: otherFees.electricityCostMeterStatusDatePlaceholder, + width: 'half', + condition: electricityCostPayedByTenant, + }), + + // Heating cost fields + buildRadioField({ + id: 'otherFees.heatingCost', + title: otherFees.heatingCostTitle, + options: getOtherFeesPayeeOptions, + width: 'half', + space: 6, + }), + buildTextField({ + id: 'otherFees.heatingCostMeterNumber', + title: otherFees.heatingCostMeterNumberLabel, + placeholder: otherFees.heatingCostMeterNumberPlaceholder, + width: 'half', + maxLength: 20, + condition: heatingCostPayedByTenant, + }), + buildTextField({ + id: 'otherFees.heatingCostMeterStatus', + title: otherFees.heatingCostMeterStatusLabel, + placeholder: otherFees.heatingCostMeterStatusPlaceholder, + width: 'half', + maxLength: 10, + condition: heatingCostPayedByTenant, + }), + buildDateField({ + id: 'otherFees.heatingCostMeterStatusDate', + title: otherFees.heatingCostMeterStatusDateLabel, + placeholder: otherFees.heatingCostMeterStatusDatePlaceholder, + width: 'half', + condition: heatingCostPayedByTenant, + }), + + // TODO: Add otherCosts fields when ready + // Other fees + // buildDescriptionField({ + // id: 'otherFees.otherCostsTitle', + // title: otherFees.otherCostsTitle, + // titleVariant: 'h4', + // space: 6, + // }), + // buildCheckboxField({ + // id: 'otherFees.otherCosts', + // title: '', + // options: [ + // { + // value: TRUE, + // label: otherFees.otherCostsLabel, + // }, + // ], + // spacing: 0, + // }), + // buildTextField({ + // id: 'otherFees.otherCostsDescription', + // title: otherFees.otherCostsDescriptionLabel, + // placeholder: otherFees.otherCostsDescriptionPlaceholder, + // width: 'half', + // condition: (answers) => { + // const otherFeesOtherCosts = getValueViaPath( + // answers, + // 'otherFees.otherCosts', + // [], + // ) as string[] + // return ( + // otherFeesOtherCosts && otherFeesOtherCosts.includes(TRUE) + // ) + // }, + // }), + // buildTextField({ + // id: 'otherFees.otherCostsAmount', + // title: otherFees.otherCostsAmountLabel, + // placeholder: otherFees.otherCostsAmountPlaceholder, + // width: 'half', + // condition: (answers) => { + // const otherFeesOtherCosts = getValueViaPath( + // answers, + // 'otherFees.otherCosts', + // [], + // ) as string[] + // return ( + // otherFeesOtherCosts && otherFeesOtherCosts.includes(TRUE) + // ) + // }, + // }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodSecurityDeposit.ts b/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodSecurityDeposit.ts new file mode 100644 index 000000000000..cffa03b5c42c --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/rentalPeriod/rentalPeriodSecurityDeposit.ts @@ -0,0 +1,213 @@ +import { + buildSubSection, + buildMultiField, + buildTextField, + buildSelectField, + buildDescriptionField, + buildAlertMessageField, + buildHiddenInputWithWatchedValue, + buildRadioField, + getValueViaPath, +} from '@island.is/application/core' +import { FormValue } from '@island.is/application/types' +import { + SecurityDepositTypeOptions, + SecurityDepositAmountOptions, + Routes, + AnswerOptions, +} from '../../lib/constants' +import { + getSecurityDepositTypeOptions, + getSecurityAmountOptions, +} from '../../lib/utils' +import { securityDeposit } from '../../lib/messages' + +export const RentalPeriodSecurityDeposit = buildSubSection({ + condition: (answers) => { + const securityDeposit = getValueViaPath>( + answers, + 'rentalAmount.isPaymentInsuranceRequired', + ) + return securityDeposit?.includes(AnswerOptions.YES) || false + }, + id: Routes.SECURITYDEPOSIT, + title: securityDeposit.subSectionName, + children: [ + buildMultiField({ + condition: (answers) => { + const securityDeposit = getValueViaPath>( + answers, + 'rentalAmount.isPaymentInsuranceRequired', + ) + return securityDeposit?.includes(AnswerOptions.YES) || false + }, + id: Routes.SECURITYDEPOSIT, + title: securityDeposit.pageTitle, + description: securityDeposit.pageDescription, + children: [ + buildDescriptionField({ + id: 'securityDeposit.TypeHeader', + title: securityDeposit.typeHeaderTitle, + titleTooltip: securityDeposit.typeHeaderToolTip, + titleVariant: 'h3', + }), + buildSelectField({ + id: 'securityDeposit.securityType', + title: securityDeposit.typeSelectionTitle, + options: getSecurityDepositTypeOptions, + placeholder: securityDeposit.typeSelectionPlaceholder, + }), + + // Tegund tryggingar: Bankaábyrgð + buildTextField({ + id: 'securityDeposit.bankGuaranteeInfo', + title: securityDeposit.bankGuaranteeInfoTitle, + placeholder: securityDeposit.bankGuaranteeInfoPlaceholder, + condition: (answers) => { + const securityDeposit = answers.securityDeposit as FormValue + return ( + securityDeposit && + Boolean(securityDeposit.securityType) && + securityDeposit.securityType === + SecurityDepositTypeOptions.BANK_GUARANTEE + ) + }, + }), + + // Tegund tryggingar: Tryggingarfé + buildDescriptionField({ + id: 'securityDeposit.typeCapitalInfo', + title: '', + description: securityDeposit.capitalBulletPoints, + condition: (answers) => { + const securityDeposit = answers.securityDeposit as FormValue + return ( + securityDeposit && + Boolean(securityDeposit.securityType) && + securityDeposit.securityType === + SecurityDepositTypeOptions.CAPITAL + ) + }, + space: 2, + }), + + // Tegund tryggingar: Sjálfskuldarábyrgð þriðja aðila + buildTextField({ + id: 'securityDeposit.thirdPartyGuaranteeInfo', + title: securityDeposit.thirdPartyGuaranteeInfoTitle, + placeholder: securityDeposit.thirdPartyGuaranteeInfoPlaceholder, + condition: (answers) => { + const securityDeposit = answers.securityDeposit as FormValue + return ( + securityDeposit && + Boolean(securityDeposit.securityType) && + securityDeposit.securityType === + SecurityDepositTypeOptions.THIRD_PARTY_GUARANTEE + ) + }, + }), + + // Tegund tryggingar: Leigugreiðslu- og viðskilnaðartrygging + buildTextField({ + id: 'securityDeposit.insuranceCompanyInfo', + title: securityDeposit.insuranceCompanyInfoTitle, + placeholder: securityDeposit.insuranceCompanyInfoPlaceholder, + condition: (answers) => { + const securityDeposit = answers.securityDeposit as FormValue + return ( + securityDeposit && + Boolean(securityDeposit.securityType) && + securityDeposit.securityType === + SecurityDepositTypeOptions.INSURANCE_COMPANY + ) + }, + }), + + // Tegund tryggingar: Gjald í samtryggingarsjóð leigusala + buildTextField({ + id: 'securityDeposit.mutualFundInfo', + title: securityDeposit.mutualFundInfoTitle, + placeholder: securityDeposit.mutualFundInfoPlaceholder, + condition: (answers) => { + const securityDeposit = answers.securityDeposit as FormValue + return ( + securityDeposit && + Boolean(securityDeposit.securityType) && + securityDeposit.securityType === + SecurityDepositTypeOptions.MUTUAL_FUND + ) + }, + }), + + // Tegund tryggingar: annað + buildTextField({ + id: 'securityDeposit.otherInfo', + title: securityDeposit.otherInfoTitle, + placeholder: securityDeposit.otherInfoPlaceholder, + condition: (answers) => { + const securityDeposit = answers.securityDeposit as FormValue + return ( + securityDeposit && + Boolean(securityDeposit.securityType) && + securityDeposit.securityType === SecurityDepositTypeOptions.OTHER + ) + }, + }), + buildRadioField({ + id: 'securityDeposit.securityAmount', + title: securityDeposit.amountRadioFieldTitle, + options: getSecurityAmountOptions, + width: 'half', + space: 3, + condition: (answers) => { + const securityDeposit = answers.securityDeposit as FormValue + return ( + !securityDeposit || + securityDeposit.securityType === undefined || + securityDeposit.securityType !== + SecurityDepositTypeOptions.MUTUAL_FUND + ) + }, + }), + + // Tegund tryggingar: Gjald í samtryggingarsjóð leigusala + buildAlertMessageField({ + id: 'securityDeposit.mutualFundAmountInfo', + title: securityDeposit.mutualFundAmountInfoTitle, + alertType: 'info', + message: securityDeposit.mutualFundAmountInfoMessage, + condition: (answers) => { + const securityDeposit = answers.securityDeposit as FormValue + return ( + securityDeposit && + Boolean(securityDeposit.securityType) && + securityDeposit.securityType === + SecurityDepositTypeOptions.MUTUAL_FUND + ) + }, + }), + buildTextField({ + id: 'securityDeposit.securityAmountOther', + title: securityDeposit.securityAmountOtherTitle, + placeholder: securityDeposit.securityAmountOtherPlaceholder, + variant: 'currency', + condition: (answers) => { + const securityDeposit = answers.securityDeposit as FormValue + + return ( + securityDeposit && + (securityDeposit.securityType === + SecurityDepositTypeOptions.MUTUAL_FUND || + securityDeposit.securityAmount === + SecurityDepositAmountOptions.OTHER) + ) + }, + }), + buildHiddenInputWithWatchedValue({ + id: 'securityDeposit.rentalAmount', + watchValue: 'rentalAmount.amount', + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/signatureInfo/signatureInfo.ts b/libs/application/templates/rental-agreement/src/forms/signatureInfo/signatureInfo.ts new file mode 100644 index 000000000000..bff296f42e4f --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/signatureInfo/signatureInfo.ts @@ -0,0 +1,90 @@ +import { + buildCheckboxField, + buildDescriptionField, + buildMultiField, + buildSection, + buildStaticTableField, + buildSubmitField, +} from '@island.is/application/core' +import { DefaultEvents } from '@island.is/application/types' +import { RentalAgreement } from '../../lib/dataSchema' +import { formatNationalId, formatPhoneNumber } from '../../lib/utils' +import { TRUE } from '../../lib/constants' +import { signatureInfo } from '../../lib/messages' + +export const SignatureInfo = buildSection({ + id: 'signature', + title: signatureInfo.sectionName, + children: [ + buildMultiField({ + id: 'signatureInfo', + title: signatureInfo.sectionName, + description: signatureInfo.pageDescription, + nextButtonText: '', + children: [ + buildDescriptionField({ + id: 'signatureInfo.info', + title: signatureInfo.infoHeading, + description: signatureInfo.infoBullets, + titleVariant: 'h3', + space: 0, + }), + buildStaticTableField({ + title: signatureInfo.tableTitle, + marginTop: 6, + header: [ + signatureInfo.tableHeaderName, + signatureInfo.tableHeaderId, + signatureInfo.tableHeaderPhone, + signatureInfo.tableHeaderEmail, + ], + rows: (application) => { + const { landlordInfo, tenantInfo } = + application.answers as RentalAgreement + + const filterLandlords = landlordInfo.table.filter( + (landlord) => landlord.isRepresentative?.length === 0, + ) + + const filterTenants = tenantInfo.table.filter( + (tenant) => tenant.isRepresentative?.length === 0, + ) + + const signees = [...filterLandlords, ...filterTenants] + + return signees.map((person) => [ + person.nationalIdWithName.name ?? '', + formatNationalId(person.nationalIdWithName.nationalId) ?? '', + formatPhoneNumber(person.phone as string) ?? '', + person.email ?? '', + ]) + }, + }), + buildCheckboxField({ + id: 'signatureInfo.statement', + title: '', + required: true, + options: [ + { + value: TRUE, + label: signatureInfo.statementLabel, + }, + ], + large: true, + marginTop: 9, + }), + buildSubmitField({ + id: 'signatureInfo.submit', + title: '', + actions: [ + { + event: DefaultEvents.SUBMIT, + name: signatureInfo.submitButtonText, + type: 'sign', + }, + ], + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/signing/signing.ts b/libs/application/templates/rental-agreement/src/forms/signing/signing.ts new file mode 100644 index 000000000000..35883b26c029 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/signing/signing.ts @@ -0,0 +1,47 @@ +import { + buildAlertMessageField, + buildDescriptionField, + buildImageField, + buildMultiField, + buildSection, +} from '@island.is/application/core' +import { Section } from '@island.is/application/types' +import { signing } from '../../lib/messages/signing' + +import RA from '../../assets/RA' + +export const Signing: Section = buildSection({ + id: 'signing', + title: signing.sectionName, + children: [ + buildMultiField({ + id: 'signing.info', + title: signing.pageTitle, + description: '', + children: [ + buildAlertMessageField({ + id: 'signing.alert', + alertType: 'success', + title: signing.alertMessageSuccess, + marginTop: 0, + marginBottom: 6, + }), + buildDescriptionField({ + id: 'signing.description', + title: signing.pageInfoTitle, + titleVariant: 'h3', + description: signing.pageInfoDescription, + marginBottom: 8, + }), + buildImageField({ + id: 'signing.image', + title: '', + width: 'full', + image: RA, + imagePosition: 'center', + alt: 'Undirritun', + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/signingForm.ts b/libs/application/templates/rental-agreement/src/forms/signingForm.ts new file mode 100644 index 000000000000..18ac780c14e7 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/signingForm.ts @@ -0,0 +1,14 @@ +import { buildForm } from '@island.is/application/core' +import { Form, FormModes } from '@island.is/application/types' +import Logo from '../assets/Logo' +import { Signing } from './signing/signing' +import { application } from '../lib/messages' + +export const SigningForm: Form = buildForm({ + id: 'SigningForm', + title: application.name, + logo: Logo, + mode: FormModes.IN_PROGRESS, + renderLastScreenButton: true, + children: [Signing], +}) diff --git a/libs/application/templates/rental-agreement/src/forms/summary/summary.ts b/libs/application/templates/rental-agreement/src/forms/summary/summary.ts new file mode 100644 index 000000000000..c08784ca7ba2 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/forms/summary/summary.ts @@ -0,0 +1,24 @@ +import { + buildCustomField, + buildMultiField, + buildSection, +} from '@island.is/application/core' +import { summary } from '../../lib/messages' + +export const Summary = buildSection({ + id: 'summary', + title: summary.sectionName, + children: [ + buildMultiField({ + id: 'summary', + title: '', + children: [ + buildCustomField({ + id: 'summaryComponent', + title: '', + component: 'Summary', + }), + ], + }), + ], +}) diff --git a/libs/application/templates/rental-agreement/src/index.ts b/libs/application/templates/rental-agreement/src/index.ts new file mode 100644 index 000000000000..2eca07f1d28a --- /dev/null +++ b/libs/application/templates/rental-agreement/src/index.ts @@ -0,0 +1,11 @@ +import RentalAgreementTemplate from './lib/RentalAgreementTemplate' +export * from './lib/RentalAgreementTemplate' + +export const getDataProviders = () => import('./dataProviders/') +export const getFields = () => import('./fields/') + +export * from './lib/types' +export * from './lib/utils' +export * as messages from './lib/messages' + +export default RentalAgreementTemplate diff --git a/libs/application/templates/rental-agreement/src/lib/RentalAgreementTemplate.ts b/libs/application/templates/rental-agreement/src/lib/RentalAgreementTemplate.ts new file mode 100644 index 000000000000..79c1cb3bb545 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/RentalAgreementTemplate.ts @@ -0,0 +1,116 @@ +import { pruneAfterDays } from '@island.is/application/core' +import { Features } from '@island.is/feature-flags' +import { AuthDelegationType } from '@island.is/shared/types' +import { + Application, + ApplicationTemplate, + ApplicationTypes, + ApplicationContext, + ApplicationStateSchema, + DefaultEvents, + UserProfileApi, + ApplicationConfigurations, +} from '@island.is/application/types' +import { States, Roles } from './constants' +import { dataSchema } from './dataSchema' +import { + NationalRegistryUserApi, + NationalRegistrySpouseApi, +} from '../dataProviders' + +type Events = { type: DefaultEvents.SUBMIT } | { type: DefaultEvents.EDIT } + +const RentalAgreementTemplate: ApplicationTemplate< + ApplicationContext, + ApplicationStateSchema, + Events +> = { + type: ApplicationTypes.RENTAL_AGREEMENT, + name: 'Leigusamningur', + institution: 'Húsnæðis- og mannvirkjastofnun', + translationNamespaces: [ + ApplicationConfigurations.RentalAgreement.translation, + ], + dataSchema, + featureFlag: Features.rentalAgreement, + allowedDelegations: [{ type: AuthDelegationType.GeneralMandate }], + stateMachineConfig: { + initial: States.PREREQUISITES, + states: { + [States.PREREQUISITES]: { + meta: { + name: States.PREREQUISITES, + progress: 0, + status: 'draft', + lifecycle: pruneAfterDays(30), + roles: [ + { + id: Roles.APPLICANT, + formLoader: () => + import('../forms/prerequisitesForm').then((module) => + Promise.resolve(module.PrerequisitesForm), + ), + actions: [ + { event: 'SUBMIT', name: 'Staðfesta', type: 'primary' }, + ], + write: 'all', + read: 'all', + delete: true, + api: [ + UserProfileApi, + NationalRegistryUserApi, + NationalRegistrySpouseApi, + ], + }, + ], + }, + on: { + [DefaultEvents.SUBMIT]: [{ target: States.DRAFT }], + }, + }, + [States.DRAFT]: { + meta: { + name: States.DRAFT, + progress: 75, + status: 'draft', + lifecycle: pruneAfterDays(30), + roles: [ + { + id: Roles.APPLICANT, + formLoader: () => + import('../forms/rentalAgreementForm').then((module) => + Promise.resolve(module.RentalAgreementForm), + ), + actions: [ + { + event: DefaultEvents.SUBMIT, + name: 'Staðfesta', + type: 'primary', + }, + ], + write: 'all', + read: 'all', + delete: true, + }, + ], + }, + on: { + [DefaultEvents.SUBMIT]: { + target: States.DRAFT, + }, + }, + }, + }, + }, + mapUserToRole( + nationalId: string, + application: Application, + ): Roles | undefined { + if (application.applicant === nationalId) { + return Roles.APPLICANT + } + return undefined + }, +} + +export default RentalAgreementTemplate diff --git a/libs/application/templates/rental-agreement/src/lib/constants.ts b/libs/application/templates/rental-agreement/src/lib/constants.ts new file mode 100644 index 000000000000..ce9af52b6107 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/constants.ts @@ -0,0 +1,118 @@ +import { StateLifeCycle } from '@island.is/application/types' + +export const TRUE = 'true' +export const FALSE = 'false' + +export enum States { + PREREQUISITES = 'prerequisites', + DRAFT = 'draft', + ONEACCEPTED = 'oneAccepted', + TWOACCEPTED = 'twoAccepted', + SIGNING = 'signing', + COMPLETED = 'completed', +} + +export enum Roles { + APPLICANT = 'applicant', +} + +export enum Routes { + LANDLORDINFORMATION = 'landlordInfo', + TENANTINFORMATION = 'tenantInfo', + PROPERTYINFORMATION = 'registerProperty.info', + PROPERTYINFORMATION_SERCH = 'registerProperty.search', + PROPERTYCATEGORY = 'registerProperty.category', + SPECIALPROVISIONS = 'specialProvisions', + CONDITION = 'condition', + FIREPROTECTIONS = 'fireProtections', + RENTALPERIOD = 'rentalPeriod', + RENTALAMOUNT = 'rentalAmount', + SECURITYDEPOSIT = 'securityDeposit', + OTHERFEES = 'otherFees', +} +export const IS_REPRESENTATIVE = 'isRepresentative' + +export enum AnswerOptions { + YES = 'yes', + NO = 'no', +} + +export enum RentalHousingCategoryTypes { + ENTIRE_HOME = 'entireHome', + ROOM = 'room', + COMMERCIAL = 'commercial', +} + +export enum RentalHousingCategoryClass { + GENERAL_MARKET = 'generalMarket', + SPECIAL_GROUPS = 'specialGroups', +} + +export enum RentalHousingCategoryClassGroup { + STUDENT_HOUSING = 'studentHousing', + SENIOR_CITIZEN_HOUSING = 'seniorCitizenHousing', + COMMUNE = 'commune', + HALFWAY_HOUSE = 'halfwayHouse', + SOCIAL_HOUSING = 'socialHousing', + INCOME_BASED_HOUSING = 'incomeBasedHousing', + EMPLOYEE_HOUSING = 'employeeHousing', +} + +export enum RentalHousingConditionInspector { + CONTRACT_PARTIES = 'contractParties', + INDEPENDENT_PARTY = 'independentParty', +} + +export enum RentalAmountIndexTypes { + CONSUMER_PRICE_INDEX = 'consumerPriceIndex', + CONSTRUCTION_COST_INDEX = 'constructionCostIndex', + WAGE_INDEX = 'wageIndex', +} + +export enum RentalAmountPaymentDateOptions { + FIRST_DAY = 'firstDay', + LAST_DAY = 'lastDay', + OTHER = 'other', +} + +export enum RentalPaymentMethodOptions { + BANK_TRANSFER = 'bankTransfer', + PAYMENT_SLIP = 'paymentSlip', + OTHER = 'other', +} + +export enum SecurityDepositTypeOptions { + BANK_GUARANTEE = 'bankGuarantee', + CAPITAL = 'capital', + THIRD_PARTY_GUARANTEE = 'thirdPartyGuarantee', + INSURANCE_COMPANY = 'insuranceCompany', + MUTUAL_FUND = 'mutualFund', + OTHER = 'other', +} + +export enum SecurityDepositAmountOptions { + ONE_MONTH = '1 month', + TWO_MONTHS = '2 months', + THREE_MONTHS = '3 months', + + OTHER = 'other', +} + +export enum OtherFeesPayeeOptions { + LANDLORD_OR_NOT_APPLICABLE = 'landlordPaysOrNotApplicable', + LANDLORD = 'landlordPays', + TENANT = 'tenantPays', +} + +export const pruneAfterDays = (Days: number): StateLifeCycle => { + return { + shouldBeListed: false, + shouldBePruned: true, + whenToPrune: Days * 24 * 3600 * 1000, + } +} + +export enum UserRole { + LANDLORD = 'landlord', + TENANT = 'tenant', +} diff --git a/libs/application/templates/rental-agreement/src/lib/dataSchema.ts b/libs/application/templates/rental-agreement/src/lib/dataSchema.ts new file mode 100644 index 000000000000..db8e982f4181 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/dataSchema.ts @@ -0,0 +1,703 @@ +import { z } from 'zod' +import * as kennitala from 'kennitala' +import { + RentalAmountIndexTypes, + RentalAmountPaymentDateOptions, + RentalHousingCategoryClass, + RentalHousingCategoryTypes, + OtherFeesPayeeOptions, + SecurityDepositAmountOptions, + SecurityDepositTypeOptions, + TRUE, + RentalPaymentMethodOptions, +} from './constants' +import * as m from './messages' + +const isValidMeterNumber = (value: string) => { + const meterNumberRegex = /^[0-9]{1,20}$/ + return meterNumberRegex.test(value) +} + +const isValidMeterStatus = (value: string) => { + const meterStatusRegex = /^[0-9]{1,10}(,[0-9])?$/ + return meterStatusRegex.test(value) +} + +const checkIfNegative = (inputNumber: string) => { + if (Number(inputNumber) < 0) { + return false + } else { + return true + } +} + +const approveExternalData = z.boolean().refine((v) => v) + +const applicant = z.object({ + nationalId: z + .string() + .refine((val) => (val ? kennitala.isValid(val) : false), { + params: m.dataSchema.nationalId, + }), +}) + +const fileSchema = z.object({ + name: z.string(), + key: z.string(), + url: z.string().optional(), +}) + +const propertyUnit = z.object({ + unitId: z.string(), + markingNr: z.string(), + unitType: z.string(), + size: z.string(), + numberOfRooms: z.string(), +}) + +const PropertyId = z.object({ + propertyId: z.string(), + marking: z.string(), + propertySize: z.string(), + units: z.array(propertyUnit), +}) + +const Property = z.object({ + streetAddress: z.string(), + regionNumber: z.string(), + cityName: z.string(), + propertyIds: z.array(PropertyId), +}) + +const landlordInfo = z + .object({ + table: z.array( + z.object({ + nationalIdWithName: z.object({ + nationalId: z.string().refine((x) => !!x && x.trim().length > 0, { + params: m.landlordDetails.landlordNationalIdEmptyError, + }), + name: z.string(), + }), + phone: z + .string() + .optional() + .refine((x) => !!x && x.trim().length > 0, { + params: m.landlordDetails.landlordPhoneNumberEmptyError, + }), + email: z + .string() + .optional() + .refine((x) => !!x && x.trim().length > 0, { + params: m.landlordDetails.landlordEmailEmptyError, + }), + address: z + .string() + .optional() + .refine((x) => !!x && x.trim().length > 0, { + params: m.landlordDetails.landlordAddressEmptyError, + }), + isRepresentative: z.array(z.string()).optional(), + }), + ), + }) + .superRefine((data, ctx) => { + // TODO: Uncomment this when validation in repeatable table is fixed + // const filterNonRepresentatives = + // data.table && + // data.table.filter( + // (landlord) => !landlord.isRepresentative?.includes(IS_REPRESENTATIVE), + // ) + if (data.table && data.table.length === 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.landlordDetails.landlordEmptyTableError, + path: ['table'], + }) + } + // TODO: Uncomment this when validation in repeatable table is fixed + // else if (filterNonRepresentatives?.length === 0) { + // ctx.addIssue({ + // code: z.ZodIssueCode.custom, + // message: 'Custom error message', + // params: m.landlordDetails.landlordOnlyRepresentativeTableError, + // path: ['table'], + // }) + // } + }) + +const tenantInfo = z + .object({ + table: z.array( + z.object({ + nationalIdWithName: z.object({ + nationalId: z.string().refine((x) => !!x && x.trim().length > 0, { + params: m.tenantDetails.tenantNationalIdEmptyError, + }), + name: z.string(), + }), + phone: z + .string() + .optional() + .refine((x) => !!x && x.trim().length > 0, { + params: m.tenantDetails.tenantPhoneNumberEmptyError, + }), + email: z + .string() + .optional() + .refine((x) => !!x && x.trim().length > 0, { + params: m.tenantDetails.tenantEmailEmptyError, + }), + address: z + .string() + .optional() + .refine((x) => !!x && x.trim().length > 0, { + params: m.tenantDetails.tenantAddressEmptyError, + }), + isRepresentative: z.array(z.string()).optional(), + }), + ), + }) + .superRefine((data, ctx) => { + // TODO: Uncomment this when validation in repeatable table is fixed + // const filterNonRepresentatives = + // data.table && + // data.table.filter( + // (tenant) => !tenant.isRepresentative?.includes(IS_REPRESENTATIVE), + // ) + if (data.table && data.table.length === 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.tenantDetails.tenantEmptyTableError, + path: ['table'], + }) + } + // TODO: Uncomment this when validation in repeatable table is fixed + // else if (filterNonRepresentatives?.length === 0) { + // ctx.addIssue({ + // code: z.ZodIssueCode.custom, + // message: 'Custom error message', + // params: m.tenantDetails.tenantOnlyRepresentativeTableError, + // path: ['table'], + // }) + // } + }) + +const registerProperty = z + .object({ + searchResults: z.array(Property).optional(), + categoryType: z + .enum([ + RentalHousingCategoryTypes.ENTIRE_HOME, + RentalHousingCategoryTypes.ROOM, + RentalHousingCategoryTypes.COMMERCIAL, + ]) + .optional(), + categoryClass: z + .enum([ + RentalHousingCategoryClass.GENERAL_MARKET, + RentalHousingCategoryClass.SPECIAL_GROUPS, + ]) + .optional(), + categoryClassGroup: z.string().optional(), + }) + .superRefine((data, ctx) => { + if ( + data.categoryClass && + data.categoryClass.includes('specialGroups') && + !data.categoryClassGroup + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.registerProperty.category.classGroupRequiredError, + path: ['categoryClassGroup'], + }) + } + }) + +const rentalPeriod = z + .object({ + startDate: z + .string() + .optional() + .refine((x) => !!x && x.trim().length > 0, { + params: m.rentalPeriod.errorAgreementStartDateNotFilled, + }), + endDate: z.string().optional(), + isDefinite: z.string().array().optional(), + }) + .superRefine((data, ctx) => { + const start = data.startDate ? new Date(data.startDate) : '' + const end = data.endDate ? new Date(data.endDate) : '' + const isDefiniteChecked = data.isDefinite && data.isDefinite.includes(TRUE) + if (isDefiniteChecked) { + if (!data.endDate || !data.endDate.trim().length) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ['endDate'], + params: m.rentalPeriod.errorAgreementEndDateNotFilled, + }) + } else if (start >= end) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ['endDate'], + params: m.rentalPeriod.errorEndDateBeforeStart, + }) + } + } + }) + +const rentalAmount = z + .object({ + amount: z + .string() + .refine((x) => Boolean(x), { + params: m.dataSchema.requiredErrorMsg, + }) + .refine((x) => checkIfNegative(x), { + params: m.dataSchema.negativeNumberError, + }), + indexTypes: z + .enum([ + RentalAmountIndexTypes.CONSUMER_PRICE_INDEX, + RentalAmountIndexTypes.CONSTRUCTION_COST_INDEX, + RentalAmountIndexTypes.WAGE_INDEX, + ]) + .optional(), + indexValue: z.string().optional(), + isIndexConnected: z.string().array().optional(), + paymentDateOptions: z + .enum([ + RentalAmountPaymentDateOptions.FIRST_DAY, + RentalAmountPaymentDateOptions.LAST_DAY, + RentalAmountPaymentDateOptions.OTHER, + ]) + .optional(), + paymentDateOther: z.string().optional(), + paymentMethodOptions: z + .enum([ + RentalPaymentMethodOptions.BANK_TRANSFER, + RentalPaymentMethodOptions.PAYMENT_SLIP, + RentalPaymentMethodOptions.OTHER, + ]) + .optional(), + paymentMethodNationalId: z.string().optional(), + paymentMethodBankAccountNumber: z.string().optional(), + paymentMethodOtherTextField: z.string().optional(), + isPaymentInsuranceRequired: z.string().array().optional(), + }) + .superRefine((data, ctx) => { + if ( + data.paymentDateOptions && + data.paymentDateOptions.includes(RentalAmountPaymentDateOptions.OTHER) && + !data.paymentDateOther?.trim().length + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.rentalAmount.paymentDateOtherOptionRequiredError, + path: ['paymentDateOther'], + }) + } + + if ( + data.paymentMethodOptions === RentalPaymentMethodOptions.BANK_TRANSFER + ) { + if (!data.paymentMethodNationalId?.trim().length) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.rentalAmount.paymentMethodNationalIdRequiredError, + path: ['paymentMethodNationalId'], + }) + } + if ( + data.paymentMethodNationalId && + !kennitala.isValid(data.paymentMethodNationalId) + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.rentalAmount.paymentMethodNationalIdInvalidError, + path: ['paymentMethodNationalId'], + }) + } + if (!data.paymentMethodBankAccountNumber?.trim().length) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.rentalAmount.paymentMethodBankAccountNumberRequiredError, + path: ['paymentMethodBankAccountNumber'], + }) + } + if ( + data.paymentMethodBankAccountNumber && + data.paymentMethodBankAccountNumber.length < 7 + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.rentalAmount.paymentMethodBankAccountNumberInvalidError, + path: ['paymentMethodBankAccountNumber'], + }) + } + } + + if (data.paymentMethodOptions === RentalPaymentMethodOptions.OTHER) { + if (!data.paymentMethodOtherTextField?.trim().length) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.rentalAmount.paymentMethodOtherTextFieldRequiredError, + path: ['paymentMethodOtherTextField'], + }) + } + } + }) + +const specialProvisions = z.object({ + descriptionInput: z.string().optional(), + rulesInput: z.string().optional(), +}) + +const condition = z.object({ + inspector: z.string().optional(), + inspectorName: z.string().optional(), + resultsDescription: z.string().optional(), + resultsFiles: z.array(fileSchema), +}) + +const fireProtections = z + .object({ + smokeDetectors: z.string().optional(), + fireExtinguisher: z.string().optional(), + emergencyExits: z.string().optional(), + fireBlanket: z.string().optional(), + propertySize: z.string().optional(), + }) + .superRefine((data, ctx) => { + const propertySizeString = data.propertySize?.replace(',', '.') || '' + const numberOfSmokeDetectors = Number(data.smokeDetectors) + const requiredSmokeDetectors = Math.ceil(Number(propertySizeString) / 80) + if ( + data.smokeDetectors && + numberOfSmokeDetectors < requiredSmokeDetectors + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.housingFireProtections.smokeDetectorMinRequiredError, + path: ['smokeDetectors'], + }) + } + + if (data.fireExtinguisher && Number(data.fireExtinguisher) < 1) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.housingFireProtections.fireExtinguisherNullError, + path: ['fireExtinguisher'], + }) + } + + if (data.emergencyExits && Number(data.emergencyExits) < 1) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.housingFireProtections.emergencyExitNullError, + path: ['emergencyExits'], + }) + } + }) + +const securityDeposit = z + .object({ + securityType: z + .string() + .optional() + .refine((x) => Boolean(x), { + params: m.securityDeposit.typeError, + }), + bankGuaranteeInfo: z.string().optional(), + thirdPartyGuaranteeInfo: z.string().optional(), + insuranceCompanyInfo: z.string().optional(), + mutualFundInfo: z.string().optional(), + otherInfo: z.string().optional(), + securityAmount: z.string().optional(), + securityAmountOther: z.string().optional(), + rentalAmount: z.string().optional(), + }) + .superRefine((data, ctx) => { + if ( + data.securityType === SecurityDepositTypeOptions.BANK_GUARANTEE && + !data.bankGuaranteeInfo + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.securityDeposit.bankInfoError, + path: ['bankGuaranteeInfo'], + }) + } + + if ( + data.securityType === SecurityDepositTypeOptions.THIRD_PARTY_GUARANTEE && + !data.thirdPartyGuaranteeInfo + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.securityDeposit.thirdPartyGuaranteeError, + path: ['thirdPartyGuaranteeInfo'], + }) + } + + if ( + data.securityType === SecurityDepositTypeOptions.INSURANCE_COMPANY && + !data.insuranceCompanyInfo + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.securityDeposit.insuranceCompanyError, + path: ['insuranceCompanyInfo'], + }) + } + + if ( + data.securityType === SecurityDepositTypeOptions.MUTUAL_FUND && + !data.mutualFundInfo + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.securityDeposit.mutualFundError, + path: ['mutualFundInfo'], + }) + } + + if ( + data.securityType === SecurityDepositTypeOptions.OTHER && + !data.otherInfo + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.securityDeposit.otherError, + path: ['otherInfo'], + }) + } + + if ( + data.securityType !== SecurityDepositTypeOptions.MUTUAL_FUND && + !data.securityAmount + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.securityDeposit.amountError, + path: ['securityAmount'], + }) + } + + if ( + (data.securityType === SecurityDepositTypeOptions.MUTUAL_FUND || + data.securityAmount === SecurityDepositAmountOptions.OTHER) && + !data.securityAmountOther + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.securityDeposit.amountOtherError, + path: ['securityAmountOther'], + }) + } + + if ( + data.securityType === SecurityDepositTypeOptions.MUTUAL_FUND && + Number(data.rentalAmount) * 0.1 < Number(data.securityAmountOther) + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.securityDeposit.amountOtherMutualFundError, + path: ['securityAmountOther'], + }) + } + + if ( + (data.securityType === SecurityDepositTypeOptions.CAPITAL || + data.securityType === + SecurityDepositTypeOptions.THIRD_PARTY_GUARANTEE) && + Number(data.rentalAmount) * 3 < Number(data.securityAmountOther) + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.securityDeposit.amountOtherCapitolError, + path: ['securityAmountOther'], + }) + } + }) + +const otherFees = z + .object({ + housingFund: z.string().optional(), + housingFundAmount: z.string().optional(), + electricityCost: z.string().optional(), + electricityCostMeterNumber: z.string().optional(), + electricityCostMeterStatus: z.string().optional(), + electricityCostMeterStatusDate: z.string().optional(), + heatingCost: z.string().optional(), + heatingCostMeterNumber: z.string().optional(), + heatingCostMeterStatus: z.string().optional(), + heatingCostMeterStatusDate: z.string().optional(), + }) + .superRefine((data, ctx) => { + const tenantPaysHousingFund = + data.housingFund === OtherFeesPayeeOptions.TENANT + const tenantPaysElectricityCost = + data.electricityCost === OtherFeesPayeeOptions.TENANT + const tenantPaysHeatingCost = + data.heatingCost === OtherFeesPayeeOptions.TENANT + + if (data.housingFund && tenantPaysHousingFund) { + if (!data.housingFundAmount) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorHousingFundEmpty, + path: ['housingFundAmount'], + }) + } + } + + if (data.electricityCost && tenantPaysElectricityCost) { + if (!data.electricityCostMeterNumber) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorMeterNumberEmpty, + path: ['electricityCostMeterNumber'], + }) + } + if ( + data.electricityCostMeterNumber && + !isValidMeterNumber(data.electricityCostMeterNumber) + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorMeterStatusRegex, + path: ['electricityCostMeterNumber'], + }) + } + if (!data.electricityCostMeterStatus) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorMeterStatusEmpty, + path: ['electricityCostMeterStatus'], + }) + } + if ( + data.electricityCostMeterStatus && + !isValidMeterStatus(data.electricityCostMeterStatus) + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorMeterStatusRegex, + path: ['electricityCostMeterStatus'], + }) + } + if (!data.electricityCostMeterStatusDate) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorMeterStatusDateEmpty, + path: ['electricityCostMeterStatusDate'], + }) + } + } + + if (data.heatingCost && tenantPaysHeatingCost) { + if (!data.heatingCostMeterNumber) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorMeterNumberEmpty, + path: ['heatingCostMeterNumber'], + }) + } + if ( + data.heatingCostMeterNumber && + !isValidMeterNumber(data.heatingCostMeterNumber) + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorMeterNumberRegex, + path: ['heatingCostMeterNumber'], + }) + } + if (!data.heatingCostMeterStatus) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorMeterNumberEmpty, + path: ['heatingCostMeterStatus'], + }) + } + if ( + data.heatingCostMeterStatus && + !isValidMeterStatus(data.heatingCostMeterStatus) + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorMeterStatusRegex, + path: ['heatingCostMeterStatus'], + }) + } + if (!data.heatingCostMeterStatusDate) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Custom error message', + params: m.otherFees.errorMeterStatusDateEmpty, + path: ['heatingCostMeterStatusDate'], + }) + } + } + return true + }) + +const signatureInfo = z.object({ + statement: z + .string() + .array() + .refine((x) => x.includes(TRUE), { + params: m.signatureInfo.statementError, + }), +}) + +export const dataSchema = z.object({ + approveExternalData, + applicant, + landlordInfo, + tenantInfo, + registerProperty, + rentalPeriod, + rentalAmount, + securityDeposit, + specialProvisions, + condition, + fireProtections, + otherFees, + signatureInfo, +}) + +export type RentalAgreement = z.TypeOf diff --git a/libs/application/templates/rental-agreement/src/lib/messages/dataSchema.ts b/libs/application/templates/rental-agreement/src/lib/messages/dataSchema.ts new file mode 100644 index 000000000000..6707c442ffd1 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/dataSchema.ts @@ -0,0 +1,44 @@ +import { defineMessages } from 'react-intl' + +export const dataSchema = defineMessages({ + nationalId: { + id: 'ra.application:dataSchema.national.id', + defaultMessage: 'Kennitala er ekki á réttu formi', + description: 'Error message when nationalid is wrong', + }, + phoneNumber: { + id: 'ra.application:dataSchema.phoneNumber', + defaultMessage: 'Símanúmerið þarf að vera gilt.', + description: 'Error message when phone number is invalid.', + }, + + // Debug error messages + requiredErrorMsg: { + id: 'ra.application:error.required', + defaultMessage: 'Reitur má ekki vera tómur', + description: 'Error message when a required field has not been filled', + }, + negativeNumberError: { + id: 'ra.application:error.negativeNumber', + defaultMessage: 'Ekki er leyfilegt að setja inn neikvæðar tölur', + description: 'Error message when a required field has not been filled', + }, + + phoneNumberFormatError: { + id: 'ra.application:dataSchema.phoneNumberFormatError', + defaultMessage: 'Símanúmer verður að vera á réttu formi', + description: 'Tenant details phone number format error', + }, + emailFormatError: { + id: 'ra.application:dataSchema.emailFormatError', + defaultMessage: + 'Netfangið er rangt ritað. Vinsamlegast athugaðu hvort vanti @-merkið eða lénið (eins og ".is")', + description: 'Tenant details email format error', + }, + nationalIdNotFoundError: { + id: 'ra.application:tenantDetails.nationalIdNotFoundError', + defaultMessage: + 'Enginn aðili í Þjóðskrá hefur þessa kennitölu. Aðilar leigusamnings verða að hafa kennitölu til að geta undirritað samning rafrænt.', + description: 'National id not found error', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/housing/housingCondition.ts b/libs/application/templates/rental-agreement/src/lib/messages/housing/housingCondition.ts new file mode 100644 index 000000000000..09e257cb114f --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/housing/housingCondition.ts @@ -0,0 +1,83 @@ +import { defineMessages } from 'react-intl' + +export const housingCondition = defineMessages({ + subSectionName: { + id: 'ra.application:housingCondition.subSectionName', + defaultMessage: 'Ástandsskoðun', + description: 'Housing condition inspection sub section name', + }, + pageTitle: { + id: 'ra.application:housingCondition.pageTitle', + defaultMessage: 'Ástand húsnæðis', + description: 'Housing condition inspection page title', + }, + pageDescription: { + id: 'ra.application:housingCondition.pageDescription#markdown', + defaultMessage: + 'Leigusamningur þarf lögum samkvæmt að innihalda ástandsúttekt á húsnæðinu. Sú úttekt þarf að fara fram við samningsgerðina. Gott er að skoða húsnæðið gaumgæfilega og taka myndir af ástandi. [Sjá nánar hér](https://island.is/skraning-leigusamnings-i-leiguskra#astandsuttekt-og-brunauttekt).', + description: 'Housing condition inspection page description', + }, + inspectorTitle: { + id: 'ra.application:housingCondition.inspectorTitle', + defaultMessage: 'Framkvæmdaraðili ástandsskoðunar', + description: 'Housing condition inspector title', + }, + inspectorDescription: { + id: 'ra.application:housingCondition.inspectorDescription', + defaultMessage: + 'Athugið að aðilar geta sjálfir gert ástandsúttekt eða fengið óháðan aðila til þess og þá skiptist kostnaðurinn við það jafnt á milli aðila.', + description: 'Housing condition inspector description', + }, + inspectorOptionContractParties: { + id: 'ra.application:housingCondition.inspectorOptionContractParties', + defaultMessage: 'Samningsaðilar', + description: 'Housing condition inspector option contract parties', + }, + inspectorOptionIndependentParty: { + id: 'ra.application:housingCondition.inspectorOptionIndependentParty', + defaultMessage: 'Óháður aðili', + description: 'Housing condition inspector option independent party', + }, + independentInspectorNameLabel: { + id: 'ra.application:housingCondition.independentInspectorNameLabel', + defaultMessage: 'Fullt nafn', + description: 'Housing condition independent inspector name', + }, + independentInspectorNamePlaceholder: { + id: 'ra.application:housingCondition.independentInspectorNamePlaceholder', + defaultMessage: 'Skrifaðu hér fullt nafn óháðs aðila', + description: 'Housing condition independent inspector name placeholder', + }, + inspectionResultsTitle: { + id: 'ra.application:housingCondition.inspectionResultsTitle', + defaultMessage: 'Niðurstöður ástandsúttektar', + description: 'Housing condition inspection results title', + }, + inspectionResultsDescription: { + id: 'ra.application:housingCondition.inspectionResultsDescription', + defaultMessage: + 'Hér á að setja inn helstu niðurstöður ástandsúttektar. Gott er að taka myndir af þeim atriðum sem skipta máli. Ef óháður aðili hefur framkvæmt úttektina má setja niðurstöðurnar með sem fylgiskjal.', + description: 'Housing condition inspection results description', + }, + inspectionResultsInputLabel: { + id: 'ra.application:housingCondition.inspectionResultsInputLabel', + defaultMessage: 'Ástandsúttekt', + description: 'Housing condition inspection results input label', + }, + inspectionResultsInputPlaceholder: { + id: 'ra.application:housingCondition.inspectionResultsPlaceholder', + defaultMessage: 'Skrifaðu hér allt sem á við', + description: 'Housing condition inspection results placeholder', + }, + fileUploadTitle: { + id: 'ra.application:housingCondition.fileUploadTitle', + defaultMessage: 'Dragðu skjöl hingað til að hlaða upp', + description: 'Housing condition file upload title', + }, + fileUploadDescription: { + id: 'ra.application:housingCondition.fileUploadDescription#markdown', + defaultMessage: + 'Tekið er við skjölum með endingu: \n.pdf, .doc, .docx, .rtf, .jpg, .jpeg, .png, .heic', + description: 'Housing condition file upload description', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/housing/housingFireProtections.ts b/libs/application/templates/rental-agreement/src/lib/messages/housing/housingFireProtections.ts new file mode 100644 index 000000000000..0ea096f626c1 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/housing/housingFireProtections.ts @@ -0,0 +1,69 @@ +import { defineMessages } from 'react-intl' + +export const housingFireProtections = defineMessages({ + subSectionName: { + id: 'ra.application:housingFireProtections.subSectionName', + defaultMessage: 'Brunavarnir', + description: 'Fire protections sub section name', + }, + pageTitle: { + id: 'ra.application:housingFireProtections.pageTitle', + defaultMessage: 'Staða brunavarna í húsnæðinu', + description: 'Fire protections page title', + }, + pageDescription: { + id: 'ra.application:housingFireProtections.pageDescription', + defaultMessage: + 'Leigusamningur þarf lögum samkvæmt að innihalda úttekt á brunavörnum í húsnæðinu. Sú úttekt þarf að fara fram við samningsgerðina. Gott er að skoða húsnæðið gaumgæfilega út frá öryggismálum.', + description: 'Fire protections page description', + }, + smokeDetectorsFireExtinguisherRequirements: { + id: 'ra.application:housingFireProtections.smokeDetectorsFireExtinguisherRequirements#markdown', + defaultMessage: + 'Nauðsynlegt er að hafa að minnsta kosti **1 CE merktan reykskynjara** á hverja 80m2 og **1 slökkvitæki** í eigninni.', + description: 'Smoke detector and fire extinguisher requirements', + }, + smokeDetectorsLabel: { + id: 'ra.application:housingFireProtections.smokeDetectorsLabel', + defaultMessage: 'Reykskynjari', + description: 'Smoke dectectors label', + }, + fireExtinguisherLabel: { + id: 'ra.application:housingFireProtections.fireExtinguisherLabel', + defaultMessage: 'Slökkvitæki', + description: 'Fire extinguisher label', + }, + exitFireBlanketRequirements: { + id: 'ra.application:housingFireProtections.exitFireBlanketRequirements', + defaultMessage: + 'Flóttaleiðir þurfa að vera auðrataðar og greiðfærar en ekki er gerð krafa um eldvarnarteppi.', + description: 'Smoke detector and fire blanket requirements', + }, + exitsLabel: { + id: 'ra.application:housingFireProtections.exitsLabel', + defaultMessage: 'Flóttaleiðir', + description: 'Exits label', + }, + fireBlanketLabel: { + id: 'ra.application:housingFireProtections.fireBlanketLabel', + defaultMessage: 'Eldvarnarteppi', + description: 'Fire blanket label', + }, + + // dataSchema + smokeDetectorMinRequiredError: { + id: 'ra.application:housingFireProtections.smokeDetectorMinRequiredError', + defaultMessage: 'Reykskynjarar þurfa að vera a.m.k. 1 á hverja 80m2', + description: 'Smoke detectors min 1 per 80 square meters', + }, + fireExtinguisherNullError: { + id: 'ra.application:housingFireProtections.fireExtinguisherNullError', + defaultMessage: 'Það þarf að vera a.m.k. eitt slökkvitæki í eigninni', + description: 'Fire extinguisher 0 error', + }, + emergencyExitNullError: { + id: 'ra.application:housingFireProtections.emergencyExitNullError', + defaultMessage: 'Það þarf að vera a.m.k. ein flóttaleið úr eigninni', + description: 'Emergency exit 0 error', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/housing/landlordDetails.ts b/libs/application/templates/rental-agreement/src/lib/messages/housing/landlordDetails.ts new file mode 100644 index 000000000000..66c3aeebf719 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/housing/landlordDetails.ts @@ -0,0 +1,99 @@ +import { defineMessages } from 'react-intl' + +export const landlordDetails = defineMessages({ + subSectionName: { + id: 'ra.application:landlordDetails.subSectionName', + defaultMessage: 'Leigusali', + description: 'Landlord details subsection name', + }, + pageTitle: { + id: 'ra.application:landlordDetails.pageTitle', + defaultMessage: 'Skrá leigusala', + description: 'Landlord details page title', + }, + pageDescription: { + id: 'ra.application:landlordDetails.pageDescription', + defaultMessage: + 'Hér skal skrá leigusala húsnæðis. Hægt er að bæta við eins mörgum leigusölum á samninginn eins og óskað er eftir.', + description: 'Landlord details page description', + }, + nationalIdInputLabel: { + id: 'ra.application:landlordDetails.nationalIdInputLabel', + defaultMessage: 'Kennitala leigusala', + description: 'Landlord details national id input label', + }, + nationalIdHeaderLabel: { + id: 'ra.application:landlordDetails.nationalIdHeaderLabel', + defaultMessage: 'Kennitala', + description: 'Landlord details national id header label', + }, + cancelButtonText: { + id: 'ra.application:landlordDetails.cancelButtonText', + defaultMessage: 'Hætta við', + description: 'Landlord details cancel button text', + }, + nameInputLabel: { + id: 'ra.application:landlordDetails.nameLabel', + defaultMessage: 'Fullt nafn', + description: 'Landlord details name input label', + }, + isRepresentative: { + id: 'ra.application:landlordDetails.isRepresentative', + defaultMessage: 'umboðsaðili', + description: 'Landlord is representative', + }, + emailInputLabel: { + id: 'ra.application:landlordDetails.emailLabel', + defaultMessage: 'Netfang', + description: 'Landlord details email input label', + }, + phoneInputLabel: { + id: 'ra.application:landlordDetails.phoneLabel', + defaultMessage: 'Símanúmer', + description: 'Landlord details phone input label', + }, + addressInputLabel: { + id: 'ra.application:landlordDetails.addressInputLabel', + defaultMessage: 'Heimilisfang', + description: 'Landlord details address input label', + }, + representativeLabel: { + id: 'ra.application:landlordDetails.representativeLabel', + defaultMessage: 'Þessi aðili er umboðsaðili leigusala', + description: 'Landlord details representative label', + }, + + // DataSchema errors + landlordEmptyTableError: { + id: 'ra.application:landlordDetails.landlordEmptyTableError', + defaultMessage: + 'Að minnsta kosti einn leigusali þarf að vera skráður á leigusamninginn.', + description: 'Landlord details no landlords in table', + }, + landlordOnlyRepresentativeTableError: { + id: 'ra.application:landlordDetails.landlordOnlyRepresentativeTableError', + defaultMessage: + 'Að minnsta kosti einn leigusali þarf að vera skráður á leigusamninginn. Ekki er nóg að skrá umboðsaðlia leigusala.', + description: 'Landlord details only a representative of landlord in table', + }, + landlordNationalIdEmptyError: { + id: 'ra.application:landlordDetails.landlordNationalIdEmptyError', + defaultMessage: 'Kennitala leigusala þarf að vera skráð', + description: 'Landlord details national id empty error', + }, + landlordPhoneNumberEmptyError: { + id: 'ra.application:landlordDetails.landlordPhoneNumberEmptyError', + defaultMessage: 'Símanúmer leigusala þarf að vera skráð', + description: 'Landlord details phone number empty error', + }, + landlordEmailEmptyError: { + id: 'ra.application:landlordDetails.landlordEmailEmptyError', + defaultMessage: 'Netfang leigusala þarf að vera skráð', + description: 'Landlord details email empty error', + }, + landlordAddressEmptyError: { + id: 'ra.application:landlordDetails.landlordAddressEmptyError', + defaultMessage: 'Heimilisfang leigusala þarf að vera skráð', + description: 'Landlord details address empty error', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/housing/registerProperty.ts b/libs/application/templates/rental-agreement/src/lib/messages/housing/registerProperty.ts new file mode 100644 index 000000000000..8e79768833b8 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/housing/registerProperty.ts @@ -0,0 +1,189 @@ +import { defineMessages } from 'react-intl' + +export const registerProperty = { + subsection: defineMessages({ + name: { + id: 'ra.application:registerProperty.subSection.name', + defaultMessage: 'Skrá húsnæði', + description: 'Register property subsection name', + }, + }), + + info: defineMessages({ + pageTitle: { + id: 'ra.application:registerProperty.info.pageTitle', + defaultMessage: 'Húsnæðið', + description: 'Register property page title', + }, + pageDescription: { + id: 'ra.application:registerProperty.info.pageDescription', + defaultMessage: + 'Finndu eignina með fasteignanúmeri eða heimilisfangi. Nánari upplýsingar er að finna í [fasteignaskrá HMS](https://leit.fasteignaskra.is/).', + description: 'Register property page description', + }, + + // Error messages + searchResultsEmptyError: { + id: 'ra.application:registerProperty.category.searchResultsEmptyError', + defaultMessage: + 'Skráning leiguhúsnæðis þarf að vera til staðar til að halda áfram', + description: 'Error message when no search results', + }, + }), + + infoSummary: defineMessages({ + pageTitle: { + id: 'ra.application:registerProperty.infoSummary.pageTitle', + defaultMessage: 'Húsnæðið', + description: 'Property info summary page title', + }, + pageDescription: { + id: 'ra.application:registerProperty.infoSummary.pageDescription', + defaultMessage: + 'Eftirtaldar upplýsingar eru samantekt af skráningu frá fyrra skrefi. Farðu vel yfir skráninguna til að vera viss um að allar upplýsingar séu réttar. Þú getur farið til baka til að breyta upplýsingum.', + description: 'Property info summary page description', + }, + tableHeaderPropertyId: { + id: 'ra.application:registerProperty.infoSummary.tableHeaderPropertyId', + defaultMessage: 'Fasteignanúmer', + description: 'Summary table header for property number', + }, + tableHeaderAddress: { + id: 'ra.application:registerProperty.infoSummary.tableHeaderAddress', + defaultMessage: 'Heimilisfang', + description: 'Summary table header for address', + }, + tableHeaderUnitId: { + id: 'ra.application:registerProperty.infoSummary.tableHeaderUnitId', + defaultMessage: 'Merking', + description: 'Summary table header for property unit id', + }, + tableHeaderSize: { + id: 'ra.application:registerProperty.infoSummary.tableHeaderSize', + defaultMessage: 'Birt stærð', + description: 'Summary table header for size', + }, + tableHeaderNumOfRooms: { + id: 'ra.application:registerProperty.infoSummary.tableHeaderNumOfRooms', + defaultMessage: 'herbergi', + description: 'Summary table header for number of rooms', + }, + }), + + category: defineMessages({ + pageTitle: { + id: 'ra.application:registerProperty.category.pageTitle', + defaultMessage: 'Skráning húsnæðis', + description: 'Property category page title', + }, + pageDescription: { + id: 'ra.application:registerProperty.category.pageDescription', + defaultMessage: + 'Hér þarft þú að velja tegund og flokkun leiguhúsnæðisins.', + description: 'Property category page description', + }, + + typeTitle: { + id: 'ra.application:registerProperty.category.typeTitle', + defaultMessage: 'Tegund húsnæðis', + description: 'Title for property type', + }, + typeDescription: { + id: 'ra.application:registerProperty.category.typeDescription', + defaultMessage: + 'Veldu hér hvort um er að ræða heila íbúð, herbergi eða atvinnuhúsnæði.', + description: 'Description for property type', + }, + typeSelectLabelEntireHome: { + id: 'ra.application:registerProperty.category.typeSelectLabelEntireHome', + defaultMessage: 'Íbúð / Einbýlishús', + description: 'Label for entire home select option', + }, + typeSelectLabelRoom: { + id: 'ra.application:registerProperty.category.typeSelectLabelRoom', + defaultMessage: 'Herbergi', + description: 'Label for room select option', + }, + typeSelectLabelCommercial: { + id: 'ra.application:registerProperty.category.typeSelectLabelCommercial', + defaultMessage: 'Atvinnuhúsnæði', + description: 'Label for commercial select option', + }, + + classTitle: { + id: 'ra.application:registerProperty.category.classTitle', + defaultMessage: 'Flokkun húsnæðis', + description: 'Title for property class', + }, + classDescription: { + id: 'ra.application:registerProperty.category.classDescription', + defaultMessage: + 'Veldu hér hvort húsnæðið sé á almennum leigumarkaði eða fyrir sérstaka hópa, t.d. námsfólk, eldri borgara eða tekjulægri hópa.', + description: 'Description for property class', + }, + classSelectLabelGeneralMarket: { + id: 'ra.application:registerProperty.category.classSelectLabelGeneralMarket', + defaultMessage: 'Almennur leigumarkaður', + description: 'Label for general market select option', + }, + classSelectLabelSpecialGroups: { + id: 'ra.application:registerProperty.category.classSelectLabelSpecialGroups', + defaultMessage: 'Húsnæði fyrir sérstaka hópa', + description: 'Label for special groups select option', + }, + + classGroupLabel: { + id: 'ra.application:registerProperty.category.classGroupLabel', + defaultMessage: 'Sérstakur flokkur húsnæðis', + description: 'Label for property class group select', + }, + classGroupPlaceholder: { + id: 'ra.application:registerProperty.category.classGroupPlaceholder', + defaultMessage: 'Veldu', + description: 'Placeholder for property class group select', + }, + classGroupSelectLabelStudentHousing: { + id: 'ra.application:registerProperty.category.classGroupSelectLabelStudentHousing', + defaultMessage: 'Námsmannaíbúðir', + description: 'Label for student housing select option', + }, + classGroupSelectLabelSeniorCitizenHousing: { + id: 'ra.application:registerProperty.category.classGroupSelectLabelSeniorCitizenHousing', + defaultMessage: 'Íbúðir fyrir eldri borgara', + description: 'Label for senior citizen housing select option', + }, + classGroupSelectLabelCommune: { + id: 'ra.application:registerProperty.category.classGroupSelectLabelCommune', + defaultMessage: 'Sambýli', + description: 'Label for commune select option', + }, + classGroupSelectLabelHalfwayHouse: { + id: 'ra.application:registerProperty.category.classGroupSelectLabelHalfwayHouse', + defaultMessage: 'Áfangaheimili', + description: 'Label for halfway house select option', + }, + classGroupSelectLabelSocialHousing: { + id: 'ra.application:registerProperty.category.classGroupSelectLabelSocialHousing', + defaultMessage: 'Félagslegt húsnæði', + description: 'Label for social housing select option', + }, + classGroupSelectLabelIncomeBasedHousing: { + id: 'ra.application:registerProperty.category.classGroupSelectLabelIncomeBasedHousing', + defaultMessage: 'Tekjumarksíbúð', + description: 'Label for income based housing select option', + }, + classGroupSelectLabelEmployeeHousing: { + id: 'ra.application:registerProperty.category.classGroupSelectLabelEmployeeHousing', + defaultMessage: 'Starfsmannaíbúð eða -herbergi', + description: 'Label for employee housing select option', + }, + + // Error messages + classGroupRequiredError: { + id: 'ra.application:registerProperty.category.categoryClassGroupError', + defaultMessage: 'Veldu flokk húsnæðis', + description: + 'Error message when property category class group is not selected', + }, + }), +} diff --git a/libs/application/templates/rental-agreement/src/lib/messages/housing/specialProvisions.ts b/libs/application/templates/rental-agreement/src/lib/messages/housing/specialProvisions.ts new file mode 100644 index 000000000000..3bbaf998834f --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/housing/specialProvisions.ts @@ -0,0 +1,70 @@ +import { defineMessages } from 'react-intl' + +export const specialProvisions = { + subsection: defineMessages({ + name: { + id: 'ra.application:specialProvisions.subSection.name', + defaultMessage: 'Sérákvæði', + description: 'Special provisions sub section name', + }, + pageTitle: { + id: 'ra.application:specialProvisions.subSection.pageTitle', + defaultMessage: 'Nánari lýsing og sérákvæði', + description: 'Special provisions page title', + }, + pageDescription: { + id: 'ra.application:specialProvisions.subSection.pageDescription', + defaultMessage: + 'Hér má taka fram hvað fylgir húsnæðinu, hvort húsreglur séu til staðar eða önnur ákvæði sem fylgja samningnum. Athugið að þau ákvæði sem eru andstætt húsaleigulögum munu ekki hafa gildi í túlkun leigusamningsins. [Sjá nánar hér](https://www.althingi.is/lagas/nuna/1994036.html).', + description: 'Special provisions page description', + }, + }), + + housingInfo: defineMessages({ + title: { + id: 'ra.application:specialProvisions.housingInfo.title', + defaultMessage: 'Lýsing á húsnæðinu og því sem með fylgir ', + description: 'Special provisions housing description title', + }, + tooltip: { + id: 'ra.application:specialProvisions.housingInfo.tooltip', + defaultMessage: + 'Fylgja húsgögn? Ertu að leigja hluta af húsnæðinu? Annað sem skiptir máli?', + description: 'Special provisions housing description title tooltip', + }, + inputLabel: { + id: 'ra.application:specialProvisions.housingInfo.inputLabel', + defaultMessage: 'Lýsing á húsnæði', + description: 'Special provisions housing description input', + }, + inputPlaceholder: { + id: 'ra.application:specialProvisions.housingInfo.inputPlaceholder', + defaultMessage: 'Skrifaðu hér lýsingu á húsnæðinu ', + description: 'Special provisions housing description input placeholder', + }, + }), + + housingRules: defineMessages({ + title: { + id: 'ra.application:specialProvisions.housingRules.title', + defaultMessage: 'Sérákvæði eða húsreglur ', + description: 'Special provisions housing rules title', + }, + tooltip: { + id: 'ra.application:specialProvisions.housingRules.tooltip', + defaultMessage: + 'Eru einhvern önnur ákvæði sem eiga að vera í samningnum og eru í samræmi við húsaleigulög? T.d. eru gæludýr leyfð? Reykingar? Sérreglur um umgengni húsnæðisins?', + description: 'Special provisions housing rules title tooltip', + }, + inputLabel: { + id: 'ra.application:specialProvisions.housingRules.inputLabel', + defaultMessage: 'Sérákvæði', + description: 'Special provisions housing rules input', + }, + inputPlaceholder: { + id: 'ra.application:specialProvisions.housingRules.inputPlaceholder', + defaultMessage: 'Skrifaðu hér allt sem á við', + description: 'Special provisions housing rules input placeholder', + }, + }), +} diff --git a/libs/application/templates/rental-agreement/src/lib/messages/housing/tenantDetails.ts b/libs/application/templates/rental-agreement/src/lib/messages/housing/tenantDetails.ts new file mode 100644 index 000000000000..13748514f7f3 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/housing/tenantDetails.ts @@ -0,0 +1,89 @@ +import { defineMessages } from 'react-intl' + +export const tenantDetails = defineMessages({ + subSectionName: { + id: 'ra.application:tenantDetails.subSectionName', + defaultMessage: 'Leigjandi', + description: 'Tenant Details sub section name', + }, + pageTitle: { + id: 'ra.application:tenantDetails.pageTitle', + defaultMessage: 'Skrá leigjanda', + description: 'Tenant Details page title', + }, + pageDescription: { + id: 'ra.application:tenantDetails.pageDescription', + defaultMessage: + 'Hér skal skrá leigjendur í húsnæðinu. Hægt er að bæta við eins mörgum leigjendum á samninginn eins og óskað er eftir.', + description: 'Tenant Details page description', + }, + nationalIdInputLabel: { + id: 'ra.application:tenantDetails.nationalIdLabel', + defaultMessage: 'Kennitala leigjanda', + description: 'Tenant Details national id input label', + }, + nationalIdHeaderLabel: { + id: 'ra.application:tenantDetails.nationalIdHeaderLabel', + defaultMessage: 'Kennitala', + description: 'Tenant details national id header label', + }, + nameInputLabel: { + id: 'ra.application:tenantDetails.nameLabel', + defaultMessage: 'Fullt nafn', + description: 'Tenant Details name input label', + }, + emailInputLabel: { + id: 'ra.application:tenantDetails.emailLabel', + defaultMessage: 'Netfang', + description: 'Tenant Details email input label', + }, + phoneInputLabel: { + id: 'ra.application:tenantDetails.phoneLabel', + defaultMessage: 'Símanúmer', + description: 'Tenant Details phone input label', + }, + addressInputLabel: { + id: 'ra.application:tenantDetails.addressInputLabel', + defaultMessage: 'Heimilisfang', + description: 'Tenant details address input label', + }, + representativeLabel: { + id: 'ra.application:tenantDetails.representativeLabel', + defaultMessage: 'Þessi aðili er umboðsaðili leigjanda', + description: 'Tenant Details representative label', + }, + + // DataSchema errors + tenantEmptyTableError: { + id: 'ra.application:tenantDetails.tenantEmptyTableError', + defaultMessage: + 'Að minnsta kosti einn leigutaki þarf að vera skráður á leigusamninginn.', + description: 'Tenant details no tenants in table', + }, + tenantOnlyRepresentativeTableError: { + id: 'ra.application:tenantDetails.tenantOnlyRepresentativeTableError', + defaultMessage: + 'Að minnsta kosti einn leigutaki þarf að vera skráður á leigusamninginn. Ekki er nóg að skrá umboðsaðlia leigusala.', + description: 'Tenant details only a representative of tenant in table', + }, + tenantNationalIdEmptyError: { + id: 'ra.application:tenantDetails.tenantNationalIdEmptyError', + defaultMessage: 'Kennitala leigutaka þarf að vera skráð', + description: 'Tenant details national id empty error', + }, + tenantPhoneNumberEmptyError: { + id: 'ra.application:tenantDetails.tenantPhoneNumberEmptyError', + defaultMessage: 'Símanúmer leigutaka þarf að vera skráð', + description: 'Tenant details phone number empty error', + }, + tenantEmailEmptyError: { + id: 'ra.application:tenantDetails.tenantEmailEmptyError', + defaultMessage: 'Netfang leigutaka þarf að vera skráð', + description: 'Tenant details email empty error', + }, + tenantAddressEmptyError: { + id: 'ra.application:tenantDetails.tenantAddressEmptyError', + defaultMessage: 'Heimilisfang leigutaka þarf að vera skráð', + description: 'Tenant details address empty error', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/housing/userRole.ts b/libs/application/templates/rental-agreement/src/lib/messages/housing/userRole.ts new file mode 100644 index 000000000000..ff50eb840973 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/housing/userRole.ts @@ -0,0 +1,30 @@ +import { defineMessages } from 'react-intl' + +export const userRole = defineMessages({ + subSectionName: { + id: 'ra.application:userRole.subSectionName', + defaultMessage: 'Aðillar samnings', + description: 'User role sub section name', + }, + pageTitle: { + id: 'ra.application:userRole.pageTitle', + defaultMessage: 'Aðillar samnings', + description: 'User role page title', + }, + pageDescription: { + id: 'ra.application:userRole.pageDescription', + defaultMessage: + 'Til að hægt sé að sækja réttar upplýsingar um þig biðjum við þig um að gera grein fyrir því hvort þú sért leigusali eða leigjandi.', + description: 'User role page description', + }, + landlordOptionLabel: { + id: 'ra.application:userRole.landlordOptionLabel', + defaultMessage: 'Ég er leigusali / í umboði leigusala', + description: 'Landlord option label', + }, + tenantOptionLabel: { + id: 'ra.application:userRole.tenantdOptionLabel', + defaultMessage: 'Ég er leigjandi / í umboði leigjanda', + description: 'Tenant option label', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/index.ts b/libs/application/templates/rental-agreement/src/lib/messages/index.ts new file mode 100644 index 000000000000..1b556d4aa03d --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/index.ts @@ -0,0 +1,15 @@ +export * from './dataSchema' +export * from './prerequisites' +export * from './housing/registerProperty' +export * from './housing/landlordDetails' +export * from './housing/userRole' +export * from './housing/tenantDetails' +export * from './housing/specialProvisions' +export * from './housing/housingCondition' +export * from './housing/housingFireProtections' +export * from './rentalInfo/rentalPeriod' +export * from './rentalInfo/rentalAmount' +export * from './rentalInfo/securityDeposit' +export * from './rentalInfo/otherFees' +export * from './summary' +export * from './signatureInfo' diff --git a/libs/application/templates/rental-agreement/src/lib/messages/prerequisites.ts b/libs/application/templates/rental-agreement/src/lib/messages/prerequisites.ts new file mode 100644 index 000000000000..5f57b3d2dab9 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/prerequisites.ts @@ -0,0 +1,105 @@ +import { defineMessages } from 'react-intl' + +export const application = defineMessages({ + name: { + id: 'ra.application:application.name', + defaultMessage: 'Leigusamningur', + description: `Name of rental agreement application`, + }, + housingSectionName: { + id: 'ra.application:application.housingSectionName', + defaultMessage: 'Húsnæðið', + description: `Name of housing section`, + }, + rentalPeriodSectionName: { + id: 'ra.application:application.rentalPeriodSectionName', + defaultMessage: 'Tímabil og verð', + description: `Name of rental period section`, + }, + summarySectionName: { + id: 'ra.application:application.summarySectionName', + defaultMessage: 'Samantekt', + description: `Name of summary section`, + }, + signingSectionName: { + id: 'ra.application:application.signingSectionName', + defaultMessage: 'Undirritun', + description: `Name of signing section`, + }, +}) + +export const prerequisites = { + intro: defineMessages({ + sectionTitle: { + id: 'ra.application:prerequisites.intro.sectionTitle', + defaultMessage: 'Forsendur', + description: 'Section title for intro', + }, + subSectionTitle: { + id: 'ra.application:prerequisites.intro.subSectionTitle', + defaultMessage: 'Upplýsingar', + description: 'Subsection title for intro', + }, + pageTitle: { + id: 'ra.application:prerequisites.intro.pageTitle', + defaultMessage: 'Þú ert að fara að gera rafrænan húsaleigusamning', + description: 'Page title for intro', + }, + text: { + id: 'ra.application:prerequisites.intro.text#markdown', + defaultMessage: + 'Mikilvægt er að hafa í huga að í samningnum þurfa að koma fram öll þau atriði sem aðilar samningsins eru sammála um og skipta máli við skilgreiningar og skýringar á því um hvað samningurinn snýst.', + description: 'Introductory text about the application', + }, + bullets: { + id: 'ra.application:prerequisites.intro.bullets#markdown', + defaultMessage: + '- Leigusamningur er skráður í Leiguskrá HMS þegar allir aðilar samningsins hafa undirritað rafrænt. \n- Skráning leigusamnings í Leiguskrá HMS er ein forsenda þess að leigjandi geti fengið greiddar húsnæðisbætur. \n- Hægt er að sækja um húsnæðisbætur samhliða skráningu á leigusamningnum og því þinglýsing óþörf. \n- Með rafrænni skráningu eru vottar óþarfi. \n- Staðfesting á brunavörnum og ástandi húsnæðis er hluti af leigusamningnum', + description: 'First bullet point about the application', + }, + }), + externalData: defineMessages({ + sectionTitle: { + id: 'ra.application:prerequisites.externalData.sectionTitle', + defaultMessage: 'Gagnaöflun', + description: 'Section title for external data', + }, + pageTitle: { + id: 'ra.application:prerequisites.externalData.pageTitle', + defaultMessage: 'Gagnaöflun', + description: 'Page title for external data', + }, + subTitle: { + id: 'ra.application:prerequisites.externalData.subTitle', + defaultMessage: 'Eftirfarandi gögn verða sótt rafrænt með þínu samþykki', + description: 'Explanation about the external data collection', + }, + checkboxLabel: { + id: 'ra.application:prerequisites.externalData.checkboxLabel', + defaultMessage: + 'Ég skil að ofangreindra gagna verður aflað í samningsferlinu', + description: 'Text for external data collection approval', + }, + nationalRegistryTitle: { + id: 'ra.application:prerequisites.externalData.nationalRegistryTitle', + defaultMessage: 'Þjóðskrá', + description: 'Title for national registry data collection', + }, + nationalRegistrySubTitle: { + id: 'ra.application:prerequisites.externalData.nationalRegistrySubTitle', + defaultMessage: 'Upplýsingar um lögheimili og hjúskaparstöðu.', + description: 'Subtitle for national registry data collection', + }, + currentApplicationTitle: { + id: 'ra.application:prerequisites.externalData.currentApplicationTitle', + defaultMessage: 'Mínar upplýsingar á Mínum síðum Ísland.is', + description: 'Title for current application data collection', + }, + currentApplicationSubTitle: { + id: 'ra.application:prerequisites.externalData.currentApplicationSubTitle', + defaultMessage: + 'Upplýsingar um símanúmer og netfang til að auðvelda samningagerðina.', + description: 'Subtitle for current application data collection', + }, + }), +} diff --git a/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/otherFees.ts b/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/otherFees.ts new file mode 100644 index 000000000000..7fcb40b33861 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/otherFees.ts @@ -0,0 +1,192 @@ +import { defineMessages } from 'react-intl' + +export const otherFees = defineMessages({ + subSectionName: { + id: 'ra.application:otherFees.subSectionName', + defaultMessage: 'Önnur gjöld', + description: 'Other fees sub section name', + }, + pageTitle: { + id: 'ra.application:otherFees.pageTitle', + defaultMessage: 'Önnur gjöld', + description: 'Other fees page title', + }, + pageDescription: { + id: 'ra.application:otherFees.pageDescription', + defaultMessage: + 'Það er mismunandi hvort leigjandi eða leigusali greiði fyrir gjöld eins og hússjóð, rafmagns- eða hitakostnað.', + description: 'Other fees page description', + }, + paidByTenantLabel: { + id: 'ra.application:otherFees.paidByTenantLabel', + defaultMessage: 'Greitt af leigjanda', + description: 'Label for paid by tenant', + }, + paidByLandlordLabel: { + id: 'ra.application:otherFees.paidByLandlordLabel', + defaultMessage: 'Greitt af leigusala', + description: 'Label for paid by landlord', + }, + housingFundPayedByLandlordLabel: { + id: 'ra.application:otherFees.housingFundPayedByTenantLabel', + defaultMessage: 'Greitt af leigusala / Á ekki við', + description: 'Label for housing fund payed by tenant', + }, + housingFundTitle: { + id: 'ra.application:otherFees.housingFundTitle', + defaultMessage: 'Hússjóður', + description: 'Housing fund title', + }, + housingFundCheckboxLabel: { + id: 'ra.application:otherFees.housingFundCheckboxLabel', + defaultMessage: 'Greitt er í hússjóð', + description: 'Housing fund checkbox label', + }, + housingFundAmountLabel: { + id: 'ra.application:otherFees.housingFundAmountLabel', + defaultMessage: 'Upphæð á mánuði', + description: 'Housing fund amount label', + }, + housingFundAmountPlaceholder: { + id: 'ra.application:otherFees.housingFundAmountPlaceholder', + defaultMessage: 'Skrifaðu upphæð í tölustöfum', + description: 'Housing fund amount placeholder', + }, + // Electricity cost fields translations + electricityCostTitle: { + id: 'ra.application:otherFees.electricityCostTitle', + defaultMessage: 'Rafmagnskostnaður', + description: 'Electricity cost title', + }, + electricityCostMeterNumberLabel: { + id: 'ra.application:otherFees.electricityCostMeterNumberLabel', + defaultMessage: 'Númer rafmagnsmælis', + description: 'Electricity cost meter number label', + }, + electricityCostMeterNumberPlaceholder: { + id: 'ra.application:otherFees.electricityCostMeterNumberPlaceholder', + defaultMessage: 'Skráðu númer mælis', + description: 'Electricity cost meter number placeholder', + }, + electricityCostMeterStatusLabel: { + id: 'ra.application:otherFees.electricityCostMeterStatusLabel', + defaultMessage: 'Staða rafmagnsmælis', + description: 'Electricity cost meter status label', + }, + electricityCostMeterStatusPlaceholder: { + id: 'ra.application:otherFees.electricityCostMeterStatusPlaceholder', + defaultMessage: 'Staða mælis', + description: 'Electricity cost meter status placeholder', + }, + electricityCostMeterStatusDateLabel: { + id: 'ra.application:otherFees.electricityCostMeterStatusDateLabel', + defaultMessage: 'Dagsetning aflesturs', + description: 'Electricity cost meter status date label', + }, + electricityCostMeterStatusDatePlaceholder: { + id: 'ra.application:otherFees.electricityCostMeterStatusDatePlaceholder', + defaultMessage: 'Dagsetning', + description: 'Electricity cost meter status date placeholder', + }, + + // Heating cost fields translations + heatingCostTitle: { + id: 'ra.application:otherFees.heatingCostTitle', + defaultMessage: 'Hitakostnaður', + description: 'Heating cost title', + }, + heatingCostMeterNumberLabel: { + id: 'ra.application:otherFees.heatingCostMeterNumberLabel', + defaultMessage: 'Númer hitamælis', + description: 'Heating cost meter number label', + }, + heatingCostMeterNumberPlaceholder: { + id: 'ra.application:otherFees.heatingCostMeterNumberPlaceholder', + defaultMessage: 'Skráðu númer mælis', + description: 'Heating cost meter number placeholder', + }, + heatingCostMeterStatusLabel: { + id: 'ra.application:otherFees.heatingCostMeterStatusLabel', + defaultMessage: 'Staða hitamælis', + description: 'Heating cost meter status label', + }, + heatingCostMeterStatusPlaceholder: { + id: 'ra.application:otherFees.heatingCostMeterStatusPlaceholder', + defaultMessage: 'Staða mælis', + description: 'Heating cost meter status placeholder', + }, + heatingCostMeterStatusDateLabel: { + id: 'ra.application:otherFees.heatingCostMeterStatusDateLabel', + defaultMessage: 'Dagsetning aflesturs', + description: 'Heating cost meter status date label', + }, + heatingCostMeterStatusDatePlaceholder: { + id: 'ra.application:otherFees.heatingCostMeterStatusDatePlaceholder', + defaultMessage: 'Dagsetning', + description: 'Heating cost meter status date placeholder', + }, + + // Other cost fields translations + otherCostsTitle: { + id: 'ra.application:otherFees.otherCostsTitle', + defaultMessage: 'Annað', + description: 'Other costs title', + }, + otherCostsLabel: { + id: 'ra.application:otherFees.otherCostsLabel', + defaultMessage: 'Skrá annan kostnað sem leigjandi greiðir', + description: 'Other costs label', + }, + otherCostsDescriptionLabel: { + id: 'ra.application:otherFees.otherCostsDescriptionLabel', + defaultMessage: 'Kostnaðarliður', + description: 'Other costs description label', + }, + otherCostsDescriptionPlaceholder: { + id: 'ra.application:otherFees.otherCostsDescriptionPlaceholder', + defaultMessage: 'Hvað er verið að borga fyrir?', + description: 'Other costs description placeholder', + }, + otherCostsAmountLabel: { + id: 'ra.application:otherFees.otherCostsAmountLabel', + defaultMessage: 'Upphæð', + description: 'Other costs amount label', + }, + otherCostsAmountPlaceholder: { + id: 'ra.application:otherFees.otherCostsAmountPlaceholder', + defaultMessage: 'Upphæð í tölustöfum', + description: 'Other costs amount placeholder', + }, + + // Error messages + errorHousingFundEmpty: { + id: 'ra.application:dataSchema.errorHousingFundEmpty', + defaultMessage: 'Þú verður að slá inn mánaðarlega upphæð fyrir hússjóð', + description: 'Error message when housing fund amount is empty', + }, + errorMeterNumberEmpty: { + id: 'ra.application:dataSchema.errorMeterNumberEmpty', + defaultMessage: 'Númer mælis þarf að vera skráð', + description: 'Error message when meter number is empty', + }, + errorMeterStatusEmpty: { + id: 'ra.application:dataSchema.errorMeterStatusEmpty', + defaultMessage: 'Staða mælis verður að vera skráð', + description: 'Error message when meter status is empty', + }, + errorMeterStatusDateEmpty: { + id: 'ra.application:dataSchema.errorMeterStatusDateEmpty', + defaultMessage: 'Dagsetning aflesturs verður að vera skráð', + description: 'Error message when meter status date is empty', + }, + errorMeterNumberRegex: { + id: 'ra.application:dataSchema.errorMeterNumberRegex', + defaultMessage: 'Sláðu inn númer í tölustöfum', + description: 'Error message when meter number is not valid', + }, + errorMeterStatusRegex: { + id: 'ra.application:dataSchema.errorMeterStatusRegex', + defaultMessage: 'Sláðu inn stöðu í tölustöfum með mest einum aukastaf', + description: 'Error message when meter status is not valid', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/rentalAmount.ts b/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/rentalAmount.ts new file mode 100644 index 000000000000..c5a21bd7e721 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/rentalAmount.ts @@ -0,0 +1,221 @@ +import { defineMessages } from 'react-intl' + +export const rentalAmount = defineMessages({ + subSectionName: { + id: 'ra.application:rentalAmount.subSectionName', + defaultMessage: 'Verð', + description: 'Rental amount sub section name', + }, + pageTitle: { + id: 'ra.application:rentalAmount.pageTitle', + defaultMessage: 'Upphæð leigu', + description: 'Rental amount page title', + }, + pageDescription: { + id: 'ra.application:rentalAmount.pageDescription', + defaultMessage: + 'Hér er einungis átt við verð fyrir bein leiguafnot. Gjöld fyrir hússjóð, rafmagns- og hitakostnað sem og tryggingar eru skráð í næstu skrefum.', + description: 'Rental amount page description', + }, + + // Rental amount + infoTitle: { + id: 'ra.application:rentalAmount.infoTitle', + defaultMessage: 'Mánaðarlegt leiguverð fyrir afnot á húsnæðinu', + description: 'Rental amount title', + }, + inputLabel: { + id: 'ra.application:rentalAmount.inputLabel', + defaultMessage: 'Leiguverð', + description: 'Rental amount input label', + }, + inputPlaceholder: { + id: 'ra.application:rentalAmount.inputPlaceholder', + defaultMessage: 'Upphæð í tölustöfum', + description: 'Rental amount input placeholder', + }, + + // Indexation + priceIndexLabel: { + id: 'ra.application:rentalAmount.priceIndexLabel', + defaultMessage: 'Leiguverð fylgir vísitölu', + description: 'Rental amount price index checkbox label', + }, + indexOptionsLabel: { + id: 'ra.application:rentalAmount.indexOptionsLabel', + defaultMessage: 'Vísitala', + description: 'Rental amount index options label', + }, + indexOptionConsumerPriceIndex: { + id: 'ra.application:rentalAmount.indexOptionConsumerPriceIndex', + defaultMessage: 'Vísitala neysluverðs', + description: 'Rental amount consumer price index option', + }, + indexOptionConstructionCostIndex: { + id: 'ra.application:rentalAmount.indexOptionConstructionCostIndex', + defaultMessage: 'Byggingarvísitala', + description: 'Rental amount construction cost index option', + }, + indexOptionWageIndex: { + id: 'ra.application:rentalAmount.indexOptionWageIndex', + defaultMessage: 'Launavísitala', + description: 'Rental amount wage index option', + }, + indexDateLabel: { + id: 'ra.application:rentalAmount.indexDateLabel', + defaultMessage: 'Útgáfudagur vísitölu', + description: 'Rental amount index type date label', + }, + indexValueLabel: { + id: 'ra.application:rentalAmount.indexValueLabel', + defaultMessage: 'Vísitala við upphaf samnings', + description: 'Rental amount index type value label', + }, + indexValuePlaceholder: { + id: 'ra.application:rentalAmount.indexValuePlaceholder', + defaultMessage: 'Sláðu inn gildi', + description: 'Rental amount index type value placeholder', + }, + + // Payment date + paymentDateTitle: { + id: 'ra.application:rentalAmount.paymentDateTitle', + defaultMessage: 'Mánaðardagur greiðslu', + description: 'Rental amount payment date title', + }, + paymentDateDescription: { + id: 'ra.application:rentalAmount.paymentDateDescription', + defaultMessage: + 'Algengast er að leiga sé greidd fyrirfram í upphafi mánaðar, eða eftir á síðasta dag mánaðar.', + description: 'Rental amount payment date description', + }, + paymentDateOptionsLabel: { + id: 'ra.application:rentalAmount.paymentDateOptionsLabel', + defaultMessage: 'Greiðsludagur', + description: 'Rental amount payment date options label', + }, + paymentDateOptionFirstDay: { + id: 'ra.application:rentalAmount.paymentDateOptionFirstDay', + defaultMessage: 'Fyrsti dagur mánaðar', + description: 'Rental amount payment date first day of month option', + }, + paymentDateOptionLastDay: { + id: 'ra.application:rentalAmount.paymentDateOptionLastDay', + defaultMessage: 'Síðasti dagur mánaðar', + description: 'Rental amount payment date last day of month option', + }, + paymentDateOptionOther: { + id: 'ra.application:rentalAmount.paymentDateOptionOther', + defaultMessage: 'Annar mánaðardagur', + description: 'Rental amount payment date other option', + }, + paymentDateOtherOptionLabel: { + id: 'ra.application:rentalAmount.paymentDateOtherOptionLabel', + defaultMessage: 'Annar greiðsludagur', + description: 'Rental amount payment other option date label', + }, + paymentDateOtherOptionPlaceholder: { + id: 'ra.application:rentalAmount.paymentDateOtherOptionPlaceholder', + defaultMessage: 'Dæmi: 5. hvers mánaðar', + description: 'Rental amount payment other option date placeholder', + }, + + // Payment method + paymentMethodTitle: { + id: 'ra.application:rentalAmount.peymentMethodTitle', + defaultMessage: 'Greiðsla', + description: 'Rental amount payment method title', + }, + paymentMethodOptionsLabel: { + id: 'ra.application:rentalAmount.paymentMethodOptionsLabel', + defaultMessage: 'Greiðslufyrirkomulag', + description: 'Rental amount payment method options label', + }, + paymentMethodBankTransferLabel: { + id: 'ra.application:rentalAmount.paymentMethodBankTransferLabel', + defaultMessage: 'Greitt inn á reikning', + description: 'Rental amount payment method bank transfer label', + }, + paymentMethodNationalIdLabel: { + id: 'ra.application:rentalAmount.paymentMethodNationalIdLabel', + defaultMessage: 'Kennitala viðtakanda', + description: 'Rental amount payment method national id label', + }, + paymentMethodBankAccountNumberLabel: { + id: 'ra.application:rentalAmount.paymentMethodBankAccountNumberLabel', + defaultMessage: 'Bankareikningur', + description: 'Rental amount payment method bank account number label', + }, + paymentMethodPaymentSlipLabel: { + id: 'ra.application:rentalAmount.paymentMethodPaymentSlipLabel', + defaultMessage: 'Greitt með greiðsluseðli', + description: 'Rental amount payment method payment slip label', + }, + paymentMethodOtherLabel: { + id: 'ra.application:rentalAmount.paymentMethodOtherLabel', + defaultMessage: 'Annað', + description: 'Rental amount payment method other label', + }, + paymentMethodOtherTextFieldLabel: { + id: 'ra.application:rentalAmount.paymentMethodOtherTextFieldLabel', + defaultMessage: 'Lýsing', + description: 'Rental amount payment method other text field label', + }, + + // Payment insurance + paymentInsuranceTitle: { + id: 'ra.application:rentalAmount.paymentInsuranceTitle', + defaultMessage: 'Trygging', + description: 'Rental amount payment insurance title', + }, + paymentInsuranceRequiredLabel: { + id: 'ra.application:rentalAmount.paymentInsuranceRequiredLabel', + defaultMessage: 'Tryggingar er krafist við upphaf leigutíma', + description: 'Rental amount payment insurance option label', + }, + + // Error messages + indexValueRequiredError: { + id: 'ra.application:rentalAmount.indexValueRequiredError', + defaultMessage: 'Sláðu inn vísitölu', + description: 'Rental amount index value required error', + }, + indexValueValidationError: { + id: 'ra.application:rentalAmount.indexValueRequiredError', + defaultMessage: 'vísitala má aðeins innihalda tölustafi með einum aukastaf', + description: 'Rental amount index value required error', + }, + paymentDateOtherOptionRequiredError: { + id: 'ra.application:rentalAmount.paymentDateOtherOptionRequiredError', + defaultMessage: 'Sláðu inn mánaðardag greiðslu', + description: 'Rental amount payment date other option required error', + }, + + paymentMethodNationalIdRequiredError: { + id: 'ra.application:rentalAmount.paymentMethodNationalIdRequiredError', + defaultMessage: 'Kennitala viðtakanda þarf að vera til staðar', + description: 'Rental amount payment method national id required error', + }, + paymentMethodNationalIdInvalidError: { + id: 'ra.application:rentalAmount.paymentMethodNationalIdInvalidError', + defaultMessage: 'Kennitala viðtakanda er ekki á réttu formi', + description: 'Rental amount payment method national id invalid error', + }, + paymentMethodBankAccountNumberRequiredError: { + id: 'ra.application:rentalAmount.paymentMethodBankAccountNumberRequiredError', + defaultMessage: 'Bankareikningur viðtakanda þarf að vera til staðar', + description: + 'Rental amount payment method bank account number required error', + }, + paymentMethodBankAccountNumberInvalidError: { + id: 'ra.application:rentalAmount.paymentMethodBankAccountNumberInvalidError', + defaultMessage: 'Upplýsingar um bankareikning eru ekki fullnægjandi', + description: + 'Rental amount payment method bank account number invalid error', + }, + paymentMethodOtherTextFieldRequiredError: { + id: 'ra.application:rentalAmount.paymentMethodOtherTextFieldRequiredError', + defaultMessage: 'Lýsing á greiðslufyrirkomulagi þarf að vera til staðar', + description: 'Rental amount payment method other text field required error', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/rentalPeriod.ts b/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/rentalPeriod.ts new file mode 100644 index 000000000000..019cfeab8434 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/rentalPeriod.ts @@ -0,0 +1,77 @@ +import { defineMessages } from 'react-intl' + +export const rentalPeriod = defineMessages({ + subSectionName: { + id: 'ra.application:rentalPeriodDetails.subSectionName', + defaultMessage: 'Tímabil', + description: 'Rental period sub section name', + }, + pageTitle: { + id: 'ra.application:rentalPeriodDetails.pageTitle', + defaultMessage: 'Tímabil', + description: 'Rental period page title', + }, + pageDescription: { + id: 'ra.application:rentalPeriodDetails.pageDescription', + defaultMessage: + 'Veldu upphafsdag leigusamnings og fyrirkomulag. Hægt er gera ótímabundinn samning með 6 mánaða uppsagnarfresti, eða tímabundinn samning með lokadagsetningu.', + description: 'Rental period page description', + }, + startDateTitle: { + id: 'ra.application:rentalPeriodDetails.startDateTitle', + defaultMessage: 'Upphafsdagur samnings', + description: 'Start date title', + }, + startDatePlaceholder: { + id: 'ra.application:rentalPeriodDetails.startDatePlaceholder', + defaultMessage: 'Veldu dagsetningu', + description: 'Start date placeholder', + }, + endDateTitle: { + id: 'ra.application:rentalPeriodDetails.endDateTitle', + defaultMessage: 'Lokadagur samnings', + description: 'End date title', + }, + endDatePlaceholder: { + id: 'ra.application:rentalPeriodDetails.endDatePlaceholder', + defaultMessage: 'Veldu dagsetningu', + description: 'End date placeholder', + }, + + rentalPeriodDefiniteLabel: { + id: 'ra.application:rentalPeriodDetails.rentalPeriodDefinite', + defaultMessage: 'Tímabundinn leigusamningur', + description: 'Rental period definite', + }, + + terminationLabel: { + id: 'ra.application:rentalPeriodDetails.terminationLabel', + defaultMessage: 'Uppsagnarfrestur', + description: 'Rental period termination label', + }, + + terminationDescription: { + id: 'ra.application:rentalPeriodDetails.terminationDescription#markdown', + defaultMessage: + 'Lögbundinn uppsagnarfrestur ótímabundinna samninga eru **6 mánuðir**. Sé leigusamningur tímabundinn lýkur honum án sérstakrar uppsagnar nema um annað sé samið. \n\n Tilgreina þarf þær ástæður sem geta leitt til uppsagnar tímabundins húsaleigusamnings í sérákvæðum, en uppsagnarfrestur tímabundins húsaleigusamnings skal þó vera a.m.k. **3 mánuðir**.', + description: 'Rental period termination description', + }, + + // Error messages + errorAgreementStartDateNotFilled: { + id: 'ra.application:dataSchema.errorStartDateNotFilled', + defaultMessage: 'Veldu upphafsdag samnings', + description: 'Error message when start date is not filled', + }, + errorAgreementEndDateNotFilled: { + id: 'ra.application:dataSchema.errorEndDateNotFilled', + defaultMessage: 'Veldu síðasta dag samnings', + description: 'Error message when end date is not filled', + }, + errorEndDateBeforeStart: { + id: 'ra.application:dataSchema.errorEndDateBeforeStart', + defaultMessage: + 'Loka dagur samnings má ekki vera sami eða fyrir upphafsdag samnings', + description: 'Error message when end date is before start date', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/securityDeposit.ts b/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/securityDeposit.ts new file mode 100644 index 000000000000..551a6c2370ad --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/rentalInfo/securityDeposit.ts @@ -0,0 +1,230 @@ +import { defineMessages } from 'react-intl' + +export const securityDeposit = defineMessages({ + subSectionName: { + id: 'ra.application:securityDeposit.subSectionName', + defaultMessage: 'Trygging', + description: 'security deposit sub section name', + }, + pageTitle: { + id: 'ra.application:securityDeposit.pageTitle', + defaultMessage: 'Trygging', + description: 'security deposit page title', + }, + pageDescription: { + id: 'ra.application:securityDeposit.pageDescription', + defaultMessage: + 'Leigusalar krefjast oft tryggingar annað hvort í formi millifærslu eða bankaábyrgðar. Hér þarf einnig að skrá hve há tryggingin er.', + description: 'security deposit page description', + }, + typeHeaderTitle: { + id: 'ra.application:securityDeposit.typeHeaderTitle', + defaultMessage: 'Tegund tryggingar', + description: 'security deposit type header title', + }, + typeHeaderToolTip: { + id: 'ra.application:securityDeposit.typeHeaderToolTip', + defaultMessage: + 'Áður en afhending hins leigða húsnæðis fer fram er leigusala rétt að krefjast þess að leigjandi setji honum tryggingu fyrir réttum efndum á leigusamningnum, þ.e. fyrir leigugreiðslum og skaðabótum vegna tjóns á hinu leigða sem leigjandi ber ábyrgð á samkvæmt ákvæðum laga þessara eða almennum reglum.', + description: 'security deposit type header tool tip', + }, + typeSelectionTitle: { + id: 'ra.application:securityDeposit.typeSelectionTitle', + defaultMessage: 'Tegund tryggingar ', + description: 'security deposit type selection title', + }, + typeSelectionPlaceholder: { + id: 'ra.application:securityDeposit.typeSelectionPlaceholder', + defaultMessage: 'Veldu tegund', + description: 'security deposit type selection placeholder', + }, + typeSelectionBankGuaranteeTitle: { + id: 'ra.application:securityDeposit.typeSelectionBankGuaranteeTitle', + defaultMessage: 'Bankaábyrgð', + description: 'security deposit type selection bank guarantee title', + }, + typeSelectionCapitalTitle: { + id: 'ra.application:securityDeposit.typeSelectionCapitalTitle', + defaultMessage: 'Tryggingarfé', + description: 'security deposit type selection capital title', + }, + typeSelectionThirdPartyGuaranteeTitle: { + id: 'ra.application:securityDeposit.typeSelectionThirdPartyGuaranteeTitle', + defaultMessage: 'Sjálfskuldarábyrgð þriðja aðila', + description: 'security deposit type selection third party guarantee title', + }, + typeSelectionInsuranceCompanyTitle: { + id: 'ra.application:securityDeposit.typeSelectionInsuranceCompanyTitle', + defaultMessage: 'Leigugreiðslu- og viðskilnaðartrygging', + description: 'security deposit type selection insurance company title', + }, + typeSelectionMutualFundTitle: { + id: 'ra.application:securityDeposit.typeSelectionMutualFundTitle', + defaultMessage: 'Gjald í samtryggingarsjóð leigusala', + description: 'security deposit type selection mutual fund title', + }, + typeSelectionOtherTitle: { + id: 'ra.application:securityDeposit.typeSelectionOtherTitle', + defaultMessage: 'Annað', + description: 'security deposit type selection other title', + }, + bankGuaranteeInfoTitle: { + id: 'ra.application:securityDeposit.bankGuaranteeInfoTitle', + defaultMessage: 'Nafn banka eða stofnunar', + description: 'security deposit bank guarantee info title', + }, + bankGuaranteeInfoPlaceholder: { + id: 'ra.application:securityDeposit.bankGuaranteeInfoPlaceholder', + defaultMessage: 'Skrifaðu hér hjá hvaða stofnun ábyrgðin er', + description: 'security deposit bank guarantee info placeholder', + }, + capitalBulletPoints: { + id: 'ra.application:securityDeposit.capitalBulletPoints#markdown', + defaultMessage: + '- Tryggingarfjárhæð getur ekki vera hærri en það sem nemur 3ja mánaða leigufjárhæð. \n- Leigusala er skylt að varðveita tryggingarféð á aðgreindum óbundnum hávaxtareikningi. \n- Féð er í vörslu en ekki eigu leigusala. Leigusali má ekki ráðstafa fénu á neinn hátt á leigutímanum nema upp í leigu sem ekki hefur verið greidd. \n- Í lok leigutímans fær leigjandi féð til baka með vöxtum. Leigusali má ekki draga af því nema endanleg niðurstaða liggi fyrir um bótaskyldu.', + description: 'First bullet point about the application', + }, + thirdPartyGuaranteeInfoTitle: { + id: 'ra.application:securityDeposit.thirdPartyGuaranteeInfoTitle', + defaultMessage: 'Nafn ábyrgðaraðila', + description: 'security deposit third party guarantee info title', + }, + thirdPartyGuaranteeInfoPlaceholder: { + id: 'ra.application:securityDeposit.thirdPartyGuaranteeInfoPlaceholder', + defaultMessage: 'Skrifaðu hér hjá hvaða stofnun ábyrgðin er', + description: 'security deposit third party guarantee info placeholder', + }, + insuranceCompanyInfoTitle: { + id: 'ra.application:securityDeposit.insuranceCompanyInfoTitle', + defaultMessage: 'Nafn tryggingarfélags', + description: 'security deposit third party guarantee info title', + }, + insuranceCompanyInfoPlaceholder: { + id: 'ra.application:securityDeposit.insuranceCompanyInfoPlaceholder', + defaultMessage: + 'Skrifaðu hér hjá hvaða tryggingarfélagi tryggingin er keypt', + description: 'security deposit third party guarantee info placeholder', + }, + mutualFundInfoTitle: { + id: 'ra.application:securityDeposit.mutualFundInfoTitle', + defaultMessage: 'Nafn samtryggingarsjóðs', + description: 'security deposit mutal fund info title', + }, + mutualFundInfoPlaceholder: { + id: 'ra.application:securityDeposit.mutualFundInfoPlaceholder', + defaultMessage: 'Skrifaðu hér nafn samtryggingasjóðsins', + description: 'security deposit mutal fund info placeholder', + }, + otherInfoTitle: { + id: 'ra.application:securityDeposit.otherInfoTitle', + defaultMessage: 'Tegund tryggingar', + description: 'security deposit other info title', + }, + otherInfoPlaceholder: { + id: 'ra.application:securityDeposit.otherInfoPlaceholder', + defaultMessage: 'Skrifaðu hér í hvaða formi tryggingin er', + description: 'security deposit other info placeholder', + }, + amountHeaderTitle: { + id: 'ra.application:securityDeposit.amountHeaderTitle', + defaultMessage: 'Upphæð tryggingar', + description: 'security deposit amount header title', + }, + amountRadioFieldTitle: { + id: 'ra.application:securityDeposit.amountRadioFieldTitle', + defaultMessage: 'Veldu upphæð', + description: 'security deposit amount radio field title', + }, + amountSelection1Month: { + id: 'ra.application:securityDeposit.amountSelection1Month', + defaultMessage: '1 mánuður af leiguverði', + description: 'security deposit amount selection 1 month', + }, + amountSelection2Month: { + id: 'ra.application:securityDeposit.amountSelection1Month', + defaultMessage: '2 mánuðir af leiguverði', + description: 'security deposit amount selection 2 months', + }, + amountSelection3Month: { + id: 'ra.application:securityDeposit.amountSelection3Month', + defaultMessage: '3 mánuðir af leiguverði', + description: 'security deposit amount selection 3 months', + }, + amountSelectionOther: { + id: 'ra.application:securityDeposit.amountSelectionOther', + defaultMessage: 'Önnur upphæð', + description: 'security deposit amount selection other', + }, + mutualFundAmountInfoTitle: { + id: 'ra.application:securityDeposit.mutualFundAmountInfoTitle', + defaultMessage: 'Til upplýsinga', + description: 'security deposit mutual fund amount info title', + }, + mutualFundAmountInfoMessage: { + id: 'ra.application:securityDeposit.mutualFundAmountInfoMessage', + defaultMessage: + 'Gjald í samtryggingasjóð leigusala má ekki vera hærri en 10% af mánaðarlegu leiguverði', + description: 'security deposit mutual fund amount info message', + }, + securityAmountOtherTitle: { + id: 'ra.application:securityDeposit.securityAmountOtherTitle', + defaultMessage: 'Upphæð', + description: 'security deposit security amount other title', + }, + securityAmountOtherPlaceholder: { + id: 'ra.application:securityDeposit.securityAmountOtherPlaceholder', + defaultMessage: 'Upphæð í tölustöfum', + description: 'security deposit security amount other placeholder', + }, + typeError: { + id: 'ra.application:securityDeposit.typeError', + defaultMessage: 'Veldu tegund tryggingar', + description: 'security deposit type not selected error', + }, + bankInfoError: { + id: 'ra.application:securityDeposit.bankInfoError', + defaultMessage: 'Verður að slá inn nafn banka eða stofnunar', + description: 'security deposit bank info not entered error', + }, + thirdPartyGuaranteeError: { + id: 'ra.application:securityDeposit.thirdPartyGuaranteeError', + defaultMessage: 'Verður að slá inn nafn ábyrgðaraðila', + description: 'security deposit third party guarantee not entered error', + }, + insuranceCompanyError: { + id: 'ra.application:securityDeposit.insuranceCompanyError', + defaultMessage: 'Verður að slá inn nafn tryggingarfélags', + description: 'security deposit third party guarantee not entered error', + }, + mutualFundError: { + id: 'ra.application:securityDeposit.mutualFundError', + defaultMessage: 'Verður að slá inn nafn samtryggingarsjóðs', + description: 'security deposit mutual fund not entered error', + }, + otherError: { + id: 'ra.application:securityDeposit.otherError', + defaultMessage: 'Verður að slá inn tegund tryggingar', + description: 'security deposit other not entered error', + }, + amountError: { + id: 'ra.application:securityDeposit.amountError', + defaultMessage: 'Verður að velja upphæð tryggingar', + description: 'security deposit amount not selected error', + }, + amountOtherError: { + id: 'ra.application:securityDeposit.amountOtherError', + defaultMessage: 'Verður að slá inn upphæð tryggingar', + description: 'security deposit amount other not entered error', + }, + amountOtherMutualFundError: { + id: 'ra.application:securityDeposit.amountOtherMutualFundError', + defaultMessage: 'Upphæð tryggingar ef of há', + description: 'security deposit amount other mutual fund error', + }, + amountOtherCapitolError: { + id: 'ra.application:securityDeposit.amountOtherCapitolError', + defaultMessage: + 'Upphæð tryggingar má ekki vera meira en þreföld mánaðarleg leiguupphæð', + description: 'security deposit amount other capitol error', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/signatureInfo.ts b/libs/application/templates/rental-agreement/src/lib/messages/signatureInfo.ts new file mode 100644 index 000000000000..beceffbf3670 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/signatureInfo.ts @@ -0,0 +1,70 @@ +import { defineMessages } from 'react-intl' + +export const signatureInfo = defineMessages({ + sectionName: { + id: 'ra.application:signture.sectionName', + defaultMessage: 'Undirritun', + description: 'Name of the signature section', + }, + pageDescription: { + id: 'ra.application:signture.pageDescription', + defaultMessage: + 'Þegar samningur er sendur í undirritun fá aðilar samnings SMS og tölvupóst frá HMS með beiðni um rafræna undirritun. Þegar allir aðilar hafa undirritað er samningurinn fullkláraður og skráist sjálfkrafa í leiguskrá HMS.', + description: 'Description of the signature page', + }, + infoHeading: { + id: 'ra.application:signture.pageInfoHeading', + defaultMessage: 'Gott að vita', + description: 'Heading for the signature page info', + }, + infoBullets: { + id: 'ra.application:signture.pageInfoBullets#markdown', + defaultMessage: + '- Ekki er hægt að gera breytingar á samningi eftir að búið er að senda í undirritun \n- Ef nauðsynlegt þykir að gera breytingu þarf að útbúa nýjan samning \n- Samningur tekur ekki gildi fyrr en allir aðilar samnings hafa undirritað', + description: 'Bullets for the signature page info', + }, + tableTitle: { + id: 'ra.application:signture.tableTitle', + defaultMessage: 'Aðilar sem undirrita', + description: 'Title for the signature table', + }, + tableHeaderName: { + id: 'ra.application:signture.tableHeaderName', + defaultMessage: 'Fullt nafn', + description: 'Header for the name column in signature table', + }, + tableHeaderId: { + id: 'ra.application:signture.tableHeaderId', + defaultMessage: 'Kennitala', + description: 'Header for the ID column in signature table', + }, + tableHeaderPhone: { + id: 'ra.application:signture.tableHeaderPhone', + defaultMessage: 'Símanúmer', + description: 'Header for the phone column in signature table', + }, + tableHeaderEmail: { + id: 'ra.application:signture.tableHeaderEmail', + defaultMessage: 'Netfang', + description: 'Header for the email column in signature table', + }, + statementLabel: { + id: 'ra.application:signture.statementLabel', + defaultMessage: + 'Ég skil að ekki er hægt að gera breytingar á samningi eftir að búið er að senda í undirritun.', + description: 'Label for the statement checkbox', + }, + submitButtonText: { + id: 'ra.application:signture.submitButtonText', + defaultMessage: 'Senda í undirritun', + description: 'Text on the page submit button', + }, + + // dataSchema errors + statementError: { + id: 'ra.application:signture.statementError', + defaultMessage: + 'Þú þarft að samþykkja skilyrði undirritunar til að halda áfram', + description: 'Error message when statement is not checked', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/signing.ts b/libs/application/templates/rental-agreement/src/lib/messages/signing.ts new file mode 100644 index 000000000000..3ae98ed247a7 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/signing.ts @@ -0,0 +1,36 @@ +import { defineMessages } from 'react-intl' + +export const signing = defineMessages({ + sectionName: { + id: 'ra.application:signingForm.sectionName', + defaultMessage: 'Undirritunarferli', + description: 'Name of the signing section', + }, + pageTitle: { + id: 'ra.application:signingForm.pageTitle', + defaultMessage: 'Undirritunarferli hafið', + description: 'Signing page title', + }, + alertMessageSuccess: { + id: 'ra.application:signingForm.alertMessageSuccess', + defaultMessage: 'Samningurinn hefur verið sendur í undirritun', + description: + 'Success message when the agreement has been sent to Taktikal signatures', + }, + alertMessageError: { + id: 'ra.application:signingForm.alertMessageFailed', + defaultMessage: 'Undirritun mistókst', + description: 'Error message when the signing failed', + }, + pageInfoTitle: { + id: 'ra.application:signingForm.pageInfoTitle', + defaultMessage: 'Hvað gerist næst?', + description: 'Title for the signing page info', + }, + pageInfoDescription: { + id: 'ra.application:signingForm.pageInfoDescription#markdown', + defaultMessage: + '- Allir aðilar samnings fá SMS og tölvupóst með hlekk til að undirrita samninginn rafrænt \n- Hægt er að fylgjast með framvindu undirritunar á Mínum síðum undir Mínar umsóknir \n- Samningur skráist sjálfkrafa í leiguskrá HMS að undirritun lokinni', + description: 'Description for what comes next in the signing process', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/messages/summary.ts b/libs/application/templates/rental-agreement/src/lib/messages/summary.ts new file mode 100644 index 000000000000..0645041e0215 --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/messages/summary.ts @@ -0,0 +1,362 @@ +import { defineMessages } from 'react-intl' + +export const summary = defineMessages({ + sectionName: { + id: 'ra.application:summary.sectionName', + defaultMessage: 'Samantekt', + description: 'Name of the summary section', + }, + pageTitle: { + id: 'ra.application:summary.pageTitle', + defaultMessage: 'Samantekt', + description: 'Title of the summary page', + }, + pageDescription: { + id: 'ra.application:summary.pageDescription', + defaultMessage: + 'Vinsamlegast farðu yfir gögnin hér að neðan til að staðfesta að réttar upplýsingar hafi verið gefnar upp. ', + description: 'Description of the summary page', + }, + changeSectionButtonLabel: { + id: 'ra.application:summary.changeSectionButtonLabel', + defaultMessage: 'Breyta', + description: 'Change section button label', + }, + + // Property address + rentalPropertyIdPrefix: { + id: 'ra.application:summary.rentalPropertyIdPrefix', + defaultMessage: 'Fasteignanúmer: F', + description: 'Property id prefix', + }, + + // Rental period + rentalPeriodStartDateLabel: { + id: 'ra.application:summary.rentalPeriodStartDateLabel', + defaultMessage: 'Upphafsdagur samnings', + description: 'Rental period start date label', + }, + rentalPeriodEndDateLabel: { + id: 'ra.application:summary.rentalPeriodEndDateLabel', + defaultMessage: 'Lokadagur samnings', + description: 'Rental period end date label', + }, + rentalPeriodDefiniteLabel: { + id: 'ra.application:summary.rentalPeriodDefiniteLabel', + defaultMessage: 'Leigutímabil', + description: 'Rental period label', + }, + rentalPeriodDefiniteValue: { + id: 'ra.application:summary.rentalPeriodDefiniteValue', + defaultMessage: 'Ótímabundinn samningur', + description: 'Value if rental period is indefinite', + }, + + // Rental amount & security deposit + rentalAmountLabel: { + id: 'ra.application:summary.rentalAmountLabel', + defaultMessage: 'Leiguupphæð', + description: 'Rental amount label', + }, + securityDepositLabel: { + id: 'ra.application:summary.securityDepositLabel', + defaultMessage: 'Trygging', + description: 'Security deposit label', + }, + securityDepositNotRequired: { + id: 'ra.application:summary.securityDepositNotRequired', + defaultMessage: 'Ekki krafist', + description: 'Security deposit not required', + }, + securityTypeLabel: { + id: 'ra.application:summary.securityTypeLabel', + defaultMessage: 'Tegund', + description: 'Security type label', + }, + securityTypeInstitutionLabel: { + id: 'ra.application:summary.securityTypeInstitutionLabel', + defaultMessage: 'Nafn stofnunar', + description: 'Bank guarantee label', + }, + securityTypeThirdPartyGuaranteeLabel: { + id: 'ra.application:summary.securityTypeThirdPartyGuaranteeLabel', + defaultMessage: 'Nafn ábyrgðaraðila', + description: 'Insurance label', + }, + securityTypeInsuranceLabel: { + id: 'ra.application:summary.securityTypeInsuranceLabel', + defaultMessage: 'Nafn tryggingarfélags', + description: 'Insurance label', + }, + securityTypeMutualFundLabel: { + id: 'ra.application:summary.securityTypeMutualFundLabel', + defaultMessage: 'Nafn samtryggingasjóðs', + description: 'Mutual fund label', + }, + securityTypeOtherLabel: { + id: 'ra.application:summary.securityTypeOtherLabel', + defaultMessage: 'Tegund Tryggingar', + description: 'Other label', + }, + + // Payment & indexation + paymentDateOptionsLabel: { + id: 'ra.application:summary.paymentDateOptionsLabel', + defaultMessage: 'Gjalddagi leigu', + description: 'Payment date options label', + }, + indexTypeLabel: { + id: 'ra.application:summary.indexTypeLabel', + defaultMessage: 'Vísitala', + description: 'Indexation type label', + }, + indexValueLabel: { + id: 'ra.application:summary.indexValueLabel', + defaultMessage: 'Vísitala við upphaf samnings', + description: 'Indexation value label', + }, + + // Rent transaction details + paymentMethodTypeLabel: { + id: 'ra.application:summary.paymentMethodTypeLabel', + defaultMessage: 'Greiðslufyrirkomulag', + description: 'Payment method type label', + }, + paymentMethodAccountLabel: { + id: 'ra.application:summary.paymentMethodAccountLabel', + defaultMessage: 'Reikningsnúmer', + description: 'Payment method account label', + }, + paymentMethodNationalIdLabel: { + id: 'ra.application:summary.paymentMethodNationalIdLabel', + defaultMessage: 'Kennitala', + description: 'Payment method national id label', + }, + + // Other costs + otherCostsHeader: { + id: 'ra.application:summary.otherCostsHeader', + defaultMessage: 'Önnur gjöld', + description: 'Other costs header', + }, + electricityCostLabel: { + id: 'ra.application:summary.electricityCostLabel', + defaultMessage: 'Rafmagnskostnaður', + description: 'Electricity cost label', + }, + heatingCostLabel: { + id: 'ra.application:summary.heatingCostLabel', + defaultMessage: 'Hitakostnaður', + description: 'Heating and water cost label', + }, + houseFundLabel: { + id: 'ra.application:summary.houseFundLabel', + defaultMessage: 'Hússjóður', + description: 'Housing fund label', + }, + houseFundAmountLabel: { + id: 'ra.application:summary.houseFundAmountLabel', + defaultMessage: 'Upphæð hússjóðs', + description: 'House fund amount label', + }, + electricityMeterNumberLabel: { + id: 'ra.application:summary.electricityMeterNumberLabel', + defaultMessage: 'Rafmagnsmælir', + description: 'Electricity meter label', + }, + heatingCostMeterNumberLabel: { + id: 'ra.application:summary.heatingCostMeterNumberLabel', + defaultMessage: 'Hitamælir', + description: 'Meter number label', + }, + meterStatusLabel: { + id: 'ra.application:summary.meterStatusLabel', + defaultMessage: 'Staða mælis', + description: 'Meter status label', + }, + dateOfMeterReadingLabel: { + id: 'ra.application:summary.dateOfMeterReadingLabel', + defaultMessage: 'Dags.', + description: 'Date of meter reading label', + }, + otherCostsAmountLabel: { + id: 'ra.application:summary.otherCostsAmountLabel', + defaultMessage: 'Upphæð', + description: 'Other costs amount label', + }, + + // Property information + propertyInfoHeader: { + id: 'ra.application:summary.propertyInfoHeader', + defaultMessage: 'Húsnæðið', + description: 'Property information header', + }, + propertyTypeLabel: { + id: 'ra.application:summary.propertyTypeLabel', + defaultMessage: 'Tegund húsnæðis', + description: 'Property type label', + }, + PropertyNumOfRoomsLabel: { + id: 'ra.application:summary.PropertyNumOfRoomsLabel', + defaultMessage: 'Herbergi', + description: 'Number of rooms label', + }, + propertySizeLabel: { + id: 'ra.application:summary.propertySizeLabel', + defaultMessage: 'Fermetrar', + description: 'Property size label', + }, + propertyClassLabel: { + id: 'ra.application:summary.propertyClassLabel', + defaultMessage: 'Flokkun húsnæðis', + description: 'Property classification label', + }, + propertyClassGroupLabel: { + id: 'ra.application:summary.propertyClassGroupLabel', + defaultMessage: 'Hópur', + description: 'Property classification group label', + }, + propertyDescriptionLabel: { + id: 'ra.application:summary.propertyDescriptionLabel', + defaultMessage: 'Lýsing á húsnæðinu og því sem með fylgir', + description: 'Property description label', + }, + PropertySpecialProvisionsLabel: { + id: 'ra.application:summary.PropertySpecialProvisionsLabel', + defaultMessage: 'Sérákvæði eða húsreglur', + description: 'Special conditions label', + }, + propertyConditionInspectorLabel: { + id: 'ra.application:summary.propertyConditionInspectorLabel', + defaultMessage: 'Ástandsskoðun', + description: 'Property condition inspector label', + }, + propertyConditionInspectorValuePrefix: { + id: 'ra.application:summary.propertyConditionInspectorValuePrefix', + defaultMessage: 'Framkvæmd af ', + description: 'Property condition inspector value prefix', + }, + propertyConditionInspectorValueContractParties: { + id: 'ra.application:summary.propertyConditionInspectorValueContractParties', + defaultMessage: 'samningsaðilum', + description: 'Property condition inspector value contract parties', + }, + propertyConditionDescriptionLabel: { + id: 'ra.application:summary.propertyConditionDescriptionLabel', + defaultMessage: 'Ástandsúttekt', + description: 'Property condition description label', + }, + fileUploadLabel: { + id: 'ra.application:summary.fileUploadLabel', + defaultMessage: 'Upphlaðin gögn', + description: 'File upload label', + }, + fireProtectionsSmokeDetectorsLabel: { + id: 'ra.application:summary.fireProtectionsSmokeDetectorsLabel', + defaultMessage: 'Reykskynjari', + description: 'Smoke detectors label', + }, + fireProtectionsFireExtinguisherLabel: { + id: 'ra.application:summary.fireProtectionsFireExtinguisherLabel', + defaultMessage: 'Slökkvitæki', + description: 'Fire extinguisher label', + }, + fireProtectionsExitsLabel: { + id: 'ra.application:summary.fireProtectionsExitsLabel', + defaultMessage: 'Flóttaleiðir', + description: 'Exits label', + }, + fireProtectionsFireBlanketLabel: { + id: 'ra.application:summary.fireProtectionsFireBlanketLabel', + defaultMessage: 'Eldvarnarteppi', + description: 'Fire blanket label', + }, + + // Tenants and landlords information + tenantsHeader: { + id: 'ra.application:summary.tenantsHeader', + defaultMessage: 'Leigjandi', + description: 'Tenants header', + }, + tenantsHeaderPlural: { + id: 'ra.application:summary.tenantsHeaderPlural', + defaultMessage: 'Leigjendur', + description: 'Tenants header', + }, + tenantsRepresentativeLabel: { + id: 'ra.application:summary.tenantsRepresentativeLabel', + defaultMessage: 'Umboðsaðili leigjanda', + description: 'Delegator label', + }, + landlordsHeader: { + id: 'ra.application:summary.landlordsHeader', + defaultMessage: 'Leigusali', + description: 'Landlords header', + }, + landlordsHeaderPlural: { + id: 'ra.application:summary.landlordsHeaderPlural', + defaultMessage: 'Leigusalar', + description: 'Landlords header', + }, + landlordsRepresentativeLabel: { + id: 'ra.application:summary.landlordsRepresentativeLabel', + defaultMessage: 'Umboðsaðili leigusala', + description: 'Delegator label', + }, + nationalIdLabel: { + id: 'ra.application:summary.nationalIdLabel', + defaultMessage: 'Kennitala: ', + description: 'National ID label', + }, + phoneNumberLabel: { + id: 'ra.application:summary.phoneNumberLabel', + defaultMessage: 'Símanúmer', + description: 'Phone number label', + }, + emailLabel: { + id: 'ra.application:summary.emailLabel', + defaultMessage: 'Netfang', + description: 'Email label', + }, + + // Share link + shareLinkLabel: { + id: 'ra.application:summary.shareLinkLabel', + defaultMessage: 'Deila samningsdrögum', + description: 'Share link label', + }, + shareLinkTooltip: { + id: 'ra.application:summary.shareLinkTooltip', + defaultMessage: + 'Hér getur þú deilt samningsdrögum með öðrum aðilum smnings til að fá álit þeirra.', + description: 'Share link tooltip', + }, + shareLinkbuttonLabel: { + id: 'ra.application:summary.shareLinkbuttonLabel', + defaultMessage: 'Afrita hlekk', + description: 'Share link copy button label', + }, + + // Alert message for missing information + alertMissingInfoTitle: { + id: 'ra.application:summary.alertMissingInfoTitle', + defaultMessage: + 'Ekki er hægt að halda áfram í undirritun fyrr en eftirfarandi upplýsingar hafa verið fylltar út:', + description: 'Missing information alert title', + }, + alertMissingInfoFireProtections: { + id: 'ra.application:summary.alertMissingInfoFireProtections', + defaultMessage: 'Staða brunavarna í húsnæðinu', + description: 'Missing information alert fire protections', + }, + alertMissingInfoCondition: { + id: 'ra.application:summary.alertMissingInfoCondition', + defaultMessage: 'Ástand húsnæðis', + description: 'Missing information alert condition', + }, + alertMissingInfoOtherFees: { + id: 'ra.application:summary.alertMissingInfoOtherFees', + defaultMessage: 'Önnur gjöld', + description: 'Missing information alert other fees', + }, +}) diff --git a/libs/application/templates/rental-agreement/src/lib/types.ts b/libs/application/templates/rental-agreement/src/lib/types.ts new file mode 100644 index 000000000000..3cf8f2a77a0c --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/types.ts @@ -0,0 +1,11 @@ +import { NationalRegistryIndividual } from '@island.is/application/types' + +export interface ExternalData { + nationalRegistry: { + data: NationalRegistryIndividual + date: string + status: StatusProvider + } +} + +export type StatusProvider = 'failure' | 'success' diff --git a/libs/application/templates/rental-agreement/src/lib/utils.ts b/libs/application/templates/rental-agreement/src/lib/utils.ts new file mode 100644 index 000000000000..84fd59538bda --- /dev/null +++ b/libs/application/templates/rental-agreement/src/lib/utils.ts @@ -0,0 +1,301 @@ +import { getValueViaPath } from '@island.is/application/core' +import { Application } from '@island.is/application/types' +import { + RentalAmountIndexTypes, + RentalHousingCategoryClass, + RentalHousingCategoryClassGroup, + RentalHousingCategoryTypes, + RentalHousingConditionInspector, + RentalAmountPaymentDateOptions, + OtherFeesPayeeOptions, + SecurityDepositTypeOptions, + SecurityDepositAmountOptions, + UserRole, + RentalPaymentMethodOptions, +} from './constants' +import { parsePhoneNumberFromString } from 'libphonenumber-js' +import format from 'date-fns/format' +import parseISO from 'date-fns/parseISO' +import is from 'date-fns/locale/is' +import * as m from './messages' + +export const validateEmail = (value: string) => { + const regex = + /^[\w!#$%&'*+/=?`{|}~^-]+(?:\.[\w!#$%&'*+/=?`{|}~^-]+)*@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$/i + return regex.test(value) +} + +export const insertAt = (str: string, sub: string, pos: number) => + `${str.slice(0, pos)}${sub}${str.slice(pos)}` + +export const formatNationalId = (nationalId: string) => + insertAt(nationalId.replace('-', ''), '-', 6) || '-' + +export const formatDate = (date: string) => { + return format(parseISO(date), 'dd.MM.yyyy', { + locale: is, + }) +} + +export const formatPhoneNumber = (phoneNumber: string): string => { + const phone = parsePhoneNumberFromString(phoneNumber, 'IS') + return phone?.formatNational() || phoneNumber +} + +export const formatBankInfo = (bankInfo: string) => { + const formattedBankInfo = bankInfo.replace(/^(.{4})(.{2})/, '$1-$2-') + if (formattedBankInfo && formattedBankInfo.length >= 6) { + return formattedBankInfo + } + return bankInfo +} + +export const formatCurrency = (answer: string) => + answer.replace(/\B(?=(\d{3})+(?!\d))/g, '.') + ' ISK' + +export const getApplicationAnswers = (answers: Application['answers']) => { + const propertyTypeOptions = getValueViaPath( + answers, + 'registerProperty.categoryType', + ) + + const propertyClassOptions = getValueViaPath( + answers, + 'registerProperty.categoryClass', + ) + + const inspectorOptions = getValueViaPath( + answers, + 'condition.inspector', + ) + + const rentalAmountIndexTypesOptions = getValueViaPath( + answers, + 'rentalAmount.indexTypes', + ) + + const rentalAmountPaymentDateOptions = + getValueViaPath( + answers, + 'rentalAmount.paymentDateOptions', + ) + + const otherFeesHousingFund = getValueViaPath( + answers, + 'otherFees.housingFund', + ) + + const otherFeesElectricityCost = getValueViaPath( + answers, + 'otherFees.electricityCost', + ) + + const otherFeesHeatingCost = getValueViaPath( + answers, + 'otherFees.heatingCost', + ) + + return { + propertyTypeOptions, + propertyClassOptions, + inspectorOptions, + rentalAmountIndexTypesOptions, + rentalAmountPaymentDateOptions, + otherFeesElectricityCost, + otherFeesHeatingCost, + otherFeesHousingFund, + } +} + +export const getPropertyTypeOptions = () => [ + { + value: RentalHousingCategoryTypes.ENTIRE_HOME, + label: m.registerProperty.category.typeSelectLabelEntireHome, + }, + { + value: RentalHousingCategoryTypes.ROOM, + label: m.registerProperty.category.typeSelectLabelRoom, + }, + { + value: RentalHousingCategoryTypes.COMMERCIAL, + label: m.registerProperty.category.typeSelectLabelCommercial, + }, +] + +export const getPropertyClassOptions = () => [ + { + value: RentalHousingCategoryClass.GENERAL_MARKET, + label: m.registerProperty.category.classSelectLabelGeneralMarket, + }, + { + value: RentalHousingCategoryClass.SPECIAL_GROUPS, + label: m.registerProperty.category.classSelectLabelSpecialGroups, + }, +] + +export const getPropertyClassGroupOptions = () => [ + { + value: RentalHousingCategoryClassGroup.STUDENT_HOUSING, + label: m.registerProperty.category.classGroupSelectLabelStudentHousing, + }, + { + value: RentalHousingCategoryClassGroup.SENIOR_CITIZEN_HOUSING, + label: + m.registerProperty.category.classGroupSelectLabelSeniorCitizenHousing, + }, + { + value: RentalHousingCategoryClassGroup.COMMUNE, + label: m.registerProperty.category.classGroupSelectLabelCommune, + }, + { + value: RentalHousingCategoryClassGroup.HALFWAY_HOUSE, + label: m.registerProperty.category.classGroupSelectLabelHalfwayHouse, + }, + { + value: RentalHousingCategoryClassGroup.SOCIAL_HOUSING, + label: m.registerProperty.category.classGroupSelectLabelSocialHousing, + }, + { + value: RentalHousingCategoryClassGroup.INCOME_BASED_HOUSING, + label: m.registerProperty.category.classGroupSelectLabelIncomeBasedHousing, + }, + { + value: RentalHousingCategoryClassGroup.EMPLOYEE_HOUSING, + label: m.registerProperty.category.classGroupSelectLabelEmployeeHousing, + }, +] + +export const getInspectorOptions = () => [ + { + value: RentalHousingConditionInspector.CONTRACT_PARTIES, + label: m.housingCondition.inspectorOptionContractParties, + }, + { + value: RentalHousingConditionInspector.INDEPENDENT_PARTY, + label: m.housingCondition.inspectorOptionIndependentParty, + }, +] + +export const getRentalAmountIndexTypes = () => [ + { + value: RentalAmountIndexTypes.CONSUMER_PRICE_INDEX, + label: m.rentalAmount.indexOptionConsumerPriceIndex, + }, + { + value: RentalAmountIndexTypes.CONSTRUCTION_COST_INDEX, + label: m.rentalAmount.indexOptionConstructionCostIndex, + }, + { + value: RentalAmountIndexTypes.WAGE_INDEX, + label: m.rentalAmount.indexOptionWageIndex, + }, +] + +export const getRentalAmountPaymentDateOptions = () => [ + { + value: RentalAmountPaymentDateOptions.FIRST_DAY, + label: m.rentalAmount.paymentDateOptionFirstDay, + }, + { + value: RentalAmountPaymentDateOptions.LAST_DAY, + label: m.rentalAmount.paymentDateOptionLastDay, + }, + { + value: RentalAmountPaymentDateOptions.OTHER, + label: m.rentalAmount.paymentDateOptionOther, + }, +] + +export const getSecurityDepositTypeOptions = () => [ + { + label: m.securityDeposit.typeSelectionBankGuaranteeTitle, + value: SecurityDepositTypeOptions.BANK_GUARANTEE, + }, + { + label: m.securityDeposit.typeSelectionCapitalTitle, + value: SecurityDepositTypeOptions.CAPITAL, + }, + { + label: m.securityDeposit.typeSelectionThirdPartyGuaranteeTitle, + value: SecurityDepositTypeOptions.THIRD_PARTY_GUARANTEE, + }, + { + label: m.securityDeposit.typeSelectionInsuranceCompanyTitle, + value: SecurityDepositTypeOptions.INSURANCE_COMPANY, + }, + { + label: m.securityDeposit.typeSelectionMutualFundTitle, + value: SecurityDepositTypeOptions.MUTUAL_FUND, + }, + { + label: m.securityDeposit.typeSelectionOtherTitle, + value: SecurityDepositTypeOptions.OTHER, + }, +] + +export const getSecurityAmountOptions = () => [ + { + label: m.securityDeposit.amountSelection1Month, + value: SecurityDepositAmountOptions.ONE_MONTH, + }, + { + label: m.securityDeposit.amountSelection2Month, + value: SecurityDepositAmountOptions.TWO_MONTHS, + }, + { + label: m.securityDeposit.amountSelection3Month, + value: SecurityDepositAmountOptions.THREE_MONTHS, + }, + { + label: m.securityDeposit.amountSelectionOther, + value: SecurityDepositAmountOptions.OTHER, + }, +] + +export const getOtherFeesPayeeOptions = () => [ + { + value: OtherFeesPayeeOptions.LANDLORD, + label: m.otherFees.paidByLandlordLabel, + }, + { + value: OtherFeesPayeeOptions.TENANT, + label: m.otherFees.paidByTenantLabel, + }, +] + +export const getOtherFeesHousingFundPayeeOptions = () => [ + { + value: OtherFeesPayeeOptions.LANDLORD_OR_NOT_APPLICABLE, + label: m.otherFees.housingFundPayedByLandlordLabel, + }, + { + value: OtherFeesPayeeOptions.TENANT, + label: m.otherFees.paidByTenantLabel, + }, +] + +export const getPaymentMethodOptions = () => [ + { + value: RentalPaymentMethodOptions.BANK_TRANSFER, + label: m.rentalAmount.paymentMethodBankTransferLabel, + }, + { + value: RentalPaymentMethodOptions.PAYMENT_SLIP, + label: m.rentalAmount.paymentMethodPaymentSlipLabel, + }, + { + value: RentalPaymentMethodOptions.OTHER, + label: m.rentalAmount.paymentMethodOtherLabel, + }, +] + +export const getUserRoleOptions = [ + { + label: m.userRole.landlordOptionLabel, + value: UserRole.LANDLORD, + }, + { + label: m.userRole.tenantOptionLabel, + value: UserRole.TENANT, + }, +] diff --git a/libs/application/templates/rental-agreement/tsconfig.json b/libs/application/templates/rental-agreement/tsconfig.json new file mode 100644 index 000000000000..cb5a692ec7bc --- /dev/null +++ b/libs/application/templates/rental-agreement/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": true, + "resolveJsonModule": true, + "esModuleInterop": true + }, + + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/application/templates/rental-agreement/tsconfig.lib.json b/libs/application/templates/rental-agreement/tsconfig.lib.json new file mode 100644 index 000000000000..d547efefcf0b --- /dev/null +++ b/libs/application/templates/rental-agreement/tsconfig.lib.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../../dist/out-tsc", + "types": ["node"] + }, + "files": [ + "../../../../node_modules/@nx/react/typings/cssmodule.d.ts", + "../../../../node_modules/@nx/react/typings/image.d.ts" + ], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "jest.config.ts" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/application/templates/rental-agreement/tsconfig.spec.json b/libs/application/templates/rental-agreement/tsconfig.spec.json new file mode 100644 index 000000000000..515fdb6e5dd4 --- /dev/null +++ b/libs/application/templates/rental-agreement/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "**/*.d.ts", + "jest.config.ts" + ] +} diff --git a/libs/application/types/src/lib/ApplicationTypes.ts b/libs/application/types/src/lib/ApplicationTypes.ts index 113bf2bb33b8..4be5ac52f4c4 100644 --- a/libs/application/types/src/lib/ApplicationTypes.ts +++ b/libs/application/types/src/lib/ApplicationTypes.ts @@ -78,6 +78,7 @@ export enum ApplicationTypes { NEW_PRIMARY_SCHOOL = 'NewPrimarySchool', WORK_ACCIDENT_NOTIFICATION = 'WorkAccidentNotification', MACHINE_REGISTRATION = 'MachineRegistration', + RENTAL_AGREEMENT = 'RentalAgreement', SECONDARY_SCHOOL = 'SecondarySchool', } @@ -402,6 +403,10 @@ export const ApplicationConfigurations = { slug: 'nyskraning-taekis', translation: ['aosh.rnm.application'], }, + [ApplicationTypes.RENTAL_AGREEMENT]: { + slug: 'leigusamningur', + translation: 'ra.application', + }, [ApplicationTypes.SECONDARY_SCHOOL]: { slug: 'framhaldsskoli', translation: 'ss.application', diff --git a/libs/application/types/src/lib/InstitutionContentfulIds.ts b/libs/application/types/src/lib/InstitutionContentfulIds.ts index 23e546757965..625faad77f6f 100644 --- a/libs/application/types/src/lib/InstitutionContentfulIds.ts +++ b/libs/application/types/src/lib/InstitutionContentfulIds.ts @@ -23,4 +23,5 @@ export enum InstitutionContentfulIds { HASKOLARADUNEYTI = '3sehE6LnPfPkS6fR0DkIqK', DOMSMALARADUNEYTID = '26M5901Ntp7GhY14TRYSvw', MIDSTOD_MENNTUNAR_SKOLATHJONUSTU = '48Sa01Rahbo7FAdWPQbRub', + HUSNAEDIS_OG_MANNVIRKJASTOFNUN = '53jrbgxPKpbNtordSfEZUK', } diff --git a/libs/application/types/src/lib/InstitutionMapper.ts b/libs/application/types/src/lib/InstitutionMapper.ts index 626faaa34375..ba8703e6f7d1 100644 --- a/libs/application/types/src/lib/InstitutionMapper.ts +++ b/libs/application/types/src/lib/InstitutionMapper.ts @@ -394,6 +394,11 @@ export const institutionMapper = { slug: InstitutionTypes.VINNUEFTIRLITID, contentfulId: InstitutionContentfulIds.VINNUEFTIRLITID, }, + [ApplicationTypes.RENTAL_AGREEMENT]: { + nationalId: InstitutionNationalIds.HUSNAEDIS_OG_MANNVIRKJASTOFNUN, + slug: InstitutionTypes.HUSNAEDIS_OG_MANNVIRKJASTOFNUN, + contentfulId: InstitutionContentfulIds.HUSNAEDIS_OG_MANNVIRKJASTOFNUN, + }, [ApplicationTypes.WORK_ACCIDENT_NOTIFICATION]: { nationalId: InstitutionNationalIds.VINNUEFTIRLITID, slug: InstitutionTypes.VINNUEFTIRLITID, diff --git a/libs/application/types/src/lib/InstitutionNationalIds.ts b/libs/application/types/src/lib/InstitutionNationalIds.ts index aca8d0a2b257..0cc6449c573d 100644 --- a/libs/application/types/src/lib/InstitutionNationalIds.ts +++ b/libs/application/types/src/lib/InstitutionNationalIds.ts @@ -25,4 +25,5 @@ export enum InstitutionNationalIds { URVINNSLUSJODUR = ' 5308033680', DOMSMALA_RADUNEYTID = '5804170510', MIDSTOD_MENNTUNAR_SKOLATHJONUSTU = '6601241280', + HUSNAEDIS_OG_MANNVIRKJASTOFNUN = '5812191480', } diff --git a/libs/application/types/src/lib/InstitutionTypes.ts b/libs/application/types/src/lib/InstitutionTypes.ts index c1fe6e31ef59..d0df7642c05c 100644 --- a/libs/application/types/src/lib/InstitutionTypes.ts +++ b/libs/application/types/src/lib/InstitutionTypes.ts @@ -24,4 +24,5 @@ export enum InstitutionTypes { HASKOLARADUNEYTI = 'haskolaraduneyti', DOMSMALARADUNEYTID = 'domsmalaraduneytid', MIDSTOD_MENNTUNAR_SKOLATHJONUSTU = 'midstod-menntunar-og-skolathjonustu', + HUSNAEDIS_OG_MANNVIRKJASTOFNUN = 'husnaedis-og-mannvirkjastofnun', } diff --git a/libs/feature-flags/src/lib/features.ts b/libs/feature-flags/src/lib/features.ts index a040efdedf0e..fd71bb6a64a3 100644 --- a/libs/feature-flags/src/lib/features.ts +++ b/libs/feature-flags/src/lib/features.ts @@ -30,6 +30,7 @@ export enum Features { deathBenefits = 'isdeathbenefitsapplicationenabled', FinancialStatementPoliticalPartyEnabled = 'isFinancialStatementPoliticalPartyEnabled', IncomePlanEnabled = 'isIncomePlanEnabled', + rentalAgreement = 'isRentalAgreementEnabled', WorkAccidentNotificationEnabled = 'isWorkAccidentNotificationEnabled', SecondarySchoolEnabled = 'isSecondarySchoolEnabled', diff --git a/libs/shared/constants/src/lib/codeOwners.ts b/libs/shared/constants/src/lib/codeOwners.ts index 912e323b0b61..1b51b3712bf0 100644 --- a/libs/shared/constants/src/lib/codeOwners.ts +++ b/libs/shared/constants/src/lib/codeOwners.ts @@ -11,6 +11,7 @@ export enum CodeOwners { Juni = 'juni', KolibriJusticeLeague = 'kolibri-justice-league', KolibriRobinHood = 'kolibri-robin-hood', + KolibriKotid = 'kolibri-kotid', NordaApplications = 'norda-applications', Origo = 'origo', Programm = 'programm', diff --git a/tsconfig.base.json b/tsconfig.base.json index c6892d6c2dd3..f891578ace9f 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -492,6 +492,9 @@ "@island.is/application/templates/reference-template": [ "libs/application/templates/reference-template/src/index.ts" ], + "@island.is/application/templates/rental-agreement": [ + "libs/application/templates/rental-agreement/src/index.ts" + ], "@island.is/application/templates/secondary-school": [ "libs/application/templates/secondary-school/src/index.ts" ],