Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Questions:

  •  Possibles questions about this feature

Technical Refinement

Description

  • intl-whitelabel-graphql

    • TASK 1 - Create type

      • We will create a type named RequiredAcceptanceAgreementInfo

        • path: intl-whitelabel-graphql/src/functions/graphql/schemas/users.gql

          Code Block
          languagegraphql
          type RequiredAcceptanceAgreementInfo {
            """
            Acceptance Agreement ID
            """
            id: String
            """
            Updated Date
            """
            updatedAt: String
          }
      • Also, we will add requiredAcceptanceAgreementInfo on type UserDetails

        Code Block
        languagegraphql
        type UserDetails {
          ...
          """
          Acceptance Agreement info
          """
          requiredAcceptanceAgreementInfo: [RequiredAcceptanceAgreementInfo]
        }
      • We will run the command:

        Code Block
        yarn run graphql:types
        • After that, will be created an automatic code on file: intl-whitelabel-graphql/src/functions/graphql/generated/graphql.ts, probably, will be many changes, but we can to discard all, except of change related about requiredAcceptanceAgreementInfo

  • intl-whitelabel-app

    • TASK 2 - Create fragment

      • We will add the attribute requiredAcceptanceAgreementInfo on fragment:

        • path: intl-whitelabel-app/workspaces/frontend/src/remote/queries/user.ts

          Code Block
          languagegraphql
          const DetailsFragment = gql`
            fragment DetailsFragment on UserDetails {
              ...
              requiredAcceptanceAgreementInfo {
                id
                updatedAt
              }
            }
          `;
        • We will run the command:

          Code Block
          languagepowershell
          yarn run apollo:generate
          • After that, will be created an automatic code on file: intl-whitelabel-app/workspaces/frontend/src/generated/rbi-graphql.tsx, probably, will be many changes, but we can to discard all, except of change related about:

            Code Block
            languagetypescript
            export interface IRequiredAcceptanceAgreementInfo {
              readonly __typename?: 'RequiredAcceptanceAgreementInfo',
              readonly id: Maybe<Scalars['String']>,
              readonly updatedAt: Maybe<Scalars['String']>,
            }
            Code Block
            languagetypescript
            export interface ISignUpUserInput {
              ...   readonly requiredAcceptanceAgreementInfo?: Maybe<ReadonlyArray<IRequiredAcceptanceAgreementInfoInput>>,
            }
            Code Block
            languagetypescript
            export interface IUserDetails {
              ...
              readonly requiredAcceptanceAgreementInfo: Maybe<ReadonlyArray<Maybe<IRequiredAcceptanceAgreementInfo>>>,
            }
            Code Block
            languagetypescript
            export type IUserDetailsFragment = { ...  readonly requiredAcceptanceAgreementInfo: Maybe<ReadonlyArray<Maybe<{ readonly __typename?: 'RequiredAcceptanceAgreementInfo', readonly id: Maybe<string>, readonly updatedAt: Maybe<string> }>>>}
            Code Block
            languagegraphql
            export const UserDetailsFragmentFragmentDoc = gql`
                fragment UserDetailsFragment on UserDetails {
              ...
              requiredAcceptanceAgreementInfo {
                id
                updatedAt
              }
            }
    • TASK 3 - Refactore method getRequiredAcceptanceAgreementInfo

      • We will change the existent method getRequiredAcceptanceAgreementInfo (name and container)

        • path: intl-whitelabel-app/workspaces/frontend/src/state/auth/hooks/use-account-authentication.ts

          • before

            Code Block
            languagetypescript
            const getRequiredAcceptanceAgreementInfo = useCallback(() => {
                if (!loadRoutesHasBeenCalled) {
                  loadRoutes();
                }
                return staticPageRoute
                  .map(pages => {
                    if (pages?.requiredUserAcceptance) {
                      return {
                        id: pages._id,
                        updatedAt: pages._updatedAt,
                      } as IRequiredAcceptanceAgreementInfoInput;
                    }
                    return [];
                  })
                  .flat();
              }, [loadRoutes, loadRoutesHasBeenCalled, staticPageRoute]);
          • after

            Code Block
            languagetypescript
            const getAcceptanceAgreementFromSanity = useCallback(() => {
                if (!loadRoutesHasBeenCalled) {
                  loadRoutes();
                }
                return staticPageRoute.filter(pages => pages?.requiredUserAcceptance);
              }, [loadRoutes, loadRoutesHasBeenCalled, staticPageRoute]);
          • After that, we will update the call from method signUp

            • before

              Code Block
              languagetypescript
              const requiredAcceptance = enableRequiredAcceptanceAgreementInfo
                    ? getRequiredAcceptanceAgreementInfo()
                    : undefined;
                    
              try {
                if (enableSignUpInBE) {
                  const { data } = await signUpMutation({
                    variables: {
                      input: {
                        ...
                        requiredAcceptanceAgreementInfo: requiredAcceptance,
                      },
                    },
                  });
                  ...
                } else {
                  ...      
                }
              } catch (error) {
                  ...
              };
            • after

              Code Block
              languagetypescript
              const requiredAcceptance = enableRequiredAcceptanceAgreementInfo
                    ? getAcceptanceAgreementFromSanity()
                    : [];
              
                  const requiredAcceptanceFilter = requiredAcceptance.map(pages => {
                    return {
                      id: pages._id,
                      updatedAt: pages._updatedAt,
                    } as IRequiredAcceptanceAgreementInfoInput;
                  });
                  
                  
              try {
                if (enableSignUpInBE) {
                  const { data } = await signUpMutation({
                    variables: {
                      input: {
                        ...
                        requiredAcceptanceAgreementInfo: requiredAcceptanceFilter,
                      },
                    },
                  });
                  ...
                } else {
                  ...      
                }
              } catch (error) {
                  ...
              };
          • We will create the method validateAcceptanceAgreement

            Code Block
            languagetypescript
            const validateAcceptanceAgreement = useCallback((user: IUser): IStaticPageRoute[] => {
                const requiredAcceptanceAgreementInfo = user?.details?.requiredAcceptanceAgreementInfo;
                
               if (requiredAcceptanceAgreementInfo?.length) { const sanityAcceptanceAgreement = getAcceptanceAgreementFromSanity();
                
              const sanityAcceptanceAgreement =if getAcceptanceAgreementFromSanity(requiredAcceptanceAgreementInfo?.length); {
                  return sanityAcceptanceAgreement.filter((sanityAcceptance: IStaticPageRoute) =>
                    requiredAcceptanceAgreementInfo.find(
                      (acceptanceAgreement: IRequiredAcceptanceAgreementInfo) =>
                        sanityAcceptance._id === acceptanceAgreement.id &&
                        sanityAcceptance._updatedAt !== acceptanceAgreement.updatedAt
                    )
                  );
                }
                
                return []sanityAcceptanceAgreement;
              }, [getAcceptanceAgreementFromSanity, user]);
          • Finishing, we will export these methods getAcceptanceAgreementFromSanity and validateAcceptanceAgreement on hook useAccountAuthentication return

            Code Block
            languagetypescript
            return {
                ...
                getAcceptanceAgreementFromSanity,
                validateAcceptanceAgreement
              };
    • TASK 4 - Add validation on index auth

      • On file:

        • path: intl-whitelabel-app/workspaces/frontend/src/state/auth/index.tsx

        • We will export validateAcceptanceAgreement

          Code Block
          languagetypescript
          const {
              ...
              validateAcceptanceAgreement,
            } = useAccountAuthentication({
              refreshCurrentUser,
              openErrorDialog,
              setCurrentUser,
            });
        • After that, we will create a useEffect:

          Code Block
          languagetypescript
          useEffect(() => {
            const validate = enableRequiredAcceptanceAgreementInfo ? validateAcceptanceAgreement(user) : [];
          
            if (validate?.length) {
              // TODO MODAL COMPONENT
            }
          }, [user, validateAcceptanceAgreement, getCtx]);
          • We will add on useEffect the method getCtx because all time the getCtx will change, we will validate the Acceptance Agreements

Screenshots

  • TODO

POC

  • TODO

Impact Analysis

  • Signup

  • Authentication

Unit Test

  • Signup

  • Authentication

MOCKS

  • TODO

Workflows: https://lucid.app/lucidchart/56ec4afb-d8ea-42a2-a2dd-3cc38bfd87e7/edit?viewport_loc=-11%2C-75%2C2219%2C1004%2C0_0&invitationId=inv_57ecb6ad-cde2-4c13-be58-853204ed3007

...