Merge pull request #9 from Doble-Technologies/feature/registration-page-completion

Feature/registration page completion
This commit is contained in:
John Parkhurst 2024-08-30 02:07:22 -04:00 committed by GitHub
commit 5eb973869e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 385 additions and 199 deletions

331
app/generalHelpers.jsx Normal file
View file

@ -0,0 +1,331 @@
import styled from 'styled-components';
import { View, Text, LayoutAnimation, Image, TextInput, TouchableOpacity, TouchableNativeFeedback, ScrollView } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { Row } from '../components/Row';
import { Container } from '../components/Container';
export const StyledContainer = styled.View`
flex: 1;
padding: 25px;
`;
export const InnerContainer = styled.View`
flex: 1;
width: 100%;
align-items: center;
`;
export const StyledFormArea = styled.View`
padding-top: 10px;
width: 90%;
`;
export const Title = styled.Text`
text-align: center;
padding: 10px 10px 0px 10px;
font-size: 30px;
font-wieght: bold;
`;
export const SubTitle = styled.Text`
text-align: center;
font-size: 15px;
`;
export const PageImage = styled.Image``;
export const StyledTextInput = styled.TextInput`
background-color: #E5E7EB;
padding: 15px 55px 15px 55px;
border-radius: 5px;
font-size: 16px;
height: 60px;
margin-vertical: 3px;
margin-bottom: 10px;
`;
export const StyledInputLabel = styled.Text`
font-size: 13px;
text-align: left;
`;
export const LeftIcon = styled.View`
left: 15px;
top: 32px;
position: absolute;
z-index: 1;
`;
export const RightIcon = styled.TouchableOpacity`
right: 15px;
top: 32px;
position: absolute;
z-index: 1;
`;
export const DropdownArrow = styled.TouchableOpacity`
right: 15px;
position: absolute;
z-index: 1;
`;
export const SelectedCheckmark = styled.View`
right: 4px;
top: 4px;
position: absolute;
z-index: 1;
`;
export const StyledButton = styled.TouchableOpacity`
padding: 15px;
background-color: red;
justify-content: center;
align-items: center;
border-radius: 5px;
margin-vertical: 5px;
height: 60px;
`;
export const ButtonText = styled.Text`
font-size: 16px;
font-weight: 450;
color: white;
`;
export const MessageBox = styled.Text`
text-align: center;
font-size: 13px;
`
export const Line = styled.View`
height: 1px;
width: 100%;
background-color: 'gray';
margin-vertical: 10px;
`
export const ExtraView = styled.View`
justify-content: center;
flex-direction: row;
align-items: center;
padding: 10px;
`
export const ExtraText = styled.Text`
justify0content: center;
align-content: center;
font-size: 15px;
`
export const TextLink = styled.TouchableOpacity`
justify-content: center;
align-content: center;
`
export const TextLinkContent = styled.Text`
color: red;
font-size: 15px;
`
const ProviderDropdown = styled.TouchableOpacity`
background-color: #E5E7EB;
padding: 15px 55px 15px 55px;
border-radius: 5px;
font-size: 16px;
height: 60px;
margin-vertical: 3px;
margin-bottom: 10px;
`
export const providerMenu = {
menuName: 'providerList',
placeholder: 'Select Provider',
iconColor: 'red',
iconName: 'globe-outline',
dropdownList: [
{ label: 'AllTel', value: 'alltel' },
{ label: 'AT&T', value: 'att' },
{ label: 'AT&T MMS', value: 'attmms' },
{ label: 'Boost', value: 'boost' },
{ label: 'Boost MMS', value: 'boostmms' },
{ label: 'C Spire', value: 'c' },
{ label: 'Consumer Cellular', value: 'consumer' },
{ label: 'Cricket', value: 'cricket' },
{ label: 'Cricket MMS', value: 'cricketmms' },
{ label: 'Google Fi', value: 'googlefi' },
{ label: 'Mint Mobile', value: 'mint' },
{ label: 'MetroPCS', value: 'metro' },
{ label: 'Optimum', value: 'optimum' },
{ label: 'Republic Wireless', value: 'republic' },
{ label: 'Spectrum', value: 'spectrum' },
{ label: 'Sprint', value: 'sprint' },
{ label: 'Sprint MMS', value: 'sprintmms' },
{ label: 'Ting', value: 'ting' },
{ label: 'T-Mobile', value: 'tmobile' },
{ label: 'TracFone', value: 'tracfone' },
{ label: 'US Cellular', value: 'us' },
{ label: 'US Cellular MMS', value: 'usmms' },
{ label: 'Verizon', value: 'verizon' },
{ label: 'Verizon MMS', value: 'verizonmms' },
{ label: 'VerizonBiz', value: 'verizonbiz' },
{ label: 'Virgin', value: 'virgin' },
{ label: 'Virgin MMS', value: 'virginmms' },
]
}
const providerConversion = {
alltel: 'AllTel',
att: 'AT&T',
attmms: 'AT&T MMS',
boost: 'Boost',
boostmms: 'Boost MMS',
c: 'C Spire',
consumer: 'Consumer Cellular',
cricket: 'Cricket',
cricketmms: 'Cricket MMS',
googlefi: 'Google Fi',
mint: 'Mint Mobile',
metro: 'MetroPCS',
optimum: 'Optimum',
republic: 'Republic Wireless',
spectrum: 'Spectrum',
sprint: 'Sprint',
sprintmms: 'Sprint MMS',
ting: 'Ting',
tmobile: 'T-Mobile',
tracfone: 'TracFone',
us: 'US Cellular',
usmms: 'US Cellular MMS',
verizon: 'Verizon',
verizonmms: 'Verizon MMS',
verizonbiz: 'VerizonBiz',
virgin: 'Virgin',
virginmms: 'Virgin MMS',
}
export const PageHeader = ({
children
}) => {
return (
<View style={{ position: 'sticky', top: 0, backgroundColor: '#ECEDEE', zIndex: 1, marginBottom: -80 }}>
<View style={{ flexDirection: 'row', height: 80, alignItems: 'flex-end' }}>
{children}
</View>
</View>
)
}
export const LoginTextInput = ({
label,
icon,
isPassword = false,
hidePassword = true,
setHidePassword = (boolean) => {},
...props
}) => {
return (
<View>
<LeftIcon>
<Ionicons name={icon} size={30} color='red' />
</LeftIcon>
<StyledInputLabel>{label}</StyledInputLabel>
<StyledTextInput {...props} />
{isPassword ? (
<RightIcon onPress={() => {setHidePassword(!hidePassword)}}>
<Ionicons name={hidePassword ? 'eye-off-outline' : 'eye-outline'} size={30} color="gray" />
</RightIcon>
) : null}
</View>
)
}
export const RegisterDropdownInput = ({
label,
isOpen,
setOpen,
selectedValue,
onValueChange,
menu
}) => {
return (
<Container>
<StyledInputLabel>{label}</StyledInputLabel>
<TouchableOpacity activeOpacity={0.8} key={`${menu.menuName}2`}
style={{
backgroundColor: '#E5E7EB',
marginTop: 3,
marginBottom: 10,
borderRadius: '5px',
}}
onPress={() => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity'));
isOpen ? setOpen(false) : setOpen(true);
}}>
<Row style={{
paddingHorizontal: 16,
paddingVertical: 16 / 1.2,
}}>
<Ionicons
name={menu.iconName}
size={30}
color={menu.iconColor}
/>
<Text style={{
fontSize: 16,
paddingHorizontal: 16
}}>
{selectedValue ? providerConversion[selectedValue] : menu.placeholder}
</Text>
<DropdownArrow
onPress={() => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity'));
isOpen ? setOpen(false) : setOpen(true);
}}
>
<Ionicons
name={isOpen ? "chevron-up-outline" : "chevron-down-outline"}
size={30}
color="gray"
/>
</DropdownArrow>
</Row>
{isOpen && <ScrollView style={{ borderRadius: '5px', backgroundColor: '#E5E7EB' }}>
{menu.dropdownList.map((subMenu, index) => {
return (
<TouchableNativeFeedback
key={index}
onPress={() => {
onValueChange(subMenu.value);
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity'));
setOpen(false);
}}
>
<View style={{
paddingHorizontal: 16,
paddingVertical: 16 / 1.5,
borderTopColor: 'gray',
borderTopWidth: .5,
marginHorizontal: 10
}}>
<Text>{subMenu.label}</Text>
{selectedValue === subMenu.value &&
<SelectedCheckmark>
<Ionicons
name="checkmark-outline"
size={30}
color="red"
/>
</SelectedCheckmark>
}
</View>
</TouchableNativeFeedback>
)
})}
</ScrollView>}
</TouchableOpacity>
</Container>
)
}

