Skip to content

Commit c5aa602

Browse files
author
MargeBot
committed
Merge branch 'CP-9953-referral-signup-page' into 'main'
Add referral signup page See merge request web/clients!17479
2 parents 238ab81 + 6bbeab6 commit c5aa602

File tree

81 files changed

+2513
-207
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+2513
-207
lines changed

applications/account/src/app/content/PublicApp.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ const BasePublicApp = ({ sessions }: { sessions: ReturnType<typeof bootstrapApp>
624624
path={[
625625
SSO_PATHS.SIGNUP,
626626
SSO_PATHS.START,
627-
SSO_PATHS.REFER,
627+
SSO_PATHS.REFERAL_PLAN_SELECTION,
628628
SSO_PATHS.BUSINESS_SIGNUP,
629629
SSO_PATHS.CALENDAR_SIGNUP,
630630
SSO_PATHS.CALENDAR_SIGNUP_B2B,
@@ -655,7 +655,7 @@ const BasePublicApp = ({ sessions }: { sessions: ReturnType<typeof bootstrapApp>
655655
toApp={maybePreAppIntent}
656656
toAppName={toAppName}
657657
searchParams={searchParams}
658-
onLogin={handleLogin}
658+
handleLogin={handleLogin}
659659
fork={!!forkState}
660660
onBack={
661661
hasBackToSwitch

applications/account/src/app/content/SingleSignupSwitchContainer.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type { ActiveSession } from '@proton/shared/lib/authentication/persistedS
77
import { type APP_NAMES, type CLIENT_TYPES, SSO_PATHS } from '@proton/shared/lib/constants';
88

99
import SignupContainer from '../signup/SignupContainer';
10-
import { isMailReferAFriendSignup } from '../signup/helper';
10+
import { isReferralSignup } from '../signup/helper';
1111
import { getSignupMeta } from '../signup/signupPagesJson';
1212
import SignupCtxRouter from '../signupCtx/SignupCtxRouter';
1313
import SingleSignupContainerV2 from '../single-signup-v2/SingleSignupContainerV2';
@@ -19,7 +19,7 @@ interface Props {
1919
maybePreAppIntent: APP_NAMES | undefined;
2020
searchParams: URLSearchParams;
2121
initialSearchParams?: URLSearchParams;
22-
onLogin: OnLoginCallback;
22+
handleLogin: OnLoginCallback;
2323
productParam: ProductParam;
2424
toApp?: APP_NAMES;
2525
toAppName?: string;
@@ -38,7 +38,7 @@ interface Props {
3838
const SingleSignupSwitchContainer = ({
3939
maybePreAppIntent,
4040
initialSearchParams,
41-
onLogin,
41+
handleLogin,
4242
productParam,
4343
toAppName,
4444
clientType,
@@ -54,9 +54,8 @@ const SingleSignupSwitchContainer = ({
5454
initialSessionsLength,
5555
}: Props) => {
5656
const location = useLocation();
57-
const isMailRefer = isMailReferAFriendSignup(location);
5857

59-
// Ignore mail refer until we're sure it's been tested on sps
58+
const isReferral = isReferralSignup(location);
6059

6160
const renderContextSignup = searchParams.get('mode') === 'ctx' || location.pathname === SSO_PATHS.START;
6261

@@ -66,15 +65,15 @@ const SingleSignupSwitchContainer = ({
6665
<SignupCtxRouter
6766
onPreSubmit={onPreSubmit}
6867
onStartAuth={onStartAuth}
69-
onLogin={onLogin}
68+
handleLogin={handleLogin}
7069
loginUrl={paths.login}
7170
productParam={productParam}
7271
/>
7372
</UnAuthenticated>
7473
);
7574
}
7675

77-
if (isMailRefer) {
76+
if (isReferral) {
7877
return (
7978
<UnAuthenticated>
8079
<SignupContainer
@@ -85,7 +84,7 @@ const SingleSignupSwitchContainer = ({
8584
clientType={clientType}
8685
toApp={maybePreAppIntent}
8786
toAppName={toAppName}
88-
onLogin={onLogin}
87+
onLogin={handleLogin}
8988
onBack={onBack}
9089
onPreSubmit={onPreSubmit}
9190
onStartAuth={onStartAuth}
@@ -105,7 +104,7 @@ const SingleSignupSwitchContainer = ({
105104
clientType={clientType}
106105
toApp={maybePreAppIntent}
107106
toAppName={toAppName}
108-
onLogin={onLogin}
107+
onLogin={handleLogin}
109108
fork={fork}
110109
onBack={onBack}
111110
onPreSubmit={onPreSubmit}

applications/account/src/app/content/helper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export const getPaths = ({
156156
};
157157
};
158158

159-
export const getLocaleTermsURL = (app: APP_NAMES) => {
159+
export const getLocaleTermsURL = (app: APP_NAMES | undefined) => {
160160
return getTermsURL(app, getLocaleMapping(localeCode));
161161
};
162162

applications/account/src/app/signup/SignupContainer.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ import {
7676
getOptimisticDomains,
7777
getSignupApplication,
7878
getSubscriptionPricesWithFallback,
79-
isMailReferAFriendSignup,
79+
isReferralSignup,
8080
} from './helper';
8181
import type { InviteData, SignupActionResponse, SignupCacheResult, SignupModel, SubscriptionData } from './interfaces';
8282
import { SignupSteps, SignupType } from './interfaces';
@@ -142,7 +142,7 @@ const SignupContainer = ({
142142
const { APP_NAME } = useConfig();
143143

144144
const location = useLocationWithoutLocale<{ invite?: InviteData }>();
145-
const isMailRefer = isMailReferAFriendSignup(location);
145+
const isMailRefer = isReferralSignup(location);
146146

147147
useMetaTags(isMailRefer ? mailReferPage() : metaTags);
148148

@@ -300,7 +300,7 @@ const SignupContainer = ({
300300

301301
const { plans: Plans, freePlan } = plansResult;
302302

303-
if (location.pathname === SSO_PATHS.REFER && !referralData) {
303+
if (location.pathname === SSO_PATHS.REFERAL_PLAN_SELECTION && !referralData) {
304304
history.replace(SSO_PATHS.SIGNUP);
305305
}
306306

applications/account/src/app/signup/helper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ export async function getSubscriptionPricesWithFallback<T>(
7878
}
7979
}
8080

81-
export const isMailReferAFriendSignup = (location: Location) => {
82-
return location.pathname.includes(SSO_PATHS.REFER);
81+
export const isReferralSignup = (location: Location) => {
82+
return location.pathname.includes(SSO_PATHS.REFERAL_PLAN_SELECTION);
8383
};
8484

8585
export const isPorkbunSignup = (location: Location) => {

applications/account/src/app/signupCtx/SignupCtxRouter.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { type BaseSignupContextProps } from './context/SignupContext';
88
import DrivePricing from './flows/drive/DrivePricing';
99
import DriveSignup from './flows/drive/DriveSignup';
1010
import GenericStartSignup from './flows/genericStart/GenericStartSignup';
11+
import ReferralSignup from './flows/referral/ReferralSignup';
1112

1213
const DriveSignupController = (props: BaseSignupContextProps) => {
1314
return (
@@ -22,6 +23,10 @@ const DriveSignupController = (props: BaseSignupContextProps) => {
2223
);
2324
};
2425

26+
const ReferralSignupController = (props: BaseSignupContextProps) => {
27+
return <ReferralSignup {...props} />;
28+
};
29+
2530
const GenericSignupController = (props: BaseSignupContextProps) => {
2631
/**
2732
* Here we can control which signups to initiate
@@ -48,6 +53,9 @@ const SignupCtxRouter = (props: BaseSignupContextProps) => {
4853
<Route path={SSO_PATHS.DRIVE_SIGNUP}>
4954
<DriveSignupController {...props} />
5055
</Route>
56+
<Route path={SSO_PATHS.REFERAL_PLAN_SELECTION}>
57+
<ReferralSignupController {...props} />
58+
</Route>
5159
<Route>
5260
<GenericSignupController {...props} />
5361
</Route>

applications/account/src/app/signupCtx/accountDetailsInputs/username/useEmailInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const useEmailInput = ({
4141

4242
const [loadingChallenge, setLoadingChallenge] = useState(true);
4343

44-
const inputsWrapper = 'flex flex-column';
44+
const inputsWrapper = 'relative flex flex-column';
4545

4646
const { refs, state, errors, onValue, asyncStates, getAssistVisible } = accountDataContext;
4747

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { c } from 'ttag';
2+
3+
import { Href } from '@proton/atoms';
4+
import { getPrivacyPolicyURL } from '@proton/shared/lib/helpers/url';
5+
import clsx from '@proton/utils/clsx';
6+
7+
import { getLocaleTermsURL } from '../../content/helper';
8+
import { useSignup } from '../context/SignupContext';
9+
10+
const Terms = ({ className }: { className?: string }) => {
11+
const { app } = useSignup();
12+
13+
const termsApp = (() => {
14+
if (app === 'generic') {
15+
return undefined;
16+
}
17+
return app;
18+
})();
19+
20+
const termsAndConditionsLink = (
21+
<Href className="color-weak" key="terms" href={getLocaleTermsURL(termsApp)}>
22+
{
23+
// translator: Full sentence "By continuing, you agree to our terms and conditions and privacy policy."
24+
c('new_plans: signup').t`terms and conditions`
25+
}
26+
</Href>
27+
);
28+
29+
const privacyPolicyLink = (
30+
<Href className="color-weak" key="privacy" href={getPrivacyPolicyURL(termsApp)}>
31+
{
32+
// translator: Full sentence "By continuing, you agree to our terms and conditions and privacy policy."
33+
c('Link').t`privacy policy`
34+
}
35+
</Href>
36+
);
37+
38+
return (
39+
<div className={clsx('text-sm color-weak text-center', className)}>
40+
{
41+
// translator: Full sentence "By continuing, you agree to our terms and conditions and privacy policy."
42+
c('pass_signup_2023: Info')
43+
.jt`By continuing, you agree to our ${termsAndConditionsLink} and ${privacyPolicyLink}.`
44+
}
45+
</div>
46+
);
47+
};
48+
49+
export default Terms;

applications/account/src/app/signupCtx/context/SignupContext.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export interface AvailablePlan {
7171
}
7272

7373
interface SignupContextType {
74+
app: APP_NAMES | 'generic';
7475
domains: string[];
7576
/**
7677
* Sets the validated account data ready for the signup process.
@@ -105,7 +106,7 @@ const SignupContext = createContext<SignupContextType | null>(null);
105106
export interface BaseSignupContextProps {
106107
onPreSubmit?: () => Promise<void>;
107108
onStartAuth: () => Promise<void>;
108-
onLogin: OnLoginCallback;
109+
handleLogin: OnLoginCallback;
109110
loginUrl: string;
110111
productParam: ProductParam;
111112
}
@@ -662,6 +663,7 @@ export const InnerSignupContextProvider = ({
662663
}
663664

664665
const value: SignupContextType = {
666+
app,
665667
domains: domainsData.domains,
666668
login,
667669
submitAccountData: (accountData) => updateSignupData({ accountData }),

applications/account/src/app/signupCtx/flows/drive/DriveSignup.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import { LoaderPage } from '@proton/components';
55
import { useNotifyErrorHandler } from '@proton/components/hooks/useErrorHandler';
66
import { CYCLE, type Cycle, PLANS, type PlanIDs, getIsB2BAudienceFromPlan, getPlanNameFromIDs } from '@proton/payments';
77
import { usePaymentOptimistic } from '@proton/payments/ui';
8-
import { getAppHref } from '@proton/shared/lib/apps/helper';
98
import { APPS } from '@proton/shared/lib/constants';
10-
import { replaceUrl } from '@proton/shared/lib/helpers/browser';
119
import { hasFreePlanIDs } from '@proton/shared/lib/helpers/planIDs';
1210

1311
import { SignupType } from '../../../signup/interfaces';
@@ -82,10 +80,17 @@ const DriveSignupInner = () => {
8280

8381
const signup = useSignup();
8482

85-
const { options } = usePaymentOptimistic();
83+
const { options, initializationStatus } = usePaymentOptimistic();
8684

8785
const notifyError = useNotifyErrorHandler();
8886

87+
/**
88+
* Prevent content flashes where selected plan is initially the default before initialization occurs
89+
*/
90+
if (!initializationStatus.triggered) {
91+
return null;
92+
}
93+
8994
return (
9095
<>
9196
{step === 'account-details' && (
@@ -172,8 +177,7 @@ const DriveSignup = (props: BaseSignupContextProps) => {
172177
app={APPS.PROTONDRIVE}
173178
flowId="drive-generic"
174179
onLogin={(session) => {
175-
const url = new URL(getAppHref('/', APPS.PROTONDRIVE, session.localID));
176-
replaceUrl(url.toString());
180+
return props.handleLogin({ data: session, flow: 'signup', appIntent: { app: APPS.PROTONDRIVE } });
177181
}}
178182
paymentsDataConfig={{
179183
availablePlans,

0 commit comments

Comments
 (0)