From c758389ad2ebe98196d4618ec08dbf2b24d95bfa Mon Sep 17 00:00:00 2001 From: Ashm Walia <40498934+ashmgarv@users.noreply.github.com> Date: Tue, 12 Jan 2021 13:35:33 -0800 Subject: [TMA 472] Added option to be added to Taggs wait list (#168) * Added screens to add to waitlist and a page to display on success of the same * Incorporated small comment --- src/assets/icons/celebration-logo.svg | 1 + src/components/onboarding/TaggBigInput.tsx | 3 +- src/components/onboarding/TaggInput.tsx | 3 +- .../onboarding/TermsAndConditionsText.tsx | 13 +- src/constants/api.ts | 1 + src/constants/constants.ts | 2 + src/routes/onboarding/OnboardingStackNavigator.tsx | 2 + src/routes/onboarding/OnboardingStackScreen.tsx | 10 + src/screens/onboarding/AddWaitlistUserScreen.tsx | 238 +++++++++++++++++++++ .../onboarding/InvitationCodeVerification.tsx | 29 ++- src/screens/onboarding/Login.tsx | 8 +- src/screens/onboarding/WaitlistSuccessScreen.tsx | 156 ++++++++++++++ src/screens/onboarding/index.ts | 2 + src/services/WaitlistUserService.tsx | 45 ++++ src/services/index.ts | 1 + 15 files changed, 506 insertions(+), 8 deletions(-) create mode 100644 src/assets/icons/celebration-logo.svg create mode 100644 src/screens/onboarding/AddWaitlistUserScreen.tsx create mode 100644 src/screens/onboarding/WaitlistSuccessScreen.tsx create mode 100644 src/services/WaitlistUserService.tsx (limited to 'src') diff --git a/src/assets/icons/celebration-logo.svg b/src/assets/icons/celebration-logo.svg new file mode 100644 index 00000000..5e4e89a0 --- /dev/null +++ b/src/assets/icons/celebration-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/onboarding/TaggBigInput.tsx b/src/components/onboarding/TaggBigInput.tsx index ba965465..4e8e1ef7 100644 --- a/src/components/onboarding/TaggBigInput.tsx +++ b/src/components/onboarding/TaggBigInput.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {View, TextInput, StyleSheet, TextInputProps} from 'react-native'; import * as Animatable from 'react-native-animatable'; +import {TAGG_LIGHT_PURPLE} from '../../constants'; interface TaggBigInputProps extends TextInputProps { valid?: boolean; @@ -55,7 +56,7 @@ const styles = StyleSheet.create({ warning: { fontSize: 14, marginTop: 5, - color: '#f4ddff', + color: TAGG_LIGHT_PURPLE, maxWidth: 350, textAlign: 'center', }, diff --git a/src/components/onboarding/TaggInput.tsx b/src/components/onboarding/TaggInput.tsx index 12d99325..405564ab 100644 --- a/src/components/onboarding/TaggInput.tsx +++ b/src/components/onboarding/TaggInput.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {View, TextInput, StyleSheet, TextInputProps} from 'react-native'; import * as Animatable from 'react-native-animatable'; +import {TAGG_LIGHT_PURPLE} from '../../constants'; interface TaggInputProps extends TextInputProps { valid?: boolean; @@ -52,7 +53,7 @@ const styles = StyleSheet.create({ warning: { fontSize: 14, marginTop: 5, - color: '#f4ddff', + color: TAGG_LIGHT_PURPLE, maxWidth: 350, textAlign: 'center', }, diff --git a/src/components/onboarding/TermsAndConditionsText.tsx b/src/components/onboarding/TermsAndConditionsText.tsx index 39450667..2102d613 100644 --- a/src/components/onboarding/TermsAndConditionsText.tsx +++ b/src/components/onboarding/TermsAndConditionsText.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; -import {StyleSheet, Text} from 'react-native'; +import {Linking, StyleSheet, Text} from 'react-native'; +import {TAGG_WEBSITE} from '../../constants'; const TermsAndConditionsText: React.FC = () => { const textWithBulletPoint = (data: string, style: object) => { @@ -550,8 +551,14 @@ const TermsAndConditionsText: React.FC = () => { By email: support@tagg.id - By visiting this page on our website:{' '} - https://www.tagg.id/ + By visiting this page on our{' '} + { + Linking.openURL(TAGG_WEBSITE + 'terms-and-conditions/'); + }}> + website + ); diff --git a/src/constants/api.ts b/src/constants/api.ts index 3b2289fd..639bc8f8 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -27,6 +27,7 @@ export const BLOCK_USER_ENDPOINT: string = API_URL + 'block/'; export const PASSWORD_RESET_ENDPOINT: string = API_URL + 'password-reset/'; export const MOMENT_CATEGORY_ENDPOINT: string = API_URL + 'moment-category/'; export const NOTIFICATIONS_ENDPOINT: string = API_URL + 'notifications/'; +export const WAITLIST_USER_ENDPOINT: string = API_URL + 'waitlist-user/'; // Register as FCM device export const FCM_ENDPOINT: string = API_URL + 'fcm/'; diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 8d8b7dfe..90d70724 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -60,6 +60,7 @@ export const YOUTUBE_FONT_COLOR: string = '#FCA4A4'; export const TAGG_DARK_BLUE = '#4E699C'; export const TAGG_TEXT_LIGHT_BLUE: string = '#698DD3'; +export const TAGG_LIGHT_PURPLE = '#F4DDFF'; export const TAGGS_GRADIENT = { start: '#9F00FF', @@ -141,6 +142,7 @@ export const CLASS_YEAR_LIST: Array = [ '2026', ]; +export const TAGG_WEBSITE = 'https://www.tagg.id/'; export const MOMENT_CATEGORY_BG_COLORS: string[] = [ '#5E4AE4', '#5044A6', diff --git a/src/routes/onboarding/OnboardingStackNavigator.tsx b/src/routes/onboarding/OnboardingStackNavigator.tsx index ea7ce8e8..9f614f7c 100644 --- a/src/routes/onboarding/OnboardingStackNavigator.tsx +++ b/src/routes/onboarding/OnboardingStackNavigator.tsx @@ -39,6 +39,8 @@ export type OnboardingStackParams = { TaggPopup: { popupProps: TaggPopupType; }; + AddWaitlistUser: undefined; + WaitlistSuccess: undefined; }; export const OnboardingStack = createStackNavigator(); diff --git a/src/routes/onboarding/OnboardingStackScreen.tsx b/src/routes/onboarding/OnboardingStackScreen.tsx index 54614b32..afc5be99 100644 --- a/src/routes/onboarding/OnboardingStackScreen.tsx +++ b/src/routes/onboarding/OnboardingStackScreen.tsx @@ -14,6 +14,8 @@ import { PasswordReset, WelcomeScreen, CategorySelection, + AddWaitlistUserScreen, + WaitlistSuccessScreen, } from '../../screens'; import {StackCardInterpolationProps} from '@react-navigation/stack'; import TaggPopup from '../../components/common/TaggPopup'; @@ -96,6 +98,14 @@ const Onboarding: React.FC = () => { name="InvitationCodeVerification" component={InvitationCodeVerification} /> + + ; + +interface AddWaitlistUserScreenProps { + navigation: AddWaitlistUserScreenProp; +} + +const AddWaitlistUserScreen: React.FC = ({ + navigation, +}) => { + const phoneRef = React.useRef(); + const lnameRef = React.useRef(); + + const [form, setForm] = React.useState({ + phone_number: {value: '', isValid: false}, + first_name: {value: '', isValid: false}, + last_name: {value: '', isValid: false}, + attemptedSubmit: false, + }); + + //Handlers + const handleFocusChange = (field: string): void => { + switch (field) { + case 'last_name': + const lnameField: any = lnameRef.current; + lnameField.focus(); + break; + case 'phone_number': + const phoneField: any = phoneRef.current; + phoneField.focus(); + break; + default: + return; + } + }; + + const validate = (value: string, type: string) => { + let isValid: boolean = false; + switch (type) { + case 'phone_number': + isValid = phoneRegex.test(value); + break; + default: + isValid = nameRegex.test(value); + break; + } + return isValid; + }; + + const handleUpdate = (value: string, type: string) => { + value = value.trim(); + const isValid = validate(value, type); + setForm({ + ...form, + [type]: {value, isValid}, + }); + }; + + const handleAddUser = async () => { + if (!form.attemptedSubmit) { + setForm({ + ...form, + attemptedSubmit: true, + }); + } + try { + const {phone_number, first_name, last_name} = form; + if (phone_number.isValid && first_name.isValid && last_name.isValid) { + const success = await adduserToWaitlist( + phone_number.value, + first_name.value, + last_name.value, + ); + if (success) { + navigation.navigate('WaitlistSuccess'); + } + } else { + setForm({...form, attemptedSubmit: false}); + setTimeout(() => setForm({...form, attemptedSubmit: true})); + } + } catch (err) { + console.log(err); + } + }; + + //Components + const Footer = () => ( + + navigation.navigate('InvitationCodeVerification')} + /> + + ); + + const {phone_number, first_name, last_name} = form; + + return ( + + + + + JOIN WAITLIST + + handleUpdate(text, 'first_name')} + onSubmitEditing={() => handleFocusChange('first_name')} + blurOnSubmit={false} + valid={first_name.isValid} + invalidWarning="Please enter a valid first name." + attemptedSubmit={form.attemptedSubmit} + width={280} + /> + handleUpdate(text, 'last_name')} + blurOnSubmit={false} + ref={lnameRef} + valid={last_name.isValid} + invalidWarning="Please enter a valid last name." + onSubmitEditing={() => handleFocusChange('phone_number')} + attemptedSubmit={form.attemptedSubmit} + width={280} + /> + handleUpdate(text, 'phone_number')} + blurOnSubmit={false} + ref={phoneRef} + valid={phone_number.isValid} + invalidWarning="Please enter a valid 10 digit number." + onSubmitEditing={handleAddUser} + attemptedSubmit={form.attemptedSubmit} + width={280} + /> + + Submit + + + +