From 831af23146e05dcfd5d74dd30f01caa66fea37cf Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Tue, 5 Nov 2024 13:24:25 +0530 Subject: [PATCH 01/88] chore: updates husky to allow "address-mgmt/" branch pattern --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c9faee4e6..87eb5ea899 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "prepare": "node ./husky-prepare.js" }, "validate-branch-name": { - "pattern": "^(main|develop){1}$|^(feature|hotfix)/[a-z0-9-_]+$", + "pattern": "^(main|develop){1}$|^(feature|hotfix|address-mgmt)/[a-z0-9-_]+$", "errorMsg": "Invalid branch name. \n 1.Branch names can contain lowercase characters, numbers, hyphen and underscore. \n 2.Except for 'main' and 'develop', branch names must begin with 'feature/' or 'hotfix/' " }, "engines": { From a93545e37a6b4908ecfd95816e28fb7a2b87390e Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:23:44 +0530 Subject: [PATCH 02/88] refactor: set up story for single address --- .../AddressManagement.module.scss | 0 src/temp/AddressManagment/index.tsx | 24 ++++++++++ .../stories/AddressManagement.stories.tsx | 44 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 src/temp/AddressManagment/AddressManagement.module.scss create mode 100644 src/temp/AddressManagment/index.tsx create mode 100644 src/temp/stories/AddressManagement.stories.tsx diff --git a/src/temp/AddressManagment/AddressManagement.module.scss b/src/temp/AddressManagment/AddressManagement.module.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/temp/AddressManagment/index.tsx b/src/temp/AddressManagment/index.tsx new file mode 100644 index 0000000000..320197bb68 --- /dev/null +++ b/src/temp/AddressManagment/index.tsx @@ -0,0 +1,24 @@ +import type { Address } from '@planet-sdk/common'; + +export interface UpdatedAddress extends Address { + id: string; + type: 'primary' | 'mailing' | 'other'; + name: string | null; + state: string | null; + isPrimary: boolean | null; + address2: string | null; +} + +interface Props { + addresses: UpdatedAddress[]; +} + +const AddressManagement = ({ addresses }: Props) => { + return ( +
+
+
+ ); +}; + +export default AddressManagement; diff --git a/src/temp/stories/AddressManagement.stories.tsx b/src/temp/stories/AddressManagement.stories.tsx new file mode 100644 index 0000000000..38ecb0f925 --- /dev/null +++ b/src/temp/stories/AddressManagement.stories.tsx @@ -0,0 +1,44 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import AddressManagement, { UpdatedAddress } from '../AddressManagment'; + +const meta: Meta = { + title: 'AddressManagement/AddressManagement', + component: AddressManagement, +}; + +export default meta; +type Story = StoryObj; + +const address1: UpdatedAddress = { + address: 'string', + city: 'string', + zipCode: 'string', + country: 'DE', + id: 'adr_U6sdZGo4a2rmzb1bMEw2F9PA', + type: 'primary', + name: 'primary', + address2: null, + state: null, + isPrimary: true, +}; + +const address2: UpdatedAddress = { + id: 'adr_4z4rf3oVe848vKEeC36LxWJq', + type: 'mailing', + address: 'mailing', + address2: 'mailing address', + city: 'Dullington', + zipCode: '98212', + country: 'CH', + state: 'California', + isPrimary: null, + name: 'Home', +}; + +const addresses = [address1, address2]; + +export const Default: Story = { + args: { + addresses: addresses, + }, +}; From 47abd98a165c3a859fef6ede2c2641e28d4147ff Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 6 Nov 2024 12:13:21 +0530 Subject: [PATCH 03/88] feat: story for address list --- .github/workflows/chromatic.yml | 1 + public/static/locales/en/me.json | 7 +++- .../AddressManagement.module.scss | 32 ++++++++++++++++ src/temp/AddressManagment/index.tsx | 19 ++++++++-- .../microComponents/SingleAddress.tsx | 36 ++++++++++++++++++ .../stories/AddressManagement.stories.tsx | 37 +++++++++++++------ src/utils/addressManagement.ts | 15 ++++++++ 7 files changed, 131 insertions(+), 16 deletions(-) create mode 100644 src/temp/AddressManagment/microComponents/SingleAddress.tsx create mode 100644 src/utils/addressManagement.ts diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index 9f0582a914..e3fa311322 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -11,6 +11,7 @@ on: - develop - feature/redesign-explore-btn - feature/design-projectlist-filter + - address-mgmt/single-address-story # List of jobs jobs: chromatic-deployment: diff --git a/public/static/locales/en/me.json b/public/static/locales/en/me.json index b4e45539d3..7a205452cb 100644 --- a/public/static/locales/en/me.json +++ b/public/static/locales/en/me.json @@ -286,6 +286,11 @@ "vplatform-payout": "Platform Payout", "processing": "Processing", "bankDetails": "Bank Details", - "refundAmount": "Refunded Amount" + "refundAmount": "Refunded Amount", + "addressManagement": { + "address": "Address", + "primaryAddress": "Primary Address", + "BillingAddress": "Billing Address" + } } } diff --git a/src/temp/AddressManagment/AddressManagement.module.scss b/src/temp/AddressManagment/AddressManagement.module.scss index e69de29bb2..e2bb2e383d 100644 --- a/src/temp/AddressManagment/AddressManagement.module.scss +++ b/src/temp/AddressManagment/AddressManagement.module.scss @@ -0,0 +1,32 @@ +@import '../../theme/theme'; + +.addressContainer { + display: flex; + flex-direction: column; + gap: 16px; + width: 100%; + background: rgba(242, 242, 242, 0.5); + border-radius: 8px; + font-size: $fontSmall; + font-weight: 400; + padding: 24px 0px 24px 24px; + .addressTag { + padding: 5px 10px; + width: max-content; + border-radius: 10px; + color: #fff; + font-size: $fontXSmall; + font-weight: 600; + } + .address { + max-width: 346px; + } +} + +.primary { + background: rgba(0, 122, 73, 1); +} + +.mailing { + background: rgba(45, 156, 219, 1); +} diff --git a/src/temp/AddressManagment/index.tsx b/src/temp/AddressManagment/index.tsx index 320197bb68..a3c234a3d0 100644 --- a/src/temp/AddressManagment/index.tsx +++ b/src/temp/AddressManagment/index.tsx @@ -1,5 +1,11 @@ import type { Address } from '@planet-sdk/common'; +import DashboardView from '../../features/common/Layout/DashboardView'; +import SingleColumnView from '../../features/common/Layout/SingleColumnView'; +import CenteredContainer from '../../features/common/Layout/CenteredContainer'; +import { useTranslations } from 'next-intl'; +import SingleAddress from './microComponents/SingleAddress'; + export interface UpdatedAddress extends Address { id: string; type: 'primary' | 'mailing' | 'other'; @@ -14,10 +20,17 @@ interface Props { } const AddressManagement = ({ addresses }: Props) => { + const t = useTranslations('Me'); return ( -
-
-
+ + + + {addresses.map((address) => ( + + ))} + + + ); }; diff --git a/src/temp/AddressManagment/microComponents/SingleAddress.tsx b/src/temp/AddressManagment/microComponents/SingleAddress.tsx new file mode 100644 index 0000000000..890144eeac --- /dev/null +++ b/src/temp/AddressManagment/microComponents/SingleAddress.tsx @@ -0,0 +1,36 @@ +import type { UpdatedAddress } from '..'; + +import { useTranslations } from 'next-intl'; +import { formatAddress } from '../../../utils/addressManagement'; +import style from '../AddressManagement.module.scss'; +import { CountryCode } from '@planet-sdk/common'; + +const SingleAddress = ({ userAddress }: { userAddress: UpdatedAddress }) => { + const tCountry = useTranslations('Country'); + const t = useTranslations('Me'); + const { zipCode, city, state, country, address, type } = userAddress; + const countryFullForm = tCountry( + country.toLowerCase() as Lowercase + ); + const formattedAddress = formatAddress( + address, + zipCode, + city, + state, + countryFullForm + ); + return ( +
+ {type !== 'other' && ( + + {type === 'primary' + ? t('addressManagement.primaryAddress') + : t('addressManagement.BillingAddress')} + + )} +
{formattedAddress}
+
+ ); +}; + +export default SingleAddress; diff --git a/src/temp/stories/AddressManagement.stories.tsx b/src/temp/stories/AddressManagement.stories.tsx index 38ecb0f925..6df142ead9 100644 --- a/src/temp/stories/AddressManagement.stories.tsx +++ b/src/temp/stories/AddressManagement.stories.tsx @@ -10,32 +10,45 @@ export default meta; type Story = StoryObj; const address1: UpdatedAddress = { - address: 'string', - city: 'string', - zipCode: 'string', + address: 'Königsallee 45, Building A, Floor 3, Apartment 3C', + city: 'Düsseldorf', + zipCode: '40212', + state: 'North Rhine-Westphalia', country: 'DE', id: 'adr_U6sdZGo4a2rmzb1bMEw2F9PA', type: 'primary', name: 'primary', address2: null, - state: null, isPrimary: true, }; const address2: UpdatedAddress = { + address: 'Baker Street 221B, Building B, Floor 2, Apartment 5A', + zipCode: 'NW1 6XE', + city: 'London', + state: 'Greater London', + country: 'GB', id: 'adr_4z4rf3oVe848vKEeC36LxWJq', type: 'mailing', - address: 'mailing', - address2: 'mailing address', - city: 'Dullington', - zipCode: '98212', - country: 'CH', - state: 'California', - isPrimary: null, name: 'Home', + address2: null, + isPrimary: null, +}; + +const address3: UpdatedAddress = { + address: 'Broadway 123, Suite 45', + city: 'New York', + zipCode: '10006', + state: 'New York', + country: 'US', + id: 'adr_X2sdTGo9b4qvzq1bREw3D9YZ', + type: 'other', + name: 'office', + address2: null, + isPrimary: null, }; -const addresses = [address1, address2]; +const addresses = [address1, address2, address3]; export const Default: Story = { args: { diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts new file mode 100644 index 0000000000..9179b48543 --- /dev/null +++ b/src/utils/addressManagement.ts @@ -0,0 +1,15 @@ +export const formatAddress = ( + address: string | undefined, + zipCode: string | undefined, + city: string | undefined, + state: string | null, + country: string +) => { + const cleanAddress = [address, `${zipCode} ${city}`, state, country] + .filter(Boolean) + .join(', ') + .replace(/\s+/g, ' ') + .trim(); + + return cleanAddress; +}; From 2fbe97fcc11fa3b0c96fa662dda7b8f929196068 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:13:08 +0530 Subject: [PATCH 04/88] feat: ui of address action popup --- public/assets/images/icons/KababMenuIcon.tsx | 11 +++ public/static/locales/en/me.json | 6 +- .../AddressManagement.module.scss | 51 ++++++++-- src/temp/AddressManagment/index.tsx | 10 +- .../microComponents/AddressActions.tsx | 95 +++++++++++++++++++ .../microComponents/AddressContent.tsx | 26 +++++ .../microComponents/AddressList.tsx | 14 +++ .../microComponents/SingleAddress.tsx | 19 ++-- src/temp/AddressManagment/utils.tsx | 19 ++++ 9 files changed, 227 insertions(+), 24 deletions(-) create mode 100644 public/assets/images/icons/KababMenuIcon.tsx create mode 100644 src/temp/AddressManagment/microComponents/AddressActions.tsx create mode 100644 src/temp/AddressManagment/microComponents/AddressContent.tsx create mode 100644 src/temp/AddressManagment/microComponents/AddressList.tsx create mode 100644 src/temp/AddressManagment/utils.tsx diff --git a/public/assets/images/icons/KababMenuIcon.tsx b/public/assets/images/icons/KababMenuIcon.tsx new file mode 100644 index 0000000000..cbb0f1501d --- /dev/null +++ b/public/assets/images/icons/KababMenuIcon.tsx @@ -0,0 +1,11 @@ +const KababMenuIcon = () => { + return ( + + + + + + ); +}; + +export default KababMenuIcon; diff --git a/public/static/locales/en/me.json b/public/static/locales/en/me.json index 7a205452cb..01ef680bb6 100644 --- a/public/static/locales/en/me.json +++ b/public/static/locales/en/me.json @@ -290,7 +290,11 @@ "addressManagement": { "address": "Address", "primaryAddress": "Primary Address", - "BillingAddress": "Billing Address" + "BillingAddress": "Billing Address", + "edit": "Edit", + "delete": "Delete", + "setAsPrimaryAddress": "Set as Primary Address", + "setAsBillingAddress": "Set as Billing Address" } } } diff --git a/src/temp/AddressManagment/AddressManagement.module.scss b/src/temp/AddressManagment/AddressManagement.module.scss index e2bb2e383d..dd3aade379 100644 --- a/src/temp/AddressManagment/AddressManagement.module.scss +++ b/src/temp/AddressManagment/AddressManagement.module.scss @@ -2,25 +2,39 @@ .addressContainer { display: flex; - flex-direction: column; - gap: 16px; + justify-content: space-between; width: 100%; background: rgba(242, 242, 242, 0.5); border-radius: 8px; font-size: $fontSmall; font-weight: 400; + .address { + max-width: 346px; + } + svg { + height: 20px; + width: 12px; + padding-right: 24px; + padding-top: 24px; + cursor: pointer; + } +} + +.addressSubContainer { + display: flex; + flex-direction: column; + gap: 16px; padding: 24px 0px 24px 24px; .addressTag { padding: 5px 10px; - width: max-content; - border-radius: 10px; + max-width: 98px; + border-radius: 6px; + text-align: center; color: #fff; font-size: $fontXSmall; + line-height: 16px; font-weight: 600; } - .address { - max-width: 346px; - } } .primary { @@ -30,3 +44,26 @@ .mailing { background: rgba(45, 156, 219, 1); } + +.kababMenuButton { + cursor: pointer; +} + +.addressActions { + min-width: 184px; + cursor: pointer; + padding: 12px; + list-style: none; + .action { + font-size: 12px; + font-weight: 400; + } +} + +.addressActions li { + padding: 8px 0px; +} + +.addressActions li:not(:last-child) { + border-bottom: 1px solid rgba(189, 189, 189, 1); +} diff --git a/src/temp/AddressManagment/index.tsx b/src/temp/AddressManagment/index.tsx index a3c234a3d0..9eee1cde45 100644 --- a/src/temp/AddressManagment/index.tsx +++ b/src/temp/AddressManagment/index.tsx @@ -4,11 +4,13 @@ import DashboardView from '../../features/common/Layout/DashboardView'; import SingleColumnView from '../../features/common/Layout/SingleColumnView'; import CenteredContainer from '../../features/common/Layout/CenteredContainer'; import { useTranslations } from 'next-intl'; -import SingleAddress from './microComponents/SingleAddress'; +import AddressList from './microComponents/AddressList'; + +export type AddressType = 'primary' | 'mailing' | 'other'; export interface UpdatedAddress extends Address { id: string; - type: 'primary' | 'mailing' | 'other'; + type: AddressType; name: string | null; state: string | null; isPrimary: boolean | null; @@ -25,9 +27,7 @@ const AddressManagement = ({ addresses }: Props) => { - {addresses.map((address) => ( - - ))} + diff --git a/src/temp/AddressManagment/microComponents/AddressActions.tsx b/src/temp/AddressManagment/microComponents/AddressActions.tsx new file mode 100644 index 0000000000..c94e263433 --- /dev/null +++ b/src/temp/AddressManagment/microComponents/AddressActions.tsx @@ -0,0 +1,95 @@ +import { useState } from 'react'; +import { useTranslations } from 'next-intl'; +import { Button, Popover } from '@mui/material'; +import KababMenuIcon from '../../../../public/assets/images/icons/KababMenuIcon'; +import styles from '../AddressManagement.module.scss'; +import { filterAddressActions } from '../utils'; + +export type AddressType = 'primary' | 'mailing' | 'other'; +export const ADDRESS_ACTIONS = { + EDIT: 'edit', + DELETE: 'delete', + SET_PRIMARY: 'setPrimary', + SET_BILLING: 'setBilling', +} as const; + +export type AddressAction = + (typeof ADDRESS_ACTIONS)[keyof typeof ADDRESS_ACTIONS]; + +export interface AddressActionItem { + label: string; + action: AddressAction; +} + +const AddressActions = ({ type }: { type: AddressType }) => { + const t = useTranslations('Me'); + const [popoverAnchor, setPopoverAnchor] = useState( + null + ); + + const addressActions: AddressActionItem[] = filterAddressActions( + [ + { label: t('addressManagement.edit'), action: ADDRESS_ACTIONS.EDIT }, + { label: t('addressManagement.delete'), action: ADDRESS_ACTIONS.DELETE }, + { + label: t('addressManagement.setAsPrimaryAddress'), + action: ADDRESS_ACTIONS.SET_PRIMARY, + }, + { + label: t('addressManagement.setAsBillingAddress'), + action: ADDRESS_ACTIONS.SET_BILLING, + }, + ], + type + ); + + const openPopover = (event: React.MouseEvent) => { + setPopoverAnchor(event.currentTarget); + }; + + const closePopover = () => { + setPopoverAnchor(null); + }; + + const open = Boolean(popoverAnchor); + const id = open ? 'simple-popover' : undefined; + + return ( +
+
+ ); +}; + +export default AddressActions; diff --git a/src/temp/AddressManagment/microComponents/AddressContent.tsx b/src/temp/AddressManagment/microComponents/AddressContent.tsx new file mode 100644 index 0000000000..239eb3d351 --- /dev/null +++ b/src/temp/AddressManagment/microComponents/AddressContent.tsx @@ -0,0 +1,26 @@ +import styles from '../AddressManagement.module.scss'; +import { useTranslations } from 'next-intl'; + +interface Props { + type: 'primary' | 'mailing' | 'other'; + userAddress: string; +} +const AddressContent = ({ type, userAddress }: Props) => { + const t = useTranslations('Me'); + return ( +
+ {type !== 'other' && ( + + {t( + `addressManagement.${ + type === 'primary' ? 'primaryAddress' : 'BillingAddress' + }` + )} + + )} +
{userAddress}
+
+ ); +}; + +export default AddressContent; diff --git a/src/temp/AddressManagment/microComponents/AddressList.tsx b/src/temp/AddressManagment/microComponents/AddressList.tsx new file mode 100644 index 0000000000..83c97b70b3 --- /dev/null +++ b/src/temp/AddressManagment/microComponents/AddressList.tsx @@ -0,0 +1,14 @@ +import type { UpdatedAddress } from '..'; +import SingleAddress from './SingleAddress'; + +const AddressList = ({ addresses }: { addresses: UpdatedAddress[] }) => { + return ( + <> + {addresses.map((address) => ( + + ))} + + ); +}; + +export default AddressList; diff --git a/src/temp/AddressManagment/microComponents/SingleAddress.tsx b/src/temp/AddressManagment/microComponents/SingleAddress.tsx index 890144eeac..0cdc06034e 100644 --- a/src/temp/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/temp/AddressManagment/microComponents/SingleAddress.tsx @@ -1,13 +1,15 @@ import type { UpdatedAddress } from '..'; +import React from 'react'; import { useTranslations } from 'next-intl'; import { formatAddress } from '../../../utils/addressManagement'; -import style from '../AddressManagement.module.scss'; +import styles from '../AddressManagement.module.scss'; import { CountryCode } from '@planet-sdk/common'; +import AddressContent from './AddressContent'; +import AddressActions from './AddressActions'; const SingleAddress = ({ userAddress }: { userAddress: UpdatedAddress }) => { const tCountry = useTranslations('Country'); - const t = useTranslations('Me'); const { zipCode, city, state, country, address, type } = userAddress; const countryFullForm = tCountry( country.toLowerCase() as Lowercase @@ -19,16 +21,11 @@ const SingleAddress = ({ userAddress }: { userAddress: UpdatedAddress }) => { state, countryFullForm ); + return ( -
- {type !== 'other' && ( - - {type === 'primary' - ? t('addressManagement.primaryAddress') - : t('addressManagement.BillingAddress')} - - )} -
{formattedAddress}
+
+ +
); }; diff --git a/src/temp/AddressManagment/utils.tsx b/src/temp/AddressManagment/utils.tsx new file mode 100644 index 0000000000..34cddb1191 --- /dev/null +++ b/src/temp/AddressManagment/utils.tsx @@ -0,0 +1,19 @@ +import type { + AddressActionItem, + AddressType, +} from './microComponents/AddressActions'; + +import { ADDRESS_ACTIONS } from './microComponents/AddressActions'; + +export const filterAddressActions = ( + actions: AddressActionItem[], + type: AddressType +) => { + return actions.filter((item) => { + if (type === 'primary' && item.action === ADDRESS_ACTIONS.SET_PRIMARY) + return false; + if (type === 'mailing' && item.action === ADDRESS_ACTIONS.SET_BILLING) + return false; + return true; + }); +}; From 71440bb0b316e76559963559a416299e878533f3 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:02:27 +0530 Subject: [PATCH 05/88] feat: once a action is selected close the action modal --- .../microComponents/AddressActions.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/temp/AddressManagment/microComponents/AddressActions.tsx b/src/temp/AddressManagment/microComponents/AddressActions.tsx index c94e263433..a8f0c8888a 100644 --- a/src/temp/AddressManagment/microComponents/AddressActions.tsx +++ b/src/temp/AddressManagment/microComponents/AddressActions.tsx @@ -51,6 +51,10 @@ const AddressActions = ({ type }: { type: AddressType }) => { setPopoverAnchor(null); }; + const handleActionClick = (action: AddressAction) => { + setPopoverAnchor(null); + }; + const open = Boolean(popoverAnchor); const id = open ? 'simple-popover' : undefined; @@ -82,7 +86,11 @@ const AddressActions = ({ type }: { type: AddressType }) => { >
    {addressActions.map((item, key) => ( -
  • +
  • handleActionClick(item.action)} + > {item.label}
  • ))} From 6eb041c823771ab577b08f3e3b55b08ac6adeaec Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 7 Nov 2024 18:00:20 +0530 Subject: [PATCH 06/88] refactor: clean up unused utils, update address action config --- .../microComponents/AddressActions.tsx | 69 ++++++++++++------- .../microComponents/AddressList.tsx | 15 +++- .../microComponents/SingleAddress.tsx | 20 +++++- src/temp/AddressManagment/utils.tsx | 19 ----- 4 files changed, 75 insertions(+), 48 deletions(-) delete mode 100644 src/temp/AddressManagment/utils.tsx diff --git a/src/temp/AddressManagment/microComponents/AddressActions.tsx b/src/temp/AddressManagment/microComponents/AddressActions.tsx index a8f0c8888a..1ed58c044e 100644 --- a/src/temp/AddressManagment/microComponents/AddressActions.tsx +++ b/src/temp/AddressManagment/microComponents/AddressActions.tsx @@ -3,7 +3,7 @@ import { useTranslations } from 'next-intl'; import { Button, Popover } from '@mui/material'; import KababMenuIcon from '../../../../public/assets/images/icons/KababMenuIcon'; import styles from '../AddressManagement.module.scss'; -import { filterAddressActions } from '../utils'; +import { SetState } from '../../../features/common/types/common'; export type AddressType = 'primary' | 'mailing' | 'other'; export const ADDRESS_ACTIONS = { @@ -19,29 +19,42 @@ export type AddressAction = export interface AddressActionItem { label: string; action: AddressAction; + shouldRender: boolean; +} +interface Props { + type: AddressType; + addressCount: number; + setAddressAction: SetState; } -const AddressActions = ({ type }: { type: AddressType }) => { +const AddressActions = ({ type, addressCount, setAddressAction }: Props) => { const t = useTranslations('Me'); const [popoverAnchor, setPopoverAnchor] = useState( null ); - const addressActions: AddressActionItem[] = filterAddressActions( - [ - { label: t('addressManagement.edit'), action: ADDRESS_ACTIONS.EDIT }, - { label: t('addressManagement.delete'), action: ADDRESS_ACTIONS.DELETE }, - { - label: t('addressManagement.setAsPrimaryAddress'), - action: ADDRESS_ACTIONS.SET_PRIMARY, - }, - { - label: t('addressManagement.setAsBillingAddress'), - action: ADDRESS_ACTIONS.SET_BILLING, - }, - ], - type - ); + const addressActionConfig: AddressActionItem[] = [ + { + label: t('addressManagement.edit'), + action: ADDRESS_ACTIONS.EDIT, + shouldRender: true, + }, + { + label: t('addressManagement.delete'), + action: ADDRESS_ACTIONS.DELETE, + shouldRender: addressCount > 1, + }, + { + label: t('addressManagement.setAsPrimaryAddress'), + action: ADDRESS_ACTIONS.SET_PRIMARY, + shouldRender: !(type === 'mailing' || type === 'primary'), + }, + { + label: t('addressManagement.setAsBillingAddress'), + action: ADDRESS_ACTIONS.SET_BILLING, + shouldRender: !(type === 'mailing' || type === 'primary'), + }, + ]; const openPopover = (event: React.MouseEvent) => { setPopoverAnchor(event.currentTarget); @@ -52,6 +65,7 @@ const AddressActions = ({ type }: { type: AddressType }) => { }; const handleActionClick = (action: AddressAction) => { + setAddressAction(action); setPopoverAnchor(null); }; @@ -85,15 +99,18 @@ const AddressActions = ({ type }: { type: AddressType }) => { }} >
      - {addressActions.map((item, key) => ( -
    • handleActionClick(item.action)} - > - {item.label} -
    • - ))} + {addressActionConfig.map((item, key) => { + if (!item.shouldRender) return; + return ( +
    • handleActionClick(item.action)} + > + {item.label} +
    • + ); + })}
diff --git a/src/temp/AddressManagment/microComponents/AddressList.tsx b/src/temp/AddressManagment/microComponents/AddressList.tsx index 83c97b70b3..80b6dffbd4 100644 --- a/src/temp/AddressManagment/microComponents/AddressList.tsx +++ b/src/temp/AddressManagment/microComponents/AddressList.tsx @@ -1,11 +1,24 @@ import type { UpdatedAddress } from '..'; +import type { AddressAction } from './AddressActions'; + +import { useState } from 'react'; import SingleAddress from './SingleAddress'; const AddressList = ({ addresses }: { addresses: UpdatedAddress[] }) => { + const [addressAction, setAddressAction] = useState( + null + ); + const addressCount = addresses.length; + return ( <> {addresses.map((address) => ( - + ))} ); diff --git a/src/temp/AddressManagment/microComponents/SingleAddress.tsx b/src/temp/AddressManagment/microComponents/SingleAddress.tsx index 0cdc06034e..f18c6a11cf 100644 --- a/src/temp/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/temp/AddressManagment/microComponents/SingleAddress.tsx @@ -1,4 +1,6 @@ import type { UpdatedAddress } from '..'; +import type { SetState } from '../../../features/common/types/common'; +import type { AddressAction } from './AddressActions'; import React from 'react'; import { useTranslations } from 'next-intl'; @@ -8,7 +10,17 @@ import { CountryCode } from '@planet-sdk/common'; import AddressContent from './AddressContent'; import AddressActions from './AddressActions'; -const SingleAddress = ({ userAddress }: { userAddress: UpdatedAddress }) => { +interface Props { + userAddress: UpdatedAddress; + addressCount: number; + setAddressAction: SetState; +} + +const SingleAddress = ({ + userAddress, + addressCount, + setAddressAction, +}: Props) => { const tCountry = useTranslations('Country'); const { zipCode, city, state, country, address, type } = userAddress; const countryFullForm = tCountry( @@ -25,7 +37,11 @@ const SingleAddress = ({ userAddress }: { userAddress: UpdatedAddress }) => { return (
- +
); }; diff --git a/src/temp/AddressManagment/utils.tsx b/src/temp/AddressManagment/utils.tsx deleted file mode 100644 index 34cddb1191..0000000000 --- a/src/temp/AddressManagment/utils.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import type { - AddressActionItem, - AddressType, -} from './microComponents/AddressActions'; - -import { ADDRESS_ACTIONS } from './microComponents/AddressActions'; - -export const filterAddressActions = ( - actions: AddressActionItem[], - type: AddressType -) => { - return actions.filter((item) => { - if (type === 'primary' && item.action === ADDRESS_ACTIONS.SET_PRIMARY) - return false; - if (type === 'mailing' && item.action === ADDRESS_ACTIONS.SET_BILLING) - return false; - return true; - }); -}; From 5cd3ec4feaecf2eb2738797fc02ab56bd5149b81 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:55:57 +0530 Subject: [PATCH 07/88] feat: add UI for adding addresses --- public/static/locales/en/editProfile.json | 2 + public/static/locales/en/me.json | 4 +- .../user/Settings/EditProfile/index.tsx | 18 +- src/temp/AddressManagment/AddressForm.tsx | 197 ++++++++++++++++++ .../AddressManagement.module.scss | 31 +++ 5 files changed, 244 insertions(+), 8 deletions(-) create mode 100644 src/temp/AddressManagment/AddressForm.tsx diff --git a/public/static/locales/en/editProfile.json b/public/static/locales/en/editProfile.json index 3848a5420e..6d03eac1df 100644 --- a/public/static/locales/en/editProfile.json +++ b/public/static/locales/en/editProfile.json @@ -39,6 +39,7 @@ "email": "Email", "address": "Address", "city": "City", + "state": "State", "zipCode": "Postal/Zip Code", "country": "Country", "bio": "Your Description", @@ -61,6 +62,7 @@ "addressInvalid": "Address is invalid. Only these special characters are allowed: space . , # - /", "cityRequired": "City is required", "cityInvalid": "City is invalid. Only letters and these special characters are allowed: space . , ( ) -", + "stateInvalid": "State is invalid. Only letters and these special characters are allowed: space . , ( ) -", "zipCodeRequired": "Zip Code is required", "zipCodeInvalid": "Zip Code is invalid", "websiteInvalid": "Please enter valid Website URL", diff --git a/public/static/locales/en/me.json b/public/static/locales/en/me.json index 01ef680bb6..3862049f02 100644 --- a/public/static/locales/en/me.json +++ b/public/static/locales/en/me.json @@ -294,7 +294,9 @@ "edit": "Edit", "delete": "Delete", "setAsPrimaryAddress": "Set as Primary Address", - "setAsBillingAddress": "Set as Billing Address" + "setAsBillingAddress": "Set as Billing Address", + "addAddress": "Add Address", + "alternativeAddress": "Address 2(optional)" } } } diff --git a/src/features/user/Settings/EditProfile/index.tsx b/src/features/user/Settings/EditProfile/index.tsx index 36b4dbf2ca..76bc4b2940 100644 --- a/src/features/user/Settings/EditProfile/index.tsx +++ b/src/features/user/Settings/EditProfile/index.tsx @@ -4,17 +4,21 @@ import CenteredContainer from '../../../common/Layout/CenteredContainer'; import DashboardView from '../../../common/Layout/DashboardView'; import EditProfileForm from './EditProfileForm'; import SingleColumnView from '../../../common/Layout/SingleColumnView'; +import AddressForm from '../../../../temp/AddressManagment/AddressForm'; export default function EditProfile(): ReactElement | null { const t = useTranslations('Me'); return ( - - - - - - - + <> + + + + + + + + + ); } diff --git a/src/temp/AddressManagment/AddressForm.tsx b/src/temp/AddressManagment/AddressForm.tsx new file mode 100644 index 0000000000..4ddbd19180 --- /dev/null +++ b/src/temp/AddressManagment/AddressForm.tsx @@ -0,0 +1,197 @@ +import type { ExtendedCountryCode } from '../../features/common/types/country'; + +import { useState } from 'react'; +import { Controller, useForm } from 'react-hook-form'; +import { useTranslations } from 'next-intl'; +import { TextField } from '@mui/material'; +import styles from './AddressManagement.module.scss'; +import WebappButton from '../../features/common/WebappButton'; +import InlineFormDisplayGroup from '../../features/common/Layout/Forms/InlineFormDisplayGroup'; +import SelectCountry from '../../features/common/InputTypes/AutoCompleteCountry'; +import { allCountries } from '../../utils/constants/countries'; + +type FormData = { + address: string; + alternativeAddress: string | undefined; + city: string; + zipCode: string; + state: string; +}; + +const AddressForm = ({ mode }) => { + const defaultAddressDetail = { + address: '', + alternativeAddress: '', + city: '', + zipCode: '', + state: '', + }; + const { + control, + handleSubmit, + formState: { errors }, + } = useForm({ + mode: 'onBlur', + defaultValues: defaultAddressDetail, + }); + const t = useTranslations('EditProfile'); + const tMe = useTranslations('Me'); + const tCommon = useTranslations('Common'); + const [country, setCountry] = useState('DE'); + const closeModal = () => {}; + return ( +
+

{tMe('addressManagement.addAddress')}

+
+ ( + { + handleChange(event); + }} + onBlur={() => handleBlur()} + value={value} + error={errors.address !== undefined} + helperText={ + errors.address !== undefined ? errors.address?.message : null + } + /> + )} + /> + ( + { + handleChange(event); + }} + onBlur={() => handleBlur()} + value={value} + error={errors.alternativeAddress !== undefined} + helperText={ + errors.alternativeAddress !== undefined + ? errors.alternativeAddress?.message + : null + } + /> + )} + /> + + ( + + )} + /> + ( + + )} + /> + + + ( + + )} + /> + + + +
+ + +
+
+ ); +}; + +export default AddressForm; diff --git a/src/temp/AddressManagment/AddressManagement.module.scss b/src/temp/AddressManagment/AddressManagement.module.scss index dd3aade379..9f1e14edb2 100644 --- a/src/temp/AddressManagment/AddressManagement.module.scss +++ b/src/temp/AddressManagment/AddressManagement.module.scss @@ -67,3 +67,34 @@ .addressActions li:not(:last-child) { border-bottom: 1px solid rgba(189, 189, 189, 1); } +// address action form + +.addressFormContainer { + display: flex; + flex-direction: column; + gap: 40px; + max-width: 565px; + background: rgba(255, 255, 255, 1); + border-radius: 16px; + padding: 20px; + h1 { + font-weight: 700; + font-size: $fontSixteen; + } +} + +.addressForm { + display: flex; + flex-direction: column; + gap: 23px; +} + +.formButtonContainer { + display: flex; + justify-content: space-between; + .addAddressButton, + .cancelButton { + min-width: 252px; + min-height: 40px; + } +} From a210e251b4a54ed4d91859580eeef925ba7094fb Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sat, 9 Nov 2024 14:10:14 +0530 Subject: [PATCH 08/88] refactor: move adddress management folder to edit profile section, update hover effect styling for kabab menu button --- pages/sites/[slug]/[locale]/profile/edit.tsx | 2 +- .../AddressManagement.module.scss | 33 ++++++++------ .../EditProfile/AddressManagment/index.tsx | 44 +++++++++++++++++++ .../microComponents/AddressActionMenu.tsx} | 30 ++++++------- .../microComponents/AddressContent.tsx | 0 .../microComponents/AddressList.tsx | 16 ++++--- .../microComponents/SingleAddress.tsx | 13 +++--- .../stories/AddressManagement.stories.tsx | 14 +++--- .../user/Settings/EditProfile/index.tsx | 24 +++++++--- src/temp/AddressManagment/index.tsx | 37 ---------------- 10 files changed, 121 insertions(+), 92 deletions(-) rename src/{temp => features/user/Settings/EditProfile}/AddressManagment/AddressManagement.module.scss (66%) create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/index.tsx rename src/{temp/AddressManagment/microComponents/AddressActions.tsx => features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx} (82%) rename src/{temp => features/user/Settings/EditProfile}/AddressManagment/microComponents/AddressContent.tsx (100%) rename src/{temp => features/user/Settings/EditProfile}/AddressManagment/microComponents/AddressList.tsx (52%) rename src/{temp => features/user/Settings/EditProfile}/AddressManagment/microComponents/SingleAddress.tsx (75%) rename src/{temp => features/user/Settings/EditProfile/AddressManagment}/stories/AddressManagement.stories.tsx (74%) delete mode 100644 src/temp/AddressManagment/index.tsx diff --git a/pages/sites/[slug]/[locale]/profile/edit.tsx b/pages/sites/[slug]/[locale]/profile/edit.tsx index d9fa25135b..5a4e531a91 100644 --- a/pages/sites/[slug]/[locale]/profile/edit.tsx +++ b/pages/sites/[slug]/[locale]/profile/edit.tsx @@ -50,7 +50,7 @@ export default EditProfilePage; export const getStaticPaths = async () => { const subDomainPaths = await constructPathsForTenantSlug(); - const paths = subDomainPaths.map((path) => { + const paths = subDomainPaths?.map((path) => { return { params: { slug: path.params.slug, diff --git a/src/temp/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss similarity index 66% rename from src/temp/AddressManagment/AddressManagement.module.scss rename to src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index dd3aade379..226eaa3e1e 100644 --- a/src/temp/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -1,4 +1,4 @@ -@import '../../theme/theme'; +@import '../../../../../theme/theme'; .addressContainer { display: flex; @@ -8,26 +8,37 @@ border-radius: 8px; font-size: $fontSmall; font-weight: 400; + padding: 24px 10px 24px 24px; .address { max-width: 346px; } - svg { - height: 20px; - width: 12px; - padding-right: 24px; - padding-top: 24px; + .kababMenuButton { + height: 34px; + width: 34px; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + background-color: transparent; cursor: pointer; + svg { + height: 20px; + width: 12px; + } + } + .kababMenuButton:hover { + background-color: rgba(120, 120, 120, 0.1); } } .addressSubContainer { display: flex; flex-direction: column; + justify-content: center; gap: 16px; - padding: 24px 0px 24px 24px; .addressTag { padding: 5px 10px; - max-width: 98px; + max-width: 110px; border-radius: 6px; text-align: center; color: #fff; @@ -45,14 +56,10 @@ background: rgba(45, 156, 219, 1); } -.kababMenuButton { - cursor: pointer; -} - .addressActions { min-width: 184px; cursor: pointer; - padding: 12px; + padding: 2px 12px; list-style: none; .action { font-size: 12px; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx new file mode 100644 index 0000000000..84f177da43 --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -0,0 +1,44 @@ +import type { Address } from '@planet-sdk/common'; +import type { AddressAction } from './microComponents/AddressActionMenu'; + +import { useMemo, useState } from 'react'; +import AddressList from './microComponents/AddressList'; +import { useUserProps } from '../../../../common/Layout/UserPropsContext'; + +export type AddressType = 'primary' | 'mailing' | 'other'; + +export interface UpdatedAddress extends Address { + id: string; + type: AddressType; + name: string | null; + state: string | null; + isPrimary: boolean | null; + address2: string | null; +} +export const addressType = ['primary', 'mailing', 'other']; +const AddressManagement = () => { + const { user } = useUserProps(); + const [userAddresses, setUserAddresses] = useState( + user?.addresses + ); // need to update planet-sdk to include addresses key + const [addressAction, setAddressAction] = useState( + null + ); + + const sortedAddresses = useMemo(() => { + return userAddresses.sort((a, b) => { + return addressType.indexOf(a.type) - addressType.indexOf(b.type); + }); + }, [userAddresses]); + + return ( + <> + + + ); +}; + +export default AddressManagement; diff --git a/src/temp/AddressManagment/microComponents/AddressActions.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx similarity index 82% rename from src/temp/AddressManagment/microComponents/AddressActions.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 1ed58c044e..de658fc37a 100644 --- a/src/temp/AddressManagment/microComponents/AddressActions.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -1,9 +1,10 @@ +import type { SetState } from '../../../../../common/types/common'; + import { useState } from 'react'; import { useTranslations } from 'next-intl'; -import { Button, Popover } from '@mui/material'; -import KababMenuIcon from '../../../../public/assets/images/icons/KababMenuIcon'; +import { Popover } from '@mui/material'; +import KababMenuIcon from '../../../../../../../public/assets/images/icons/KababMenuIcon'; import styles from '../AddressManagement.module.scss'; -import { SetState } from '../../../features/common/types/common'; export type AddressType = 'primary' | 'mailing' | 'other'; export const ADDRESS_ACTIONS = { @@ -27,7 +28,11 @@ interface Props { setAddressAction: SetState; } -const AddressActions = ({ type, addressCount, setAddressAction }: Props) => { +const AddressActionsMenu = ({ + type, + addressCount, + setAddressAction, +}: Props) => { const t = useTranslations('Me'); const [popoverAnchor, setPopoverAnchor] = useState( null @@ -74,11 +79,9 @@ const AddressActions = ({ type, addressCount, setAddressAction }: Props) => { return (
- { onClose={closePopover} anchorOrigin={{ vertical: 'bottom', - horizontal: 'right', - }} - transformOrigin={{ - vertical: 'top', - horizontal: 'right', + horizontal: 'left', }} sx={{ '& .MuiPaper-root': { @@ -106,6 +105,7 @@ const AddressActions = ({ type, addressCount, setAddressAction }: Props) => { key={key} className={styles.action} onClick={() => handleActionClick(item.action)} + role="button" > {item.label} @@ -117,4 +117,4 @@ const AddressActions = ({ type, addressCount, setAddressAction }: Props) => { ); }; -export default AddressActions; +export default AddressActionsMenu; diff --git a/src/temp/AddressManagment/microComponents/AddressContent.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx similarity index 100% rename from src/temp/AddressManagment/microComponents/AddressContent.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx diff --git a/src/temp/AddressManagment/microComponents/AddressList.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx similarity index 52% rename from src/temp/AddressManagment/microComponents/AddressList.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx index 80b6dffbd4..b13823fcad 100644 --- a/src/temp/AddressManagment/microComponents/AddressList.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx @@ -1,14 +1,16 @@ import type { UpdatedAddress } from '..'; -import type { AddressAction } from './AddressActions'; +import type { AddressAction } from './AddressActionMenu'; +import type { SetState } from '../../../../../common/types/common'; -import { useState } from 'react'; import SingleAddress from './SingleAddress'; -const AddressList = ({ addresses }: { addresses: UpdatedAddress[] }) => { - const [addressAction, setAddressAction] = useState( - null - ); - const addressCount = addresses.length; +interface Props { + addresses: UpdatedAddress[]; + setAddressAction: SetState; +} + +const AddressList = ({ addresses, setAddressAction }: Props) => { + const addressCount = addresses?.length; return ( <> diff --git a/src/temp/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx similarity index 75% rename from src/temp/AddressManagment/microComponents/SingleAddress.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index f18c6a11cf..cd921f92a4 100644 --- a/src/temp/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -1,14 +1,13 @@ import type { UpdatedAddress } from '..'; -import type { SetState } from '../../../features/common/types/common'; -import type { AddressAction } from './AddressActions'; +import type { SetState } from '../../../../../common/types/common'; +import type { AddressAction } from './AddressActionMenu'; +import type { CountryCode } from '@planet-sdk/common'; -import React from 'react'; import { useTranslations } from 'next-intl'; -import { formatAddress } from '../../../utils/addressManagement'; +import { formatAddress } from '../../../../../../utils/addressManagement'; import styles from '../AddressManagement.module.scss'; -import { CountryCode } from '@planet-sdk/common'; import AddressContent from './AddressContent'; -import AddressActions from './AddressActions'; +import AddressActionsMenu from './AddressActionMenu'; interface Props { userAddress: UpdatedAddress; @@ -37,7 +36,7 @@ const SingleAddress = ({ return (
- = { +import AddressList from '../microComponents/AddressList'; + +const meta: Meta = { title: 'AddressManagement/AddressManagement', - component: AddressManagement, + component: AddressList, }; export default meta; -type Story = StoryObj; +type Story = StoryObj; const address1: UpdatedAddress = { address: 'Königsallee 45, Building A, Floor 3, Apartment 3C', @@ -48,7 +50,9 @@ const address3: UpdatedAddress = { isPrimary: null, }; -const addresses = [address1, address2, address3]; +const addresses = [address1, address2, address3].sort((a, b) => { + return addressType.indexOf(a.type) - addressType.indexOf(b.type); +}); export const Default: Story = { args: { diff --git a/src/features/user/Settings/EditProfile/index.tsx b/src/features/user/Settings/EditProfile/index.tsx index 36b4dbf2ca..98042ee137 100644 --- a/src/features/user/Settings/EditProfile/index.tsx +++ b/src/features/user/Settings/EditProfile/index.tsx @@ -4,17 +4,27 @@ import CenteredContainer from '../../../common/Layout/CenteredContainer'; import DashboardView from '../../../common/Layout/DashboardView'; import EditProfileForm from './EditProfileForm'; import SingleColumnView from '../../../common/Layout/SingleColumnView'; +import AddressManagement from './AddressManagment'; export default function EditProfile(): ReactElement | null { const t = useTranslations('Me'); return ( - - - - - - - + <> + + + + + + + + + + + + + + + ); } diff --git a/src/temp/AddressManagment/index.tsx b/src/temp/AddressManagment/index.tsx deleted file mode 100644 index 9eee1cde45..0000000000 --- a/src/temp/AddressManagment/index.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import type { Address } from '@planet-sdk/common'; - -import DashboardView from '../../features/common/Layout/DashboardView'; -import SingleColumnView from '../../features/common/Layout/SingleColumnView'; -import CenteredContainer from '../../features/common/Layout/CenteredContainer'; -import { useTranslations } from 'next-intl'; -import AddressList from './microComponents/AddressList'; - -export type AddressType = 'primary' | 'mailing' | 'other'; - -export interface UpdatedAddress extends Address { - id: string; - type: AddressType; - name: string | null; - state: string | null; - isPrimary: boolean | null; - address2: string | null; -} - -interface Props { - addresses: UpdatedAddress[]; -} - -const AddressManagement = ({ addresses }: Props) => { - const t = useTranslations('Me'); - return ( - - - - - - - - ); -}; - -export default AddressManagement; From 804ebd483096e6ebc50db9e3e8a0790ff856b927 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sat, 9 Nov 2024 14:42:52 +0530 Subject: [PATCH 09/88] feat: add new address button UI --- public/static/locales/en/me.json | 3 ++- .../AddressManagment/AddressManagement.module.scss | 8 +++++++- .../Settings/EditProfile/AddressManagment/index.tsx | 13 ++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/public/static/locales/en/me.json b/public/static/locales/en/me.json index 01ef680bb6..a65dcae1f4 100644 --- a/public/static/locales/en/me.json +++ b/public/static/locales/en/me.json @@ -294,7 +294,8 @@ "edit": "Edit", "delete": "Delete", "setAsPrimaryAddress": "Set as Primary Address", - "setAsBillingAddress": "Set as Billing Address" + "setAsBillingAddress": "Set as Billing Address", + "addNewAddress": "Add New Address" } } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 226eaa3e1e..6ebff283ca 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -38,7 +38,7 @@ gap: 16px; .addressTag { padding: 5px 10px; - max-width: 110px; + max-width: 112px; border-radius: 6px; text-align: center; color: #fff; @@ -48,6 +48,12 @@ } } +.addNewAddressButton { + width: 342px; + height: 40px; + margin-top: 40px; +} + .primary { background: rgba(0, 122, 73, 1); } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 84f177da43..316e7b6522 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -2,8 +2,11 @@ import type { Address } from '@planet-sdk/common'; import type { AddressAction } from './microComponents/AddressActionMenu'; import { useMemo, useState } from 'react'; +import { useTranslations } from 'next-intl'; import AddressList from './microComponents/AddressList'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; +import WebappButton from '../../../../common/WebappButton'; +import styles from './AddressManagement.module.scss'; export type AddressType = 'primary' | 'mailing' | 'other'; @@ -18,13 +21,14 @@ export interface UpdatedAddress extends Address { export const addressType = ['primary', 'mailing', 'other']; const AddressManagement = () => { const { user } = useUserProps(); + const tMe = useTranslations('Me'); const [userAddresses, setUserAddresses] = useState( user?.addresses ); // need to update planet-sdk to include addresses key const [addressAction, setAddressAction] = useState( null ); - + const openAddressForm = () => {}; const sortedAddresses = useMemo(() => { return userAddresses.sort((a, b) => { return addressType.indexOf(a.type) - addressType.indexOf(b.type); @@ -37,6 +41,13 @@ const AddressManagement = () => { addresses={sortedAddresses} setAddressAction={setAddressAction} /> + ); }; From abf402ae1b5355311e0c1b8cf83dc348eaa487c3 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sat, 9 Nov 2024 17:13:45 +0530 Subject: [PATCH 10/88] refactor: consolidate translation resources --- pages/sites/[slug]/[locale]/profile/edit.tsx | 2 +- public/static/locales/en/me.json | 12 +----------- public/static/locales/en/profile.json | 10 ++++++++++ .../Settings/EditProfile/AddressManagment/index.tsx | 4 ++-- .../microComponents/AddressActionMenu.tsx | 10 +++++----- .../microComponents/AddressContent.tsx | 8 +++----- 6 files changed, 22 insertions(+), 24 deletions(-) diff --git a/pages/sites/[slug]/[locale]/profile/edit.tsx b/pages/sites/[slug]/[locale]/profile/edit.tsx index 5a4e531a91..ab4e587a2b 100644 --- a/pages/sites/[slug]/[locale]/profile/edit.tsx +++ b/pages/sites/[slug]/[locale]/profile/edit.tsx @@ -78,7 +78,7 @@ export const getStaticProps: GetStaticProps = async ( const messages = await getMessagesForPage({ locale: context.params?.locale as string, - filenames: ['common', 'me', 'country', 'editProfile'], + filenames: ['common', 'me', 'country', 'editProfile', 'profile'], }); return { diff --git a/public/static/locales/en/me.json b/public/static/locales/en/me.json index a65dcae1f4..b4e45539d3 100644 --- a/public/static/locales/en/me.json +++ b/public/static/locales/en/me.json @@ -286,16 +286,6 @@ "vplatform-payout": "Platform Payout", "processing": "Processing", "bankDetails": "Bank Details", - "refundAmount": "Refunded Amount", - "addressManagement": { - "address": "Address", - "primaryAddress": "Primary Address", - "BillingAddress": "Billing Address", - "edit": "Edit", - "delete": "Delete", - "setAsPrimaryAddress": "Set as Primary Address", - "setAsBillingAddress": "Set as Billing Address", - "addNewAddress": "Add New Address" - } + "refundAmount": "Refunded Amount" } } diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index 2bddb971aa..8689977f3c 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -134,6 +134,16 @@ "lifeOnLand": "Life on land", "partnership": "Partnerships for the goals" } + }, + "addressManagement": { + "address": "Address", + "primaryAddress": "Primary Address", + "BillingAddress": "Billing Address", + "edit": "Edit", + "delete": "Delete", + "setAsPrimaryAddress": "Set as Primary Address", + "setAsBillingAddress": "Set as Billing Address", + "addNewAddress": "Add New Address" } } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 316e7b6522..261f4971df 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -21,7 +21,7 @@ export interface UpdatedAddress extends Address { export const addressType = ['primary', 'mailing', 'other']; const AddressManagement = () => { const { user } = useUserProps(); - const tMe = useTranslations('Me'); + const tProfile = useTranslations('Profile.addressManagement'); const [userAddresses, setUserAddresses] = useState( user?.addresses ); // need to update planet-sdk to include addresses key @@ -42,7 +42,7 @@ const AddressManagement = () => { setAddressAction={setAddressAction} /> { - const t = useTranslations('Me'); + const tProfile = useTranslations('Profile.addressManagement'); const [popoverAnchor, setPopoverAnchor] = useState( null ); const addressActionConfig: AddressActionItem[] = [ { - label: t('addressManagement.edit'), + label: tProfile('edit'), action: ADDRESS_ACTIONS.EDIT, shouldRender: true, }, { - label: t('addressManagement.delete'), + label: tProfile('delete'), action: ADDRESS_ACTIONS.DELETE, shouldRender: addressCount > 1, }, { - label: t('addressManagement.setAsPrimaryAddress'), + label: tProfile('setAsPrimaryAddress'), action: ADDRESS_ACTIONS.SET_PRIMARY, shouldRender: !(type === 'mailing' || type === 'primary'), }, { - label: t('addressManagement.setAsBillingAddress'), + label: tProfile('setAsBillingAddress'), action: ADDRESS_ACTIONS.SET_BILLING, shouldRender: !(type === 'mailing' || type === 'primary'), }, diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx index 239eb3d351..4c69a213c8 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx @@ -6,15 +6,13 @@ interface Props { userAddress: string; } const AddressContent = ({ type, userAddress }: Props) => { - const t = useTranslations('Me'); + const tProfile = useTranslations('Profile.addressManagement'); return (
{type !== 'other' && ( - {t( - `addressManagement.${ - type === 'primary' ? 'primaryAddress' : 'BillingAddress' - }` + {tProfile( + `${type === 'primary' ? 'primaryAddress' : 'BillingAddress'}` )} )} From 667ba5ea4a1a826fb1f78b8e9ea590b515808f69 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sun, 10 Nov 2024 09:34:54 +0530 Subject: [PATCH 11/88] fix: translation issue --- .../AddressManagment/microComponents/AddressActionMenu.tsx | 2 +- src/features/user/Settings/EditProfile/index.tsx | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 7be1ec958f..95a3acd2b0 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -75,7 +75,7 @@ const AddressActionsMenu = ({ }; const open = Boolean(popoverAnchor); - const id = open ? 'simple-popover' : undefined; + const id = open ? 'address-action-popOver' : undefined; return (
diff --git a/src/features/user/Settings/EditProfile/index.tsx b/src/features/user/Settings/EditProfile/index.tsx index 98042ee137..a57537c87a 100644 --- a/src/features/user/Settings/EditProfile/index.tsx +++ b/src/features/user/Settings/EditProfile/index.tsx @@ -8,6 +8,7 @@ import AddressManagement from './AddressManagment'; export default function EditProfile(): ReactElement | null { const t = useTranslations('Me'); + const tProfile = useTranslations('Profile'); return ( <> @@ -18,7 +19,10 @@ export default function EditProfile(): ReactElement | null { - + From b0a716a0395300ff1fb4e1edc0905ccf5a6a6ecc Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:17:34 +0530 Subject: [PATCH 12/88] feat: integrate the api --- public/static/locales/en/me.json | 2 +- src/temp/AddressManagment/AddressForm.tsx | 198 ++++++++++++++---- .../AddressManagement.module.scss | 29 +++ src/utils/addressManagement.ts | 5 + 4 files changed, 192 insertions(+), 42 deletions(-) diff --git a/public/static/locales/en/me.json b/public/static/locales/en/me.json index 3862049f02..87f1c82133 100644 --- a/public/static/locales/en/me.json +++ b/public/static/locales/en/me.json @@ -296,7 +296,7 @@ "setAsPrimaryAddress": "Set as Primary Address", "setAsBillingAddress": "Set as Billing Address", "addAddress": "Add Address", - "alternativeAddress": "Address 2(optional)" + "address2": "Address 2(optional)" } } } diff --git a/src/temp/AddressManagment/AddressForm.tsx b/src/temp/AddressManagment/AddressForm.tsx index 4ddbd19180..a56620d75e 100644 --- a/src/temp/AddressManagment/AddressForm.tsx +++ b/src/temp/AddressManagment/AddressForm.tsx @@ -1,27 +1,46 @@ import type { ExtendedCountryCode } from '../../features/common/types/country'; +import type { + AddressSuggestionsType, + AddressType, +} from '../../features/common/types/geocoder'; -import { useState } from 'react'; +import { useState, useContext, useMemo } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { useTranslations } from 'next-intl'; -import { TextField } from '@mui/material'; +import { Autocomplete, TextField } from '@mui/material'; +import GeocoderArcGIs from 'geocoder-arcgis'; +import { APIError, handleError } from '@planet-sdk/common'; import styles from './AddressManagement.module.scss'; import WebappButton from '../../features/common/WebappButton'; import InlineFormDisplayGroup from '../../features/common/Layout/Forms/InlineFormDisplayGroup'; import SelectCountry from '../../features/common/InputTypes/AutoCompleteCountry'; import { allCountries } from '../../utils/constants/countries'; +import COUNTRY_ADDRESS_POSTALS from '../../utils/countryZipCode'; +import { useUserProps } from '../../features/common/Layout/UserPropsContext'; +import { postAuthenticatedRequest } from '../../utils/apiRequests/api'; +import { useTenant } from '../../features/common/Layout/TenantContext'; +import { ErrorHandlingContext } from '../../features/common/Layout/ErrorHandlingContext'; +import { validationPattern } from '../../utils/addressManagement'; type FormData = { address: string; - alternativeAddress: string | undefined; + address2: string | undefined; city: string; zipCode: string; state: string; }; - +const geocoder = new GeocoderArcGIs( + process.env.ESRI_CLIENT_SECRET + ? { + client_id: process.env.ESRI_CLIENT_ID, + client_secret: process.env.ESRI_CLIENT_SECRET, + } + : {} +); const AddressForm = ({ mode }) => { const defaultAddressDetail = { address: '', - alternativeAddress: '', + address2: '', city: '', zipCode: '', state: '', @@ -29,6 +48,8 @@ const AddressForm = ({ mode }) => { const { control, handleSubmit, + setValue, + reset, formState: { errors }, } = useForm({ mode: 'onBlur', @@ -37,8 +58,89 @@ const AddressForm = ({ mode }) => { const t = useTranslations('EditProfile'); const tMe = useTranslations('Me'); const tCommon = useTranslations('Common'); + const { contextLoaded, user, token, logoutUser } = useUserProps(); + const { tenantConfig } = useTenant(); + const { setErrors } = useContext(ErrorHandlingContext); const [country, setCountry] = useState('DE'); - const closeModal = () => {}; + const [addressSuggestions, setAddressSuggestions] = useState< + AddressSuggestionsType[] + >([]); + const [isUploadingData, setIsUploadingData] = useState(false); // This state will be useful to conditionally render loader. + + const suggestAddress = (value: string) => { + if (value.length > 3) { + geocoder + .suggest(value, { category: 'Address', countryCode: country }) + .then((result: { suggestions: AddressSuggestionsType[] }) => { + const filterdSuggestions = result.suggestions.filter( + (suggestion: AddressSuggestionsType) => { + return !suggestion.isCollection; + } + ); + setAddressSuggestions(filterdSuggestions); + }) + .catch(console.log); + } + }; + + const getAddress = (value: string) => { + geocoder + .findAddressCandidates(value, { outfields: '*' }) + .then((result: AddressType) => { + setValue('address', result.candidates[0].attributes.ShortLabel, { + shouldValidate: true, + }); + setValue('city', result.candidates[0].attributes.City, { + shouldValidate: true, + }); + setValue('zipCode', result.candidates[0].attributes.Postal, { + shouldValidate: true, + }); + setAddressSuggestions([]); + }) + .catch(console.log); + }; + + const postalRegex = useMemo(() => { + const filteredCountry = COUNTRY_ADDRESS_POSTALS.find( + (item) => item.abbrev === country + ); + return filteredCountry?.postal; + }, [country]); + + const resetForm = () => { + reset(defaultAddressDetail); + setAddressSuggestions([]); + }; + const closeModal = () => { + resetForm(); + }; + + const addNewAddress = async (data: FormData) => { + setIsUploadingData(true); + const bodyToSend = { + ...data, + country, + type: 'other', + }; + if (contextLoaded && user) { + try { + const req = await postAuthenticatedRequest( + tenantConfig.id, + '/app/addresses', + bodyToSend, + token, + logoutUser + ); + } catch (error) { + setIsUploadingData(false); + setErrors(handleError(error as APIError)); + } finally { + setIsUploadingData(false); + } + } + }; + return (

{tMe('addressManagement.addAddress')}

@@ -49,33 +151,53 @@ const AddressForm = ({ mode }) => { rules={{ required: t('validationErrors.addressRequired'), pattern: { - value: /^[\p{L}\p{N}\sß.,#/-]+$/u, + value: validationPattern.address, message: t('validationErrors.addressInvalid'), }, }} - render={({ - field: { onChange: handleChange, value, onBlur: handleBlur }, - }) => ( - { - handleChange(event); + render={({ field }) => ( + { + suggestAddress(newValue); + field.onChange(newValue); }} - onBlur={() => handleBlur()} - value={value} - error={errors.address !== undefined} - helperText={ - errors.address !== undefined ? errors.address?.message : null - } + onChange={(_, newValue) => { + if (newValue) getAddress(newValue as string); + field.onChange( + typeof newValue === 'string' ? newValue : newValue?.text || '' + ); + }} + value={field.value} + getOptionLabel={(option) => { + if (typeof option === 'string') { + return option; // Return the string value when typing + } + if (typeof option === 'object' && 'text' in option) { + return option.text; // Return the text property for suggestion objects + } + return ''; + }} + renderInput={(params) => ( + + )} /> )} /> { field: { onChange: handleChange, value, onBlur: handleBlur }, }) => ( { handleChange(event); }} onBlur={() => handleBlur()} value={value} - error={errors.alternativeAddress !== undefined} - helperText={ - errors.alternativeAddress !== undefined - ? errors.alternativeAddress?.message - : null - } + error={errors.address2 !== undefined} + helperText={errors.address2?.message} /> )} /> @@ -105,7 +223,7 @@ const AddressForm = ({ mode }) => { rules={{ required: t('validationErrors.cityRequired'), pattern: { - value: /^[\p{L}\sß.,()-]+$/u, + value: validationPattern.cityState, message: t('validationErrors.cityInvalid'), }, }} @@ -116,7 +234,7 @@ const AddressForm = ({ mode }) => { onBlur={onBlur} value={value} error={errors.city !== undefined} - helperText={errors.city !== undefined && errors.city.message} + helperText={errors.city?.message} /> )} /> @@ -125,10 +243,10 @@ const AddressForm = ({ mode }) => { control={control} rules={{ required: t('validationErrors.zipCodeRequired'), - // pattern: { - // value: postalRegex as RegExp, - // message: t('validationErrors.zipCodeInvalid'), - // }, + pattern: { + value: postalRegex as RegExp, + message: t('validationErrors.zipCodeInvalid'), + }, }} render={({ field: { onChange, value, onBlur } }) => ( { onBlur={onBlur} value={value} error={errors.zipCode !== undefined} - helperText={ - errors.zipCode !== undefined && errors.zipCode.message - } + helperText={errors.zipCode?.message} /> )} /> @@ -150,7 +266,7 @@ const AddressForm = ({ mode }) => { control={control} rules={{ pattern: { - value: /^[\p{L}\sß.,()-]+$/u, + value: validationPattern.cityState, message: t('validationErrors.stateInvalid'), }, }} @@ -161,7 +277,7 @@ const AddressForm = ({ mode }) => { onBlur={onBlur} value={value} error={errors.state !== undefined} - helperText={errors.state !== undefined && errors.state.message} + helperText={errors.state?.message} /> )} /> @@ -186,7 +302,7 @@ const AddressForm = ({ mode }) => { text={tMe('addressManagement.addAddress')} variant="primary" elementType="button" - onClick={closeModal} + onClick={handleSubmit(addNewAddress)} buttonClasses={styles.addAddressButton} />
diff --git a/src/temp/AddressManagment/AddressManagement.module.scss b/src/temp/AddressManagment/AddressManagement.module.scss index 9f1e14edb2..697fc743ec 100644 --- a/src/temp/AddressManagment/AddressManagement.module.scss +++ b/src/temp/AddressManagment/AddressManagement.module.scss @@ -98,3 +98,32 @@ min-height: 40px; } } + +// Loader +.spinner { + border: 2px solid var(--disabled-font-color); + border-radius: 50%; + border-top: 2px solid transparent; + width: 16px !important; + height: 16px !important; + -webkit-animation: spin 1s linear infinite; /* Safari */ + animation: spin 1s linear infinite; +} + +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + } +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index 9179b48543..c79cba641a 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -13,3 +13,8 @@ export const formatAddress = ( return cleanAddress; }; + +export const validationPattern = { + address: /^[\p{L}\p{N}\sß.,#/-]+$/u, + cityState: /^[\p{L}\sß.,()-]+$/u, +}; From a6d09e152955c13591a798106fe50fca0678b83d Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:18:52 +0530 Subject: [PATCH 13/88] feat: use modal for add new address form --- .../ForestProgress/ForestProgress.module.scss | 2 +- .../AddressManagment/AddressForm.tsx | 9 ++++++++- .../AddressManagement.module.scss | 19 +++++++++++++++++++ .../EditProfile/AddressManagment/index.tsx | 8 +++++++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/features/user/Profile/ForestProgress/ForestProgress.module.scss b/src/features/user/Profile/ForestProgress/ForestProgress.module.scss index a789a4fd23..30c3854736 100644 --- a/src/features/user/Profile/ForestProgress/ForestProgress.module.scss +++ b/src/features/user/Profile/ForestProgress/ForestProgress.module.scss @@ -114,10 +114,10 @@ position: relative; left: 50%; top: 50%; + transform: translate(-50%, -50%); width: 398px; height: 524px; background: #fff; - transform: translate(-50%, -50%); border-radius: 16px; padding: 18px; display: flex; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index 1441e27cfd..ccb7e7ced1 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -3,6 +3,7 @@ import type { AddressType, } from '../../../../common/types/geocoder'; import type { ExtendedCountryCode } from '../../../../common/types/country'; +import type { SetState } from '../../../../common/types/common'; import { useState, useContext, useMemo } from 'react'; import { Controller, useForm } from 'react-hook-form'; @@ -29,6 +30,11 @@ type FormData = { zipCode: string; state: string; }; + +interface Props { + mode: string; + setIsModalOpen: SetState; +} const geocoder = new GeocoderArcGIs( process.env.ESRI_CLIENT_SECRET ? { @@ -37,7 +43,7 @@ const geocoder = new GeocoderArcGIs( } : {} ); -const AddressForm = ({ mode }) => { +const AddressForm = ({ mode, setIsModalOpen }: Props) => { const defaultAddressDetail = { address: '', address2: '', @@ -113,6 +119,7 @@ const AddressForm = ({ mode }) => { setAddressSuggestions([]); }; const closeModal = () => { + setIsModalOpen(false); resetForm(); }; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 6c602b01ab..84c6b5b0a3 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -90,6 +90,10 @@ background: rgba(255, 255, 255, 1); border-radius: 16px; padding: 20px; + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); h1 { font-weight: 700; font-size: $fontSixteen; @@ -104,6 +108,7 @@ .formButtonContainer { display: flex; + gap: 8px; justify-content: space-between; .addAddressButton, .cancelButton { @@ -112,6 +117,20 @@ } } +@include xsPhoneView { + .addressFormContainer { + width: 95%; + } + .formButtonContainer { + display: flex; + flex-direction: column; + .addAddressButton, + .cancelButton { + width: 100%; + } + } +} + // Loader .spinner { border: 2px solid var(--disabled-font-color); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 261f4971df..15acea52e6 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -3,10 +3,12 @@ import type { AddressAction } from './microComponents/AddressActionMenu'; import { useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; +import { Modal } from '@mui/material'; import AddressList from './microComponents/AddressList'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import WebappButton from '../../../../common/WebappButton'; import styles from './AddressManagement.module.scss'; +import AddressForm from './AddressForm'; export type AddressType = 'primary' | 'mailing' | 'other'; @@ -28,6 +30,7 @@ const AddressManagement = () => { const [addressAction, setAddressAction] = useState( null ); + const [isModalOpen, setIsModalOpen] = useState(false); const openAddressForm = () => {}; const sortedAddresses = useMemo(() => { return userAddresses.sort((a, b) => { @@ -44,10 +47,13 @@ const AddressManagement = () => { setIsModalOpen(true)} variant="primary" buttonClasses={styles.addNewAddressButton} /> + + + ); }; From 8948142ba212c584ed7073a120ea24f5d33706c9 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:12:37 +0530 Subject: [PATCH 14/88] feat: debounce address suggestions to improve performance --- .../AddressManagment/AddressForm.tsx | 63 +++++++++++++------ .../EditProfile/AddressManagment/index.tsx | 7 ++- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index ccb7e7ced1..5015dc67b1 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -4,8 +4,9 @@ import type { } from '../../../../common/types/geocoder'; import type { ExtendedCountryCode } from '../../../../common/types/country'; import type { SetState } from '../../../../common/types/common'; +import type { UpdatedAddress } from '.'; -import { useState, useContext, useMemo } from 'react'; +import { useState, useContext, useMemo, useCallback } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { useTranslations } from 'next-intl'; import { Autocomplete, TextField } from '@mui/material'; @@ -22,6 +23,7 @@ import { postAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import { validationPattern } from '../../../../../utils/addressManagement'; +import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; type FormData = { address: string; @@ -34,6 +36,7 @@ type FormData = { interface Props { mode: string; setIsModalOpen: SetState; + setUserAddresses: SetState; } const geocoder = new GeocoderArcGIs( process.env.ESRI_CLIENT_SECRET @@ -43,7 +46,7 @@ const geocoder = new GeocoderArcGIs( } : {} ); -const AddressForm = ({ mode, setIsModalOpen }: Props) => { +const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { const defaultAddressDetail = { address: '', address2: '', @@ -67,27 +70,43 @@ const AddressForm = ({ mode, setIsModalOpen }: Props) => { const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const [country, setCountry] = useState('DE'); + const [country, setCountry] = useState( + user?.country || 'DE' + ); const [addressSuggestions, setAddressSuggestions] = useState< AddressSuggestionsType[] >([]); + const [inputValue, setInputValue] = useState(''); const [isUploadingData, setIsUploadingData] = useState(false); // This state will be useful to conditionally render loader. - const suggestAddress = (value: string) => { - if (value.length > 3) { - geocoder - .suggest(value, { category: 'Address', countryCode: country }) - .then((result: { suggestions: AddressSuggestionsType[] }) => { - const filterdSuggestions = result.suggestions.filter( - (suggestion: AddressSuggestionsType) => { - return !suggestion.isCollection; - } - ); - setAddressSuggestions(filterdSuggestions); - }) - .catch(console.log); - } - }; + const suggestAddress = useCallback( + (value: string) => { + if (value.length > 3) { + geocoder + .suggest(value, { category: 'Address', countryCode: country }) + .then((result: { suggestions: AddressSuggestionsType[] }) => { + const filterdSuggestions = result.suggestions.filter( + (suggestion: AddressSuggestionsType) => { + return !suggestion.isCollection; + } + ); + setAddressSuggestions(filterdSuggestions); + }) + .catch(console.log); + } + }, + [country, geocoder] + ); + + useDebouncedEffect( + () => { + if (inputValue) { + suggestAddress(inputValue); + } + }, + 700, + [inputValue] + ); const getAddress = (value: string) => { geocoder @@ -132,13 +151,17 @@ const AddressForm = ({ mode, setIsModalOpen }: Props) => { }; if (contextLoaded && user) { try { - const req = await postAuthenticatedRequest( + const res = await postAuthenticatedRequest( tenantConfig.id, '/app/addresses', bodyToSend, token, logoutUser ); + if (res) { + setUserAddresses((prevAddresses) => [...prevAddresses, res]); + closeModal(); + } } catch (error) { setIsUploadingData(false); setErrors(handleError(error as APIError)); @@ -167,7 +190,7 @@ const AddressForm = ({ mode, setIsModalOpen }: Props) => { freeSolo options={addressSuggestions} onInputChange={(_, newValue) => { - suggestAddress(newValue); + setInputValue(newValue); field.onChange(newValue); }} onChange={(_, newValue) => { diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 15acea52e6..4f2ae47dc6 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -31,7 +31,6 @@ const AddressManagement = () => { null ); const [isModalOpen, setIsModalOpen] = useState(false); - const openAddressForm = () => {}; const sortedAddresses = useMemo(() => { return userAddresses.sort((a, b) => { return addressType.indexOf(a.type) - addressType.indexOf(b.type); @@ -52,7 +51,11 @@ const AddressManagement = () => { buttonClasses={styles.addNewAddressButton} /> - + ); From b2e639bfa8a5c135110981c14c10825484704a91 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:53:21 +0530 Subject: [PATCH 15/88] feat: introduce a simple spinner for address mgmt form --- .../AddressManagment/AddressForm.tsx | 43 +++++++++++-------- .../AddressManagement.module.scss | 30 ++----------- 2 files changed, 29 insertions(+), 44 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index 5015dc67b1..bb73c7efed 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -9,7 +9,7 @@ import type { UpdatedAddress } from '.'; import { useState, useContext, useMemo, useCallback } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { useTranslations } from 'next-intl'; -import { Autocomplete, TextField } from '@mui/material'; +import { Autocomplete, CircularProgress, TextField } from '@mui/material'; import GeocoderArcGIs from 'geocoder-arcgis'; import { APIError, handleError } from '@planet-sdk/common'; import styles from './AddressManagement.module.scss'; @@ -77,7 +77,7 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { AddressSuggestionsType[] >([]); const [inputValue, setInputValue] = useState(''); - const [isUploadingData, setIsUploadingData] = useState(false); // This state will be useful to conditionally render loader. + const [isUploadingData, setIsUploadingData] = useState(false); const suggestAddress = useCallback( (value: string) => { @@ -163,6 +163,7 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { closeModal(); } } catch (error) { + resetForm(); setIsUploadingData(false); setErrors(handleError(error as APIError)); } finally { @@ -320,22 +321,28 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { /> -
- - -
+ {isUploadingData ? ( +
+ +
+ ) : ( +
+ + +
+ )}
); }; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 84c6b5b0a3..dd7e0e882d 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -131,31 +131,9 @@ } } -// Loader -.spinner { - border: 2px solid var(--disabled-font-color); - border-radius: 50%; - border-top: 2px solid transparent; - width: 16px !important; - height: 16px !important; - -webkit-animation: spin 1s linear infinite; /* Safari */ - animation: spin 1s linear infinite; -} - -@-webkit-keyframes spin { - 0% { - -webkit-transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - } -} +// Form spinner -@keyframes spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } +.addressMgmtSpinner { + display: flex; + justify-content: center; } From ae8575e25102017a70a519d86413d8455023b211 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 12 Nov 2024 13:15:35 +0530 Subject: [PATCH 16/88] refactor(forms): create reusable AddressInput component - Extract duplicated address input logic into a shared component - Add TypeScript interfaces for improved type safety - Implement flexible validation through props - Maintain compatibility with react-hook-form and Material-UI - Reduce code duplication in address form implementations. --- .../AddressManagment/AddressForm.tsx | 89 ++++++------------- .../microComponents/AddressInput.tsx | 89 +++++++++++++++++++ 2 files changed, 115 insertions(+), 63 deletions(-) create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressInput.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index bb73c7efed..b54e9d3797 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -9,7 +9,7 @@ import type { UpdatedAddress } from '.'; import { useState, useContext, useMemo, useCallback } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { useTranslations } from 'next-intl'; -import { Autocomplete, CircularProgress, TextField } from '@mui/material'; +import { CircularProgress, TextField } from '@mui/material'; import GeocoderArcGIs from 'geocoder-arcgis'; import { APIError, handleError } from '@planet-sdk/common'; import styles from './AddressManagement.module.scss'; @@ -24,6 +24,7 @@ import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import { validationPattern } from '../../../../../utils/addressManagement'; import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; +import AddressInput from './microComponents/AddressInput'; type FormData = { address: string; @@ -171,81 +172,43 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { } } }; + const handleInputChange = (value: string) => { + setInputValue(value); + }; + + const handleAddressSelect = (address: string) => { + getAddress(address); + }; return (

{tProfile('addressManagement.addAddress')}

- ( - { - setInputValue(newValue); - field.onChange(newValue); - }} - onChange={(_, newValue) => { - if (newValue) getAddress(newValue as string); - field.onChange( - typeof newValue === 'string' ? newValue : newValue?.text || '' - ); - }} - value={field.value} - getOptionLabel={(option) => { - if (typeof option === 'string') { - return option; // Return the string value when typing - } - if (typeof option === 'object' && 'text' in option) { - return option.text; // Return the text property for suggestion objects - } - return ''; - }} - renderInput={(params) => ( - - )} - /> - )} + suggestions={addressSuggestions} + onInputChange={handleInputChange} + onAddressSelect={handleAddressSelect} /> - ( - { - handleChange(event); - }} - onBlur={() => handleBlur()} - value={value} - error={errors.address2 !== undefined} - helperText={errors.address2?.message} - /> - )} + suggestions={addressSuggestions} + onInputChange={handleInputChange} /> ; + label: string; + required?: boolean; + validationPattern?: RegExp; + validationMessages: { + required: string; + invalid: string; + }; + suggestions: AddressOption[]; + onInputChange?: (value: string) => void; + onAddressSelect?: (address: string) => void; +} + +const AddressInput: React.FC = ({ + name, + control, + label, + required = false, + validationPattern, + validationMessages, + suggestions, + onInputChange, + onAddressSelect, +}) => { + const validationRules = { + ...(required && { required: validationMessages.required }), + ...(validationPattern && { + pattern: { + value: validationPattern, + message: validationMessages.invalid, + }, + }), + }; + + const getOptionLabel = (option: string | AddressOption): string => { + if (typeof option === 'string') { + return option; + } + return 'text' in option ? option.text : ''; + }; + + return ( + ( + { + field.onChange(newValue); + onInputChange?.(newValue); + }} + onChange={(_, newValue) => { + const value = + typeof newValue === 'string' ? newValue : newValue?.text || ''; + field.onChange(value); + onAddressSelect?.(value); + }} + value={field.value} + getOptionLabel={getOptionLabel} + renderInput={(params) => ( + + )} + /> + )} + /> + ); +}; + +export default AddressInput; From c5c62f777c54072688badce31994d469fe26172c Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 12 Nov 2024 14:32:05 +0530 Subject: [PATCH 17/88] style: adjust min-width for address form container --- .../EditProfile/AddressManagment/AddressManagement.module.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index dd7e0e882d..943277a68d 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -86,7 +86,7 @@ display: flex; flex-direction: column; gap: 40px; - max-width: 565px; + min-width: 565px; background: rgba(255, 255, 255, 1); border-radius: 16px; padding: 20px; @@ -119,6 +119,7 @@ @include xsPhoneView { .addressFormContainer { + min-width: fit-content; width: 95%; } .formButtonContainer { From fd991421479b5b504c5816cb2daeb9d294ca0c93 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:08:53 +0530 Subject: [PATCH 18/88] feat: update add address form to make it work as edit address form. - add address type and action constant definitions - Implement address editing functionality with error handling - add TypeScript type definitions for address operations --- public/static/locales/en/profile.json | 7 +- .../common/InputTypes/AutoCompleteCountry.tsx | 2 +- .../AddressManagment/AddressForm.tsx | 92 ++++++++++++++----- .../EditProfile/AddressManagment/index.tsx | 21 +++-- .../microComponents/AddressActionMenu.tsx | 24 +++-- .../microComponents/AddressContent.tsx | 10 +- .../microComponents/AddressList.tsx | 11 ++- .../microComponents/SingleAddress.tsx | 23 +++++ src/utils/addressManagement.ts | 29 ++++++ 9 files changed, 176 insertions(+), 43 deletions(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index fd408f9370..03a20743ed 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -145,7 +145,12 @@ "setAsPrimaryAddress": "Set as Primary Address", "setAsBillingAddress": "Set as Billing Address", "addNewAddress": "Add New Address", - "addAddress": "Add Address" + "editAddress": "Edit Address", + "saveChanges": "Save Changes", + "formType": { + "add": "Add Address", + "edit": "Edit Address" + } } } } diff --git a/src/features/common/InputTypes/AutoCompleteCountry.tsx b/src/features/common/InputTypes/AutoCompleteCountry.tsx index 7b7e7264ba..ceeb28f494 100644 --- a/src/features/common/InputTypes/AutoCompleteCountry.tsx +++ b/src/features/common/InputTypes/AutoCompleteCountry.tsx @@ -24,7 +24,7 @@ interface CountrySelectProps { label?: ReactNode; name: string | undefined; defaultValue: string | undefined; //This will be a country code e.g. DE, IN, US - onChange: SetState; + onChange: SetState; countries?: CountryType[]; } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index b54e9d3797..e084b56d21 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -19,25 +19,35 @@ import SelectCountry from '../../../../common/InputTypes/AutoCompleteCountry'; import { allCountries } from '../../../../../utils/constants/countries'; import COUNTRY_ADDRESS_POSTALS from '../../../../../utils/countryZipCode'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; -import { postAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; +import { + postAuthenticatedRequest, + putAuthenticatedRequest, +} from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; -import { validationPattern } from '../../../../../utils/addressManagement'; +import { + ADDRESS_TYPE, + getAddressType, + validationPattern, +} from '../../../../../utils/addressManagement'; import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; import AddressInput from './microComponents/AddressInput'; +import { AddressAction } from './microComponents/AddressActionMenu'; type FormData = { - address: string; - address2: string | undefined; - city: string; - zipCode: string; - state: string; + address: string | undefined; + address2: string | null; + city: string | undefined; + zipCode: string | undefined; + state: string | null; }; interface Props { - mode: string; + formType: 'edit' | 'add'; setIsModalOpen: SetState; setUserAddresses: SetState; + userAddress?: UpdatedAddress; + addressAction?: AddressAction | null; } const geocoder = new GeocoderArcGIs( process.env.ESRI_CLIENT_SECRET @@ -47,13 +57,19 @@ const geocoder = new GeocoderArcGIs( } : {} ); -const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { +const AddressForm = ({ + formType, + addressAction, + setIsModalOpen, + setUserAddresses, + userAddress, +}: Props) => { const defaultAddressDetail = { - address: '', - address2: '', - city: '', - zipCode: '', - state: '', + address: userAddress ? userAddress.address : '', + address2: userAddress ? userAddress.address2 : '', + city: userAddress ? userAddress.city : '', + zipCode: userAddress ? userAddress.zipCode : '', + state: userAddress ? userAddress.state : '', }; const { control, @@ -71,8 +87,9 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const [country, setCountry] = useState( - user?.country || 'DE' + const userCountry = formType === 'add' ? user?.country : userAddress?.country; + const [country, setCountry] = useState( + userCountry ?? 'DE' ); const [addressSuggestions, setAddressSuggestions] = useState< AddressSuggestionsType[] @@ -143,12 +160,40 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { resetForm(); }; + const editAddress = async (data: FormData) => { + if (!addressAction || !userAddress) return; + setIsUploadingData(true); + const bodyToSend = { + ...data, + country, + type: getAddressType(formType, userAddress.type), + }; + try { + const res = await putAuthenticatedRequest( + tenantConfig.id, + `/app/addresses/${userAddress?.id}`, + bodyToSend, + token, + logoutUser + ); + if (res) { + setUserAddresses((prevAddresses) => [...prevAddresses, res]); + closeModal(); + } + } catch (error) { + setIsUploadingData(false); + setErrors(handleError(error as APIError)); + } finally { + setIsUploadingData(false); + } + }; + const addNewAddress = async (data: FormData) => { setIsUploadingData(true); const bodyToSend = { ...data, country, - type: 'other', + type: ADDRESS_TYPE.OTHER, }; if (contextLoaded && user) { try { @@ -179,10 +224,9 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { const handleAddressSelect = (address: string) => { getAddress(address); }; - return (
-

{tProfile('addressManagement.addAddress')}

+

{tProfile(`addressManagement.formType.${formType}`)}

{ buttonClasses={styles.cancelButton} />
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 4f2ae47dc6..1f693a7720 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -1,5 +1,8 @@ -import type { Address } from '@planet-sdk/common'; -import type { AddressAction } from './microComponents/AddressActionMenu'; +import type { CountryCode } from '@planet-sdk/common'; +import type { + AddressAction, + AddressType, +} from './microComponents/AddressActionMenu'; import { useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; @@ -10,15 +13,17 @@ import WebappButton from '../../../../common/WebappButton'; import styles from './AddressManagement.module.scss'; import AddressForm from './AddressForm'; -export type AddressType = 'primary' | 'mailing' | 'other'; - -export interface UpdatedAddress extends Address { +export interface UpdatedAddress { id: string; type: AddressType; name: string | null; state: string | null; isPrimary: boolean | null; address2: string | null; + address: string; + city?: string; + zipCode?: string; + country: CountryCode; } export const addressType = ['primary', 'mailing', 'other']; const AddressManagement = () => { @@ -41,7 +46,9 @@ const AddressManagement = () => { <> { variant="primary" buttonClasses={styles.addNewAddressButton} /> - + setIsModalOpen(false)}> diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 95a3acd2b0..d5da1962c3 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -5,15 +5,12 @@ import { useTranslations } from 'next-intl'; import { Popover } from '@mui/material'; import KababMenuIcon from '../../../../../../../public/assets/images/icons/KababMenuIcon'; import styles from '../AddressManagement.module.scss'; +import { + ADDRESS_ACTIONS, + ADDRESS_TYPE, +} from '../../../../../../utils/addressManagement'; -export type AddressType = 'primary' | 'mailing' | 'other'; -export const ADDRESS_ACTIONS = { - EDIT: 'edit', - DELETE: 'delete', - SET_PRIMARY: 'setPrimary', - SET_BILLING: 'setBilling', -} as const; - +export type AddressType = (typeof ADDRESS_TYPE)[keyof typeof ADDRESS_TYPE]; export type AddressAction = (typeof ADDRESS_ACTIONS)[keyof typeof ADDRESS_ACTIONS]; @@ -26,12 +23,14 @@ interface Props { type: AddressType; addressCount: number; setAddressAction: SetState; + setIsModalOpen: SetState; } const AddressActionsMenu = ({ type, addressCount, setAddressAction, + setIsModalOpen, }: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const [popoverAnchor, setPopoverAnchor] = useState( @@ -52,12 +51,16 @@ const AddressActionsMenu = ({ { label: tProfile('setAsPrimaryAddress'), action: ADDRESS_ACTIONS.SET_PRIMARY, - shouldRender: !(type === 'mailing' || type === 'primary'), + shouldRender: !( + type === ADDRESS_TYPE.MAILING || type === ADDRESS_TYPE.PRIMARY + ), }, { label: tProfile('setAsBillingAddress'), action: ADDRESS_ACTIONS.SET_BILLING, - shouldRender: !(type === 'mailing' || type === 'primary'), + shouldRender: !( + type === ADDRESS_TYPE.MAILING || type === ADDRESS_TYPE.PRIMARY + ), }, ]; @@ -70,6 +73,7 @@ const AddressActionsMenu = ({ }; const handleActionClick = (action: AddressAction) => { + setIsModalOpen(true); setAddressAction(action); setPopoverAnchor(null); }; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx index 4c69a213c8..0a60c03031 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx @@ -1,8 +1,10 @@ import styles from '../AddressManagement.module.scss'; import { useTranslations } from 'next-intl'; +import { AddressType } from './AddressActionMenu'; +import { ADDRESS_TYPE } from '../../../../../../utils/addressManagement'; interface Props { - type: 'primary' | 'mailing' | 'other'; + type: AddressType; userAddress: string; } const AddressContent = ({ type, userAddress }: Props) => { @@ -12,7 +14,11 @@ const AddressContent = ({ type, userAddress }: Props) => { {type !== 'other' && ( {tProfile( - `${type === 'primary' ? 'primaryAddress' : 'BillingAddress'}` + `${ + type === ADDRESS_TYPE.PRIMARY + ? 'primaryAddress' + : 'BillingAddress' + }` )} )} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx index b13823fcad..6f90273f9c 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx @@ -6,10 +6,17 @@ import SingleAddress from './SingleAddress'; interface Props { addresses: UpdatedAddress[]; + addressAction: AddressAction | null; setAddressAction: SetState; + setUserAddresses: SetState; } -const AddressList = ({ addresses, setAddressAction }: Props) => { +const AddressList = ({ + addresses, + addressAction, + setAddressAction, + setUserAddresses, +}: Props) => { const addressCount = addresses?.length; return ( @@ -19,7 +26,9 @@ const AddressList = ({ addresses, setAddressAction }: Props) => { key={address.id} userAddress={address} addressCount={addressCount} + addressAction={addressAction} setAddressAction={setAddressAction} + setUserAddresses={setUserAddresses} /> ))} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index cd921f92a4..fb587ee7c7 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -3,28 +3,37 @@ import type { SetState } from '../../../../../common/types/common'; import type { AddressAction } from './AddressActionMenu'; import type { CountryCode } from '@planet-sdk/common'; +import { useState } from 'react'; +import { Modal } from '@mui/material'; import { useTranslations } from 'next-intl'; import { formatAddress } from '../../../../../../utils/addressManagement'; import styles from '../AddressManagement.module.scss'; import AddressContent from './AddressContent'; import AddressActionsMenu from './AddressActionMenu'; +import AddressForm from '../AddressForm'; +import { ADDRESS_ACTIONS } from '../../../../../../utils/addressManagement'; interface Props { userAddress: UpdatedAddress; addressCount: number; + addressAction: AddressAction | null; setAddressAction: SetState; + setUserAddresses: SetState; } const SingleAddress = ({ userAddress, addressCount, + addressAction, setAddressAction, + setUserAddresses, }: Props) => { const tCountry = useTranslations('Country'); const { zipCode, city, state, country, address, type } = userAddress; const countryFullForm = tCountry( country.toLowerCase() as Lowercase ); + const [isModalOpen, setIsModalOpen] = useState(false); const formattedAddress = formatAddress( address, zipCode, @@ -40,7 +49,21 @@ const SingleAddress = ({ type={type} addressCount={addressCount} setAddressAction={setAddressAction} + setIsModalOpen={setIsModalOpen} /> + setIsModalOpen(false)}> + {addressAction === ADDRESS_ACTIONS.EDIT ? ( + + ) : ( + <> + )} +
); }; diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index c79cba641a..90e1878312 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -1,3 +1,18 @@ +import { AddressType } from '../features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu'; + +export const ADDRESS_TYPE = { + PRIMARY: 'primary', + MAILING: 'mailing', + OTHER: 'other', +} as const; + +export const ADDRESS_ACTIONS = { + EDIT: 'edit', + DELETE: 'delete', + SET_PRIMARY: 'setPrimary', + SET_BILLING: 'setBilling', +} as const; + export const formatAddress = ( address: string | undefined, zipCode: string | undefined, @@ -18,3 +33,17 @@ export const validationPattern = { address: /^[\p{L}\p{N}\sß.,#/-]+$/u, cityState: /^[\p{L}\sß.,()-]+$/u, }; + +export const getAddressType = ( + formType: 'add' | 'edit', + userAddressType: AddressType +) => { + if ( + formType === 'edit' && + (userAddressType === ADDRESS_TYPE.MAILING || + userAddressType === ADDRESS_TYPE.PRIMARY) + ) { + return userAddressType; + } + return 'other'; +}; From f840a5838247fcb348db3b2cdec91f551286c91f Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 13 Nov 2024 12:55:34 +0530 Subject: [PATCH 19/88] feat: add api call to fetch user addresses --- .../AddressManagment/AddressForm.tsx | 6 ++-- .../EditProfile/AddressManagment/index.tsx | 28 +++++++++++++++++-- .../microComponents/AddressList.tsx | 3 ++ .../microComponents/SingleAddress.tsx | 3 ++ 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index e084b56d21..3d64b93cbe 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -48,6 +48,7 @@ interface Props { setUserAddresses: SetState; userAddress?: UpdatedAddress; addressAction?: AddressAction | null; + fetchUserAddresses?: () => Promise; } const geocoder = new GeocoderArcGIs( process.env.ESRI_CLIENT_SECRET @@ -63,6 +64,7 @@ const AddressForm = ({ setIsModalOpen, setUserAddresses, userAddress, + fetchUserAddresses, }: Props) => { const defaultAddressDetail = { address: userAddress ? userAddress.address : '', @@ -176,8 +178,8 @@ const AddressForm = ({ token, logoutUser ); - if (res) { - setUserAddresses((prevAddresses) => [...prevAddresses, res]); + if (res && fetchUserAddresses) { + fetchUserAddresses(); closeModal(); } } catch (error) { diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 1f693a7720..1e2f6bfa7a 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -1,10 +1,10 @@ -import type { CountryCode } from '@planet-sdk/common'; +import type { APIError, CountryCode } from '@planet-sdk/common'; import type { AddressAction, AddressType, } from './microComponents/AddressActionMenu'; -import { useMemo, useState } from 'react'; +import { useContext, useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; import { Modal } from '@mui/material'; import AddressList from './microComponents/AddressList'; @@ -12,6 +12,10 @@ import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import WebappButton from '../../../../common/WebappButton'; import styles from './AddressManagement.module.scss'; import AddressForm from './AddressForm'; +import { getAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; +import { useTenant } from '../../../../common/Layout/TenantContext'; +import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; +import { handleError } from '@planet-sdk/common'; export interface UpdatedAddress { id: string; @@ -27,7 +31,9 @@ export interface UpdatedAddress { } export const addressType = ['primary', 'mailing', 'other']; const AddressManagement = () => { - const { user } = useUserProps(); + const { user, contextLoaded, token, logoutUser } = useUserProps(); + const { tenantConfig } = useTenant(); + const { setErrors } = useContext(ErrorHandlingContext); const tProfile = useTranslations('Profile.addressManagement'); const [userAddresses, setUserAddresses] = useState( user?.addresses @@ -42,6 +48,21 @@ const AddressManagement = () => { }); }, [userAddresses]); + const fetchUserAddresses = async () => { + if (!user || !token || !contextLoaded) return; + try { + const res = await getAuthenticatedRequest( + tenantConfig.id, + '/app/addresses', + token, + logoutUser + ); + if (res) setUserAddresses(res); + } catch (error) { + setErrors(handleError(error as APIError)); + } + }; + return ( <> { addressAction={addressAction} setAddressAction={setAddressAction} setUserAddresses={setUserAddresses} + fetchUserAddresses={fetchUserAddresses} /> ; setUserAddresses: SetState; + fetchUserAddresses: () => Promise; } const AddressList = ({ @@ -16,6 +17,7 @@ const AddressList = ({ addressAction, setAddressAction, setUserAddresses, + fetchUserAddresses, }: Props) => { const addressCount = addresses?.length; @@ -29,6 +31,7 @@ const AddressList = ({ addressAction={addressAction} setAddressAction={setAddressAction} setUserAddresses={setUserAddresses} + fetchUserAddresses={fetchUserAddresses} /> ))} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index fb587ee7c7..7551714af5 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -19,6 +19,7 @@ interface Props { addressAction: AddressAction | null; setAddressAction: SetState; setUserAddresses: SetState; + fetchUserAddresses: () => Promise; } const SingleAddress = ({ @@ -27,6 +28,7 @@ const SingleAddress = ({ addressAction, setAddressAction, setUserAddresses, + fetchUserAddresses, }: Props) => { const tCountry = useTranslations('Country'); const { zipCode, city, state, country, address, type } = userAddress; @@ -59,6 +61,7 @@ const SingleAddress = ({ setIsModalOpen={setIsModalOpen} setUserAddresses={setUserAddresses} userAddress={userAddress} + fetchUserAddresses={fetchUserAddresses} /> ) : ( <> From 1eff9ade9476d8a8d5e775378da1879a40e6d768 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 13 Nov 2024 13:06:41 +0530 Subject: [PATCH 20/88] feat: add a space between 2 and ( for Address 2(optional) --- public/static/locales/en/profile.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index 03a20743ed..fda72e7a73 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -137,7 +137,7 @@ }, "addressManagement": { "address": "Address", - "address2": "Address 2(optional)", + "address2": "Address 2 (optional)", "primaryAddress": "Primary Address", "BillingAddress": "Billing Address", "edit": "Edit", From cfd513d64f2619bf8d9659c9a79751d947e1db32 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:45:32 +0530 Subject: [PATCH 21/88] feat: set address type modal UI --- public/static/locales/en/profile.json | 4 +- .../AddressManagment/AddressForm.tsx | 8 +- .../AddressManagement.module.scss | 77 +++++++++++++------ .../AddressManagment/AddressTypeChange.tsx | 57 ++++++++++++++ .../microComponents/SingleAddress.tsx | 37 ++++++--- 5 files changed, 144 insertions(+), 39 deletions(-) create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index fda72e7a73..0b102b9338 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -150,7 +150,9 @@ "formType": { "add": "Add Address", "edit": "Edit Address" - } + }, + "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType} Address? This will replace your current {addressType} Address.", + "confirm": "Confirm" } } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index 3d64b93cbe..2db1753b0a 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -228,7 +228,9 @@ const AddressForm = ({ }; return (
-

{tProfile(`addressManagement.formType.${formType}`)}

+

+ {tProfile(`addressManagement.formType.${formType}`)} +

) : ( -
+
)} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 943277a68d..48b93e0665 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -82,11 +82,15 @@ } // address action form +.addressActionHeader { + font-weight: 700; + font-size: $fontSixteen; +} .addressFormContainer { + min-width: 565px; display: flex; flex-direction: column; gap: 40px; - min-width: 565px; background: rgba(255, 255, 255, 1); border-radius: 16px; padding: 20px; @@ -94,26 +98,49 @@ left: 50%; top: 50%; transform: translate(-50%, -50%); - h1 { - font-weight: 700; - font-size: $fontSixteen; + .addressForm { + display: flex; + flex-direction: column; + gap: 23px; + } + .buttonContainer { + display: flex; + justify-content: space-between; + gap: 8px; + button { + min-width: 252px; + min-height: 40px; + } } } - -.addressForm { +.addrConfirmContainer { + width: 468px; display: flex; + gap: 10px; flex-direction: column; - gap: 23px; -} + background: rgba(255, 255, 255, 1); + border-radius: 16px; + padding: 20px; + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + .address { + width: 100%; + background: rgba(242, 242, 242, 0.5); + border-radius: 8px; + font-size: $fontSmall; + font-weight: 400; + padding: 24px; + } -.formButtonContainer { - display: flex; - gap: 8px; - justify-content: space-between; - .addAddressButton, - .cancelButton { - min-width: 252px; - min-height: 40px; + .buttonContainer { + display: flex; + justify-content: space-between; + button { + min-width: 206px; + min-height: 40px; + } } } @@ -121,13 +148,19 @@ .addressFormContainer { min-width: fit-content; width: 95%; + .buttonContainer { + display: flex; + flex-direction: column; + button { + width: 100%; + } + } } - .formButtonContainer { - display: flex; - flex-direction: column; - .addAddressButton, - .cancelButton { - width: 100%; + .addrConfirmContainer { + width: 95%; + .buttonContainer { + flex-direction: column; + gap: 8px; } } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx new file mode 100644 index 0000000000..7cb67733c6 --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx @@ -0,0 +1,57 @@ +import { UpdatedAddress } from '.'; +import { ADDRESS_ACTIONS } from '../../../../../utils/addressManagement'; +import styles from './AddressManagement.module.scss'; +import { useTranslations } from 'next-intl'; +import { AddressAction } from './microComponents/AddressActionMenu'; +import WebappButton from '../../../../common/WebappButton'; +import { SetState } from '../../../../common/types/common'; + +interface Props { + addressAction: AddressAction; + formattedAddress: string; + setIsModalOpen: SetState; +} + +const AddressTypeChange = ({ + addressAction, + formattedAddress, + setIsModalOpen, +}: Props) => { + const tProfile = useTranslations('Profile.addressManagement'); + const tCommon = useTranslations('Common'); + const changeAddressType = () => {}; + return ( +
+

+ {addressAction === ADDRESS_ACTIONS.SET_BILLING + ? tProfile('BillingAddress') + : tProfile('primaryAddress')} +

+

+ {tProfile('addressConfirmationMessage', { + addressType: + addressAction === ADDRESS_ACTIONS.SET_BILLING + ? 'Billing' + : 'Primary', + })} +

+

{formattedAddress}

+
+ setIsModalOpen(false)} + /> + +
+
+ ); +}; + +export default AddressTypeChange; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index 7551714af5..b781f9b34b 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -12,6 +12,7 @@ import AddressContent from './AddressContent'; import AddressActionsMenu from './AddressActionMenu'; import AddressForm from '../AddressForm'; import { ADDRESS_ACTIONS } from '../../../../../../utils/addressManagement'; +import AddressTypeChange from '../AddressTypeChange'; interface Props { userAddress: UpdatedAddress; @@ -54,18 +55,30 @@ const SingleAddress = ({ setIsModalOpen={setIsModalOpen} /> setIsModalOpen(false)}> - {addressAction === ADDRESS_ACTIONS.EDIT ? ( - - ) : ( - <> - )} + <> + {addressAction === ADDRESS_ACTIONS.EDIT ? ( + + ) : ( + <> + )} + {addressAction === ADDRESS_ACTIONS.SET_BILLING || + addressAction === ADDRESS_ACTIONS.SET_PRIMARY ? ( + + ) : ( + <> + )} +
); From 26c7cd3e73b34b5544a16acb71e71c792f512efb Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:11:02 +0530 Subject: [PATCH 22/88] feat: modify the edit address api to handle change address type --- .../AddressManagment/AddressForm.tsx | 54 ++++------------ .../AddressManagement.module.scss | 1 + .../AddressManagment/AddressTypeChange.tsx | 20 +++--- .../microComponents/SingleAddress.tsx | 62 +++++++++++++++---- 4 files changed, 74 insertions(+), 63 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index 2db1753b0a..3634e5a810 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -19,22 +19,17 @@ import SelectCountry from '../../../../common/InputTypes/AutoCompleteCountry'; import { allCountries } from '../../../../../utils/constants/countries'; import COUNTRY_ADDRESS_POSTALS from '../../../../../utils/countryZipCode'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; -import { - postAuthenticatedRequest, - putAuthenticatedRequest, -} from '../../../../../utils/apiRequests/api'; +import { postAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import { ADDRESS_TYPE, - getAddressType, validationPattern, } from '../../../../../utils/addressManagement'; import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; import AddressInput from './microComponents/AddressInput'; -import { AddressAction } from './microComponents/AddressActionMenu'; -type FormData = { +export type AddressFormData = { address: string | undefined; address2: string | null; city: string | undefined; @@ -47,8 +42,10 @@ interface Props { setIsModalOpen: SetState; setUserAddresses: SetState; userAddress?: UpdatedAddress; - addressAction?: AddressAction | null; - fetchUserAddresses?: () => Promise; + editAddress: ( + data: AddressFormData | null, + addressType: string + ) => Promise; } const geocoder = new GeocoderArcGIs( process.env.ESRI_CLIENT_SECRET @@ -60,11 +57,10 @@ const geocoder = new GeocoderArcGIs( ); const AddressForm = ({ formType, - addressAction, setIsModalOpen, setUserAddresses, userAddress, - fetchUserAddresses, + editAddress, }: Props) => { const defaultAddressDetail = { address: userAddress ? userAddress.address : '', @@ -79,7 +75,7 @@ const AddressForm = ({ setValue, reset, formState: { errors }, - } = useForm({ + } = useForm({ mode: 'onBlur', defaultValues: defaultAddressDetail, }); @@ -162,35 +158,7 @@ const AddressForm = ({ resetForm(); }; - const editAddress = async (data: FormData) => { - if (!addressAction || !userAddress) return; - setIsUploadingData(true); - const bodyToSend = { - ...data, - country, - type: getAddressType(formType, userAddress.type), - }; - try { - const res = await putAuthenticatedRequest( - tenantConfig.id, - `/app/addresses/${userAddress?.id}`, - bodyToSend, - token, - logoutUser - ); - if (res && fetchUserAddresses) { - fetchUserAddresses(); - closeModal(); - } - } catch (error) { - setIsUploadingData(false); - setErrors(handleError(error as APIError)); - } finally { - setIsUploadingData(false); - } - }; - - const addNewAddress = async (data: FormData) => { + const addNewAddress = async (data: AddressFormData) => { setIsUploadingData(true); const bodyToSend = { ...data, @@ -353,7 +321,9 @@ const AddressForm = ({ variant="primary" elementType="button" onClick={handleSubmit( - formType === 'add' ? addNewAddress : editAddress + formType === 'add' + ? addNewAddress + : (data) => editAddress(data, '') )} />
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 48b93e0665..e74c54de40 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -137,6 +137,7 @@ .buttonContainer { display: flex; justify-content: space-between; + margin-top: 40px; button { min-width: 206px; min-height: 40px; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx index 7cb67733c6..ac9fb2f654 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx @@ -1,38 +1,40 @@ -import { UpdatedAddress } from '.'; import { ADDRESS_ACTIONS } from '../../../../../utils/addressManagement'; import styles from './AddressManagement.module.scss'; import { useTranslations } from 'next-intl'; import { AddressAction } from './microComponents/AddressActionMenu'; import WebappButton from '../../../../common/WebappButton'; import { SetState } from '../../../../common/types/common'; +import { AddressFormData } from './AddressForm'; interface Props { addressAction: AddressAction; formattedAddress: string; setIsModalOpen: SetState; + editAddress: ( + data: AddressFormData | null, + addressType: string + ) => Promise; } const AddressTypeChange = ({ addressAction, formattedAddress, setIsModalOpen, + editAddress, }: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); - const changeAddressType = () => {}; + const isBillingAddress = addressAction === ADDRESS_ACTIONS.SET_BILLING; return (

- {addressAction === ADDRESS_ACTIONS.SET_BILLING + {isBillingAddress ? tProfile('BillingAddress') : tProfile('primaryAddress')}

{tProfile('addressConfirmationMessage', { - addressType: - addressAction === ADDRESS_ACTIONS.SET_BILLING - ? 'Billing' - : 'Primary', + addressType: isBillingAddress ? 'Billing' : 'Primary', })}

{formattedAddress}

@@ -47,7 +49,9 @@ const AddressTypeChange = ({ text={tProfile('confirm')} elementType="button" variant="primary" - onClick={changeAddressType} + onClick={() => + editAddress(null, isBillingAddress ? 'mailing' : 'primary') + } />
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index b781f9b34b..9d7e071f5c 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -1,18 +1,26 @@ import type { UpdatedAddress } from '..'; import type { SetState } from '../../../../../common/types/common'; import type { AddressAction } from './AddressActionMenu'; -import type { CountryCode } from '@planet-sdk/common'; +import type { APIError, CountryCode } from '@planet-sdk/common'; -import { useState } from 'react'; +import { useContext, useState } from 'react'; import { Modal } from '@mui/material'; import { useTranslations } from 'next-intl'; -import { formatAddress } from '../../../../../../utils/addressManagement'; +import { handleError } from '@planet-sdk/common'; +import { + formatAddress, + getAddressType, +} from '../../../../../../utils/addressManagement'; import styles from '../AddressManagement.module.scss'; import AddressContent from './AddressContent'; import AddressActionsMenu from './AddressActionMenu'; -import AddressForm from '../AddressForm'; +import AddressForm, { AddressFormData } from '../AddressForm'; import { ADDRESS_ACTIONS } from '../../../../../../utils/addressManagement'; import AddressTypeChange from '../AddressTypeChange'; +import { putAuthenticatedRequest } from '../../../../../../utils/apiRequests/api'; +import { useTenant } from '../../../../../common/Layout/TenantContext'; +import { useUserProps } from '../../../../../common/Layout/UserPropsContext'; +import { ErrorHandlingContext } from '../../../../../common/Layout/ErrorHandlingContext'; interface Props { userAddress: UpdatedAddress; @@ -33,6 +41,9 @@ const SingleAddress = ({ }: Props) => { const tCountry = useTranslations('Country'); const { zipCode, city, state, country, address, type } = userAddress; + const { tenantConfig } = useTenant(); + const { token, logoutUser } = useUserProps(); + const { setErrors } = useContext(ErrorHandlingContext); const countryFullForm = tCountry( country.toLowerCase() as Lowercase ); @@ -45,6 +56,35 @@ const SingleAddress = ({ countryFullForm ); + const editAddress = async ( + data: AddressFormData | null, + addressType: string + ) => { + if (!addressAction || !userAddress) return; + const bodyToSend = addressType + ? { type: addressType } + : { + ...data, + country, + type: getAddressType('edit', userAddress.type), + }; + try { + const res = await putAuthenticatedRequest( + tenantConfig.id, + `/app/addresses/${userAddress?.id}`, + bodyToSend, + token, + logoutUser + ); + if (res && fetchUserAddresses) { + fetchUserAddresses(); + setIsModalOpen(false); + } + } catch (error) { + setErrors(handleError(error as APIError)); + } + }; + return (
@@ -56,27 +96,23 @@ const SingleAddress = ({ /> setIsModalOpen(false)}> <> - {addressAction === ADDRESS_ACTIONS.EDIT ? ( + {addressAction === ADDRESS_ACTIONS.EDIT && ( - ) : ( - <> )} - {addressAction === ADDRESS_ACTIONS.SET_BILLING || - addressAction === ADDRESS_ACTIONS.SET_PRIMARY ? ( + {(addressAction === ADDRESS_ACTIONS.SET_BILLING || + addressAction === ADDRESS_ACTIONS.SET_PRIMARY) && ( - ) : ( - <> )} From 7a29a2b94fbb501ae6848effb4172ce3312ca89a Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:51:50 +0530 Subject: [PATCH 23/88] feat: component rename for better clarity --- .../AddressManagment/AddressDeleteModal.tsx | 11 +++++++++++ .../{AddressForm.tsx => AddressFormModal.tsx} | 6 ++++-- ...dressTypeChange.tsx => AddressTypeChangeModal.tsx} | 6 +++--- .../Settings/EditProfile/AddressManagment/index.tsx | 4 ++-- .../microComponents/SingleAddress.tsx | 10 ++++++---- 5 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx rename src/features/user/Settings/EditProfile/AddressManagment/{AddressForm.tsx => AddressFormModal.tsx} (98%) rename src/features/user/Settings/EditProfile/AddressManagment/{AddressTypeChange.tsx => AddressTypeChangeModal.tsx} (93%) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx new file mode 100644 index 0000000000..4372ccf570 --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx @@ -0,0 +1,11 @@ +import styles from './AddressManagement.module.scss'; + +const AddressDeleteModal = () => { + return ( +
+ <> +
+ ); +}; + +export default AddressDeleteModal; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx similarity index 98% rename from src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx index 3634e5a810..a6ece7429f 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx @@ -42,7 +42,7 @@ interface Props { setIsModalOpen: SetState; setUserAddresses: SetState; userAddress?: UpdatedAddress; - editAddress: ( + editAddress?: ( data: AddressFormData | null, addressType: string ) => Promise; @@ -323,7 +323,9 @@ const AddressForm = ({ onClick={handleSubmit( formType === 'add' ? addNewAddress - : (data) => editAddress(data, '') + : editAddress + ? (data) => editAddress(data, '') + : () => {} )} />
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx similarity index 93% rename from src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx index ac9fb2f654..e7283ad89b 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChange.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx @@ -4,7 +4,7 @@ import { useTranslations } from 'next-intl'; import { AddressAction } from './microComponents/AddressActionMenu'; import WebappButton from '../../../../common/WebappButton'; import { SetState } from '../../../../common/types/common'; -import { AddressFormData } from './AddressForm'; +import { AddressFormData } from './AddressFormModal'; interface Props { addressAction: AddressAction; @@ -16,7 +16,7 @@ interface Props { ) => Promise; } -const AddressTypeChange = ({ +const AddressTypeChangeModal = ({ addressAction, formattedAddress, setIsModalOpen, @@ -58,4 +58,4 @@ const AddressTypeChange = ({ ); }; -export default AddressTypeChange; +export default AddressTypeChangeModal; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 1e2f6bfa7a..41b0952e11 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -11,7 +11,7 @@ import AddressList from './microComponents/AddressList'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import WebappButton from '../../../../common/WebappButton'; import styles from './AddressManagement.module.scss'; -import AddressForm from './AddressForm'; +import AddressFormModal from './AddressFormModal'; import { getAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; @@ -80,7 +80,7 @@ const AddressManagement = () => { buttonClasses={styles.addNewAddressButton} /> setIsModalOpen(false)}> - setIsModalOpen(false)}> <> {addressAction === ADDRESS_ACTIONS.EDIT && ( - )} + {addressAction === ADDRESS_ACTIONS.DELETE && }
From dbdc164a23a7a134b3063d968182886d27120e25 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:56:02 +0530 Subject: [PATCH 24/88] feat: implement delete action & lift state management - add delete functionality for address entries - move isUploadingData state to parent component - refactor child components to use shared loading state --- public/static/locales/en/profile.json | 2 + .../AddressManagment/AddressDeleteModal.tsx | 31 +++++++++++++++- .../AddressManagment/AddressFormModal.tsx | 9 +++-- .../EditProfile/AddressManagment/index.tsx | 21 ++++++++--- .../microComponents/AddressList.tsx | 20 ++++++---- .../microComponents/SingleAddress.tsx | 37 ++++++++++++++++++- 6 files changed, 100 insertions(+), 20 deletions(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index 0b102b9338..88f23036e0 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -142,6 +142,7 @@ "BillingAddress": "Billing Address", "edit": "Edit", "delete": "Delete", + "deleteAddress": "Delete Address", "setAsPrimaryAddress": "Set as Primary Address", "setAsBillingAddress": "Set as Billing Address", "addNewAddress": "Add New Address", @@ -152,6 +153,7 @@ "edit": "Edit Address" }, "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType} Address? This will replace your current {addressType} Address.", + "deleteAddressConfirmationMessage": "Are you sure you want to delete this address? If you want to use it again, please add it as a new address.", "confirm": "Confirm" } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx index 4372ccf570..fc374669ac 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx @@ -1,9 +1,36 @@ +import { SetState } from '../../../../common/types/common'; +import WebappButton from '../../../../common/WebappButton'; import styles from './AddressManagement.module.scss'; +import { useTranslations } from 'next-intl'; -const AddressDeleteModal = () => { +interface Props { + setIsModalOpen: SetState; + deleteAddress: () => Promise; +} + +const AddressDeleteModal = ({ setIsModalOpen, deleteAddress }: Props) => { + const tProfile = useTranslations('Profile.addressManagement'); + const tCommon = useTranslations('Common'); return (
- <> +

+ {tProfile('deleteAddress')} +

+

{tProfile('deleteAddressConfirmationMessage')}

+
+ setIsModalOpen(false)} + /> + +
); }; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx index a6ece7429f..3ca3851373 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx @@ -46,6 +46,8 @@ interface Props { data: AddressFormData | null, addressType: string ) => Promise; + isUploadingData: boolean; + setIsUploadingData: SetState; } const geocoder = new GeocoderArcGIs( process.env.ESRI_CLIENT_SECRET @@ -55,12 +57,14 @@ const geocoder = new GeocoderArcGIs( } : {} ); -const AddressForm = ({ +const AddressFormModal = ({ formType, setIsModalOpen, setUserAddresses, userAddress, editAddress, + setIsUploadingData, + isUploadingData, }: Props) => { const defaultAddressDetail = { address: userAddress ? userAddress.address : '', @@ -93,7 +97,6 @@ const AddressForm = ({ AddressSuggestionsType[] >([]); const [inputValue, setInputValue] = useState(''); - const [isUploadingData, setIsUploadingData] = useState(false); const suggestAddress = useCallback( (value: string) => { @@ -334,4 +337,4 @@ const AddressForm = ({ ); }; -export default AddressForm; +export default AddressFormModal; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 41b0952e11..f63a7f07ca 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -4,7 +4,7 @@ import type { AddressType, } from './microComponents/AddressActionMenu'; -import { useContext, useMemo, useState } from 'react'; +import { useContext, useEffect, useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; import { Modal } from '@mui/material'; import AddressList from './microComponents/AddressList'; @@ -31,19 +31,20 @@ export interface UpdatedAddress { } export const addressType = ['primary', 'mailing', 'other']; const AddressManagement = () => { + const tProfile = useTranslations('Profile.addressManagement'); const { user, contextLoaded, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const tProfile = useTranslations('Profile.addressManagement'); - const [userAddresses, setUserAddresses] = useState( - user?.addresses - ); // need to update planet-sdk to include addresses key + + const [userAddresses, setUserAddresses] = useState([]); const [addressAction, setAddressAction] = useState( null ); const [isModalOpen, setIsModalOpen] = useState(false); + const [isUploadingData, setIsUploadingData] = useState(false); + const sortedAddresses = useMemo(() => { - return userAddresses.sort((a, b) => { + return userAddresses?.sort((a, b) => { return addressType.indexOf(a.type) - addressType.indexOf(b.type); }); }, [userAddresses]); @@ -63,6 +64,10 @@ const AddressManagement = () => { } }; + useEffect(() => { + fetchUserAddresses(); + }, []); + return ( <> { addressAction={addressAction} setAddressAction={setAddressAction} setUserAddresses={setUserAddresses} + isUploadingData={isUploadingData} + setIsUploadingData={setIsUploadingData} fetchUserAddresses={fetchUserAddresses} /> { formType="add" setIsModalOpen={setIsModalOpen} setUserAddresses={setUserAddresses} + isUploadingData={isUploadingData} + setIsUploadingData={setIsUploadingData} /> diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx index 9a0213423d..33f26c87cb 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx @@ -5,33 +5,39 @@ import type { SetState } from '../../../../../common/types/common'; import SingleAddress from './SingleAddress'; interface Props { - addresses: UpdatedAddress[]; + addresses: UpdatedAddress[] | undefined; addressAction: AddressAction | null; setAddressAction: SetState; setUserAddresses: SetState; fetchUserAddresses: () => Promise; + isUploadingData: boolean; + setIsUploadingData: SetState; } const AddressList = ({ - addresses, + fetchUserAddresses, addressAction, setAddressAction, + addresses, setUserAddresses, - fetchUserAddresses, + isUploadingData, + setIsUploadingData, }: Props) => { - const addressCount = addresses?.length; + const addressCount = addresses?.length ?? 0; return ( <> - {addresses.map((address) => ( + {addresses?.map((address) => ( ))} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index 8f97dc3491..5c547b3ace 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -17,7 +17,10 @@ import AddressActionsMenu from './AddressActionMenu'; import AddressFormModal, { AddressFormData } from '../AddressFormModal'; import { ADDRESS_ACTIONS } from '../../../../../../utils/addressManagement'; import AddressTypeChangeModal from '../AddressTypeChangeModal'; -import { putAuthenticatedRequest } from '../../../../../../utils/apiRequests/api'; +import { + deleteAuthenticatedRequest, + putAuthenticatedRequest, +} from '../../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../../common/Layout/TenantContext'; import { useUserProps } from '../../../../../common/Layout/UserPropsContext'; import { ErrorHandlingContext } from '../../../../../common/Layout/ErrorHandlingContext'; @@ -30,6 +33,8 @@ interface Props { setAddressAction: SetState; setUserAddresses: SetState; fetchUserAddresses: () => Promise; + isUploadingData: boolean; + setIsUploadingData: SetState; } const SingleAddress = ({ @@ -39,6 +44,8 @@ const SingleAddress = ({ setAddressAction, setUserAddresses, fetchUserAddresses, + isUploadingData, + setIsUploadingData, }: Props) => { const tCountry = useTranslations('Country'); const { zipCode, city, state, country, address, type } = userAddress; @@ -49,6 +56,7 @@ const SingleAddress = ({ country.toLowerCase() as Lowercase ); const [isModalOpen, setIsModalOpen] = useState(false); + const formattedAddress = formatAddress( address, zipCode, @@ -62,6 +70,7 @@ const SingleAddress = ({ addressType: string ) => { if (!addressAction || !userAddress) return; + setIsUploadingData(true); const bodyToSend = addressType ? { type: addressType } : { @@ -79,12 +88,29 @@ const SingleAddress = ({ ); if (res && fetchUserAddresses) { fetchUserAddresses(); + setIsUploadingData(false); setIsModalOpen(false); } } catch (error) { setErrors(handleError(error as APIError)); } }; + const deleteAddress = async () => { + try { + setIsUploadingData(true); + await deleteAuthenticatedRequest( + tenantConfig.id, + `/app/addresses/${userAddress?.id}`, + token, + logoutUser + ); + fetchUserAddresses(); + setIsModalOpen(false); + } catch (error) { + setIsUploadingData(false); + setErrors(handleError(error as APIError)); + } + }; return (
@@ -104,6 +130,8 @@ const SingleAddress = ({ setUserAddresses={setUserAddresses} userAddress={userAddress} editAddress={editAddress} + isUploadingData={isUploadingData} + setIsUploadingData={setIsUploadingData} /> )} {(addressAction === ADDRESS_ACTIONS.SET_BILLING || @@ -115,7 +143,12 @@ const SingleAddress = ({ editAddress={editAddress} /> )} - {addressAction === ADDRESS_ACTIONS.DELETE && } + {addressAction === ADDRESS_ACTIONS.DELETE && ( + + )}
From 3dfea1f082fc294594d2c449b5c28aff75dbd0b0 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sat, 16 Nov 2024 12:58:07 +0530 Subject: [PATCH 25/88] refactor: refactor translations, optimize address selection, and define address form types - Refactored translation key to use ICU select pattern for dynamic translations. - use useMemo to find primary, billing, address - Defined constant ADDRESS_FORM_TYPE for address form actions (add, edit) and associated type. --- public/static/locales/en/profile.json | 11 ++--- .../AddressManagment/AddressFormModal.tsx | 12 +++-- .../AddressTypeChangeModal.tsx | 44 ++++++++++++----- .../EditProfile/AddressManagment/index.tsx | 3 +- .../microComponents/AddressActionMenu.tsx | 3 ++ .../microComponents/AddressContent.tsx | 9 +--- .../microComponents/AddressList.tsx | 12 +++++ .../microComponents/SingleAddress.tsx | 49 ++++++++++++++++--- src/utils/addressManagement.ts | 14 ++++-- 9 files changed, 115 insertions(+), 42 deletions(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index 88f23036e0..e9ac006ed1 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -138,21 +138,20 @@ "addressManagement": { "address": "Address", "address2": "Address 2 (optional)", - "primaryAddress": "Primary Address", - "BillingAddress": "Billing Address", "edit": "Edit", + "editAddress": "Edit Address", "delete": "Delete", "deleteAddress": "Delete Address", - "setAsPrimaryAddress": "Set as Primary Address", - "setAsBillingAddress": "Set as Billing Address", "addNewAddress": "Add New Address", - "editAddress": "Edit Address", "saveChanges": "Save Changes", "formType": { "add": "Add Address", "edit": "Edit Address" }, - "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType} Address? This will replace your current {addressType} Address.", + "addressType": "{address, select, mailing {Billing} primary {Primary} other{}} Address", + "setAsPrimaryAddress": "Set as Primary Address", + "setAsBillingAddress": "Set as Billing Address", + "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType, select, mailing {Billing} primary {Primary} other {}} Address? {billingAddress, select, mailing {This will replace your current Billing Address.} other {}} {primaryAddress, select, primary {This will replace your current Primary Address.} other {}}", "deleteAddressConfirmationMessage": "Are you sure you want to delete this address? If you want to use it again, please add it as a new address.", "confirm": "Confirm" } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx index 3ca3851373..c2d08a4941 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressFormModal.tsx @@ -5,6 +5,7 @@ import type { import type { ExtendedCountryCode } from '../../../../common/types/country'; import type { SetState } from '../../../../common/types/common'; import type { UpdatedAddress } from '.'; +import type { AddressFormType } from './microComponents/AddressActionMenu'; import { useState, useContext, useMemo, useCallback } from 'react'; import { Controller, useForm } from 'react-hook-form'; @@ -23,6 +24,7 @@ import { postAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import { + ADDRESS_FORM_TYPE, ADDRESS_TYPE, validationPattern, } from '../../../../../utils/addressManagement'; @@ -38,7 +40,7 @@ export type AddressFormData = { }; interface Props { - formType: 'edit' | 'add'; + formType: AddressFormType; setIsModalOpen: SetState; setUserAddresses: SetState; userAddress?: UpdatedAddress; @@ -89,7 +91,8 @@ const AddressFormModal = ({ const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const userCountry = formType === 'add' ? user?.country : userAddress?.country; + const isAddAddressForm = formType === ADDRESS_FORM_TYPE.ADD_ADDRESS; + const userCountry = isAddAddressForm ? user?.country : userAddress?.country; const [country, setCountry] = useState( userCountry ?? 'DE' ); @@ -97,7 +100,6 @@ const AddressFormModal = ({ AddressSuggestionsType[] >([]); const [inputValue, setInputValue] = useState(''); - const suggestAddress = useCallback( (value: string) => { if (value.length > 3) { @@ -317,14 +319,14 @@ const AddressFormModal = ({ /> editAddress(data, '') diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx index e7283ad89b..1c8813e900 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx @@ -1,43 +1,58 @@ -import { ADDRESS_ACTIONS } from '../../../../../utils/addressManagement'; +import { ADDRESS_TYPE } from '../../../../../utils/addressManagement'; import styles from './AddressManagement.module.scss'; import { useTranslations } from 'next-intl'; -import { AddressAction } from './microComponents/AddressActionMenu'; import WebappButton from '../../../../common/WebappButton'; import { SetState } from '../../../../common/types/common'; import { AddressFormData } from './AddressFormModal'; interface Props { - addressAction: AddressAction; - formattedAddress: string; setIsModalOpen: SetState; editAddress: ( data: AddressFormData | null, addressType: string ) => Promise; + primaryAddress: string | undefined; + billingAddress: string | undefined; + isSetBillingAction: boolean; + isSetPrimaryAction: boolean; } const AddressTypeChangeModal = ({ - addressAction, - formattedAddress, setIsModalOpen, editAddress, + primaryAddress, + billingAddress, + isSetBillingAction, + isSetPrimaryAction, }: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); - const isBillingAddress = addressAction === ADDRESS_ACTIONS.SET_BILLING; return (

- {isBillingAddress - ? tProfile('BillingAddress') - : tProfile('primaryAddress')} + {tProfile('addressType', { + address: isSetPrimaryAction + ? ADDRESS_TYPE.PRIMARY + : ADDRESS_TYPE.MAILING, + })}

{tProfile('addressConfirmationMessage', { - addressType: isBillingAddress ? 'Billing' : 'Primary', + addressType: isSetBillingAction + ? ADDRESS_TYPE.MAILING + : ADDRESS_TYPE.PRIMARY, + billingAddress: + isSetBillingAction && billingAddress ? ADDRESS_TYPE.MAILING : '', + primaryAddress: + isSetPrimaryAction && primaryAddress ? ADDRESS_TYPE.PRIMARY : '', })}

-

{formattedAddress}

+ {billingAddress && isSetBillingAction && ( +

{billingAddress}

+ )} + {primaryAddress && isSetPrimaryAction && ( +

{primaryAddress}

+ )}
- editAddress(null, isBillingAddress ? 'mailing' : 'primary') + editAddress( + null, + isSetBillingAction ? ADDRESS_TYPE.MAILING : ADDRESS_TYPE.PRIMARY + ) } />
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index f63a7f07ca..a9b9706ebf 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -16,6 +16,7 @@ import { getAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import { handleError } from '@planet-sdk/common'; +import { ADDRESS_FORM_TYPE } from '../../../../../utils/addressManagement'; export interface UpdatedAddress { id: string; @@ -88,7 +89,7 @@ const AddressManagement = () => { /> setIsModalOpen(false)}> {
{type !== 'other' && ( - {tProfile( - `${ - type === ADDRESS_TYPE.PRIMARY - ? 'primaryAddress' - : 'BillingAddress' - }` - )} + {tProfile('addressType', { address: type })} )}
{userAddress}
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx index 33f26c87cb..f7c40a2a9d 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx @@ -3,6 +3,8 @@ import type { AddressAction } from './AddressActionMenu'; import type { SetState } from '../../../../../common/types/common'; import SingleAddress from './SingleAddress'; +import { useMemo } from 'react'; +import { ADDRESS_TYPE } from '../../../../../../utils/addressManagement'; interface Props { addresses: UpdatedAddress[] | undefined; @@ -24,7 +26,15 @@ const AddressList = ({ setIsUploadingData, }: Props) => { const addressCount = addresses?.length ?? 0; + const primaryAddress = useMemo( + () => addresses?.find((address) => address.type === ADDRESS_TYPE.PRIMARY), + [addresses] + ); + const billingAddress = useMemo( + () => addresses?.find((address) => address.type === ADDRESS_TYPE.MAILING), + [addresses] + ); return ( <> {addresses?.map((address) => ( @@ -38,6 +48,8 @@ const AddressList = ({ fetchUserAddresses={fetchUserAddresses} isUploadingData={isUploadingData} setIsUploadingData={setIsUploadingData} + primaryAddress={primaryAddress} + billingAddress={billingAddress} /> ))} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index 5c547b3ace..6cff110598 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -8,6 +8,7 @@ import { Modal } from '@mui/material'; import { useTranslations } from 'next-intl'; import { handleError } from '@planet-sdk/common'; import { + ADDRESS_FORM_TYPE, formatAddress, getAddressType, } from '../../../../../../utils/addressManagement'; @@ -35,6 +36,8 @@ interface Props { fetchUserAddresses: () => Promise; isUploadingData: boolean; setIsUploadingData: SetState; + primaryAddress: UpdatedAddress | undefined; + billingAddress: UpdatedAddress | undefined; } const SingleAddress = ({ @@ -46,6 +49,8 @@ const SingleAddress = ({ fetchUserAddresses, isUploadingData, setIsUploadingData, + primaryAddress, + billingAddress, }: Props) => { const tCountry = useTranslations('Country'); const { zipCode, city, state, country, address, type } = userAddress; @@ -55,6 +60,14 @@ const SingleAddress = ({ const countryFullForm = tCountry( country.toLowerCase() as Lowercase ); + const isSetBillingAction = addressAction === ADDRESS_ACTIONS.SET_BILLING; + const isSetPrimaryAction = addressAction === ADDRESS_ACTIONS.SET_PRIMARY; + const pcountryFullForm = tCountry( + primaryAddress?.country.toLowerCase() as Lowercase + ); + const bcountryFullForm = tCountry( + billingAddress?.country.toLowerCase() as Lowercase + ); const [isModalOpen, setIsModalOpen] = useState(false); const formattedAddress = formatAddress( @@ -65,6 +78,22 @@ const SingleAddress = ({ countryFullForm ); + const primaryFrmtAddress = formatAddress( + primaryAddress?.address, + primaryAddress?.zipCode, + primaryAddress?.city, + primaryAddress?.state ?? '', + pcountryFullForm + ); + + const billingFrmtAddress = formatAddress( + billingAddress?.address, + billingAddress?.zipCode, + billingAddress?.city, + billingAddress?.state ?? '', + bcountryFullForm + ); + const editAddress = async ( data: AddressFormData | null, addressType: string @@ -76,7 +105,10 @@ const SingleAddress = ({ : { ...data, country, - type: getAddressType('edit', userAddress.type), + type: getAddressType( + ADDRESS_FORM_TYPE.EDIT_ADDRESS, + userAddress.type + ), }; try { const res = await putAuthenticatedRequest( @@ -125,7 +157,7 @@ const SingleAddress = ({ <> {addressAction === ADDRESS_ACTIONS.EDIT && ( )} - {(addressAction === ADDRESS_ACTIONS.SET_BILLING || - addressAction === ADDRESS_ACTIONS.SET_PRIMARY) && ( + {(isSetBillingAction || isSetPrimaryAction) && ( )} {addressAction === ADDRESS_ACTIONS.DELETE && ( diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index 90e1878312..d1b464a310 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -1,4 +1,7 @@ -import { AddressType } from '../features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu'; +import { + AddressFormType, + AddressType, +} from '../features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu'; export const ADDRESS_TYPE = { PRIMARY: 'primary', @@ -13,6 +16,11 @@ export const ADDRESS_ACTIONS = { SET_BILLING: 'setBilling', } as const; +export const ADDRESS_FORM_TYPE = { + ADD_ADDRESS: 'add', + EDIT_ADDRESS: 'edit', +} as const; + export const formatAddress = ( address: string | undefined, zipCode: string | undefined, @@ -35,11 +43,11 @@ export const validationPattern = { }; export const getAddressType = ( - formType: 'add' | 'edit', + formType: AddressFormType, userAddressType: AddressType ) => { if ( - formType === 'edit' && + formType === ADDRESS_FORM_TYPE.EDIT_ADDRESS && (userAddressType === ADDRESS_TYPE.MAILING || userAddressType === ADDRESS_TYPE.PRIMARY) ) { From 7ea712673f55f72b52cbe305584714aedca33f22 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sun, 17 Nov 2024 14:26:15 +0530 Subject: [PATCH 26/88] refactor singleAddress component: simplify address formatting, optimize modal rendering with useMemo and useCallback" --- .../AddressTypeChangeModal.tsx | 34 ++- .../microComponents/AddressList.tsx | 13 +- .../microComponents/SingleAddress.tsx | 224 ++++++++++-------- src/utils/addressManagement.ts | 11 +- 4 files changed, 160 insertions(+), 122 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx index 1c8813e900..89e6106a73 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx @@ -1,9 +1,13 @@ -import { ADDRESS_TYPE } from '../../../../../utils/addressManagement'; +import { + ADDRESS_ACTIONS, + ADDRESS_TYPE, +} from '../../../../../utils/addressManagement'; import styles from './AddressManagement.module.scss'; import { useTranslations } from 'next-intl'; import WebappButton from '../../../../common/WebappButton'; import { SetState } from '../../../../common/types/common'; import { AddressFormData } from './AddressFormModal'; +import { AddressAction } from './microComponents/AddressActionMenu'; interface Props { setIsModalOpen: SetState; @@ -11,10 +15,9 @@ interface Props { data: AddressFormData | null, addressType: string ) => Promise; - primaryAddress: string | undefined; - billingAddress: string | undefined; - isSetBillingAction: boolean; - isSetPrimaryAction: boolean; + primaryAddress: string | null; + billingAddress: string | null; + addressAction: AddressAction; } const AddressTypeChangeModal = ({ @@ -22,11 +25,14 @@ const AddressTypeChangeModal = ({ editAddress, primaryAddress, billingAddress, - isSetBillingAction, - isSetPrimaryAction, + addressAction, }: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); + const isSetPrimaryAction = addressAction === ADDRESS_ACTIONS.SET_PRIMARY; + const isSetBillingAction = addressAction === ADDRESS_ACTIONS.SET_BILLING; + const isBillingAddressAlreadyPresent = isSetBillingAction && billingAddress; + const isPrimaryAddressAlreadyPresent = isSetPrimaryAction && primaryAddress; return (

@@ -41,16 +47,18 @@ const AddressTypeChangeModal = ({ addressType: isSetBillingAction ? ADDRESS_TYPE.MAILING : ADDRESS_TYPE.PRIMARY, - billingAddress: - isSetBillingAction && billingAddress ? ADDRESS_TYPE.MAILING : '', - primaryAddress: - isSetPrimaryAction && primaryAddress ? ADDRESS_TYPE.PRIMARY : '', + billingAddress: isBillingAddressAlreadyPresent + ? ADDRESS_TYPE.MAILING + : '', + primaryAddress: isPrimaryAddressAlreadyPresent + ? ADDRESS_TYPE.PRIMARY + : '', })}

- {billingAddress && isSetBillingAction && ( + {isBillingAddressAlreadyPresent && (

{billingAddress}

)} - {primaryAddress && isSetPrimaryAction && ( + {isPrimaryAddressAlreadyPresent && (

{primaryAddress}

)}
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx index f7c40a2a9d..da9352b61e 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx @@ -2,9 +2,12 @@ import type { UpdatedAddress } from '..'; import type { AddressAction } from './AddressActionMenu'; import type { SetState } from '../../../../../common/types/common'; -import SingleAddress from './SingleAddress'; import { useMemo } from 'react'; -import { ADDRESS_TYPE } from '../../../../../../utils/addressManagement'; +import SingleAddress from './SingleAddress'; +import { + ADDRESS_TYPE, + findAddressByType, +} from '../../../../../../utils/addressManagement'; interface Props { addresses: UpdatedAddress[] | undefined; @@ -26,13 +29,13 @@ const AddressList = ({ setIsUploadingData, }: Props) => { const addressCount = addresses?.length ?? 0; + const primaryAddress = useMemo( - () => addresses?.find((address) => address.type === ADDRESS_TYPE.PRIMARY), + () => findAddressByType(addresses, ADDRESS_TYPE.PRIMARY), [addresses] ); - const billingAddress = useMemo( - () => addresses?.find((address) => address.type === ADDRESS_TYPE.MAILING), + () => findAddressByType(addresses, ADDRESS_TYPE.MAILING), [addresses] ); return ( diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index 6cff110598..624b31c4c7 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -3,7 +3,7 @@ import type { SetState } from '../../../../../common/types/common'; import type { AddressAction } from './AddressActionMenu'; import type { APIError, CountryCode } from '@planet-sdk/common'; -import { useContext, useState } from 'react'; +import { useContext, useState, useMemo, useCallback } from 'react'; import { Modal } from '@mui/material'; import { useTranslations } from 'next-intl'; import { handleError } from '@planet-sdk/common'; @@ -36,8 +36,8 @@ interface Props { fetchUserAddresses: () => Promise; isUploadingData: boolean; setIsUploadingData: SetState; - primaryAddress: UpdatedAddress | undefined; - billingAddress: UpdatedAddress | undefined; + primaryAddress: UpdatedAddress | null; + billingAddress: UpdatedAddress | null; } const SingleAddress = ({ @@ -53,81 +53,79 @@ const SingleAddress = ({ billingAddress, }: Props) => { const tCountry = useTranslations('Country'); - const { zipCode, city, state, country, address, type } = userAddress; const { tenantConfig } = useTenant(); const { token, logoutUser } = useUserProps(); const { setErrors } = useContext(ErrorHandlingContext); - const countryFullForm = tCountry( - country.toLowerCase() as Lowercase - ); - const isSetBillingAction = addressAction === ADDRESS_ACTIONS.SET_BILLING; - const isSetPrimaryAction = addressAction === ADDRESS_ACTIONS.SET_PRIMARY; - const pcountryFullForm = tCountry( - primaryAddress?.country.toLowerCase() as Lowercase - ); - const bcountryFullForm = tCountry( - billingAddress?.country.toLowerCase() as Lowercase - ); const [isModalOpen, setIsModalOpen] = useState(false); + const { country, type } = userAddress; + const getCountryFullForm = (countryCode: string | undefined) => { + return countryCode + ? tCountry(countryCode.toLowerCase() as Lowercase) + : ''; + }; + const getFormattedAddress = (address: UpdatedAddress) => { + const { address: userAddress, zipCode, city, state, country } = address; + const countryFullForm = getCountryFullForm(country); + return formatAddress(userAddress, zipCode, city, state, countryFullForm); + }; - const formattedAddress = formatAddress( - address, - zipCode, - city, - state, - countryFullForm + const formattedAddress = useMemo( + () => getFormattedAddress(userAddress), + [userAddress] ); - - const primaryFrmtAddress = formatAddress( - primaryAddress?.address, - primaryAddress?.zipCode, - primaryAddress?.city, - primaryAddress?.state ?? '', - pcountryFullForm + const primaryFormattedAddress = useMemo( + () => (primaryAddress ? getFormattedAddress(primaryAddress) : null), + [primaryAddress] ); - - const billingFrmtAddress = formatAddress( - billingAddress?.address, - billingAddress?.zipCode, - billingAddress?.city, - billingAddress?.state ?? '', - bcountryFullForm + const billingFormattedAddress = useMemo( + () => (billingAddress ? getFormattedAddress(billingAddress) : null), + [billingAddress] ); - const editAddress = async ( - data: AddressFormData | null, - addressType: string - ) => { - if (!addressAction || !userAddress) return; - setIsUploadingData(true); - const bodyToSend = addressType - ? { type: addressType } - : { - ...data, - country, - type: getAddressType( - ADDRESS_FORM_TYPE.EDIT_ADDRESS, - userAddress.type - ), - }; - try { - const res = await putAuthenticatedRequest( - tenantConfig.id, - `/app/addresses/${userAddress?.id}`, - bodyToSend, - token, - logoutUser - ); - if (res && fetchUserAddresses) { - fetchUserAddresses(); + const editAddress = useCallback( + async (data: AddressFormData | null, addressType: string) => { + if (!addressAction || !userAddress) return; + setIsUploadingData(true); + const bodyToSend = addressType + ? { type: addressType } + : { + ...data, + country, + type: getAddressType( + ADDRESS_FORM_TYPE.EDIT_ADDRESS, + userAddress.type + ), + }; + try { + const res = await putAuthenticatedRequest( + tenantConfig.id, + `/app/addresses/${userAddress?.id}`, + bodyToSend, + token, + logoutUser + ); + if (res && fetchUserAddresses) { + fetchUserAddresses(); + } + } catch (error) { + setErrors(handleError(error as APIError)); + } finally { setIsUploadingData(false); setIsModalOpen(false); } - } catch (error) { - setErrors(handleError(error as APIError)); - } - }; - const deleteAddress = async () => { + }, + [ + addressAction, + country, + fetchUserAddresses, + logoutUser, + setErrors, + tenantConfig.id, + token, + userAddress, + ] + ); + const deleteAddress = useCallback(async () => { try { setIsUploadingData(true); await deleteAuthenticatedRequest( @@ -137,12 +135,66 @@ const SingleAddress = ({ logoutUser ); fetchUserAddresses(); - setIsModalOpen(false); } catch (error) { - setIsUploadingData(false); setErrors(handleError(error as APIError)); + } finally { + setIsModalOpen(false); + setIsUploadingData(false); } - }; + }, [ + fetchUserAddresses, + logoutUser, + setErrors, + tenantConfig.id, + token, + userAddress, + ]); + + const renderModalContent = useMemo(() => { + switch (addressAction) { + case ADDRESS_ACTIONS.EDIT: + return ( + + ); + case ADDRESS_ACTIONS.SET_BILLING: + case ADDRESS_ACTIONS.SET_PRIMARY: + return ( + + ); + case ADDRESS_ACTIONS.DELETE: + return ( + + ); + } + }, [ + addressAction, + setIsModalOpen, + editAddress, + deleteAddress, + userAddress, + isUploadingData, + setIsUploadingData, + setUserAddresses, + primaryFormattedAddress, + billingFormattedAddress, + ]); return (
@@ -154,39 +206,7 @@ const SingleAddress = ({ setIsModalOpen={setIsModalOpen} /> setIsModalOpen(false)}> - <> - {addressAction === ADDRESS_ACTIONS.EDIT && ( - - )} - {(isSetBillingAction || isSetPrimaryAction) && ( - - )} - {addressAction === ADDRESS_ACTIONS.DELETE && ( - - )} - + <>{renderModalContent}
); diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index d1b464a310..99ed700abb 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -1,4 +1,5 @@ -import { +import type { UpdatedAddress } from '../features/user/Settings/EditProfile/AddressManagment'; +import type { AddressFormType, AddressType, } from '../features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu'; @@ -33,7 +34,6 @@ export const formatAddress = ( .join(', ') .replace(/\s+/g, ' ') .trim(); - return cleanAddress; }; @@ -55,3 +55,10 @@ export const getAddressType = ( } return 'other'; }; + +export const findAddressByType = ( + addresses: UpdatedAddress[] | undefined, + type: AddressType +) => { + return addresses?.find((address) => address.type === type) || null; +}; From 1afb4262cda515d262f7c10405f7e1fb3b95c5ce Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 20 Nov 2024 11:26:00 +0530 Subject: [PATCH 27/88] refactor: modularize address management styles using scss mixins and variables - Introduced SCSS mixins for reusable flexbox layouts and modal positioning. - Centralized common variables for padding, border-radius, and colors. - Simplified and modularized styles for better readability and maintainability. - Enhanced mobile responsiveness with improved `xsPhoneView` handling. - Optimized button and container styling for consistency across components. --- .../AddressManagement.module.scss | 128 +++++++++--------- .../microComponents/AddressActionMenu.tsx | 2 +- 2 files changed, 68 insertions(+), 62 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index e74c54de40..2dcaab97f2 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -1,40 +1,62 @@ @import '../../../../../theme/theme'; -.addressContainer { +$border-radius-sm: 8px; +$border-radius-lg: 16px; +$padding-standard: 24px; + +@mixin flex-container($direction: row, $justify: space-between) { display: flex; - justify-content: space-between; + flex-direction: $direction; + justify-content: $justify; +} + +@mixin centered-absolute { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); +} + +@mixin modal-container { + @include centered-absolute; + padding: 20px; + border-radius: $border-radius-lg; + background: rgba(255, 255, 255, 1); +} + +// Base Components +.addressContainer { + @include flex-container; width: 100%; background: rgba(242, 242, 242, 0.5); - border-radius: 8px; + border-radius: $border-radius-sm; font-size: $fontSmall; font-weight: 400; - padding: 24px 10px 24px 24px; + padding: $padding-standard 10px $padding-standard $padding-standard; .address { max-width: 346px; } - .kababMenuButton { - height: 34px; - width: 34px; - border-radius: 50%; - display: flex; - justify-content: center; - align-items: center; - background-color: transparent; - cursor: pointer; - svg { - height: 20px; - width: 12px; - } +} + +.kebabMenuButton { + @include flex-container(row, center); + align-items: center; + height: 34px; + width: 34px; + border-radius: 50%; + background-color: transparent; + cursor: pointer; + svg { + height: 20px; + width: 12px; } - .kababMenuButton:hover { + &:hover { background-color: rgba(120, 120, 120, 0.1); } } .addressSubContainer { - display: flex; - flex-direction: column; - justify-content: center; + @include flex-container(column, center); gap: 16px; .addressTag { padding: 5px 10px; @@ -54,6 +76,7 @@ margin-top: 40px; } +// Address Types .primary { background: rgba(0, 122, 73, 1); } @@ -62,50 +85,41 @@ background: rgba(45, 156, 219, 1); } +// Address Actions .addressActions { min-width: 184px; cursor: pointer; padding: 2px 12px; list-style: none; .action { - font-size: 12px; + font-size: $fontXSmall; font-weight: 400; } + li { + padding: 8px 0px; + &:not(:last-child) { + border-bottom: 1px solid rgba(189, 189, 189, 1); + } + } } -.addressActions li { - padding: 8px 0px; -} - -.addressActions li:not(:last-child) { - border-bottom: 1px solid rgba(189, 189, 189, 1); -} -// address action form +// Modal Forms .addressActionHeader { font-weight: 700; font-size: $fontSixteen; } .addressFormContainer { + @include flex-container(column); + @include modal-container; min-width: 565px; - display: flex; - flex-direction: column; gap: 40px; - background: rgba(255, 255, 255, 1); - border-radius: 16px; - padding: 20px; - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); .addressForm { - display: flex; - flex-direction: column; + @include flex-container(column); gap: 23px; } .buttonContainer { - display: flex; - justify-content: space-between; + @include flex-container; gap: 8px; button { min-width: 252px; @@ -114,29 +128,21 @@ } } .addrConfirmContainer { - width: 468px; - display: flex; + @include flex-container(column); + @include modal-container; + min-width: 468px; gap: 10px; - flex-direction: column; - background: rgba(255, 255, 255, 1); - border-radius: 16px; - padding: 20px; - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); .address { width: 100%; background: rgba(242, 242, 242, 0.5); - border-radius: 8px; + border-radius: $border-radius-sm; font-size: $fontSmall; font-weight: 400; - padding: 24px; + padding: $padding-standard; } .buttonContainer { - display: flex; - justify-content: space-between; + @include flex-container; margin-top: 40px; button { min-width: 206px; @@ -145,13 +151,13 @@ } } +// Mobile style @include xsPhoneView { .addressFormContainer { min-width: fit-content; width: 95%; .buttonContainer { - display: flex; - flex-direction: column; + @include flex-container(column); button { width: 100%; } @@ -159,6 +165,7 @@ } .addrConfirmContainer { width: 95%; + min-width: fit-content; .buttonContainer { flex-direction: column; gap: 8px; @@ -169,6 +176,5 @@ // Form spinner .addressMgmtSpinner { - display: flex; - justify-content: center; + @include flex-container(row, center); } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 795bf5b8b4..d4fc404d45 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -86,7 +86,7 @@ const AddressActionsMenu = ({ return (
- Date: Wed, 20 Nov 2024 13:07:14 +0530 Subject: [PATCH 28/88] refactor: clean up address related code in edit profile component --- .../Settings/EditProfile/EditProfileForm.tsx | 174 ------------------ 1 file changed, 174 deletions(-) diff --git a/src/features/user/Settings/EditProfile/EditProfileForm.tsx b/src/features/user/Settings/EditProfile/EditProfileForm.tsx index d4c9b94055..7d2f288a45 100644 --- a/src/features/user/Settings/EditProfile/EditProfileForm.tsx +++ b/src/features/user/Settings/EditProfile/EditProfileForm.tsx @@ -7,30 +7,21 @@ import { Controller, useForm } from 'react-hook-form'; import { User } from '@planet-sdk/common/build/types/user'; import Camera from '../../../../../public/assets/images/icons/userProfileIcons/Camera'; import { putAuthenticatedRequest } from '../../../../utils/apiRequests/api'; -import COUNTRY_ADDRESS_POSTALS from '../../../../utils/countryZipCode'; import getImageUrl from '../../../../utils/getImageURL'; import { selectUserType } from '../../../../utils/selectUserType'; -import AutoCompleteCountry from '../../../common/InputTypes/AutoCompleteCountry'; import { useUserProps } from '../../../common/Layout/UserPropsContext'; import styles from './EditProfile.module.scss'; -import GeocoderArcGIS from 'geocoder-arcgis'; import { ErrorHandlingContext } from '../../../common/Layout/ErrorHandlingContext'; import { useLocale, useTranslations } from 'next-intl'; -import { allCountries } from '../../../../utils/constants/countries'; import InlineFormDisplayGroup from '../../../common/Layout/Forms/InlineFormDisplayGroup'; import { MuiAutoComplete, StyledAutoCompleteOption, } from '../../../common/InputTypes/MuiAutoComplete'; import StyledForm from '../../../common/Layout/StyledForm'; -import { - AddressSuggestionsType, - AddressType, -} from '../../../common/types/geocoder'; import { AlertColor } from '@mui/lab'; import { APIError, handleError } from '@planet-sdk/common'; import { useTenant } from '../../../common/Layout/TenantContext'; -import { ExtendedCountryCode } from '../../../common/types/country'; import Delete from '../../../../../public/assets/images/icons/manageProjects/Delete'; import CustomTooltip from '../../../common/Layout/CustomTooltip'; import NewToggleSwitch from '../../../common/InputTypes/NewToggleSwitch'; @@ -97,7 +88,6 @@ export default function EditProfileForm() { handleSubmit, control, reset, - setValue, formState: { errors }, } = useForm({ mode: 'onBlur', @@ -117,71 +107,12 @@ export default function EditProfileForm() { setSnackbarOpen(false); }; - const [country, setCountry] = React.useState( - user?.country || 'DE' - ); - React.useEffect(() => { reset(defaultProfileDetails); }, [defaultProfileDetails]); const [updatingPic, setUpdatingPic] = React.useState(false); - const [addressSugggestions, setaddressSugggestions] = React.useState< - AddressSuggestionsType[] - >([]); - const geocoder = new GeocoderArcGIS( - process.env.ESRI_CLIENT_SECRET - ? { - client_id: process.env.ESRI_CLIENT_ID, - client_secret: process.env.ESRI_CLIENT_SECRET, - } - : {} - ); - - const suggestAddress = (value: string) => { - if (value.length > 3) { - geocoder - .suggest(value, { category: 'Address', countryCode: country }) - .then((result: { suggestions: AddressSuggestionsType[] }) => { - const filterdSuggestions = result.suggestions.filter( - (suggestion: AddressSuggestionsType) => { - return !suggestion.isCollection; - } - ); - setaddressSugggestions(filterdSuggestions); - }) - .catch(console.log); - } - }; - const getAddress = (value: string) => { - geocoder - .findAddressCandidates(value, { outfields: '*' }) - .then((result: AddressType) => { - setValue('address', result.candidates[0].attributes.ShortLabel, { - shouldValidate: true, - }); - setValue('city', result.candidates[0].attributes.City, { - shouldValidate: true, - }); - setValue('zipCode', result.candidates[0].attributes.Postal, { - shouldValidate: true, - }); - setaddressSugggestions([]); - }) - .catch(console.log); - }; - - const [postalRegex, setPostalRegex] = React.useState( - COUNTRY_ADDRESS_POSTALS.filter((item) => item.abbrev === country)[0]?.postal - ); - React.useEffect(() => { - const fiteredCountry = COUNTRY_ADDRESS_POSTALS.filter( - (item) => item.abbrev === country - ); - setPostalRegex(fiteredCountry[0]?.postal); - }, [country]); - // the form values const [severity, setSeverity] = useState('success'); const [snackbarMessage, setSnackbarMessage] = useState('OK'); @@ -296,7 +227,6 @@ export default function EditProfileForm() { const bodyToSend = { ...otherData, - country: country, isPrivate: !isPublic, ...(type !== 'tpo' ? { type: type } : {}), }; @@ -321,7 +251,6 @@ export default function EditProfileForm() { } } }; - let suggestion_counter = 0; return ( @@ -514,109 +443,6 @@ export default function EditProfileForm() { )} /> )} - ( - { - suggestAddress(event.target.value); - handleChange(event); - }} - onBlur={() => { - setaddressSugggestions([]); - handleBlur(); - }} - value={value} - error={errors.address !== undefined} - helperText={ - errors.address !== undefined && errors.address.message - } - /> - )} - /> - {addressSugggestions - ? addressSugggestions.length > 0 && ( -
- {addressSugggestions.map((suggestion) => { - return ( -
{ - getAddress(suggestion['text']); - }} - className="suggestion" - > - {suggestion['text']} -
- ); - })} -
- ) - : null} - - ( - - )} - /> - ( - - )} - /> - - Date: Wed, 20 Nov 2024 13:27:08 +0530 Subject: [PATCH 29/88] refactor: minor width adjustment. --- .../EditProfile/AddressManagment/AddressManagement.module.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 2dcaab97f2..33915b536e 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -130,7 +130,7 @@ $padding-standard: 24px; .addrConfirmContainer { @include flex-container(column); @include modal-container; - min-width: 468px; + width: 468px; gap: 10px; .address { width: 100%; From 9ccd86fd1ab3f9d9929e64de48342f80a2acead8 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 21 Nov 2024 13:47:20 +0530 Subject: [PATCH 30/88] refactor: group translation resources base on their use --- public/static/locales/en/profile.json | 18 +++++++++++------- .../microComponents/AddressActionMenu.tsx | 8 ++++---- .../microComponents/AddressContent.tsx | 4 +--- .../user/Settings/EditProfile/index.tsx | 2 +- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index 8689977f3c..098e3e3704 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -136,13 +136,17 @@ } }, "addressManagement": { - "address": "Address", - "primaryAddress": "Primary Address", - "BillingAddress": "Billing Address", - "edit": "Edit", - "delete": "Delete", - "setAsPrimaryAddress": "Set as Primary Address", - "setAsBillingAddress": "Set as Billing Address", + "addressManagementTitle": "Address", + "addressTags": { + "primary": "Primary Address", + "mailing": "Billing Address" + }, + "actions": { + "edit": "Edit", + "delete": "Delete", + "setAsPrimaryAddress": "Set as Primary Address", + "setAsBillingAddress": "Set as Billing Address" + }, "addNewAddress": "Add New Address" } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 95a3acd2b0..bc965a24da 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -40,22 +40,22 @@ const AddressActionsMenu = ({ const addressActionConfig: AddressActionItem[] = [ { - label: tProfile('edit'), + label: tProfile(`actions.${ADDRESS_ACTIONS.EDIT}`), action: ADDRESS_ACTIONS.EDIT, shouldRender: true, }, { - label: tProfile('delete'), + label: tProfile(`actions.${ADDRESS_ACTIONS.DELETE}`), action: ADDRESS_ACTIONS.DELETE, shouldRender: addressCount > 1, }, { - label: tProfile('setAsPrimaryAddress'), + label: tProfile('actions.setAsPrimaryAddress'), action: ADDRESS_ACTIONS.SET_PRIMARY, shouldRender: !(type === 'mailing' || type === 'primary'), }, { - label: tProfile('setAsBillingAddress'), + label: tProfile('actions.setAsBillingAddress'), action: ADDRESS_ACTIONS.SET_BILLING, shouldRender: !(type === 'mailing' || type === 'primary'), }, diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx index 4c69a213c8..da0fbfbf63 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx @@ -11,9 +11,7 @@ const AddressContent = ({ type, userAddress }: Props) => {
{type !== 'other' && ( - {tProfile( - `${type === 'primary' ? 'primaryAddress' : 'BillingAddress'}` - )} + {tProfile(`addressTags.${type}`)} )}
{userAddress}
diff --git a/src/features/user/Settings/EditProfile/index.tsx b/src/features/user/Settings/EditProfile/index.tsx index a57537c87a..cffe70a076 100644 --- a/src/features/user/Settings/EditProfile/index.tsx +++ b/src/features/user/Settings/EditProfile/index.tsx @@ -20,7 +20,7 @@ export default function EditProfile(): ReactElement | null { From 2801e9bcdf53a364973b59ef32674a62dd670be1 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:17:11 +0530 Subject: [PATCH 31/88] refactor: avoid using multiple DashboardView in the edit profile page --- .../AddressManagement.module.scss | 7 +++++ .../EditProfile/AddressManagment/index.tsx | 28 +++++++++++-------- .../user/Settings/EditProfile/index.tsx | 12 +------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 6ebff283ca..40d061fd9a 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -1,5 +1,12 @@ @import '../../../../../theme/theme'; +.addressManagementTitle { + font-size: $fontLarge; + font-weight: 600; + margin-top: 40px; + margin-bottom: 20px; +} + .addressContainer { display: flex; justify-content: space-between; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 261f4971df..7b61c1e3fe 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -7,6 +7,7 @@ import AddressList from './microComponents/AddressList'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import WebappButton from '../../../../common/WebappButton'; import styles from './AddressManagement.module.scss'; +import CenteredContainer from '../../../../common/Layout/CenteredContainer'; export type AddressType = 'primary' | 'mailing' | 'other'; @@ -37,17 +38,22 @@ const AddressManagement = () => { return ( <> - - +

+ {tProfile('addressManagementTitle')} +

+ + + + ); }; diff --git a/src/features/user/Settings/EditProfile/index.tsx b/src/features/user/Settings/EditProfile/index.tsx index cffe70a076..25b2506bf1 100644 --- a/src/features/user/Settings/EditProfile/index.tsx +++ b/src/features/user/Settings/EditProfile/index.tsx @@ -8,7 +8,6 @@ import AddressManagement from './AddressManagment'; export default function EditProfile(): ReactElement | null { const t = useTranslations('Me'); - const tProfile = useTranslations('Profile'); return ( <> @@ -17,16 +16,7 @@ export default function EditProfile(): ReactElement | null { -
-
- - - - - + From 40eb9014e5ac9ad754a21af0f52cddb0c1f70fce Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:20:57 +0530 Subject: [PATCH 32/88] refactor: remove the stories --- .github/workflows/chromatic.yml | 1 - .../AddressManagement.module.scss | 3 +- .../stories/AddressManagement.stories.tsx | 61 ------------------- 3 files changed, 1 insertion(+), 64 deletions(-) delete mode 100644 src/features/user/Settings/EditProfile/AddressManagment/stories/AddressManagement.stories.tsx diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index e3fa311322..9f0582a914 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -11,7 +11,6 @@ on: - develop - feature/redesign-explore-btn - feature/design-projectlist-filter - - address-mgmt/single-address-story # List of jobs jobs: chromatic-deployment: diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 40d061fd9a..412a950f2e 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -3,8 +3,7 @@ .addressManagementTitle { font-size: $fontLarge; font-weight: 600; - margin-top: 40px; - margin-bottom: 20px; + margin: 40px 0 20px; } .addressContainer { diff --git a/src/features/user/Settings/EditProfile/AddressManagment/stories/AddressManagement.stories.tsx b/src/features/user/Settings/EditProfile/AddressManagment/stories/AddressManagement.stories.tsx deleted file mode 100644 index 35fc66d571..0000000000 --- a/src/features/user/Settings/EditProfile/AddressManagment/stories/AddressManagement.stories.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { addressType, type UpdatedAddress } from '..'; - -import AddressList from '../microComponents/AddressList'; - -const meta: Meta = { - title: 'AddressManagement/AddressManagement', - component: AddressList, -}; - -export default meta; -type Story = StoryObj; - -const address1: UpdatedAddress = { - address: 'Königsallee 45, Building A, Floor 3, Apartment 3C', - city: 'Düsseldorf', - zipCode: '40212', - state: 'North Rhine-Westphalia', - country: 'DE', - id: 'adr_U6sdZGo4a2rmzb1bMEw2F9PA', - type: 'primary', - name: 'primary', - address2: null, - isPrimary: true, -}; - -const address2: UpdatedAddress = { - address: 'Baker Street 221B, Building B, Floor 2, Apartment 5A', - zipCode: 'NW1 6XE', - city: 'London', - state: 'Greater London', - country: 'GB', - id: 'adr_4z4rf3oVe848vKEeC36LxWJq', - type: 'mailing', - name: 'Home', - address2: null, - isPrimary: null, -}; - -const address3: UpdatedAddress = { - address: 'Broadway 123, Suite 45', - city: 'New York', - zipCode: '10006', - state: 'New York', - country: 'US', - id: 'adr_X2sdTGo9b4qvzq1bREw3D9YZ', - type: 'other', - name: 'office', - address2: null, - isPrimary: null, -}; - -const addresses = [address1, address2, address3].sort((a, b) => { - return addressType.indexOf(a.type) - addressType.indexOf(b.type); -}); - -export const Default: Story = { - args: { - addresses: addresses, - }, -}; From d6b2a9b9aeb2809cf9cc3ade547628704454b595 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:12:43 +0530 Subject: [PATCH 33/88] refactor: rename variables --- public/static/locales/en/profile.json | 2 +- .../AddressManagment/AddressManagement.module.scss | 10 +++++----- .../EditProfile/AddressManagment/index.tsx | 14 ++++++++------ .../microComponents/AddressActionMenu.tsx | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index 098e3e3704..160f93014b 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -147,7 +147,7 @@ "setAsPrimaryAddress": "Set as Primary Address", "setAsBillingAddress": "Set as Billing Address" }, - "addNewAddress": "Add New Address" + "addAddress": "Add New Address" } } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 412a950f2e..9f5eee71ff 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -18,7 +18,7 @@ .address { max-width: 346px; } - .kababMenuButton { + .kebabMenuButton { height: 34px; width: 34px; border-radius: 50%; @@ -31,9 +31,9 @@ height: 20px; width: 12px; } - } - .kababMenuButton:hover { - background-color: rgba(120, 120, 120, 0.1); + &:hover { + background-color: rgba(120, 120, 120, 0.1); + } } } @@ -54,7 +54,7 @@ } } -.addNewAddressButton { +.addAddressButton { width: 342px; height: 40px; margin-top: 40px; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 7b61c1e3fe..31dfda558e 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -19,7 +19,7 @@ export interface UpdatedAddress extends Address { isPrimary: boolean | null; address2: string | null; } -export const addressType = ['primary', 'mailing', 'other']; +export const addressTypeOrder = ['primary', 'mailing', 'other']; const AddressManagement = () => { const { user } = useUserProps(); const tProfile = useTranslations('Profile.addressManagement'); @@ -29,10 +29,12 @@ const AddressManagement = () => { const [addressAction, setAddressAction] = useState( null ); - const openAddressForm = () => {}; + const toggleAddAddressModal = () => {}; const sortedAddresses = useMemo(() => { return userAddresses.sort((a, b) => { - return addressType.indexOf(a.type) - addressType.indexOf(b.type); + return ( + addressTypeOrder.indexOf(a.type) - addressTypeOrder.indexOf(b.type) + ); }); }, [userAddresses]); @@ -47,11 +49,11 @@ const AddressManagement = () => { setAddressAction={setAddressAction} /> diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index bc965a24da..476c56b160 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -79,7 +79,7 @@ const AddressActionsMenu = ({ return (
- Date: Thu, 21 Nov 2024 15:37:19 +0530 Subject: [PATCH 34/88] refactor: minor width adjustment for the button,address tag --- .../AddressManagment/AddressManagement.module.scss | 4 +--- .../user/Settings/EditProfile/AddressManagment/index.tsx | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 9f5eee71ff..d7bf332c67 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -44,7 +44,7 @@ gap: 16px; .addressTag { padding: 5px 10px; - max-width: 112px; + max-width: fit-content; border-radius: 6px; text-align: center; color: #fff; @@ -55,8 +55,6 @@ } .addAddressButton { - width: 342px; - height: 40px; margin-top: 40px; } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 31dfda558e..b005deaca5 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -39,7 +39,7 @@ const AddressManagement = () => { }, [userAddresses]); return ( - <> +

{tProfile('addressManagementTitle')}

@@ -56,7 +56,7 @@ const AddressManagement = () => { buttonClasses={styles.addAddressButton} /> - +
); }; From 03dc974293bac83869f20877db9cd6e79986210a Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 21 Nov 2024 20:47:14 +0530 Subject: [PATCH 35/88] refactor: minor change in styling in the form button container --- .../AddressManagment/AddressManagement.module.scss | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index c4bd3d4e2b..6791a96dda 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -54,10 +54,6 @@ } } -.addAddressButton { - margin-top: 40px; -} - .primary { background: rgba(0, 122, 73, 1); } @@ -87,9 +83,6 @@ // address action form .addressFormContainer { - display: flex; - flex-direction: column; - gap: 40px; min-width: 565px; background: rgba(255, 255, 255, 1); border-radius: 16px; @@ -108,16 +101,18 @@ display: flex; flex-direction: column; gap: 23px; + margin-top: 20px; } .formButtonContainer { display: flex; gap: 8px; justify-content: space-between; + align-items: end; + margin-top: 40px; .addAddressButton, .cancelButton { min-width: 252px; - min-height: 40px; } } From 8b7b54442e4fef2190a05d144e6de93604947bcf Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:57:33 +0530 Subject: [PATCH 36/88] refactor: extract form input's into a seperate component. --- public/static/locales/en/profile.json | 3 +- .../AddressManagment/AddressForm.tsx | 127 ++------------- .../AddressManagement.module.scss | 7 +- .../EditProfile/AddressManagment/index.tsx | 2 +- .../microComponents/AddressFormInputs.tsx | 145 ++++++++++++++++++ 5 files changed, 168 insertions(+), 116 deletions(-) create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index 0e708a8f19..224c398710 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -147,7 +147,8 @@ "setAsPrimaryAddress": "Set as Primary Address", "setAsBillingAddress": "Set as Billing Address" }, - "addAddress": "Add New Address", + "addNewAddress": "Add New Address", + "addAddress": "Add Address", "address2": "Address 2(optional)" } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index b54e9d3797..d15c9c696f 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -7,26 +7,22 @@ import type { SetState } from '../../../../common/types/common'; import type { UpdatedAddress } from '.'; import { useState, useContext, useMemo, useCallback } from 'react'; -import { Controller, useForm } from 'react-hook-form'; +import { useForm } from 'react-hook-form'; import { useTranslations } from 'next-intl'; -import { CircularProgress, TextField } from '@mui/material'; +import { CircularProgress } from '@mui/material'; import GeocoderArcGIs from 'geocoder-arcgis'; import { APIError, handleError } from '@planet-sdk/common'; import styles from './AddressManagement.module.scss'; import WebappButton from '../../../../common/WebappButton'; -import InlineFormDisplayGroup from '../../../../common/Layout/Forms/InlineFormDisplayGroup'; -import SelectCountry from '../../../../common/InputTypes/AutoCompleteCountry'; -import { allCountries } from '../../../../../utils/constants/countries'; import COUNTRY_ADDRESS_POSTALS from '../../../../../utils/countryZipCode'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import { postAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; -import { validationPattern } from '../../../../../utils/addressManagement'; import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; -import AddressInput from './microComponents/AddressInput'; +import AddressFormInputs from './microComponents/AddressFormInputs'; -type FormData = { +export type FormData = { address: string; address2: string | undefined; city: string; @@ -65,7 +61,7 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { mode: 'onBlur', defaultValues: defaultAddressDetail, }); - const t = useTranslations('EditProfile'); + const tProfile = useTranslations('Profile'); const tCommon = useTranslations('Common'); const { contextLoaded, user, token, logoutUser } = useUserProps(); @@ -182,108 +178,17 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { return (
-

{tProfile('addressManagement.addAddress')}

- - - - - ( - - )} - /> - ( - - )} - /> - - - ( - - )} - /> - - - +

{tProfile('addressManagement.addAddress')}

+ {isUploadingData ? (
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 6791a96dda..e864cbefbb 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -83,6 +83,9 @@ // address action form .addressFormContainer { + display: flex; + flex-direction: column; + gap: 40px; min-width: 565px; background: rgba(255, 255, 255, 1); border-radius: 16px; @@ -91,7 +94,7 @@ left: 50%; top: 50%; transform: translate(-50%, -50%); - h1 { + h2 { font-weight: 700; font-size: $fontSixteen; } @@ -101,7 +104,6 @@ display: flex; flex-direction: column; gap: 23px; - margin-top: 20px; } .formButtonContainer { @@ -109,7 +111,6 @@ gap: 8px; justify-content: space-between; align-items: end; - margin-top: 40px; .addAddressButton, .cancelButton { min-width: 252px; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index a74a153ffe..a572a961f0 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -52,7 +52,7 @@ const AddressManagement = () => { setAddressAction={setAddressAction} /> setIsModalOpen(true)} variant="primary" diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx new file mode 100644 index 0000000000..f85b111297 --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx @@ -0,0 +1,145 @@ +import type { Control, FieldErrors } from 'react-hook-form'; +import type { AddressSuggestionsType } from '../../../../../common/types/geocoder'; +import type { ExtendedCountryCode } from '../../../../../common/types/country'; +import type { SetState } from '../../../../../common/types/common'; + +import { TextField } from '@mui/material'; +import { useTranslations } from 'next-intl'; +import { Controller } from 'react-hook-form'; +import { validationPattern } from '../../../../../../utils/addressManagement'; +import InlineFormDisplayGroup from '../../../../../common/Layout/Forms/InlineFormDisplayGroup'; +import styles from '../AddressManagement.module.scss'; +import AddressInput from './AddressInput'; +import CountrySelect from '../../../../../common/InputTypes/AutoCompleteCountry'; +import { allCountries } from '../../../../../../utils/constants/countries'; +import { FormData } from '../AddressForm'; + +interface Props { + handleInputChange: (value: string) => void; + handleAddressSelect: (value: string) => void; + addressSuggestions: AddressSuggestionsType[]; + control: Control; + errors: FieldErrors; + postalRegex: RegExp | undefined; + country: ExtendedCountryCode | ''; + setCountry: SetState; +} + +const AddressFormInputs = ({ + handleInputChange, + handleAddressSelect, + addressSuggestions, + control, + errors, + postalRegex, + country, + setCountry, +}: Props) => { + const t = useTranslations('EditProfile'); + const tProfile = useTranslations('Profile'); + return ( +
+ + + + ( + + )} + /> + ( + + )} + /> + + + ( + + )} + /> + + + + ); +}; + +export default AddressFormInputs; From c4edd1f99185107ecf3322031cd0e17ed323dff9 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:51:51 +0530 Subject: [PATCH 37/88] refactor: renaming of helper function, render add address form conditionally --- .../AddressManagment/AddressForm.tsx | 14 +++++----- .../EditProfile/AddressManagment/index.tsx | 28 +++++++++++++------ .../microComponents/AddressActionMenu.tsx | 1 + 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index d15c9c696f..3752821511 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -31,7 +31,7 @@ export type FormData = { }; interface Props { - mode: string; + formType: string; setIsModalOpen: SetState; setUserAddresses: SetState; } @@ -43,7 +43,7 @@ const geocoder = new GeocoderArcGIs( } : {} ); -const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { +const AddressForm = ({ formType, setIsModalOpen, setUserAddresses }: Props) => { const defaultAddressDetail = { address: '', address2: '', @@ -134,12 +134,12 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { reset(defaultAddressDetail); setAddressSuggestions([]); }; - const closeModal = () => { + const handleCancel = () => { setIsModalOpen(false); resetForm(); }; - const addNewAddress = async (data: FormData) => { + const addAddress = async (data: FormData) => { setIsUploadingData(true); const bodyToSend = { ...data, @@ -157,7 +157,7 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { ); if (res) { setUserAddresses((prevAddresses) => [...prevAddresses, res]); - closeModal(); + handleCancel(); } } catch (error) { resetForm(); @@ -199,14 +199,14 @@ const AddressForm = ({ mode, setIsModalOpen, setUserAddresses }: Props) => { text={tCommon('cancel')} variant="secondary" elementType="button" - onClick={closeModal} + onClick={handleCancel} buttonClasses={styles.cancelButton} />
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index a572a961f0..0aebc0c84f 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -1,5 +1,8 @@ import type { Address } from '@planet-sdk/common'; -import type { AddressAction } from './microComponents/AddressActionMenu'; +import { + ADDRESS_ACTIONS, + type AddressAction, +} from './microComponents/AddressActionMenu'; import { useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; @@ -27,7 +30,7 @@ const AddressManagement = () => { const tProfile = useTranslations('Profile.addressManagement'); const [userAddresses, setUserAddresses] = useState( user?.addresses - ); // need to update planet-sdk to include addresses key + ); const [addressAction, setAddressAction] = useState( null ); @@ -41,6 +44,11 @@ const AddressManagement = () => { }); }, [userAddresses]); + const toggleAddAddressModal = () => { + setIsModalOpen(true); + setAddressAction(ADDRESS_ACTIONS.ADD); + }; + return (

@@ -54,17 +62,21 @@ const AddressManagement = () => { setIsModalOpen(true)} + onClick={toggleAddAddressModal} variant="primary" buttonClasses={styles.addAddressButton} /> - + <> + {addressAction === ADDRESS_ACTIONS.ADD && ( + + )} +

); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 476c56b160..68e46a0487 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -8,6 +8,7 @@ import styles from '../AddressManagement.module.scss'; export type AddressType = 'primary' | 'mailing' | 'other'; export const ADDRESS_ACTIONS = { + ADD: 'add', EDIT: 'edit', DELETE: 'delete', SET_PRIMARY: 'setPrimary', From 39b53e1e8da08899e7bc49611517c0cbcde9e99d Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:07:08 +0530 Subject: [PATCH 38/88] refactor: shift the edit form to the root component --- .../AddressManagment/AddressForm.tsx | 31 +++++++++---------- .../EditProfile/AddressManagment/index.tsx | 25 +++++++++++---- .../microComponents/AddressActionMenu.tsx | 6 ++++ .../microComponents/AddressList.tsx | 15 ++++----- .../microComponents/SingleAddress.tsx | 31 ++++--------------- src/utils/addressManagement.ts | 2 ++ 6 files changed, 54 insertions(+), 56 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index 9a0913758b..0fd68eb791 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -24,12 +24,10 @@ import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; import AddressFormInputs from './microComponents/AddressFormInputs'; -import AddressInput from './microComponents/AddressInput'; import { AddressAction } from './microComponents/AddressActionMenu'; import { ADDRESS_TYPE, getAddressType, - validationPattern, } from '../../../../../utils/addressManagement'; export type FormData = { @@ -43,8 +41,8 @@ export type FormData = { interface Props { formType: 'edit' | 'add'; setIsModalOpen: SetState; - setUserAddresses: SetState; - userAddress?: UpdatedAddress; + setUserAddresses?: SetState; + selectedAddressForAction?: UpdatedAddress | null; addressAction?: AddressAction | null; fetchUserAddresses?: () => Promise; } @@ -61,15 +59,15 @@ const AddressForm = ({ addressAction, setIsModalOpen, setUserAddresses, - userAddress, + selectedAddressForAction, fetchUserAddresses, }: Props) => { const defaultAddressDetail = { - address: userAddress ? userAddress.address : '', - address2: userAddress ? userAddress.address2 : '', - city: userAddress ? userAddress.city : '', - zipCode: userAddress ? userAddress.zipCode : '', - state: userAddress ? userAddress.state : '', + address: selectedAddressForAction ? selectedAddressForAction.address : '', + address2: selectedAddressForAction ? selectedAddressForAction.address2 : '', + city: selectedAddressForAction ? selectedAddressForAction.city : '', + zipCode: selectedAddressForAction ? selectedAddressForAction.zipCode : '', + state: selectedAddressForAction ? selectedAddressForAction.state : '', }; const { control, @@ -87,7 +85,8 @@ const AddressForm = ({ const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const userCountry = formType === 'add' ? user?.country : userAddress?.country; + const userCountry = + formType === 'add' ? user?.country : selectedAddressForAction?.country; const [country, setCountry] = useState( userCountry ?? 'DE' ); @@ -161,17 +160,17 @@ const AddressForm = ({ }; const editAddress = async (data: FormData) => { - if (!addressAction || !userAddress) return; + if (!addressAction || !selectedAddressForAction) return; setIsUploadingData(true); const bodyToSend = { ...data, country, - type: getAddressType(formType, userAddress.type), + type: getAddressType(formType, selectedAddressForAction.type), }; try { const res = await putAuthenticatedRequest( tenantConfig.id, - `/app/addresses/${userAddress?.id}`, + `/app/addresses/${selectedAddressForAction?.id}`, bodyToSend, token, logoutUser @@ -204,7 +203,7 @@ const AddressForm = ({ token, logoutUser ); - if (res) { + if (res && setUserAddresses) { setUserAddresses((prevAddresses) => [...prevAddresses, res]); handleCancel(); } @@ -226,7 +225,7 @@ const AddressForm = ({ }; return (
-

{tProfile(`addressManagement.formType.${formType}`)}

+

{tProfile(`addressManagement.formType.${formType}`)}

{ const { user, contextLoaded, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); @@ -43,6 +46,8 @@ const AddressManagement = () => { const [addressAction, setAddressAction] = useState( null ); + const [selectedAddressForAction, setSelectedAddressForAction] = + useState(null); const [isModalOpen, setIsModalOpen] = useState(false); const sortedAddresses = useMemo(() => { @@ -81,10 +86,9 @@ const AddressManagement = () => { { + )} + {addressAction === ADDRESS_ACTIONS.EDIT && ( + )} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 02acc0b8b5..66ed7b5e91 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -9,6 +9,7 @@ import { ADDRESS_ACTIONS, ADDRESS_TYPE, } from '../../../../../../utils/addressManagement'; +import { UpdatedAddress } from '..'; export type AddressType = (typeof ADDRESS_TYPE)[keyof typeof ADDRESS_TYPE]; export type AddressAction = @@ -24,6 +25,8 @@ interface Props { addressCount: number; setAddressAction: SetState; setIsModalOpen: SetState; + setSelectedAddressForAction: SetState; + userAddress: UpdatedAddress; } const AddressActionsMenu = ({ @@ -31,6 +34,8 @@ const AddressActionsMenu = ({ addressCount, setAddressAction, setIsModalOpen, + setSelectedAddressForAction, + userAddress, }: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const [popoverAnchor, setPopoverAnchor] = useState( @@ -73,6 +78,7 @@ const AddressActionsMenu = ({ }; const handleActionClick = (action: AddressAction) => { + setSelectedAddressForAction(userAddress); setIsModalOpen(true); setAddressAction(action); setPopoverAnchor(null); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx index 9a0213423d..6d96854c40 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx @@ -6,18 +6,16 @@ import SingleAddress from './SingleAddress'; interface Props { addresses: UpdatedAddress[]; - addressAction: AddressAction | null; setAddressAction: SetState; - setUserAddresses: SetState; - fetchUserAddresses: () => Promise; + setSelectedAddressForAction: SetState; + setIsModalOpen: SetState; } const AddressList = ({ addresses, - addressAction, setAddressAction, - setUserAddresses, - fetchUserAddresses, + setSelectedAddressForAction, + setIsModalOpen, }: Props) => { const addressCount = addresses?.length; @@ -28,10 +26,9 @@ const AddressList = ({ key={address.id} userAddress={address} addressCount={addressCount} - addressAction={addressAction} setAddressAction={setAddressAction} - setUserAddresses={setUserAddresses} - fetchUserAddresses={fetchUserAddresses} + setSelectedAddressForAction={setSelectedAddressForAction} + setIsModalOpen={setIsModalOpen} /> ))} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index 7551714af5..751cc548f4 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -3,39 +3,32 @@ import type { SetState } from '../../../../../common/types/common'; import type { AddressAction } from './AddressActionMenu'; import type { CountryCode } from '@planet-sdk/common'; -import { useState } from 'react'; -import { Modal } from '@mui/material'; import { useTranslations } from 'next-intl'; import { formatAddress } from '../../../../../../utils/addressManagement'; import styles from '../AddressManagement.module.scss'; import AddressContent from './AddressContent'; import AddressActionsMenu from './AddressActionMenu'; -import AddressForm from '../AddressForm'; -import { ADDRESS_ACTIONS } from '../../../../../../utils/addressManagement'; interface Props { userAddress: UpdatedAddress; addressCount: number; - addressAction: AddressAction | null; setAddressAction: SetState; - setUserAddresses: SetState; - fetchUserAddresses: () => Promise; + setSelectedAddressForAction: SetState; + setIsModalOpen: SetState; } const SingleAddress = ({ userAddress, addressCount, - addressAction, + setIsModalOpen, setAddressAction, - setUserAddresses, - fetchUserAddresses, + setSelectedAddressForAction, }: Props) => { const tCountry = useTranslations('Country'); const { zipCode, city, state, country, address, type } = userAddress; const countryFullForm = tCountry( country.toLowerCase() as Lowercase ); - const [isModalOpen, setIsModalOpen] = useState(false); const formattedAddress = formatAddress( address, zipCode, @@ -52,21 +45,9 @@ const SingleAddress = ({ addressCount={addressCount} setAddressAction={setAddressAction} setIsModalOpen={setIsModalOpen} + setSelectedAddressForAction={setSelectedAddressForAction} + userAddress={userAddress} /> - setIsModalOpen(false)}> - {addressAction === ADDRESS_ACTIONS.EDIT ? ( - - ) : ( - <> - )} -
); }; diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index ec24487fae..fb3fe372eb 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -14,6 +14,8 @@ export const ADDRESS_ACTIONS = { SET_BILLING: 'setBilling', } as const; +export const addressTypeOrder = ['primary', 'mailing', 'other']; + export const formatAddress = ( address: string | undefined, zipCode: string | undefined, From a4d058ac257f9032e825547d2b82044cdd8c2cda Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:14:52 +0530 Subject: [PATCH 39/88] feat: avoid using profile response addresses --- .../EditProfile/AddressManagment/index.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index e70742516d..c9bfd6142f 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -4,7 +4,7 @@ import type { AddressType, } from './microComponents/AddressActionMenu'; -import { useContext, useMemo, useState } from 'react'; +import { useContext, useEffect, useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; import { Modal } from '@mui/material'; import AddressList from './microComponents/AddressList'; @@ -40,9 +40,7 @@ const AddressManagement = () => { const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); const tProfile = useTranslations('Profile.addressManagement'); - const [userAddresses, setUserAddresses] = useState( - user?.addresses - ); + const [userAddresses, setUserAddresses] = useState([]); const [addressAction, setAddressAction] = useState( null ); @@ -73,12 +71,16 @@ const AddressManagement = () => { } }; + useEffect(() => { + fetchUserAddresses(); + }, []); + const toggleAddAddressModal = () => { setIsModalOpen(true); setAddressAction(ADDRESS_ACTIONS.ADD); }; - return ( + return userAddresses.length > 0 ? (

{tProfile('addressManagementTitle')} @@ -119,7 +121,7 @@ const AddressManagement = () => {

- ); + ) : null; }; export default AddressManagement; From 949f36c6be9d9172178b1ce0ce7b086338ceec69 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:43:09 +0530 Subject: [PATCH 40/88] refactor: use switch case to render modal content, remove unneeded utils. --- .../AddressManagment/AddressForm.tsx | 14 +++--- .../EditProfile/AddressManagment/index.tsx | 48 ++++++++++++------- src/utils/addressManagement.ts | 14 ------ 3 files changed, 36 insertions(+), 40 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index 0fd68eb791..979cd5bac1 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -25,10 +25,7 @@ import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingCon import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; import AddressFormInputs from './microComponents/AddressFormInputs'; import { AddressAction } from './microComponents/AddressActionMenu'; -import { - ADDRESS_TYPE, - getAddressType, -} from '../../../../../utils/addressManagement'; +import { ADDRESS_TYPE } from '../../../../../utils/addressManagement'; export type FormData = { address: string | undefined; @@ -159,13 +156,14 @@ const AddressForm = ({ resetForm(); }; - const editAddress = async (data: FormData) => { - if (!addressAction || !selectedAddressForAction) return; + const updateAddress = async (data: FormData) => { + if (!addressAction || !selectedAddressForAction || formType === 'add') + return; setIsUploadingData(true); const bodyToSend = { ...data, country, - type: getAddressType(formType, selectedAddressForAction.type), + type: selectedAddressForAction.type, }; try { const res = await putAuthenticatedRequest( @@ -258,7 +256,7 @@ const AddressForm = ({ variant="primary" elementType="button" onClick={handleSubmit( - formType === 'add' ? addAddress : editAddress + formType === 'add' ? addAddress : updateAddress )} buttonClasses={styles.addAddressButton} /> diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index c9bfd6142f..edf772e65e 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -80,6 +80,35 @@ const AddressManagement = () => { setAddressAction(ADDRESS_ACTIONS.ADD); }; + const renderModalContent = useMemo(() => { + switch (addressAction) { + case ADDRESS_ACTIONS.ADD: + return ( + + ); + case ADDRESS_ACTIONS.EDIT: + return ( + + ); + } + }, [ + addressAction, + setIsModalOpen, + setUserAddresses, + selectedAddressForAction, + fetchUserAddresses, + ]); + return userAddresses.length > 0 ? (

@@ -101,24 +130,7 @@ const AddressManagement = () => { /> - <> - {addressAction === ADDRESS_ACTIONS.ADD && ( - - )} - {addressAction === ADDRESS_ACTIONS.EDIT && ( - - )} - + <>{renderModalContent}

) : null; diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index fb3fe372eb..b7d871e6b0 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -36,17 +36,3 @@ export const validationPattern = { address: /^[\p{L}\p{N}\sß.,#/-]+$/u, cityState: /^[\p{L}\sß.,()-]+$/u, }; - -export const getAddressType = ( - formType: 'add' | 'edit', - userAddressType: AddressType -) => { - if ( - formType === 'edit' && - (userAddressType === ADDRESS_TYPE.MAILING || - userAddressType === ADDRESS_TYPE.PRIMARY) - ) { - return userAddressType; - } - return 'other'; -}; From 13311acaae89a69dea15e5dff86f05559ab00cc6 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Fri, 22 Nov 2024 20:56:31 +0530 Subject: [PATCH 41/88] refactor: shift address delete modal to the root component --- .../AddressManagment/AddressDeleteModal.tsx | 78 ++++++++++++++----- .../AddressManagment/AddressForm.tsx | 14 ++-- .../AddressManagement.module.scss | 8 +- .../AddressTypeChangeModal.tsx | 59 +++++++------- .../EditProfile/AddressManagment/index.tsx | 16 ++-- 5 files changed, 109 insertions(+), 66 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx index fc374669ac..b63f6b35de 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx @@ -1,38 +1,76 @@ +import { useContext, useState } from 'react'; +import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; +import { useTenant } from '../../../../common/Layout/TenantContext'; +import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import { SetState } from '../../../../common/types/common'; import WebappButton from '../../../../common/WebappButton'; import styles from './AddressManagement.module.scss'; import { useTranslations } from 'next-intl'; +import { deleteAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; +import { APIError, handleError } from '@planet-sdk/common'; +import { CircularProgress } from '@mui/material'; interface Props { setIsModalOpen: SetState; - deleteAddress: () => Promise; + addressId: string | undefined; + fetchUserAddresses: () => Promise; } -const AddressDeleteModal = ({ setIsModalOpen, deleteAddress }: Props) => { +const AddressDeleteModal = ({ + setIsModalOpen, + addressId, + fetchUserAddresses, +}: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); + const { contextLoaded, user, token, logoutUser } = useUserProps(); + const { tenantConfig } = useTenant(); + const { setErrors } = useContext(ErrorHandlingContext); + const [isUploadingData, setIsUploadingData] = useState(false); + + const deleteAddress = async () => { + if (!contextLoaded || !user) return; + try { + setIsUploadingData(true); + await deleteAuthenticatedRequest( + tenantConfig.id, + `/app/addresses/${addressId}`, + token, + logoutUser + ); + fetchUserAddresses(); + } catch (error) { + setErrors(handleError(error as APIError)); + } finally { + setIsModalOpen(false); + setIsUploadingData(false); + } + }; return (
-

- {tProfile('deleteAddress')} -

+

{tProfile('deleteAddress')}

{tProfile('deleteAddressConfirmationMessage')}

-
- setIsModalOpen(false)} - /> - -
+ {!isUploadingData ? ( +
+ setIsModalOpen(false)} + /> + +
+ ) : ( +
+ +
+ )}
); }; - export default AddressDeleteModal; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index 1db54c981c..d4c50130cb 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -182,10 +182,10 @@ const AddressForm = ({ handleCancel(); } } catch (error) { - setIsUploadingData(false); setErrors(handleError(error as APIError)); } finally { setIsUploadingData(false); + setIsModalOpen(false); } }; @@ -211,10 +211,10 @@ const AddressForm = ({ } } catch (error) { resetForm(); - setIsUploadingData(false); setErrors(handleError(error as APIError)); } finally { setIsUploadingData(false); + setIsModalOpen(false); } } }; @@ -238,11 +238,7 @@ const AddressForm = ({ country={country} setCountry={setCountry} /> - {isUploadingData ? ( -
- -
- ) : ( + {!isUploadingData ? (
+ ) : ( +
+ +
)}
); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 56c0d5bf99..d19c1584ec 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -82,10 +82,6 @@ } // address action form -.addressActionHeader { - font-weight: 700; - font-size: $fontSixteen; -} .addressFormContainer { min-width: 565px; display: flex; @@ -129,6 +125,10 @@ left: 50%; top: 50%; transform: translate(-50%, -50%); + h2 { + font-weight: 700; + font-size: $fontSixteen; + } .address { width: 100%; background: rgba(242, 242, 242, 0.5); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx index a201fd1038..ef47b18a88 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx @@ -14,6 +14,7 @@ import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import { useContext, useMemo, useState } from 'react'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import { APIError, CountryCode, handleError } from '@planet-sdk/common'; +import { CircularProgress } from '@mui/material'; interface Props { setIsModalOpen: SetState; @@ -78,13 +79,8 @@ const AddressTypeChangeModal = ({ token, logoutUser ); - if (res) { - fetchUserAddresses(); - setIsUploadingData(false); - setIsModalOpen(false); - } + if (res) fetchUserAddresses(); } catch (error) { - setIsUploadingData(false); setErrors(handleError(error as APIError)); } finally { setIsUploadingData(false); @@ -93,13 +89,13 @@ const AddressTypeChangeModal = ({ }; return (
-

+

{tProfile('addressType', { address: isSetPrimaryAction ? ADDRESS_TYPE.PRIMARY : ADDRESS_TYPE.MAILING, })} -

+

{tProfile('addressConfirmationMessage', { addressType: isSetBillingAction @@ -119,26 +115,33 @@ const AddressTypeChangeModal = ({ {isPrimaryAddressAlreadyPresent && (

{primaryFormattedAddress}

)} -
- setIsModalOpen(false)} - /> - - updateAddress( - addressAction === ADDRESS_ACTIONS.SET_PRIMARY - ? ADDRESS_TYPE.PRIMARY - : ADDRESS_TYPE.MAILING - ) - } - /> -
+ + {!isUploadingData ? ( +
+ setIsModalOpen(false)} + /> + + updateAddress( + addressAction === ADDRESS_ACTIONS.SET_PRIMARY + ? ADDRESS_TYPE.PRIMARY + : ADDRESS_TYPE.MAILING + ) + } + /> +
+ ) : ( +
+ +
+ )}
); }; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 8df004cb5b..c1f2e005bb 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -25,6 +25,7 @@ import { import CenteredContainer from '../../../../common/Layout/CenteredContainer'; import AddressForm from './AddressForm'; import AddressTypeChangeModal from './AddressTypeChangeModal'; +import AddressDeleteModal from './AddressDeleteModal'; export interface UpdatedAddress { id: string; @@ -123,13 +124,14 @@ const AddressManagement = () => { fetchUserAddresses={fetchUserAddresses} /> ); - // case ADDRESS_ACTIONS.DELETE: - // return ( - // - // ); + case ADDRESS_ACTIONS.DELETE: + return ( + + ); } }, [ addressAction, From b16d70543c6dc49bb442187e7e088848fd5bf2ee Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Fri, 22 Nov 2024 22:17:07 +0530 Subject: [PATCH 42/88] refactor: simplify AddressTypeConfirmationModal component --- public/static/locales/en/profile.json | 5 +- ...l.tsx => AddressTypeConfirmationModal.tsx} | 69 ++++--------------- .../EditProfile/AddressManagment/index.tsx | 32 ++++++--- .../microComponents/AddressContent.tsx | 2 +- 4 files changed, 39 insertions(+), 69 deletions(-) rename src/features/user/Settings/EditProfile/AddressManagment/{AddressTypeChangeModal.tsx => AddressTypeConfirmationModal.tsx} (61%) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index de6747a8e7..9cd7cc3b14 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -137,7 +137,7 @@ }, "addressManagement": { "addressManagementTitle": "Address", - "addressTags": { + "addressType": { "primary": "Primary Address", "mailing": "Billing Address" }, @@ -158,8 +158,7 @@ "add": "Add Address", "edit": "Edit Address" }, - "addressType": "{address, select, mailing {Billing} primary {Primary} other{}} Address", - "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType, select, mailing {Billing} primary {Primary} other {}} Address? {billingAddress, select, mailing {This will replace your current Billing Address.} other {}} {primaryAddress, select, primary {This will replace your current Primary Address.} other {}}", + "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType, select, mailing {billing} other {{addressType}}} address? {isAddressSet, select, true {This will replace your current {addressType, select, mailing {billing} other {{addressType}}} address.} other {}}", "deleteAddressConfirmationMessage": "Are you sure you want to delete this address? If you want to use it again, please add it as a new address.", "confirm": "Confirm" } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx similarity index 61% rename from src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx index ef47b18a88..65701cf0d5 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeChangeModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx @@ -1,8 +1,4 @@ -import { - ADDRESS_ACTIONS, - ADDRESS_TYPE, - formatAddress, -} from '../../../../../utils/addressManagement'; +import { formatAddress } from '../../../../../utils/addressManagement'; import styles from './AddressManagement.module.scss'; import { useTranslations } from 'next-intl'; import WebappButton from '../../../../common/WebappButton'; @@ -17,19 +13,17 @@ import { APIError, CountryCode, handleError } from '@planet-sdk/common'; import { CircularProgress } from '@mui/material'; interface Props { + type: 'primary' | 'mailing'; setIsModalOpen: SetState; - primaryAddress: UpdatedAddress | undefined; - billingAddress: UpdatedAddress | undefined; - addressAction: 'setPrimary' | 'setBilling'; + address: UpdatedAddress | undefined; selectedAddressForAction: UpdatedAddress | null; fetchUserAddresses: () => Promise; } -const AddressTypeChangeModal = ({ +const AddressTypeConfirmationModal = ({ + type, setIsModalOpen, - primaryAddress, - billingAddress, - addressAction, + address, selectedAddressForAction, fetchUserAddresses, }: Props) => { @@ -40,10 +34,6 @@ const AddressTypeChangeModal = ({ const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); const [isUploadingData, setIsUploadingData] = useState(false); - const isSetPrimaryAction = addressAction === ADDRESS_ACTIONS.SET_PRIMARY; - const isSetBillingAction = addressAction === ADDRESS_ACTIONS.SET_BILLING; - const isBillingAddressAlreadyPresent = isSetBillingAction && billingAddress; - const isPrimaryAddressAlreadyPresent = isSetPrimaryAction && primaryAddress; const getCountryFullForm = (countryCode: string | undefined) => { return countryCode @@ -56,13 +46,9 @@ const AddressTypeChangeModal = ({ return formatAddress(userAddress, zipCode, city, state, countryFullForm); }; - const primaryFormattedAddress = useMemo( - () => (primaryAddress ? getFormattedAddress(primaryAddress) : null), - [primaryAddress] - ); - const billingFormattedAddress = useMemo( - () => (billingAddress ? getFormattedAddress(billingAddress) : null), - [billingAddress] + const formattedAddress = useMemo( + () => (address ? getFormattedAddress(address) : null), + [address] ); const updateAddress = async (addressType: 'primary' | 'mailing') => { @@ -89,33 +75,14 @@ const AddressTypeChangeModal = ({ }; return (
-

- {tProfile('addressType', { - address: isSetPrimaryAction - ? ADDRESS_TYPE.PRIMARY - : ADDRESS_TYPE.MAILING, - })} -

+

{tProfile(`addressType.${type}`)}

{tProfile('addressConfirmationMessage', { - addressType: isSetBillingAction - ? ADDRESS_TYPE.MAILING - : ADDRESS_TYPE.PRIMARY, - billingAddress: isBillingAddressAlreadyPresent - ? ADDRESS_TYPE.MAILING - : '', - primaryAddress: isPrimaryAddressAlreadyPresent - ? ADDRESS_TYPE.PRIMARY - : '', + addressType: type, + isAddressSet: !!address, })}

- {isBillingAddressAlreadyPresent && ( -

{billingFormattedAddress}

- )} - {isPrimaryAddressAlreadyPresent && ( -

{primaryFormattedAddress}

- )} - + {formattedAddress &&

{formattedAddress}

} {!isUploadingData ? (
- updateAddress( - addressAction === ADDRESS_ACTIONS.SET_PRIMARY - ? ADDRESS_TYPE.PRIMARY - : ADDRESS_TYPE.MAILING - ) - } + onClick={() => updateAddress(type)} />
) : ( @@ -146,4 +107,4 @@ const AddressTypeChangeModal = ({ ); }; -export default AddressTypeChangeModal; +export default AddressTypeConfirmationModal; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index c1f2e005bb..e4e970a386 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -24,7 +24,7 @@ import { } from '../../../../../utils/addressManagement'; import CenteredContainer from '../../../../common/Layout/CenteredContainer'; import AddressForm from './AddressForm'; -import AddressTypeChangeModal from './AddressTypeChangeModal'; +import AddressTypeConfirmationModal from './AddressTypeConfirmationModal'; import AddressDeleteModal from './AddressDeleteModal'; export interface UpdatedAddress { @@ -99,7 +99,7 @@ const AddressManagement = () => { ); case ADDRESS_ACTIONS.EDIT: @@ -109,26 +109,34 @@ const AddressManagement = () => { setIsModalOpen={setIsModalOpen} addressAction={addressAction} selectedAddressForAction={selectedAddressForAction} - fetchUserAddresses={fetchUserAddresses} // to update the address list + fetchUserAddresses={fetchUserAddresses} + /> + ); + case ADDRESS_ACTIONS.DELETE: + return ( + ); - case ADDRESS_ACTIONS.SET_BILLING: case ADDRESS_ACTIONS.SET_PRIMARY: return ( - ); - case ADDRESS_ACTIONS.DELETE: + case ADDRESS_ACTIONS.SET_BILLING: return ( - ); @@ -139,6 +147,8 @@ const AddressManagement = () => { setUserAddresses, selectedAddressForAction, fetchUserAddresses, + primaryAddress, + billingAddress, ]); return userAddresses.length > 0 ? ( diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx index 2b37b776e8..f5fa163496 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx @@ -12,7 +12,7 @@ const AddressContent = ({ type, userAddress }: Props) => {
{type !== 'other' && ( - {tProfile(`addressTags.${type}`)} + {tProfile(`addressType.${type}`)} )}
{userAddress}
From dbab76a57883799aed1ae925eb86332e87e72b11 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sun, 24 Nov 2024 13:24:45 +0530 Subject: [PATCH 43/88] refactor: format address details to render address 2, minor code clean up --- .../AddressManagement.module.scss | 10 ++--- .../microComponents/AddressActionMenu.tsx | 4 +- .../microComponents/AddressContent.tsx | 22 ----------- .../microComponents/AddressDetails.tsx | 39 +++++++++++++++++++ .../microComponents/SingleAddress.tsx | 22 ++--------- 5 files changed, 49 insertions(+), 48 deletions(-) delete mode 100644 src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index d7bf332c67..974764d15f 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -15,9 +15,6 @@ font-size: $fontSmall; font-weight: 400; padding: 24px 10px 24px 24px; - .address { - max-width: 346px; - } .kebabMenuButton { height: 34px; width: 34px; @@ -37,12 +34,12 @@ } } -.addressSubContainer { +.addressDetails { display: flex; flex-direction: column; justify-content: center; gap: 16px; - .addressTag { + span { padding: 5px 10px; max-width: fit-content; border-radius: 6px; @@ -52,6 +49,9 @@ line-height: 16px; font-weight: 600; } + p { + margin-top: 2px; + } } .addAddressButton { diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 476c56b160..03579509cb 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -40,12 +40,12 @@ const AddressActionsMenu = ({ const addressActionConfig: AddressActionItem[] = [ { - label: tProfile(`actions.${ADDRESS_ACTIONS.EDIT}`), + label: tProfile(`actions.edit`), action: ADDRESS_ACTIONS.EDIT, shouldRender: true, }, { - label: tProfile(`actions.${ADDRESS_ACTIONS.DELETE}`), + label: tProfile(`actions.delete`), action: ADDRESS_ACTIONS.DELETE, shouldRender: addressCount > 1, }, diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx deleted file mode 100644 index da0fbfbf63..0000000000 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import styles from '../AddressManagement.module.scss'; -import { useTranslations } from 'next-intl'; - -interface Props { - type: 'primary' | 'mailing' | 'other'; - userAddress: string; -} -const AddressContent = ({ type, userAddress }: Props) => { - const tProfile = useTranslations('Profile.addressManagement'); - return ( -
- {type !== 'other' && ( - - {tProfile(`addressTags.${type}`)} - - )} -
{userAddress}
-
- ); -}; - -export default AddressContent; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx new file mode 100644 index 0000000000..22d7768b69 --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx @@ -0,0 +1,39 @@ +import { CountryCode } from '@planet-sdk/common'; +import { UpdatedAddress } from '..'; +import styles from '../AddressManagement.module.scss'; +import { useTranslations } from 'next-intl'; +import { useMemo } from 'react'; + +interface Props { + userAddress: UpdatedAddress; +} +const AddressDetails = ({ userAddress }: Props) => { + const { zipCode, city, state, country, address, address2, type } = + userAddress; + const tProfile = useTranslations('Profile.addressManagement'); + const tCountry = useTranslations('Country'); + const countryName = tCountry(country.toLowerCase() as Lowercase); + + const formattedAddress = useMemo(() => { + return [zipCode, city, state, countryName] + .filter(Boolean) + .join(', ') + .replace(/\s+/g, ' ') + .trim(); + }, [zipCode, city, state, countryName]); + + return ( +
+ {type !== 'other' && ( + {tProfile(`addressTags.${type}`)} + )} +
+

{address}

+ {address2 &&

{address2}

} +

{formattedAddress}

+
+
+ ); +}; + +export default AddressDetails; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index cd921f92a4..3f397bd233 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -1,12 +1,9 @@ import type { UpdatedAddress } from '..'; import type { SetState } from '../../../../../common/types/common'; import type { AddressAction } from './AddressActionMenu'; -import type { CountryCode } from '@planet-sdk/common'; -import { useTranslations } from 'next-intl'; -import { formatAddress } from '../../../../../../utils/addressManagement'; import styles from '../AddressManagement.module.scss'; -import AddressContent from './AddressContent'; +import AddressDetails from './AddressDetails'; import AddressActionsMenu from './AddressActionMenu'; interface Props { @@ -20,24 +17,11 @@ const SingleAddress = ({ addressCount, setAddressAction, }: Props) => { - const tCountry = useTranslations('Country'); - const { zipCode, city, state, country, address, type } = userAddress; - const countryFullForm = tCountry( - country.toLowerCase() as Lowercase - ); - const formattedAddress = formatAddress( - address, - zipCode, - city, - state, - countryFullForm - ); - return (
- + From 77af5eb904020e737ec1167d9b961cfd10f8cb24 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:19:04 +0530 Subject: [PATCH 44/88] refactor: move type definitions to d.ts file and improve addressList layout - moved type definitions from component-level to a dedicated d.ts file for better modularity and maintainability. - wrapped address list items in a container element to group components semantically. --- src/features/common/types/profile.d.ts | 8 ++++++++ .../AddressManagment/AddressManagement.module.scss | 9 ++++++++- .../user/Settings/EditProfile/AddressManagment/index.tsx | 5 ++--- .../microComponents/AddressActionMenu.tsx | 8 ++++---- .../AddressManagment/microComponents/AddressDetails.tsx | 9 +++++---- .../AddressManagment/microComponents/AddressList.tsx | 7 ++++--- .../AddressManagment/microComponents/SingleAddress.tsx | 4 ++-- 7 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/features/common/types/profile.d.ts b/src/features/common/types/profile.d.ts index 1ae18f5c07..dfbb1b189c 100644 --- a/src/features/common/types/profile.d.ts +++ b/src/features/common/types/profile.d.ts @@ -1,6 +1,7 @@ import { User, UserPublicProfile } from '@planet-sdk/common'; import { SetState } from './common'; import { PublicUser } from './user'; +import { ADDRESS_ACTIONS } from '../../user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu'; export interface UserFeaturesProps { handleShare: () => void; @@ -25,3 +26,10 @@ export type PublicProfileV2Props = { }; export type ProfileV2Props = PrivateProfileV2Props | PublicProfileV2Props; + +// address management + +export type AddressAction = + (typeof ADDRESS_ACTIONS)[keyof typeof ADDRESS_ACTIONS]; + +export type AddressType = 'primary' | 'mailing' | 'other'; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 974764d15f..efef5b7dc1 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -6,7 +6,14 @@ margin: 40px 0 20px; } -.addressContainer { +.addressListContainer { + display: flex; + flex-direction: column; + gap: 16px; + width: 100%; +} + +.singleAddressContainer { display: flex; justify-content: space-between; width: 100%; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index b005deaca5..3ae01d46f8 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -1,5 +1,6 @@ import type { Address } from '@planet-sdk/common'; -import type { AddressAction } from './microComponents/AddressActionMenu'; +import type { AddressAction } from '../../../../common/types/profile'; +import type { AddressType } from '../../../../common/types/profile'; import { useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; @@ -9,8 +10,6 @@ import WebappButton from '../../../../common/WebappButton'; import styles from './AddressManagement.module.scss'; import CenteredContainer from '../../../../common/Layout/CenteredContainer'; -export type AddressType = 'primary' | 'mailing' | 'other'; - export interface UpdatedAddress extends Address { id: string; type: AddressType; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 03579509cb..e128d1597c 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -1,4 +1,8 @@ import type { SetState } from '../../../../../common/types/common'; +import type { + AddressAction, + AddressType, +} from '../../../../../common/types/profile'; import { useState } from 'react'; import { useTranslations } from 'next-intl'; @@ -6,7 +10,6 @@ import { Popover } from '@mui/material'; import KababMenuIcon from '../../../../../../../public/assets/images/icons/KababMenuIcon'; import styles from '../AddressManagement.module.scss'; -export type AddressType = 'primary' | 'mailing' | 'other'; export const ADDRESS_ACTIONS = { EDIT: 'edit', DELETE: 'delete', @@ -14,9 +17,6 @@ export const ADDRESS_ACTIONS = { SET_BILLING: 'setBilling', } as const; -export type AddressAction = - (typeof ADDRESS_ACTIONS)[keyof typeof ADDRESS_ACTIONS]; - export interface AddressActionItem { label: string; action: AddressAction; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx index 22d7768b69..1e12bc3222 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx @@ -1,8 +1,9 @@ -import { CountryCode } from '@planet-sdk/common'; -import { UpdatedAddress } from '..'; -import styles from '../AddressManagement.module.scss'; -import { useTranslations } from 'next-intl'; +import type { CountryCode } from '@planet-sdk/common'; +import type { UpdatedAddress } from '..'; + import { useMemo } from 'react'; +import { useTranslations } from 'next-intl'; +import styles from '../AddressManagement.module.scss'; interface Props { userAddress: UpdatedAddress; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx index b13823fcad..8b8d449797 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx @@ -1,8 +1,9 @@ import type { UpdatedAddress } from '..'; -import type { AddressAction } from './AddressActionMenu'; +import type { AddressAction } from '../../../../../common/types/profile'; import type { SetState } from '../../../../../common/types/common'; import SingleAddress from './SingleAddress'; +import styles from '../AddressManagement.module.scss'; interface Props { addresses: UpdatedAddress[]; @@ -13,7 +14,7 @@ const AddressList = ({ addresses, setAddressAction }: Props) => { const addressCount = addresses?.length; return ( - <> +
{addresses.map((address) => ( { setAddressAction={setAddressAction} /> ))} - +
); }; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index 3f397bd233..37615aefa2 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -1,6 +1,6 @@ import type { UpdatedAddress } from '..'; import type { SetState } from '../../../../../common/types/common'; -import type { AddressAction } from './AddressActionMenu'; +import type { AddressAction } from '../../../../../common/types/profile'; import styles from '../AddressManagement.module.scss'; import AddressDetails from './AddressDetails'; @@ -18,7 +18,7 @@ const SingleAddress = ({ setAddressAction, }: Props) => { return ( -
+
Date: Sun, 24 Nov 2024 17:32:00 +0530 Subject: [PATCH 45/88] refactor: resolve merge conflicts --- package.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package.json b/package.json index 0c93a0eed0..e53e2ad4be 100644 --- a/package.json +++ b/package.json @@ -25,11 +25,7 @@ "prepare": "node ./husky-prepare.js" }, "validate-branch-name": { -<<<<<<< HEAD "pattern": "^(main|develop){1}$|^(feature|hotfix|address-mgmt)/[a-z0-9-_]+$", -======= - "pattern": "^(main|develop){1}$|^(feature|hotfix|projects-redesign)/[a-z0-9-_]+$", ->>>>>>> develop "errorMsg": "Invalid branch name. \n 1.Branch names can contain lowercase characters, numbers, hyphen and underscore. \n 2.Except for 'main' and 'develop', branch names must begin with 'feature/' or 'hotfix/' " }, "engines": { From 93cd55538dfc0f02b2bfd71ceccc29fcda1c8f1b Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:39:37 +0530 Subject: [PATCH 46/88] refactor: use user address type from planet-sdk/common --- .../Settings/EditProfile/AddressManagment/index.tsx | 11 +---------- .../microComponents/AddressDetails.tsx | 5 ++--- .../AddressManagment/microComponents/AddressList.tsx | 4 ++-- .../microComponents/SingleAddress.tsx | 4 ++-- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 3ae01d46f8..c52f6e4d7a 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -1,6 +1,5 @@ import type { Address } from '@planet-sdk/common'; import type { AddressAction } from '../../../../common/types/profile'; -import type { AddressType } from '../../../../common/types/profile'; import { useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; @@ -10,19 +9,11 @@ import WebappButton from '../../../../common/WebappButton'; import styles from './AddressManagement.module.scss'; import CenteredContainer from '../../../../common/Layout/CenteredContainer'; -export interface UpdatedAddress extends Address { - id: string; - type: AddressType; - name: string | null; - state: string | null; - isPrimary: boolean | null; - address2: string | null; -} export const addressTypeOrder = ['primary', 'mailing', 'other']; const AddressManagement = () => { const { user } = useUserProps(); const tProfile = useTranslations('Profile.addressManagement'); - const [userAddresses, setUserAddresses] = useState( + const [userAddresses, setUserAddresses] = useState( user?.addresses ); // need to update planet-sdk to include addresses key const [addressAction, setAddressAction] = useState( diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx index 1e12bc3222..d6d8429ac1 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx @@ -1,12 +1,11 @@ -import type { CountryCode } from '@planet-sdk/common'; -import type { UpdatedAddress } from '..'; +import type { CountryCode, Address } from '@planet-sdk/common'; import { useMemo } from 'react'; import { useTranslations } from 'next-intl'; import styles from '../AddressManagement.module.scss'; interface Props { - userAddress: UpdatedAddress; + userAddress: Address; } const AddressDetails = ({ userAddress }: Props) => { const { zipCode, city, state, country, address, address2, type } = diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx index 8b8d449797..5c6fd68cb9 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx @@ -1,12 +1,12 @@ -import type { UpdatedAddress } from '..'; import type { AddressAction } from '../../../../../common/types/profile'; import type { SetState } from '../../../../../common/types/common'; +import type { Address } from '@planet-sdk/common'; import SingleAddress from './SingleAddress'; import styles from '../AddressManagement.module.scss'; interface Props { - addresses: UpdatedAddress[]; + addresses: Address[]; setAddressAction: SetState; } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index 37615aefa2..8890e8f6c6 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -1,13 +1,13 @@ -import type { UpdatedAddress } from '..'; import type { SetState } from '../../../../../common/types/common'; import type { AddressAction } from '../../../../../common/types/profile'; +import type { Address } from '@planet-sdk/common'; import styles from '../AddressManagement.module.scss'; import AddressDetails from './AddressDetails'; import AddressActionsMenu from './AddressActionMenu'; interface Props { - userAddress: UpdatedAddress; + userAddress: Address; addressCount: number; setAddressAction: SetState; } From 69701c7335a6b5bf297ef84f57862e0c6a0e0765 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:48:48 +0530 Subject: [PATCH 47/88] refactor: corrected typo: "kabab" to "kebab" across all affected files, - use AddressType from the planet-sdk/common --- .../icons/{KababMenuIcon.tsx => KebabMenuIcon.tsx} | 4 ++-- src/features/common/types/profile.d.ts | 2 -- .../microComponents/AddressActionMenu.tsx | 10 ++++------ 3 files changed, 6 insertions(+), 10 deletions(-) rename public/assets/images/icons/{KababMenuIcon.tsx => KebabMenuIcon.tsx} (83%) diff --git a/public/assets/images/icons/KababMenuIcon.tsx b/public/assets/images/icons/KebabMenuIcon.tsx similarity index 83% rename from public/assets/images/icons/KababMenuIcon.tsx rename to public/assets/images/icons/KebabMenuIcon.tsx index cbb0f1501d..06232b4e03 100644 --- a/public/assets/images/icons/KababMenuIcon.tsx +++ b/public/assets/images/icons/KebabMenuIcon.tsx @@ -1,4 +1,4 @@ -const KababMenuIcon = () => { +const KebabMenuIcon = () => { return ( @@ -8,4 +8,4 @@ const KababMenuIcon = () => { ); }; -export default KababMenuIcon; +export default KebabMenuIcon; diff --git a/src/features/common/types/profile.d.ts b/src/features/common/types/profile.d.ts index dfbb1b189c..4076af85c9 100644 --- a/src/features/common/types/profile.d.ts +++ b/src/features/common/types/profile.d.ts @@ -31,5 +31,3 @@ export type ProfileV2Props = PrivateProfileV2Props | PublicProfileV2Props; export type AddressAction = (typeof ADDRESS_ACTIONS)[keyof typeof ADDRESS_ACTIONS]; - -export type AddressType = 'primary' | 'mailing' | 'other'; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index e128d1597c..11c551186c 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -1,13 +1,11 @@ import type { SetState } from '../../../../../common/types/common'; -import type { - AddressAction, - AddressType, -} from '../../../../../common/types/profile'; +import type { AddressAction } from '../../../../../common/types/profile'; +import type { AddressType } from '@planet-sdk/common'; import { useState } from 'react'; import { useTranslations } from 'next-intl'; import { Popover } from '@mui/material'; -import KababMenuIcon from '../../../../../../../public/assets/images/icons/KababMenuIcon'; +import KebabMenuIcon from '../../../../../../../public/assets/images/icons/KebabMenuIcon'; import styles from '../AddressManagement.module.scss'; export const ADDRESS_ACTIONS = { @@ -80,7 +78,7 @@ const AddressActionsMenu = ({ return (
Date: Mon, 25 Nov 2024 12:24:41 +0530 Subject: [PATCH 48/88] refactor: simplify address formatting logic, --- .../AddressTypeConfirmationModal.tsx | 61 ++++++++++--------- .../EditProfile/AddressManagment/index.tsx | 21 ++++--- .../microComponents/AddressDetails.tsx | 13 ++-- src/utils/addressManagement.ts | 9 ++- 4 files changed, 53 insertions(+), 51 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx index c0c82afa07..051973b925 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx @@ -1,30 +1,30 @@ import type { SetState } from '../../../../common/types/common'; import type { APIError, CountryCode, Address } from '@planet-sdk/common'; -import { formatAddress } from '../../../../../utils/addressManagement'; -import styles from './AddressManagement.module.scss'; +import { useContext, useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; +import { handleError } from '@planet-sdk/common'; +import { CircularProgress } from '@mui/material'; +import styles from './AddressManagement.module.scss'; import WebappButton from '../../../../common/WebappButton'; import { putAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; -import { useContext, useMemo, useState } from 'react'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; -import { handleError } from '@planet-sdk/common'; -import { CircularProgress } from '@mui/material'; +import { getFormattedAddress } from '../../../../../utils/addressManagement'; interface Props { - type: 'primary' | 'mailing'; + mode: 'primary' | 'mailing'; setIsModalOpen: SetState; - address: Address | undefined; + userAddress: Address | undefined; selectedAddressForAction: Address | null; fetchUserAddresses: () => Promise; } const AddressTypeConfirmationModal = ({ - type, + mode, setIsModalOpen, - address, + userAddress, selectedAddressForAction, fetchUserAddresses, }: Props) => { @@ -35,23 +35,20 @@ const AddressTypeConfirmationModal = ({ const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); const [isUploadingData, setIsUploadingData] = useState(false); - - const getCountryFullForm = (countryCode: string | undefined) => { - return countryCode - ? tCountry(countryCode.toLowerCase() as Lowercase) - : ''; - }; - const getFormattedAddress = (address: Address) => { - const { address: userAddress, zipCode, city, state, country } = address; - const countryFullForm = getCountryFullForm(country); - return formatAddress(userAddress, zipCode, city, state, countryFullForm); - }; + const countryName = tCountry( + userAddress?.country.toLowerCase() as Lowercase + ); const formattedAddress = useMemo( - () => (address ? getFormattedAddress(address) : null), - [address] + () => + getFormattedAddress( + userAddress?.zipCode, + userAddress?.city, + userAddress?.state, + countryName + ), + [userAddress, countryName] ); - const updateAddress = async (addressType: 'primary' | 'mailing') => { if (!contextLoaded || !user) return; setIsUploadingData(true); @@ -76,14 +73,22 @@ const AddressTypeConfirmationModal = ({ }; return (
-

{tProfile(`addressType.${type}`)}

+

{tProfile(`addressType.${mode}`)}

{tProfile('addressConfirmationMessage', { - addressType: type, - isAddressSet: !!address, + addressType: mode, + isAddressSet: !!userAddress, })}

- {formattedAddress &&

{formattedAddress}

} + {userAddress && ( +
+
+

{userAddress?.address}

+ {userAddress?.address2 &&

{userAddress?.address2}

} +

{formattedAddress}

+
+
+ )} {!isUploadingData ? (
updateAddress(type)} + onClick={() => updateAddress(mode)} />
) : ( diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 2dab7bf3da..faba27f203 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -76,6 +76,11 @@ const AddressManagement = () => { () => findAddressByType(userAddresses, ADDRESS_TYPE.MAILING), [userAddresses] ); + const addrTypeConfProps = { + setIsModalOpen, + selectedAddressForAction, + fetchUserAddresses, + }; const renderModalContent = useMemo(() => { switch (addressAction) { case ADDRESS_ACTIONS.ADD: @@ -107,21 +112,17 @@ const AddressManagement = () => { case ADDRESS_ACTIONS.SET_PRIMARY: return ( ); case ADDRESS_ACTIONS.SET_BILLING: return ( ); } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx index a92872fcb1..4c434b21f1 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx @@ -3,6 +3,7 @@ import type { CountryCode, Address } from '@planet-sdk/common'; import { useMemo } from 'react'; import { useTranslations } from 'next-intl'; import styles from '../AddressManagement.module.scss'; +import { getFormattedAddress } from '../../../../../../utils/addressManagement'; interface Props { userAddress: Address; @@ -14,14 +15,10 @@ const AddressDetails = ({ userAddress }: Props) => { const tCountry = useTranslations('Country'); const countryName = tCountry(country.toLowerCase() as Lowercase); - const formattedAddress = useMemo(() => { - return [zipCode, city, state, countryName] - .filter(Boolean) - .join(', ') - .replace(/\s+/g, ' ') - .trim(); - }, [zipCode, city, state, countryName]); - + const formattedAddress = useMemo( + () => getFormattedAddress(zipCode, city, state, countryName), + [zipCode, city, state, countryName] + ); return (
{type !== 'other' && ( diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index 84bd43ec4d..b90462b12d 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -20,14 +20,13 @@ export const ADDRESS_FORM_TYPE = { } as const; export const addressTypeOrder = ['primary', 'mailing', 'other']; -export const formatAddress = ( - address: string | undefined, +export const getFormattedAddress = ( zipCode: string | undefined, city: string | undefined, - state: string | null, - country: string + state: string | null | undefined, + countryName: string ) => { - const cleanAddress = [address, `${zipCode} ${city}`, state, country] + const cleanAddress = [zipCode, city, state, countryName] .filter(Boolean) .join(', ') .replace(/\s+/g, ' ') From df3db6911c825d2040ace25c8478c932b94a616f Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Mon, 25 Nov 2024 12:45:13 +0530 Subject: [PATCH 49/88] feat: add FormattedAddressBlock component to display user address --- .../AddressTypeConfirmationModal.tsx | 26 +++-------------- .../microComponents/AddressDetails.tsx | 20 +++---------- .../microComponents/FormattedAddressBlock.tsx | 28 +++++++++++++++++++ 3 files changed, 36 insertions(+), 38 deletions(-) create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/microComponents/FormattedAddressBlock.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx index 051973b925..adb5eaad2c 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx @@ -1,7 +1,7 @@ import type { SetState } from '../../../../common/types/common'; -import type { APIError, CountryCode, Address } from '@planet-sdk/common'; +import type { APIError, Address } from '@planet-sdk/common'; -import { useContext, useMemo, useState } from 'react'; +import { useContext, useState } from 'react'; import { useTranslations } from 'next-intl'; import { handleError } from '@planet-sdk/common'; import { CircularProgress } from '@mui/material'; @@ -11,7 +11,7 @@ import { putAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; -import { getFormattedAddress } from '../../../../../utils/addressManagement'; +import FormattedAddressBlock from './microComponents/FormattedAddressBlock'; interface Props { mode: 'primary' | 'mailing'; @@ -30,25 +30,11 @@ const AddressTypeConfirmationModal = ({ }: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); - const tCountry = useTranslations('Country'); const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); const [isUploadingData, setIsUploadingData] = useState(false); - const countryName = tCountry( - userAddress?.country.toLowerCase() as Lowercase - ); - const formattedAddress = useMemo( - () => - getFormattedAddress( - userAddress?.zipCode, - userAddress?.city, - userAddress?.state, - countryName - ), - [userAddress, countryName] - ); const updateAddress = async (addressType: 'primary' | 'mailing') => { if (!contextLoaded || !user) return; setIsUploadingData(true); @@ -82,11 +68,7 @@ const AddressTypeConfirmationModal = ({

{userAddress && (
-
-

{userAddress?.address}

- {userAddress?.address2 &&

{userAddress?.address2}

} -

{formattedAddress}

-
+
)} {!isUploadingData ? ( diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx index 4c434b21f1..8670580d3e 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx @@ -1,34 +1,22 @@ -import type { CountryCode, Address } from '@planet-sdk/common'; +import type { Address } from '@planet-sdk/common'; -import { useMemo } from 'react'; import { useTranslations } from 'next-intl'; import styles from '../AddressManagement.module.scss'; -import { getFormattedAddress } from '../../../../../../utils/addressManagement'; +import FormattedAddressBlock from './FormattedAddressBlock'; interface Props { userAddress: Address; } const AddressDetails = ({ userAddress }: Props) => { - const { zipCode, city, state, country, address, address2, type } = - userAddress; + const { type } = userAddress; const tProfile = useTranslations('Profile.addressManagement'); - const tCountry = useTranslations('Country'); - const countryName = tCountry(country.toLowerCase() as Lowercase); - const formattedAddress = useMemo( - () => getFormattedAddress(zipCode, city, state, countryName), - [zipCode, city, state, countryName] - ); return (
{type !== 'other' && ( {tProfile(`addressType.${type}`)} )} -
-

{address}

- {address2 &&

{address2}

} -

{formattedAddress}

-
+
); }; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/FormattedAddressBlock.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/FormattedAddressBlock.tsx new file mode 100644 index 0000000000..ab09e0a9fa --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/FormattedAddressBlock.tsx @@ -0,0 +1,28 @@ +import type { Address, CountryCode } from '@planet-sdk/common'; + +import { useMemo } from 'react'; +import { useTranslations } from 'next-intl'; +import { getFormattedAddress } from '../../../../../../utils/addressManagement'; + +interface Props { + userAddress: Address | undefined; +} + +const FormattedAddressBlock = ({ userAddress }: Props) => { + if (!userAddress) return null; + const tCountry = useTranslations('Country'); + const { zipCode, city, state, country, address, address2 } = userAddress; + const countryName = tCountry(country.toLowerCase() as Lowercase); + const formattedAddress = useMemo( + () => getFormattedAddress(zipCode, city, state, countryName), + [zipCode, city, state, countryName] + ); + return ( +
+

{address}

+ {address2 &&

{address2}

} +

{formattedAddress}

+
+ ); +}; +export default FormattedAddressBlock; From ea0228b1017d17773d1183adeb486a927ca185ea Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:33:44 +0530 Subject: [PATCH 50/88] refactor: rename variable, and wrap the fetchUserAddresses function in useCallback --- .../AddressManagment/AddressDeleteModal.tsx | 8 ++++---- .../AddressManagment/AddressTypeConfirmationModal.tsx | 10 +++++----- .../Settings/EditProfile/AddressManagment/index.tsx | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx index 3229463b8b..1443dd6829 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx @@ -28,12 +28,12 @@ const AddressDeleteModal = ({ const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const [isUploadingData, setIsUploadingData] = useState(false); + const [isLoading, setIsLoading] = useState(false); const deleteAddress = async () => { if (!contextLoaded || !user) return; try { - setIsUploadingData(true); + setIsLoading(true); await deleteAuthenticatedRequest( tenantConfig.id, `/app/addresses/${addressId}`, @@ -45,14 +45,14 @@ const AddressDeleteModal = ({ setErrors(handleError(error as APIError)); } finally { setIsModalOpen(false); - setIsUploadingData(false); + setIsLoading(false); } }; return (

{tProfile('deleteAddress')}

{tProfile('deleteAddressConfirmationMessage')}

- {!isUploadingData ? ( + {!isLoading ? (
; userAddress: Address | undefined; selectedAddressForAction: Address | null; @@ -22,7 +22,7 @@ interface Props { } const AddressTypeConfirmationModal = ({ - mode, + addressType, setIsModalOpen, userAddress, selectedAddressForAction, @@ -59,10 +59,10 @@ const AddressTypeConfirmationModal = ({ }; return (
-

{tProfile(`addressType.${mode}`)}

+

{tProfile(`addressType.${addressType}`)}

{tProfile('addressConfirmationMessage', { - addressType: mode, + addressType, isAddressSet: !!userAddress, })}

@@ -83,7 +83,7 @@ const AddressTypeConfirmationModal = ({ text={tProfile('confirm')} elementType="button" variant="primary" - onClick={() => updateAddress(mode)} + onClick={() => updateAddress(addressType)} />
) : ( diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index faba27f203..be989a104c 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -1,7 +1,7 @@ import type { Address, APIError } from '@planet-sdk/common'; import type { AddressAction } from '../../../../common/types/profile'; -import { useContext, useEffect, useMemo, useState } from 'react'; +import { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; import { Modal } from '@mui/material'; import { handleError } from '@planet-sdk/common'; @@ -45,7 +45,7 @@ const AddressManagement = () => { }); }, [userAddresses]); - const fetchUserAddresses = async () => { + const fetchUserAddresses = useCallback(async () => { if (!user || !token || !contextLoaded) return; try { const res = await getAuthenticatedRequest( @@ -58,7 +58,7 @@ const AddressManagement = () => { } catch (error) { setErrors(handleError(error as APIError)); } - }; + }, [user, token, contextLoaded, tenantConfig.id, logoutUser]); useEffect(() => { fetchUserAddresses(); @@ -112,7 +112,7 @@ const AddressManagement = () => { case ADDRESS_ACTIONS.SET_PRIMARY: return ( @@ -120,7 +120,7 @@ const AddressManagement = () => { case ADDRESS_ACTIONS.SET_BILLING: return ( From f82fd281fbf2b6262d76cdc909758eb8299ebd7c Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:41:56 +0530 Subject: [PATCH 51/88] refactor: consistent type import --- .../Settings/EditProfile/AddressManagment/AddressForm.tsx | 8 ++++---- .../microComponents/AddressFormInputs.tsx | 2 +- .../AddressManagment/microComponents/AddressInput.tsx | 4 +++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index 3752821511..07e887155a 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -4,14 +4,13 @@ import type { } from '../../../../common/types/geocoder'; import type { ExtendedCountryCode } from '../../../../common/types/country'; import type { SetState } from '../../../../common/types/common'; -import type { UpdatedAddress } from '.'; +import type { Address, APIError } from '@planet-sdk/common'; import { useState, useContext, useMemo, useCallback } from 'react'; import { useForm } from 'react-hook-form'; import { useTranslations } from 'next-intl'; import { CircularProgress } from '@mui/material'; import GeocoderArcGIs from 'geocoder-arcgis'; -import { APIError, handleError } from '@planet-sdk/common'; import styles from './AddressManagement.module.scss'; import WebappButton from '../../../../common/WebappButton'; import COUNTRY_ADDRESS_POSTALS from '../../../../../utils/countryZipCode'; @@ -21,6 +20,7 @@ import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; import AddressFormInputs from './microComponents/AddressFormInputs'; +import { handleError } from '@planet-sdk/common'; export type FormData = { address: string; @@ -33,7 +33,7 @@ export type FormData = { interface Props { formType: string; setIsModalOpen: SetState; - setUserAddresses: SetState; + setUserAddresses: SetState; } const geocoder = new GeocoderArcGIs( process.env.ESRI_CLIENT_SECRET @@ -148,7 +148,7 @@ const AddressForm = ({ formType, setIsModalOpen, setUserAddresses }: Props) => { }; if (contextLoaded && user) { try { - const res = await postAuthenticatedRequest( + const res = await postAuthenticatedRequest
( tenantConfig.id, '/app/addresses', bodyToSend, diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx index f85b111297..419efa6f83 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx @@ -2,6 +2,7 @@ import type { Control, FieldErrors } from 'react-hook-form'; import type { AddressSuggestionsType } from '../../../../../common/types/geocoder'; import type { ExtendedCountryCode } from '../../../../../common/types/country'; import type { SetState } from '../../../../../common/types/common'; +import type { FormData } from '../AddressForm'; import { TextField } from '@mui/material'; import { useTranslations } from 'next-intl'; @@ -12,7 +13,6 @@ import styles from '../AddressManagement.module.scss'; import AddressInput from './AddressInput'; import CountrySelect from '../../../../../common/InputTypes/AutoCompleteCountry'; import { allCountries } from '../../../../../../utils/constants/countries'; -import { FormData } from '../AddressForm'; interface Props { handleInputChange: (value: string) => void; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressInput.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressInput.tsx index fd4033ffaa..233943407d 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressInput.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressInput.tsx @@ -1,5 +1,7 @@ +import type { Control } from 'react-hook-form'; + import { Autocomplete, TextField } from '@mui/material'; -import { Control, Controller } from 'react-hook-form'; +import { Controller } from 'react-hook-form'; interface AddressOption { text: string; From 830164850e39b78ee329ceefb29027a36ae5e4f3 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:03:24 +0530 Subject: [PATCH 52/88] refactor: remove duplicate import --- .../AddressManagment/microComponents/AddressFormInputs.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx index 2cb80816a3..489ed1a9d1 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx @@ -3,7 +3,6 @@ import type { AddressSuggestionsType } from '../../../../../common/types/geocode import type { ExtendedCountryCode } from '../../../../../common/types/country'; import type { FormData } from '../AddressForm'; import type { SetState } from '../../../../../common/types/common'; -import type { FormData } from '../AddressForm'; import { TextField } from '@mui/material'; import { useTranslations } from 'next-intl'; From ceae2b303233e46bae686be18d9c5a4cadbed273 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:40:51 +0530 Subject: [PATCH 53/88] refactor: seperate out edit address form. - move the geocoder logic into utils file --- .../AddressManagment/AddressForm.tsx | 2 - .../AddressManagment/EditAddressForm.tsx | 197 ++++++++++++++++++ .../EditProfile/AddressManagment/index.tsx | 5 +- src/utils/addressManagement.ts | 64 ++++++ 4 files changed, 263 insertions(+), 5 deletions(-) create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx index 28020167f5..e0ed76391e 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx @@ -36,7 +36,6 @@ export type FormData = { }; interface Props { - formType: 'edit' | 'add'; setIsModalOpen: SetState; setUserAddresses?: SetState; selectedAddressForAction?: Address | null; @@ -52,7 +51,6 @@ const geocoder = new GeocoderArcGIs( : {} ); const AddressForm = ({ - formType, addressAction, setIsModalOpen, setUserAddresses, diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx new file mode 100644 index 0000000000..d6f790aff9 --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx @@ -0,0 +1,197 @@ +import type { AddressSuggestionsType } from '../../../../common/types/geocoder'; +import type { ExtendedCountryCode } from '../../../../common/types/country'; +import type { SetState } from '../../../../common/types/common'; +import type { Address, APIError } from '@planet-sdk/common'; + +import { useState, useContext, useMemo, useCallback } from 'react'; +import { useForm } from 'react-hook-form'; +import { useTranslations } from 'next-intl'; +import { CircularProgress } from '@mui/material'; +import { handleError } from '@planet-sdk/common'; +import styles from './AddressManagement.module.scss'; +import WebappButton from '../../../../common/WebappButton'; +import COUNTRY_ADDRESS_POSTALS from '../../../../../utils/countryZipCode'; +import { useUserProps } from '../../../../common/Layout/UserPropsContext'; +import { putAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; +import { useTenant } from '../../../../common/Layout/TenantContext'; +import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; +import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; +import AddressFormInputs from './microComponents/AddressFormInputs'; +import { + fetchAddressDetails, + geocoder, + suggestAddress, +} from '../../../../../utils/addressManagement'; + +export type FormData = { + address: string | undefined; + address2: string | null; + city: string | undefined; + zipCode: string | undefined; + state: string | null; +}; + +interface Props { + setIsModalOpen: SetState; + selectedAddressForAction: Address | null; + fetchUserAddresses?: () => Promise; +} + +const EditAddressForm = ({ + setIsModalOpen, + selectedAddressForAction, + fetchUserAddresses, +}: Props) => { + const defaultAddressDetail = { + address: selectedAddressForAction?.address, + address2: selectedAddressForAction?.address2, + city: selectedAddressForAction?.city, + zipCode: selectedAddressForAction?.zipCode, + state: selectedAddressForAction?.state, + }; + const { + control, + handleSubmit, + setValue, + reset, + formState: { errors }, + } = useForm({ + mode: 'onBlur', + defaultValues: defaultAddressDetail, + }); + + const tProfile = useTranslations('Profile.addressManagement'); + const tCommon = useTranslations('Common'); + const { contextLoaded, user, token, logoutUser } = useUserProps(); + const { tenantConfig } = useTenant(); + const { setErrors } = useContext(ErrorHandlingContext); + const [country, setCountry] = useState( + selectedAddressForAction?.country ?? 'DE' + ); + const [addressSuggestions, setAddressSuggestions] = useState< + AddressSuggestionsType[] + >([]); + const [inputValue, setInputValue] = useState(''); + const [isUploadingData, setIsUploadingData] = useState(false); + + const handleSuggestAddress = useCallback( + async (value: string) => { + const suggestions = await suggestAddress(value, country); + setAddressSuggestions(suggestions); + }, + [geocoder, country] + ); + + const handleGetAddress = useCallback( + async (value: string) => { + const details = await fetchAddressDetails(value); + if (details) { + setValue('address', details.address, { shouldValidate: true }); + setValue('city', details.city, { shouldValidate: true }); + setValue('zipCode', details.zipCode, { shouldValidate: true }); + } + setAddressSuggestions([]); + }, + [geocoder, setValue] + ); + useDebouncedEffect( + () => { + if (inputValue) { + handleSuggestAddress(inputValue); + } + }, + 700, + [inputValue] + ); + + const postalRegex = useMemo(() => { + const filteredCountry = COUNTRY_ADDRESS_POSTALS.find( + (item) => item.abbrev === country + ); + return filteredCountry?.postal; + }, [country]); + + const resetForm = () => { + reset(defaultAddressDetail); + setAddressSuggestions([]); + }; + const handleCancel = () => { + setIsModalOpen(false); + resetForm(); + }; + const handleInputChange = (value: string) => { + setInputValue(value); + }; + + const handleAddressSelect = (address: string) => { + handleGetAddress(address); + }; + + const updateAddress = async (data: FormData) => { + if (!contextLoaded || !user) return; + setIsUploadingData(true); + const bodyToSend = { + ...data, + country, + type: selectedAddressForAction?.type, + }; + try { + const res = await putAuthenticatedRequest
( + tenantConfig.id, + `/app/addresses/${selectedAddressForAction?.id}`, + bodyToSend, + token, + logoutUser + ); + if (res && fetchUserAddresses) { + fetchUserAddresses(); + handleCancel(); + } + } catch (error) { + setIsUploadingData(false); + setErrors(handleError(error as APIError)); + } finally { + setIsUploadingData(false); + } + }; + + return ( +
+

{tProfile('formType.edit')}

+ + {isUploadingData ? ( +
+ +
+ ) : ( +
+ + +
+ )} +
+ ); +}; + +export default EditAddressForm; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 2ccd2b8255..346aa77500 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -18,6 +18,7 @@ import { addressTypeOrder, } from '../../../../../utils/addressManagement'; import CenteredContainer from '../../../../common/Layout/CenteredContainer'; +import EditAddressForm from './EditAddressForm'; const AddressManagement = () => { const { user, contextLoaded, token, logoutUser } = useUserProps(); @@ -76,10 +77,8 @@ const AddressManagement = () => { ); case ADDRESS_ACTIONS.EDIT: return ( - diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index 45d2591f24..230be54a42 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -1,3 +1,11 @@ +import type { ExtendedCountryCode } from '../features/common/types/country'; +import type { + AddressSuggestionsType, + AddressType, +} from '../features/common/types/geocoder'; + +import GeocoderArcGIs from 'geocoder-arcgis'; + export const ADDRESS_TYPE = { PRIMARY: 'primary', MAILING: 'mailing', @@ -34,3 +42,59 @@ export const validationPattern = { address: /^[\p{L}\p{N}\sß.,#/-]+$/u, cityState: /^[\p{L}\sß.,()-]+$/u, }; + +export const geocoder = new GeocoderArcGIs( + process.env.ESRI_CLIENT_SECRET + ? { + client_id: process.env.ESRI_CLIENT_ID, + client_secret: process.env.ESRI_CLIENT_SECRET, + } + : {} +); + +export const suggestAddress = async ( + value: string, + country: ExtendedCountryCode | '' +): Promise => { + if (value.length > 3) { + try { + const result = await geocoder.suggest(value, { + category: 'Address', + countryCode: country, + }); + return result.suggestions.filter( + (suggestion: AddressSuggestionsType) => !suggestion.isCollection + ); + } catch (error) { + console.log(error); + return []; + } + } + return []; +}; + +export const fetchAddressDetails = async ( + value: string +): Promise<{ + address: string; + city: string; + zipCode: string; +} | null> => { + try { + const result: AddressType = await geocoder.findAddressCandidates(value, { + outfields: '*', + }); + if (result.candidates.length > 0) { + const { ShortLabel, City, Postal } = result.candidates[0].attributes; + return { + address: ShortLabel, + city: City, + zipCode: Postal, + }; + } + return null; + } catch (error) { + console.log(error); + return null; + } +}; From 75bb560915f0813971da08289cc87a2393db05a8 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:05:41 +0530 Subject: [PATCH 54/88] refactor: remove the edit address form logic from the add address form --- public/static/locales/en/profile.json | 8 +- .../{AddressForm.tsx => AddAddressForm.tsx} | 155 +++++------------- .../AddressManagment/EditAddressForm.tsx | 2 +- .../EditProfile/AddressManagment/index.tsx | 10 +- .../microComponents/AddressFormInputs.tsx | 2 +- 5 files changed, 50 insertions(+), 127 deletions(-) rename src/features/user/Settings/EditProfile/AddressManagment/{AddressForm.tsx => AddAddressForm.tsx} (53%) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index bfbd2b7a5a..96cbfdd302 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -149,13 +149,9 @@ }, "addNewAddress": "Add New Address", "addAddress": "Add Address", - "address2": "Address 2(optional)", "editAddress": "Edit Address", - "saveChanges": "Save Changes", - "formType": { - "add": "Add Address", - "edit": "Edit Address" - } + "address2": "Address 2(optional)", + "saveChanges": "Save Changes" } } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx similarity index 53% rename from src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx index e0ed76391e..b032db43d7 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx @@ -1,31 +1,28 @@ -import type { - AddressSuggestionsType, - AddressType, -} from '../../../../common/types/geocoder'; +import type { AddressSuggestionsType } from '../../../../common/types/geocoder'; import type { ExtendedCountryCode } from '../../../../common/types/country'; import type { SetState } from '../../../../common/types/common'; import type { Address, APIError } from '@planet-sdk/common'; -import type { AddressAction } from '../../../../common/types/profile'; import { useState, useContext, useMemo, useCallback } from 'react'; import { useForm } from 'react-hook-form'; import { useTranslations } from 'next-intl'; import { CircularProgress } from '@mui/material'; -import GeocoderArcGIs from 'geocoder-arcgis'; import { handleError } from '@planet-sdk/common'; import styles from './AddressManagement.module.scss'; import WebappButton from '../../../../common/WebappButton'; import COUNTRY_ADDRESS_POSTALS from '../../../../../utils/countryZipCode'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; -import { - postAuthenticatedRequest, - putAuthenticatedRequest, -} from '../../../../../utils/apiRequests/api'; +import { postAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; import AddressFormInputs from './microComponents/AddressFormInputs'; -import { ADDRESS_TYPE } from '../../../../../utils/addressManagement'; +import { + ADDRESS_TYPE, + fetchAddressDetails, + geocoder, + suggestAddress, +} from '../../../../../utils/addressManagement'; export type FormData = { address: string | undefined; @@ -37,32 +34,16 @@ export type FormData = { interface Props { setIsModalOpen: SetState; - setUserAddresses?: SetState; - selectedAddressForAction?: Address | null; - addressAction?: AddressAction | null; - fetchUserAddresses?: () => Promise; + setUserAddresses: SetState; } -const geocoder = new GeocoderArcGIs( - process.env.ESRI_CLIENT_SECRET - ? { - client_id: process.env.ESRI_CLIENT_ID, - client_secret: process.env.ESRI_CLIENT_SECRET, - } - : {} -); -const AddressForm = ({ - addressAction, - setIsModalOpen, - setUserAddresses, - selectedAddressForAction, - fetchUserAddresses, -}: Props) => { + +const AddAddressForm = ({ setIsModalOpen, setUserAddresses }: Props) => { const defaultAddressDetail = { - address: selectedAddressForAction ? selectedAddressForAction.address : '', - address2: selectedAddressForAction ? selectedAddressForAction.address2 : '', - city: selectedAddressForAction ? selectedAddressForAction.city : '', - zipCode: selectedAddressForAction ? selectedAddressForAction.zipCode : '', - state: selectedAddressForAction ? selectedAddressForAction.state : '', + address: '', + address2: '', + city: '', + zipCode: '', + state: '', }; const { control, @@ -75,15 +56,13 @@ const AddressForm = ({ defaultValues: defaultAddressDetail, }); - const tProfile = useTranslations('Profile'); + const tProfile = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const userCountry = - formType === 'add' ? user?.country : selectedAddressForAction?.country; const [country, setCountry] = useState( - userCountry ?? 'DE' + user?.country ?? 'DE' ); const [addressSuggestions, setAddressSuggestions] = useState< AddressSuggestionsType[] @@ -91,53 +70,37 @@ const AddressForm = ({ const [inputValue, setInputValue] = useState(''); const [isUploadingData, setIsUploadingData] = useState(false); - const suggestAddress = useCallback( - (value: string) => { - if (value.length > 3) { - geocoder - .suggest(value, { category: 'Address', countryCode: country }) - .then((result: { suggestions: AddressSuggestionsType[] }) => { - const filterdSuggestions = result.suggestions.filter( - (suggestion: AddressSuggestionsType) => { - return !suggestion.isCollection; - } - ); - setAddressSuggestions(filterdSuggestions); - }) - .catch(console.log); + const handleSuggestAddress = useCallback( + async (value: string) => { + const suggestions = await suggestAddress(value, country); + setAddressSuggestions(suggestions); + }, + [geocoder, country] + ); + + const handleGetAddress = useCallback( + async (value: string) => { + const details = await fetchAddressDetails(value); + if (details) { + setValue('address', details.address, { shouldValidate: true }); + setValue('city', details.city, { shouldValidate: true }); + setValue('zipCode', details.zipCode, { shouldValidate: true }); } + setAddressSuggestions([]); }, - [country, geocoder] + [geocoder, setValue] ); useDebouncedEffect( () => { if (inputValue) { - suggestAddress(inputValue); + handleSuggestAddress(inputValue); } }, 700, [inputValue] ); - const getAddress = (value: string) => { - geocoder - .findAddressCandidates(value, { outfields: '*' }) - .then((result: AddressType) => { - setValue('address', result.candidates[0].attributes.ShortLabel, { - shouldValidate: true, - }); - setValue('city', result.candidates[0].attributes.City, { - shouldValidate: true, - }); - setValue('zipCode', result.candidates[0].attributes.Postal, { - shouldValidate: true, - }); - setAddressSuggestions([]); - }) - .catch(console.log); - }; - const postalRegex = useMemo(() => { const filteredCountry = COUNTRY_ADDRESS_POSTALS.find( (item) => item.abbrev === country @@ -154,35 +117,6 @@ const AddressForm = ({ resetForm(); }; - const updateAddress = async (data: FormData) => { - if (!addressAction || !selectedAddressForAction || formType === 'add') - return; - setIsUploadingData(true); - const bodyToSend = { - ...data, - country, - type: selectedAddressForAction.type, - }; - try { - const res = await putAuthenticatedRequest
( - tenantConfig.id, - `/app/addresses/${selectedAddressForAction?.id}`, - bodyToSend, - token, - logoutUser - ); - if (res && fetchUserAddresses) { - fetchUserAddresses(); - handleCancel(); - } - } catch (error) { - setIsUploadingData(false); - setErrors(handleError(error as APIError)); - } finally { - setIsUploadingData(false); - } - }; - const addAddress = async (data: FormData) => { setIsUploadingData(true); const bodyToSend = { @@ -209,6 +143,7 @@ const AddressForm = ({ setErrors(handleError(error as APIError)); } finally { setIsUploadingData(false); + setIsModalOpen(false); } } }; @@ -217,11 +152,11 @@ const AddressForm = ({ }; const handleAddressSelect = (address: string) => { - getAddress(address); + handleGetAddress(address); }; return (
-

{tProfile(`addressManagement.formType.${formType}`)}

+

{tProfile('addAddress')}

@@ -264,4 +193,4 @@ const AddressForm = ({ ); }; -export default AddressForm; +export default AddAddressForm; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx index d6f790aff9..5ea3f8ba85 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx @@ -157,7 +157,7 @@ const EditAddressForm = ({ return (
-

{tProfile('formType.edit')}

+

{tProfile('editAddress')}

{ const { user, contextLoaded, token, logoutUser } = useUserProps(); @@ -69,10 +69,9 @@ const AddressManagement = () => { switch (addressAction) { case ADDRESS_ACTIONS.ADD: return ( - ); case ADDRESS_ACTIONS.EDIT: @@ -80,12 +79,11 @@ const AddressManagement = () => { ); } }, [ - addressAction, setIsModalOpen, setUserAddresses, selectedAddressForAction, diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx index 489ed1a9d1..483a100a70 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx @@ -1,7 +1,7 @@ import type { Control, FieldErrors } from 'react-hook-form'; import type { AddressSuggestionsType } from '../../../../../common/types/geocoder'; import type { ExtendedCountryCode } from '../../../../../common/types/country'; -import type { FormData } from '../AddressForm'; +import type { FormData } from '../AddAddressForm'; import type { SetState } from '../../../../../common/types/common'; import { TextField } from '@mui/material'; From 417554fdd2c91bed9d2e516df0aaac912d944a0a Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:18:20 +0530 Subject: [PATCH 55/88] refactor: move early return condition to the top for better readability and logic clarity. --- .../AddressManagment/AddAddressForm.tsx | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx index b032db43d7..c507b41851 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx @@ -118,33 +118,32 @@ const AddAddressForm = ({ setIsModalOpen, setUserAddresses }: Props) => { }; const addAddress = async (data: FormData) => { + if (!contextLoaded || !user) return; setIsUploadingData(true); const bodyToSend = { ...data, country, type: ADDRESS_TYPE.OTHER, }; - if (contextLoaded && user) { - try { - const res = await postAuthenticatedRequest
( - tenantConfig.id, - '/app/addresses', - bodyToSend, - token, - logoutUser - ); - if (res && setUserAddresses) { - setUserAddresses((prevAddresses) => [...prevAddresses, res]); - handleCancel(); - } - } catch (error) { - resetForm(); - setIsUploadingData(false); - setErrors(handleError(error as APIError)); - } finally { - setIsUploadingData(false); - setIsModalOpen(false); + try { + const res = await postAuthenticatedRequest
( + tenantConfig.id, + '/app/addresses', + bodyToSend, + token, + logoutUser + ); + if (res && setUserAddresses) { + setUserAddresses((prevAddresses) => [...prevAddresses, res]); + handleCancel(); } + } catch (error) { + resetForm(); + setIsUploadingData(false); + setErrors(handleError(error as APIError)); + } finally { + setIsUploadingData(false); + setIsModalOpen(false); } }; const handleInputChange = (value: string) => { From 3cc040693cde96c48be40b083f1d3579c7027bfa Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:32:02 +0530 Subject: [PATCH 56/88] refactor: address feedbacks --- src/features/common/types/profile.d.ts | 8 +++---- .../AddressManagement.module.scss | 7 +++++++ .../microComponents/AddressDetails.tsx | 6 +++--- .../user/Settings/EditProfile/index.tsx | 21 ++++++++----------- src/utils/addressManagement.ts | 14 ------------- 5 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/features/common/types/profile.d.ts b/src/features/common/types/profile.d.ts index 4076af85c9..88aa9a940c 100644 --- a/src/features/common/types/profile.d.ts +++ b/src/features/common/types/profile.d.ts @@ -1,7 +1,7 @@ -import { User, UserPublicProfile } from '@planet-sdk/common'; -import { SetState } from './common'; -import { PublicUser } from './user'; -import { ADDRESS_ACTIONS } from '../../user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu'; +import type { User, UserPublicProfile } from '@planet-sdk/common'; +import type { SetState } from './common'; +import type { PublicUser } from './user'; +import type { ADDRESS_ACTIONS } from '../../user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu'; export interface UserFeaturesProps { handleShare: () => void; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index efef5b7dc1..808219eceb 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -1,5 +1,12 @@ @import '../../../../../theme/theme'; +.addressManagement { + display: flex; + flex-direction: column; + margin-top: 20px; + gap: 20px; +} + .addressManagementTitle { font-size: $fontLarge; font-weight: 600; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx index d6d8429ac1..a71294cbec 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx @@ -14,7 +14,7 @@ const AddressDetails = ({ userAddress }: Props) => { const tCountry = useTranslations('Country'); const countryName = tCountry(country.toLowerCase() as Lowercase); - const formattedAddress = useMemo(() => { + const cityStatePostalString = useMemo(() => { return [zipCode, city, state, countryName] .filter(Boolean) .join(', ') @@ -29,8 +29,8 @@ const AddressDetails = ({ userAddress }: Props) => { )}

{address}

- {address2 &&

{address2}

} -

{formattedAddress}

+ {address2 !== null &&

{address2}

} +

{cityStatePostalString}

); diff --git a/src/features/user/Settings/EditProfile/index.tsx b/src/features/user/Settings/EditProfile/index.tsx index 25b2506bf1..3d91724759 100644 --- a/src/features/user/Settings/EditProfile/index.tsx +++ b/src/features/user/Settings/EditProfile/index.tsx @@ -1,24 +1,21 @@ import { useTranslations } from 'next-intl'; -import { ReactElement } from 'react'; import CenteredContainer from '../../../common/Layout/CenteredContainer'; import DashboardView from '../../../common/Layout/DashboardView'; import EditProfileForm from './EditProfileForm'; import SingleColumnView from '../../../common/Layout/SingleColumnView'; import AddressManagement from './AddressManagment'; -export default function EditProfile(): ReactElement | null { +export default function EditProfile(): React.ReactElement | null { const t = useTranslations('Me'); return ( - <> - - - - - - - - - + + + + + + + + ); } diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index 9179b48543..8b13789179 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -1,15 +1 @@ -export const formatAddress = ( - address: string | undefined, - zipCode: string | undefined, - city: string | undefined, - state: string | null, - country: string -) => { - const cleanAddress = [address, `${zipCode} ${city}`, state, country] - .filter(Boolean) - .join(', ') - .replace(/\s+/g, ' ') - .trim(); - return cleanAddress; -}; From 2991b4384defb8d87e5f1938cd8810be168e4916 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:44:41 +0530 Subject: [PATCH 57/88] refactor: consistent type import --- pages/sites/[slug]/[locale]/profile/edit.tsx | 19 +++++++++++-------- src/utils/addressManagement.ts | 1 - 2 files changed, 11 insertions(+), 9 deletions(-) delete mode 100644 src/utils/addressManagement.ts diff --git a/pages/sites/[slug]/[locale]/profile/edit.tsx b/pages/sites/[slug]/[locale]/profile/edit.tsx index ab4e587a2b..0a171a832e 100644 --- a/pages/sites/[slug]/[locale]/profile/edit.tsx +++ b/pages/sites/[slug]/[locale]/profile/edit.tsx @@ -1,18 +1,21 @@ -import Head from 'next/head'; -import React, { ReactElement } from 'react'; -import UserLayout from '../../../../../src/features/common/Layout/UserLayout/UserLayout'; -import { AbstractIntlMessages, useTranslations } from 'next-intl'; -import EditProfile from '../../../../../src/features/user/Settings/EditProfile'; -import { +import type { AbstractIntlMessages } from 'next-intl'; +import type { GetStaticProps, GetStaticPropsContext, GetStaticPropsResult, } from 'next'; +import type { Tenant } from '@planet-sdk/common/build/types/tenant'; +import type { ReactElement } from 'react'; + +import { useEffect } from 'react'; +import Head from 'next/head'; +import { useTranslations } from 'next-intl'; +import UserLayout from '../../../../../src/features/common/Layout/UserLayout/UserLayout'; +import EditProfile from '../../../../../src/features/user/Settings/EditProfile'; import { constructPathsForTenantSlug, getTenantConfig, } from '../../../../../src/utils/multiTenancy/helpers'; -import { Tenant } from '@planet-sdk/common/build/types/tenant'; import { defaultTenant } from '../../../../../tenant.config'; import { useRouter } from 'next/router'; import { useTenant } from '../../../../../src/features/common/Layout/TenantContext'; @@ -27,7 +30,7 @@ function EditProfilePage({ pageProps: { tenantConfig } }: Props): ReactElement { const router = useRouter(); const { setTenantConfig } = useTenant(); - React.useEffect(() => { + useEffect(() => { if (router.isReady) { setTenantConfig(tenantConfig); } diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts deleted file mode 100644 index 8b13789179..0000000000 --- a/src/utils/addressManagement.ts +++ /dev/null @@ -1 +0,0 @@ - From 25860aa63e3f69024a87540b2993e20bfa3e7d5b Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:12:57 +0530 Subject: [PATCH 58/88] docs: add documentation for geocoding functions: suggestAddress and fetchAddressDetails --- .../microComponents/AddressContent.tsx | 24 ------------------- src/utils/addressManagement.ts | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 24 deletions(-) delete mode 100644 src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx deleted file mode 100644 index 54f928cf88..0000000000 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import type { AddressType } from '@planet-sdk/common'; - -import styles from '../AddressManagement.module.scss'; -import { useTranslations } from 'next-intl'; - -interface Props { - type: AddressType; - userAddress: string; -} -const AddressContent = ({ type, userAddress }: Props) => { - const tProfile = useTranslations('Profile.addressManagement'); - return ( -
- {type !== 'other' && ( - - {tProfile(`addressTags.${type}`)} - - )} -
{userAddress}
-
- ); -}; - -export default AddressContent; diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index 230be54a42..bea0c0165e 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -52,6 +52,19 @@ export const geocoder = new GeocoderArcGIs( : {} ); +/** + * Suggests address options based on user input. + * + * This function queries the geocoder's `suggest` method with the provided input value + * and optional country code to fetch address suggestions categorized as "Address". + * It filters out suggestions marked as collections (`isCollection`) to ensure only + * individual address suggestions are returned. + * + * @param value - The input string to search for address suggestions. + * @param country - The optional country code to narrow down the address suggestions. + * @returns A promise that resolves to an array of valid address suggestions or an empty array. + */ + export const suggestAddress = async ( value: string, country: ExtendedCountryCode | '' @@ -73,6 +86,17 @@ export const suggestAddress = async ( return []; }; +/** + * Fetches detailed address information based on the input value. + * + * This function uses the geocoder's `findAddressCandidates` method to search for + * address candidates and retrieves key information such as formatted address, city, + * and postal code (ZIP code). If no candidates are found, it returns `null`. + * + * @param value - The input string to search for address details. + * @returns A promise that resolves to an object containing address details (address, city, zipCode) + * or `null` if no candidates are found or an error occurs. + */ export const fetchAddressDetails = async ( value: string ): Promise<{ From ce39b5d91c628acab041740bc1828fcc17fa67e4 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:43:42 +0530 Subject: [PATCH 59/88] fix: update margin-top for address management styles --- .../EditProfile/AddressManagment/AddressManagement.module.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 808219eceb..2f4efc8596 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -3,14 +3,13 @@ .addressManagement { display: flex; flex-direction: column; - margin-top: 20px; + margin-top: 40px; gap: 20px; } .addressManagementTitle { font-size: $fontLarge; font-weight: 600; - margin: 40px 0 20px; } .addressListContainer { From 2462e842baf15f3e0fe534045a58d10c6f715f68 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:49:34 +0530 Subject: [PATCH 60/88] refactor: move helper function to the utils file --- .../common/InputTypes/AutoCompleteCountry.tsx | 21 +++++++++++-------- .../AddressManagment/AddAddressForm.tsx | 9 ++------ .../AddressManagment/EditAddressForm.tsx | 9 ++------ src/utils/addressManagement.ts | 17 +++++++++++++++ 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/features/common/InputTypes/AutoCompleteCountry.tsx b/src/features/common/InputTypes/AutoCompleteCountry.tsx index ceeb28f494..1f57498062 100644 --- a/src/features/common/InputTypes/AutoCompleteCountry.tsx +++ b/src/features/common/InputTypes/AutoCompleteCountry.tsx @@ -1,12 +1,14 @@ /* eslint-disable no-use-before-define */ -import { useState, ReactElement, useEffect, ReactNode } from 'react'; +import type { CountryType, ExtendedCountryCode } from '../types/country'; +import type { SetState } from '../types/common'; +import type { ReactNode, ReactElement } from 'react'; +import type { CountryCode } from '@planet-sdk/common'; + +import { useState, useEffect } from 'react'; import { TextField } from '@mui/material'; -import React from 'react'; import { useTranslations } from 'next-intl'; import { MuiAutoComplete, StyledAutoCompleteOption } from './MuiAutoComplete'; -import { CountryType, ExtendedCountryCode } from '../types/country'; import { allCountries } from '../../../utils/constants/countries'; -import { SetState } from '../types/common'; // ISO 3166-1 alpha-2 // ⚠️ No support for IE 11 @@ -24,7 +26,7 @@ interface CountrySelectProps { label?: ReactNode; name: string | undefined; defaultValue: string | undefined; //This will be a country code e.g. DE, IN, US - onChange: SetState; + onChange: SetState; countries?: CountryType[]; } @@ -66,8 +68,8 @@ export default function CountrySelect({ useEffect(() => { countries.sort((a, b) => { - const nameA = t(a.code.toLowerCase()); - const nameB = t(b.code.toLowerCase()); + const nameA = t(a.code.toLowerCase() as Lowercase); + const nameB = t(b.code.toLowerCase() as Lowercase); //Automatic Selection option is always at first position (if present) if (a.code === 'auto') return -1; @@ -91,7 +93,8 @@ export default function CountrySelect({ getOptionLabel={(option) => { const { code: countryCode, currency } = option as CountryType; const label = - (currency ? `(${currency}) ` : '') + t(countryCode.toLowerCase()); + (currency ? `(${currency}) ` : '') + + t(countryCode.toLowerCase() as Lowercase); return label; }} isOptionEqualToValue={(option, value) => @@ -101,7 +104,7 @@ export default function CountrySelect({ const { code: countryCode, currency } = option as CountryType; const displayedOption = (currency ? `(${currency}) ` : '') + - t(countryCode.toLowerCase()) + + t(countryCode.toLowerCase() as Lowercase) + (!(name == 'editProfile' || countryCode === 'auto') ? ` ${countryCode}` : ''); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx index c507b41851..6129162180 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx @@ -10,7 +10,6 @@ import { CircularProgress } from '@mui/material'; import { handleError } from '@planet-sdk/common'; import styles from './AddressManagement.module.scss'; import WebappButton from '../../../../common/WebappButton'; -import COUNTRY_ADDRESS_POSTALS from '../../../../../utils/countryZipCode'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import { postAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; @@ -21,6 +20,7 @@ import { ADDRESS_TYPE, fetchAddressDetails, geocoder, + getPostalRegex, suggestAddress, } from '../../../../../utils/addressManagement'; @@ -101,12 +101,7 @@ const AddAddressForm = ({ setIsModalOpen, setUserAddresses }: Props) => { [inputValue] ); - const postalRegex = useMemo(() => { - const filteredCountry = COUNTRY_ADDRESS_POSTALS.find( - (item) => item.abbrev === country - ); - return filteredCountry?.postal; - }, [country]); + const postalRegex = useMemo(() => getPostalRegex(country), [country]); const resetForm = () => { reset(defaultAddressDetail); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx index 5ea3f8ba85..23621a5e85 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx @@ -10,7 +10,6 @@ import { CircularProgress } from '@mui/material'; import { handleError } from '@planet-sdk/common'; import styles from './AddressManagement.module.scss'; import WebappButton from '../../../../common/WebappButton'; -import COUNTRY_ADDRESS_POSTALS from '../../../../../utils/countryZipCode'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import { putAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; @@ -20,6 +19,7 @@ import AddressFormInputs from './microComponents/AddressFormInputs'; import { fetchAddressDetails, geocoder, + getPostalRegex, suggestAddress, } from '../../../../../utils/addressManagement'; @@ -104,12 +104,7 @@ const EditAddressForm = ({ [inputValue] ); - const postalRegex = useMemo(() => { - const filteredCountry = COUNTRY_ADDRESS_POSTALS.find( - (item) => item.abbrev === country - ); - return filteredCountry?.postal; - }, [country]); + const postalRegex = useMemo(() => getPostalRegex(country), [country]); const resetForm = () => { reset(defaultAddressDetail); diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index 8488f935a4..282eea0586 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -5,6 +5,7 @@ import type { } from '../features/common/types/geocoder'; import GeocoderArcGIs from 'geocoder-arcgis'; +import COUNTRY_ADDRESS_POSTALS from './countryZipCode'; export const ADDRESS_TYPE = { PRIMARY: 'primary', @@ -106,3 +107,19 @@ export const fetchAddressDetails = async ( return null; } }; + +/** + * Retrieves the postal regex for a given country code. + * + * This function searches the `COUNTRY_ADDRESS_POSTALS` array for the country matching the provided + * `country` code and returns the associated postal regex pattern. If no match is found, it returns `undefined`. + * + * @param country - The country code for which to retrieve the postal regex. + * @returns The postal regex pattern for the given country, or `undefined` if no match is found. + */ +export const getPostalRegex = (country: ExtendedCountryCode | '') => { + const filteredCountry = COUNTRY_ADDRESS_POSTALS.find( + (item) => item.abbrev === country + ); + return filteredCountry?.postal; +}; From 0e60fac0606c3e527b32143c04911ec01d28511a Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:59:43 +0530 Subject: [PATCH 61/88] refactor: early return if token is missing --- .../Settings/EditProfile/AddressManagment/AddAddressForm.tsx | 2 +- .../Settings/EditProfile/AddressManagment/EditAddressForm.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx index 6129162180..2e08a31c03 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx @@ -113,7 +113,7 @@ const AddAddressForm = ({ setIsModalOpen, setUserAddresses }: Props) => { }; const addAddress = async (data: FormData) => { - if (!contextLoaded || !user) return; + if (!contextLoaded || !user || !token) return; setIsUploadingData(true); const bodyToSend = { ...data, diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx index 23621a5e85..4bf7ed9ad4 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx @@ -123,7 +123,7 @@ const EditAddressForm = ({ }; const updateAddress = async (data: FormData) => { - if (!contextLoaded || !user) return; + if (!contextLoaded || !user || !token) return; setIsUploadingData(true); const bodyToSend = { ...data, @@ -147,6 +147,7 @@ const EditAddressForm = ({ setErrors(handleError(error as APIError)); } finally { setIsUploadingData(false); + setIsModalOpen(false); } }; From 64f735181f6256d7089a78449370dd29cc57e515 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:14:30 +0530 Subject: [PATCH 62/88] refactor: minor ui fixes --- .../AddressManagment/AddAddressForm.tsx | 4 +- .../AddressManagment/AddressDeleteModal.tsx | 2 +- .../AddressManagment/AddressForm.tsx | 274 ------------------ .../AddressManagement.module.scss | 16 +- .../AddressTypeConfirmationModal.tsx | 4 +- .../AddressManagment/EditAddressForm.tsx | 4 +- .../EditProfile/AddressManagment/index.tsx | 3 +- 7 files changed, 15 insertions(+), 292 deletions(-) delete mode 100644 src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx index 2e08a31c03..b2e98cf566 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx @@ -150,7 +150,7 @@ const AddAddressForm = ({ setIsModalOpen, setUserAddresses }: Props) => { }; return (
-

{tProfile('addAddress')}

+

{tProfile('addAddress')}

{
) : ( -
+
-

{tProfile('deleteAddress')}

+

{tProfile('deleteAddress')}

{tProfile('deleteAddressConfirmationMessage')}

{!isLoading ? (
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx deleted file mode 100644 index 6c9efafe25..0000000000 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressForm.tsx +++ /dev/null @@ -1,274 +0,0 @@ -import type { - AddressSuggestionsType, - AddressType, -} from '../../../../common/types/geocoder'; -import type { ExtendedCountryCode } from '../../../../common/types/country'; -import type { SetState } from '../../../../common/types/common'; -import type { Address, APIError } from '@planet-sdk/common'; -import type { AddressAction } from '../../../../common/types/profile'; - -import { useState, useContext, useMemo, useCallback } from 'react'; -import { useForm } from 'react-hook-form'; -import { useTranslations } from 'next-intl'; -import { CircularProgress } from '@mui/material'; -import GeocoderArcGIs from 'geocoder-arcgis'; -import { handleError } from '@planet-sdk/common'; -import styles from './AddressManagement.module.scss'; -import WebappButton from '../../../../common/WebappButton'; -import COUNTRY_ADDRESS_POSTALS from '../../../../../utils/countryZipCode'; -import { useUserProps } from '../../../../common/Layout/UserPropsContext'; -import { - postAuthenticatedRequest, - putAuthenticatedRequest, -} from '../../../../../utils/apiRequests/api'; -import { useTenant } from '../../../../common/Layout/TenantContext'; -import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; -import { - ADDRESS_FORM_TYPE, - ADDRESS_TYPE, -} from '../../../../../utils/addressManagement'; -import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; -import AddressFormInputs from './microComponents/AddressFormInputs'; - -export type AddressFormData = { - address: string | undefined; - address2: string | null; - city: string | undefined; - zipCode: string | undefined; - state: string | null; -}; - -type AddressFormType = - (typeof ADDRESS_FORM_TYPE)[keyof typeof ADDRESS_FORM_TYPE]; -interface Props { - formType: AddressFormType; - setIsModalOpen: SetState; - setUserAddresses?: SetState; - selectedAddressForAction?: Address | null; - addressAction?: AddressAction | null; - fetchUserAddresses?: () => Promise; -} -const geocoder = new GeocoderArcGIs( - process.env.ESRI_CLIENT_SECRET - ? { - client_id: process.env.ESRI_CLIENT_ID, - client_secret: process.env.ESRI_CLIENT_SECRET, - } - : {} -); -const AddressForm = ({ - addressAction, - formType, - setIsModalOpen, - setUserAddresses, - selectedAddressForAction, - fetchUserAddresses, -}: Props) => { - const defaultAddressDetail = { - address: selectedAddressForAction ? selectedAddressForAction.address : '', - address2: selectedAddressForAction ? selectedAddressForAction.address2 : '', - city: selectedAddressForAction ? selectedAddressForAction.city : '', - zipCode: selectedAddressForAction ? selectedAddressForAction.zipCode : '', - state: selectedAddressForAction ? selectedAddressForAction.state : '', - }; - const { - control, - handleSubmit, - setValue, - reset, - formState: { errors }, - } = useForm({ - mode: 'onBlur', - defaultValues: defaultAddressDetail, - }); - - const tProfile = useTranslations('Profile'); - const tCommon = useTranslations('Common'); - const { contextLoaded, user, token, logoutUser } = useUserProps(); - const { tenantConfig } = useTenant(); - const { setErrors } = useContext(ErrorHandlingContext); - const isAddAddressForm = formType === ADDRESS_FORM_TYPE.ADD_ADDRESS; - const userCountry = isAddAddressForm - ? user?.country - : selectedAddressForAction?.country; - const [country, setCountry] = useState( - userCountry ?? 'DE' - ); - const [addressSuggestions, setAddressSuggestions] = useState< - AddressSuggestionsType[] - >([]); - const [inputValue, setInputValue] = useState(''); - const [isUploadingData, setIsUploadingData] = useState(false); - const suggestAddress = useCallback( - (value: string) => { - if (value.length > 3) { - geocoder - .suggest(value, { category: 'Address', countryCode: country }) - .then((result: { suggestions: AddressSuggestionsType[] }) => { - const filterdSuggestions = result.suggestions.filter( - (suggestion: AddressSuggestionsType) => { - return !suggestion.isCollection; - } - ); - setAddressSuggestions(filterdSuggestions); - }) - .catch(console.log); - } - }, - [country, geocoder] - ); - - useDebouncedEffect( - () => { - if (inputValue) { - suggestAddress(inputValue); - } - }, - 700, - [inputValue] - ); - - const getAddress = (value: string) => { - geocoder - .findAddressCandidates(value, { outfields: '*' }) - .then((result: AddressType) => { - setValue('address', result.candidates[0].attributes.ShortLabel, { - shouldValidate: true, - }); - setValue('city', result.candidates[0].attributes.City, { - shouldValidate: true, - }); - setValue('zipCode', result.candidates[0].attributes.Postal, { - shouldValidate: true, - }); - setAddressSuggestions([]); - }) - .catch(console.log); - }; - - const postalRegex = useMemo(() => { - const filteredCountry = COUNTRY_ADDRESS_POSTALS.find( - (item) => item.abbrev === country - ); - return filteredCountry?.postal; - }, [country]); - - const resetForm = () => { - reset(defaultAddressDetail); - setAddressSuggestions([]); - }; - const handleCancel = () => { - setIsModalOpen(false); - resetForm(); - }; - - const updateAddress = async (data: AddressFormData) => { - if (!addressAction || !selectedAddressForAction || formType === 'add') - return; - setIsUploadingData(true); - const bodyToSend = { - ...data, - country, - type: selectedAddressForAction.type, - }; - try { - const res = await putAuthenticatedRequest
( - tenantConfig.id, - `/app/addresses/${selectedAddressForAction?.id}`, - bodyToSend, - token, - logoutUser - ); - if (res && fetchUserAddresses) { - fetchUserAddresses(); - handleCancel(); - } - } catch (error) { - setErrors(handleError(error as APIError)); - } finally { - setIsUploadingData(false); - setIsModalOpen(false); - } - }; - - const addAddress = async (data: AddressFormData) => { - setIsUploadingData(true); - const bodyToSend = { - ...data, - country, - type: ADDRESS_TYPE.OTHER, - }; - if (contextLoaded && user) { - try { - const res = await postAuthenticatedRequest
( - tenantConfig.id, - '/app/addresses', - bodyToSend, - token, - logoutUser - ); - if (res && setUserAddresses) { - setUserAddresses((prevAddresses) => [...prevAddresses, res]); - handleCancel(); - } - } catch (error) { - resetForm(); - setErrors(handleError(error as APIError)); - } finally { - setIsUploadingData(false); - setIsModalOpen(false); - } - } - }; - const handleInputChange = (value: string) => { - setInputValue(value); - }; - - const handleAddressSelect = (address: string) => { - getAddress(address); - }; - return ( -
-

{tProfile(`addressManagement.formType.${formType}`)}

- - {!isUploadingData ? ( -
- - -
- ) : ( -
- -
- )} -
- ); -}; - -export default AddressForm; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 15109e1c9c..0b144e5ce3 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -95,6 +95,11 @@ } // address action form +.header { + font-weight: 700; + font-size: $fontSixteen; +} + .addressFormContainer { min-width: 565px; display: flex; @@ -107,10 +112,6 @@ left: 50%; top: 50%; transform: translate(-50%, -50%); - h2 { - font-weight: 700; - font-size: $fontSixteen; - } .addressForm { display: flex; flex-direction: column; @@ -121,8 +122,7 @@ justify-content: space-between; gap: 8px; button { - min-width: 252px; - min-height: 40px; + flex: 1 1; } } } @@ -138,10 +138,6 @@ left: 50%; top: 50%; transform: translate(-50%, -50%); - h2 { - font-weight: 700; - font-size: $fontSixteen; - } .address { width: 100%; background: rgba(242, 242, 242, 0.5); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx index ec0a82ed65..8454fe73af 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx @@ -59,7 +59,9 @@ const AddressTypeConfirmationModal = ({ }; return (
-

{tProfile(`addressType.${addressType}`)}

+

+ {tProfile(`addressType.${addressType}`)} +

{tProfile('addressConfirmationMessage', { addressType, diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx index 4bf7ed9ad4..7371908f33 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx @@ -153,7 +153,7 @@ const EditAddressForm = ({ return (

-

{tProfile('editAddress')}

+

{tProfile('editAddress')}

) : ( -
+
{ fetchUserAddresses, primaryAddress, billingAddress, + addressAction, ]); - return userAddresses.length > 0 ? (

From 917756ce0993fc77dc0d7d06a34aae0523637591 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:57:51 +0530 Subject: [PATCH 63/88] refactor(styles): use flex-container mixin for consistent layout styling --- .../AddressManagement.module.scss | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 6a476f36ed..5e1d0e3a37 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -10,15 +10,11 @@ $padding-standard: 24px; justify-content: $justify; } -@mixin centered-absolute { +@mixin modal-container { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); -} - -@mixin modal-container { - @include centered-absolute; padding: 20px; border-radius: $border-radius-lg; background: rgba(255, 255, 255, 1); @@ -27,8 +23,7 @@ $padding-standard: 24px; // Base Components .addressManagement { - display: flex; - flex-direction: column; + @include flex-container(column); margin-top: 40px; gap: 20px; } @@ -39,8 +34,7 @@ $padding-standard: 24px; } .addressListContainer { - display: flex; - flex-direction: column; + @include flex-container(column); gap: 16px; width: 100%; } @@ -73,9 +67,7 @@ $padding-standard: 24px; } .addressDetails { - display: flex; - justify-content: center; - flex-direction: column; + @include flex-container(column, center); gap: 16px; span { padding: 5px 10px; @@ -94,11 +86,11 @@ $padding-standard: 24px; // Address Types .primary { - background: rgba(0, 122, 73, 1); + background: $primaryDarkColor; } .mailing { - background: rgba(45, 156, 219, 1); + background: $mediumBlueColor; } // Address Actions From 7dfa3e5ad4a0457c67848b29044a5bd8400fd114 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 27 Nov 2024 12:34:47 +0530 Subject: [PATCH 64/88] feat: add address limit check and show message when limit is reached --- public/static/locales/en/profile.json | 1 + .../AddressManagement.module.scss | 4 ++++ .../EditProfile/AddressManagment/index.tsx | 20 ++++++++++++------- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index eb753c7574..d3b230850d 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -155,6 +155,7 @@ "saveChanges": "Save Changes", "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType, select, mailing {billing} other {{addressType}}} address? {isAddressSet, select, true {This will replace your current {addressType, select, mailing {billing} other {{addressType}}} address.} other {}}", "deleteAddressConfirmationMessage": "Are you sure you want to delete this address? If you want to use it again, please add it as a new address.", + "maxAddressesMessage": "You have reached the maximum number of addresses ! Remove one to add a new address.", "confirm": "Confirm", "address2": "Address 2(optional)" } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 0b144e5ce3..742880bc29 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -5,6 +5,10 @@ flex-direction: column; margin-top: 40px; gap: 20px; + .maxAddress { + font-size: $fontXSmall; + color: #6c757d; + } } .addressManagementTitle { diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 74de1d637d..6501e23af9 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -132,6 +132,8 @@ const AddressManagement = () => { billingAddress, addressAction, ]); + const maxAddressLimit = 5; + const canAddMoreAddresses = userAddresses.length < maxAddressLimit; return userAddresses.length > 0 ? (

@@ -144,13 +146,17 @@ const AddressManagement = () => { setSelectedAddressForAction={setSelectedAddressForAction} setIsModalOpen={setIsModalOpen} /> - + {canAddMoreAddresses ? ( + + ) : ( +

{tProfile('maxAddressesMessage')}

+ )} <>{renderModalContent} From 0c35ec5f3a1d566b325d2fc158ea19ef8718fc5c Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:19:22 +0530 Subject: [PATCH 65/88] refactor: remove unneeded space. --- public/static/locales/en/profile.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index d3b230850d..f86ccd7d27 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -155,7 +155,7 @@ "saveChanges": "Save Changes", "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType, select, mailing {billing} other {{addressType}}} address? {isAddressSet, select, true {This will replace your current {addressType, select, mailing {billing} other {{addressType}}} address.} other {}}", "deleteAddressConfirmationMessage": "Are you sure you want to delete this address? If you want to use it again, please add it as a new address.", - "maxAddressesMessage": "You have reached the maximum number of addresses ! Remove one to add a new address.", + "maxAddressesMessage": "You have reached the maximum number of addresses! Remove one to add a new address.", "confirm": "Confirm", "address2": "Address 2(optional)" } From e5ce25f3f64ae04c9a64c63a366c448becf0799c Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 28 Nov 2024 15:33:44 +0530 Subject: [PATCH 66/88] refactor: Initialize userAddresses state with profile addresses. --- .../Settings/EditProfile/AddressManagment/index.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index d6d0ad8dce..84cbef9558 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -1,7 +1,7 @@ import type { Address, APIError } from '@planet-sdk/common'; import type { AddressAction } from '../../../../common/types/profile'; -import { useContext, useEffect, useMemo, useState } from 'react'; +import { useContext, useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; import { Modal } from '@mui/material'; import { handleError } from '@planet-sdk/common'; @@ -25,7 +25,9 @@ const AddressManagement = () => { const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); const tProfile = useTranslations('Profile.addressManagement'); - const [userAddresses, setUserAddresses] = useState([]); + const [userAddresses, setUserAddresses] = useState( + user?.addresses ?? [] + ); const [addressAction, setAddressAction] = useState( null ); @@ -56,10 +58,6 @@ const AddressManagement = () => { } }; - useEffect(() => { - fetchUserAddresses(); - }, []); - const toggleAddAddressModal = () => { setIsModalOpen(true); setAddressAction(ADDRESS_ACTIONS.ADD); From fe263b6cf423ca3f3026a0820cee4e222ec0a8d2 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 28 Nov 2024 15:41:15 +0530 Subject: [PATCH 67/88] refactor: rename tProfile to tAddressManagement --- .../EditProfile/AddressManagment/AddAddressForm.tsx | 6 +++--- .../EditProfile/AddressManagment/EditAddressForm.tsx | 6 +++--- .../Settings/EditProfile/AddressManagment/index.tsx | 6 +++--- .../microComponents/AddressActionMenu.tsx | 10 +++++----- .../microComponents/AddressDetails.tsx | 6 ++++-- .../microComponents/AddressFormInputs.tsx | 4 ++-- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx index 2e08a31c03..c16cbfff7f 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx @@ -56,7 +56,7 @@ const AddAddressForm = ({ setIsModalOpen, setUserAddresses }: Props) => { defaultValues: defaultAddressDetail, }); - const tProfile = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); @@ -150,7 +150,7 @@ const AddAddressForm = ({ setIsModalOpen, setUserAddresses }: Props) => { }; return (
-

{tProfile('addAddress')}

+

{tAddressManagement('addAddress')}

{ buttonClasses={styles.cancelButton} /> -

{tProfile('editAddress')}

+

{tAddressManagement('editAddress')}

{ const { user, contextLoaded, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const tProfile = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('Profile.addressManagement'); const [userAddresses, setUserAddresses] = useState( user?.addresses ?? [] ); @@ -91,7 +91,7 @@ const AddressManagement = () => { return userAddresses.length > 0 ? (

- {tProfile('addressManagementTitle')} + {tAddressManagement('addressManagementTitle')}

{ setIsModalOpen={setIsModalOpen} /> { - const tProfile = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('Profile.addressManagement'); const [popoverAnchor, setPopoverAnchor] = useState( null ); const addressActionConfig: AddressActionItem[] = [ { - label: tProfile(`actions.edit`), + label: tAddressManagement(`actions.edit`), action: ADDRESS_ACTIONS.EDIT, shouldRender: true, }, { - label: tProfile(`actions.delete`), + label: tAddressManagement(`actions.delete`), action: ADDRESS_ACTIONS.DELETE, shouldRender: addressCount > 1, }, { - label: tProfile('actions.setAsPrimaryAddress'), + label: tAddressManagement('actions.setAsPrimaryAddress'), action: ADDRESS_ACTIONS.SET_PRIMARY, shouldRender: !( type === ADDRESS_TYPE.MAILING || type === ADDRESS_TYPE.PRIMARY ), }, { - label: tProfile('actions.setAsBillingAddress'), + label: tAddressManagement('actions.setAsBillingAddress'), action: ADDRESS_ACTIONS.SET_BILLING, shouldRender: !( type === ADDRESS_TYPE.MAILING || type === ADDRESS_TYPE.PRIMARY diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx index a71294cbec..387935b895 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx @@ -10,7 +10,7 @@ interface Props { const AddressDetails = ({ userAddress }: Props) => { const { zipCode, city, state, country, address, address2, type } = userAddress; - const tProfile = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('Profile.addressManagement'); const tCountry = useTranslations('Country'); const countryName = tCountry(country.toLowerCase() as Lowercase); @@ -25,7 +25,9 @@ const AddressDetails = ({ userAddress }: Props) => { return (
{type !== 'other' && ( - {tProfile(`addressTags.${type}`)} + + {tAddressManagement(`addressTags.${type}`)} + )}

{address}

diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx index 483a100a70..3a37bd476b 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx @@ -36,7 +36,7 @@ const AddressFormInputs = ({ setCountry, }: Props) => { const t = useTranslations('EditProfile'); - const tProfile = useTranslations('Profile'); + const tAddressManagement = useTranslations('Profile'); return (
Date: Fri, 29 Nov 2024 10:47:31 +0530 Subject: [PATCH 68/88] refactor(address-form): centralize handlers and buttons, improve reusability - renamed isUploading state to isLoading. - renamed EditAddressForm to EditAddress and AddAddressForm to AddAddress. - created a common AddressForm component for both add/edit features. - shifted all handlers and form buttons within the AddressForm. - used useCallback for API call helper functions. --- .../AddressManagment/AddAddress.tsx | 103 ++++++++++ .../AddressManagment/AddAddressForm.tsx | 190 ----------------- .../AddressManagment/EditAddress.tsx | 108 ++++++++++ .../AddressManagment/EditAddressForm.tsx | 193 ------------------ .../EditProfile/AddressManagment/index.tsx | 12 +- .../microComponents/AddressActionMenu.tsx | 6 +- ...{AddressFormInputs.tsx => AddressForm.tsx} | 122 +++++++++-- .../microComponents/AddressFormButtons.tsx | 33 +++ .../microComponents/AddressFormWrapper.tsx | 17 ++ .../microComponents/SingleAddress.tsx | 1 - 10 files changed, 372 insertions(+), 413 deletions(-) create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx delete mode 100644 src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx delete mode 100644 src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx rename src/features/user/Settings/EditProfile/AddressManagment/microComponents/{AddressFormInputs.tsx => AddressForm.tsx} (58%) create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormButtons.tsx create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormWrapper.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx new file mode 100644 index 0000000000..959d6ba223 --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx @@ -0,0 +1,103 @@ +import type { ExtendedCountryCode } from '../../../../common/types/country'; +import type { SetState } from '../../../../common/types/common'; +import type { Address, APIError } from '@planet-sdk/common'; + +import { useState, useContext, useCallback } from 'react'; +import { useTranslations } from 'next-intl'; +import { handleError } from '@planet-sdk/common'; +import { useUserProps } from '../../../../common/Layout/UserPropsContext'; +import { postAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; +import { useTenant } from '../../../../common/Layout/TenantContext'; +import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; +import AddressForm from './microComponents/AddressForm'; +import { ADDRESS_TYPE } from '../../../../../utils/addressManagement'; +import AddressFormWrapper from './microComponents/AddressFormWrapper'; + +export type FormData = { + address: string | undefined; + address2: string | null; + city: string | undefined; + zipCode: string | undefined; + state: string | null; +}; + +interface Props { + setIsModalOpen: SetState; + setUserAddresses: SetState; +} + +const defaultAddressDetail = { + address: '', + address2: '', + city: '', + zipCode: '', + state: '', +}; + +const AddAddress = ({ setIsModalOpen, setUserAddresses }: Props) => { + const tAddressManagement = useTranslations('Profile.addressManagement'); + const { contextLoaded, user, token, logoutUser } = useUserProps(); + const { tenantConfig } = useTenant(); + const { setErrors } = useContext(ErrorHandlingContext); + const [country, setCountry] = useState( + user?.country ?? 'DE' + ); + const [isLoading, setIsLoading] = useState(false); + + const addAddress = useCallback( + async (data: FormData) => { + if (!contextLoaded || !user || !token) return; + setIsLoading(true); + const bodyToSend = { + ...data, + country, + type: ADDRESS_TYPE.OTHER, + }; + try { + const res = await postAuthenticatedRequest
( + tenantConfig.id, + '/app/addresses', + bodyToSend, + token, + logoutUser + ); + if (res && setUserAddresses) { + setUserAddresses((prevAddresses) => [...prevAddresses, res]); + } + } catch (error) { + setErrors(handleError(error as APIError)); + } finally { + setIsLoading(false); + setIsModalOpen(false); + } + }, + [ + contextLoaded, + user, + token, + country, + logoutUser, + setUserAddresses, + handleError, + setIsLoading, + setIsModalOpen, + postAuthenticatedRequest, + ] + ); + + return ( + + + + ); +}; + +export default AddAddress; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx deleted file mode 100644 index c16cbfff7f..0000000000 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import type { AddressSuggestionsType } from '../../../../common/types/geocoder'; -import type { ExtendedCountryCode } from '../../../../common/types/country'; -import type { SetState } from '../../../../common/types/common'; -import type { Address, APIError } from '@planet-sdk/common'; - -import { useState, useContext, useMemo, useCallback } from 'react'; -import { useForm } from 'react-hook-form'; -import { useTranslations } from 'next-intl'; -import { CircularProgress } from '@mui/material'; -import { handleError } from '@planet-sdk/common'; -import styles from './AddressManagement.module.scss'; -import WebappButton from '../../../../common/WebappButton'; -import { useUserProps } from '../../../../common/Layout/UserPropsContext'; -import { postAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; -import { useTenant } from '../../../../common/Layout/TenantContext'; -import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; -import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; -import AddressFormInputs from './microComponents/AddressFormInputs'; -import { - ADDRESS_TYPE, - fetchAddressDetails, - geocoder, - getPostalRegex, - suggestAddress, -} from '../../../../../utils/addressManagement'; - -export type FormData = { - address: string | undefined; - address2: string | null; - city: string | undefined; - zipCode: string | undefined; - state: string | null; -}; - -interface Props { - setIsModalOpen: SetState; - setUserAddresses: SetState; -} - -const AddAddressForm = ({ setIsModalOpen, setUserAddresses }: Props) => { - const defaultAddressDetail = { - address: '', - address2: '', - city: '', - zipCode: '', - state: '', - }; - const { - control, - handleSubmit, - setValue, - reset, - formState: { errors }, - } = useForm({ - mode: 'onBlur', - defaultValues: defaultAddressDetail, - }); - - const tAddressManagement = useTranslations('Profile.addressManagement'); - const tCommon = useTranslations('Common'); - const { contextLoaded, user, token, logoutUser } = useUserProps(); - const { tenantConfig } = useTenant(); - const { setErrors } = useContext(ErrorHandlingContext); - const [country, setCountry] = useState( - user?.country ?? 'DE' - ); - const [addressSuggestions, setAddressSuggestions] = useState< - AddressSuggestionsType[] - >([]); - const [inputValue, setInputValue] = useState(''); - const [isUploadingData, setIsUploadingData] = useState(false); - - const handleSuggestAddress = useCallback( - async (value: string) => { - const suggestions = await suggestAddress(value, country); - setAddressSuggestions(suggestions); - }, - [geocoder, country] - ); - - const handleGetAddress = useCallback( - async (value: string) => { - const details = await fetchAddressDetails(value); - if (details) { - setValue('address', details.address, { shouldValidate: true }); - setValue('city', details.city, { shouldValidate: true }); - setValue('zipCode', details.zipCode, { shouldValidate: true }); - } - setAddressSuggestions([]); - }, - [geocoder, setValue] - ); - - useDebouncedEffect( - () => { - if (inputValue) { - handleSuggestAddress(inputValue); - } - }, - 700, - [inputValue] - ); - - const postalRegex = useMemo(() => getPostalRegex(country), [country]); - - const resetForm = () => { - reset(defaultAddressDetail); - setAddressSuggestions([]); - }; - const handleCancel = () => { - setIsModalOpen(false); - resetForm(); - }; - - const addAddress = async (data: FormData) => { - if (!contextLoaded || !user || !token) return; - setIsUploadingData(true); - const bodyToSend = { - ...data, - country, - type: ADDRESS_TYPE.OTHER, - }; - try { - const res = await postAuthenticatedRequest
( - tenantConfig.id, - '/app/addresses', - bodyToSend, - token, - logoutUser - ); - if (res && setUserAddresses) { - setUserAddresses((prevAddresses) => [...prevAddresses, res]); - handleCancel(); - } - } catch (error) { - resetForm(); - setIsUploadingData(false); - setErrors(handleError(error as APIError)); - } finally { - setIsUploadingData(false); - setIsModalOpen(false); - } - }; - const handleInputChange = (value: string) => { - setInputValue(value); - }; - - const handleAddressSelect = (address: string) => { - handleGetAddress(address); - }; - return ( -
-

{tAddressManagement('addAddress')}

- - {isUploadingData ? ( -
- -
- ) : ( -
- - -
- )} -
- ); -}; - -export default AddAddressForm; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx new file mode 100644 index 0000000000..6afbc34347 --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx @@ -0,0 +1,108 @@ +import type { ExtendedCountryCode } from '../../../../common/types/country'; +import type { SetState } from '../../../../common/types/common'; +import type { Address, APIError } from '@planet-sdk/common'; + +import { useState, useContext, useCallback } from 'react'; +import { useTranslations } from 'next-intl'; +import { handleError } from '@planet-sdk/common'; +import { useUserProps } from '../../../../common/Layout/UserPropsContext'; +import { putAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; +import { useTenant } from '../../../../common/Layout/TenantContext'; +import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; +import AddressForm from './microComponents/AddressForm'; +import AddressFormWrapper from './microComponents/AddressFormWrapper'; + +export type FormData = { + address: string | undefined; + address2: string | null; + city: string | undefined; + zipCode: string | undefined; + state: string | null; +}; + +interface Props { + setIsModalOpen: SetState; + selectedAddressForAction: Address | null; + fetchUserAddresses?: () => Promise; +} + +const EditAddress = ({ + setIsModalOpen, + selectedAddressForAction, + fetchUserAddresses, +}: Props) => { + const defaultAddressDetail = { + address: selectedAddressForAction?.address, + address2: selectedAddressForAction?.address2, + city: selectedAddressForAction?.city, + zipCode: selectedAddressForAction?.zipCode, + state: selectedAddressForAction?.state, + }; + + const tAddressManagement = useTranslations('Profile.addressManagement'); + const { contextLoaded, user, token, logoutUser } = useUserProps(); + const { tenantConfig } = useTenant(); + const { setErrors } = useContext(ErrorHandlingContext); + const [country, setCountry] = useState( + selectedAddressForAction?.country ?? 'DE' + ); + const [isLoading, setIsLoading] = useState(false); + + const updateAddress = useCallback( + async (data: FormData) => { + if (!contextLoaded || !user || !token) return; + setIsLoading(true); + const bodyToSend = { + ...data, + country, + type: selectedAddressForAction?.type, + }; + try { + const res = await putAuthenticatedRequest
( + tenantConfig.id, + `/app/addresses/${selectedAddressForAction?.id}`, + bodyToSend, + token, + logoutUser + ); + if (res && fetchUserAddresses) { + fetchUserAddresses(); + } + } catch (error) { + setErrors(handleError(error as APIError)); + } finally { + setIsLoading(false); + setIsModalOpen(false); + } + }, + [ + contextLoaded, + user, + token, + country, + selectedAddressForAction?.type, + selectedAddressForAction?.id, + tenantConfig.id, + logoutUser, + fetchUserAddresses, + handleError, + putAuthenticatedRequest, + ] + ); + + return ( + + + + ); +}; + +export default EditAddress; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx deleted file mode 100644 index 25ab96047b..0000000000 --- a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx +++ /dev/null @@ -1,193 +0,0 @@ -import type { AddressSuggestionsType } from '../../../../common/types/geocoder'; -import type { ExtendedCountryCode } from '../../../../common/types/country'; -import type { SetState } from '../../../../common/types/common'; -import type { Address, APIError } from '@planet-sdk/common'; - -import { useState, useContext, useMemo, useCallback } from 'react'; -import { useForm } from 'react-hook-form'; -import { useTranslations } from 'next-intl'; -import { CircularProgress } from '@mui/material'; -import { handleError } from '@planet-sdk/common'; -import styles from './AddressManagement.module.scss'; -import WebappButton from '../../../../common/WebappButton'; -import { useUserProps } from '../../../../common/Layout/UserPropsContext'; -import { putAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; -import { useTenant } from '../../../../common/Layout/TenantContext'; -import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; -import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; -import AddressFormInputs from './microComponents/AddressFormInputs'; -import { - fetchAddressDetails, - geocoder, - getPostalRegex, - suggestAddress, -} from '../../../../../utils/addressManagement'; - -export type FormData = { - address: string | undefined; - address2: string | null; - city: string | undefined; - zipCode: string | undefined; - state: string | null; -}; - -interface Props { - setIsModalOpen: SetState; - selectedAddressForAction: Address | null; - fetchUserAddresses?: () => Promise; -} - -const EditAddressForm = ({ - setIsModalOpen, - selectedAddressForAction, - fetchUserAddresses, -}: Props) => { - const defaultAddressDetail = { - address: selectedAddressForAction?.address, - address2: selectedAddressForAction?.address2, - city: selectedAddressForAction?.city, - zipCode: selectedAddressForAction?.zipCode, - state: selectedAddressForAction?.state, - }; - const { - control, - handleSubmit, - setValue, - reset, - formState: { errors }, - } = useForm({ - mode: 'onBlur', - defaultValues: defaultAddressDetail, - }); - - const tAddressManagement = useTranslations('Profile.addressManagement'); - const tCommon = useTranslations('Common'); - const { contextLoaded, user, token, logoutUser } = useUserProps(); - const { tenantConfig } = useTenant(); - const { setErrors } = useContext(ErrorHandlingContext); - const [country, setCountry] = useState( - selectedAddressForAction?.country ?? 'DE' - ); - const [addressSuggestions, setAddressSuggestions] = useState< - AddressSuggestionsType[] - >([]); - const [inputValue, setInputValue] = useState(''); - const [isUploadingData, setIsUploadingData] = useState(false); - - const handleSuggestAddress = useCallback( - async (value: string) => { - const suggestions = await suggestAddress(value, country); - setAddressSuggestions(suggestions); - }, - [geocoder, country] - ); - - const handleGetAddress = useCallback( - async (value: string) => { - const details = await fetchAddressDetails(value); - if (details) { - setValue('address', details.address, { shouldValidate: true }); - setValue('city', details.city, { shouldValidate: true }); - setValue('zipCode', details.zipCode, { shouldValidate: true }); - } - setAddressSuggestions([]); - }, - [geocoder, setValue] - ); - useDebouncedEffect( - () => { - if (inputValue) { - handleSuggestAddress(inputValue); - } - }, - 700, - [inputValue] - ); - - const postalRegex = useMemo(() => getPostalRegex(country), [country]); - - const resetForm = () => { - reset(defaultAddressDetail); - setAddressSuggestions([]); - }; - const handleCancel = () => { - setIsModalOpen(false); - resetForm(); - }; - const handleInputChange = (value: string) => { - setInputValue(value); - }; - - const handleAddressSelect = (address: string) => { - handleGetAddress(address); - }; - - const updateAddress = async (data: FormData) => { - if (!contextLoaded || !user || !token) return; - setIsUploadingData(true); - const bodyToSend = { - ...data, - country, - type: selectedAddressForAction?.type, - }; - try { - const res = await putAuthenticatedRequest
( - tenantConfig.id, - `/app/addresses/${selectedAddressForAction?.id}`, - bodyToSend, - token, - logoutUser - ); - if (res && fetchUserAddresses) { - fetchUserAddresses(); - handleCancel(); - } - } catch (error) { - setIsUploadingData(false); - setErrors(handleError(error as APIError)); - } finally { - setIsUploadingData(false); - setIsModalOpen(false); - } - }; - - return ( -
-

{tAddressManagement('editAddress')}

- - {isUploadingData ? ( -
- -
- ) : ( -
- - -
- )} -
- ); -}; - -export default EditAddressForm; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index d9924808d6..bcce87f56d 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -17,8 +17,8 @@ import { addressTypeOrder, } from '../../../../../utils/addressManagement'; import CenteredContainer from '../../../../common/Layout/CenteredContainer'; -import EditAddressForm from './EditAddressForm'; -import AddAddressForm from './AddAddressForm'; +import EditAddress from './EditAddress'; +import AddAddress from './AddAddress'; const AddressManagement = () => { const { user, contextLoaded, token, logoutUser } = useUserProps(); @@ -67,14 +67,14 @@ const AddressManagement = () => { switch (addressAction) { case ADDRESS_ACTIONS.ADD: return ( - ); case ADDRESS_ACTIONS.EDIT: return ( - { fetchUserAddresses, ]); - return userAddresses.length > 0 ? ( + return (

{tAddressManagement('addressManagementTitle')} @@ -112,7 +112,7 @@ const AddressManagement = () => { <>{renderModalContent}

- ) : null; + ); }; export default AddressManagement; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 3dccf44b5f..0f4265166a 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -1,6 +1,6 @@ import type { SetState } from '../../../../../common/types/common'; import type { AddressAction } from '../../../../../common/types/profile'; -import type { AddressType, Address } from '@planet-sdk/common'; +import type { Address } from '@planet-sdk/common'; import { useState } from 'react'; import { useTranslations } from 'next-intl'; @@ -18,7 +18,6 @@ export interface AddressActionItem { shouldRender: boolean; } interface Props { - type: AddressType; addressCount: number; setAddressAction: SetState; setIsModalOpen: SetState; @@ -27,7 +26,6 @@ interface Props { } const AddressActionsMenu = ({ - type, addressCount, setAddressAction, setIsModalOpen, @@ -38,7 +36,7 @@ const AddressActionsMenu = ({ const [popoverAnchor, setPopoverAnchor] = useState( null ); - + const { type } = userAddress; const addressActionConfig: AddressActionItem[] = [ { label: tAddressManagement(`actions.edit`), diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx similarity index 58% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx index 3a37bd476b..061447ccba 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormInputs.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx @@ -1,42 +1,115 @@ -import type { Control, FieldErrors } from 'react-hook-form'; import type { AddressSuggestionsType } from '../../../../../common/types/geocoder'; import type { ExtendedCountryCode } from '../../../../../common/types/country'; -import type { FormData } from '../AddAddressForm'; +import type { FormData } from '../AddAddress'; import type { SetState } from '../../../../../common/types/common'; +import type { Nullable } from '@planet-sdk/common/build/types/util'; -import { TextField } from '@mui/material'; +import { useCallback, useMemo, useState } from 'react'; +import { CircularProgress, TextField } from '@mui/material'; import { useTranslations } from 'next-intl'; -import { Controller } from 'react-hook-form'; -import { validationPattern } from '../../../../../../utils/addressManagement'; +import { Controller, useForm } from 'react-hook-form'; +import { + fetchAddressDetails, + geocoder, + getPostalRegex, + suggestAddress, + validationPattern, +} from '../../../../../../utils/addressManagement'; import InlineFormDisplayGroup from '../../../../../common/Layout/Forms/InlineFormDisplayGroup'; import styles from '../AddressManagement.module.scss'; import AddressInput from './AddressInput'; import CountrySelect from '../../../../../common/InputTypes/AutoCompleteCountry'; import { allCountries } from '../../../../../../utils/constants/countries'; +import AddressFormButtons from './AddressFormButtons'; +import { useDebouncedEffect } from '../../../../../../utils/useDebouncedEffect'; interface Props { - handleInputChange: (value: string) => void; - handleAddressSelect: (value: string) => void; - addressSuggestions: AddressSuggestionsType[]; - control: Control; - errors: FieldErrors; - postalRegex: RegExp | undefined; country: ExtendedCountryCode | ''; setCountry: SetState; + label: string; + processFormData: (data: FormData) => Promise; + defaultAddressDetail: { + address: string | undefined; + address2: Nullable | undefined; + city: string | undefined; + zipCode: string | undefined; + state: Nullable | undefined; + }; + setIsModalOpen: SetState; + isLoading: boolean; } -const AddressFormInputs = ({ - handleInputChange, - handleAddressSelect, - addressSuggestions, - control, - errors, - postalRegex, +const AddressForm = ({ country, setCountry, + defaultAddressDetail, + setIsModalOpen, + label, + processFormData, + isLoading, }: Props) => { const t = useTranslations('EditProfile'); const tAddressManagement = useTranslations('Profile'); + const [addressSuggestions, setAddressSuggestions] = useState< + AddressSuggestionsType[] + >([]); + const { + control, + handleSubmit, + setValue, + reset, + formState: { errors }, + } = useForm({ + mode: 'onBlur', + defaultValues: defaultAddressDetail, + }); + const [inputValue, setInputValue] = useState(''); + const postalRegex = useMemo(() => getPostalRegex(country), [country]); + const handleInputChange = (value: string) => { + setInputValue(value); + }; + + const handleSuggestAddress = useCallback( + async (value: string) => { + const suggestions = await suggestAddress(value, country); + setAddressSuggestions(suggestions); + }, + [geocoder, country] + ); + + useDebouncedEffect( + () => { + if (inputValue) { + handleSuggestAddress(inputValue); + } + }, + 700, + [inputValue] + ); + const handleGetAddress = useCallback( + async (value: string) => { + const details = await fetchAddressDetails(value); + if (details) { + setValue('address', details.address, { shouldValidate: true }); + setValue('city', details.city, { shouldValidate: true }); + setValue('zipCode', details.zipCode, { shouldValidate: true }); + } + setAddressSuggestions([]); + }, + [geocoder, setValue] + ); + const handleAddressSelect = (address: string) => { + handleGetAddress(address); + }; + + const resetForm = () => { + reset(defaultAddressDetail); + setAddressSuggestions([]); + }; + const handleCancel = () => { + setIsModalOpen(false); + resetForm(); + }; return ( + {isLoading ? ( +
+ +
+ ) : ( + + )} ); }; -export default AddressFormInputs; +export default AddressForm; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormButtons.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormButtons.tsx new file mode 100644 index 0000000000..3ccd3f41c1 --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormButtons.tsx @@ -0,0 +1,33 @@ +import styles from '../AddressManagement.module.scss'; +import WebappButton from '../../../../../common/WebappButton'; +import { useTranslations } from 'next-intl'; + +interface Props { + text: string; + handleSubmit: () => void; + handleCancel: () => void; +} + +const AddressFormButtons = ({ text, handleSubmit, handleCancel }: Props) => { + const tCommon = useTranslations('Common'); + return ( +
+ + +
+ ); +}; + +export default AddressFormButtons; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormWrapper.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormWrapper.tsx new file mode 100644 index 0000000000..3ff11d694c --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormWrapper.tsx @@ -0,0 +1,17 @@ +import type { JSX } from 'react'; +import styles from '../AddressManagement.module.scss'; + +interface Props { + children: JSX.Element; + label: string; +} +const AddressFormLayout = ({ children, label }: Props) => { + return ( +
+

{label}

+ {children} +
+ ); +}; + +export default AddressFormLayout; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx index 295d7079fc..3be49a9cd1 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx @@ -25,7 +25,6 @@ const SingleAddress = ({
Date: Fri, 29 Nov 2024 10:57:53 +0530 Subject: [PATCH 69/88] fix: handle cases where the user has no address --- .../EditProfile/AddressManagment/index.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index bcce87f56d..dec83a8560 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -87,19 +87,22 @@ const AddressManagement = () => { selectedAddressForAction, fetchUserAddresses, ]); - + const shouldRenderAddressList = + user?.addresses !== undefined && user.addresses.length > 0; return (

{tAddressManagement('addressManagementTitle')}

- + {shouldRenderAddressList && ( + + )} Date: Fri, 29 Nov 2024 11:11:36 +0530 Subject: [PATCH 70/88] refactor: consolidate translation resources --- public/static/locales/en/profile.json | 12 +++++++----- .../EditProfile/AddressManagment/AddAddress.tsx | 4 ++-- .../EditProfile/AddressManagment/EditAddress.tsx | 4 ++-- .../Settings/EditProfile/AddressManagment/index.tsx | 2 +- .../AddressManagment/microComponents/AddressForm.tsx | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index 96cbfdd302..c45b0b2f1b 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -147,11 +147,13 @@ "setAsPrimaryAddress": "Set as Primary Address", "setAsBillingAddress": "Set as Billing Address" }, - "addNewAddress": "Add New Address", - "addAddress": "Add Address", - "editAddress": "Edit Address", - "address2": "Address 2(optional)", - "saveChanges": "Save Changes" + "addAddress": "Add New Address", + "addressForm": { + "addAddress": "Add Address", + "editAddress": "Edit Address", + "saveChanges": "Save Changes", + "address2": "Address 2(optional)" + } } } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx index 959d6ba223..83a3f954a6 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx @@ -86,13 +86,13 @@ const AddAddress = ({ setIsModalOpen, setUserAddresses }: Props) => { ); return ( - + diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx index 6afbc34347..aed253f0e9 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx @@ -91,13 +91,13 @@ const EditAddress = ({ ); return ( - + diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index dec83a8560..3621cd9777 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -104,7 +104,7 @@ const AddressManagement = () => { /> )} Date: Fri, 29 Nov 2024 11:35:21 +0530 Subject: [PATCH 71/88] refactor: initialize country state with prioritized userCountry value --- .../Settings/EditProfile/AddressManagment/AddAddress.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx index 83a3f954a6..6bcea87e19 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx @@ -12,6 +12,7 @@ import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingCon import AddressForm from './microComponents/AddressForm'; import { ADDRESS_TYPE } from '../../../../../utils/addressManagement'; import AddressFormWrapper from './microComponents/AddressFormWrapper'; +import { getStoredConfig } from '../../../../../utils/storeConfig'; export type FormData = { address: string | undefined; @@ -37,11 +38,11 @@ const defaultAddressDetail = { const AddAddress = ({ setIsModalOpen, setUserAddresses }: Props) => { const tAddressManagement = useTranslations('Profile.addressManagement'); const { contextLoaded, user, token, logoutUser } = useUserProps(); + const configCountry = getStoredConfig('country'); + const userCountry = user?.country || configCountry || 'DE'; const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const [country, setCountry] = useState( - user?.country ?? 'DE' - ); + const [country, setCountry] = useState(userCountry); const [isLoading, setIsLoading] = useState(false); const addAddress = useCallback( From 36a67d68788989222d1d1c4c58bc1cbbfb4a7029 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Mon, 2 Dec 2024 13:35:00 +0530 Subject: [PATCH 72/88] refactor: address the feedbacks. - rename variable userCountry -> defaultCountry. - rename component and className AddressFormWrapper -> AddressFormLayout. - add margin-top to .formButtonContainer for spacing. - use flex-end instead of end (Terminal warning). --- .../EditProfile/AddressManagment/AddAddress.tsx | 12 +++++++----- .../AddressManagment/AddressManagement.module.scss | 9 +++++---- .../EditProfile/AddressManagment/EditAddress.tsx | 6 +++--- ...{AddressFormWrapper.tsx => AddressFormLayout.tsx} | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) rename src/features/user/Settings/EditProfile/AddressManagment/microComponents/{AddressFormWrapper.tsx => AddressFormLayout.tsx} (86%) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx index 6bcea87e19..389d126c12 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx @@ -11,7 +11,7 @@ import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import AddressForm from './microComponents/AddressForm'; import { ADDRESS_TYPE } from '../../../../../utils/addressManagement'; -import AddressFormWrapper from './microComponents/AddressFormWrapper'; +import AddressFormLayout from './microComponents/AddressFormLayout'; import { getStoredConfig } from '../../../../../utils/storeConfig'; export type FormData = { @@ -39,10 +39,12 @@ const AddAddress = ({ setIsModalOpen, setUserAddresses }: Props) => { const tAddressManagement = useTranslations('Profile.addressManagement'); const { contextLoaded, user, token, logoutUser } = useUserProps(); const configCountry = getStoredConfig('country'); - const userCountry = user?.country || configCountry || 'DE'; + const defaultCountry = user?.country || configCountry || 'DE'; const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const [country, setCountry] = useState(userCountry); + const [country, setCountry] = useState( + defaultCountry + ); const [isLoading, setIsLoading] = useState(false); const addAddress = useCallback( @@ -87,7 +89,7 @@ const AddAddress = ({ setIsModalOpen, setUserAddresses }: Props) => { ); return ( - + { defaultAddressDetail={defaultAddressDetail} processFormData={addAddress} /> - + ); }; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index 54a6350369..d03d3e9933 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -95,7 +95,7 @@ } // address action form -.addressFormContainer { +.addressFormLayout { display: flex; flex-direction: column; gap: 40px; @@ -121,9 +121,9 @@ .formButtonContainer { display: flex; - gap: 8px; justify-content: space-between; - align-items: end; + align-items: flex-end; + margin-top: 25px; .addAddressButton, .cancelButton { min-width: 252px; @@ -131,13 +131,14 @@ } @include xsPhoneView { - .addressFormContainer { + .addressFormLayout { min-width: fit-content; width: 95%; } .formButtonContainer { display: flex; flex-direction: column; + gap: 8px; .addAddressButton, .cancelButton { width: 100%; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx index aed253f0e9..e4820d0ad9 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx @@ -10,7 +10,7 @@ import { putAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useTenant } from '../../../../common/Layout/TenantContext'; import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; import AddressForm from './microComponents/AddressForm'; -import AddressFormWrapper from './microComponents/AddressFormWrapper'; +import AddressFormLayout from './microComponents/AddressFormLayout'; export type FormData = { address: string | undefined; @@ -91,7 +91,7 @@ const EditAddress = ({ ); return ( - + - + ); }; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormWrapper.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormLayout.tsx similarity index 86% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormWrapper.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormLayout.tsx index 3ff11d694c..eb8d176746 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormWrapper.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormLayout.tsx @@ -7,7 +7,7 @@ interface Props { } const AddressFormLayout = ({ children, label }: Props) => { return ( -
+

{label}

{children}
From 9ff86732d207510313bdadf432064b6a668e8b13 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Mon, 2 Dec 2024 15:10:22 +0530 Subject: [PATCH 73/88] refactor: remove unneeded files --- .../AddressManagment/AddAddressForm.tsx | 190 ----------------- .../AddressManagment/EditAddressForm.tsx | 193 ------------------ .../microComponents/AddressContent.tsx | 24 --- 3 files changed, 407 deletions(-) delete mode 100644 src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx delete mode 100644 src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx delete mode 100644 src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx deleted file mode 100644 index b2e98cf566..0000000000 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddressForm.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import type { AddressSuggestionsType } from '../../../../common/types/geocoder'; -import type { ExtendedCountryCode } from '../../../../common/types/country'; -import type { SetState } from '../../../../common/types/common'; -import type { Address, APIError } from '@planet-sdk/common'; - -import { useState, useContext, useMemo, useCallback } from 'react'; -import { useForm } from 'react-hook-form'; -import { useTranslations } from 'next-intl'; -import { CircularProgress } from '@mui/material'; -import { handleError } from '@planet-sdk/common'; -import styles from './AddressManagement.module.scss'; -import WebappButton from '../../../../common/WebappButton'; -import { useUserProps } from '../../../../common/Layout/UserPropsContext'; -import { postAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; -import { useTenant } from '../../../../common/Layout/TenantContext'; -import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; -import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; -import AddressFormInputs from './microComponents/AddressFormInputs'; -import { - ADDRESS_TYPE, - fetchAddressDetails, - geocoder, - getPostalRegex, - suggestAddress, -} from '../../../../../utils/addressManagement'; - -export type FormData = { - address: string | undefined; - address2: string | null; - city: string | undefined; - zipCode: string | undefined; - state: string | null; -}; - -interface Props { - setIsModalOpen: SetState; - setUserAddresses: SetState; -} - -const AddAddressForm = ({ setIsModalOpen, setUserAddresses }: Props) => { - const defaultAddressDetail = { - address: '', - address2: '', - city: '', - zipCode: '', - state: '', - }; - const { - control, - handleSubmit, - setValue, - reset, - formState: { errors }, - } = useForm({ - mode: 'onBlur', - defaultValues: defaultAddressDetail, - }); - - const tProfile = useTranslations('Profile.addressManagement'); - const tCommon = useTranslations('Common'); - const { contextLoaded, user, token, logoutUser } = useUserProps(); - const { tenantConfig } = useTenant(); - const { setErrors } = useContext(ErrorHandlingContext); - const [country, setCountry] = useState( - user?.country ?? 'DE' - ); - const [addressSuggestions, setAddressSuggestions] = useState< - AddressSuggestionsType[] - >([]); - const [inputValue, setInputValue] = useState(''); - const [isUploadingData, setIsUploadingData] = useState(false); - - const handleSuggestAddress = useCallback( - async (value: string) => { - const suggestions = await suggestAddress(value, country); - setAddressSuggestions(suggestions); - }, - [geocoder, country] - ); - - const handleGetAddress = useCallback( - async (value: string) => { - const details = await fetchAddressDetails(value); - if (details) { - setValue('address', details.address, { shouldValidate: true }); - setValue('city', details.city, { shouldValidate: true }); - setValue('zipCode', details.zipCode, { shouldValidate: true }); - } - setAddressSuggestions([]); - }, - [geocoder, setValue] - ); - - useDebouncedEffect( - () => { - if (inputValue) { - handleSuggestAddress(inputValue); - } - }, - 700, - [inputValue] - ); - - const postalRegex = useMemo(() => getPostalRegex(country), [country]); - - const resetForm = () => { - reset(defaultAddressDetail); - setAddressSuggestions([]); - }; - const handleCancel = () => { - setIsModalOpen(false); - resetForm(); - }; - - const addAddress = async (data: FormData) => { - if (!contextLoaded || !user || !token) return; - setIsUploadingData(true); - const bodyToSend = { - ...data, - country, - type: ADDRESS_TYPE.OTHER, - }; - try { - const res = await postAuthenticatedRequest
( - tenantConfig.id, - '/app/addresses', - bodyToSend, - token, - logoutUser - ); - if (res && setUserAddresses) { - setUserAddresses((prevAddresses) => [...prevAddresses, res]); - handleCancel(); - } - } catch (error) { - resetForm(); - setIsUploadingData(false); - setErrors(handleError(error as APIError)); - } finally { - setIsUploadingData(false); - setIsModalOpen(false); - } - }; - const handleInputChange = (value: string) => { - setInputValue(value); - }; - - const handleAddressSelect = (address: string) => { - handleGetAddress(address); - }; - return ( -
-

{tProfile('addAddress')}

- - {isUploadingData ? ( -
- -
- ) : ( -
- - -
- )} -
- ); -}; - -export default AddAddressForm; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx deleted file mode 100644 index 7371908f33..0000000000 --- a/src/features/user/Settings/EditProfile/AddressManagment/EditAddressForm.tsx +++ /dev/null @@ -1,193 +0,0 @@ -import type { AddressSuggestionsType } from '../../../../common/types/geocoder'; -import type { ExtendedCountryCode } from '../../../../common/types/country'; -import type { SetState } from '../../../../common/types/common'; -import type { Address, APIError } from '@planet-sdk/common'; - -import { useState, useContext, useMemo, useCallback } from 'react'; -import { useForm } from 'react-hook-form'; -import { useTranslations } from 'next-intl'; -import { CircularProgress } from '@mui/material'; -import { handleError } from '@planet-sdk/common'; -import styles from './AddressManagement.module.scss'; -import WebappButton from '../../../../common/WebappButton'; -import { useUserProps } from '../../../../common/Layout/UserPropsContext'; -import { putAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; -import { useTenant } from '../../../../common/Layout/TenantContext'; -import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; -import { useDebouncedEffect } from '../../../../../utils/useDebouncedEffect'; -import AddressFormInputs from './microComponents/AddressFormInputs'; -import { - fetchAddressDetails, - geocoder, - getPostalRegex, - suggestAddress, -} from '../../../../../utils/addressManagement'; - -export type FormData = { - address: string | undefined; - address2: string | null; - city: string | undefined; - zipCode: string | undefined; - state: string | null; -}; - -interface Props { - setIsModalOpen: SetState; - selectedAddressForAction: Address | null; - fetchUserAddresses?: () => Promise; -} - -const EditAddressForm = ({ - setIsModalOpen, - selectedAddressForAction, - fetchUserAddresses, -}: Props) => { - const defaultAddressDetail = { - address: selectedAddressForAction?.address, - address2: selectedAddressForAction?.address2, - city: selectedAddressForAction?.city, - zipCode: selectedAddressForAction?.zipCode, - state: selectedAddressForAction?.state, - }; - const { - control, - handleSubmit, - setValue, - reset, - formState: { errors }, - } = useForm({ - mode: 'onBlur', - defaultValues: defaultAddressDetail, - }); - - const tProfile = useTranslations('Profile.addressManagement'); - const tCommon = useTranslations('Common'); - const { contextLoaded, user, token, logoutUser } = useUserProps(); - const { tenantConfig } = useTenant(); - const { setErrors } = useContext(ErrorHandlingContext); - const [country, setCountry] = useState( - selectedAddressForAction?.country ?? 'DE' - ); - const [addressSuggestions, setAddressSuggestions] = useState< - AddressSuggestionsType[] - >([]); - const [inputValue, setInputValue] = useState(''); - const [isUploadingData, setIsUploadingData] = useState(false); - - const handleSuggestAddress = useCallback( - async (value: string) => { - const suggestions = await suggestAddress(value, country); - setAddressSuggestions(suggestions); - }, - [geocoder, country] - ); - - const handleGetAddress = useCallback( - async (value: string) => { - const details = await fetchAddressDetails(value); - if (details) { - setValue('address', details.address, { shouldValidate: true }); - setValue('city', details.city, { shouldValidate: true }); - setValue('zipCode', details.zipCode, { shouldValidate: true }); - } - setAddressSuggestions([]); - }, - [geocoder, setValue] - ); - useDebouncedEffect( - () => { - if (inputValue) { - handleSuggestAddress(inputValue); - } - }, - 700, - [inputValue] - ); - - const postalRegex = useMemo(() => getPostalRegex(country), [country]); - - const resetForm = () => { - reset(defaultAddressDetail); - setAddressSuggestions([]); - }; - const handleCancel = () => { - setIsModalOpen(false); - resetForm(); - }; - const handleInputChange = (value: string) => { - setInputValue(value); - }; - - const handleAddressSelect = (address: string) => { - handleGetAddress(address); - }; - - const updateAddress = async (data: FormData) => { - if (!contextLoaded || !user || !token) return; - setIsUploadingData(true); - const bodyToSend = { - ...data, - country, - type: selectedAddressForAction?.type, - }; - try { - const res = await putAuthenticatedRequest
( - tenantConfig.id, - `/app/addresses/${selectedAddressForAction?.id}`, - bodyToSend, - token, - logoutUser - ); - if (res && fetchUserAddresses) { - fetchUserAddresses(); - handleCancel(); - } - } catch (error) { - setIsUploadingData(false); - setErrors(handleError(error as APIError)); - } finally { - setIsUploadingData(false); - setIsModalOpen(false); - } - }; - - return ( -
-

{tProfile('editAddress')}

- - {isUploadingData ? ( -
- -
- ) : ( -
- - -
- )} -
- ); -}; - -export default EditAddressForm; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx deleted file mode 100644 index 0571498de9..0000000000 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressContent.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import type { AddressType } from '@planet-sdk/common'; - -import styles from '../AddressManagement.module.scss'; -import { useTranslations } from 'next-intl'; - -interface Props { - type: AddressType; - userAddress: string; -} -const AddressContent = ({ type, userAddress }: Props) => { - const tProfile = useTranslations('Profile.addressManagement'); - return ( -
- {type !== 'other' && ( - - {tProfile(`addressType.${type}`)} - - )} -
{userAddress}
-
- ); -}; - -export default AddressContent; From 3837dc7db7968bcdef96026e2a6ad3c7b5031162 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 4 Dec 2024 11:43:55 +0530 Subject: [PATCH 74/88] refactor: rename component/function/props. - fetchUserAddresses -> updateUserAddresses - AddressDeleteModal -> DeleteAddress - AddressTypeConfirmationModal -> UpdateAddressType --- ...dressDeleteModal.tsx => DeleteAddress.tsx} | 10 +++++----- .../AddressManagment/EditAddress.tsx | 10 +++++----- ...rmationModal.tsx => UpdateAddressType.tsx} | 10 +++++----- .../EditProfile/AddressManagment/index.tsx | 20 +++++++++---------- 4 files changed, 25 insertions(+), 25 deletions(-) rename src/features/user/Settings/EditProfile/AddressManagment/{AddressDeleteModal.tsx => DeleteAddress.tsx} (93%) rename src/features/user/Settings/EditProfile/AddressManagment/{AddressTypeConfirmationModal.tsx => UpdateAddressType.tsx} (94%) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx similarity index 93% rename from src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx index a15baaa377..d1b764ead9 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressDeleteModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx @@ -15,13 +15,13 @@ import { deleteAuthenticatedRequest } from '../../../../../utils/apiRequests/api interface Props { setIsModalOpen: SetState; addressId: string | undefined; - fetchUserAddresses: () => Promise; + updateUserAddresses: () => Promise; } -const AddressDeleteModal = ({ +const DeleteAddress = ({ setIsModalOpen, addressId, - fetchUserAddresses, + updateUserAddresses, }: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); @@ -40,7 +40,7 @@ const AddressDeleteModal = ({ token, logoutUser ); - fetchUserAddresses(); + updateUserAddresses(); } catch (error) { setErrors(handleError(error as APIError)); } finally { @@ -75,4 +75,4 @@ const AddressDeleteModal = ({
); }; -export default AddressDeleteModal; +export default DeleteAddress; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx index 1f9d370228..8d263b4f35 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx @@ -16,13 +16,13 @@ import AddressFormLayout from './microComponents/AddressFormLayout'; interface Props { setIsModalOpen: SetState; selectedAddressForAction: Address | null; - fetchUserAddresses?: () => Promise; + updateUserAddresses?: () => Promise; } const EditAddress = ({ setIsModalOpen, selectedAddressForAction, - fetchUserAddresses, + updateUserAddresses, }: Props) => { const defaultAddressDetail = { address: selectedAddressForAction?.address, @@ -58,8 +58,8 @@ const EditAddress = ({ token, logoutUser ); - if (res && fetchUserAddresses) { - fetchUserAddresses(); + if (res && updateUserAddresses) { + updateUserAddresses(); } } catch (error) { setErrors(handleError(error as APIError)); @@ -77,7 +77,7 @@ const EditAddress = ({ selectedAddressForAction?.id, tenantConfig.id, logoutUser, - fetchUserAddresses, + updateUserAddresses, handleError, putAuthenticatedRequest, ] diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx b/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx similarity index 94% rename from src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx rename to src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx index 8454fe73af..43f9e6d69c 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressTypeConfirmationModal.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx @@ -18,15 +18,15 @@ interface Props { setIsModalOpen: SetState; userAddress: Address | undefined; selectedAddressForAction: Address | null; - fetchUserAddresses: () => Promise; + updateUserAddresses: () => Promise; } -const AddressTypeConfirmationModal = ({ +const UpdateAddressType = ({ addressType, setIsModalOpen, userAddress, selectedAddressForAction, - fetchUserAddresses, + updateUserAddresses, }: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); @@ -49,7 +49,7 @@ const AddressTypeConfirmationModal = ({ token, logoutUser ); - if (res) fetchUserAddresses(); + if (res) updateUserAddresses(); } catch (error) { setErrors(handleError(error as APIError)); } finally { @@ -97,4 +97,4 @@ const AddressTypeConfirmationModal = ({ ); }; -export default AddressTypeConfirmationModal; +export default UpdateAddressType; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 0add9cf9a8..979d6ed30d 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -19,8 +19,8 @@ import { findAddressByType, } from '../../../../../utils/addressManagement'; import CenteredContainer from '../../../../common/Layout/CenteredContainer'; -import AddressTypeConfirmationModal from './AddressTypeConfirmationModal'; -import AddressDeleteModal from './AddressDeleteModal'; +import UpdateAddressType from './UpdateAddressType'; +import DeleteAddress from './DeleteAddress'; import EditAddress from './EditAddress'; import AddAddress from './AddAddress'; @@ -47,7 +47,7 @@ const AddressManagement = () => { }); }, [userAddresses]); - const fetchUserAddresses = useCallback(async () => { + const updateUserAddresses = useCallback(async () => { if (!user || !token || !contextLoaded) return; try { const res = await getAuthenticatedRequest( @@ -77,7 +77,7 @@ const AddressManagement = () => { const addrTypeConfProps = { setIsModalOpen, selectedAddressForAction, - fetchUserAddresses, + updateUserAddresses, }; const renderModalContent = useMemo(() => { switch (addressAction) { @@ -93,20 +93,20 @@ const AddressManagement = () => { ); case ADDRESS_ACTIONS.DELETE: return ( - ); case ADDRESS_ACTIONS.SET_PRIMARY: return ( - { ); case ADDRESS_ACTIONS.SET_BILLING: return ( - { setIsModalOpen, setUserAddresses, selectedAddressForAction, - fetchUserAddresses, + updateUserAddresses, primaryAddress, billingAddress, addressAction, From 6783400f5d288d3dad22331f5b4cfc7bdd95ea9c Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 4 Dec 2024 12:26:23 +0530 Subject: [PATCH 75/88] "refactor: reset addressAction state when the modal is opened or closed --- .../EditProfile/AddressManagment/AddAddress.tsx | 10 +++++++++- .../EditProfile/AddressManagment/DeleteAddress.tsx | 10 +++++++++- .../EditProfile/AddressManagment/EditAddress.tsx | 5 +++++ .../EditProfile/AddressManagment/UpdateAddressType.tsx | 10 +++++++++- .../Settings/EditProfile/AddressManagment/index.tsx | 6 ++++++ .../AddressManagment/microComponents/AddressForm.tsx | 4 ++++ 6 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx index 389d126c12..bdffb022db 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx @@ -1,6 +1,7 @@ import type { ExtendedCountryCode } from '../../../../common/types/country'; import type { SetState } from '../../../../common/types/common'; import type { Address, APIError } from '@planet-sdk/common'; +import type { AddressAction } from '../../../../common/types/profile'; import { useState, useContext, useCallback } from 'react'; import { useTranslations } from 'next-intl'; @@ -25,6 +26,7 @@ export type FormData = { interface Props { setIsModalOpen: SetState; setUserAddresses: SetState; + setAddressAction: SetState; } const defaultAddressDetail = { @@ -35,7 +37,11 @@ const defaultAddressDetail = { state: '', }; -const AddAddress = ({ setIsModalOpen, setUserAddresses }: Props) => { +const AddAddress = ({ + setIsModalOpen, + setUserAddresses, + setAddressAction, +}: Props) => { const tAddressManagement = useTranslations('Profile.addressManagement'); const { contextLoaded, user, token, logoutUser } = useUserProps(); const configCountry = getStoredConfig('country'); @@ -72,6 +78,7 @@ const AddAddress = ({ setIsModalOpen, setUserAddresses }: Props) => { } finally { setIsLoading(false); setIsModalOpen(false); + setAddressAction(null); } }, [ @@ -98,6 +105,7 @@ const AddAddress = ({ setIsModalOpen, setUserAddresses }: Props) => { label={tAddressManagement('addressForm.addAddress')} defaultAddressDetail={defaultAddressDetail} processFormData={addAddress} + setAddressAction={setAddressAction} /> ); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx index d1b764ead9..10733681ad 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx @@ -1,5 +1,6 @@ import type { SetState } from '../../../../common/types/common'; import type { APIError } from '@planet-sdk/common'; +import type { AddressAction } from '../../../../common/types/profile'; import { useContext, useState } from 'react'; import { useTranslations } from 'next-intl'; @@ -16,12 +17,14 @@ interface Props { setIsModalOpen: SetState; addressId: string | undefined; updateUserAddresses: () => Promise; + setAddressAction: SetState; } const DeleteAddress = ({ setIsModalOpen, addressId, updateUserAddresses, + setAddressAction, }: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); @@ -46,8 +49,13 @@ const DeleteAddress = ({ } finally { setIsModalOpen(false); setIsLoading(false); + setAddressAction(null); } }; + const handleCancel = () => { + setIsModalOpen(false); + setAddressAction(null); + }; return (

{tProfile('deleteAddress')}

@@ -58,7 +66,7 @@ const DeleteAddress = ({ text={tCommon('cancel')} elementType="button" variant="secondary" - onClick={() => setIsModalOpen(false)} + onClick={handleCancel} /> ; selectedAddressForAction: Address | null; updateUserAddresses?: () => Promise; + setAddressAction: SetState; } const EditAddress = ({ setIsModalOpen, selectedAddressForAction, updateUserAddresses, + setAddressAction, }: Props) => { const defaultAddressDetail = { address: selectedAddressForAction?.address, @@ -66,6 +69,7 @@ const EditAddress = ({ } finally { setIsLoading(false); setIsModalOpen(false); + setAddressAction(null); } }, [ @@ -93,6 +97,7 @@ const EditAddress = ({ label={tAddressManagement('addressForm.saveChanges')} defaultAddressDetail={defaultAddressDetail} processFormData={updateAddress} + setAddressAction={setAddressAction} /> ); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx b/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx index 43f9e6d69c..1d577309e5 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx @@ -1,5 +1,6 @@ import type { SetState } from '../../../../common/types/common'; import type { APIError, Address } from '@planet-sdk/common'; +import type { AddressAction } from '../../../../common/types/profile'; import { useContext, useState } from 'react'; import { useTranslations } from 'next-intl'; @@ -19,6 +20,7 @@ interface Props { userAddress: Address | undefined; selectedAddressForAction: Address | null; updateUserAddresses: () => Promise; + setAddressAction: SetState; } const UpdateAddressType = ({ @@ -27,6 +29,7 @@ const UpdateAddressType = ({ userAddress, selectedAddressForAction, updateUserAddresses, + setAddressAction, }: Props) => { const tProfile = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); @@ -55,8 +58,13 @@ const UpdateAddressType = ({ } finally { setIsUploadingData(false); setIsModalOpen(false); + setAddressAction(null); } }; + const handleCancel = () => { + setIsModalOpen(false); + setAddressAction(null); + }; return (

@@ -79,7 +87,7 @@ const UpdateAddressType = ({ text={tCommon('cancel')} elementType="button" variant="secondary" - onClick={() => setIsModalOpen(false)} + onClick={handleCancel} /> { selectedAddressForAction, updateUserAddresses, }; + console.log(isModalOpen, addressAction, '==1'); const renderModalContent = useMemo(() => { switch (addressAction) { case ADDRESS_ACTIONS.ADD: @@ -86,6 +87,7 @@ const AddressManagement = () => { ); case ADDRESS_ACTIONS.EDIT: @@ -94,6 +96,7 @@ const AddressManagement = () => { setIsModalOpen={setIsModalOpen} selectedAddressForAction={selectedAddressForAction} updateUserAddresses={updateUserAddresses} + setAddressAction={setAddressAction} /> ); case ADDRESS_ACTIONS.DELETE: @@ -102,6 +105,7 @@ const AddressManagement = () => { addressId={selectedAddressForAction?.id} setIsModalOpen={setIsModalOpen} updateUserAddresses={updateUserAddresses} + setAddressAction={setAddressAction} /> ); case ADDRESS_ACTIONS.SET_PRIMARY: @@ -109,6 +113,7 @@ const AddressManagement = () => { ); @@ -117,6 +122,7 @@ const AddressManagement = () => { ); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx index 3710a2ec1b..2ac75226bf 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx @@ -3,6 +3,7 @@ import type { ExtendedCountryCode } from '../../../../../common/types/country'; import type { SetState } from '../../../../../common/types/common'; import type { Nullable } from '@planet-sdk/common/build/types/util'; import type { FormData } from '../AddAddress'; +import type { AddressAction } from '../../../../../common/types/profile'; import { useCallback, useMemo, useState } from 'react'; import { CircularProgress, TextField } from '@mui/material'; @@ -37,6 +38,7 @@ interface Props { }; setIsModalOpen: SetState; isLoading: boolean; + setAddressAction: SetState; } const AddressForm = ({ @@ -47,6 +49,7 @@ const AddressForm = ({ label, processFormData, isLoading, + setAddressAction, }: Props) => { const t = useTranslations('EditProfile'); const tAddressManagement = useTranslations('Profile'); @@ -108,6 +111,7 @@ const AddressForm = ({ }; const handleCancel = () => { setIsModalOpen(false); + setAddressAction(null); resetForm(); }; return ( From 075a427a1129a1af2e6f29c011ff99d3431ecd40 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 4 Dec 2024 12:57:55 +0530 Subject: [PATCH 76/88] refactor: minor code clean up --- .../AddressManagment/DeleteAddress.tsx | 2 +- .../AddressManagment/UpdateAddressType.tsx | 2 +- .../EditProfile/AddressManagment/index.tsx | 15 +++++++-------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx index 10733681ad..55c55861c5 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx @@ -57,7 +57,7 @@ const DeleteAddress = ({ setAddressAction(null); }; return ( -
+

{tProfile('deleteAddress')}

{tProfile('deleteAddressConfirmationMessage')}

{!isLoading ? ( diff --git a/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx b/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx index 1d577309e5..4db9f82dce 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx @@ -66,7 +66,7 @@ const UpdateAddressType = ({ setAddressAction(null); }; return ( -
+

{tProfile(`addressType.${addressType}`)}

diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 8b71adbe2f..5ba2c1493b 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -74,12 +74,7 @@ const AddressManagement = () => { () => findAddressByType(userAddresses, ADDRESS_TYPE.MAILING), [userAddresses] ); - const addrTypeConfProps = { - setIsModalOpen, - selectedAddressForAction, - updateUserAddresses, - }; - console.log(isModalOpen, addressAction, '==1'); + const renderModalContent = useMemo(() => { switch (addressAction) { case ADDRESS_ACTIONS.ADD: @@ -114,7 +109,9 @@ const AddressManagement = () => { addressType={ADDRESS_TYPE.PRIMARY} userAddress={primaryAddress} setAddressAction={setAddressAction} - {...addrTypeConfProps} + setIsModalOpen={setIsModalOpen} + selectedAddressForAction={selectedAddressForAction} + updateUserAddresses={updateUserAddresses} /> ); case ADDRESS_ACTIONS.SET_BILLING: @@ -123,7 +120,9 @@ const AddressManagement = () => { addressType={ADDRESS_TYPE.MAILING} userAddress={billingAddress} setAddressAction={setAddressAction} - {...addrTypeConfProps} + setIsModalOpen={setIsModalOpen} + selectedAddressForAction={selectedAddressForAction} + updateUserAddresses={updateUserAddresses} /> ); } From 9e154b65038a7e3b9d69fd1b40bf8e74969d3126 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:20:38 +0530 Subject: [PATCH 77/88] refactor: simplify translation interpolation --- public/static/locales/en/profile.json | 3 +-- .../AddressManagment/AddressManagement.module.scss | 4 ++-- .../EditProfile/AddressManagment/UpdateAddressType.tsx | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index 9894c3445c..8f816a7198 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -149,10 +149,9 @@ }, "deleteAddress": "Delete Address", "delete": "Delete", - "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType, select, mailing {billing} other {{addressType}}} address? {isAddressSet, select, true {This will replace your current {addressType, select, mailing {billing} other {{addressType}}} address.} other {}}", + "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType}? {isAddressSet, select, true {This will replace your current {addressType}.} other {}}", "deleteAddressConfirmationMessage": "Are you sure you want to delete this address? If you want to use it again, please add it as a new address.", "confirm": "Confirm", - "address2": "Address 2(optional)", "addAddress": "Add New Address", "addressForm": { "addAddress": "Add Address", diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index cec942cda8..37744643c7 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -125,7 +125,7 @@ } } } -.addrConfirmContainer { +.addressActionContainer { width: 468px; display: flex; gap: 10px; @@ -167,7 +167,7 @@ } } } - .addrConfirmContainer { + .addressActionContainer { width: 95%; .buttonContainer { flex-direction: column; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx b/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx index 4db9f82dce..0962ec3b36 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx @@ -72,7 +72,7 @@ const UpdateAddressType = ({

{tProfile('addressConfirmationMessage', { - addressType, + addressType: tProfile(`addressType.${addressType}`), isAddressSet: !!userAddress, })}

From ef5ce97789fd951e34e7646e63a0f6de03d49866 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:38:19 +0530 Subject: [PATCH 78/88] refactor: rename tProfile to tAddressManagement --- .../EditProfile/AddressManagment/DeleteAddress.tsx | 8 ++++---- .../EditProfile/AddressManagment/UpdateAddressType.tsx | 10 +++++----- .../AddressManagment/microComponents/AddressForm.tsx | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx index 55c55861c5..884daeaee2 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx @@ -26,7 +26,7 @@ const DeleteAddress = ({ updateUserAddresses, setAddressAction, }: Props) => { - const tProfile = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); @@ -58,8 +58,8 @@ const DeleteAddress = ({ }; return (
-

{tProfile('deleteAddress')}

-

{tProfile('deleteAddressConfirmationMessage')}

+

{tAddressManagement('deleteAddress')}

+

{tAddressManagement('deleteAddressConfirmationMessage')}

{!isLoading ? (
{ - const tProfile = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('Profile.addressManagement'); const tCommon = useTranslations('Common'); const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); @@ -68,11 +68,11 @@ const UpdateAddressType = ({ return (

- {tProfile(`addressType.${addressType}`)} + {tAddressManagement(`addressType.${addressType}`)}

- {tProfile('addressConfirmationMessage', { - addressType: tProfile(`addressType.${addressType}`), + {tAddressManagement('addressConfirmationMessage', { + addressType: tAddressManagement(`addressType.${addressType}`), isAddressSet: !!userAddress, })}

@@ -90,7 +90,7 @@ const UpdateAddressType = ({ onClick={handleCancel} /> updateAddress(addressType)} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx index 2ac75226bf..4eefefa5fa 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx @@ -52,7 +52,7 @@ const AddressForm = ({ setAddressAction, }: Props) => { const t = useTranslations('EditProfile'); - const tAddressManagement = useTranslations('Profile'); + const tAddressManagement = useTranslations('Profile.addressManagement'); const [addressSuggestions, setAddressSuggestions] = useState< AddressSuggestionsType[] >([]); @@ -133,7 +133,7 @@ const AddressForm = ({ Date: Wed, 4 Dec 2024 15:02:41 +0530 Subject: [PATCH 79/88] refactor: define constant for max address limit --- .../user/Settings/EditProfile/AddressManagment/index.tsx | 5 +++-- src/utils/addressManagement.ts | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 6501e23af9..3f0fd15ed5 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -17,6 +17,7 @@ import { ADDRESS_TYPE, addressTypeOrder, findAddressByType, + MAX_ADDRESS_LIMIT, } from '../../../../../utils/addressManagement'; import CenteredContainer from '../../../../common/Layout/CenteredContainer'; import AddressTypeConfirmationModal from './AddressTypeConfirmationModal'; @@ -132,8 +133,8 @@ const AddressManagement = () => { billingAddress, addressAction, ]); - const maxAddressLimit = 5; - const canAddMoreAddresses = userAddresses.length < maxAddressLimit; + + const canAddMoreAddresses = userAddresses.length < MAX_ADDRESS_LIMIT; return userAddresses.length > 0 ? (

diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index ceb1ac9096..33f40119cb 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -28,6 +28,8 @@ export const ADDRESS_FORM_TYPE = { } as const; export const addressTypeOrder = ['primary', 'mailing', 'other']; +export const MAX_ADDRESS_LIMIT = 5; + export const getFormattedAddress = ( zipCode: string | undefined, city: string | undefined, From 035c34ed8d5326ecf0a48b0bfc79f5b0f5cb17e3 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:06:02 +0530 Subject: [PATCH 80/88] refactor: update address confirmation messages for clarity and structure --- public/static/locales/en/profile.json | 3 ++- .../EditProfile/AddressManagment/UpdateAddressType.tsx | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index 8f816a7198..4250a713bf 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -149,7 +149,8 @@ }, "deleteAddress": "Delete Address", "delete": "Delete", - "addressConfirmationMessage": "Are you sure you want to set this address as your {addressType}? {isAddressSet, select, true {This will replace your current {addressType}.} other {}}", + "setAddressConfirmation": "Are you sure you want to set this address as your {addressType}?", + "replaceAddressWarning": " This will replace your current {addressType}.", "deleteAddressConfirmationMessage": "Are you sure you want to delete this address? If you want to use it again, please add it as a new address.", "confirm": "Confirm", "addAddress": "Add New Address", diff --git a/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx b/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx index cca6ca0bb0..e24e1351ac 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx @@ -71,10 +71,13 @@ const UpdateAddressType = ({ {tAddressManagement(`addressType.${addressType}`)}

- {tAddressManagement('addressConfirmationMessage', { + {tAddressManagement('setAddressConfirmation', { addressType: tAddressManagement(`addressType.${addressType}`), - isAddressSet: !!userAddress, })} + {userAddress && + tAddressManagement('replaceAddressWarning', { + addressType: tAddressManagement(`addressType.${addressType}`), + })}

{userAddress !== undefined && (
From b64c57f9b37a0706c5b587a415255b8a6119c172 Mon Sep 17 00:00:00 2001 From: mohitb35 <44917347+mohitb35@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:14:10 +0530 Subject: [PATCH 81/88] fix: corrects import path for ADDRESS_ACTIONS while creating AddressAction type --- src/features/common/types/profile.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/common/types/profile.d.ts b/src/features/common/types/profile.d.ts index 88aa9a940c..532583abdc 100644 --- a/src/features/common/types/profile.d.ts +++ b/src/features/common/types/profile.d.ts @@ -1,7 +1,7 @@ import type { User, UserPublicProfile } from '@planet-sdk/common'; import type { SetState } from './common'; import type { PublicUser } from './user'; -import type { ADDRESS_ACTIONS } from '../../user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu'; +import type { ADDRESS_ACTIONS } from '../../../utils/addressManagement'; export interface UserFeaturesProps { handleShare: () => void; From 8ade0d7d8d7b74de348c8f27594e3e77cb032e5b Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 4 Dec 2024 17:29:49 +0530 Subject: [PATCH 82/88] refactor: replace SCSS variables with direct values --- .../AddressManagement.module.scss | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss index c15b23d3fd..6407a604f7 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss @@ -1,9 +1,5 @@ @import '../../../../../theme/theme'; -$border-radius-sm: 8px; -$border-radius-lg: 16px; -$padding-standard: 24px; - @mixin flex-container($direction: row, $justify: space-between) { display: flex; flex-direction: $direction; @@ -16,16 +12,16 @@ $padding-standard: 24px; top: 50%; transform: translate(-50%, -50%); padding: 20px; - border-radius: $border-radius-lg; + border-radius: 16px; background: rgba(255, 255, 255, 1); } // Base Components - .addressManagement { @include flex-container(column); margin-top: 40px; gap: 20px; + .maxAddress { font-size: $fontXSmall; color: #6c757d; @@ -47,10 +43,11 @@ $padding-standard: 24px; @include flex-container; width: 100%; background: rgba(242, 242, 242, 0.5); - border-radius: $border-radius-sm; + border-radius: 8px; font-size: $fontSmall; font-weight: 400; - padding: $padding-standard 10px $padding-standard $padding-standard; + padding: 24px 10px 24px 24px; + .kebabMenuButton { display: flex; justify-content: center; @@ -60,10 +57,12 @@ $padding-standard: 24px; border-radius: 50%; background-color: transparent; cursor: pointer; + svg { height: 20px; width: 12px; } + &:hover { background-color: rgba(120, 120, 120, 0.1); } @@ -73,6 +72,7 @@ $padding-standard: 24px; .addressDetails { @include flex-container(column, center); gap: 16px; + span { padding: 5px 10px; max-width: fit-content; @@ -83,6 +83,7 @@ $padding-standard: 24px; line-height: 16px; font-weight: 600; } + p { margin-top: 2px; } @@ -103,12 +104,15 @@ $padding-standard: 24px; cursor: pointer; padding: 2px 12px; list-style: none; + .action { font-size: $fontXSmall; font-weight: 400; } + li { - padding: 8px 0px; + padding: 8px 0; + &:not(:last-child) { border-bottom: 1px solid rgba(189, 189, 189, 1); } @@ -116,75 +120,86 @@ $padding-standard: 24px; } // Modal Forms - .header { font-weight: 700; font-size: $fontSixteen; } + .addressFormLayout { @include flex-container(column); @include modal-container; min-width: 565px; gap: 40px; + .addressForm { @include flex-container(column); gap: 23px; } + .buttonContainer { @include flex-container; gap: 8px; margin-top: 25px; + button { flex: 1 1; } } } + .addressActionContainer { @include flex-container(column); @include modal-container; width: 468px; gap: 10px; + .address { width: 100%; background: rgba(242, 242, 242, 0.5); - border-radius: $border-radius-sm; + border-radius: 8px; font-size: $fontSmall; font-weight: 400; - padding: $padding-standard; + padding: 24px; } + .buttonContainer { @include flex-container; gap: 8px; margin-top: 40px; + button { flex: 1 1; } } } -// Mobile style +// Mobile Style @include xsPhoneView { .addressFormLayout { min-width: fit-content; width: 95%; + .buttonContainer { @include flex-container(column); + button { width: 100%; } } } + .addressActionContainer { width: 95%; min-width: fit-content; + .buttonContainer { flex-direction: column; gap: 8px; } } } -// Form spinner +// Form Spinner .addressMgmtSpinner { @include flex-container(row, center); } From 2e3127663c867eacc0258fbf268d9821ee12fe1d Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:42:20 +0530 Subject: [PATCH 83/88] refactor: group the addressManagement translation resources. - move addressManagement translation resources (profile.json -> editProfile.json). --- public/static/locales/en/editProfile.json | 33 +++++++++++++++++++ public/static/locales/en/profile.json | 27 --------------- .../AddressManagment/AddAddress.tsx | 2 +- .../AddressManagment/DeleteAddress.tsx | 12 ++++--- .../AddressManagment/EditAddress.tsx | 2 +- .../AddressManagment/UpdateAddressType.tsx | 8 ++--- .../EditProfile/AddressManagment/index.tsx | 6 ++-- .../microComponents/AddressActionMenu.tsx | 2 +- .../microComponents/AddressDetails.tsx | 2 +- .../microComponents/AddressForm.tsx | 3 +- 10 files changed, 53 insertions(+), 44 deletions(-) diff --git a/public/static/locales/en/editProfile.json b/public/static/locales/en/editProfile.json index 6d03eac1df..9f274e25d5 100644 --- a/public/static/locales/en/editProfile.json +++ b/public/static/locales/en/editProfile.json @@ -68,6 +68,39 @@ "websiteInvalid": "Please enter valid Website URL", "countryRequired": "Country is required", "companyRequired": "Company Name is required" + }, + "addressManagement": { + "addressManagementTitle": "Address", + "addressType": { + "primary": "Primary Address", + "mailing": "Billing Address" + }, + "actions": { + "edit": "Edit", + "delete": "Delete", + "setAsPrimaryAddress": "Set as Primary Address", + "setAsBillingAddress": "Set as Billing Address", + "addAddress": "Add New Address" + }, + "deleteAction": { + "deleteAddress": "Delete Address", + "delete": "Delete", + "deleteAddressConfirmationMessage": "Are you sure you want to delete this address? If you want to use it again, please add it as a new address." + }, + "addressPrompts": { + "setAddressConfirmation": "Are you sure you want to set this address as your {addressType}?", + "confirm": "Confirm" + }, + "addressNotifications": { + "maxAddressesMessage": "You have reached the maximum number of addresses! Remove one to add a new address.", + "replaceAddressWarning": "This will replace your current {addressType}." + }, + "addressForm": { + "addAddress": "Add Address", + "editAddress": "Edit Address", + "saveChanges": "Save Changes", + "address2": "Address 2(optional)" + } } } } diff --git a/public/static/locales/en/profile.json b/public/static/locales/en/profile.json index fdbf4c196e..2bddb971aa 100644 --- a/public/static/locales/en/profile.json +++ b/public/static/locales/en/profile.json @@ -134,33 +134,6 @@ "lifeOnLand": "Life on land", "partnership": "Partnerships for the goals" } - }, - "addressManagement": { - "addressManagementTitle": "Address", - "addressType": { - "primary": "Primary Address", - "mailing": "Billing Address" - }, - "actions": { - "edit": "Edit", - "delete": "Delete", - "setAsPrimaryAddress": "Set as Primary Address", - "setAsBillingAddress": "Set as Billing Address" - }, - "deleteAddress": "Delete Address", - "delete": "Delete", - "setAddressConfirmation": "Are you sure you want to set this address as your {addressType}?", - "replaceAddressWarning": " This will replace your current {addressType}.", - "deleteAddressConfirmationMessage": "Are you sure you want to delete this address? If you want to use it again, please add it as a new address.", - "maxAddressesMessage": "You have reached the maximum number of addresses! Remove one to add a new address.", - "confirm": "Confirm", - "addAddress": "Add New Address", - "addressForm": { - "addAddress": "Add Address", - "editAddress": "Edit Address", - "saveChanges": "Save Changes", - "address2": "Address 2(optional)" - } } } } diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx index bdffb022db..bada5fb106 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx @@ -42,7 +42,7 @@ const AddAddress = ({ setUserAddresses, setAddressAction, }: Props) => { - const tAddressManagement = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('EditProfile.addressManagement'); const { contextLoaded, user, token, logoutUser } = useUserProps(); const configCountry = getStoredConfig('country'); const defaultCountry = user?.country || configCountry || 'DE'; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx index 884daeaee2..5752c0645b 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx @@ -26,7 +26,7 @@ const DeleteAddress = ({ updateUserAddresses, setAddressAction, }: Props) => { - const tAddressManagement = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('EditProfile.addressManagement'); const tCommon = useTranslations('Common'); const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); @@ -58,8 +58,12 @@ const DeleteAddress = ({ }; return (
-

{tAddressManagement('deleteAddress')}

-

{tAddressManagement('deleteAddressConfirmationMessage')}

+

+ {tAddressManagement('deleteAction.deleteAddress')} +

+

+ {tAddressManagement('deleteAction.deleteAddressConfirmationMessage')} +

{!isLoading ? (
{ - const tAddressManagement = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('EditProfile.addressManagement'); const tCommon = useTranslations('Common'); const { contextLoaded, user, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); @@ -71,11 +71,11 @@ const UpdateAddressType = ({ {tAddressManagement(`addressType.${addressType}`)}

- {tAddressManagement('setAddressConfirmation', { + {tAddressManagement('addressPrompts.setAddressConfirmation', { addressType: tAddressManagement(`addressType.${addressType}`), })} {userAddress && - tAddressManagement('replaceAddressWarning', { + tAddressManagement('addressNotifications.replaceAddressWarning', { addressType: tAddressManagement(`addressType.${addressType}`), })}

@@ -93,7 +93,7 @@ const UpdateAddressType = ({ onClick={handleCancel} /> updateAddress(addressType)} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index e78c626114..66758c31e1 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -29,7 +29,7 @@ const AddressManagement = () => { const { user, contextLoaded, token, logoutUser } = useUserProps(); const { tenantConfig } = useTenant(); const { setErrors } = useContext(ErrorHandlingContext); - const tAddressManagement = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('EditProfile.addressManagement'); const [userAddresses, setUserAddresses] = useState( user?.addresses ?? [] ); @@ -156,7 +156,7 @@ const AddressManagement = () => { )} {canAddMoreAddresses ? ( { /> ) : (

- {tAddressManagement('maxAddressesMessage')} + {tAddressManagement('addressNotifications.maxAddressesMessage')}

)} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index 0f4265166a..c9f66b8eeb 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -32,7 +32,7 @@ const AddressActionsMenu = ({ setSelectedAddressForAction, userAddress, }: Props) => { - const tAddressManagement = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('EditProfile.addressManagement'); const [popoverAnchor, setPopoverAnchor] = useState( null ); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx index 2212331e9a..3245cca8f1 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx @@ -9,7 +9,7 @@ interface Props { } const AddressDetails = ({ userAddress }: Props) => { const { type } = userAddress; - const tAddressManagement = useTranslations('Profile.addressManagement'); + const tAddressManagement = useTranslations('EditProfile.addressManagement'); return (
diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx index 4eefefa5fa..49ae875178 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx @@ -52,7 +52,6 @@ const AddressForm = ({ setAddressAction, }: Props) => { const t = useTranslations('EditProfile'); - const tAddressManagement = useTranslations('Profile.addressManagement'); const [addressSuggestions, setAddressSuggestions] = useState< AddressSuggestionsType[] >([]); @@ -133,7 +132,7 @@ const AddressForm = ({ Date: Fri, 6 Dec 2024 10:28:55 +0530 Subject: [PATCH 84/88] refactor: organize address management translation keys for consistency --- public/static/locales/en/editProfile.json | 14 ++++++-------- .../EditProfile/AddressManagment/DeleteAddress.tsx | 4 ++-- .../AddressManagment/UpdateAddressType.tsx | 6 +++--- .../EditProfile/AddressManagment/index.tsx | 2 +- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/public/static/locales/en/editProfile.json b/public/static/locales/en/editProfile.json index 9f274e25d5..b9c2b250b2 100644 --- a/public/static/locales/en/editProfile.json +++ b/public/static/locales/en/editProfile.json @@ -83,18 +83,16 @@ "addAddress": "Add New Address" }, "deleteAction": { - "deleteAddress": "Delete Address", - "delete": "Delete", + "title": "Delete Address", + "deleteButton": "Delete", "deleteAddressConfirmationMessage": "Are you sure you want to delete this address? If you want to use it again, please add it as a new address." }, - "addressPrompts": { + "updateAddressType": { "setAddressConfirmation": "Are you sure you want to set this address as your {addressType}?", - "confirm": "Confirm" - }, - "addressNotifications": { - "maxAddressesMessage": "You have reached the maximum number of addresses! Remove one to add a new address.", - "replaceAddressWarning": "This will replace your current {addressType}." + "replaceAddressWarning": "This will replace your current {addressType}.", + "confirmButton": "Confirm" }, + "maxAddressesMessage": "You have reached the maximum number of addresses! Remove one to add a new address.", "addressForm": { "addAddress": "Add Address", "editAddress": "Edit Address", diff --git a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx index 5752c0645b..b285392902 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx @@ -59,7 +59,7 @@ const DeleteAddress = ({ return (

- {tAddressManagement('deleteAction.deleteAddress')} + {tAddressManagement('deleteAction.title')}

{tAddressManagement('deleteAction.deleteAddressConfirmationMessage')} @@ -73,7 +73,7 @@ const DeleteAddress = ({ onClick={handleCancel} />

- {tAddressManagement('addressPrompts.setAddressConfirmation', { + {tAddressManagement('updateAddressType.setAddressConfirmation', { addressType: tAddressManagement(`addressType.${addressType}`), })} {userAddress && - tAddressManagement('addressNotifications.replaceAddressWarning', { + tAddressManagement('updateAddressType.replaceAddressWarning', { addressType: tAddressManagement(`addressType.${addressType}`), })}

@@ -93,7 +93,7 @@ const UpdateAddressType = ({ onClick={handleCancel} /> updateAddress(addressType)} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index 66758c31e1..a79a75182f 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -164,7 +164,7 @@ const AddressManagement = () => { /> ) : (

- {tAddressManagement('addressNotifications.maxAddressesMessage')} + {tAddressManagement('maxAddressesMessage')}

)} From e5e093f5db333a7acc9c851630c605e17d70b82c Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 11 Dec 2024 13:33:33 +0530 Subject: [PATCH 85/88] feat: add unset billing address option to the address action menu. --- public/static/locales/en/editProfile.json | 4 +- .../AddressManagment/UnsetBillingAddress.tsx | 98 +++++++++++++++++++ .../EditProfile/AddressManagment/index.tsx | 11 +++ .../microComponents/AddressActionMenu.tsx | 5 + src/utils/addressManagement.ts | 1 + 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx diff --git a/public/static/locales/en/editProfile.json b/public/static/locales/en/editProfile.json index b9c2b250b2..2b21a25775 100644 --- a/public/static/locales/en/editProfile.json +++ b/public/static/locales/en/editProfile.json @@ -80,6 +80,7 @@ "delete": "Delete", "setAsPrimaryAddress": "Set as Primary Address", "setAsBillingAddress": "Set as Billing Address", + "unsetBillingAddress": "Unset Billing Address", "addAddress": "Add New Address" }, "deleteAction": { @@ -90,7 +91,8 @@ "updateAddressType": { "setAddressConfirmation": "Are you sure you want to set this address as your {addressType}?", "replaceAddressWarning": "This will replace your current {addressType}.", - "confirmButton": "Confirm" + "confirmButton": "Confirm", + "unsetBillingAddressMessage": "Do you want to unset your billing address? Your primary address will be used as billing address." }, "maxAddressesMessage": "You have reached the maximum number of addresses! Remove one to add a new address.", "addressForm": { diff --git a/src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx new file mode 100644 index 0000000000..8c1e091876 --- /dev/null +++ b/src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx @@ -0,0 +1,98 @@ +import type { Address, APIError } from '@planet-sdk/common'; +import type { SetState } from '../../../../common/types/common'; +import type { AddressAction } from '../../../../common/types/profile'; + +import { useContext, useState } from 'react'; +import { useTranslations } from 'next-intl'; +import { CircularProgress } from '@mui/material'; +import { handleError } from '@planet-sdk/common'; +import styles from './AddressManagement.module.scss'; +import WebappButton from '../../../../common/WebappButton'; +import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext'; +import { putAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; +import { useUserProps } from '../../../../common/Layout/UserPropsContext'; +import { useTenant } from '../../../../common/Layout/TenantContext'; + +interface Props { + addressType: 'mailing'; + setIsModalOpen: SetState; + setAddressAction: SetState; + updateUserAddresses: () => Promise; + selectedAddressForAction: Address | null; +} + +const UnsetBillingAddress = ({ + addressType, + setIsModalOpen, + setAddressAction, + updateUserAddresses, + selectedAddressForAction, +}: Props) => { + const tAddressManagement = useTranslations('EditProfile.addressManagement'); + const tCommon = useTranslations('Common'); + const { contextLoaded, user, token, logoutUser } = useUserProps(); + const { setErrors } = useContext(ErrorHandlingContext); + const { tenantConfig } = useTenant(); + const [isLoading, setIsLoading] = useState(false); + + const unsetAddress = async () => { + if (!contextLoaded || !user || !token) return; + setIsLoading(true); + const bodyToSend = { + type: 'other', + }; + try { + const res = await putAuthenticatedRequest
( + tenantConfig.id, + `/app/addresses/${selectedAddressForAction?.id}`, + bodyToSend, + token, + logoutUser + ); + if (res) updateUserAddresses(); + } catch (error) { + setErrors(handleError(error as APIError)); + } finally { + setIsLoading(false); + setIsModalOpen(false); + setAddressAction(null); + } + }; + + const handleCancel = () => { + setIsModalOpen(false); + setAddressAction(null); + }; + return ( +
+

+ {tAddressManagement(`addressType.${addressType}`)} +

+

+ {tAddressManagement('updateAddressType.unsetBillingAddressMessage')} +

+ {!isLoading ? ( +
+ + +
+ ) : ( +
+ +
+ )} +
+ ); +}; + +export default UnsetBillingAddress; diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx index a79a75182f..70d0a14b90 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/index.tsx @@ -24,6 +24,7 @@ import UpdateAddressType from './UpdateAddressType'; import DeleteAddress from './DeleteAddress'; import EditAddress from './EditAddress'; import AddAddress from './AddAddress'; +import UnsetBillingAddress from './UnsetBillingAddress'; const AddressManagement = () => { const { user, contextLoaded, token, logoutUser } = useUserProps(); @@ -126,6 +127,16 @@ const AddressManagement = () => { updateUserAddresses={updateUserAddresses} /> ); + case ADDRESS_ACTIONS.UNSET_BILLING: + return ( + + ); } }, [ setIsModalOpen, diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index c9f66b8eeb..fd91011754 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -62,6 +62,11 @@ const AddressActionsMenu = ({ type === ADDRESS_TYPE.MAILING || type === ADDRESS_TYPE.PRIMARY ), }, + { + label: tAddressManagement('actions.unsetBillingAddress'), + action: ADDRESS_ACTIONS.UNSET_BILLING, + shouldRender: type === ADDRESS_TYPE.MAILING, + }, ]; const openPopover = (event: React.MouseEvent) => { diff --git a/src/utils/addressManagement.ts b/src/utils/addressManagement.ts index 33f40119cb..c974b00739 100644 --- a/src/utils/addressManagement.ts +++ b/src/utils/addressManagement.ts @@ -20,6 +20,7 @@ export const ADDRESS_ACTIONS = { DELETE: 'delete', SET_PRIMARY: 'setPrimary', SET_BILLING: 'setBilling', + UNSET_BILLING: 'unsetBilling', } as const; export const ADDRESS_FORM_TYPE = { From bfe457db033000f9998452608c11a2e6c6da3523 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:35:18 +0530 Subject: [PATCH 86/88] feat: hide delete option for primary address --- .../EditProfile/AddressManagment/UnsetBillingAddress.tsx | 3 ++- .../AddressManagment/microComponents/AddressActionMenu.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx index 8c1e091876..775521b79c 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx @@ -12,6 +12,7 @@ import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingCon import { putAuthenticatedRequest } from '../../../../../utils/apiRequests/api'; import { useUserProps } from '../../../../common/Layout/UserPropsContext'; import { useTenant } from '../../../../common/Layout/TenantContext'; +import { ADDRESS_TYPE } from '../../../../../utils/addressManagement'; interface Props { addressType: 'mailing'; @@ -39,7 +40,7 @@ const UnsetBillingAddress = ({ if (!contextLoaded || !user || !token) return; setIsLoading(true); const bodyToSend = { - type: 'other', + type: ADDRESS_TYPE.OTHER, }; try { const res = await putAuthenticatedRequest
( diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx index fd91011754..a7a183bc7e 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx @@ -46,7 +46,7 @@ const AddressActionsMenu = ({ { label: tAddressManagement(`actions.delete`), action: ADDRESS_ACTIONS.DELETE, - shouldRender: addressCount > 1, + shouldRender: addressCount > 1 && type !== ADDRESS_TYPE.PRIMARY, }, { label: tAddressManagement('actions.setAsPrimaryAddress'), From e1b69ad544e224ec92bf590e5f24b475e71fce6e Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 12 Dec 2024 10:15:16 +0530 Subject: [PATCH 87/88] refactor: address coderabbit points --- .../AddAddress.tsx | 0 .../AddressManagement.module.scss | 0 .../DeleteAddress.tsx | 0 .../EditAddress.tsx | 4 +--- .../UnsetBillingAddress.tsx | 5 +++-- .../UpdateAddressType.tsx | 0 .../{AddressManagment => AddressManagement}/index.tsx | 6 ++++-- .../microComponents/AddressActionMenu.tsx | 9 ++++++++- .../microComponents/AddressDetails.tsx | 0 .../microComponents/AddressForm.tsx | 0 .../microComponents/AddressFormButtons.tsx | 0 .../microComponents/AddressFormLayout.tsx | 0 .../microComponents/AddressInput.tsx | 0 .../microComponents/AddressList.tsx | 0 .../microComponents/FormattedAddressBlock.tsx | 0 .../microComponents/SingleAddress.tsx | 0 src/features/user/Settings/EditProfile/index.tsx | 2 +- 17 files changed, 17 insertions(+), 9 deletions(-) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/AddAddress.tsx (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/AddressManagement.module.scss (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/DeleteAddress.tsx (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/EditAddress.tsx (97%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/UnsetBillingAddress.tsx (95%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/UpdateAddressType.tsx (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/index.tsx (97%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/microComponents/AddressActionMenu.tsx (94%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/microComponents/AddressDetails.tsx (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/microComponents/AddressForm.tsx (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/microComponents/AddressFormButtons.tsx (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/microComponents/AddressFormLayout.tsx (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/microComponents/AddressInput.tsx (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/microComponents/AddressList.tsx (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/microComponents/FormattedAddressBlock.tsx (100%) rename src/features/user/Settings/EditProfile/{AddressManagment => AddressManagement}/microComponents/SingleAddress.tsx (100%) diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/AddAddress.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss b/src/features/user/Settings/EditProfile/AddressManagement/AddressManagement.module.scss similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/AddressManagement.module.scss rename to src/features/user/Settings/EditProfile/AddressManagement/AddressManagement.module.scss diff --git a/src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/DeleteAddress.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx similarity index 97% rename from src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx index 9743889938..c0a80cd21e 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx @@ -61,9 +61,7 @@ const EditAddress = ({ token, logoutUser ); - if (res && updateUserAddresses) { - updateUserAddresses(); - } + if (res && updateUserAddresses) updateUserAddresses(); } catch (error) { setErrors(handleError(error as APIError)); } finally { diff --git a/src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx similarity index 95% rename from src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx index 775521b79c..f72aae589b 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/UnsetBillingAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx @@ -37,7 +37,8 @@ const UnsetBillingAddress = ({ const [isLoading, setIsLoading] = useState(false); const unsetAddress = async () => { - if (!contextLoaded || !user || !token) return; + if (!contextLoaded || !user || !token || !selectedAddressForAction?.id) + return; setIsLoading(true); const bodyToSend = { type: ADDRESS_TYPE.OTHER, @@ -45,7 +46,7 @@ const UnsetBillingAddress = ({ try { const res = await putAuthenticatedRequest
( tenantConfig.id, - `/app/addresses/${selectedAddressForAction?.id}`, + `/app/addresses/${selectedAddressForAction.id}`, bodyToSend, token, logoutUser diff --git a/src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx b/src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/UpdateAddressType.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx b/src/features/user/Settings/EditProfile/AddressManagement/index.tsx similarity index 97% rename from src/features/user/Settings/EditProfile/AddressManagment/index.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/index.tsx index 70d0a14b90..2357e1236a 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagement/index.tsx @@ -137,6 +137,8 @@ const AddressManagement = () => { selectedAddressForAction={selectedAddressForAction} /> ); + default: + return <>; } }, [ setIsModalOpen, @@ -179,8 +181,8 @@ const AddressManagement = () => {

)} - - <>{renderModalContent} + + {renderModalContent}
); diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressActionMenu.tsx similarity index 94% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressActionMenu.tsx index a7a183bc7e..da36448e4a 100644 --- a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressActionMenu.tsx @@ -89,7 +89,13 @@ const AddressActionsMenu = ({ return (
- handleActionClick(item.action)} role="button" + aria-label={item.label} > {item.label} diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressDetails.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressDetails.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressDetails.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressForm.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormButtons.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressFormButtons.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormButtons.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressFormButtons.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormLayout.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressFormLayout.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressFormLayout.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressFormLayout.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressInput.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressInput.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressInput.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressInput.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressList.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/AddressList.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressList.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/FormattedAddressBlock.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/FormattedAddressBlock.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/FormattedAddressBlock.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/microComponents/FormattedAddressBlock.tsx diff --git a/src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/SingleAddress.tsx similarity index 100% rename from src/features/user/Settings/EditProfile/AddressManagment/microComponents/SingleAddress.tsx rename to src/features/user/Settings/EditProfile/AddressManagement/microComponents/SingleAddress.tsx diff --git a/src/features/user/Settings/EditProfile/index.tsx b/src/features/user/Settings/EditProfile/index.tsx index 3d91724759..a5b47714b0 100644 --- a/src/features/user/Settings/EditProfile/index.tsx +++ b/src/features/user/Settings/EditProfile/index.tsx @@ -3,7 +3,7 @@ import CenteredContainer from '../../../common/Layout/CenteredContainer'; import DashboardView from '../../../common/Layout/DashboardView'; import EditProfileForm from './EditProfileForm'; import SingleColumnView from '../../../common/Layout/SingleColumnView'; -import AddressManagement from './AddressManagment'; +import AddressManagement from './AddressManagement'; export default function EditProfile(): React.ReactElement | null { const t = useTranslations('Me'); From f2838b156137b513972917749af53615c5f6ac23 Mon Sep 17 00:00:00 2001 From: sunilsabatp <101264823+sunilsabatp@users.noreply.github.com> Date: Thu, 12 Dec 2024 12:15:26 +0530 Subject: [PATCH 88/88] refactor: address the code rabbit points --- public/static/locales/en/editProfile.json | 3 +++ .../AddressManagement/DeleteAddress.tsx | 2 +- .../AddressManagement/EditAddress.tsx | 14 +++++----- .../AddressManagement/UnsetBillingAddress.tsx | 5 ++-- .../AddressManagement/UpdateAddressType.tsx | 4 +-- .../EditProfile/AddressManagement/index.tsx | 12 ++++++--- .../microComponents/AddressActionMenu.tsx | 9 ++++++- .../microComponents/AddressForm.tsx | 26 +++++++++++++------ .../microComponents/AddressList.tsx | 2 +- 9 files changed, 51 insertions(+), 26 deletions(-) diff --git a/public/static/locales/en/editProfile.json b/public/static/locales/en/editProfile.json index 2b21a25775..51fad4556c 100644 --- a/public/static/locales/en/editProfile.json +++ b/public/static/locales/en/editProfile.json @@ -70,6 +70,9 @@ "companyRequired": "Company Name is required" }, "addressManagement": { + "labels": { + "actionMenu": "Action menu" + }, "addressManagementTitle": "Address", "addressType": { "primary": "Primary Address", diff --git a/src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx index b285392902..11402f07b7 100644 --- a/src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx @@ -15,7 +15,7 @@ import { deleteAuthenticatedRequest } from '../../../../../utils/apiRequests/api interface Props { setIsModalOpen: SetState; - addressId: string | undefined; + addressId: string; updateUserAddresses: () => Promise; setAddressAction: SetState; } diff --git a/src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx index c0a80cd21e..25ab975bcc 100644 --- a/src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx @@ -16,8 +16,8 @@ import AddressFormLayout from './microComponents/AddressFormLayout'; interface Props { setIsModalOpen: SetState; - selectedAddressForAction: Address | null; - updateUserAddresses?: () => Promise; + selectedAddressForAction: Address; + updateUserAddresses: () => Promise; setAddressAction: SetState; } @@ -28,11 +28,11 @@ const EditAddress = ({ setAddressAction, }: Props) => { const defaultAddressDetail = { - address: selectedAddressForAction?.address, - address2: selectedAddressForAction?.address2, - city: selectedAddressForAction?.city, - zipCode: selectedAddressForAction?.zipCode, - state: selectedAddressForAction?.state, + address: selectedAddressForAction.address, + address2: selectedAddressForAction.address2, + city: selectedAddressForAction.city, + zipCode: selectedAddressForAction.zipCode, + state: selectedAddressForAction.state, }; const tAddressManagement = useTranslations('EditProfile.addressManagement'); diff --git a/src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx index f72aae589b..f83b4dae4e 100644 --- a/src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx @@ -19,7 +19,7 @@ interface Props { setIsModalOpen: SetState; setAddressAction: SetState; updateUserAddresses: () => Promise; - selectedAddressForAction: Address | null; + selectedAddressForAction: Address; } const UnsetBillingAddress = ({ @@ -37,8 +37,7 @@ const UnsetBillingAddress = ({ const [isLoading, setIsLoading] = useState(false); const unsetAddress = async () => { - if (!contextLoaded || !user || !token || !selectedAddressForAction?.id) - return; + if (!contextLoaded || !user || !token) return; setIsLoading(true); const bodyToSend = { type: ADDRESS_TYPE.OTHER, diff --git a/src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx b/src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx index 0f71ef7d8b..e3e92a9f47 100644 --- a/src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx @@ -18,7 +18,7 @@ interface Props { addressType: 'primary' | 'mailing'; setIsModalOpen: SetState; userAddress: Address | undefined; - selectedAddressForAction: Address | null; + selectedAddressForAction: Address; updateUserAddresses: () => Promise; setAddressAction: SetState; } @@ -47,7 +47,7 @@ const UpdateAddressType = ({ try { const res = await putAuthenticatedRequest
( tenantConfig.id, - `/app/addresses/${selectedAddressForAction?.id}`, + `/app/addresses/${selectedAddressForAction.id}`, bodyToSend, token, logoutUser diff --git a/src/features/user/Settings/EditProfile/AddressManagement/index.tsx b/src/features/user/Settings/EditProfile/AddressManagement/index.tsx index 2357e1236a..6cbc44f0be 100644 --- a/src/features/user/Settings/EditProfile/AddressManagement/index.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagement/index.tsx @@ -42,7 +42,7 @@ const AddressManagement = () => { const [isModalOpen, setIsModalOpen] = useState(false); const sortedAddresses = useMemo(() => { - return userAddresses.sort((a, b) => { + return [...userAddresses].sort((a, b) => { return ( addressTypeOrder.indexOf(a.type) - addressTypeOrder.indexOf(b.type) ); @@ -62,7 +62,7 @@ const AddressManagement = () => { } catch (error) { setErrors(handleError(error as APIError)); } - }, [user, token, contextLoaded, tenantConfig.id, logoutUser]); + }, [user, token, contextLoaded, tenantConfig.id, logoutUser, setErrors]); const toggleAddAddressModal = () => { setIsModalOpen(true); @@ -88,6 +88,7 @@ const AddressManagement = () => { /> ); case ADDRESS_ACTIONS.EDIT: + if (!selectedAddressForAction) return <>; return ( { /> ); case ADDRESS_ACTIONS.DELETE: + if (!selectedAddressForAction) return <>; return ( ); case ADDRESS_ACTIONS.SET_PRIMARY: + if (!selectedAddressForAction) return <>; return ( { /> ); case ADDRESS_ACTIONS.SET_BILLING: + if (!selectedAddressForAction) return <>; return ( { /> ); case ADDRESS_ACTIONS.UNSET_BILLING: + if (!selectedAddressForAction) return <>; return ( { primaryAddress, billingAddress, addressAction, + setAddressAction, ]); const canAddMoreAddresses = userAddresses.length < MAX_ADDRESS_LIMIT; diff --git a/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressActionMenu.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressActionMenu.tsx index da36448e4a..3aa037381a 100644 --- a/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressActionMenu.tsx +++ b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressActionMenu.tsx @@ -92,7 +92,7 @@ const AddressActionsMenu = ({