Repository: Plant-for-the-Planet-org/planet-webapp
Pull request #2481: Feature/use api hook6
Author: login: sunilsabatp
Labels: name: PR: reviewed-approved
Created: 2025-04-04T06:48:48Z | Merged: 2025-04-08T10:25:09Z

Refactored code to utilize the `useApi()` hook for all API interactions, improving consistency, testability, and code reusability.

Features Updated:

- Address Management
- Planet Cash 


Diff:
diff --git a/src/features/user/PlanetCash/components/CreateAccountForm.tsx b/src/features/user/PlanetCash/components/CreateAccountForm.tsx
index 634b0ada73..f7e1b3677e 100644
--- a/src/features/user/PlanetCash/components/CreateAccountForm.tsx
+++ b/src/features/user/PlanetCash/components/CreateAccountForm.tsx
@@ -5,6 +5,7 @@ import type {
 } from '../../../common/types/country';
 import { useRouter } from 'next/router';
 import type { APIError, SerializedError } from '@planet-sdk/common';
+import type { PlanetCashAccount } from '../../../common/types/planetcash';
 
 import { useState, useContext } from 'react';
 import { Button, CircularProgress } from '@mui/material';
@@ -13,18 +14,21 @@ import CustomSnackbar from '../../../common/CustomSnackbar';
 import StyledForm from '../../../common/Layout/StyledForm';
 import { useTranslations } from 'next-intl';
 import FormHeader from '../../../common/Layout/Forms/FormHeader';
-import { postAuthenticatedRequest } from '../../../../utils/apiRequests/api';
-import { useUserProps } from '../../../common/Layout/UserPropsContext';
 import { ErrorHandlingContext } from '../../../common/Layout/ErrorHandlingContext';
 import { usePlanetCash } from '../../../common/Layout/PlanetCashContext';
 import { handleError } from '@planet-sdk/common';
-import { useTenant } from '../../../common/Layout/TenantContext';
+import { useApi } from '../../../../hooks/useApi';
 
 interface Props {
   isPlanetCashActive: boolean;
   allowedCountries: CountryType[];
 }
 
