diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index a4de996f..032ab47f 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -41,3 +41,6 @@ jobs: env: REACT_APP_BUILD_ID: ${{ github.run_number }}-${{ github.run_id }} run: npm run build:dev + + - name: Build widget + run: npm run widget:dev diff --git a/e2e/user-flows.spec.ts b/e2e/user-flows.spec.ts index 02b67491..fd6a4431 100644 --- a/e2e/user-flows.spec.ts +++ b/e2e/user-flows.spec.ts @@ -140,7 +140,7 @@ test.describe('Account & Settings', () => { }); test('should load mail settings page', async ({ page }) => { - await page.goto(`/settings/mail?session=${token}`); + await page.goto(`/account/mail?session=${token}`); await page.waitForLoadState('networkidle'); await expect(page.locator('body')).toBeVisible(); }); diff --git a/package-lock.json b/package-lock.json index a8ecfc9e..75243f29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "1.0.4", "license": "MIT", "dependencies": { - "@dfx.swiss/react": "^1.3.0-beta.240", - "@dfx.swiss/react-components": "^1.3.0-beta.240", + "@dfx.swiss/react": "^1.3.0-beta.247", + "@dfx.swiss/react-components": "^1.3.0-beta.247", "@ledgerhq/hw-app-btc": "^6.24.1", "@ledgerhq/hw-app-eth": "^6.33.7", "@ledgerhq/hw-transport-webhid": "^6.27.19", @@ -2631,9 +2631,9 @@ } }, "node_modules/@dfx.swiss/react": { - "version": "1.3.0-beta.240", - "resolved": "https://registry.npmjs.org/@dfx.swiss/react/-/react-1.3.0-beta.240.tgz", - "integrity": "sha512-kS6daIyMDb8yu5XDY+ixVQDyxrAOBKVk+AchqUW4peLWSwRG8M9XkguZNsqXBWE/JE1oPhcl28iV8oxaINCM3w==", + "version": "1.3.0-beta.247", + "resolved": "https://registry.npmjs.org/@dfx.swiss/react/-/react-1.3.0-beta.247.tgz", + "integrity": "sha512-tKQKYVoBCiqtNFG5CkGpai17fzMVyLss2JjsT7cGlFcjFIBph9u//WOJFceuZBXCny3vLi3RMxaji3p5zdQ0Pw==", "license": "MIT", "dependencies": { "ibantools": "^4.2.1", @@ -2644,9 +2644,9 @@ } }, "node_modules/@dfx.swiss/react-components": { - "version": "1.3.0-beta.240", - "resolved": "https://registry.npmjs.org/@dfx.swiss/react-components/-/react-components-1.3.0-beta.240.tgz", - "integrity": "sha512-P8ACYD3vg0vU5SLoqPqyMnZgzcC1vhuLXJ6NTW83VHR91/Naf5IYusEcDmIHaXezWkEF7uXvYWltHVYtnWdeNw==", + "version": "1.3.0-beta.247", + "resolved": "https://registry.npmjs.org/@dfx.swiss/react-components/-/react-components-1.3.0-beta.247.tgz", + "integrity": "sha512-P2rRi/b8qXWYHhPRfsu3/+7Xsc6feke2wqGCVch/UG7X8v0ThPwah8T0gNGi1AbrQiUXT//snImhCehoWPwunQ==", "license": "MIT", "dependencies": { "@floating-ui/react": "^0.18.1", diff --git a/package.json b/package.json index 5524dd19..7bb20034 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "access": "public" }, "dependencies": { - "@dfx.swiss/react": "^1.3.0-beta.240", - "@dfx.swiss/react-components": "^1.3.0-beta.240", + "@dfx.swiss/react": "^1.3.0-beta.247", + "@dfx.swiss/react-components": "^1.3.0-beta.247", "@ledgerhq/hw-app-btc": "^6.24.1", "@ledgerhq/hw-app-eth": "^6.33.7", "@ledgerhq/hw-transport-webhid": "^6.27.19", diff --git a/src/App.tsx b/src/App.tsx index dd977871..5dcd1e2d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -94,12 +94,12 @@ export const Routes = [ element: withSuspense(), }, { - path: 'settings', - element: withSuspense(), + path: 'account/mail', + element: withSuspense(), }, { - path: 'settings/mail', - element: withSuspense(), + path: 'settings', + element: withSuspense(), }, { path: 'login', diff --git a/src/config/labels.ts b/src/config/labels.ts index 9b627df6..25e745cb 100644 --- a/src/config/labels.ts +++ b/src/config/labels.ts @@ -135,6 +135,7 @@ export const IssueTypeLabels = { [SupportIssueType.PARTNERSHIP_REQUEST]: 'Partnership request', [SupportIssueType.NOTIFICATION_OF_CHANGES]: 'Notification of changes', [SupportIssueType.BUG_REPORT]: 'Bug report', + [SupportIssueType.VERIFICATION_CALL]: 'Verification call', }; export const IssueReasonLabels = { @@ -142,6 +143,11 @@ export const IssueReasonLabels = { [SupportIssueReason.DATA_REQUEST]: 'Data request', [SupportIssueReason.FUNDS_NOT_RECEIVED]: 'Funds not received', [SupportIssueReason.TRANSACTION_MISSING]: 'Transaction missing', + [SupportIssueReason.REJECT_CALL]: 'Reject call', + [SupportIssueReason.REPEAT_CALL]: 'Repeat call', + [SupportIssueReason.NAME_CHANGED]: 'Name changed', + [SupportIssueReason.ADDRESS_CHANGED]: 'Address changed', + [SupportIssueReason.CIVIL_STATUS_CHANGED]: 'Civil status changed', }; export const FileTypeLabels = { @@ -155,6 +161,8 @@ export const FileTypeLabels = { [FileType.RESIDENCE_PERMIT]: 'Residence permit', [FileType.ADDITIONAL_DOCUMENTS]: 'Additional documents', [FileType.AUTHORITY]: 'Power of Attorney', + [FileType.ADDRESS_CHANGE]: 'Address change', + [FileType.NAME_CHANGE]: 'Name change', }; // --- ADDRESSES --- // diff --git a/src/hooks/kyc-helper.hook.ts b/src/hooks/kyc-helper.hook.ts index 951cbe26..8bac1f50 100644 --- a/src/hooks/kyc-helper.hook.ts +++ b/src/hooks/kyc-helper.hook.ts @@ -79,6 +79,9 @@ export function useKycHelper(): KycHelperInterface { [KycStepName.DFX_APPROVAL]: 'DFX approval', [KycStepName.PAYMENT_AGREEMENT]: 'Assignment agreement', [KycStepName.RECALL_AGREEMENT]: 'Recall agreement', + [KycStepName.PHONE_CHANGE]: 'Phone number change', + [KycStepName.ADDRESS_CHANGE]: 'Address change', + [KycStepName.NAME_CHANGE]: 'Name change', }; const typeMap: Record = { diff --git a/src/screens/account.screen.tsx b/src/screens/account.screen.tsx index a7383ac1..21deb361 100644 --- a/src/screens/account.screen.tsx +++ b/src/screens/account.screen.tsx @@ -2,6 +2,7 @@ import { ApiError, Blockchain, DetailTransaction, + KycStepName, PdfDocument, Referral, UserAddress, @@ -28,6 +29,7 @@ import { StyledDropdown, StyledInput, StyledLoadingSpinner, + StyledIconButton, StyledVerticalStack, } from '@dfx.swiss/react-components'; import copy from 'copy-to-clipboard'; @@ -40,6 +42,7 @@ import { addressLabel } from 'src/config/labels'; import { Urls } from 'src/config/urls'; import { useLayoutContext } from 'src/contexts/layout.context'; import { useWindowContext } from 'src/contexts/window.context'; +import { useKycHelper } from 'src/hooks/kyc-helper.hook'; import { useUserGuard } from 'src/hooks/guard.hook'; import { useLayoutOptions } from 'src/hooks/layout-config.hook'; import { useNavigation } from 'src/hooks/navigation.hook'; @@ -86,6 +89,7 @@ export default function AccountScreen(): JSX.Element { const { canClose, isEmbedded } = useAppHandlingContext(); const { isInitialized, setWallet } = useWalletContext(); const { changeAddress } = useUserContext(); + const { startStep } = useKycHelper(); const { rootRef } = useLayoutContext(); const { call } = useApi(); const [transactions, setTransactions] = useState[]>(); @@ -95,6 +99,7 @@ export default function AccountScreen(): JSX.Element { const [isPdfLoading, setIsPdfLoading] = useState(false); const [pdfError, setPdfError] = useState(); const [showRecommendationModal, setShowRecommendationModal] = useState(false); + const [isDataLoading, setIsDataLoading] = useState(true); const [pdfBlockchains, setPdfBlockchains] = useState([]); @@ -297,18 +302,18 @@ export default function AccountScreen(): JSX.Element { const annualVolumeSum = annualVolumeItems?.reduce((acc, item) => acc + item.value, 0); const title = showPdfModal - ? translate('screens/home', 'PDF Download Address Report') - : showRecommendationModal - ? translate('screens/recommendation', 'Create Invitation') - : isEmbedded - ? translate('screens/home', 'DFX services') - : translate('screens/home', 'Account'); + ? translate('screens/home', 'PDF Download Address Report') + : showRecommendationModal + ? translate('screens/recommendation', 'Create Invitation') + : isEmbedded + ? translate('screens/home', 'DFX services') + : translate('screens/home', 'Account'); const hasBackButton = (canClose && !isEmbedded) || showPdfModal || showRecommendationModal; const onBack = showPdfModal - ? closePdfModal - : showRecommendationModal - ? () => setShowRecommendationModal(false) - : undefined; + ? closePdfModal + : showRecommendationModal + ? () => setShowRecommendationModal(false) + : undefined; const image = 'https://dfx.swiss/images/app/berge.jpg'; useLayoutOptions({ title, backButton: hasBackButton, onBack }); @@ -330,16 +335,35 @@ export default function AccountScreen(): JSX.Element { minWidth={false} > {profile.mail && ( - {profile.mail} + +
+ {profile.mail} + navigate('/account/mail', { setRedirect: true })} inline /> +
+
+ )} + {profile.phone && ( + +
+ {profile.phone} + startStep(KycStepName.PHONE_CHANGE)} inline /> +
+
)} {(profile.firstName || profile.lastName) && ( - {[profile.firstName, profile.lastName].filter(Boolean).join(' ')} +
+ {[profile.firstName, profile.lastName].filter(Boolean).join(' ')} + startStep(KycStepName.NAME_CHANGE)} inline /> +
)} {profile.address && ( - {formatAddress(profile.address)} +
+ {formatAddress(profile.address)} + startStep(KycStepName.ADDRESS_CHANGE)} inline /> +
)} {profile.organizationName && ( diff --git a/src/screens/edit-mail.screen.tsx b/src/screens/edit-mail.screen.tsx index cb46fba7..210c7535 100644 --- a/src/screens/edit-mail.screen.tsx +++ b/src/screens/edit-mail.screen.tsx @@ -67,7 +67,7 @@ export default function EditMailScreen(): JSX.Element { setIsSubmitting(true); verifyMail(data.token) - .then(() => navigate('/settings')) + .then(() => navigate('/account')) .catch((e: ApiError) => e.statusCode === 403 ? setTokenInvalid(true) @@ -112,7 +112,7 @@ export default function EditMailScreen(): JSX.Element { prefill={user?.mail} placeholder={translate('screens/kyc', 'Email address')} validation={Validations.Mail} - onCancel={() => navigate('/settings')} + onCancel={() => navigate('/account')} onEdit={onSubmit} /> ) : ( diff --git a/src/screens/kyc.screen.tsx b/src/screens/kyc.screen.tsx index 9394fe82..3ad43132 100644 --- a/src/screens/kyc.screen.tsx +++ b/src/screens/kyc.screen.tsx @@ -7,6 +7,7 @@ import { GenderType, GoodsCategory, GoodsType, + KycAddress, KycBeneficialData, KycContactData, KycFinancialOption, @@ -521,6 +522,18 @@ function KycEdit(props: EditProps): JSX.Element { case KycStepName.RECALL_AGREEMENT: return ; + + case KycStepName.PHONE_CHANGE: + return ; + + case KycStepName.ADDRESS_CHANGE: + return ; + + case KycStepName.NAME_CHANGE: + return ; + + default: + return <>; } } @@ -2212,6 +2225,323 @@ function ManualIdent({ rootRef, code, step, onDone }: EditProps): JSX.Element { ); } +// --- Change Steps --- + +interface PhoneChangeFormData { + phone: string; +} + +function PhoneChangeData({ code, isLoading, step, onDone }: EditProps): JSX.Element { + const { translate, translateError } = useSettingsContext(); + const { setPhoneChangeData } = useKyc(); + + const [isUpdating, setIsUpdating] = useState(false); + const [error, setError] = useState(); + + const { + control, + handleSubmit, + formState: { isValid, errors }, + } = useForm({ mode: 'onTouched' }); + + function onSubmit(data: PhoneChangeFormData) { + if (!step.session) return; + + setIsUpdating(true); + setError(undefined); + setPhoneChangeData(code, step.session.url, { phone: data.phone }) + .then(onDone) + .catch((error: ApiError) => setError(error.message ?? 'Unknown error')) + .finally(() => setIsUpdating(false)); + } + + const rules = Utils.createRules({ + phone: [Validations.Required, Validations.Phone], + }); + + return ( +
+ + + + {error && ( +
+ +
+ )} + + +
+
+ ); +} + +interface AddressChangeFormData { + file: File; + address: KycAddress; +} + +function AddressChangeData({ rootRef, code, isLoading, step, onDone }: EditProps): JSX.Element { + const { allowedCountries, translate, translateError } = useSettingsContext(); + const { setAddressChangeData } = useKyc(); + const { countryCode } = useGeoLocation(); + + const [isUpdating, setIsUpdating] = useState(false); + const [error, setError] = useState(); + + const ipCountry = allowedCountries.find((c) => c.symbol === countryCode); + + const { + control, + handleSubmit, + formState: { isValid, errors }, + } = useForm({ mode: 'onTouched', defaultValues: { address: { country: ipCountry } } }); + + async function onSubmit(data: AddressChangeFormData) { + if (!step.session) return; + + const file = data.file && (await toBase64(data.file)); + if (!file) { + setError('No file selected'); + return; + } + + setIsUpdating(true); + setError(undefined); + setAddressChangeData(code, step.session.url, { + file, + fileName: data.file.name, + address: data.address, + }) + .then(onDone) + .catch((error: ApiError) => setError(error.message ?? 'Unknown error')) + .finally(() => setIsUpdating(false)); + } + + const rules = Utils.createRules({ + ['address.street']: Validations.Required, + ['address.zip']: Validations.Required, + ['address.city']: Validations.Required, + ['address.country']: Validations.Required, + file: [ + Validations.Required, + Validations.Custom((file) => (!file || DefaultFileTypes.includes(file.type) ? true : 'file_type')), + ], + }); + + return ( +
+ + +

+ {translate('screens/kyc', 'New address')} +

+ + + + + + + + + + rootRef={rootRef} + name="address.country" + autocomplete="country" + label={translate('screens/kyc', 'Country')} + placeholder={translate('general/actions', 'Select') + '...'} + items={allowedCountries} + labelFunc={(item) => item.name} + filterFunc={(i, s) => !s || [i.name, i.symbol].some((w) => w.toLowerCase().includes(s.toLowerCase()))} + matchFunc={(i, s) => i.name.toLowerCase() === s?.toLowerCase()} + smallLabel + /> +
+ + +

+ {translate('screens/kyc', 'Proof document')} +

+ +
+ + {error && ( +
+ +
+ )} + + +
+
+ ); +} + +interface NameChangeFormData { + file: File; + firstName: string; + lastName: string; +} + +function NameChangeData({ code, isLoading, step, onDone }: EditProps): JSX.Element { + const { translate, translateError } = useSettingsContext(); + const { setNameChangeData } = useKyc(); + + const [isUpdating, setIsUpdating] = useState(false); + const [error, setError] = useState(); + + const { + control, + handleSubmit, + formState: { isValid, errors }, + } = useForm({ mode: 'onTouched' }); + + async function onSubmit(data: NameChangeFormData) { + if (!step.session) return; + + const file = data.file && (await toBase64(data.file)); + if (!file) { + setError('No file selected'); + return; + } + + setIsUpdating(true); + setError(undefined); + setNameChangeData(code, step.session.url, { + file, + fileName: data.file.name, + firstName: data.firstName, + lastName: data.lastName, + }) + .then(onDone) + .catch((error: ApiError) => setError(error.message ?? 'Unknown error')) + .finally(() => setIsUpdating(false)); + } + + const rules = Utils.createRules({ + firstName: Validations.Required, + lastName: Validations.Required, + file: [ + Validations.Required, + Validations.Custom((file) => (!file || DefaultFileTypes.includes(file.type) ? true : 'file_type')), + ], + }); + + return ( +
+ + +

+ {translate('screens/kyc', 'New name')} +

+ + + + +
+ + +

+ {translate('screens/kyc', 'Proof document')} +

+ +
+ + {error && ( +
+ +
+ )} + + +
+
+ ); +} + function PaymentAgreement({ code, step, onDone }: EditProps): JSX.Element { const { translate, translateError } = useSettingsContext(); const { setPaymentData } = useKyc(); diff --git a/src/screens/settings.screen.tsx b/src/screens/settings.screen.tsx index 14976083..7648c4fa 100644 --- a/src/screens/settings.screen.tsx +++ b/src/screens/settings.screen.tsx @@ -7,20 +7,12 @@ import { UserAddress, useUserContext, Utils, - Validations, } from '@dfx.swiss/react'; import { - AlignContent, - DfxIcon, Form, - IconColor, - IconSize, - IconVariant, SpinnerSize, StyledButton, StyledButtonWidth, - StyledDataTable, - StyledDataTableRow, StyledDropdown, StyledLoadingSpinner, StyledVerticalStack, @@ -54,8 +46,6 @@ enum OverlayType { DELETE_ADDRESS, DELETE_ACCOUNT, RENAME_ADDRESS, - EDIT_EMAIL, - EDIT_PHONE, EDIT_BANK_ACCOUNT, ADD_BANK_ACCOUNT, DELETE_BANK_ACCOUNT, @@ -66,8 +56,6 @@ const OverlayHeader: { [key in OverlayType]: string } = { [OverlayType.DELETE_ADDRESS]: 'Delete address', [OverlayType.DELETE_ACCOUNT]: 'Delete account', [OverlayType.RENAME_ADDRESS]: 'Rename address', - [OverlayType.EDIT_EMAIL]: 'Edit email', - [OverlayType.EDIT_PHONE]: 'Edit phone number', [OverlayType.EDIT_BANK_ACCOUNT]: 'Edit bank account', [OverlayType.ADD_BANK_ACCOUNT]: 'Add bank account', [OverlayType.DELETE_BANK_ACCOUNT]: 'Delete bank account', @@ -115,10 +103,6 @@ export default function SettingsScreen(): JSX.Element { } }, [selectedCurrency]); - useEffect(() => { - if (overlayType === OverlayType.EDIT_EMAIL) navigate('/settings/mail', { setRedirect: true }); - }, [overlayType]); - function onCloseOverlay(): void { setOverlayType(OverlayType.NONE); setOverlayData(undefined); @@ -167,46 +151,6 @@ export default function SettingsScreen(): JSX.Element { - {!!(user?.mail || user?.phone) && ( - -

- {translate('screens/kyc', 'Personal Information')} -

- - {user?.mail && ( - -
-
- {translate('screens/kyc', 'Email address')} -
-
{user?.mail}
-
-
- -
-
- )} - {user?.phone && ( - -
-
- {translate('screens/kyc', 'Phone number')} -
-
{user?.phone}
-
-
- -
-
- )} -
-
- )} - {isLoadingBankAccounts ? (
@@ -339,7 +283,7 @@ function SettingsOverlay({ type, data, onClose }: SettingsOverlayProps): JSX.Ele const { width } = useWindowContext(); const { translate } = useSettingsContext(); const { setWallet } = useWalletContext(); - const { deleteAddress, deleteAccount, renameAddress, updatePhone } = useUserContext(); + const { deleteAddress, deleteAccount, renameAddress } = useUserContext(); const { updateAccount } = useBankAccountContext(); switch (type) { @@ -401,21 +345,6 @@ function SettingsOverlay({ type, data, onClose }: SettingsOverlayProps): JSX.Ele }} /> ); - case OverlayType.EDIT_PHONE: - return ( - { - await updatePhone(result); - onClose(); - }} - /> - ); case OverlayType.EDIT_BANK_ACCOUNT: return ; case OverlayType.ADD_BANK_ACCOUNT: diff --git a/src/screens/support-issue.screen.tsx b/src/screens/support-issue.screen.tsx index 9d601ae8..ea009685 100644 --- a/src/screens/support-issue.screen.tsx +++ b/src/screens/support-issue.screen.tsx @@ -59,8 +59,18 @@ const IssueReasons: { [t in SupportIssueType]: SupportIssueReason[] } = { [SupportIssueType.KYC_ISSUE]: [SupportIssueReason.OTHER], [SupportIssueType.LIMIT_REQUEST]: [SupportIssueReason.OTHER], [SupportIssueType.PARTNERSHIP_REQUEST]: [SupportIssueReason.OTHER], - [SupportIssueType.NOTIFICATION_OF_CHANGES]: [SupportIssueReason.OTHER], + [SupportIssueType.NOTIFICATION_OF_CHANGES]: [ + SupportIssueReason.NAME_CHANGED, + SupportIssueReason.ADDRESS_CHANGED, + SupportIssueReason.CIVIL_STATUS_CHANGED, + SupportIssueReason.OTHER, + ], [SupportIssueType.BUG_REPORT]: [SupportIssueReason.OTHER], + [SupportIssueType.VERIFICATION_CALL]: [ + SupportIssueReason.REJECT_CALL, + SupportIssueReason.REPEAT_CALL, + SupportIssueReason.OTHER, + ], }; interface FormData { @@ -398,8 +408,8 @@ export default function SupportIssueScreen(): JSX.Element { item === AddAccount ? translate('general/actions', item) : item === NoIban - ? translate('screens/iban', item) - : Utils.formatIban(item) ?? '', + ? translate('screens/iban', item) + : (Utils.formatIban(item) ?? ''), { displayLength: 30 }, ) } diff --git a/src/screens/transaction.screen.tsx b/src/screens/transaction.screen.tsx index 83273632..6720cd94 100644 --- a/src/screens/transaction.screen.tsx +++ b/src/screens/transaction.screen.tsx @@ -86,7 +86,7 @@ export default function TransactionScreen(): JSX.Element { const [isCsvLoading, setIsCsvLoading] = useState(); const [error, setError] = useState(); - const isTransaction = id && id.startsWith('T'); + const isTransaction = id && (id.startsWith('T') || id.startsWith('Q')); const isRefund = isTransaction && pathname.includes('/refund'); async function exportCsv(type: ExportType) { diff --git a/src/translations/languages/de.json b/src/translations/languages/de.json index 01d56ed7..f8431856 100644 --- a/src/translations/languages/de.json +++ b/src/translations/languages/de.json @@ -183,6 +183,12 @@ "https://example.com": "https://beispiel.de", "Mobile number": "Handynummer", "Phone number": "Telefonnummer", + "New address": "Neue Adresse", + "New name": "Neuer Name", + "Proof document": "Nachweis-Dokument", + "Phone number change": "Telefonnummer ändern", + "Address change": "Adressänderung", + "Name change": "Namensänderung", "Organization Information": "Organisation", "Organization name": "Name der Organisation", "Example inc.": "Beispiel GmbH & Co. KG", diff --git a/src/translations/languages/fr.json b/src/translations/languages/fr.json index 59de1a49..f72e59f2 100644 --- a/src/translations/languages/fr.json +++ b/src/translations/languages/fr.json @@ -183,6 +183,12 @@ "https://example.com": "https://exemple.fr", "Mobile number": "Numéro de portable", "Phone number": "Numéro de téléphone", + "New address": "Nouvelle adresse", + "New name": "Nouveau nom", + "Proof document": "Document justificatif", + "Phone number change": "Changement de numéro de téléphone", + "Address change": "Changement d'adresse", + "Name change": "Changement de nom", "Organization Information": "Organisation", "Organization name": "Nom de l'organisation", "Example inc.": "Exempel SARL & Co. KG", diff --git a/src/translations/languages/it.json b/src/translations/languages/it.json index 32ccdcc4..39ad82c5 100644 --- a/src/translations/languages/it.json +++ b/src/translations/languages/it.json @@ -183,6 +183,12 @@ "https://example.com": "https://esempio.it", "Mobile number": "Numero di cellulare", "Phone number": "Numero di telefono", + "New address": "Nuovo indirizzo", + "New name": "Nuovo nome", + "Proof document": "Documento giustificativo", + "Phone number change": "Cambio numero di telefono", + "Address change": "Cambio di indirizzo", + "Name change": "Cambio di nome", "Organization Information": "Informazioni sull'organizzazione", "Organization name": "Nome dell'organizzazione", "Example inc.": "Esempio inc.",