-
Notifications
You must be signed in to change notification settings - Fork 225
Expand file tree
/
Copy pathcontainer.tsx
More file actions
125 lines (111 loc) · 3.95 KB
/
container.tsx
File metadata and controls
125 lines (111 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { RouteComponentProps, useLocation } from '@reach/router';
import { useNavigateWithQuery } from '../../../lib/hooks/useNavigateWithQuery';
import SigninPasswordlessCode from '.';
import AppLayout from '../../../components/AppLayout';
import { useAuthClient } from '../../../models';
import { useFinishOAuthFlowHandler } from '../../../lib/oauth/hooks';
import {
PasswordlessLocationState,
SigninPasswordlessCodeContainerProps,
} from './interfaces';
import OAuthDataError from '../../../components/OAuthDataError';
import { useEffect, useState } from 'react';
const SigninPasswordlessCodeContainer = ({
integration,
setCurrentSplitLayout,
}: SigninPasswordlessCodeContainerProps & RouteComponentProps) => {
const navigateWithQuery = useNavigateWithQuery();
const location = useLocation() as ReturnType<typeof useLocation> & {
state?: PasswordlessLocationState;
};
const authClient = useAuthClient();
const { finishOAuthFlowHandler, oAuthDataError } = useFinishOAuthFlowHandler(
authClient,
integration
);
const email = location.state?.email;
const service = location.state?.service;
const isSignup = location.state?.isSignup;
const [codeSent, setCodeSent] = useState(
// If location state already has codeSent (persisted across page refresh
// via the History API), skip sending again.
() => location.state?.codeSent === true
);
const [sendError, setSendError] = useState<string | null>(null);
const cmsInfo = integration.getCmsInfo();
// Use SigninTokenCodePage layout as fallback since SigninPasswordlessCodePage doesn't exist yet
const splitLayout = (cmsInfo as any)?.SigninPasswordlessCodePage?.splitLayout ||
cmsInfo?.SigninTokenCodePage?.splitLayout;
// If no email in state, redirect to signin
useEffect(() => {
if (!email) {
navigateWithQuery('/');
}
}, [email, navigateWithQuery]);
// Send the initial code when component mounts, but skip if already sent
// (e.g. after a page refresh). On success, replace the current history
// entry with codeSent: true so the browser-persisted location state
// prevents re-sending on refresh.
useEffect(() => {
if (email && !codeSent) {
const sendCode = async () => {
try {
await authClient.passwordlessSendCode(email, { clientId: integration.getClientId() });
setCodeSent(true);
// Persist codeSent in location state so it survives page refresh
navigateWithQuery(location.pathname + location.search, {
replace: true,
state: { ...location.state, codeSent: true },
});
} catch (error: any) {
setSendError(error.message || 'Failed to send code');
}
};
sendCode();
}
}, [email, service, codeSent, authClient, integration, navigateWithQuery, location.pathname, location.search, location.state]);
if (!email) {
return (
<AppLayout
{...{ cmsInfo, loading: true, splitLayout, setCurrentSplitLayout }}
/>
);
}
if (oAuthDataError) {
return <OAuthDataError error={oAuthDataError} />;
}
if (sendError) {
// TODO: Better error handling - for now show in AppLayout
return (
<AppLayout
{...{ cmsInfo, splitLayout, setCurrentSplitLayout }}
>
<div className="text-red-600">Error: {sendError}</div>
</AppLayout>
);
}
if (!codeSent) {
return (
<AppLayout
{...{ cmsInfo, loading: true, splitLayout, setCurrentSplitLayout }}
/>
);
}
return (
<SigninPasswordlessCode
{...{
email,
expirationMinutes: 10,
integration,
finishOAuthFlowHandler,
setCurrentSplitLayout,
isSignup,
resendCountdownSeconds: 5,
}}
/>
);
};
export default SigninPasswordlessCodeContainer;