Skip to content

Commit

Permalink
feat: validate the address according to the specification (#1057)
Browse files Browse the repository at this point in the history
* feat: validate the address according to the specification

Used these docs to determine the validation rules: https://api-reference.swan.io/inputs/complete-address-with-contact-input#fields

* chore: reverted locale reordering

* feat: extra validation to make sure all the required fields are filled in

* chore: reverted reordering

* refactor: added reusable validateAddress function to handle address validation
  • Loading branch information
timo-peakfijn authored Jan 7, 2025
1 parent b41f656 commit 1f5dcd5
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import { forwardRef, useImperativeHandle, useState } from "react";
import { P, match } from "ts-pattern";
import { CompleteAddressInput } from "../graphql/partner";
import { locale, t } from "../utils/i18n";
import { validateAddressLine, validateRequired } from "../utils/validations";
import {
validateAddressLine,
validateCity,
validatePostalCode,
validateRequired,
} from "../utils/validations";

export type CardItemPhysicalDeliveryAddressFormRef = {
submit: () => void;
Expand Down Expand Up @@ -49,14 +54,15 @@ export const CardItemPhysicalDeliveryAddressForm = forwardRef<
},
addressLine2: {
initialValue: initialEditorState?.addressLine2 ?? "",
validate: validateAddressLine,
},
postalCode: {
initialValue: initialEditorState?.postalCode ?? "",
validate: validateRequired,
validate: combineValidators(validateRequired, validatePostalCode),
},
city: {
initialValue: initialEditorState?.city ?? "",
validate: validateRequired,
validate: combineValidators(validateRequired, validateCity),
},
country: {
initialValue: match(initialEditorState?.country)
Expand Down
14 changes: 11 additions & 3 deletions clients/banking/src/components/CardWizardAddressForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ import { combineValidators, useForm } from "@swan-io/use-form";
import { forwardRef, useCallback, useImperativeHandle } from "react";
import { View } from "react-native";
import { locale, t } from "../utils/i18n";
import { validateAddressLine, validateRequired } from "../utils/validations";
import {
validateAddressLine,
validateCity,
validatePostalCode,
validateRequired,
validateState,
} from "../utils/validations";

export type Address = {
addressLine1: string;
Expand Down Expand Up @@ -39,17 +45,19 @@ export const CardWizardAddressForm = forwardRef<CardWizardAddressFormRef, Props>
},
addressLine2: {
initialValue: initialAddress.addressLine2 ?? "",
validate: validateAddressLine,
},
postalCode: {
initialValue: initialAddress.postalCode,
validate: validateRequired,
validate: combineValidators(validateRequired, validatePostalCode),
},
city: {
initialValue: initialAddress.city,
validate: validateRequired,
validate: combineValidators(validateRequired, validateCity),
},
state: {
initialValue: initialAddress.state ?? "",
validate: combineValidators(validateState, validateState),
},
country: {
initialValue: initialAddress.country ?? "",
Expand Down
21 changes: 10 additions & 11 deletions clients/banking/src/components/CardWizardGroupedDelivery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { LakeText } from "@swan-io/lake/src/components/LakeText";
import { Space } from "@swan-io/lake/src/components/Space";
import { Tile } from "@swan-io/lake/src/components/Tile";
import { colors } from "@swan-io/lake/src/constants/design";
import { isNotNullish } from "@swan-io/lake/src/utils/nullish";
import { GetNode } from "@swan-io/lake/src/utils/types";
import { LakeModal } from "@swan-io/shared-business/src/components/LakeModal";
import { CountryCCA3 } from "@swan-io/shared-business/src/constants/countries";
Expand All @@ -21,7 +20,7 @@ import {
} from "../graphql/partner";
import { getMemberName } from "../utils/accountMembership";
import { t } from "../utils/i18n";
import { validateAddressLine } from "../utils/validations";
import { validateAddress } from "../utils/validations";
import { Address, CardWizardAddressForm } from "./CardWizardAddressForm";

const styles = StyleSheet.create({
Expand Down Expand Up @@ -71,18 +70,18 @@ export const CardWizardGroupedDelivery = forwardRef<CardWizardGroupedDeliveryRef

const [editingAddress, setEditingAddress] = useState<Address | null>(null);

const hasSomeError = validateAddress(currentCardGroupedDeliveryConfig.address);

useImperativeHandle(
ref,
() => ({
submit: () => {
onSubmit(currentCardGroupedDeliveryConfig);
if (!hasSomeError) {
onSubmit(currentCardGroupedDeliveryConfig);
}
},
}),
[currentCardGroupedDeliveryConfig, onSubmit],
);

const hasError = isNotNullish(
validateAddressLine(currentCardGroupedDeliveryConfig.address.addressLine1),
[currentCardGroupedDeliveryConfig, hasSomeError, onSubmit],
);

return (
Expand All @@ -95,13 +94,13 @@ export const CardWizardGroupedDelivery = forwardRef<CardWizardGroupedDeliveryRef
<Space height={12} />

<Tile
style={hasError ? styles.erroredTile : null}
style={hasSomeError ? styles.erroredTile : null}
footer={
hasError ? (
hasSomeError ? (
<LakeAlert
anchored={true}
variant="error"
title={t("cardWizard.address.tooLong")}
title={t("cardWizard.address.invalid")}
/>
) : null
}
Expand Down
13 changes: 5 additions & 8 deletions clients/banking/src/components/CardWizardIndividualDelivery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { Space } from "@swan-io/lake/src/components/Space";
import { Tile } from "@swan-io/lake/src/components/Tile";
import { commonStyles } from "@swan-io/lake/src/constants/commonStyles";
import { colors } from "@swan-io/lake/src/constants/design";
import { isNotNullish } from "@swan-io/lake/src/utils/nullish";
import { GetNode } from "@swan-io/lake/src/utils/types";
import { LakeModal } from "@swan-io/shared-business/src/components/LakeModal";
import { CountryCCA3 } from "@swan-io/shared-business/src/constants/countries";
Expand All @@ -22,7 +21,7 @@ import {
} from "../graphql/partner";
import { getMemberName } from "../utils/accountMembership";
import { t } from "../utils/i18n";
import { validateAddressLine } from "../utils/validations";
import { validateAddress } from "../utils/validations";
import { Address, CardWizardAddressForm } from "./CardWizardAddressForm";
import { CardWizardChoosePinModal } from "./CardWizardChoosePinModal";

Expand Down Expand Up @@ -67,7 +66,7 @@ const CardWizardIndividualDeliveryWithAddress = forwardRef<
const [editingAddress, setEditingAddress] = useState<[Address, number] | null>(null);

const hasSomeError = currentCardIndividualDeliveryConfig.some(config =>
isNotNullish(validateAddressLine(config.address.addressLine1)),
validateAddress(config.address),
);

useImperativeHandle(
Expand All @@ -85,18 +84,16 @@ const CardWizardIndividualDeliveryWithAddress = forwardRef<
return (
<View>
{currentCardIndividualDeliveryConfig.map((config, index) => {
const hasError = isNotNullish(validateAddressLine(config.address.addressLine1));

return (
<View key={config.member.id}>
<Tile
style={hasError ? styles.erroredTile : null}
style={hasSomeError ? styles.erroredTile : null}
footer={
hasError ? (
hasSomeError ? (
<LakeAlert
anchored={true}
variant="error"
title={t("cardWizard.address.tooLong")}
title={t("cardWizard.address.invalid")}
/>
) : null
}
Expand Down
4 changes: 2 additions & 2 deletions clients/banking/src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,14 @@
"cardWizard.address.cityPlaceholder": "Ort eingeben",
"cardWizard.address.country": "Land",
"cardWizard.address.countryPlaceholder": "Land auswählen",
"cardWizard.address.invalid": "Diese Adresse ist unvollständig oder ungültig. Klicken Sie auf „Ändern“, um die Adressdetails zu bearbeiten",
"cardWizard.address.line1": "Adresszeile 1",
"cardWizard.address.line2": "Adresszeile 2",
"cardWizard.address.line2Placeholder": "Zusätzliche Adressinformationen eingeben",
"cardWizard.address.postalCode": "Postleitzahl",
"cardWizard.address.postalCodePlaceholder": "Postleitzahl eingeben",
"cardWizard.address.state": "Bundesland",
"cardWizard.address.statePlaceholder": "Bundesland eingeben",
"cardWizard.address.tooLong": "Diese Adresse ist zu lang, klicken Sie auf „Ändern“, um die Adressdetails zu bearbeiten",
"cardWizard.header.address": "Adresse",
"cardWizard.header.cardFormat": "Welches Format?",
"cardWizard.header.cardProduct": "Welche Karte?",
Expand Down Expand Up @@ -396,7 +396,6 @@
"common.form.chooseDateBefore": "Wählen Sie ein Datum vor {date}",
"common.form.dateCannotBePast": "Dieses Datum darf nicht in der Vergangenheit liegen",
"common.form.dateIsNotWithinYear": "Sie können eine Überweisung nur bis zu einem Jahr im Voraus planen.",
"common.form.invalidAddressLine": "Dieses Feld ist auf 38 Zeichen begrenzt",
"common.form.invalidAmount": "Ungültiger Betrag",
"common.form.invalidBulkAmount": "Zeile {line} enthält einen ungültigen Betrag",
"common.form.invalidBulkBeneficiaryName": "Zeile {line} enthält einen ungültigen Empfängernamen",
Expand All @@ -410,6 +409,7 @@
"common.form.invalidEmail": "Ungültige E-Mail-Adresse",
"common.form.invalidFile": "Ungültige Datei",
"common.form.invalidFileLine": "Zeile {line} enthält ungültige oder fehlende Daten",
"common.form.invalidLength": "Dieses Feld ist auf {maxLength} Zeichen begrenzt",
"common.form.invalidMessage": "Die Nachricht darf nicht mehr als {maxLength} Zeichen enthalten",
"common.form.invalidName": "Ungültiger Name",
"common.form.invalidPhoneNumber": "Ungültige Telefonnummer",
Expand Down
4 changes: 2 additions & 2 deletions clients/banking/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,14 @@
"cardWizard.address.cityPlaceholder": "Enter the city",
"cardWizard.address.country": "Country",
"cardWizard.address.countryPlaceholder": "Select a country",
"cardWizard.address.invalid": "This address is incomplete or invalid. Click \"Change\" to edit address details.",
"cardWizard.address.line1": "Address line 1",
"cardWizard.address.line2": "Address line 2",
"cardWizard.address.line2Placeholder": "Enter additional address information",
"cardWizard.address.postalCode": "Postal code",
"cardWizard.address.postalCodePlaceholder": "Enter the postal code",
"cardWizard.address.state": "State",
"cardWizard.address.statePlaceholder": "Enter the state",
"cardWizard.address.tooLong": "This address is too long. Click \"Change\" to edit address details.",
"cardWizard.header.address": "Address",
"cardWizard.header.cardFormat": "Which format?",
"cardWizard.header.cardProduct": "Which card?",
Expand Down Expand Up @@ -396,7 +396,6 @@
"common.form.chooseDateBefore": "Choose a date before {date}",
"common.form.dateCannotBePast": "This date cannot be in the past",
"common.form.dateIsNotWithinYear": "You can only schedule a transfer up to one year in advance.",
"common.form.invalidAddressLine": "This field is limited to 38 characters",
"common.form.invalidAmount": "Invalid amount",
"common.form.invalidBulkAmount": "Line {line} has an invalid amount",
"common.form.invalidBulkBeneficiaryName": "Line {line} has an invalid beneficiary name",
Expand All @@ -410,6 +409,7 @@
"common.form.invalidEmail": "Invalid email",
"common.form.invalidFile": "Invalid file",
"common.form.invalidFileLine": "Line {line} has invalid or missing data",
"common.form.invalidLength": "This field is limited to {maxLength} characters",
"common.form.invalidMessage": "Message should not exceed {maxLength} characters",
"common.form.invalidName": "Invalid name",
"common.form.invalidPhoneNumber": "Invalid phone number",
Expand Down
4 changes: 2 additions & 2 deletions clients/banking/src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,14 @@
"cardWizard.address.cityPlaceholder": "Introduce la ciudad",
"cardWizard.address.country": "País",
"cardWizard.address.countryPlaceholder": "Seleccionar un país",
"cardWizard.address.invalid": "Esta dirección es incompleta o inválida. Haz clic en \"Cambiar\" para editar la dirección.",
"cardWizard.address.line1": "Línea de dirección 1",
"cardWizard.address.line2": "Línea de dirección 2",
"cardWizard.address.line2Placeholder": "Introduce información adicional de la dirección",
"cardWizard.address.postalCode": "Código postal",
"cardWizard.address.postalCodePlaceholder": "Introduce el código postal",
"cardWizard.address.state": "Provincia",
"cardWizard.address.statePlaceholder": "Introduce la provincia",
"cardWizard.address.tooLong": "Esta dirección es demasiado larga. Haz clic en \"Cambiar\" para editar la dirección.",
"cardWizard.header.address": "Dirección",
"cardWizard.header.cardFormat": "¿Qué formato?",
"cardWizard.header.cardProduct": "¿Qué tarjeta?",
Expand Down Expand Up @@ -396,7 +396,6 @@
"common.form.chooseDateBefore": "Elige una fecha anterior a {date}",
"common.form.dateCannotBePast": "No puede ser una fecha pasada",
"common.form.dateIsNotWithinYear": "Solo puedes programar una transferencia hasta con un año de anticipación.",
"common.form.invalidAddressLine": "Este campo está limitado a 38 caracteres",
"common.form.invalidAmount": "Esta cantidad no es válida",
"common.form.invalidBulkAmount": "La línea {line} contiene un monto inválido",
"common.form.invalidBulkBeneficiaryName": "La línea {line} contiene un nombre de beneficiario inválido",
Expand All @@ -410,6 +409,7 @@
"common.form.invalidEmail": "Correo electrónico no válido",
"common.form.invalidFile": "Archivo no válido",
"common.form.invalidFileLine": "La línea {line} contiene datos inválidos o le faltan datos",
"common.form.invalidLength": "Este campo está limitado a {maxLength} caracteres",
"common.form.invalidMessage": "El mensaje no debe superar los {maxLength} caracteres",
"common.form.invalidName": "Nombre inválido",
"common.form.invalidPhoneNumber": "Este número de teléfono no es válido",
Expand Down
4 changes: 2 additions & 2 deletions clients/banking/src/locales/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,14 @@
"cardWizard.address.cityPlaceholder": "Kirjoita kaupunki",
"cardWizard.address.country": "Maa",
"cardWizard.address.countryPlaceholder": "Valitse maa",
"cardWizard.address.invalid": "Osoite on täydentämätön tai virheellinen. Napsauta \"Muuta\" muokataksesi osoitetietoja.",
"cardWizard.address.line1": "Osoiterivi 1",
"cardWizard.address.line2": "Osoiterivi 2",
"cardWizard.address.line2Placeholder": "Lisää muut osoitetiedot",
"cardWizard.address.postalCode": "Postinumero",
"cardWizard.address.postalCodePlaceholder": "Kirjoita postinumero",
"cardWizard.address.state": "Osavaltio",
"cardWizard.address.statePlaceholder": "Kirjoita osavaltio",
"cardWizard.address.tooLong": "Osoite on liian pitkä. Napsauta \"Muuta\" muokataksesi osoitetietoja.",
"cardWizard.header.address": "Osoite",
"cardWizard.header.cardFormat": "Mikä on kortin tyyppi?",
"cardWizard.header.cardProduct": "Mikä kortti?",
Expand Down Expand Up @@ -396,7 +396,6 @@
"common.form.chooseDateBefore": "Valitse päivämäärä, joka on ennen {date}",
"common.form.dateCannotBePast": "Tämä päivämäärä ei voi olla menneisyydessä",
"common.form.dateIsNotWithinYear": "Voit ajoittaa siirron enintään yhden vuoden päähän.",
"common.form.invalidAddressLine": "Tämä kenttä on rajoitettu 38 merkkiin",
"common.form.invalidAmount": "Summa on väärässä muodossa",
"common.form.invalidBulkAmount": "Rivi {line} sisältää virheellisen summan",
"common.form.invalidBulkBeneficiaryName": "Rivi {line} sisältää virheellisen vastaanottajan nimen",
Expand All @@ -410,6 +409,7 @@
"common.form.invalidEmail": "Sähköposti on väärässä muodossa",
"common.form.invalidFile": "Virheellinen tiedosto",
"common.form.invalidFileLine": "Rivi {line} sisältää virheellisiä tai puuttuvia tietoja",
"common.form.invalidLength": "Tämä kenttä on rajoitettu {maxLength} merkkiin",
"common.form.invalidMessage": "Viestin pituus ei saa ylittää {maxLength} merkkiä",
"common.form.invalidName": "Nimi on väärässä muodossa",
"common.form.invalidPhoneNumber": "Puhelinnumero on väärässä muodossa",
Expand Down
4 changes: 2 additions & 2 deletions clients/banking/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,14 @@
"cardWizard.address.cityPlaceholder": "Saisissez la ville",
"cardWizard.address.country": "Pays",
"cardWizard.address.countryPlaceholder": "Sélectionnez un pays",
"cardWizard.address.invalid": "Cette adresse est incomplète ou incorrecte. Cliquez sur « Modifier » pour éditer les détails de l'adresse.",
"cardWizard.address.line1": "Ligne d'adresse 1",
"cardWizard.address.line2": "Ligne d'adresse 2",
"cardWizard.address.line2Placeholder": "Indiquez des informations supplémentaires sur l'adresse",
"cardWizard.address.postalCode": "Code postal",
"cardWizard.address.postalCodePlaceholder": "Saisissez le code postal",
"cardWizard.address.state": "État",
"cardWizard.address.statePlaceholder": "Saisissez l'État",
"cardWizard.address.tooLong": "Cette adresse est trop longue. Cliquez sur « Modifier » pour éditer les détails de l'adresse.",
"cardWizard.header.address": "Adresse",
"cardWizard.header.cardFormat": "Quel format ?",
"cardWizard.header.cardProduct": "Quelle carte ?",
Expand Down Expand Up @@ -396,7 +396,6 @@
"common.form.chooseDateBefore": "Veuillez choisir une date avant le {date}",
"common.form.dateCannotBePast": "Cette date ne peut pas être dans le passé",
"common.form.dateIsNotWithinYear": "Vous ne pouvez planifier un virement que jusqu'à un an à l'avance.",
"common.form.invalidAddressLine": "Ce champ est limité à 38 caractères",
"common.form.invalidAmount": "Montant non valide",
"common.form.invalidBulkAmount": "La ligne {line} contient un montant invalide",
"common.form.invalidBulkBeneficiaryName": "La ligne {line} contient un nom de bénéficiaire invalide",
Expand All @@ -410,6 +409,7 @@
"common.form.invalidEmail": "E-mail non valide",
"common.form.invalidFile": "Fichier invalide",
"common.form.invalidFileLine": "La ligne {line} contient des données invalides ou manquantes",
"common.form.invalidLength": "Ce champ est limité à {maxLength} caractères",
"common.form.invalidMessage": "Le message ne doit pas dépasser {maxLength} caractères",
"common.form.invalidName": "Nom non valide",
"common.form.invalidPhoneNumber": "Numéro de téléphone non valide",
Expand Down
4 changes: 2 additions & 2 deletions clients/banking/src/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,14 @@
"cardWizard.address.cityPlaceholder": "Inserisca la città",
"cardWizard.address.country": "Paese",
"cardWizard.address.countryPlaceholder": "Selezioni un paese",
"cardWizard.address.invalid": "Questo indirizzo è incompleto o errato. Clicchi su \"Modifica\" per modificare i dettagli dell'indirizzo.",
"cardWizard.address.line1": "Riga dell'indirizzo 1",
"cardWizard.address.line2": "Riga dell'indirizzo 2",
"cardWizard.address.line2Placeholder": "Inserisca ulteriori informazioni sull'indirizzo",
"cardWizard.address.postalCode": "Codice postale",
"cardWizard.address.postalCodePlaceholder": "Inserisca il codice postale",
"cardWizard.address.state": "Provincia",
"cardWizard.address.statePlaceholder": "Inserisca la provincia",
"cardWizard.address.tooLong": "Questo indirizzo è troppo lungo, clicchi su \"Modifica\" per cambiare i dettagli dell'indirizzo.",
"cardWizard.header.address": "Indirizzo",
"cardWizard.header.cardFormat": "Quale formato?",
"cardWizard.header.cardProduct": "Quale carta?",
Expand Down Expand Up @@ -396,7 +396,6 @@
"common.form.chooseDateBefore": "Scelga una data precedente a {date}",
"common.form.dateCannotBePast": "Questa data non può essere nel passato",
"common.form.dateIsNotWithinYear": "Può programmare un bonifico solo fino a un anno in anticipo.",
"common.form.invalidAddressLine": "Questo campo ha un limite di 38 caratteri",
"common.form.invalidAmount": "Questo importo non è valido",
"common.form.invalidBulkAmount": "La riga {line} ha un importo non valido",
"common.form.invalidBulkBeneficiaryName": "La riga {line} ha un nome del beneficiario non valido",
Expand All @@ -410,6 +409,7 @@
"common.form.invalidEmail": "Questo indirizzo email non è valido",
"common.form.invalidFile": "File non valido",
"common.form.invalidFileLine": "La riga {line} contiene dati non validi o mancanti",
"common.form.invalidLength": "Questo campo ha un limite di {maxLength} caratteri",
"common.form.invalidMessage": "Il messaggio non deve superare i {maxLength} caratteri",
"common.form.invalidName": "Nome non valido",
"common.form.invalidPhoneNumber": "Questo numero di telefono non è valido",
Expand Down
Loading

0 comments on commit 1f5dcd5

Please sign in to comment.