react-native-elements#Button TypeScript Examples
The following examples show how to use
react-native-elements#Button.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Hotel.tsx From wuhan2020-frontend-react-native-app with MIT License | 6 votes |
function Hotel({ item }: PropTypes) {
const [visible, setVisible] = useState(false);
const title = `${item.name} (${item.city})`;
return (
<Card title={title}>
<View style={{ paddingHorizontal: 30, paddingTop: 10 }}>
<View style={styles.subtitleContainer}>
<Text style={[styles.subtitle, { fontSize: 14 }]}>{item.city}</Text>
<Text style={styles.subtitle}>
发布于{moment(item.date).fromNow()}
</Text>
</View>
<ContactList data={item.contacts} />
<Address {...item} />
<Button
type="outline"
title="查看详情"
onPress={() => setVisible(true)}
/>
<WebViewModal
uri={item.url}
title={`${item.name}`}
visible={visible}
onClose={() => setVisible(false)}
/>
</View>
</Card>
);
}
Example #2
Source File: APIClientUploadScreen.tsx From react-native-network-client with Apache License 2.0 | 6 votes |
UploadButton = (props: UploadButtonProps) => {
const hasEndpoint = Boolean(props.endpoint);
const hasFileUri = Boolean(props.fileUri);
if (!hasEndpoint || !hasFileUri) {
return null;
}
let title;
let onPress;
if (props.status === undefined) {
title = "Upload File";
onPress = () => props.upload();
} else if (props.status === UploadStatus.UPLOADING) {
title = "Cancel Upload";
onPress = () => props.cancelUpload();
} else if (props.status === UploadStatus.FAILED) {
title = "Reset";
onPress = () => props.resetState();
}
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1, padding: 10 }}>
<Button title={title} onPress={onPress} />
</View>
</View>
);
}
Example #3
Source File: CartFooter.tsx From magento_react_native_graphql with MIT License | 6 votes |
CartFooter = ({
grandTotal,
handlePlaceOrder,
}: Props): React.ReactElement => {
const { theme } = useContext(ThemeContext);
const containerStyle = useMemo(
() => ({
backgroundColor: theme.colors?.white,
borderColor: theme.colors?.divider,
}),
[theme],
);
return (
<View style={[styles.container, containerStyle]}>
{grandTotal && (
<Text h4>{`${translate('common.total')} : ${formatPrice(
grandTotal,
)}`}</Text>
)}
<Button
containerStyle={styles.placeOrder}
title={translate('cartScreen.placeOrderButton')}
onPress={handlePlaceOrder}
/>
</View>
);
}
Example #4
Source File: APIClientDownloadScreen.tsx From react-native-network-client with Apache License 2.0 | 6 votes |
DownloadButton = (props: DownloadButtonProps) => {
const hasEndpoint = Boolean(props.endpoint);
const hasFilePath = Boolean(props.filePath);
if (!hasEndpoint || !hasFilePath) {
return null;
}
let title;
let onPress;
if (props.status === undefined) {
title = "Download File";
onPress = () => props.download();
} else if (props.status === DownloadStatus.DOWNLOADING) {
title = "Cancel Download";
onPress = () => props.cancelDownload();
} else if (props.status === DownloadStatus.FAILED) {
title = "Reset";
onPress = () => props.resetState();
}
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1, padding: 10 }}>
<Button title={title} onPress={onPress} />
</View>
</View>
);
}
Example #5
Source File: ProfileScreen.tsx From magento_react_native_graphql with MIT License | 6 votes |
ProfileScreen = ({ navigation }: Props): React.ReactElement => {
const { getCustomer, data, loading, error } = useCustomer();
const { logout } = useLogout();
useEffect(() => {
getCustomer();
}, []);
const handleLogout = () => {
logout();
navigation.jumpTo(Routes.NAVIGATION_TO_HOME_SCREEN);
};
if (error?.message) {
return (
<View>
<Text>{error.message}</Text>
<Button title={translate('common.logout')} onPress={handleLogout} />
</View>
);
}
return (
<GenericTemplate loading={loading}>
<Text>
{translate('profileScreen.greeting', {
name: data?.customer?.firstName ?? translate('common.user'),
})}
</Text>
<Button title={translate('common.logout')} onPress={handleLogout} />
</GenericTemplate>
);
}
Example #6
Source File: Consultation.tsx From wuhan2020-frontend-react-native-app with MIT License | 6 votes |
function Consultation({ item }: PropTypes) {
const [visible, setVisible] = useState(false);
return (
<Card title={`${item.name}`}>
<View style={styles.subtitleContainer}>
<Text style={styles.subtitle}>发布于{moment(item.date).fromNow()}</Text>
</View>
<ContactList data={item.contacts} />
<View>
<H3 title="内容" />
<Text style={{ marginVertical: 5 }}>{item.remark}</Text>
</View>
<View style={{ paddingHorizontal: 30, paddingTop: 10 }}>
<Button
type="outline"
title="查看详情"
onPress={() => setVisible(true)}
/>
<WebViewModal
uri={item.url}
title={`${item.name}`}
visible={visible}
onClose={() => setVisible(false)}
/>
</View>
</Card>
);
}
Example #7
Source File: AlphaWarning.tsx From ito-app with GNU General Public License v3.0 | 6 votes |
AlphaWarning: React.FC<AlphaWarningProps> = ({navigation}) => {
const {t} = useTranslation();
return (
<View style={styles.container}>
<View style={styles.logoWrapper}>
<Text style={styles.logo}>ito</Text>
<Text style={styles.subtitle}>track infections, not people!</Text>
<AlphaNotice
rootStyle={styles.alphaNoticeRoot}
textStyle={styles.alphaNoticeText}
/>
</View>
<View>
<Text style={styles.generalText}>{t('alphaWarning.demoPurpose')}</Text>
<Text style={styles.generalText}>
{t('alphaWarning.notFullyImplemented')}
</Text>
<Text style={styles.generalText}>{t('alphaWarning.review')}</Text>
</View>
<Text
style={[styles.generalText, styles.githubLink]}
onPress={(): Promise<void> =>
Linking.openURL('https://github.com/ito-org/ito-app/issues')
}>
https://github.com/ito-org/ito-app/issues
</Text>
<View style={styles.bottomButtonContainer}>
<Button
title={t('alphaWarning.start')}
onPress={(): void => navigation.navigate('Onboarding')}
titleStyle={styles.buttonHowTitle}
buttonStyle={styles.buttonHow}
/>
</View>
</View>
);
}
Example #8
Source File: Cart.component.tsx From react-native-woocommerce with MIT License | 6 votes |
Browse = (props: Props): JSX.Element => {
const {
products,
resetCart,
total,
handleCheckoutPress
} = props;
return (
<>
<View style={styles.cartOverview}>
<View style={styles.leftCartOverview}>
<Icon
reverse
name="trash-alt"
type="font-awesome-5"
onPress={(): void => resetCart()}
/>
<Text style={styles.textTotal}>{`Total:\n${toAmount(total)}`}</Text>
</View>
<Button
title="Checkout"
onPress={(): void => handleCheckoutPress()}
/>
</View>
<FlatList
contentContainerStyle={styles.container}
data={products}
renderItem={_renderProduct(props)}
keyExtractor={(item): string => `${item.id}`}
numColumns={2}
/>
</>
);
}
Example #9
Source File: Logistic.tsx From wuhan2020-frontend-react-native-app with MIT License | 6 votes |
function Logistic({ item }: PropTypes) {
const [visible, setVisible] = useState(false);
const title = `${item.name} - (${item.from} - ${item.dest})`;
return (
<Card title={title}>
<View style={styles.subtitleContainer}>
<Text style={styles.subtitle}>发布于{moment(item.date).fromNow()}</Text>
</View>
<ContactList data={item.contacts} />
<Remark remark={item.remark} />
<View>
<H3 title="可否载人" />
<Text style={{ marginVertical: 5 }}>
{item.allowPersonal ? '是' : '否'}
</Text>
</View>
<View style={{ paddingHorizontal: 30, paddingTop: 10 }}>
<Button
type="outline"
title="查看详情"
onPress={() => setVisible(true)}
/>
<WebViewModal
uri={item.url}
title={title}
visible={visible}
onClose={() => setVisible(false)}
/>
</View>
</Card>
);
}
Example #10
Source File: DetailScreen.tsx From react-native-sdk with MIT License | 6 votes |
render() {
const coffee = this.props.route.params.coffee
return (
<View style={styles.container}>
<Image resizeMode="contain" style={styles.image} source={coffee.icon} />
<Text style={styles.text}>{coffee.name}. {coffee.subtitle}</Text>
<Button buttonStyle={styles.button} titleStyle={styles.buttonText} title="Buy Now" onPress={this.buyTapped} />
</View>
)
}
Example #11
Source File: draft-item.tsx From bext with MIT License | 6 votes |
DraftItem: FC<{
draft: Draft;
onDelete: () => void;
onPress: () => void;
}> = ({ draft, onDelete, onPress }) => {
const updateAt = useMemo(
() => dayjs(draft.update_at).format('LLL'),
[draft.update_at],
);
return (
<ListItem.Swipeable
bottomDivider
onPress={onPress}
rightContent={
<Button
title="删除"
buttonStyle={styles.deleteButton}
icon={{ name: 'delete', color: 'white' }}
onPress={onDelete}
/>
}
>
<ListItem.Content>
<ListItem.Title>{draft.name}</ListItem.Title>
<ListItem.Subtitle>更新于 {updateAt}</ListItem.Subtitle>
</ListItem.Content>
<ListItem.Chevron />
</ListItem.Swipeable>
);
}
Example #12
Source File: ProductItem.component.tsx From RNWCShop with GNU General Public License v3.0 | 6 votes |
_renderCartDetail = ({ product, quantity = 0, subQuantity = noop, addQuantity = noop, removeFromCart = noop }: Props): JSX.Element => ( <> <View style={styles.actionView}> <Icon name="minus" type="font-awesome-5" onPress={(): void => subQuantity(product.id)} /> <Text>Quantity: {quantity}</Text> <Icon name="plus" type="font-awesome-5" onPress={(): void => addQuantity(product.id)} /> </View> <Button title="Remove" onPress={(): void => removeFromCart(product.id)} /> </> )
Example #13
Source File: ProductItem.component.tsx From react-native-woocommerce with MIT License | 6 votes |
_renderCartDetail = ({ product, quantity = 0, subQuantity, addQuantity, removeFromCart }: Props): JSX.Element => ( <> <View style={styles.actionView}> <Icon name='minus' type='font-awesome-5' onPress={(): void => subQuantity(product.id)} /> <Text>Quantity: {quantity}</Text> <Icon name='plus' type='font-awesome-5' onPress={(): void => addQuantity(product.id)} /> </View> <Button title="Remove" onPress={(): void => removeFromCart(product.id)} /> </> )
Example #14
Source File: AgreementPolicy.tsx From SQUID with MIT License | 5 votes |
AgreementPolicy = () => {
const navigation = useNavigation()
return (
<SafeAreaView style={styles.container}>
<StatusBar backgroundColor={'white'} barStyle="light-content" />
<FormHeader>
<View style={styles.header}>
<Text style={styles.title}>{I18n.t('term_and_conditions')}</Text>
<Text style={styles.subtitle}>{I18n.t('before_usage')}</Text>
<Text style={styles.subtitle}>{I18n.t('please_accept_terms')}</Text>
</View>
</FormHeader>
<View style={styles.content}>
<ScrollView
contentContainerStyle={{
flexGrow: 1,
paddingVertical: 16,
}}
>
<View style={{ paddingHorizontal: 24 }}>
<Text style={styles.agreement}>{getAgreementText()} </Text>
</View>
</ScrollView>
</View>
{/* <CheckBox
title="ฉันยอมรับ{I18n.t('term_and_conditions')}"
containerStyle={{
backgroundColor: 'transparent',
borderWidth: 0,
marginBottom: 16,
}}
checked={agree}
onPress={() => setAgree(!agree)}
checkedColor={COLORS.BLUE}
textStyle={{ color: COLORS.BLACK_1, fontSize: FONT_SIZES[600], fontWeight:'normal'}}
fontFamily={FONT_BOLD}
/> */}
<View style={styles.footer}>
<PrimaryButton
// disabled={!agree}
title={I18n.t('accept')}
style={{ width: '100%' }}
containerStyle={{ width: '100%', marginTop: normalize(16) }}
onPress={() => {
applicationState.setData('skipRegistration', true)
navigation.navigate('Onboarding')
}}
/>
<Button
type="outline"
title={I18n.t('deny')}
style={{ width: '100%' }}
titleStyle={{
fontFamily: FONT_MED,
fontSize: FONT_SIZES[600],
lineHeight: 30,
}}
containerStyle={{ width: '100%', marginTop: 8 }}
onPress={() => {
navigation.pop()
}}
/>
</View>
</SafeAreaView>
)
}
Example #15
Source File: Hospital.tsx From wuhan2020-frontend-react-native-app with MIT License | 5 votes |
function Hospital({ item }: PropTypes) {
const { supplies } = item;
const [visible, setVisible] = useState(false);
return (
<Card title={item.name}>
<View style={styles.subtitleContainer}>
<Text style={[styles.subtitle, { fontSize: 14 }]}>
{item.city} - {item.province || ''}
</Text>
<Text style={styles.subtitle}>{item.district}</Text>
</View>
<View style={styles.supplyContainer}>
<View>
{supplies.slice(0, 3).map(supply => (
<Supply item={supply} />
))}
{supplies.length - 3 > 0 ? (
<Text style={styles.supplyInfo}>
+{supplies.length - 3}项其他物资
</Text>
) : null}
</View>
</View>
<View style={{ paddingHorizontal: 30, paddingTop: 10 }}>
<Button
type="outline"
title="查看详情"
onPress={() => setVisible(true)}
/>
<Modal
animationType="fade"
presentationStyle="formSheet"
transparent={false}
onDismiss={() => {
setVisible(false);
}}
onRequestClose={() => {
setVisible(false);
}}
visible={visible}>
<View style={{ padding: 16, justifyContent: 'space-between' }}>
<View style={{ height: height - 150 }}>
<HospitalDetail item={item} />
</View>
<View>
<Button
title="关闭详情"
onPress={() => {
setVisible(false);
}}
/>
</View>
</View>
</Modal>
</View>
</Card>
);
}
Example #16
Source File: Camera.tsx From save-food with MIT License | 5 votes |
Camera = ({ navigation }: Props) => {
const cameraRef = useRef<any>()
const [loading, setLoading] = useState<boolean>(false)
const [buttonTitle, setButtonTitle] = useState<string>()
const takePhotoHandler = async () => {
setLoading(true)
const takePhoto = navigation.getParam('takePhoto', undefined)
if (cameraRef.current && takePhoto) {
await cameraRef.current.takePictureAsync({
onPictureSaved: ({ uri }: { uri: string }) => {
takePhoto(uri)
navigation.goBack()
},
})
}
}
useEffect(() => {
const buttonTitle = navigation.getParam('buttonTitle', undefined)
if (buttonTitle) {
setButtonTitle(buttonTitle)
} else {
navigation.goBack()
}
return () => {
setLoading(false)
}
}, [])
return (
<CameraComponent
style={styles.camera}
ratio='16:9'
type={CameraComponent.Constants.Type.back}
ref={cameraRef}
>
<Icon onPress={() => navigation.goBack()} variant='exitIcon' />
{loading && (
<View style={styles.loading}>
<Spinner bgColor='transparency' size={64} />
</View>
)}
<View style={[styles.takePhotoButtonWrapper, shadow]}>
<Button
disabled={loading}
onPress={takePhotoHandler}
buttonStyle={styles.takeFoodButton}
titleStyle={styles.takeFoodButtonTitle}
title={buttonTitle}
/>
</View>
</CameraComponent>
)
}
Example #17
Source File: RecommendationList.tsx From wuhan2020-frontend-react-native-app with MIT License | 5 votes |
function Entry(props: EntryPropsType) {
const [visible, setVisible] = useState(false);
const [loadingWebview, setLoading] = useState(true);
return (
<View>
<ListItem
onPress={() => setVisible(true)}
Component={TouchableOpacity}
title={<Text style={{ fontWeight: '800' }}>{props.title}</Text>}
subtitle={
<Text style={{ fontSize: 12, paddingTop: 3 }}>
修改时间:
{formatDate(props.modifyTime)} from {props.operator}
</Text>
}
leftAvatar={{ source: { uri: props.imgUrl } }}
rightIcon={{ name: 'unfold-more' }}
/>
<Modal
animationType="fade"
presentationStyle="pageSheet"
visible={visible}
onDismiss={() => {
setVisible(false);
}}
onRequestClose={() => {
setVisible(false);
}}>
<View style={{ padding: 16, justifyContent: 'space-between' }}>
{loadingWebview ? (
<ActivityIndicator size="large" color="red" />
) : null}
<View style={{ height: height - 150 }}>
<WebView
onLoad={() => setLoading(true)}
onLoadEnd={() => setLoading(false)}
source={{ uri: props.linkUrl }}
/>
</View>
<View>
<Button
buttonStyle={styles.button}
title="关闭预览"
onPress={() => {
setVisible(false);
}}
/>
</View>
</View>
</Modal>
</View>
);
}
Example #18
Source File: LoginScreen.tsx From magento_react_native_graphql with MIT License | 5 votes |
LoginScreen = ({ navigation }: Props): React.ReactElement => {
const {
values,
loading,
data,
error,
handleChange,
handleSubmit,
} = useLogin();
useEffect(() => {
if (data?.generateCustomerToken?.token) {
showMessage({
message: translate('common.success'),
description: translate('loginScreen.successMessage'),
type: 'success',
});
navigation.navigate(Routes.NAVIGATION_TO_HOME_SCREEN);
}
}, [data]);
useEffect(() => {
if (error) {
showMessage({
message: translate('common.error'),
description: error.message ?? translate('errors.genericError'),
type: 'danger',
});
}
}, [error]);
return (
<GenericTemplate style={styles.container}>
<Input
value={values.email}
editable={!loading}
leftIcon={{ name: 'email' }}
placeholder="[email protected]"
label={translate('common.email')}
onChangeText={handleChange('email')}
/>
<Input
secureTextEntry={values.secureTextEntry}
editable={!loading}
value={values.password}
leftIcon={{ name: 'lock' }}
rightIcon={{
name: values.secureTextEntry ? 'eye' : 'eye-off',
type: 'material-community',
onPress: handleChange('secureTextEntry').bind(
{},
!values.secureTextEntry,
),
}}
label={translate('common.password')}
onChangeText={handleChange('password')}
placeholder={translate('common.password')}
/>
<Button
loading={loading}
onPress={handleSubmit}
title={translate('common.login')}
containerStyle={styles.submitButton}
/>
<Button
type="clear"
disabled={loading}
title={translate('loginScreen.noAccount')}
onPress={() => navigation.navigate(Routes.NAVIGATION_TO_SIGNUP_SCREEN)}
/>
</GenericTemplate>
);
}
Example #19
Source File: Webview.tsx From wuhan2020-frontend-react-native-app with MIT License | 5 votes |
function WebViewModal({
uri,
title,
visible,
onClose,
}: {
uri: string;
title: string;
visible: boolean;
onClose: () => void;
}) {
const [loadingWebview, setLoading] = useState(true);
return (
<Modal
animationType="fade"
presentationStyle="pageSheet"
visible={visible}
onDismiss={onClose}
onRequestClose={onClose}>
<View style={{ padding: 16, justifyContent: 'space-between' }}>
<View style={{ height: height - 150 }}>
<H1 title={title} />
{loadingWebview ? (
<View style={{ paddingVertical: 20 }}>
<Loader />
</View>
) : null}
<WebView
onLoad={() => setLoading(true)}
onLoadEnd={() => setLoading(false)}
source={{ uri }}
/>
</View>
<View>
<Button
buttonStyle={styles.button}
title="关闭预览"
onPress={onClose}
/>
</View>
</View>
</Modal>
);
}
Example #20
Source File: MattermostClientUploadScreen.tsx From react-native-network-client with Apache License 2.0 | 5 votes |
UploadButton = (props: UploadButtonProps) => {
const hasChannelId = Boolean(props.channelId);
const hasSessionId = Boolean(props.sessionId);
const hasFileUri = Boolean(props.fileUri);
if (!hasChannelId || !hasFileUri) {
return null;
}
let title;
let onPress;
let error;
let reset;
if (!hasSessionId) {
title = "Create Upload Session";
onPress = () => props.createUploadSession();
} else if (props.status === undefined) {
title = "Upload File";
onPress = () => props.upload();
} else if (props.status === UploadStatus.UPLOADING) {
title = "Cancel Upload";
onPress = () => props.cancelUpload();
} else if (props.status === UploadStatus.FAILED) {
title = "Resume";
onPress = () => props.resumeUpload();
error = "Upload error";
reset = true;
} else if (props.status === UploadStatus.COMPLETED) {
title = "Post";
onPress = () => props.post();
} else if (props.status === UploadStatus.POST_FAILED) {
title = "Retry post";
onPress = () => props.post();
}
return (
<View style={{ flex: 1 }}>
{error && (
<Text
style={{
color: "red",
alignSelf: "center",
padding: 10,
}}
>
{error}
</Text>
)}
<View
style={{
flex: 1,
flexDirection: "row",
justifyContent: "space-evenly",
}}
>
<View style={{ flex: 1, paddingHorizontal: 10 }}>
<Button title={title} onPress={onPress} />
</View>
{reset && (
<View style={{ flex: 1, paddingHorizontal: 10 }}>
<Button title="Reset" onPress={props.resetState} />
</View>
)}
</View>
</View>
);
}
Example #21
Source File: Detail.component.tsx From RNWCShop with GNU General Public License v3.0 | 5 votes |
render(): JSX.Element {
const {
product,
imagesShown,
handleShowImages,
addToCart = () => {}
} = this.props;
const {
name,
images,
description,
price,
average_rating: rating
} = product;
return (
<ScrollView style={styles.wrapper}>
<Carousel
ref={this._setCarousel}
sliderWidth={screenWidth}
sliderHeight={screenWidth}
itemWidth={screenWidth - 60}
data={this._mapImages(images)}
renderItem={this._renderImageItem(handleShowImages)}
hasParallaxImages
/>
<View style={styles.detail}>
<Text style={styles.textTitle}>{name}</Text>
<Text style={styles.textPrice}>{toAmount(price)}</Text>
<HTML html={description} textSelectable />
<View style={styles.rating}>
<Text style={styles.textSubHeading}>Rating:</Text>
<Text style={styles.textRating}>{rating}</Text>
<Rating readonly imageSize={20} startingValue={Number(rating)} />
</View>
<Button
icon={{
name: 'cart-plus',
type: 'font-awesome-5',
color: 'white',
size: 16
}}
title="Add to cart"
onPress={(): void => addToCart(product)}
/>
</View>
<Modal visible={imagesShown} transparent>
{this._renderImages(images, handleShowImages)}
</Modal>
</ScrollView>
);
}
Example #22
Source File: ResponseErrorOverlay.tsx From react-native-network-client with Apache License 2.0 | 5 votes |
ResponseErrorOverlay = ({
error,
visible,
setVisible,
}: ResponseErrorOverlayProps) => {
const hide = () => setVisible(false);
return (
<Overlay
isVisible={visible}
onBackdropPress={hide}
overlayStyle={{ marginHorizontal: 20, marginVertical: 40 }}
testID="response_error_overlay"
>
<>
<Button title="Close" onPress={hide} />
<Text h2 style={{ alignSelf: "center" }}>
Error
</Text>
<Text h4>Code</Text>
<Text testID="response_error_overlay.error.code.text">
{error?.code}
</Text>
<Divider />
<Text h4>Message</Text>
<Text testID="response_error_overlay.error.message.text">
{error?.message}
</Text>
<Divider />
<Text h4>Domain</Text>
<Text testID="response_error_overlay.error.domain.text">
{error?.domain}
</Text>
<Divider />
<Text h4>User Info</Text>
<Text testID="response_error_overlay.error.user_info.text">
{JSON.stringify(error?.userInfo)}
</Text>
<Divider />
<Text h4>Native Stack</Text>
<ScrollView>
<Text testID="response_error_overlay.error.native_stack.text">
{JSON.stringify(
error?.nativeStackAndroid || error?.nativeStackIOS
)}
</Text>
</ScrollView>
</>
</Overlay>
);
}
Example #23
Source File: Food.tsx From save-food with MIT License | 4 votes |
Food = ({ navigation }: Props) => {
const { useSubscribe } = useSettingsContext()
const settings = useSubscribe((s) => s.settings)
const translations = useSubscribe((s) => ({ ...s.translations.Food, ...s.translations.common }))
const [savedData, setSavedData] = useState<WastedFood>(initialData)
const [templateData, setTemplateData] = useState<WastedFood>(initialData)
const [loading, setLoading] = useState(true)
const [saveFoodBeforeModalHide, setSaveFoodBeforeModalHide] = useState(false)
const [hasChanges, setHasChanges] = useState(false)
const [showModal, setShowModal] = useState(false)
const [modalType, setModalType] = useState<ModalType>('id')
const [modalContent, setModalContent] = useState<ReactNode>()
const [controls, setControls] = useState<InputsControl>({
name: {
label: translations.foodNameLabel,
required: true,
characterRestriction: 70,
},
quantity: {
label: translations.quantityLabel,
keyboardType: 'numeric',
required: true,
characterRestriction: 5,
number: true,
positiveNumber: true,
precision: 0,
},
price: {
label: translations.priceLabel,
keyboardType: 'numeric',
required: true,
characterRestriction: 7,
number: true,
positiveNumber: true,
precision: 2,
},
})
const correctPrice = !!(savedData.price && !controls.price.error)
const quantitySuffixes = [translations.grams, translations.milliliters]
const setFood = () => {
const savedData = {
id: navigation.getParam('id', undefined),
image: navigation.getParam('image', undefined),
name: navigation.getParam('name', ''),
quantity: navigation.getParam('quantity', 0),
price: navigation.getParam('price', 0),
paid: navigation.getParam('paid', 0),
productQuantity: navigation.getParam('productQuantity', 1),
quantitySuffixIndex: navigation.getParam('quantitySuffixIndex', 1),
percentage: navigation.getParam('percentage', 100),
selected: navigation.getParam('selected', 1),
}
setSavedData(savedData)
setTemplateData(savedData)
setLoading(false)
}
const QuantitySuffixButtons = () => {
const [value, setValue] = useState(savedData.quantitySuffixIndex)
return (
<ButtonGroup
onPress={(index) => {
setSavedData({
...savedData,
quantitySuffixIndex: index,
})
setValue(index)
}}
selectedIndex={value}
buttons={quantitySuffixes}
selectedButtonStyle={styles.selectedButtonStyle}
/>
)
}
const setContent = (type: ModalType) => {
if (type === 'discardChanges') {
setModalContent(
<Text style={styles.discardChanges}>{translations.discardChangesDescription}</Text>,
)
} else {
setModalContent(
<View style={styles.modalContentWrapper}>
<Input
inputConfig={controls[type]}
translations={translations}
value={templateData[type]}
changed={(value, control) => {
setTemplateData({
...templateData,
[type]: value,
})
setControls({
...controls,
[type]: control,
})
}}
/>
{type === 'quantity' && <QuantitySuffixButtons />}
</View>,
)
}
setShowModal(true)
setModalType(type)
}
const saveChange = () => {
if (modalType === 'discardChanges') {
return
}
if (checkValidation(controls[modalType], templateData[modalType] ?? '')) {
const preparedData = prepareData(
{ ...savedData, [modalType]: templateData[modalType] },
controls,
)
setTemplateData(preparedData)
setSavedData(preparedData)
setHasChanges(true)
setShowModal(false)
}
}
const changePercentageHandler = (percent: number) => {
setSavedData({ ...savedData, percentage: +percent.toFixed(0) })
setHasChanges(true)
}
const cancelChange = () => {
if (modalType === 'discardChanges') {
return
}
setTemplateData(savedData)
setShowModal(false)
}
const toggleModal = (type?: ModalType) => {
if (!showModal && type) {
setContent(type)
} else {
setShowModal(false)
}
}
const takePhoto = (uri: string) => {
setSavedData({
...savedData,
image: uri,
})
setHasChanges(true)
}
const toggleCamera = async () => {
const { status } = await Camera.requestPermissionsAsync()
if (status === 'granted') {
navigation.navigate('Camera', {
buttonTitle: translations.takePhoto,
takePhoto,
})
} else {
showErrorMessage('permissionError')
}
}
const showErrorMessage = (type: 'priceError' | 'permissionError') => {
if (type === 'priceError') {
const message: MessageOptions = {
message: translations.noPriceTitle,
description: translations.noPriceDescription,
type: 'warning',
icon: { icon: 'warning', position: 'left' },
duration: 2500,
}
showMessage(message)
}
if (type === 'permissionError') {
const message: MessageOptions = {
message: translations.permissionErrorTitle,
description: translations.permissionErrorCamera,
type: 'danger',
icon: { icon: 'danger', position: 'left' },
duration: 2500,
}
showMessage(message)
}
}
const exitHandler = () => {
if (hasChanges && correctPrice) {
setContent('discardChanges')
} else {
navigation.goBack()
}
}
const getModalButtons = (): ModalButtonType[] => {
if (modalType === 'discardChanges') {
return [
{
text: translations.yes,
onPress: () => {
setShowModal(false)
navigation.goBack()
},
},
{
text: translations.save,
onPress: () => {
setSaveFoodBeforeModalHide(true)
setShowModal(false)
},
},
{ text: translations.cancel, onPress: () => setShowModal(false) },
]
}
return [
{ text: translations.save, onPress: saveChange },
{ text: translations.cancel, onPress: cancelChange },
]
}
const checkErrorHandler = () => {
if (!correctPrice) {
showErrorMessage('priceError')
}
}
const saveFoodHandler = async () => {
await saveFood(savedData)
navigation.replace('List')
}
useEffect(() => {
setFood()
}, [])
if (loading) {
return <Spinner size={64} />
}
return (
<Background>
<Header
leftComponent={<Icon onPress={exitHandler} variant='backIcon' />}
centerComponent={
<Text style={styles.headerTitle}>
{savedData.id ? translations.editFood : translations.newFood}
</Text>
}
/>
<Modal
visible={showModal}
toggleModal={toggleModal}
title={translations[modalType]}
buttons={getModalButtons()}
onModalHide={async () => {
if (saveFoodBeforeModalHide) {
await saveFoodHandler()
}
}}
>
{modalContent}
</Modal>
<View style={styles.contentWrapper}>
<ScrollView>
<View style={styles.imageContainer}>
<TouchableOpacity onPress={toggleCamera}>
<View style={styles.imageWrapper}>
<Image style={styles.image} source={getImage(savedData.image)} />
<View style={styles.tapImage}>
<Text style={styles.tapImageText}>{translations.tapToChange}</Text>
</View>
</View>
</TouchableOpacity>
</View>
<View style={styles.infoWindowsContainer}>
<InfoWindow
color1={whiteColor}
color2={orangeGradient}
title={translations.name}
value={
!savedData.name || savedData.name === '' ? translations.noData : savedData.name
}
onPress={() => toggleModal('name')}
/>
<InfoWindow
color1={whiteColor}
color2={orangeGradient}
title={translations.quantity}
value={
savedData.quantity
? `${+savedData.quantity} ${getQuantitySuffix(savedData.quantitySuffixIndex)}`
: '0'
}
onPress={() => toggleModal('quantity')}
/>
<InfoWindow
color1={whiteColor}
color2={redGradient}
title={translations.price}
value={`${savedData.price ? +savedData.price : 0} ${settings.currency}`}
onPress={() => toggleModal('price')}
/>
<View style={styles.sliderContainer}>
<Text style={styles.percentInfo}>{translations.percentInfo}</Text>
<Slider
style={styles.slider}
thumbStyle={styles.sliderThumbStyle}
thumbTintColor={blackColor}
minimumTrackTintColor={darkColor}
maximumTrackTintColor={grayColor}
minimumValue={1}
maximumValue={100}
value={savedData.percentage}
onValueChange={(value: number) => changePercentageHandler(value)}
/>
<Text style={styles.percent}>{savedData.percentage}%</Text>
</View>
</View>
<View style={styles.saveButtonContainer}>
<TouchableOpacity onPress={checkErrorHandler}>
<Button
buttonStyle={styles.saveButton}
titleStyle={styles.saveButtonTitle}
disabled={!correctPrice}
type='outline'
title={translations.save}
onPress={saveFoodHandler}
/>
</TouchableOpacity>
</View>
</ScrollView>
</View>
</Background>
)
}
Example #24
Source File: QuestionaireSummary.tsx From SQUID with MIT License | 4 votes |
QuestionaireSummary = ({ navigation }) => {
const resetTo = useResetTo()
const inset = useSafeArea()
const { qrData, qrState, error, refreshQR } = useSelfQR()
// useEffect(() => {
// resetTo({ routeName: 'MainApp' })
// }, [])
return (
<Container>
<StatusBar backgroundColor="#00A0D7" barStyle="light-content" />
<FormHeader whiteLogo style={{ paddingTop: inset.top }} />
{qrState === QR_STATE.LOADING ? (
<ActivityIndicator />
) : (
<Content style={{ marginBottom: inset.bottom }}>
<Image
source={require('./assets/smile-doctor.png')}
style={{
width: Math.floor(Dimensions.get('window').width * 0.5),
height: Math.floor(
(1578 / 1370) * Dimensions.get('window').width * 0.5,
),
}}
resizeMode="cover"
/>
<Card>
<Text
style={{
fontSize: isSmallDevice? FONT_SIZES[800]:FONT_SIZES[900],
fontFamily: FONT_BOLD,
color: qrData.getStatusColor(),
}}
>
{qrData.getLabel()}
</Text>
<Text
style={{
fontSize: FONT_SIZES[600],
fontFamily: FONT_FAMILY,
color: 'black',
}}
>
{I18n.t('doc_will_give_u_qr')}
</Text>
<Text
style={{
fontSize: FONT_SIZES[600],
fontFamily: FONT_FAMILY,
color: 'black',
}}
>
{I18n.t('for_risk_assessment')}
</Text>
<Text
style={{
fontSize: FONT_SIZES[600],
marginTop: 8,
marginBottom: 4,
fontFamily: FONT_FAMILY,
color: '#576675',
}}
>
{I18n.t('risk_level')}
</Text>
<RiskLevel level={qrData.getLevel()} />
<View
style={{
marginTop: 4,
alignSelf: 'stretch',
}}
>
<PrimaryButton
title={I18n.t('receive_qr_code')}
style={{
width: '100%',
}}
containerStyle={{
width: '100%',
}}
onPress={async () => {
resetTo({ routeName: 'MainApp' })
}}
/>
<Button
title={I18n.t('do_questionaire_again')}
style={{
width: '100%',
}}
type="clear"
titleStyle={{
fontFamily: FONT_FAMILY,
fontSize: FONT_SIZES[600]
}}
containerStyle={{
marginTop: 4,
width: '100%',
}}
onPress={async () => {
resetTo({ routeName: 'Questionaire' })
}}
/>
</View>
</Card>
</Content>
)}
</Container>
)
}
Example #25
Source File: dev.tsx From bext with MIT License | 4 votes |
DevScreen: FC = () => {
const [loading, setLoading] = useState(true);
const { params } = useRoute<any>();
const { id, modify } = params || {};
const { data: draft, mutate } = useRequest(
async () => {
try {
return await getDraft(id);
} catch (error) {}
},
{
ready: !!id,
},
);
useUpdateEffect(() => {
if (draft?.id) {
updateUrl(draft.id, draft.url || '');
}
}, [draft?.url, draft?.id]);
const navigation = useNavigation();
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (loading ? <Text>加载中...</Text> : null),
...(draft?.name ? { title: draft.name } : null),
});
}, [navigation, loading, draft?.name]);
const [modalVisible, setModalVisible] = useState(false);
const { script } = useDebug();
const webView = useRef<WebView>(null);
const onMessage = (msg: string = '{}') => {
try {
const data = JSON.parse(msg);
switch (data.type) {
case 'save':
updateJson(id, JSON.stringify(data.payload));
break;
case 'ready':
webView.current?.injectJavaScript(`
if (window.injectDraft) {
window.injectDraft(decodeURIComponent("${encodeURIComponent(
draft?.json || '{}',
)}"));
}
true;
`);
break;
case 'debug':
setModalVisible(true);
script.current = data.payload;
break;
default:
break;
}
} catch (error) {}
};
const navigateToDebug = () => {
navigation.navigate(
'debug' as never,
{
url: draft?.url,
} as never,
);
setModalVisible(false);
};
return (
<>
<Overlay
transparent
isVisible={modalVisible}
onBackdropPress={() => setModalVisible(false)}
overlayStyle={styles.overlay}
>
<Input
label="输入窗口链接"
value={draft?.url}
onChangeText={(url) => mutate((old) => ({ ...old, url } as any))}
/>
<Button title="确定" disabled={!draft?.url} onPress={navigateToDebug} />
</Overlay>
<WebView
ref={webView}
originWhitelist={['*']}
source={{
uri: `${BEXT_ORIGIN}${
modify
? '/meta?from=dev&devPath=%2Fdev%2Fscript-m'
: '/dev/script-m'
}`,
}}
onLoad={() => setLoading(false)}
onMessage={(e) => onMessage(e.nativeEvent.data)}
/>
</>
);
}
Example #26
Source File: Home.tsx From wuhan2020-frontend-react-native-app with MIT License | 4 votes |
function Map() {
const { data, refresh, timeout } = useContext(DataContext);
const [selectedIndex, setIndex] = useState(0);
const filter = filterList[selectedIndex];
const [refreshing, setRefreshing] = useState(false);
let mapData = data || [];
const total = {
confirmedCount: 0,
curedCount: 0,
deadCount: 0,
};
const webviewRef = useRef(null);
useEffect(function() {
if (webviewRef.current) {
webviewRef.current.setOption({
title: {
text: `疫情地图${titleMap[filter]}`,
},
tooltip: {
trigger: 'item',
formatter: '{b}',
},
visualMap: {
pieces: piecesMap[filter],
showLabel: true,
realtime: true,
inRange: {
color: ['yellow', 'red'],
},
},
series: [
{
name: '中国',
type: 'map',
map: 'china',
selectedMode: 'single', //multiple多选
itemStyle: {
normal: {
label: {
show: false,
textStyle: {
color: '#231816',
},
},
areaStyle: { color: '#B1D0EC' },
color: '#B1D0EC',
borderColor: '#bbb',
},
emphasis: {
label: {
show: false,
textStyle: {
color: '#fa4f04',
},
},
},
},
data: mapData,
},
],
});
}
});
const onRefresh = useCallback(() => {
setRefreshing(true);
refresh();
wait(2000).then(() => setRefreshing(false));
}, [refreshing, refresh]);
if (data) {
let formatted = [];
data.getAreaStat.forEach(entry => {
total.confirmedCount = total.confirmedCount + entry.confirmedCount;
total.curedCount = total.curedCount + entry.curedCount;
total.deadCount = total.deadCount + entry.deadCount;
formatted = formatted.concat([
{
name: entry.provinceShortName,
value: entry[filter],
},
]);
});
mapData = formatted;
}
const option = {
title: {
text: `疫情地图${titleMap[filter]}`,
},
tooltip: {
trigger: 'item',
formatter: '{b}',
},
visualMap: {
pieces: piecesMap[filter],
showLabel: true,
realtime: true,
inRange: {
color: ['yellow', 'red'],
},
},
series: [
{
name: '中国',
type: 'map',
map: 'china',
selectedMode: 'single', //multiple多选
itemStyle: {
normal: {
label: {
show: false,
textStyle: {
color: '#231816',
},
},
areaStyle: { color: '#B1D0EC' },
color: '#B1D0EC',
borderColor: '#bbb',
},
emphasis: {
label: {
show: false,
textStyle: {
color: '#fa4f04',
},
},
},
},
data: mapData,
},
],
};
if (timeout) {
return (
<SafeAreaView style={{ flex: 1 }}>
<View
style={{ justifyContent: 'center', alignItems: 'center', flex: 1 }}>
<Text
style={{
color: colors.primary,
fontSize: 18,
paddingVertical: 20,
}}>
数据载入失败?
</Text>
<Button type="outline" onPress={refresh} title="点击重试" />
</View>
</SafeAreaView>
);
}
return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView
style={{
flex: 1,
}}
refreshControl={
<RefreshControl
tintColor="pink"
refreshing={refreshing}
onRefresh={onRefresh}
/>
}>
<View style={{ backgroundColor: 'white' }}>
{mapData.length ? (
<View style={{ flex: 1 }}>
<View style={{ height: 300 }}>
<ECharts
ref={webviewRef}
option={option}
backgroundColor="#fcfcfc"
/>
</View>
<ButtonGroup
selectedButtonStyle={styles.buttonGroup}
onPress={setIndex}
selectedIndex={selectedIndex}
buttons={[
`确诊 (${total.confirmedCount})`,
`治愈 (${total.curedCount})`,
`致死 (${total.deadCount})`,
]}
containerStyle={{ height: 50 }}
/>
{data && data.getTimelineService && (
<Timeline data={data.getTimelineService} />
)}
{data && data.getIndexRecommendList && (
<RecommendationList data={data.getIndexRecommendList} />
)}
</View>
) : (
<View style={{ flex: 1, width, height }}>
<Loader
size="large"
color="red"
style={{ marginTop: height / 3 }}
/>
</View>
)}
</View>
</ScrollView>
</SafeAreaView>
);
}
Example #27
Source File: Checkout.component.tsx From RNWCShop with GNU General Public License v3.0 | 4 votes |
_renderForm = ({ handleCheckoutSubmit }: Props): JSX.Element => ( <Formik initialValues={{ first_name: '', last_name: '', address_1: '', address_2: '', city: '', state: '', postcode: '', country: '', email: '', phone: '' }} onSubmit={(values): void => handleCheckoutSubmit(values)}> {({ handleChange, handleBlur, handleSubmit, values }): JSX.Element => ( <> <Input label="First Name" placeholder="James" onChangeText={handleChange('first_name')} onBlur={handleBlur('first_name')} value={values.first_name} /> <Input label="Last Name" placeholder="Moriarty" onChangeText={handleChange('last_name')} onBlur={handleBlur('last_name')} value={values.last_name} /> <Input label="Address 1" placeholder="221B Baker Street" onChangeText={handleChange('address_1')} onBlur={handleBlur('address_1')} value={values.address_1} /> <Input label="Address 2" onChangeText={handleChange('address_2')} onBlur={handleBlur('address_2')} value={values.address_2} /> <Input label="City" placeholder="Birmingham" onChangeText={handleChange('city')} onBlur={handleBlur('city')} value={values.city} /> <Input label="State" placeholder="West Midlands" onChangeText={handleChange('state')} onBlur={handleBlur('state')} value={values.state} /> <Input label="Post Code" placeholder="NW1 6XE" onChangeText={handleChange('postcode')} onBlur={handleBlur('postcode')} value={values.postcode} /> <Input label="Country" placeholder="United Kingdom" onChangeText={handleChange('country')} onBlur={handleBlur('country')} value={values.country} /> <Input label="Email" placeholder="[email protected]" onChangeText={handleChange('email')} onBlur={handleBlur('email')} value={values.email} /> <Input label="Phone" placeholder="+628123456789" onChangeText={handleChange('phone')} onBlur={handleBlur('phone')} value={values.phone} /> <Button // @ts-ignore onPress={handleSubmit} title="Proceed to payment" /> </> )} </Formik> )
Example #28
Source File: Checkout.component.tsx From react-native-woocommerce with MIT License | 4 votes |
_renderForm = ({ handleCheckoutSubmit }: Props): JSX.Element => ( <Formik initialValues={{ first_name: '', last_name: '', address_1: '', address_2: '', city: '', state: '', postcode: '', country: '', email: '', phone: '', }} onSubmit={(values): void => handleCheckoutSubmit(values)} > {({ handleChange, handleBlur, handleSubmit, values }): JSX.Element => ( <> <Input label="First Name" placeholder="James" onChangeText={handleChange('first_name')} onBlur={handleBlur('first_name')} value={values.first_name}/> <Input label="Last Name" placeholder="Moriarty" onChangeText={handleChange('last_name')} onBlur={handleBlur('last_name')} value={values.last_name}/> <Input label="Address 1" placeholder="221B Baker Street" onChangeText={handleChange('address_1')} onBlur={handleBlur('address_1')} value={values.address_1}/> <Input label="Address 2" onChangeText={handleChange('address_2')} onBlur={handleBlur('address_2')} value={values.address_2}/> <Input label="City" placeholder="Birmingham" onChangeText={handleChange('city')} onBlur={handleBlur('city')} value={values.city}/> <Input label="State" placeholder="West Midlands" onChangeText={handleChange('state')} onBlur={handleBlur('state')} value={values.state}/> <Input label="Post Code" placeholder="NW1 6XE" onChangeText={handleChange('postcode')} onBlur={handleBlur('postcode')} value={values.postcode}/> <Input label="Country" placeholder="United Kingdom" onChangeText={handleChange('country')} onBlur={handleBlur('country')} value={values.country}/> <Input label="Email" placeholder="[email protected]" onChangeText={handleChange('email')} onBlur={handleBlur('email')} value={values.email}/> <Input label="Phone" placeholder="+628123456789" onChangeText={handleChange('phone')} onBlur={handleBlur('phone')} value={values.phone}/> <Button // @ts-ignore onPress={handleSubmit} title="Proceed to payment" /> </> )} </Formik> )
Example #29
Source File: HomeBluetooth.tsx From ito-app with GNU General Public License v3.0 | 4 votes |
HomeBluetooth: React.FC<{
navigation: HomeBluetoothScreenNavigationProp;
}> = ({navigation}) => {
const {t} = useTranslation();
const [distances, setDistances] = useState<never[]>([]);
const [showIDMatch, setIDMatchShow] = useState<boolean>(false);
const [hasSeenIDMatch, setIDMatchSeen] = useState<boolean>(false);
const emitter = useRef<NativeEventEmitter | null>(null);
const latestFetchTime = NativeModules.ItoBluetooth.getLatestFetchTime();
console.log('Latest fetch time:', latestFetchTime);
const latestFetchDate =
latestFetchTime === -1 ? null : new Date(latestFetchTime * 1000);
const latestFetch =
latestFetchDate === null
? t('home.never')
: `${t('home.today')} ${latestFetchDate.toTimeString().substr(0, 5)}`;
useEffect(() => {
console.log('Setting distance event listener');
emitter.current = new NativeEventEmitter(NativeModules.ItoBluetooth);
const listener = (ds: never[]): void => {
console.log('Distances changed:', ds);
setDistances(ds);
};
emitter.current.addListener('onDistancesChanged', listener);
return (): void => {
if (emitter.current) {
emitter.current.removeListener('onDistancesChanged', listener);
emitter.current = null;
}
};
}, [distances.length]);
useEffect(() => {
function refresh(): void {
if (NativeModules.ItoBluetooth.isPossiblyInfected() && !hasSeenIDMatch) {
setIDMatchShow(true);
}
}
const interval = setInterval(refresh, 2500);
return (): void => clearInterval(interval);
}, [navigation, hasSeenIDMatch]);
const closeIDMatch = (): void => {
setIDMatchShow(false);
setIDMatchSeen(true);
};
const r1Distances = distances.filter((d) => d <= 1.5);
const r2Distances = distances.filter((d) => d > 1.5 && d <= 5);
const r3Distances = distances.filter((d) => d > 5);
// let contactDescription;
let contactStyles;
if (distances.length === 0) {
contactStyles = stylesNoContacts;
// contactDescription = 'no contacts around you';
} else if (distances.length <= 3) {
contactStyles = stylesFewContacts;
// contactDescription = 'just a few contacts around you';
} else {
contactStyles = stylesManyContacts;
// contactDescription = 'many contacts around you';
}
let radius1Style;
if (r1Distances.length < 1) {
radius1Style = StyleSheet.flatten([
styles.radius1,
stylesNoContacts.radius1,
]);
} else if (r1Distances.length >= 1 && r1Distances.length < 5) {
radius1Style = StyleSheet.flatten([
styles.radius1,
stylesFewContacts.radius1,
]);
} else {
radius1Style = StyleSheet.flatten([
styles.radius1,
stylesManyContacts.radius1,
]);
}
let radius2Style;
if (r1Distances.length >= 1) {
radius2Style = StyleSheet.flatten([
styles.radius2,
stylesManyContacts.radius2,
]);
} else if (r2Distances.length < 1) {
radius2Style = StyleSheet.flatten([
styles.radius2,
stylesNoContacts.radius2,
]);
} else if (r2Distances.length >= 1 && r2Distances.length < 5) {
radius2Style = StyleSheet.flatten([
styles.radius2,
stylesFewContacts.radius2,
]);
} else {
radius2Style = StyleSheet.flatten([
styles.radius2,
stylesManyContacts.radius2,
]);
}
let radius3Style;
if (r3Distances.length < 1) {
radius3Style = StyleSheet.flatten([
styles.radius3,
stylesNoContacts.radius3,
]);
} else if (r3Distances.length >= 1 && r3Distances.length < 5) {
radius3Style = StyleSheet.flatten([
styles.radius3,
stylesFewContacts.radius3,
]);
} else {
radius3Style = StyleSheet.flatten([
styles.radius3,
stylesManyContacts.radius3,
]);
}
const contactsStyle = StyleSheet.flatten([
styles.contacts,
contactStyles.contacts,
]);
const avgDistance = distances.length
? distances.reduce((prev, cur) => prev + cur, 0) / distances.length
: null;
const circle2Diameter =
avgDistance === null ? 220 : 80 + Math.cbrt(avgDistance) * 100;
return (
<TouchableWithoutFeedback>
<View style={global.container}>
{showIDMatch && (
<BlurBackground>
<View style={styles.IDMatchPopup}>
<Text style={styles.IDMatchText}>
{t('home.alertContactDiscovered')}
</Text>
<BasicButton title={t('home.whatNext')} onPress={closeIDMatch} />
</View>
</BlurBackground>
)}
<Header
showHelp={true}
navigationButton={{
title: 'new Home',
fn: (): void => {
navigation.navigate('Home');
},
}}
/>
<View style={styles.lastFetchRow}>
<Text style={styles.lastFetch}>
{t('home.lastIdFetch')}: {latestFetch}
</Text>
<Icon name="refresh-ccw" size={18} style={styles.refreshIcon} />
</View>
<View style={styles.radiusContainer}>
<Text style={radius1Style} />
<Text
style={[
radius2Style,
{
width: circle2Diameter,
height: circle2Diameter,
borderRadius: circle2Diameter / 2,
top: 185 - circle2Diameter / 2,
},
]}
/>
<Text style={radius3Style} />
</View>
<Text style={contactsStyle}>{`${distances.length} ${t(
'home.contacts',
)} (avg: ${
avgDistance === null ? 'n/a' : `${avgDistance.toPrecision(2)}m`
})`}</Text>
<Button
title={t('home.buttonTitleInfected')}
onPress={(): void => navigation.navigate('Endangerment')}
titleStyle={styles.buttonInfectedTitle}
buttonStyle={styles.buttonInfected}
/>
</View>
</TouchableWithoutFeedback>
);
}