diff options
Diffstat (limited to 'src/view/com')
-rw-r--r-- | src/view/com/auth/create/Step2.tsx | 62 | ||||
-rw-r--r-- | src/view/com/util/forms/Button.tsx | 11 | ||||
-rw-r--r-- | src/view/com/util/forms/DateInput.tsx | 96 | ||||
-rw-r--r-- | src/view/com/util/forms/DateInput.web.tsx | 92 |
4 files changed, 215 insertions, 46 deletions
diff --git a/src/view/com/auth/create/Step2.tsx b/src/view/com/auth/create/Step2.tsx index eceee50d3..1e014f18e 100644 --- a/src/view/com/auth/create/Step2.tsx +++ b/src/view/com/auth/create/Step2.tsx @@ -1,14 +1,9 @@ import React from 'react' -import { - StyleSheet, - TouchableOpacity, - TouchableWithoutFeedback, - View, -} from 'react-native' +import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native' import {observer} from 'mobx-react-lite' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {CreateAccountModel} from 'state/models/ui/create-account' import {Text} from 'view/com/util/text/Text' +import {DateInput} from 'view/com/util/forms/DateInput' import {StepHeader} from './StepHeader' import {s} from 'lib/styles' import {usePalette} from 'lib/hooks/usePalette' @@ -104,26 +99,20 @@ export const Step2 = observer(({model}: {model: CreateAccountModel}) => { <Text type="md-medium" style={[pal.text, s.mb2]} - nativeID="legalCheck"> - Legal check + nativeID="birthDate"> + Your birth date </Text> - <TouchableOpacity - testID="is13Input" - style={[styles.toggleBtn, pal.border]} - onPress={() => model.setIs13(!model.is13)} - accessibilityRole="checkbox" - accessibilityLabel="Verify age" - accessibilityHint="Verifies that I am at least 13 years of age" - accessibilityLabelledBy="legalCheck"> - <View style={[pal.borderDark, styles.checkbox]}> - {model.is13 && ( - <FontAwesomeIcon icon="check" style={s.blue3} size={16} /> - )} - </View> - <Text type="md" style={[pal.text, styles.toggleBtnLabel]}> - I am 13 years old or older - </Text> - </TouchableOpacity> + <DateInput + testID="birthdayInput" + value={model.birthDate} + onChange={model.setBirthDate} + buttonType="default-light" + buttonStyle={[pal.border, styles.dateInputButton]} + buttonLabelType="lg" + accessibilityLabel="Birthday" + accessibilityHint="Enter your birth date" + accessibilityLabelledBy="birthDate" + /> </View> {model.serviceDescription && ( @@ -144,26 +133,9 @@ const styles = StyleSheet.create({ marginTop: 10, }, - toggleBtn: { - flexDirection: 'row', - flex: 1, - alignItems: 'center', + dateInputButton: { borderWidth: 1, - paddingHorizontal: 10, - paddingVertical: 10, borderRadius: 6, - }, - toggleBtnLabel: { - flex: 1, - paddingHorizontal: 10, - }, - - checkbox: { - borderWidth: 1, - borderRadius: 2, - width: 24, - height: 24, - alignItems: 'center', - justifyContent: 'center', + paddingVertical: 14, }, }) diff --git a/src/view/com/util/forms/Button.tsx b/src/view/com/util/forms/Button.tsx index 3b5b00284..1c9b1cf51 100644 --- a/src/view/com/util/forms/Button.tsx +++ b/src/view/com/util/forms/Button.tsx @@ -35,6 +35,9 @@ export function Button({ onPress, children, testID, + accessibilityLabel, + accessibilityHint, + accessibilityLabelledBy, }: React.PropsWithChildren<{ type?: ButtonType label?: string @@ -42,6 +45,9 @@ export function Button({ labelStyle?: StyleProp<TextStyle> onPress?: () => void testID?: string + accessibilityLabel?: string + accessibilityHint?: string + accessibilityLabelledBy?: string }>) { const theme = useTheme() const typeOuterStyle = choose<ViewStyle, Record<ButtonType, ViewStyle>>( @@ -133,7 +139,10 @@ export function Button({ style={[typeOuterStyle, styles.outer, style]} onPress={onPressWrapped} testID={testID} - accessibilityRole="button"> + accessibilityRole="button" + accessibilityLabel={accessibilityLabel} + accessibilityHint={accessibilityHint} + accessibilityLabelledBy={accessibilityLabelledBy}> {label ? ( <Text type="button" style={[typeLabelStyle, labelStyle]}> {label} diff --git a/src/view/com/util/forms/DateInput.tsx b/src/view/com/util/forms/DateInput.tsx new file mode 100644 index 000000000..4aa5cb610 --- /dev/null +++ b/src/view/com/util/forms/DateInput.tsx @@ -0,0 +1,96 @@ +import React, {useState, useCallback} from 'react' +import {StyleProp, StyleSheet, TextStyle, View, ViewStyle} from 'react-native' +import DateTimePicker, { + DateTimePickerEvent, +} from '@react-native-community/datetimepicker' +import { + FontAwesomeIcon, + FontAwesomeIconStyle, +} from '@fortawesome/react-native-fontawesome' +import {isIOS, isAndroid} from 'platform/detection' +import {Button, ButtonType} from './Button' +import {Text} from '../text/Text' +import {TypographyVariant} from 'lib/ThemeContext' +import {useTheme} from 'lib/ThemeContext' +import {usePalette} from 'lib/hooks/usePalette' + +interface Props { + testID?: string + value: Date + onChange: (date: Date) => void + buttonType?: ButtonType + buttonStyle?: StyleProp<ViewStyle> + buttonLabelType?: TypographyVariant + buttonLabelStyle?: StyleProp<TextStyle> + accessibilityLabel: string + accessibilityHint: string + accessibilityLabelledBy?: string +} + +export function DateInput(props: Props) { + const [show, setShow] = useState(false) + const theme = useTheme() + const pal = usePalette('default') + + const onChangeInternal = useCallback( + (event: DateTimePickerEvent, date: Date | undefined) => { + setShow(false) + if (date) { + props.onChange(date) + } + }, + [setShow, props], + ) + + const onPress = useCallback(() => { + setShow(true) + }, [setShow]) + + return ( + <View> + {isAndroid && ( + <Button + type={props.buttonType} + style={props.buttonStyle} + onPress={onPress} + accessibilityLabel={props.accessibilityLabel} + accessibilityHint={props.accessibilityHint} + accessibilityLabelledBy={props.accessibilityLabelledBy}> + <View style={styles.button}> + <FontAwesomeIcon + icon={['far', 'calendar']} + style={pal.textLight as FontAwesomeIconStyle} + /> + <Text + type={props.buttonLabelType} + style={[pal.text, props.buttonLabelStyle]}> + {props.value.toLocaleDateString()} + </Text> + </View> + </Button> + )} + {(isIOS || show) && ( + <DateTimePicker + testID={props.testID ? `${props.testID}-datepicker` : undefined} + mode="date" + display="spinner" + // @ts-ignore applies in iOS only -prf + themeVariant={theme.colorScheme} + value={props.value} + onChange={onChangeInternal} + accessibilityLabel={props.accessibilityLabel} + accessibilityHint={props.accessibilityHint} + accessibilityLabelledBy={props.accessibilityLabelledBy} + /> + )} + </View> + ) +} + +const styles = StyleSheet.create({ + button: { + flexDirection: 'row', + alignItems: 'center', + gap: 10, + }, +}) diff --git a/src/view/com/util/forms/DateInput.web.tsx b/src/view/com/util/forms/DateInput.web.tsx new file mode 100644 index 000000000..89dff5510 --- /dev/null +++ b/src/view/com/util/forms/DateInput.web.tsx @@ -0,0 +1,92 @@ +import React, {useState, useCallback} from 'react' +import { + StyleProp, + StyleSheet, + TextInput as RNTextInput, + TextStyle, + View, + ViewStyle, +} from 'react-native' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' +import {useTheme} from 'lib/ThemeContext' +import {usePalette} from 'lib/hooks/usePalette' + +interface Props { + testID?: string + value: Date + onChange: (date: Date) => void + buttonType?: string + buttonStyle?: StyleProp<ViewStyle> + buttonLabelType?: string + buttonLabelStyle?: StyleProp<TextStyle> + accessibilityLabel: string + accessibilityHint: string + accessibilityLabelledBy?: string +} + +export function DateInput(props: Props) { + const theme = useTheme() + const pal = usePalette('default') + const palError = usePalette('error') + const [value, setValue] = useState(props.value.toLocaleDateString()) + const [isValid, setIsValid] = useState(true) + + const onChangeInternal = useCallback( + (v: string) => { + setValue(v) + const d = new Date(v) + if (!isNaN(Number(d))) { + setIsValid(true) + props.onChange(d) + } else { + setIsValid(false) + } + }, + [setValue, setIsValid, props], + ) + + return ( + <View style={[isValid ? pal.border : palError.border, styles.container]}> + <FontAwesomeIcon + icon={['far', 'calendar']} + style={[pal.textLight, styles.icon]} + /> + <RNTextInput + testID={props.testID} + style={[pal.text, styles.textInput]} + placeholderTextColor={pal.colors.textLight} + autoCapitalize="none" + autoCorrect={false} + keyboardAppearance={theme.colorScheme} + onChangeText={v => onChangeInternal(v)} + value={value} + accessibilityLabel={props.accessibilityLabel} + accessibilityHint={props.accessibilityHint} + accessibilityLabelledBy={props.accessibilityLabelledBy} + /> + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + borderWidth: 1, + borderRadius: 6, + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: 4, + }, + icon: { + marginLeft: 10, + }, + textInput: { + flex: 1, + width: '100%', + paddingVertical: 10, + paddingHorizontal: 10, + fontSize: 17, + letterSpacing: 0.25, + fontWeight: '400', + borderRadius: 10, + }, +}) |