diff --git a/src/components/ageAssurance/AgeAssuranceInitDialog.tsx b/src/components/ageAssurance/AgeAssuranceInitDialog.tsx index bfaff57905..da7a236efc 100644 --- a/src/components/ageAssurance/AgeAssuranceInitDialog.tsx +++ b/src/components/ageAssurance/AgeAssuranceInitDialog.tsx @@ -4,11 +4,14 @@ import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {validate as validateEmail} from 'email-validator' +import {useCleanError} from '#/lib/hooks/useCleanError' import {useLanguagePrefs} from '#/state/preferences' import {useSession} from '#/state/session' import {atoms as a, useTheme, web} from '#/alf' +import {Admonition} from '#/components/Admonition' import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge' import {urls} from '#/components/ageAssurance/const' +import {useInitAgeAssurance} from '#/components/ageAssurance/useInitAgeAssurance' import {Button, ButtonIcon, ButtonText} from '#/components/Button' import * as Dialog from '#/components/Dialog' import {Divider} from '#/components/Divider' @@ -16,6 +19,7 @@ import * as TextField from '#/components/forms/TextField' import {Envelope_Stroke2_Corner0_Rounded as Envelope} from '#/components/icons/Envelope' import {LanguageSelect} from '#/components/LanguageSelect' import {InlineLinkText} from '#/components/Link' +import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' export {useDialogControl} from '#/components/Dialog/context' @@ -51,10 +55,16 @@ function Inner() { const {_} = useLingui() const {currentAccount} = useSession() const langPrefs = useLanguagePrefs() + const cleanError = useCleanError() + const {close} = Dialog.useDialogContext() + const [success, setSuccess] = useState(false) const [email, setEmail] = useState(currentAccount?.email || '') const [emailValid, setEmailValid] = useState(validateEmail(email)) const [language, setLanguage] = useState(langPrefs.appLanguage) + const [error, setError] = useState('') + + const {mutateAsync: init, isPending} = useInitAgeAssurance() const onSubmit = async () => { try { @@ -62,7 +72,17 @@ function Inner() { setEmailValid(false) return } - } catch (e) {} + + await init({ + email, + language, + }) + + setSuccess(true) + } catch (e) { + const {clean} = cleanError(e) + setError(clean || _(msg`Something went wrong, please try again`)) + } } return ( @@ -71,108 +91,139 @@ function Inner() { - Verify your age + {success ? Success! : Verify your age} - - - We use{' '} - - KWS - {' '} - to verify that you’re an adult. When you click "Get an email" - below, Bluesky will share your email address with KWS. - - - - - If KWS cannot use your email address to confirm that you - previously verified your age, you’ll be taken to the KWS website - to provide more details. - - - - This should only take a few minutes. - + {success ? ( + + Please check your email to contine the process. + + ) : ( + <> + + + We use{' '} + + KWS + {' '} + to verify that you’re an adult. When you click "Get an email" + below, Bluesky will share your email address with KWS. + + + + + If KWS cannot use your email address to confirm that you + previously verified your age, you’ll be taken to the KWS + website to provide more details. + + + + This should only take a few minutes. + + + )} - - - - - - Your email - - - setEmailValid(true)} - onBlur={() => { - setEmailValid(validateEmail(email)) - }} - returnKeyType="done" - autoCapitalize="none" - autoComplete="off" - autoCorrect={false} - onSubmitEditing={onSubmit} - /> - + {success ? ( + + + ) : ( + <> + - - - Your preferred language - - - + + + + Your email + + + setEmailValid(true)} + onBlur={() => { + setEmailValid(validateEmail(email)) + }} + returnKeyType="done" + autoCapitalize="none" + autoComplete="off" + autoCorrect={false} + onSubmitEditing={onSubmit} + /> + + - - + + + Your preferred language + + + - - - By continuing, you agree to the{' '} - - KWS Terms of Use - {' '} - and acknowledge that KWS will store your verified status alongside - your hashed email address in accordance with the{' '} - - KWS Privacy Policy - - . This means you won’t need to verify again the next time you use - this email for other apps, games, and services powered by KWS - technology. - - + {error && {error}} + + + + + + + By continuing, you agree to the{' '} + + KWS Terms of Use + {' '} + and acknowledge that KWS will store your verified status + alongside your hashed email address in accordance with the{' '} + + KWS Privacy Policy + + . This means you won’t need to verify again the next time you + use this email for other apps, games, and services powered by + KWS technology. + + + + )} ) diff --git a/src/components/ageAssurance/useInitAgeAssurance.ts b/src/components/ageAssurance/useInitAgeAssurance.ts new file mode 100644 index 0000000000..9d79ca31c8 --- /dev/null +++ b/src/components/ageAssurance/useInitAgeAssurance.ts @@ -0,0 +1,38 @@ +import {useMutation} from '@tanstack/react-query' + +import {wait} from '#/lib/async/wait' +import {isNetworkError} from '#/lib/hooks/useCleanError' +import {logger} from '#/logger' +// import {useAgent} from '#/state/session'; + +type TempInputSchema = { + email: string + language: string +} + +export function useInitAgeAssurance() { + // const agent = useAgent() + return useMutation({ + async mutationFn(_props: TempInputSchema) { + // 2s wait is good actually, email sending takes a hot sec + // const {data} = await wait(2e3, agent.app.bsky.unspecced.initAgeAssurance(props)) + await wait( + 2e3, + (() => ({ + data: { + $type: 'app.bsky.unspecced.defs#ageAssuranceState', + lastInitiatedAt: new Date().toISOString(), + status: 'pending', + }, + }))(), + ) + }, + onError(e) { + if (!isNetworkError(e)) { + logger.error(`useInitAgeAssurance failed`, { + safeMessage: e, + }) + } + }, + }) +}