+type PlanetCashStatusApiPayload = {
+  country: string | ExtendedCountryCode;
+  activate: boolean;
+};
+
 const CreateAccountForm = ({
   allowedCountries,
   isPlanetCashActive,
@@ -35,23 +39,24 @@ const CreateAccountForm = ({
   const [country, setCountry] = useState<ExtendedCountryCode | ''>('');
   const [isProcessing, setIsProcessing] = useState(false);
   const [isAccountCreated, setIsAccountCreated] = useState(false);
-  const { token, logoutUser } = useUserProps();
   const { setErrors } = useContext(ErrorHandlingContext);
   const router = useRouter();
-  const { tenantConfig } = useTenant();
+  const { postApiAuthenticated } = useApi();
 
   const onSubmit = async (event: FormEvent<HTMLFormElement>) => {
     event.preventDefault();
-    const data = { country: country, activate: !isPlanetCashActive };
+    const payload: PlanetCashStatusApiPayload = {
+      country: country,
+      activate: !isPlanetCashActive,
+    };
     setIsProcessing(true);
 
     try {
-      const res = await postAuthenticatedRequest({
-        tenant: tenantConfig?.id,
-        url: '/app/planetCash',
-        data,
-        token,
-        logoutUser,
+      const res = await postApiAuthenticated<
+        PlanetCashAccount,
+        PlanetCashStatusApiPayload
+      >('/app/planetCash', {
+        payload,
       });
       setIsAccountCreated(true);
       setAccounts([res]);
diff --git a/src/features/user/PlanetCash/screens/Transactions.tsx b/src/features/user/PlanetCash/screens/Transactions.tsx
index ef4c66e6c6..5900d4112d 100644
--- a/src/features/user/PlanetCash/screens/Transactions.tsx
+++ b/src/features/user/PlanetCash/screens/Transactions.tsx
@@ -7,12 +7,11 @@ import AccountRecord from '../../Account/components/AccountRecord';
 import TransactionListLoader from '../../../../../public/assets/images/icons/TransactionListLoader';
 import { Button, CircularProgress } from '@mui/material';
 import { usePlanetCash } from '../../../common/Layout/PlanetCashContext';
-import { getAuthenticatedRequest } from '../../../../utils/apiRequests/api';
 import { useUserProps } from '../../../common/Layout/UserPropsContext';
 import { ErrorHandlingContext } from '../../../common/Layout/ErrorHandlingContext';
 import NoTransactionsFound from '../components/NoTransactionsFound';
 import { handleError } from '@planet-sdk/common';
-import { useTenant } from '../../../common/Layout/TenantContext';
+import { useApi } from '../../../../hooks/useApi';
 
 interface TransactionsProps {
   setProgress?: (progress: number) => void;
@@ -22,10 +21,10 @@ const Transactions = ({
   setProgress,
 }: TransactionsProps): ReactElement | null => {
   const t = useTranslations('Me');
-  const { token, contextLoaded, logoutUser } = useUserProps();
-  const { tenantConfig } = useTenant();
+  const { token, contextLoaded } = useUserProps();
   const { redirect, setErrors } = useContext(ErrorHandlingContext);
   const { accounts } = usePlanetCash();
+  const { getApiAuthenticated } = useApi();
   const [transactionHistory, setTransactionHistory] =
     useState<PaymentHistory | null>(null);
   const [selectedRecord, setSelectedRecord] = useState<number | null>(null);
@@ -48,23 +47,24 @@ const Transactions = ({
         setIsDataLoading(true);
         setProgress && setProgress(70);
 
-        const nextPage =
-          next && transactionHistory?._links?.next
-            ? transactionHistory._links.next.split('?').pop()
-            : undefined;
+        const queryParams: Record<string, string> = {
+          filter: 'planet-cash',
+          limit: '15',
+        };
 
-        const apiUrl =
-          next && transactionHistory?._links?.next
-            ? `/app/paymentHistory?filter=planet-cash&limit=15&${nextPage}`
-            : `/app/paymentHistory?filter=planet-cash&limit=15`;
+        if (transactionHistory?._links?.next && next) {
+          const nextUrl = new URL(
+            transactionHistory?._links?.next,
+            window.location.origin
+          );
 
-        const newTransactionHistory =
-          await getAuthenticatedRequest<PaymentHistory>({
-            tenant: tenantConfig?.id,
-            url: apiUrl,
-            token,
-            logoutUser,
-          });
+          const page = nextUrl.searchParams.get('page');
+          if (page) queryParams.page = page;
+        }
+        const newTransactionHistory = await getApiAuthenticated<PaymentHistory>(
+          `/app/paymentHistory`,
+          { queryParams }
+        );
 
         if (transactionHistory) {
           setTransactionHistory({
diff --git a/src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx
index 6808763aab..8ca00de27d 100644
--- a/src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx
+++ b/src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx
@@ -2,25 +2,22 @@ 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 type { AddressFormData } from './microComponents/AddressForm';
 
 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 AddressFormLayout from './microComponents/AddressFormLayout';
 import { getStoredConfig } from '../../../../../utils/storeConfig';
+import { useApi } from '../../../../../hooks/useApi';
 
-export type FormData = {
-  address: string | undefined;
-  address2: string | null;
-  city: string | undefined;
-  zipCode: string | undefined;
-  state: string | null;
+export type AddAddressApiPayload = AddressFormData & {
+  country: ExtendedCountryCode | string;
+  type: 'other' | 'primary';
 };
 
 interface Props {
@@ -49,8 +46,8 @@ const AddAddress = ({
   const { contextLoaded, user, token, logoutUser, setUser } = useUserProps();
   const configCountry = getStoredConfig('country');
   const defaultCountry = user?.country || configCountry || 'DE';
-  const { tenantConfig } = useTenant();
   const { setErrors } = useContext(ErrorHandlingContext);
+  const { postApiAuthenticated } = useApi();
   const [country, setCountry] = useState<ExtendedCountryCode | ''>(
     defaultCountry
   );
@@ -58,22 +55,21 @@ const AddAddress = ({
   const [primaryAddressChecked, setPrimaryAddressChecked] = useState(false);
 
   const addAddress = useCallback(
-    async (data: FormData) => {
+    async (data: AddressFormData) => {
       if (!contextLoaded || !user || !token) return;
       setIsLoading(true);
-      const bodyToSend = {
+      const payload: AddAddressApiPayload = {
         ...data,
         country,
         type: primaryAddressChecked ? ADDRESS_TYPE.PRIMARY : ADDRESS_TYPE.OTHER,
       };
       try {
-        const res = await postAuthenticatedRequest<Address>({
-          tenant: tenantConfig.id,
-          url: '/app/addresses',
-          data: bodyToSend,
-          token,
-          logoutUser,
-        });
+        const res = await postApiAuthenticated<Address, AddAddressApiPayload>(
+          '/app/addresses',
+          {
+            payload,
+          }
+        );
         if (res) {
           setUser((prev) => {
             if (!prev) return null;
@@ -111,7 +107,7 @@ const AddAddress = ({
       handleError,
       setIsLoading,
       setIsModalOpen,
-      postAuthenticatedRequest,
+      postApiAuthenticated,
       primaryAddressChecked,
       updateUserAddresses,
     ]
diff --git a/src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx
index 795e16697f..f5d9b97b00 100644
--- a/src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx
+++ b/src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx
@@ -7,11 +7,10 @@ import { useTranslations } from 'next-intl';
 import { handleError } from '@planet-sdk/common';
 import { CircularProgress } from '@mui/material';
 import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext';
-import { useTenant } from '../../../../common/Layout/TenantContext';
 import { useUserProps } from '../../../../common/Layout/UserPropsContext';
 import WebappButton from '../../../../common/WebappButton';
 import styles from './AddressManagement.module.scss';
-import { deleteAuthenticatedRequest } from '../../../../../utils/apiRequests/api';
+import { useApi } from '../../../../../hooks/useApi';
 
 interface Props {
   setIsModalOpen: SetState<boolean>;
@@ -28,21 +27,16 @@ const DeleteAddress = ({
 }: Props) => {
   const tAddressManagement = useTranslations('EditProfile.addressManagement');
   const tCommon = useTranslations('Common');
-  const { contextLoaded, user, token, logoutUser } = useUserProps();
-  const { tenantConfig } = useTenant();
+  const { contextLoaded, user, token } = useUserProps();
   const { setErrors } = useContext(ErrorHandlingContext);
+  const { deleteApiAuthenticated } = useApi();
   const [isLoading, setIsLoading] = useState(false);
 
   const deleteAddress = async () => {
     if (!contextLoaded || !user || !token) return;
     try {
       setIsLoading(true);
-      await deleteAuthenticatedRequest({
-        tenant: tenantConfig.id,
-        url: `/app/addresses/${addressId}`,
-        token,
-        logoutUser,
-      });
+      await deleteApiAuthenticated(`/app/addresses/${addressId}`);
       updateUserAddresses();
     } catch (error) {
       setErrors(handleError(error as APIError));
diff --git a/src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx
index bdfc5aa123..8eb2174cd3 100644
--- a/src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx
+++ b/src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx
@@ -1,19 +1,19 @@
 import type { ExtendedCountryCode } from '../../../../common/types/country';
 import type { SetState } from '../../../../common/types/common';
-import type { Address, APIError } from '@planet-sdk/common';
-import type { FormData } from './AddAddress';
+import type { Address, AddressType, APIError } from '@planet-sdk/common';
+import type { AddressFormData } from './microComponents/AddressForm';
 import type { AddressAction } from '../../../../common/types/profile';
 
 import { useState, useContext, useCallback, useEffect } 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 AddressFormLayout from './microComponents/AddressFormLayout';
 import { ADDRESS_TYPE } from '../../../../../utils/addressManagement';
+import { useApi } from '../../../../../hooks/useApi';
 
 interface Props {
   setIsModalOpen: SetState<boolean>;
@@ -23,6 +23,11 @@ interface Props {
   showPrimaryAddressToggle: boolean;
 }
 
+type EditAddressApiPayload = AddressFormData & {
+  country: ExtendedCountryCode | string;
+  type: AddressType;
+};
+
 const EditAddress = ({
   setIsModalOpen,
   selectedAddressForAction,
@@ -43,6 +48,7 @@ const EditAddress = ({
   const { contextLoaded, user, token, logoutUser, setUser } = useUserProps();
   const { tenantConfig } = useTenant();
   const { setErrors } = useContext(ErrorHandlingContext);
+  const { putApiAuthenticated } = useApi();
   const [country, setCountry] = useState<ExtendedCountryCode | ''>(
     selectedAddressForAction?.country ?? 'DE'
   );
@@ -57,10 +63,10 @@ const EditAddress = ({
   }, [selectedAddressForAction]);
 
   const updateAddress = useCallback(
-    async (data: FormData) => {
+    async (data: AddressFormData) => {
       if (!contextLoaded || !user || !token) return;
       setIsLoading(true);
-      const bodyToSend = {
+      const payload: EditAddressApiPayload = {
         ...data,
         country,
         type: primaryAddressChecked
@@ -68,13 +74,12 @@ const EditAddress = ({
           : selectedAddressForAction?.type,
       };
       try {
-        const res = await putAuthenticatedRequest<Address>({
-          tenant: tenantConfig.id,
-          url: `/app/addresses/${selectedAddressForAction?.id}`,
-          data: bodyToSend,
-          token,
-          logoutUser,
-        });
+        const res = await putApiAuthenticated<Address, EditAddressApiPayload>(
+          `/app/addresses/${selectedAddressForAction?.id}`,
+          {
+            payload,
+          }
+        );
         if (res) {
           if (updateUserAddresses) updateUserAddresses();
           setUser((prev) => {
@@ -126,7 +131,7 @@ const EditAddress = ({
       logoutUser,
       updateUserAddresses,
       handleError,
-      putAuthenticatedRequest,
+      putApiAuthenticated,
       primaryAddressChecked,
     ]
   );
diff --git a/src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx b/src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx
index e4461371c7..0fa9bcd2c8 100644
--- a/src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx
+++ b/src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx
@@ -9,10 +9,9 @@ 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';
 import { ADDRESS_TYPE } from '../../../../../utils/addressManagement';
+import { useApi } from '../../../../../hooks/useApi';
 
 interface Props {
   addressType: 'mailing';
@@ -22,6 +21,10 @@ interface Props {
   selectedAddressForAction: Address;
 }
 
+type UnsetBillingAddressApiPayload = {
+  type: 'other';
+};
+
 const UnsetBillingAddress = ({
   addressType,
   setIsModalOpen,
@@ -31,24 +34,23 @@ const UnsetBillingAddress = ({
 }: Props) => {
   const tAddressManagement = useTranslations('EditProfile.addressManagement');
   const tCommon = useTranslations('Common');
-  const { contextLoaded, user, token, logoutUser } = useUserProps();
+  const { contextLoaded, user, token } = useUserProps();
+  const { putApiAuthenticated } = useApi();
   const { setErrors } = useContext(ErrorHandlingContext);
-  const { tenantConfig } = useTenant();
   const [isLoading, setIsLoading] = useState(false);
 
   const unsetAddress = async () => {
     if (!contextLoaded || !user || !token) return;
     setIsLoading(true);
-    const bodyToSend = {
+    const payload: UnsetBillingAddressApiPayload = {
       type: ADDRESS_TYPE.OTHER,
     };
     try {
-      const res = await putAuthenticatedRequest<Address>({
-        tenant: tenantConfig.id,
-        url: `/app/addresses/${selectedAddressForAction.id}`,
-        data: bodyToSend,
-        token,
-        logoutUser,
+      const res = await putApiAuthenticated<
+        Address,
+        UnsetBillingAddressApiPayload
+      >(`/app/addresses/${selectedAddressForAction.id}`, {
+        payload,
       });
       if (res) updateUserAddresses();
     } catch (error) {
diff --git a/src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx b/src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx
index 01cbc4669e..af66906f3c 100644
--- a/src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx
+++ b/src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx
@@ -8,14 +8,14 @@ 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 { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext';
 import FormattedAddressBlock from './microComponents/FormattedAddressBlock';
+import { useApi } from '../../../../../hooks/useApi';
 
+type AddressType = 'primary' | 'mailing';
 interface Props {
-  addressType: 'primary' | 'mailing';
+  addressType: AddressType;
   setIsModalOpen: SetState<boolean>;
   userAddress: Address | undefined;
   selectedAddressForAction: Address;
@@ -23,6 +23,10 @@ interface Props {
   setAddressAction: SetState<AddressAction | null>;
 }
 
+type AddressTypeApiPayload = {
+  type: AddressType;
+};
+
 const UpdateAddressType = ({
   addressType,
   setIsModalOpen,
@@ -33,25 +37,24 @@ const UpdateAddressType = ({
 }: Props) => {
   const tAddressManagement = useTranslations('EditProfile.addressManagement');
   const tCommon = useTranslations('Common');
-  const { contextLoaded, user, token, logoutUser } = useUserProps();
-  const { tenantConfig } = useTenant();
+  const { contextLoaded, user, token } = useUserProps();
+  const { putApiAuthenticated } = useApi();
   const { setErrors } = useContext(ErrorHandlingContext);
   const [isUploadingData, setIsUploadingData] = useState(false);
 
-  const updateAddress = async (addressType: 'primary' | 'mailing') => {
+  const updateAddress = async (addressType: AddressType) => {
     if (!contextLoaded || !user || !token) return;
     setIsUploadingData(true);
-    const bodyToSend = {
+    const payload: AddressTypeApiPayload = {
       type: addressType,
     };
     try {
-      const res = await putAuthenticatedRequest<Address>({
-        tenant: tenantConfig.id,
-        url: `/app/addresses/${selectedAddressForAction.id}`,
-        data: bodyToSend,
-        token,
-        logoutUser,
-      });
+      const res = await putApiAuthenticated<Address, AddressTypeApiPayload>(
+        `/app/addresses/${selectedAddressForAction.id}`,
+        {
+          payload,
+        }
+      );
       if (res) updateUserAddresses();
     } catch (error) {
       setErrors(handleError(error as APIError));
diff --git a/src/features/user/Settings/EditProfile/AddressManagement/index.tsx b/src/features/user/Settings/EditProfile/AddressManagement/index.tsx
index 8264a5a862..625461e6a8 100644
--- a/src/features/user/Settings/EditProfile/AddressManagement/index.tsx
+++ b/src/features/user/Settings/EditProfile/AddressManagement/index.tsx
@@ -9,7 +9,6 @@ import AddressList from './microComponents/AddressList';
 import { useUserProps } from '../../../../common/Layout/UserPropsContext';
 import WebappButton from '../../../../common/WebappButton';
 import styles from './AddressManagement.module.scss';
-import { getAuthenticatedRequest } from '../../../../../utils/apiRequests/api';
 import { useTenant } from '../../../../common/Layout/TenantContext';
 import { ErrorHandlingContext } from '../../../../common/Layout/ErrorHandlingContext';
 import {
@@ -25,10 +24,12 @@ import DeleteAddress from './DeleteAddress';
 import EditAddress from './EditAddress';
 import AddAddress from './AddAddress';
 import UnsetBillingAddress from './UnsetBillingAddress';
+import { useApi } from '../../../../../hooks/useApi';
 
 const AddressManagement = () => {
   const { user, contextLoaded, token, logoutUser } = useUserProps();
   const { tenantConfig } = useTenant();
+  const { getApiAuthenticated } = useApi();
   const { setErrors } = useContext(ErrorHandlingContext);
   const tAddressManagement = useTranslations('EditProfile.addressManagement');
   const [userAddresses, setUserAddresses] = useState<Address[]>(
@@ -52,12 +53,7 @@ const AddressManagement = () => {
   const updateUserAddresses = useCallback(async () => {
     if (!user || !token || !contextLoaded) return;
     try {
-      const res = await getAuthenticatedRequest<Address[]>({
-        tenant: tenantConfig.id,
-        url: '/app/addresses',
-        token,
-        logoutUser,
-      });
+      const res = await getApiAuthenticated<Address[]>('/app/addresses');
       if (res) setUserAddresses(res);
     } catch (error) {
       setErrors(handleError(error as APIError));
diff --git a/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx
index fe8ce2cdfb..6e38747746 100644
--- a/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx
+++ b/src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx
@@ -2,7 +2,6 @@ import type { AddressSuggestionsType } from '../../../../../common/types/geocode
 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 type { AddressType } from '@planet-sdk/common';
 
@@ -27,19 +26,20 @@ import AddressFormButtons from './AddressFormButtons';
 import { useDebouncedEffect } from '../../../../../../utils/useDebouncedEffect';
 import PrimaryAddressToggle from './PrimaryAddressToggle';
 
+export type AddressFormData = {
+  address: string;
+  address2: Nullable<string>;
+  city: string;
+  zipCode: string;
+  state: Nullable<string>;
+};
+
 interface Props {
   country: ExtendedCountryCode | '';
   setCountry: SetState<ExtendedCountryCode | ''>;
   label: string;
-  processFormData: (data: FormData) => Promise<void>;
-  defaultAddressDetail: {
-    address: string | undefined;
-    address2: Nullable<string> | undefined;
-    city: string | undefined;
-    zipCode: string | undefined;
-    state: Nullable<string> | undefined;
-    type: AddressType;
-  };
+  processFormData: (data: AddressFormData) => Promise<void>;
+  defaultAddressDetail: AddressFormData & { type: AddressType };
   setIsModalOpen: SetState<boolean>;
   isLoading: boolean;
   setAddressAction: SetState<AddressAction | null>;
@@ -71,7 +71,7 @@ const AddressForm = ({
     setValue,
     reset,
     formState: { errors },
-  } = useForm<FormData>({
+  } = useForm<AddressFormData>({
     mode: 'onBlur',
     defaultValues: defaultAddressDetail,
   });


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/index.tsx (1)</summary><blockquote>

`53-61`: **Update dependency array to match usage.**

The dependency array still includes `tenantConfig.id` and `logoutUser`, but these variables are no longer used in the function body after the refactoring.

```diff
- }, [user, token, contextLoaded, tenantConfig.id, logoutUser, setErrors]);
+ }, [user, token, contextLoaded, setErrors, getApiAuthenticated]);
```

</blockquote></details>
<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx (1)</summary><blockquote>

`130-130`: **Potentially unused dependency**

The `tenantConfig.id` is still included in the dependency array, but it doesn't appear to be used in the function body after the refactoring. Consider removing it from the dependencies.

```diff
    [
      contextLoaded,
      user,
      token,
      country,
      selectedAddressForAction?.type,
      selectedAddressForAction?.id,
-     tenantConfig.id,
      logoutUser,
      updateUserAddresses,
      handleError,
      putApiAuthenticated,
      primaryAddressChecked,
    ]
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between e07ff263fdfe8e1b4c380a86b9b1118c0da64d68 and caef0e46dafe38e664fab99bebc07548dea42a71.

</details>

<details>
<summary>📒 Files selected for processing (8)</summary>

* `src/features/user/PlanetCash/components/CreateAccountForm.tsx` (3 hunks)
* `src/features/user/PlanetCash/screens/Transactions.tsx` (3 hunks)
* `src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx` (5 hunks)
* `src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx` (2 hunks)
* `src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx` (5 hunks)
* `src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx` (3 hunks)
* `src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx` (2 hunks)
* `src/features/user/Settings/EditProfile/AddressManagement/index.tsx` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (3)</summary>

<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx (1)</summary>

```
Learnt from: mohitb35
PR: Plant-for-the-Planet-org/planet-webapp#2286
File: src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx:17-23
Timestamp: 2025-04-03T06:35:00.581Z
Learning: In `src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx`, the `addressType` prop should remain as `'mailing'` because `'mailing'` is the API term used in the backend. Even though the UI displays "Billing address", the code and API use `'mailing'` as the address type. Do not change `addressType` to include `'billing'`.
```

</details>
<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/index.tsx (1)</summary>

```
Learnt from: sunilsabatp
PR: Plant-for-the-Planet-org/planet-webapp#2286
File: src/features/user/Settings/EditProfile/AddressManagment/EditAddress.tsx:0-0
Timestamp: 2025-04-03T06:35:00.581Z
Learning: In 'src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx', the `updateAddress` function relies on the React useForm hook for validation, so manual validation before the API call is unnecessary.
```

</details>
<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx (2)</summary>

```
Learnt from: mohitb35
PR: Plant-for-the-Planet-org/planet-webapp#2286
File: src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx:17-23
Timestamp: 2025-04-03T06:35:00.581Z
Learning: In `src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx`, the `addressType` prop should remain as `'mailing'` because `'mailing'` is the API term used in the backend. Even though the UI displays "Billing address", the code and API use `'mailing'` as the address type. Do not change `addressType` to include `'billing'`.
```

```
Learnt from: mohitb35
PR: Plant-for-the-Planet-org/planet-webapp#2286
File: src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx:39-62
Timestamp: 2025-04-03T06:35:00.581Z
Learning: Avoid suggesting wrapping functions with `useCallback` when it results in unnecessary optimization, such as for the `unsetAddress` function in `src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx`.
```

</details>

</details><details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx (1)</summary><blockquote>

<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx (1)</summary>

* `FormData` (17-23)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Analyze (javascript)
* GitHub Check: ESLint on Ubuntu

</details>

<details>
<summary>🔇 Additional comments (27)</summary><blockquote>

<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/DeleteAddress.tsx (3)</summary>

`1-13`: **Good adoption of the useApi hook.**

The removal of the `useTenant` import and addition of the `useApi` hook aligns with the overall refactoring effort across the codebase to standardize API request handling.

---

`30-32`: **Clean simplification of dependencies.**

Removing `logoutUser` and `tenantConfig` from the destructured properties of `useUserProps` helps streamline the component by eliminating unused variables.

---

`35-40`: **API call simplification looks good.**

Updating from `deleteAuthenticatedRequest` to `deleteApiAuthenticated` simplifies the function call by eliminating the need to pass tenant ID, token, and logout function as parameters.

</details>
<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/index.tsx (1)</summary>

`27-32`: **Good adoption of the useApi hook.**

The addition of the `useApi` hook aligns with the overall refactoring effort across the codebase to standardize API request handling.

</details>
<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx (4)</summary>

`14-14`: **Good adoption of the useApi hook.**

The addition of the `useApi` hook aligns with the overall refactoring effort across the codebase.

---

`24-26`: **Good type definition for the API payload.**

The addition of the `UnsetBillingAddressApiPayload` type enhances type safety by explicitly defining the structure of the payload.

---

`37-38`: **Clean simplification of dependencies.**

Removing `logoutUser` from the destructured properties of `useUserProps` helps streamline the component.

---

`42-54`: **Properly typed API call with enhanced structure.**

The implementation of the API call with generic type parameters `<Address, UnsetBillingAddressApiPayload>` and the restructured payload improves type safety and clarity. The explicit typing of `bodyToSend` is also a good practice.

</details>
<details>
<summary>src/features/user/PlanetCash/components/CreateAccountForm.tsx (5)</summary>

`7-9`: **Clean import organization.**

The update to import only the necessary type enhances code readability and maintainability.

---

`20-20`: **Good adoption of the useApi hook.**

The addition of the `useApi` hook aligns with the overall refactoring effort across the codebase.

---

`27-30`: **Good type definition for the API payload.**

The addition of the `PlanetCashStatusApiPayload` type enhances type safety by explicitly defining the structure of the payload with properties for `country` and `activate`.

---

`44-44`: **Clean simplification of dependencies.**

Using the hook's `postApiAuthenticated` method simplifies the component's dependencies.

---

`47-61`: **Properly typed API call with enhanced structure.**

The implementation of the API call with generic type parameters `<PlanetCashAccount, PlanetCashStatusApiPayload>` and the restructured payload improves type safety and clarity. The explicit typing of `data` is also a good practice.

</details>
<details>
<summary>src/features/user/PlanetCash/screens/Transactions.tsx (3)</summary>

`14-14`: **Import added for useApi hook**

The code correctly imports the `useApi` hook to replace the previous direct API request method.

---

`27-27`: **Good implementation of the useApi hook**

Properly destructures the required `getApiAuthenticated` method from the hook.

---

`50-67`: **Improved API request structure**

The refactored implementation uses a more structured approach for API requests:
1. Creates a dedicated `queryParams` object for query parameters
2. Properly extracts pagination parameters from the next URL
3. Uses the typed `getApiAuthenticated` method for better type safety

This is a significant improvement over direct URL string construction.

</details>
<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx (4)</summary>

`25-28`: **Good type definition for API payload**

The new `AddAddressApiPayload` type properly extends the existing `FormData` type with the additional fields required by the API. This enhances type safety and provides better documentation of the API contract.

---

`57-57`: **Proper use of useApi hook**

Correctly destructures the `postApiAuthenticated` method from the hook.

---

`68-72`: **Enhanced type safety with explicit typing**

The `bodyToSend` variable is now explicitly typed as `AddAddressApiPayload`, ensuring type safety for the API payload.

---

`74-79`: **Improved API call structure**

The refactored API call uses the typed `postApiAuthenticated` method with properly structured parameters:
1. Uses generics for better type safety (`Address` for response, `AddAddressApiPayload` for request)
2. Passes payload as a structured object rather than separate parameters
3. Simplifies the overall API interaction pattern

This approach is more maintainable and type-safe.

</details>
<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx (3)</summary>

`3-3`: **Added AddressType import**

Properly imports the `AddressType` type from the SDK package for better type safety.

---

`26-29`: **Well-defined type for API payload**

The new `EditAddressApiPayload` type properly extends `FormData` with the necessary API fields, providing clear type documentation for the API contract.

---

`77-82`: **Improved API request pattern**

The API call has been refactored to use the typed `putApiAuthenticated` method, which:
1. Uses generics to ensure type safety for both request and response
2. Simplifies the payload structure with a single object
3. Makes the code more consistent with other components

This is a good improvement for maintainability and type safety.

</details>
<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx (4)</summary>

`16-16`: **Good type definition for address types**

Creating the `AddressType` type alias helps ensure consistent usage of valid address types throughout the codebase.

---

`26-28`: **Clear type definition for API payload**

The `AddressTypeApiPayload` type clearly defines the structure expected by the API, enhancing type safety and documentation.

---

`40-42`: **Simplified props usage and proper hook implementation**

1. Removed unused `logoutUser` from props destructuring
2. Added the `useApi` hook to get the `putApiAuthenticated` method

This refactoring properly adopts the new API request pattern.

---

`52-57`: **Improved API call implementation**

The refactored API call:
1. Uses proper generic typing for request and response types
2. Simplifies the payload structure into a single object
3. Maintains the same functionality with less code

This change is consistent with the pattern used in other components.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-04T06:51:48Z
user: login: mohitb35
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T08:27:10Z
user: login: mohitb35
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T08:30:24Z
user: login: mohitb35
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T08:31:03Z
user: login: mohitb35
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T08:32:17Z
user: login: mohitb35
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T08:32:42Z
user: login: mohitb35
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T08:34:34Z
user: login: mohitb35
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-07T08:35:14Z
user: login: mohitb35
body: @sunilsabatp Please go through some minor feedback.
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-07T08:35:48Z
user: login: sunilsabatp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T04:19:01Z
user: login: sunilsabatp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T04:19:13Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx (1)</summary><blockquote>

`123-136`: **Consider removing unused dependencies from the dependency array.**

The dependency array includes `tenantConfig.id` which doesn't appear to be used in the `updateAddress` function anymore. Also, `handleError` is imported directly from '@planet-sdk/common' and not derived from component state or props, so it likely doesn't need to be in the dependency array.


```diff
    [
      contextLoaded,
      user,
      token,
      country,
      selectedAddressForAction?.type,
      selectedAddressForAction?.id,
-     tenantConfig.id,
      logoutUser,
      updateUserAddresses,
-     handleError,
      putApiAuthenticated,
      primaryAddressChecked,
    ]
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between d53d24233d1b23eba5d8f7204458408f8cd671bd and 48f40f71f1c965f03c33c3a5910bc6c385e46e18.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx` (3 hunks)
* `src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx` (5 hunks)
* `src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx` (3 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary>

* src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx
* src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx (3)</summary><blockquote>

<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx (1)</summary>

* `AddressFormData` (50-56)

</details>
<details>
<summary>src/hooks/useApi.ts (1)</summary>

* `useApi` (93-320)

</details>
<details>
<summary>src/utils/addressManagement.ts (1)</summary>

* `ADDRESS_TYPE` (11-15)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Analyze (javascript)
* GitHub Check: ESLint on Ubuntu

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx (3)</summary>

`26-29`: **Type definition looks good and addresses previous feedback.**

The `EditAddressApiPayload` type properly extends `AddressFormData` with required properties for `country` and `type`, ensuring that these mandatory fields cannot be null or undefined as requested in previous review comments.

---

`69-75`: **Good refactoring of request payload structure.**

The previous `bodyToSend` has been replaced with `payload` for better consistency, addressing the previous review comment. The type safety is also improved by explicitly typing the payload with the `EditAddressApiPayload` type.

---

`77-82`: **API call successfully migrated to use the new hook pattern.**

The implementation correctly uses the `putApiAuthenticated` function from the `useApi` hook, with proper type parameters to ensure type safety for both request and response.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T10:07:21Z
user: login: mohitb35
body: @sunilsabatp Made some minor refactors of the FormData type used in AddressForm, but this LGTM now.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-08T10:10:37Z

Review comments:
diff_hunk: @@ -35,23 +39,24 @@ const CreateAccountForm = ({
   const [country, setCountry] = useState<ExtendedCountryCode | ''>('');
   const [isProcessing, setIsProcessing] = useState(false);
   const [isAccountCreated, setIsAccountCreated] = useState(false);
-  const { token, logoutUser } = useUserProps();
   const { setErrors } = useContext(ErrorHandlingContext);
   const router = useRouter();
-  const { tenantConfig } = useTenant();
+  const { postApiAuthenticated } = useApi();
 
   const onSubmit = async (event: FormEvent<HTMLFormElement>) => {
     event.preventDefault();
-    const data = { country: country, activate: !isPlanetCashActive };
+    const data: PlanetCashStatusApiPayload = {
+      country: country,
+      activate: !isPlanetCashActive,
+    };
path: src/features/user/PlanetCash/components/CreateAccountForm.tsx
user: login: mohitb35
body: Rename `data` to maintain consistency with other places.
created_at: 2025-04-07T08:27:07Z
author_association: MEMBER
diff_hunk: @@ -23,6 +22,11 @@ export type FormData = {
   state: string | null;
 };
 
+export type AddAddressApiPayload = FormData & {
+  country: ExtendedCountryCode | string;
+  type: 'other' | 'primary';
+};
path: src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx
user: login: mohitb35
body: This type allows us to pass mandatory fields as null/undefined which is undesired. I suggest decoupling it from `FormData.`
created_at: 2025-04-07T08:30:22Z
author_association: MEMBER
diff_hunk: @@ -61,19 +65,18 @@ const AddAddress = ({
     async (data: FormData) => {
       if (!contextLoaded || !user || !token) return;
       setIsLoading(true);
-      const bodyToSend = {
+      const bodyToSend: AddAddressApiPayload = {
         ...data,
         country,
         type: primaryAddressChecked ? ADDRESS_TYPE.PRIMARY : ADDRESS_TYPE.OTHER,
       };
path: src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx
user: login: mohitb35
body: Please rename `bodyToSend` in line with other places to maintain consistency.
created_at: 2025-04-07T08:31:01Z
author_association: MEMBER
diff_hunk: @@ -23,6 +23,11 @@ interface Props {
   showPrimaryAddressToggle: boolean;
 }
 
+type EditAddressApiPayload = FormData & {
+  country: ExtendedCountryCode | string;
+  type: AddressType;
+};
path: src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx
user: login: mohitb35
body: Delink EditAddressApiPayload from FormData as FormData permits null/undefined values for mandatory types.
created_at: 2025-04-07T08:32:15Z
author_association: MEMBER
diff_hunk: @@ -60,21 +66,20 @@ const EditAddress = ({
     async (data: FormData) => {
       if (!contextLoaded || !user || !token) return;
       setIsLoading(true);
-      const bodyToSend = {
+      const bodyToSend: EditAddressApiPayload = {
         ...data,
         country,
         type: primaryAddressChecked
           ? ADDRESS_TYPE.PRIMARY
           : selectedAddressForAction?.type,
       };
       try {
-        const res = await putAuthenticatedRequest<Address>({
-          tenant: tenantConfig.id,
-          url: `/app/addresses/${selectedAddressForAction?.id}`,
-          data: bodyToSend,
-          token,
-          logoutUser,
-        });
+        const res = await putApiAuthenticated<Address, EditAddressApiPayload>(
+          `/app/addresses/${selectedAddressForAction?.id}`,
+          {
+            payload: bodyToSend,
+          }
+        );
path: src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx
user: login: mohitb35
body: Rename `bodyToSend` to maintain consistency.
created_at: 2025-04-07T08:32:41Z
author_association: MEMBER
diff_hunk: @@ -31,24 +34,23 @@ const UnsetBillingAddress = ({
 }: Props) => {
   const tAddressManagement = useTranslations('EditProfile.addressManagement');
   const tCommon = useTranslations('Common');
-  const { contextLoaded, user, token, logoutUser } = useUserProps();
+  const { contextLoaded, user, token } = useUserProps();
+  const { putApiAuthenticated } = useApi();
   const { setErrors } = useContext(ErrorHandlingContext);
-  const { tenantConfig } = useTenant();
   const [isLoading, setIsLoading] = useState(false);
 
   const unsetAddress = async () => {
     if (!contextLoaded || !user || !token) return;
     setIsLoading(true);
-    const bodyToSend = {
+    const bodyToSend: UnsetBillingAddressApiPayload = {
       type: ADDRESS_TYPE.OTHER,
     };
path: src/features/user/Settings/EditProfile/AddressManagement/UnsetBillingAddress.tsx
user: login: mohitb35
body: Rename `bodyToSend` to something more relevant, maintaining consistency with the approach elsewhere.
created_at: 2025-04-07T08:34:32Z
author_association: MEMBER
diff_hunk: @@ -33,25 +37,24 @@ const UpdateAddressType = ({
 }: Props) => {
   const tAddressManagement = useTranslations('EditProfile.addressManagement');
   const tCommon = useTranslations('Common');
-  const { contextLoaded, user, token, logoutUser } = useUserProps();
-  const { tenantConfig } = useTenant();
+  const { contextLoaded, user, token } = useUserProps();
+  const { putApiAuthenticated } = useApi();
   const { setErrors } = useContext(ErrorHandlingContext);
   const [isUploadingData, setIsUploadingData] = useState(false);
 
-  const updateAddress = async (addressType: 'primary' | 'mailing') => {
+  const updateAddress = async (addressType: AddressType) => {
     if (!contextLoaded || !user || !token) return;
     setIsUploadingData(true);
-    const bodyToSend = {
+    const bodyToSend: AddressTypeApiPayload = {
       type: addressType,
path: src/features/user/Settings/EditProfile/AddressManagement/UpdateAddressType.tsx
user: login: mohitb35
body: Rename bodyToSend to something more relevant, maintaining consistency with the approach elsewhere.


created_at: 2025-04-07T08:35:13Z
author_association: MEMBER
diff_hunk: @@ -23,6 +22,11 @@ export type FormData = {
   state: string | null;
 };
 
+export type AddAddressApiPayload = FormData & {
+  country: ExtendedCountryCode | string;
+  type: 'other' | 'primary';
+};
path: src/features/user/Settings/EditProfile/AddressManagement/AddAddress.tsx
user: login: sunilsabatp
body: I have updated the `FormData `type to no longer accept `null or undefined `for the mandatory fields.  
created_at: 2025-04-08T04:19:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -23,6 +23,11 @@ interface Props {
   showPrimaryAddressToggle: boolean;
 }
 
+type EditAddressApiPayload = FormData & {
+  country: ExtendedCountryCode | string;
+  type: AddressType;
+};
path: src/features/user/Settings/EditProfile/AddressManagement/EditAddress.tsx
user: login: sunilsabatp
body: I have updated the FormData type to no longer accept null or undefined for the mandatory fields.
created_at: 2025-04-08T04:19:13Z
author_association: CONTRIBUTOR

PR comments:
user: login: vercel[bot]
created_at: 2025-04-04T06:48:53Z
body: [vc]: #NQ4R2l2NvH/D1YryrDsQhqOaes3wGtNkpRDChNZCK+4=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJwbGFuZXQtd2ViYXBwLW11bHRpLXRlbmFuY3ktc2V0dXAiLCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20vcGxhbmV0YXBwL3BsYW5ldC13ZWJhcHAtbXVsdGktdGVuYW5jeS1zZXR1cC9DVTVXbzdGVFJuMUo5YlFLUzV1aHFYdDJKMkV1IiwicHJldmlld1VybCI6InBsYW5ldC13ZWJhcHAtbXVsdGktdGVuYW5jeS1zZXR1cC1naXQtZmVhdHVyZS1hZGE5YzQtcGxhbmV0YXBwLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJyb290RGlyZWN0b3J5IjpudWxsfV19
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Updated (UTC) |
| :--- | :----- | :------ | :------ |
| **planet-webapp-multi-tenancy-setup** | ✅ Ready ([Inspect](https://vercel.com/planetapp/planet-webapp-multi-tenancy-setup/CU5Wo7FTRn1J9bQKS5uhqXt2J2Eu)) | [Visit Preview](https://planet-webapp-multi-tenancy-setup-git-feature-ada9c4-planetapp.vercel.app) | Apr 8, 2025 10:15am |


author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-04-04T06:48:56Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request refactors API request handling across multiple user features. In the PlanetCash components, new type definitions are added and API calls are updated to use generic functions with enhanced type safety. Similarly, several address management components now introduce specific payload types and replace old API functions with updated methods from the `useApi` hook. Unused tenant-related imports have been removed throughout, streamlining the codebase and unifying the API call structure.

## Changes

| File(s) | Change Summary |
|---------|----------------|
| `src/features/user/PlanetCash/{components/CreateAccountForm.tsx, screens/Transactions.tsx}` | Added `PlanetCashStatusApiPayload` and updated API calls by replacing `postAuthenticatedRequest` with `postApiAuthenticated` and `getAuthenticatedRequest` with `getApiAuthenticated`; removed unused imports. |
| `src/features/user/Settings/EditProfile/AddressManagement/{AddAddress.tsx, DeleteAddress.tsx, EditAddress.tsx, UnsetBillingAddress.tsx, UpdateAddressType.tsx, index.tsx}` | Introduced new payload types (e.g., `AddAddressApiPayload`, `EditAddressApiPayload`, `UnsetBillingAddressApiPayload`, `AddressTypeApiPayload`) and refactored API methods by replacing old request functions with `postApiAuthenticated`, `putApiAuthenticated`, `deleteApiAuthenticated`, and `getApiAuthenticated`; eliminated tenant config usage. |
| `src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx` | Updated `defaultAddressDetail` properties to enforce stricter validation by changing types from optional to required for certain fields. |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant C as Component
    participant U as useApi Hook
    participant S as API Server

    C->>U: Call API function (postApiAuthenticated/getApiAuthenticated/putApiAuthenticated/deleteApiAuthenticated)
    U->>S: Execute API call with {payload}
    S-->>U: Return response
    U-->>C: Return data or error
```

## Possibly related PRs
- **Plant-for-the-Planet-org/planet-webapp#2469**: Related as both involve the replacement of the `getAuthenticatedRequest` function with `getApiAuthenticated` from the `useApi` hook, indicating a shared modification in API request handling.
- **Plant-for-the-Planet-org/planet-webapp#2466**: Involves replacing `postAuthenticatedRequest` with `postApiAuthenticated`, directly modifying API request handling.
- **Plant-for-the-Planet-org/planet-webapp#2455**: Related to the transition to using the `useApi` hook for API requests, specifically updating the method of making authenticated API calls and enhancing type safety in the payload structure.

## Suggested labels
`PR: reviewed-approved`

## Poem
> I'm a nimble rabbit, coding in delight,  
> Hopping through API calls with newfound type might.  
> Payloads are all tidy, functions sleek and new,  
> Unused imports tucked away like morning dew.  
> Carrots crunch for clarity, as smooth flows make me smile!  
> 🥕 Keep on coding, let's hop another mile!

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 48f40f71f1c965f03c33c3a5910bc6c385e46e18 and 49cd75dbac9dcf4ab8cae63a79704f980800c8f7.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx` (2 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* src/features/user/Settings/EditProfile/AddressManagement/microComponents/AddressForm.tsx

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Analyze (javascript)

</details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Plant-for-the-Planet-org/planet-webapp&utm_content=2481):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR