From 34f8dbca820343c76c046f715983a4bba79e1d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3hanna=20Magn=C3=BAsd=C3=B3ttir?= Date: Thu, 21 Nov 2024 13:31:32 +0000 Subject: [PATCH 1/8] Validate buyer + buyerCoOwnerAndOperator in TransferOfVehicleOwnership --- .../BuyerItem.tsx | 0 .../src/fields/Buyer/index.tsx | 63 +++++++++ .../BuyerCoOwnerAndOperatorRepeater.css.ts} | 0 .../BuyerCoOwnerAndOperatorRepeaterItem.tsx} | 2 +- .../index.tsx | 131 +++++++++--------- .../src/fields/index.ts | 3 +- .../InformationSection/buyerSubSection.ts | 9 +- 7 files changed, 138 insertions(+), 70 deletions(-) rename libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/{CoOwnerAndOperatorRepeater => Buyer}/BuyerItem.tsx (100%) create mode 100644 libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/Buyer/index.tsx rename libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/{CoOwnerAndOperatorRepeater/CoOwnerAndOperatorRepeater.css.ts => BuyerCoOwnerAndOperatorRepeater/BuyerCoOwnerAndOperatorRepeater.css.ts} (100%) rename libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/{CoOwnerAndOperatorRepeater/CoOwnerAndOperatorRepeaterItem.tsx => BuyerCoOwnerAndOperatorRepeater/BuyerCoOwnerAndOperatorRepeaterItem.tsx} (98%) rename libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/{CoOwnerAndOperatorRepeater => BuyerCoOwnerAndOperatorRepeater}/index.tsx (63%) diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/CoOwnerAndOperatorRepeater/BuyerItem.tsx b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/Buyer/BuyerItem.tsx similarity index 100% rename from libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/CoOwnerAndOperatorRepeater/BuyerItem.tsx rename to libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/Buyer/BuyerItem.tsx diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/Buyer/index.tsx b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/Buyer/index.tsx new file mode 100644 index 000000000000..914a4e7f62c3 --- /dev/null +++ b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/Buyer/index.tsx @@ -0,0 +1,63 @@ +import { getValueViaPath } from '@island.is/application/core' +import { FieldBaseProps } from '@island.is/application/types' +import { Box } from '@island.is/island-ui/core' +import { useLocale } from '@island.is/localization' +import { FC, useState, useCallback, useEffect } from 'react' +import { UserInformation } from '../../shared' +import { useMutation } from '@apollo/client' +import { UPDATE_APPLICATION } from '@island.is/application/graphql' +import { BuyerItem } from './BuyerItem' + +const emailRegex = + /^[\w!#$%&'*+/=?`{|}~^-]+(?:\.[\w!#$%&'*+/=?`{|}~^-]+)*@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$/i + +export const Buyer: FC> = (props) => { + const { locale } = useLocale() + const { application, field } = props + const { id } = field + + const [updateApplication] = useMutation(UPDATE_APPLICATION) + + const [buyer, setBuyer] = useState( + getValueViaPath(application.answers, 'buyer', { + name: '', + nationalId: '', + phone: '', + email: '', + }) as UserInformation, + ) + + const updateBuyer = useCallback( + async (buyer: UserInformation) => { + await updateApplication({ + variables: { + input: { + id: application.id, + answers: { + buyer: buyer, + }, + }, + locale, + }, + }) + }, + [application.id, locale, updateApplication], + ) + + useEffect(() => { + if ( + buyer.name.length > 0 && + buyer.nationalId.length === 10 && + buyer.phone.length >= 7 && + emailRegex.test(buyer.email) + ) { + updateBuyer(buyer) + } + }, [buyer, updateBuyer]) + + return ( + + + + ) +} diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/CoOwnerAndOperatorRepeater/CoOwnerAndOperatorRepeater.css.ts b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/BuyerCoOwnerAndOperatorRepeater.css.ts similarity index 100% rename from libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/CoOwnerAndOperatorRepeater/CoOwnerAndOperatorRepeater.css.ts rename to libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/BuyerCoOwnerAndOperatorRepeater.css.ts diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/CoOwnerAndOperatorRepeater/CoOwnerAndOperatorRepeaterItem.tsx b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/BuyerCoOwnerAndOperatorRepeaterItem.tsx similarity index 98% rename from libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/CoOwnerAndOperatorRepeater/CoOwnerAndOperatorRepeaterItem.tsx rename to libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/BuyerCoOwnerAndOperatorRepeaterItem.tsx index 865335e36582..59e71a2136f7 100644 --- a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/CoOwnerAndOperatorRepeater/CoOwnerAndOperatorRepeaterItem.tsx +++ b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/BuyerCoOwnerAndOperatorRepeaterItem.tsx @@ -24,7 +24,7 @@ interface Props { addNationalIdToCoOwners: (nationalId: string, index: number) => void } -export const CoOwnerAndOperatorRepeaterItem: FC< +export const BuyerCoOwnerAndOperatorRepeaterItem: FC< React.PropsWithChildren > = ({ id, diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/CoOwnerAndOperatorRepeater/index.tsx b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx similarity index 63% rename from libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/CoOwnerAndOperatorRepeater/index.tsx rename to libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx index da30623f3486..b212561f8d9f 100644 --- a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/CoOwnerAndOperatorRepeater/index.tsx +++ b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx @@ -2,32 +2,30 @@ import { getValueViaPath } from '@island.is/application/core' import { FieldBaseProps } from '@island.is/application/types' import { AlertMessage, Box, Button } from '@island.is/island-ui/core' import { useLocale } from '@island.is/localization' -import { FC, useState, useCallback, useEffect } from 'react' +import { FC, useState } from 'react' import { information } from '../../lib/messages' -import { CoOwnerAndOperator, UserInformation } from '../../shared' -import { BuyerItem } from './BuyerItem' -import { repeaterButtons } from './CoOwnerAndOperatorRepeater.css' -import { CoOwnerAndOperatorRepeaterItem } from './CoOwnerAndOperatorRepeaterItem' -import { useMutation } from '@apollo/client' -import { UPDATE_APPLICATION } from '@island.is/application/graphql' +import { CoOwnerAndOperator } from '../../shared' +import { repeaterButtons } from './BuyerCoOwnerAndOperatorRepeater.css' +import { BuyerCoOwnerAndOperatorRepeaterItem } from './BuyerCoOwnerAndOperatorRepeaterItem' +import { useLazyQuery } from '@apollo/client' +import { APPLICATION_APPLICATION } from '@island.is/application/graphql' -const emailRegex = - /^[\w!#$%&'*+/=?`{|}~^-]+(?:\.[\w!#$%&'*+/=?`{|}~^-]+)*@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$/i - -export const CoOwnerAndOperatorRepeater: FC< +export const BuyerCoOwnerAndOperatorRepeater: FC< React.PropsWithChildren > = (props) => { - const { locale, formatMessage } = useLocale() - const { application, setBeforeSubmitCallback } = props - const [updateApplication] = useMutation(UPDATE_APPLICATION) - const [buyer, setBuyer] = useState( - getValueViaPath(application.answers, 'buyer', { - name: '', - nationalId: '', - phone: '', - email: '', - }) as UserInformation, - ) + const { formatMessage } = useLocale() + const { application, field, setBeforeSubmitCallback } = props + const { id } = field + + const [identicalError, setIdenticalError] = useState(false) + + const [getApplicationInfo] = useLazyQuery(APPLICATION_APPLICATION, { + onError: (e) => { + console.error(e, e.message) + return + }, + }) + const [buyerCoOwnerAndOperator, setBuyerCoOwnerAndOperator] = useState< CoOwnerAndOperator[] >( @@ -37,7 +35,6 @@ export const CoOwnerAndOperatorRepeater: FC< [], ) as CoOwnerAndOperator[], ) - const [identicalError, setIdenticalError] = useState(false) const filteredCoOwnersAndOperators = buyerCoOwnerAndOperator.filter( ({ wasRemoved }) => wasRemoved !== 'true', @@ -49,42 +46,56 @@ export const CoOwnerAndOperatorRepeater: FC< (field) => field.type === 'coOwner', ) - const updateBuyer = useCallback(async (buyer: UserInformation) => { - await updateApplication({ - variables: { - input: { - id: application.id, - answers: { - buyer: buyer, - }, - }, - locale, - }, - }) - }, []) - const addNationalIdToCoOwners = (nationalId: string, newIndex: number) => { setBuyerCoOwnerAndOperator( - buyerCoOwnerAndOperator.map((coOwnerOroperator, index) => { + buyerCoOwnerAndOperator.map((coOwnerOrOperator, index) => { if (newIndex === index) { return { - ...coOwnerOroperator, + ...coOwnerOrOperator, nationalId, } } - return coOwnerOroperator + return coOwnerOrOperator }), ) } - const checkDuplicate = () => { + const getBuyerNationalId = async () => { + // Get buyer nationalId from updated answers (cannot use application.answers), + // since that is filled out in the same step as this, + // but the buyer value is updated in answers right away + const applicationInfo = await getApplicationInfo({ + variables: { + input: { + id: application.id, + }, + locale: 'is', + }, + fetchPolicy: 'no-cache', + }) + + const updatedApplication = applicationInfo?.data?.applicationApplication + + const buyerNationalId = + getValueViaPath( + updatedApplication.answers, + 'buyer.nationalId', + '', + ) || '' + + return buyerNationalId + } + + const checkDuplicate = async () => { const existingCoOwnersAndOperators = filteredCoOwnersAndOperators.map( ({ nationalId }) => { return nationalId }, ) - const jointOperators = [...existingCoOwnersAndOperators, buyer.nationalId] + const buyerNationalId = await getBuyerNationalId() + + const jointOperators = [...existingCoOwnersAndOperators, buyerNationalId] return !!jointOperators.some((nationalId, index) => { return ( nationalId && @@ -110,47 +121,35 @@ export const CoOwnerAndOperatorRepeater: FC< const handleRemove = (position: number) => { if (position > -1) { setBuyerCoOwnerAndOperator( - buyerCoOwnerAndOperator.map((coOwnerOroperator, index) => { + buyerCoOwnerAndOperator.map((coOwnerOrOperator, index) => { if (index === position) { - return { ...coOwnerOroperator, wasRemoved: 'true' } + return { ...coOwnerOrOperator, wasRemoved: 'true' } } - return coOwnerOroperator + return coOwnerOrOperator }), ) } } - useEffect(() => { - if ( - buyer.name.length > 0 && - buyer.nationalId.length === 10 && - buyer.phone.length >= 7 && - emailRegex.test(buyer.email) - ) { - updateBuyer(buyer) + setBeforeSubmitCallback?.(async () => { + const hasDuplicate = await checkDuplicate() + setIdenticalError(hasDuplicate) + if (hasDuplicate) { + return [false, 'Identical nationalIds'] } - }, [buyer]) - - setBeforeSubmitCallback && - setBeforeSubmitCallback(async () => { - setIdenticalError(checkDuplicate()) - if (checkDuplicate()) { - return [false, 'Identical nationalIds'] - } - return [true, null] - }) + return [true, null] + }) return ( - {buyerCoOwnerAndOperator.map((field, index) => { const rowLocation = field.type === 'operator' ? allOperators.indexOf(field) : allCoOwners.indexOf(field) return ( - Date: Fri, 22 Nov 2024 08:26:51 +0000 Subject: [PATCH 2/8] Validate added co-owners i ChangeCoOwnerOfVehicle --- .../NewCoOwnerRepeaterItem.tsx} | 4 +- .../index.tsx | 189 +++++++++--------- .../OldCoOwnerRepeaterItem.tsx} | 4 +- .../src/fields/OldCoOwnerRepeater/index.tsx | 95 +++++++++ .../{CoOwner => OwnerCoOwners}/index.tsx | 4 +- .../src/fields/index.ts | 5 +- .../InformationSection/coOwnerSubSection.ts | 8 +- .../InformationSection/ownerSubSection.ts | 2 +- .../src/lib/messages/information.ts | 5 + .../BuyerCoOwnerAndOperatorRepeater/index.tsx | 5 +- 10 files changed, 212 insertions(+), 109 deletions(-) rename libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/{CoOwnerRepeater/CoOwnerRepeaterItem.tsx => NewCoOwnerRepeater/NewCoOwnerRepeaterItem.tsx} (97%) rename libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/{CoOwnerRepeater => NewCoOwnerRepeater}/index.tsx (51%) rename libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/{CoOwnerRepeater/OwnerCoOwners.tsx => OldCoOwnerRepeater/OldCoOwnerRepeaterItem.tsx} (97%) create mode 100644 libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OldCoOwnerRepeater/index.tsx rename libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/{CoOwner => OwnerCoOwners}/index.tsx (98%) diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/CoOwnerRepeaterItem.tsx b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/NewCoOwnerRepeater/NewCoOwnerRepeaterItem.tsx similarity index 97% rename from libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/CoOwnerRepeaterItem.tsx rename to libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/NewCoOwnerRepeater/NewCoOwnerRepeaterItem.tsx index cb915baba273..09b7db9dd7b6 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/CoOwnerRepeaterItem.tsx +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/NewCoOwnerRepeater/NewCoOwnerRepeaterItem.tsx @@ -24,7 +24,7 @@ interface Props { addNationalIdToCoOwners: (nationalId: string, index: number) => void } -export const CoOwnerRepeaterItem: FC< +export const NewCoOwnerRepeaterItem: FC< React.PropsWithChildren > = ({ id, @@ -49,7 +49,7 @@ export const CoOwnerRepeaterItem: FC< useEffect(() => { setValue(wasRemovedField, repeaterField.wasRemoved) - }, [repeaterField.wasRemoved, setValue]) + }, [repeaterField.wasRemoved, setValue, wasRemovedField]) return ( > = ( +export const NewCoOwnerRepeater: FC> = ( props, ) => { - const { application, setBeforeSubmitCallback } = props - const { locale, formatMessage } = useLocale() + const { application, field, setBeforeSubmitCallback } = props + const { formatMessage } = useLocale() const { setValue } = useFormContext() - const [updateApplication] = useMutation(UPDATE_APPLICATION) - const [ownerCoOwners, setOwnerCoOwners] = useState< - OwnerCoOwnersInformation[] - >( - getValueViaPath( - application.answers, - 'ownerCoOwners', - [], - ) as OwnerCoOwnersInformation[], - ) + const { id } = field + + const [identicalError, setIdenticalError] = useState(false) + const [noCoOwnerChangesError, setNoCoOwnerChangesError] = + useState(false) + + const [getApplicationInfo] = useLazyQuery(APPLICATION_APPLICATION, { + onError: (e) => { + console.error(e, e.message) + return + }, + }) + const [coOwners, setCoOwners] = useState( - getValueViaPath( + getValueViaPath( application.answers, 'coOwners', [], - ) as CoOwnersInformation[], + ) || [], ) - const [identicalError, setIdenticalError] = useState(false) + const filteredCoOwners = coOwners.filter( ({ wasRemoved }) => wasRemoved !== 'true', ) - const filteredOwnerCoOwners = ownerCoOwners.filter( - ({ wasRemoved }) => wasRemoved !== 'true', - ) - - const updateData = useCallback(async (position: number) => { - await updateApplication({ - variables: { - input: { - id: application.id, - answers: { - ownerCoOwners: ownerCoOwners.map((coOwner, index) => { - if (index === position) { - return { ...coOwner, wasRemoved: 'true' } - } else { - return coOwner - } - }), - }, - }, - locale, - }, - }) - }, []) const addNationalIdToCoOwners = (nationalId: string, newIndex: number) => { setCoOwners( @@ -76,18 +55,44 @@ export const CoOwnerRepeater: FC> = ( ) } - const checkDuplicate = () => { - const existingOwnerCoOwners = filteredOwnerCoOwners.map( - ({ nationalId }) => { - return nationalId + const getOldCoOwners = async () => { + // Get updated ownerCoOwners from answers + const applicationInfo = await getApplicationInfo({ + variables: { + input: { + id: application.id, + }, + locale: 'is', }, - ) - const existingCoOwners = filteredCoOwners.map(({ nationalId }) => { - return nationalId + fetchPolicy: 'no-cache', }) + const updatedApplication = applicationInfo?.data?.applicationApplication + + const oldCoOwners = + getValueViaPath( + updatedApplication.answers, + 'ownerCoOwners', + [], + ) || [] + + const filteredOldCoOwners = oldCoOwners.filter( + ({ wasRemoved }) => wasRemoved !== 'true', + ) + + return filteredOldCoOwners + } + + const checkDuplicate = async () => { + const oldCoOwnerNationalIds = (await getOldCoOwners()).map( + ({ nationalId }) => nationalId, + ) + + const newCoOwnerNationalIds = filteredCoOwners.map( + ({ nationalId }) => nationalId, + ) const jointCoOwners = [ - ...existingOwnerCoOwners, - ...existingCoOwners, + ...oldCoOwnerNationalIds, + ...newCoOwnerNationalIds, application.applicant, ] return !!jointCoOwners.some((nationalId, index) => { @@ -122,60 +127,44 @@ export const CoOwnerRepeater: FC> = ( } } - const handleRemoveOld = (position: number) => { - if (ownerCoOwners.length >= position) { - setValue(`ownerCoOwners[${position}].wasRemoved`, 'true') - setOwnerCoOwners( - ownerCoOwners.map((coOwner, index) => { - if (index === position) { - return { ...coOwner, wasRemoved: 'true' } - } else { - return coOwner - } - }), - ) - updateData(position) - } - } - useEffect(() => { if (coOwners.length === 0) { setValue('coOwners', []) } }, [coOwners, setValue]) - setBeforeSubmitCallback && - setBeforeSubmitCallback(async () => { - setIdenticalError(checkDuplicate()) - if (checkDuplicate()) { - return [false, 'Identical nationalIds'] - } - return [true, null] - }) + setBeforeSubmitCallback?.(async () => { + setIdenticalError(false) + setNoCoOwnerChangesError(false) + + const hasDuplicate = await checkDuplicate() + if (hasDuplicate) { + setIdenticalError(true) + return [false, 'Identical nationalIds'] + } + + const coOwnerWasAdded = + coOwners?.filter(({ wasRemoved }) => wasRemoved !== 'true').length > 0 + const oldCoOwners = await getOldCoOwners() + const coOwnerWasRemoved = !!oldCoOwners?.find( + (x) => x.wasRemoved === 'true', + ) + const noCoOwnerChanges = !coOwnerWasAdded && !coOwnerWasRemoved + if (noCoOwnerChanges) { + setNoCoOwnerChangesError(true) + return [false, 'No co-owner has been added/removed'] + } + + return [true, null] + }) return ( - {ownerCoOwners.length > 0 && - ownerCoOwners.map((coOwner, index) => ( - -1 - ? filteredOwnerCoOwners.indexOf(coOwner) + 1 - : index + 1 - } - key={`ownerCoOwners-${index}`} - handleRemove={handleRemoveOld} - wasRemoved={coOwner.wasRemoved === 'true'} - {...props} - /> - ))} {coOwners.length > 0 ? ( coOwners.map((coOwner, index) => { return ( - > = ( /> )} + {noCoOwnerChangesError && ( + + + + )} ) } diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/OwnerCoOwners.tsx b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OldCoOwnerRepeater/OldCoOwnerRepeaterItem.tsx similarity index 97% rename from libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/OwnerCoOwners.tsx rename to libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OldCoOwnerRepeater/OldCoOwnerRepeaterItem.tsx index 300a4df19bbe..8c7a5576d01d 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/OwnerCoOwners.tsx +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OldCoOwnerRepeater/OldCoOwnerRepeaterItem.tsx @@ -21,7 +21,7 @@ interface Props { wasRemoved: boolean } -export const OwnerCoOwners: FC< +export const OldCoOwnerRepeaterItem: FC< React.PropsWithChildren > = ({ id, index, rowLocation, handleRemove, wasRemoved, ...props }) => { const { setValue } = useFormContext() @@ -36,7 +36,7 @@ export const OwnerCoOwners: FC< useEffect(() => { setValue(wasRemovedField, `${wasRemoved}`) - }, [wasRemoved, setValue]) + }, [wasRemoved, setValue, wasRemovedField]) return ( ) } diff --git a/libs/application/templates/transport-authority/change-operator-of-vehicle/src/lib/messages/information.ts b/libs/application/templates/transport-authority/change-operator-of-vehicle/src/lib/messages/information.ts index aa99f73e9738..4469c5b14acb 100644 --- a/libs/application/templates/transport-authority/change-operator-of-vehicle/src/lib/messages/information.ts +++ b/libs/application/templates/transport-authority/change-operator-of-vehicle/src/lib/messages/information.ts @@ -217,6 +217,11 @@ export const information = { defaultMessage: 'Það má ekki nota sömu kennitölu tvisvar', description: 'operator identical error', }, + noChangesError: { + id: 'ta.cov.application:information.labels.operator.noChangesError', + defaultMessage: 'Ekki er búið að gera neinar breytingar á umráðamönnum', + description: 'operator no changes error', + }, }), mainOperator: defineMessages({ sectionTitle: { From b60ad7f154fb6756f9fd044701ed1306d4520e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3hanna=20Magn=C3=BAsd=C3=B3ttir?= Date: Fri, 22 Nov 2024 12:24:38 +0000 Subject: [PATCH 5/8] Revert "Validate added co-owners i ChangeCoOwnerOfVehicle" This reverts commit 719277e833dc596179d09c0ce3b319d2142e00f0. --- .../{OwnerCoOwners => CoOwner}/index.tsx | 4 +- .../CoOwnerRepeaterItem.tsx} | 4 +- .../OwnerCoOwners.tsx} | 4 +- .../index.tsx | 189 +++++++++--------- .../src/fields/OldCoOwnerRepeater/index.tsx | 95 --------- .../src/fields/index.ts | 5 +- .../InformationSection/coOwnerSubSection.ts | 8 +- .../InformationSection/ownerSubSection.ts | 2 +- .../src/lib/messages/information.ts | 5 - .../BuyerCoOwnerAndOperatorRepeater/index.tsx | 5 +- 10 files changed, 109 insertions(+), 212 deletions(-) rename libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/{OwnerCoOwners => CoOwner}/index.tsx (98%) rename libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/{NewCoOwnerRepeater/NewCoOwnerRepeaterItem.tsx => CoOwnerRepeater/CoOwnerRepeaterItem.tsx} (97%) rename libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/{OldCoOwnerRepeater/OldCoOwnerRepeaterItem.tsx => CoOwnerRepeater/OwnerCoOwners.tsx} (97%) rename libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/{NewCoOwnerRepeater => CoOwnerRepeater}/index.tsx (51%) delete mode 100644 libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OldCoOwnerRepeater/index.tsx diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OwnerCoOwners/index.tsx b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwner/index.tsx similarity index 98% rename from libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OwnerCoOwners/index.tsx rename to libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwner/index.tsx index a2396aa2e1c4..2933a105e5ed 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OwnerCoOwners/index.tsx +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwner/index.tsx @@ -17,9 +17,7 @@ import { information } from '../../lib/messages' import { OwnerCoOwnersInformation } from '../../shared' import { useFormContext } from 'react-hook-form' -export const OwnerCoOwners: FC> = ( - props, -) => { +export const CoOwner: FC> = (props) => { const { application, field, setFieldLoadingState, errors } = props const { formatMessage } = useLocale() diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/NewCoOwnerRepeater/NewCoOwnerRepeaterItem.tsx b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/CoOwnerRepeaterItem.tsx similarity index 97% rename from libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/NewCoOwnerRepeater/NewCoOwnerRepeaterItem.tsx rename to libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/CoOwnerRepeaterItem.tsx index 09b7db9dd7b6..cb915baba273 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/NewCoOwnerRepeater/NewCoOwnerRepeaterItem.tsx +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/CoOwnerRepeaterItem.tsx @@ -24,7 +24,7 @@ interface Props { addNationalIdToCoOwners: (nationalId: string, index: number) => void } -export const NewCoOwnerRepeaterItem: FC< +export const CoOwnerRepeaterItem: FC< React.PropsWithChildren > = ({ id, @@ -49,7 +49,7 @@ export const NewCoOwnerRepeaterItem: FC< useEffect(() => { setValue(wasRemovedField, repeaterField.wasRemoved) - }, [repeaterField.wasRemoved, setValue, wasRemovedField]) + }, [repeaterField.wasRemoved, setValue]) return ( > = ({ id, index, rowLocation, handleRemove, wasRemoved, ...props }) => { const { setValue } = useFormContext() @@ -36,7 +36,7 @@ export const OldCoOwnerRepeaterItem: FC< useEffect(() => { setValue(wasRemovedField, `${wasRemoved}`) - }, [wasRemoved, setValue, wasRemovedField]) + }, [wasRemoved, setValue]) return ( ) } diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OldCoOwnerRepeater/index.tsx b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OldCoOwnerRepeater/index.tsx deleted file mode 100644 index 3e3d429d3a83..000000000000 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/OldCoOwnerRepeater/index.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { FieldBaseProps } from '@island.is/application/types' -import { Box } from '@island.is/island-ui/core' -import { useLocale } from '@island.is/localization' -import { FC, useCallback, useState } from 'react' -import { useFormContext } from 'react-hook-form' -import { OwnerCoOwnersInformation } from '../../shared' -import { getValueViaPath } from '@island.is/application/core' -import { OldCoOwnerRepeaterItem } from './OldCoOwnerRepeaterItem' -import { useMutation } from '@apollo/client' -import { UPDATE_APPLICATION } from '@island.is/application/graphql' - -export const OldCoOwnerRepeater: FC> = ( - props, -) => { - const { application, field } = props - const { locale } = useLocale() - const { setValue } = useFormContext() - const { id } = field - - const [updateApplication] = useMutation(UPDATE_APPLICATION) - - const [ownerCoOwners, setOwnerCoOwners] = useState< - OwnerCoOwnersInformation[] - >( - getValueViaPath( - application.answers, - 'ownerCoOwners', - [], - ) || [], - ) - - const filteredOwnerCoOwners = ownerCoOwners.filter( - ({ wasRemoved }) => wasRemoved !== 'true', - ) - - const updateData = useCallback( - async (position: number) => { - await updateApplication({ - variables: { - input: { - id: application.id, - answers: { - ownerCoOwners: ownerCoOwners.map((coOwner, index) => { - if (index === position) { - return { ...coOwner, wasRemoved: 'true' } - } else { - return coOwner - } - }), - }, - }, - locale, - }, - }) - }, - [application.id, locale, ownerCoOwners, updateApplication], - ) - - const handleRemoveOld = (position: number) => { - if (ownerCoOwners.length >= position) { - setValue(`ownerCoOwners[${position}].wasRemoved`, 'true') - setOwnerCoOwners( - ownerCoOwners.map((coOwner, index) => { - if (index === position) { - return { ...coOwner, wasRemoved: 'true' } - } else { - return coOwner - } - }), - ) - updateData(position) - } - } - - return ( - - {ownerCoOwners.length > 0 && - ownerCoOwners.map((coOwner, index) => ( - -1 - ? filteredOwnerCoOwners.indexOf(coOwner) + 1 - : index + 1 - } - key={`ownerCoOwners-${index}`} - handleRemove={handleRemoveOld} - wasRemoved={coOwner.wasRemoved === 'true'} - {...props} - /> - ))} - - ) -} diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/index.ts b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/index.ts index c149427a905a..902f060904f1 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/index.ts +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/index.ts @@ -1,7 +1,6 @@ export { VehiclesField } from './VehiclesField' -export { OwnerCoOwners } from './OwnerCoOwners' -export { OldCoOwnerRepeater } from './OldCoOwnerRepeater' -export { NewCoOwnerRepeater } from './NewCoOwnerRepeater' +export { CoOwner } from './CoOwner' +export { CoOwnerRepeater } from './CoOwnerRepeater' export { Review } from './Review' export { RejectedConclusion } from './RejectedConclusion' export { ValidationErrorMessages } from './ValidationErrorMessages' diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/forms/ChangeCoOwnerOfVehicleForm/InformationSection/coOwnerSubSection.ts b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/forms/ChangeCoOwnerOfVehicleForm/InformationSection/coOwnerSubSection.ts index 958423fc355a..75b5353dd6f8 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/forms/ChangeCoOwnerOfVehicleForm/InformationSection/coOwnerSubSection.ts +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/forms/ChangeCoOwnerOfVehicleForm/InformationSection/coOwnerSubSection.ts @@ -14,15 +14,9 @@ export const coOwnerSubSection = buildSubSection({ title: information.labels.coOwner.title, description: information.labels.coOwner.description, children: [ - buildCustomField({ - id: 'ownerCoOwners', - component: 'OldCoOwnerRepeater', - title: '', - doesNotRequireAnswer: true, - }), buildCustomField({ id: 'coOwners', - component: 'NewCoOwnerRepeater', + component: 'CoOwnerRepeater', title: '', doesNotRequireAnswer: true, }), diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/forms/ChangeCoOwnerOfVehicleForm/InformationSection/ownerSubSection.ts b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/forms/ChangeCoOwnerOfVehicleForm/InformationSection/ownerSubSection.ts index 3b7ee651884e..17ad4ac095d5 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/forms/ChangeCoOwnerOfVehicleForm/InformationSection/ownerSubSection.ts +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/forms/ChangeCoOwnerOfVehicleForm/InformationSection/ownerSubSection.ts @@ -63,7 +63,7 @@ export const ownerSubSection = buildSubSection({ buildCustomField({ id: 'ownerCoOwners', title: '', - component: 'OwnerCoOwners', + component: 'CoOwner', doesNotRequireAnswer: true, }), ], diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/messages/information.ts b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/messages/information.ts index 59c21b22b038..f09661a73d91 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/messages/information.ts +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/messages/information.ts @@ -175,11 +175,6 @@ export const information = { defaultMessage: 'Það má ekki nota sömu kennitölu tvisvar', description: 'coOwner identical error', }, - noChangesError: { - id: 'ta.ccov.application:information.labels.coOwner.noChangesError', - defaultMessage: 'Ekki er búið að gera neinar breytingar á meðeigendum', - description: 'coOwner no changes error', - }, }), vehicle: defineMessages({ sectionTitle: { diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx index 9e01002e0e99..b212561f8d9f 100644 --- a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx +++ b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx @@ -61,7 +61,9 @@ export const BuyerCoOwnerAndOperatorRepeater: FC< } const getBuyerNationalId = async () => { - // Get updated buyer nationalId from answers + // Get buyer nationalId from updated answers (cannot use application.answers), + // since that is filled out in the same step as this, + // but the buyer value is updated in answers right away const applicationInfo = await getApplicationInfo({ variables: { input: { @@ -71,6 +73,7 @@ export const BuyerCoOwnerAndOperatorRepeater: FC< }, fetchPolicy: 'no-cache', }) + const updatedApplication = applicationInfo?.data?.applicationApplication const buyerNationalId = From 9b165836dbb181b95d7faf7f54c5bc2924237f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3hanna=20Magn=C3=BAsd=C3=B3ttir?= Date: Fri, 22 Nov 2024 12:31:43 +0000 Subject: [PATCH 6/8] Add error message if no changes in ChangeCoOwnerOfVehicle --- .../src/fields/CoOwnerRepeater/index.tsx | 79 +++++++++++++------ .../src/lib/messages/information.ts | 5 ++ .../BuyerCoOwnerAndOperatorRepeater/index.tsx | 4 +- 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/index.tsx b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/index.tsx index 109a6bd97138..743efd1a7abd 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/index.tsx +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/fields/CoOwnerRepeater/index.tsx @@ -35,6 +35,9 @@ export const CoOwnerRepeater: FC> = ( ) as CoOwnersInformation[], ) const [identicalError, setIdenticalError] = useState(false) + const [noCoOwnerChangesError, setNoCoOwnerChangesError] = + useState(false) + const filteredCoOwners = coOwners.filter( ({ wasRemoved }) => wasRemoved !== 'true', ) @@ -42,25 +45,28 @@ export const CoOwnerRepeater: FC> = ( ({ wasRemoved }) => wasRemoved !== 'true', ) - const updateData = useCallback(async (position: number) => { - await updateApplication({ - variables: { - input: { - id: application.id, - answers: { - ownerCoOwners: ownerCoOwners.map((coOwner, index) => { - if (index === position) { - return { ...coOwner, wasRemoved: 'true' } - } else { - return coOwner - } - }), + const updateData = useCallback( + async (position: number) => { + await updateApplication({ + variables: { + input: { + id: application.id, + answers: { + ownerCoOwners: ownerCoOwners.map((coOwner, index) => { + if (index === position) { + return { ...coOwner, wasRemoved: 'true' } + } else { + return coOwner + } + }), + }, }, + locale, }, - locale, - }, - }) - }, []) + }) + }, + [application.id, locale, ownerCoOwners, updateApplication], + ) const addNationalIdToCoOwners = (nationalId: string, newIndex: number) => { setCoOwners( @@ -144,14 +150,29 @@ export const CoOwnerRepeater: FC> = ( } }, [coOwners, setValue]) - setBeforeSubmitCallback && - setBeforeSubmitCallback(async () => { - setIdenticalError(checkDuplicate()) - if (checkDuplicate()) { - return [false, 'Identical nationalIds'] - } - return [true, null] - }) + setBeforeSubmitCallback?.(async () => { + setIdenticalError(false) + setNoCoOwnerChangesError(false) + + const hasDuplicate = await checkDuplicate() + if (hasDuplicate) { + setIdenticalError(true) + return [false, 'Identical nationalIds'] + } + + const coOwnerWasAdded = + coOwners?.filter(({ wasRemoved }) => wasRemoved !== 'true').length > 0 + const coOwnerWasRemoved = !!ownerCoOwners?.find( + (x) => x.wasRemoved === 'true', + ) + const noCoOwnerChanges = !coOwnerWasAdded && !coOwnerWasRemoved + if (noCoOwnerChanges) { + setNoCoOwnerChangesError(true) + return [false, 'No co-owner has been added/removed'] + } + + return [true, null] + }) return ( @@ -206,6 +227,14 @@ export const CoOwnerRepeater: FC> = ( /> )} + {noCoOwnerChangesError && ( + + + + )} ) } diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/messages/information.ts b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/messages/information.ts index f09661a73d91..59c21b22b038 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/messages/information.ts +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/messages/information.ts @@ -175,6 +175,11 @@ export const information = { defaultMessage: 'Það má ekki nota sömu kennitölu tvisvar', description: 'coOwner identical error', }, + noChangesError: { + id: 'ta.ccov.application:information.labels.coOwner.noChangesError', + defaultMessage: 'Ekki er búið að gera neinar breytingar á meðeigendum', + description: 'coOwner no changes error', + }, }), vehicle: defineMessages({ sectionTitle: { diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx index b212561f8d9f..76a88d97052a 100644 --- a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx +++ b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx @@ -61,9 +61,7 @@ export const BuyerCoOwnerAndOperatorRepeater: FC< } const getBuyerNationalId = async () => { - // Get buyer nationalId from updated answers (cannot use application.answers), - // since that is filled out in the same step as this, - // but the buyer value is updated in answers right away + // Get updated buyer nationalId from answers const applicationInfo = await getApplicationInfo({ variables: { input: { From 3202ec02f07a6582dc856225d63fd23cc4a4544e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3hanna=20Magn=C3=BAsd=C3=B3ttir?= Date: Fri, 22 Nov 2024 14:33:25 +0000 Subject: [PATCH 7/8] Cleanup --- .../src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx index 76a88d97052a..390da99497fd 100644 --- a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx +++ b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx @@ -76,7 +76,7 @@ export const BuyerCoOwnerAndOperatorRepeater: FC< const buyerNationalId = getValueViaPath( - updatedApplication.answers, + updatedApplication?.answers, 'buyer.nationalId', '', ) || '' From ec0181c866e6073015655b2ac699750379345402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3hanna=20Magn=C3=BAsd=C3=B3ttir?= Date: Fri, 22 Nov 2024 15:25:07 +0000 Subject: [PATCH 8/8] Use watch instead of getApplicationInfo --- .../BuyerCoOwnerAndOperatorRepeater/index.tsx | 37 ++----------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx index 390da99497fd..5a29be5b7f7c 100644 --- a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx +++ b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/fields/BuyerCoOwnerAndOperatorRepeater/index.tsx @@ -7,8 +7,7 @@ import { information } from '../../lib/messages' import { CoOwnerAndOperator } from '../../shared' import { repeaterButtons } from './BuyerCoOwnerAndOperatorRepeater.css' import { BuyerCoOwnerAndOperatorRepeaterItem } from './BuyerCoOwnerAndOperatorRepeaterItem' -import { useLazyQuery } from '@apollo/client' -import { APPLICATION_APPLICATION } from '@island.is/application/graphql' +import { useFormContext } from 'react-hook-form' export const BuyerCoOwnerAndOperatorRepeater: FC< React.PropsWithChildren @@ -16,16 +15,10 @@ export const BuyerCoOwnerAndOperatorRepeater: FC< const { formatMessage } = useLocale() const { application, field, setBeforeSubmitCallback } = props const { id } = field + const { watch } = useFormContext() const [identicalError, setIdenticalError] = useState(false) - const [getApplicationInfo] = useLazyQuery(APPLICATION_APPLICATION, { - onError: (e) => { - console.error(e, e.message) - return - }, - }) - const [buyerCoOwnerAndOperator, setBuyerCoOwnerAndOperator] = useState< CoOwnerAndOperator[] >( @@ -60,30 +53,6 @@ export const BuyerCoOwnerAndOperatorRepeater: FC< ) } - const getBuyerNationalId = async () => { - // Get updated buyer nationalId from answers - const applicationInfo = await getApplicationInfo({ - variables: { - input: { - id: application.id, - }, - locale: 'is', - }, - fetchPolicy: 'no-cache', - }) - - const updatedApplication = applicationInfo?.data?.applicationApplication - - const buyerNationalId = - getValueViaPath( - updatedApplication?.answers, - 'buyer.nationalId', - '', - ) || '' - - return buyerNationalId - } - const checkDuplicate = async () => { const existingCoOwnersAndOperators = filteredCoOwnersAndOperators.map( ({ nationalId }) => { @@ -91,7 +60,7 @@ export const BuyerCoOwnerAndOperatorRepeater: FC< }, ) - const buyerNationalId = await getBuyerNationalId() + const buyerNationalId = watch('buyer.nationalId') const jointOperators = [...existingCoOwnersAndOperators, buyerNationalId] return !!jointOperators.some((nationalId, index) => {