diff options
Diffstat (limited to 'src/view/com/modals/Waitlist.tsx')
-rw-r--r-- | src/view/com/modals/Waitlist.tsx | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/view/com/modals/Waitlist.tsx b/src/view/com/modals/Waitlist.tsx new file mode 100644 index 000000000..f3c301937 --- /dev/null +++ b/src/view/com/modals/Waitlist.tsx @@ -0,0 +1,163 @@ +import React from 'react' +import { + ActivityIndicator, + StyleSheet, + TouchableOpacity, + View, +} from 'react-native' +import {TextInput} from './util' +import { + FontAwesomeIcon, + FontAwesomeIconStyle, +} from '@fortawesome/react-native-fontawesome' +import LinearGradient from 'react-native-linear-gradient' +import {Text} from '../util/text/Text' +import {useStores} from 'state/index' +import {s, gradients} from 'lib/styles' +import {usePalette} from 'lib/hooks/usePalette' +import {useTheme} from 'lib/ThemeContext' +import {ErrorMessage} from '../util/error/ErrorMessage' +import {cleanError} from 'lib/strings/errors' + +export const snapPoints = ['60%'] + +export function Component({}: {}) { + const pal = usePalette('default') + const theme = useTheme() + const store = useStores() + const [email, setEmail] = React.useState<string>('') + const [isEmailSent, setIsEmailSent] = React.useState<boolean>(false) + const [isProcessing, setIsProcessing] = React.useState<boolean>(false) + const [error, setError] = React.useState<string>('') + + const onPressSignup = async () => { + setError('') + setIsProcessing(true) + try { + const res = await fetch('https://bsky.app/api/waitlist', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({email}), + }) + const resBody = await res.json() + if (resBody.success) { + setIsEmailSent(true) + } else { + setError( + resBody.error || + 'Something went wrong. Check your email and try again.', + ) + } + } catch (e: any) { + setError(cleanError(e)) + } + setIsProcessing(false) + } + const onCancel = () => { + store.shell.closeModal() + } + + return ( + <View + style={[styles.container, {backgroundColor: pal.colors.backgroundLight}]}> + <View style={[styles.innerContainer, pal.view]}> + <Text type="title-xl" style={[styles.title, pal.text]}> + Join the waitlist + </Text> + <Text type="lg" style={[styles.description, pal.text]}> + Bluesky will launch soon. Join the waitlist to try the beta before + it's publicly available. + </Text> + <TextInput + style={[styles.textInput, pal.borderDark, pal.text, s.mb10, s.mt10]} + placeholder="Enter your email" + placeholderTextColor={pal.textLight.color} + autoCapitalize="none" + autoCorrect={false} + keyboardAppearance={theme.colorScheme} + value={email} + onChangeText={setEmail} + /> + {error ? ( + <View style={s.mt10}> + <ErrorMessage message={error} style={styles.error} /> + </View> + ) : undefined} + {isProcessing ? ( + <View style={[styles.btn, s.mt10]}> + <ActivityIndicator /> + </View> + ) : isEmailSent ? ( + <View style={[styles.btn, s.mt10]}> + <FontAwesomeIcon + icon="check" + style={pal.text as FontAwesomeIconStyle} + /> + <Text style={s.ml10}> + Your email has been saved! We'll be in touch soon. + </Text> + </View> + ) : ( + <> + <TouchableOpacity onPress={onPressSignup}> + <LinearGradient + colors={[gradients.blueLight.start, gradients.blueLight.end]} + start={{x: 0, y: 0}} + end={{x: 1, y: 1}} + style={[styles.btn]}> + <Text type="button-lg" style={[s.white, s.bold]}> + Join Waitlist + </Text> + </LinearGradient> + </TouchableOpacity> + <TouchableOpacity style={[styles.btn, s.mt10]} onPress={onCancel}> + <Text type="button-lg" style={pal.textLight}> + Cancel + </Text> + </TouchableOpacity> + </> + )} + </View> + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + innerContainer: { + paddingBottom: 20, + }, + title: { + textAlign: 'center', + marginTop: 12, + marginBottom: 12, + }, + description: { + textAlign: 'center', + paddingHorizontal: 22, + marginBottom: 10, + }, + textInput: { + borderWidth: 1, + borderRadius: 6, + paddingHorizontal: 16, + paddingVertical: 12, + fontSize: 20, + marginHorizontal: 20, + }, + btn: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + borderRadius: 32, + padding: 14, + marginHorizontal: 20, + }, + error: { + borderRadius: 6, + marginHorizontal: 20, + marginBottom: 20, + }, +}) |