Questions:
Possibles questions about this feature
Technical Refinement
Description
intl-whitelabel-graphql
TASK 1
We will create a
type
namedRequiredAcceptanceAgreementInfo
path:
intl-whitelabel-graphql/src/functions/graphql/schemas/users.gql
type RequiredAcceptanceAgreementInfo { """ Acceptance Agreement ID """ id: String """ Updated Date """ updatedAt: String }
Also, we will add
requiredAcceptanceAgreementInfo
on typeUserDetails
type UserDetails { ... """ Acceptance Agreement info """ requiredAcceptanceAgreementInfo: [RequiredAcceptanceAgreementInfo] }
We will run the command:
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 aboutrequiredAcceptanceAgreementInfo
intl-whitelabel-app
TASK 2
We will add the attribute
requiredAcceptanceAgreementInfo
onfragment
:path:
intl-whitelabel-app/workspaces/frontend/src/remote/queries/user.ts
const DetailsFragment = gql` fragment DetailsFragment on UserDetails { ... requiredAcceptanceAgreementInfo { id updatedAt } } `;
We will run the command:
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:export interface IRequiredAcceptanceAgreementInfo { readonly __typename?: 'RequiredAcceptanceAgreementInfo', readonly id: Maybe<Scalars['String']>, readonly updatedAt: Maybe<Scalars['String']>, }
export interface ISignUpUserInput { ... readonly requiredAcceptanceAgreementInfo?: Maybe<ReadonlyArray<IRequiredAcceptanceAgreementInfoInput>>, }
export interface IUserDetails { ... readonly requiredAcceptanceAgreementInfo: Maybe<ReadonlyArray<Maybe<IRequiredAcceptanceAgreementInfo>>>, }
export type IUserDetailsFragment = { ... readonly requiredAcceptanceAgreementInfo: Maybe<ReadonlyArray<Maybe<{ readonly __typename?: 'RequiredAcceptanceAgreementInfo', readonly id: Maybe<string>, readonly updatedAt: Maybe<string> }>>>}
export const UserDetailsFragmentFragmentDoc = gql` fragment UserDetailsFragment on UserDetails { ... requiredAcceptanceAgreementInfo { id updatedAt } }
TASK 3
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
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
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
const requiredAcceptance = enableRequiredAcceptanceAgreementInfo ? getRequiredAcceptanceAgreementInfo() : undefined; try { if (enableSignUpInBE) { const { data } = await signUpMutation({ variables: { input: { ... requiredAcceptanceAgreementInfo: requiredAcceptance, }, }, }); ... } else { ... } } catch (error) { ... };
after
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
const validateAcceptanceAgreement = useCallback((user: IUser): IStaticPageRoute[] => { const requiredAcceptanceAgreementInfo = user?.details?.requiredAcceptanceAgreementInfo; if (requiredAcceptanceAgreementInfo?.length) { const sanityAcceptanceAgreement = getAcceptanceAgreementFromSanity(); return sanityAcceptanceAgreement.filter((sanityAcceptance: IStaticPageRoute) => requiredAcceptanceAgreementInfo.find( (acceptanceAgreement: IRequiredAcceptanceAgreementInfo) => sanityAcceptance._id === acceptanceAgreement.id && sanityAcceptance._updatedAt !== acceptanceAgreement.updatedAt ) ); } return []; }, [getAcceptanceAgreementFromSanity, user]);
Finishing, we will export these methods
getAcceptanceAgreementFromSanity
andvalidateAcceptanceAgreement
on hookuseAccountAuthentication
returnreturn { ... getAcceptanceAgreementFromSanity, validateAcceptanceAgreement };
TASK 4
On file:
path:
intl-whitelabel-app/workspaces/frontend/src/state/auth/index.tsx
We will export
validateAcceptanceAgreement
const { ... validateAcceptanceAgreement, } = useAccountAuthentication({ refreshCurrentUser, openErrorDialog, setCurrentUser, });
After that, we will create a
useEffect
:useEffect(() => { const validate = enableRequiredAcceptanceAgreementInfo ? validateAcceptanceAgreement(user) : []; if (validate?.length) { // TODO MODAL COMPONENT } }, [user, validateAcceptanceAgreement, getCtx]);
We will add on
useEffect
the methodgetCtx
because all time thegetCtx
will change, we will validate the Acceptance Agreements
Screenshots
TODO
POC
TODO
Impact Analysis
Signup
Authentication
Unit Test
Signup
Authentication
MOCKS
TODO
Useful Links
Existent behavior: /wiki/spaces/IN/pages/4044391349
Add Comment