View file

@ -1,176 +0,0 @@
import styled from 'styled-components';
import Constants from 'expo-constants';
import { View, Text, Image, TextInput, TouchableOpacity } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { Picker } from '@react-native-picker/picker';
import { Children } from 'react';
const StatusBarHeight = Constants.statusBarHeight;
export const StyledContainer = styled.View`
flex: 1;
padding: 25px;
`;
export const InnerContainer = styled.View`
flex: 1;
width: 100%;
align-items: center;
`;
export const StyledFormArea = styled.View`
padding-top: 10px;
width: 90%;
`;
export const Title = styled.Text`
text-align: center;
padding: 10px 10px 0px 10px;
font-size: 30px;
font-wieght: bold;
`;
export const SubTitle = styled.Text`
text-align: center;
font-size: 15px;
`;
export const PageImage = styled.Image``;
export const StyledTextInput = styled.TextInput`
background-color: #E5E7EB;
padding: 15px 55px 15px 55px;
border-radius: 5px;
font-size: 16px;
height: 60px;
margin-vertical: 3px;
margin-bottom: 10px;
`;
export const StyledInputLabel = styled.Text`
font-size: 13px;
text-align: left;
`;
export const LeftIcon = styled.View`
left: 15px;
top: 32px;
position: absolute;
z-index: 1;
`;
export const RightIcon = styled.TouchableOpacity`
right: 15px;
top: 32px;
position: absolute;
z-index: 1;
`;
export const StyledButton = styled.TouchableOpacity`
padding: 15px;
background-color: red;
justify-content: center;
align-items: center;
border-radius: 5px;
margin-vertical: 5px;
height: 60px;
`;
export const ButtonText = styled.Text`
font-size: 16px;
font-weight: 450;
color: white;
`;
export const MessageBox = styled.Text`
text-align: center;
font-size: 13px;
`
export const Line = styled.View`
height: 1px;
width: 100%;
background-color: 'gray';
margin-vertical: 10px;
`
export const ExtraView = styled.View`
justify-content: center;
flex-direction: row;
align-items: center;
padding: 10px;
`
export const ExtraText = styled.Text`
justify0content: center;
align-content: center;
font-size: 15px;
`
export const TextLink = styled.TouchableOpacity`
justify-content: center;
align-content: center;
`
export const TextLinkContent = styled.Text`
color: red;
font-size: 15px;
`
export const PageHeader = ({
children
}) => {
return (
<View style={{ position: 'sticky', top: 0, backgroundColor: '#ECEDEE', zIndex: 1, marginBottom: -80 }}>
<View style={{ flexDirection: 'row', height: 80, alignItems: 'flex-end' }}>
{children}
</View>
</View>
)
}
export const LoginTextInput = ({
label,
icon,
isPassword = false,
hidePassword = true,
setHidePassword = (boolean) => {},
...props
}) => {
return (
<View>
<LeftIcon>
<Ionicons name={icon} size={30} color='red' />
</LeftIcon>
<StyledInputLabel>{label}</StyledInputLabel>
<StyledTextInput {...props} />
{isPassword ? (
<RightIcon onPress={() => {setHidePassword(!hidePassword)}}>
<Ionicons name={hidePassword ? 'eye-off-outline' : 'eye-outline'} size={30} color="gray" />
</RightIcon>
) : null}
</View>
)
}
export const LoginDropdownInput = ({
label,
icon,
selectedValue,
onValueChange,
items,
}) => {
return (
<View>
<StyledInputLabel>{label}</StyledInputLabel>
<Picker
selectedValue={selectedValue}
onValueChange={onValueChange}
>
{items.map((provider) => {
return <Picker.Item label={provider.label} value={provider.value} key={provider.value} />
})}
</Picker>
</View>
)
}

View file

@ -19,7 +19,7 @@ import {
ExtraText,
TextLinkContent,
LoginTextInput
} from './helpers.jsx';
} from './generalHelpers.jsx';
export default function TabLayout() {
const [hidePassword, setHidePassword] = useState(true);

View file

@ -6,6 +6,7 @@ import { useFormik } from 'formik';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
import {
providerMenu,
PageHeader,
StyledContainer,
InnerContainer,
@ -17,21 +18,16 @@ import {
ButtonText,
MessageBox,
LoginTextInput,
LoginDropdownInput
} from './helpers.jsx';
const providers = [
{label: 'Verizon', value: 'verizon'},
{label: 'AT&T', value: 'att'},
{label: 'T-Mobile', value: 'tmobile'}
]
RegisterDropdownInput,
} from './generalHelpers.jsx';
export default function Register() {
const [providerDropdownOpen, setProviderDropdownOpen] = useState(false);
const [hidePassword, setHidePassword] = useState(true);
const [registerButtonDisabled, setRegisterButtonDisabled] = useState(true);
const formik = useFormik({
initialValues: {
firstName: '',
@ -112,11 +108,13 @@ export default function Register() {
keyboardType="number-pad"
maxLength={14}
/>
<LoginDropdownInput
<RegisterDropdownInput
label="Cellular Provider"
isOpen={providerDropdownOpen}
setOpen={setProviderDropdownOpen}
selectedValue={formik.values.provider}
onValueChange={formik.handleChange('provider')}
items={providers}
menu={providerMenu}
/>
<LoginTextInput
label="Email Address"

20
components/Container.tsx Normal file
View file

@ -0,0 +1,20 @@
import { View, ViewStyle } from "react-native";
interface ContainerProps {
children?: React.ReactNode;
backgroundColor?: string;
style?: ViewStyle;
}
export const Container = ({
children,
backgroundColor,
style,
}: ContainerProps) => {
return (
<View style={[
{ flex: 1 },
{ backgroundColor },
style
]}>{children}</View>
)
};

24
components/Row.tsx Normal file
View file

@ -0,0 +1,24 @@
import { View, ViewStyle } from "react-native";
import { ReactNode } from "react";
interface RowProps {
children?: ReactNode | ReactNode[];
backgroundColor?: string;
style?: ViewStyle | ViewStyle[];
}
export const Row = ({
children,
backgroundColor,
style,
}: RowProps) => {
return (
<View style={[
{ flexDirection: 'row', alignItems: 'center' },
{ backgroundColor },
style
]}>
{children}
</View>
)
};

10
package-lock.json generated
View file

@ -9,7 +9,6 @@
"version": "1.0.2",
"dependencies": {
"@expo/vector-icons": "^14.0.2",
"@react-native-picker/picker": "2.7.5",
"@react-navigation/native": "^6.0.2",
"expo": "~51.0.24",
"expo-constants": "~16.0.2",
@ -5916,15 +5915,6 @@
"node": ">=8"
}
},
"node_modules/@react-native-picker/picker": {
"version": "2.7.5",
"resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.7.5.tgz",
"integrity": "sha512-vhMaOLkXSUb+YKVbukMJToU4g+89VMhBG2U9+cLYF8X8HtFRidrHjohGqT8/OyesDuKIXeLIP+UFYI9Q9CRA9Q==",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/@react-native/assets-registry": {
"version": "0.74.85",
"resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.74.85.tgz",

View file

@ -16,7 +16,6 @@
},
"dependencies": {
"@expo/vector-icons": "^14.0.2",
"@react-native-picker/picker": "2.7.5",
"@react-navigation/native": "^6.0.2",
"expo": "~51.0.24",
"expo-constants": "~16.0.2",