react-native-elements#ListItem TypeScript Examples

The following examples show how to use react-native-elements#ListItem. 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: HomeScreen.tsx    From react-native-sdk with MIT License 6 votes vote down vote up
render() {
    return (
      <View>
        {
          coffees.map((coffee, i) => (
            <ListItem
              onPress={() => {
                this.props.navigation.navigate('Detail', { coffee: coffee })
              }}
              key={i}
              leftAvatar={{ source: coffee.icon }}
              title={coffee.name}
              subtitle={coffee.subtitle}
              bottomDivider
              chevron
            />
          ))
        }
      </View>
    )
  }
Example #2
Source File: draft-item.tsx    From bext with MIT License 6 votes vote down vote up
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 #3
Source File: HeaderListItem.tsx    From react-native-network-client with Apache License 2.0 6 votes vote down vote up
HeaderListItem = ({
    index,
    header,
    updateHeader,
    disabled,
    testID,
}: HeaderListItemProps) => {
    const updateHeaderKey = (key: string) =>
        updateHeader && updateHeader({ ...header, key }, index);
    const updateHeaderValue = (value: string) =>
        updateHeader && updateHeader({ ...header, value }, index);

    return (
        <ListItem>
            <Input
                containerStyle={{ flex: 1 }}
                onChangeText={updateHeaderKey}
                placeholder="key"
                value={header.key}
                disabled={disabled}
                testID={`${testID}.${index}.key.input`}
            />
            <Input
                containerStyle={{ flex: 1 }}
                onChangeText={updateHeaderValue}
                placeholder="value"
                value={header.value}
                disabled={disabled}
                testID={`${testID}.${index}.value.input`}
            />
        </ListItem>
    );
}
Example #4
Source File: CartListItem.tsx    From magento_react_native_graphql with MIT License 6 votes vote down vote up
CartListItem = ({
  item,
  index,
  onPress,
  onRemovePress,
}: Props): React.ReactElement => {
  const renderImage = () => {
    const uri = `${item.product.small_image.url}?width=${DIMENS.cartScreen.imageSize}`;
    return <Image source={{ uri }} style={styles.image} />;
  };

  return (
    <ListItem onPress={() => onPress(index)} bottomDivider>
      {renderImage()}
      <ListItem.Content>
        <ListItem.Title>{item.product.name}</ListItem.Title>
        <ListItem.Subtitle>{`${translate('common.quantity')} : ${
          item.quantity
        }`}</ListItem.Subtitle>
        <ListItem.Subtitle>{`${translate('common.price')} : ${formatPrice(
          item.prices.rowTotal,
        )}`}</ListItem.Subtitle>
      </ListItem.Content>
      <ListItem.Chevron name="delete" onPress={() => onRemovePress(index)} />
    </ListItem>
  );
}
Example #5
Source File: ClientListItem.tsx    From react-native-network-client with Apache License 2.0 5 votes vote down vote up
ClientListItem = (props: ClientListItemProps) => {
    const {
        index,
        deleteClient,
        item: { name, client, type },
    } = props;

    const viewClient = () => {
        let screen = "GenericClientRequest";
        if (type === ClientType.API) {
            screen = "APIClient";
        } else if (type === ClientType.WEBSOCKET) {
            screen = "WebSocketClient";
        }

        props.navigate(screen, { item: props.item });
    };

    const invalidateClient = () => {
        if ("invalidate" in client) {
            client.invalidate();
            deleteClient(index);
        }
    };

    const removeClient = () => {
        "invalidate" in client &&
            Alert.alert(
                "Remove Client",
                "",
                [{ text: "Cancel" }, { text: "OK", onPress: invalidateClient }],
                { cancelable: true }
            );
    };

    const Subtitle = () => {
        if ("baseUrl" in client) {
            return (
                <ListItem.Subtitle testID="client_list_item.subtitle">
                    {client.baseUrl}
                </ListItem.Subtitle>
            );
        } else if ("url" in client) {
            return (
                <ListItem.Subtitle testID="client_list_item.subtitle">
                    {client.url}
                </ListItem.Subtitle>
            );
        }

        return null;
    };

    return (
        <ListItem
            onPress={viewClient}
            onLongPress={removeClient}
            bottomDivider
            testID="client_list_item.item"
        >
            <ListItem.Content testID="client_list_item.content">
                <ListItem.Title testID="client_list_item.title">
                    {name}
                </ListItem.Title>
                <Subtitle />
            </ListItem.Content>
            <ListItem.Chevron testID="client_list_item.chevron" />
        </ListItem>
    );
}
Example #6
Source File: MultipartListItem.tsx    From react-native-network-client with Apache License 2.0 5 votes vote down vote up
MultipartListItem = ({
    index,
    multipart,
    updateMultipart,
    removeMultipart,
    disabled,
    testID,
}: MultipartListItemProps) => {
    const updateMultipartKey = (key: string) =>
        updateMultipart && updateMultipart({ ...multipart, key }, index);
    const updateMultipartValue = (value: string) =>
        updateMultipart && updateMultipart({ ...multipart, value }, index);

    return (
        <ListItem>
            <Input
                containerStyle={{ flex: 1 }}
                onChangeText={updateMultipartKey}
                placeholder="key"
                value={multipart.key}
                disabled={disabled}
                testID={`${testID}.${index}.key.input`}
            />
            <Input
                containerStyle={{ flex: 1 }}
                onChangeText={updateMultipartValue}
                placeholder="value"
                value={multipart.value}
                disabled={disabled}
                testID={`${testID}.${index}.value.input`}
            />
            <Button
                type="clear"
                icon={<Icon name="trash" size={24} />}
                onPress={() => removeMultipart(index)}
                testID="remove_multipart.button"
            />
        </ListItem>
    );
}
Example #7
Source File: CategoryListItem.tsx    From magento_react_native_graphql with MIT License 5 votes vote down vote up
CategoryListItem = ({ item, navigation }: Props): React.ReactElement => {
  const [disabled] = useState<boolean>(
    +item.childrenCount < 1 && item.productCount < 1,
  );
  const onCategoryPress = () => {
    if (+item.childrenCount > 0) {
      navigation.navigate(Routes.NAVIGATION_TO_CATEGORIES_SCREEN, {
        categoryId: item.id,
        name: item.name,
      });
      return;
    }
    navigation.navigate(Routes.NAVIGATION_TO_PRODUCT_LIST_SCREEN, {
      categoryId: item.id,
      name: item.name,
    });
  };

  const renderImage = () => {
    const rawUri =
      item.image ?? item.productPreviewImage?.items?.[0]?.smallImage?.url;
    if (!rawUri) {
      return null;
    }
    const uri = `${rawUri ?? ''}?width=100`;

    return <Image source={{ uri }} resizeMode="cover" style={styles.image} />;
  };

  const renderContent = () => {
    return (
      <>
        <ListItem.Content>
          <ListItem.Title>{item.name}</ListItem.Title>
        </ListItem.Content>
      </>
    );
  };

  return (
    <ListItem
      containerStyle={styles.conatiner}
      disabled={disabled}
      onPress={onCategoryPress}
      bottomDivider
    >
      {renderImage()}
      {renderContent()}
    </ListItem>
  );
}
Example #8
Source File: Mobility.tsx    From wuhan2020-frontend-react-native-app with MIT License 5 votes vote down vote up
function Mobility({ item }: { item: EntryType }) {
  const [visible, setVisible] = useState(false);

  return (
    <View>
      <ListItem
        onPress={() => setVisible(true)}
        title={
          <Text
            style={{
              fontWeight: '800',
            }}>{`${item.t_pos_start} - ${item.t_pos_end}`}</Text>
        }
        subtitle={
          <View>
            <View
              style={{
                flexDirection: 'row',
                justifyContent: 'space-between',
              }}>
              <Text style={{ fontSize: 12 }}>{item.t_no}</Text>
              <Text style={{ fontSize: 12 }}>{item.who}</Text>
            </View>
            {Boolean(item.t_memo) && (
              <Text style={{ color: '#717171' }}>({item.t_memo})</Text>
            )}
          </View>
        }
        leftAvatar={
          <View style={{ width: 50 }}>
            <Text style={{ fontSize: 13, fontWeight: 'bold' }}>
              {typeMap[item.t_type].label}
            </Text>
          </View>
        }
        rightIcon={{ name: 'unfold-more' }}
      />
      <WebViewModal
        title={`${item.t_pos_start} - ${item.t_pos_end}`}
        uri={item.source}
        visible={visible}
        onClose={() => setVisible(false)}
      />
    </View>
  );
}
Example #9
Source File: News.tsx    From wuhan2020-frontend-react-native-app with MIT License 5 votes vote down vote up
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.content.slice(0, 50)}
          </Text>
        }
        subtitle={
          <View
            style={{
              paddingTop: 4,
              flexDirection: 'row',
              justifyContent: 'space-between',
            }}>
            <Text style={{ fontSize: 12 }}>时间: {props.sendTime}</Text>
            <Text style={{ fontSize: 12 }}>来源: {props.fromName}</Text>
          </View>
        }
        rightIcon={{ name: 'unfold-more' }}
      />
      <Modal
        animationType="fade"
        presentationStyle="pageSheet"
        visible={visible}
        onDismiss={() => {
          setVisible(false);
        }}
        onRequestClose={() => {
          setVisible(false);
        }}>
        <View style={{ padding: 16, justifyContent: 'space-between' }}>
          <View style={{ height: height - 150 }}>
            {loadingWebview ? (
              <ActivityIndicator size="large" color="red" />
            ) : null}
            <WebView
              onLoad={() => setLoading(true)}
              onLoadEnd={() => setLoading(false)}
              source={{ uri: props.url }}
            />
          </View>
          <View>
            <Button
              buttonStyle={styles.button}
              title="关闭预览"
              onPress={() => {
                setVisible(false);
              }}
            />
          </View>
        </View>
      </Modal>
    </View>
  );
}
Example #10
Source File: RecommendationList.tsx    From wuhan2020-frontend-react-native-app with MIT License 5 votes vote down vote up
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 #11
Source File: Timeline.tsx    From wuhan2020-frontend-react-native-app with MIT License 5 votes vote down vote up
function Entry(props: EntryPropsType) {
  const [visible, setVisible] = useState(false);
  return (
    <View>
      <ListItem
        onPress={() => setVisible(true)}
        Component={TouchableOpacity}
        title={<Text style={{ fontWeight: '800' }}>{props.title}</Text>}
        subtitle={`${props.summary.slice(0, 50)}...`}
        leftAvatar={
          <View>
            {props.latest ? (
              <Badge
                value="最新"
                status="error"
                textStyle={{ fontSize: 13, fontWeight: 'bold' }}
              />
            ) : null}
            <Text style={{ fontSize: 13, fontWeight: 'bold' }}>
              {props.pubDateStr}
            </Text>
            <Text style={{ fontSize: 12, color: '#717171' }}>
              {formatTime(props.modifyTime)}
            </Text>
          </View>
        }
        rightAvatar={
          <View style={{ justifyContent: 'flex-end', alignItems: 'flex-end' }}>
            <Text style={{ fontSize: 12, color: '#717171' }}>
              {props.infoSource}
            </Text>
          </View>
        }
      />
      <Modal
        animationType="fade"
        presentationStyle="pageSheet"
        visible={visible}
        onDismiss={() => {
          setVisible(false);
        }}
        onRequestClose={() => {
          setVisible(false);
        }}>
        <View style={{ padding: 16, justifyContent: 'space-between' }}>
          <View style={{ height: height - 150 }}>
            <Text
              style={{ fontSize: 20, fontWeight: 'bold', paddingBottom: 20 }}>
              {props.title}
            </Text>
            <Text style={{ fontSize: 16, lineHeight: 22 }}>
              {props.summary}
            </Text>

            <View style={{ alignSelf: 'flex-end', paddingTop: 20 }}>
              <Text style={{ fontWeight: '800' }}>
                新闻来源:{props.infoSource}
              </Text>
              <Text style={{ fontWeight: '800' }}>
                时间:{props.pubDateStr}
              </Text>
            </View>
          </View>

          <View>
            <Button
              buttonStyle={styles.button}
              title="关闭预览"
              onPress={() => {
                setVisible(false);
              }}
            />
          </View>
        </View>
      </Modal>
    </View>
  );
}
Example #12
Source File: Wuhan2020.tsx    From wuhan2020-frontend-react-native-app with MIT License 5 votes vote down vote up
function ResourceList({ navigation }) {
  return (
    <View>
      <ListItem
        titleStyle={styles.title}
        key="hospital"
        title="医院"
        onPress={() => {
          navigation.navigate({ routeName: 'Hospital' });
        }}
        chevron
        bottomDivider
      />
      <ListItem
        titleStyle={styles.title}
        key="logistic"
        title="物流"
        onPress={() => {
          navigation.navigate({ routeName: 'Logistic' });
        }}
        bottomDivider
        chevron
      />
      <ListItem
        titleStyle={styles.title}
        key="donation"
        title="捐款"
        onPress={() => {
          navigation.navigate({ routeName: 'Donation' });
        }}
        bottomDivider
        chevron
      />
      <ListItem
        titleStyle={styles.title}
        key="consultation"
        title="义诊"
        onPress={() => {
          navigation.navigate({ routeName: 'Consultation' });
        }}
        bottomDivider
        chevron
      />
      <ListItem
        titleStyle={styles.title}
        key="hotel"
        title="指定接待酒店"
        onPress={() => {
          navigation.navigate({ routeName: 'Hotel' });
        }}
        chevron
      />
    </View>
  );
}
Example #13
Source File: ProductListScreen.tsx    From magento_react_native_graphql with MIT License 4 votes vote down vote up
ProductListScreen = ({
  navigation,
  route: {
    params: { categoryId },
  },
}: Props): React.ReactElement => {
  const { data, networkStatus, error, refresh, loadMore } = useCategoryProducts(
    {
      categoryId,
    },
  );
  const { isVisible, selectedIndex, setVisible, sortOptions } = useSort({
    onPress: refresh,
  });
  const { theme } = useContext(ThemeContext);

  useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => (
        <CustomHeaderButtons>
          <CustomHeaderItem
            title={translate('common.sort')}
            iconName="sort"
            onPress={() => setVisible(true)}
          />
        </CustomHeaderButtons>
      ),
    });
  }, [navigation]);

  const onProductItemClicked = (index: number) => {
    if (data?.products?.items) {
      navigation.navigate(Routes.NAVIGATION_TO_PRODUCT_DETAILS_SCREEN, {
        name: data.products.items[index].name,
        sku: data.products.items[index].sku,
      });
    }
  };

  const renderItem = ({
    item,
    index,
  }: {
    item: ProductInListType;
    index: number;
  }) => {
    return (
      <ProductListItem
        item={item}
        index={index}
        onPress={onProductItemClicked}
      />
    );
  };

  const renderFooterComponent = () =>
    (networkStatus === NetworkStatus.fetchMore && (
      <View style={styles.footerContainer}>
        <Spinner />
      </View>
    )) || <></>;

  return (
    <GenericTemplate errorMessage={error?.message}>
      <FlatList
        numColumns={2}
        data={data?.products?.items ?? []}
        renderItem={renderItem}
        keyExtractor={item => `productListItem${item.sku}`}
        refreshControl={
          <RefreshControl
            refreshing={
              networkStatus === NetworkStatus.refetch ||
              networkStatus === NetworkStatus.loading
            }
            onRefresh={refresh}
          />
        }
        onEndReached={loadMore}
        ListFooterComponent={renderFooterComponent}
      />
      <BottomSheet isVisible={isVisible} containerStyle={styles.sortContainer}>
        {sortOptions.map((option, index) => (
          <ListItem
            key={option.title}
            containerStyle={[
              option.containerStyle,
              selectedIndex === index && {
                backgroundColor: theme.colors?.grey5,
              },
            ]}
            onPress={option.onPress}
          >
            <ListItem.Content>
              <ListItem.Title style={option.titleStyle}>
                {option.title}
              </ListItem.Title>
            </ListItem.Content>
          </ListItem>
        ))}
      </BottomSheet>
    </GenericTemplate>
  );
}
Example #14
Source File: FoodList.tsx    From save-food with MIT License 4 votes vote down vote up
FoodList = ({ navigation }: Props) => {
	const moveButton = useRef(new Animated.Value(100)).current

	const { useSubscribe } = useSettingsContext()
	const settings = useSubscribe((s) => s.settings)
	const translations = useSubscribe((s) => ({
		...s.translations.FoodList,
		...s.translations.common,
	}))

	const [list, setList] = useState<WastedFood[]>()
	const [amount, setAmount] = useState(0)
	const [visibleData, setVisibleData] = useState(8)
	const [loading, setLoading] = useState(true)
	const [wait, setWait] = useState(false)
	const [selectedId, setSelectedId] = useState<number>()
	const [showModal, setShowModal] = useState(false)

	const initWastedList = async (showMessage = false) => {
		const wastedFoods = await fetchWastedFood()
		const list = wastedFoods.map((food) => {
			let resize: ResizeMode = 'cover'

			if (food.image) {
				getResizeMode(food.image, (resizeMode) => {
					resize = resizeMode
				})
			}

			return {
				...food,
				resizeMode: resize,
			}
		})

		setList(list)
		setAmount(getAmount(list))
		setLoading(false)
		setWait(false)

		if (showMessage) showSuccessMessage()
	}

	const checkFood = async () => {
		const ids = navigation.getParam('ids', undefined)
		if (ids) {
			setLoading(true)

			await Promise.all(
				ids.map(async (id: number) => {
					await paidFood(id)
					await Promise.resolve()
				}),
			)

			await initWastedList(true)
		} else {
			await initWastedList()
		}
	}

	const showSuccessMessage = () => {
		const message: MessageOptions = {
			message: translations.paymentSuccessTitle,
			type: 'success',
			icon: { icon: 'success', position: 'left' },
			duration: 2500,
		}

		showMessage(message)
	}

	const getAmount = (list: WastedFood[]): number =>
		+list
			.filter((item) => !!item.selected)
			.reduce((a, i) => a + i.price * i.productQuantity, 0)
			.toFixed(2)

	const hideButton = () => {
		Animated.timing(moveButton, {
			toValue: 100,
			duration: 250,
			useNativeDriver: true,
		}).start()
	}

	const showButton = () => {
		Animated.timing(moveButton, {
			toValue: -25,
			duration: 250,
			useNativeDriver: true,
		}).start()
	}

	const selectItem = async (item: WastedFood) => {
		if (!wait) {
			setWait(true)
			if (item.selected) {
				await selectFood(item.id, 0)
			} else {
				await selectFood(item.id, 1)
			}

			await initWastedList()
		}
	}

	const removeItemHandler = async (id: number) => {
		await removeFood(id)
		await initWastedList()
		toggleModal()
	}

	const addFoodQuantity = async (item: WastedFood, value: number) => {
		const newQuantity = +item.productQuantity + value
		if (!wait && newQuantity < 100 && newQuantity > 0) {
			setWait(true)
			await saveFood({ ...item, productQuantity: newQuantity })
			await initWastedList()
		}
	}

	const loadNextData = () => {
		if (list && visibleData < list.length) {
			setVisibleData(visibleData + 8)
		}
	}

	const toggleModal = (id?: number) => {
		if (id) setSelectedId(id)
		setShowModal(!showModal)
	}

	const goToPayment = () => {
		navigation.navigate('Payment', {
			ids: list?.filter((item) => !!item.selected).map((i) => i.id),
			amount,
		})
	}

	const renderItemRow = ({ item }: { item: WastedFood }) => (
		<ListItem containerStyle={[styles.listItemContainer, shadow]}>
			<ListItem.Content>
				<TouchableOpacity
					style={styles.listItem}
					onPress={() => navigation.navigate('Food', { ...item })}
				>
					<View style={styles.details}>
						<View style={styles.leftElement}>
							<Image
								style={[styles.image, { resizeMode: item.resizeMode }]}
								onError={(ev) => {
									if (ev.target) {
										// @ts-ignore
										ev.target.src = '../../assets/common/dish.png'
									}
								}}
								source={getImage(item.image)}
							/>

							<View style={styles.productDetails}>
								<Text numberOfLines={2} style={styles.productName}>
									{!item.name || item.name === '' ? translations.noData : item.name}
								</Text>
								<Text numberOfLines={1} style={styles.text}>
									{translations.quantity}:{' '}
									{item.quantity
										? `${item.quantity} ${getQuantitySuffix(item.quantitySuffixIndex)}`
										: translations.noData}
								</Text>
								<Text numberOfLines={1} style={styles.text}>
									{translations.percent}: {item.percentage}%
								</Text>
							</View>
						</View>

						<View style={styles.rightElement}>
							<Icon
								size={22}
								style={styles.quantityAddIcon}
								name='add'
								type='material'
								color={blackColor}
								onPress={() => addFoodQuantity(item, 1)}
							/>
							<Icon
								size={22}
								style={styles.quantityMinusIcon}
								name='minus'
								type='entypo'
								color={blackColor}
								onPress={() => addFoodQuantity(item, -1)}
							/>
						</View>
					</View>

					<View style={styles.itemListFooter}>
						<TouchableOpacity onPress={() => selectItem(item)} style={styles.priceContainer}>
							<CheckBox
								checked={!!item.selected}
								onPress={() => selectItem(item)}
								containerStyle={styles.checkbox}
								checkedColor={primaryColor}
							/>
							<View style={styles.priceWrapper}>
								<Text style={styles.priceText}>
									{(item.price * item.productQuantity).toFixed(2)} {settings.currency}
								</Text>
								{item.productQuantity > 1 && (
									<Text style={styles.quantityText}>
										({item.price} {settings.currency} x{item.productQuantity})
									</Text>
								)}
							</View>
						</TouchableOpacity>
						<Icon
							size={22}
							onPress={() => toggleModal(item.id)}
							style={styles.deleteProductIcon}
							color={redColor}
							name='trash'
							type='font-awesome-5'
						/>
					</View>
				</TouchableOpacity>
			</ListItem.Content>
		</ListItem>
	)

	useAsyncEffect(async () => {
		await checkFood()
	}, [navigation])

	useEffect(() => {
		if (list?.some((item) => !!item.selected)) {
			showButton()
		} else {
			hideButton()
		}
	}, [list])

	useAsyncEffect(async () => {
		await initWastedList()
	}, [])

	if (!list) {
		return <Spinner size={64} />
	}

	return (
		<Background>
			<Header
				leftComponent={<Icon variant='backIcon' onPress={() => navigation.replace('Home')} />}
				centerComponent={<Text style={styles.headerTitle}>{translations.foodList}</Text>}
				rightComponent={
					<Icon
						style={styles.openScannerIcon}
						name='plus'
						type='antdesign'
						onPress={() => navigation.navigate('Scanner')}
					/>
				}
				centerSize={6}
			/>

			<Modal
				visible={showModal}
				toggleModal={toggleModal}
				title={translations.deleteProduct}
				buttons={[
					{ text: translations.yes, onPress: () => selectedId && removeItemHandler(selectedId) },
					{ text: translations.cancel, onPress: toggleModal },
				]}
			>
				<Text style={styles.deleteProductDescription}>{translations.deleteProductDescription}</Text>
			</Modal>

			<View style={styles.container}>
				<FlatList
					keyboardShouldPersistTaps='always'
					keyboardDismissMode='interactive'
					scrollEventThrottle={16}
					refreshControl={
						<RefreshControl refreshing={loading} tintColor='#fff' onRefresh={initWastedList} />
					}
					ListEmptyComponent={<EmptyList navigation={navigation} />}
					data={list}
					initialNumToRender={8}
					onEndReachedThreshold={0.2}
					onEndReached={loadNextData}
					renderItem={renderItemRow}
					keyExtractor={(item) => `${item.id}`}
					onRefresh={initWastedList}
					refreshing={loading}
					ListFooterComponent={
						list.length > visibleData ? (
							<Spinner bgColor='transparency' />
						) : (
							<View style={styles.listFooter} />
						)
					}
				/>
			</View>

			<Animated.View
				style={[{ transform: [{ translateY: moveButton }] }, styles.paymentButtonContainer, shadow]}
			>
				<View style={styles.paymentButtonWrapper}>
					<Button
						buttonStyle={styles.paymentButton}
						titleStyle={styles.paymentButtonTitle}
						onPress={goToPayment}
						disabled={amount === 0}
						title={`${translations.donate} ${getPrice(amount)} ${settings.currency}`}
					/>
				</View>
			</Animated.View>
		</Background>
	)
}
Example #15
Source File: Settings.tsx    From save-food with MIT License 4 votes vote down vote up
Settings = ({ navigation }: Props) => {
	const { useSubscribe, setSettings } = useSettingsContext()
	const settings = useSubscribe((s) => s.settings)
	const translations = useSubscribe((s) => ({
		...s.translations.Settings,
		...s.translations.common,
	}))

	const [modalType, setModalType] = useState<ModalType>('language')
	const [modalContent, setModalContent] = useState<ReactNode>()
	const [showModal, setShowModal] = useState(false)

	const languageMap: LanguageMap = {
		en: translations.english,
		pl: translations.polish,
	}

	const changeLanguageHandler = async (lang: Language) => {
		setSettings(await changeLang(lang))
		setShowModal(false)
	}

	const changeCurrencyHandler = async (currency: Currency) => {
		setSettings(await changeCurrency(currency))
		setShowModal(false)
	}

	const clearDatabaseHandler = async () => {
		setSettings(await clearDatabase())
		setShowModal(false)
		showSuccessMessage()
	}

	const setModalContentHandler = (type: ModalType) => {
		if (type === 'language') {
			setModalContent(
				<View>
					{(Object.keys(languageMap) as Array<keyof LanguageMap>).map((lang) => (
						<TouchableOpacity key={lang} onPress={() => changeLanguageHandler(lang)}>
							<ListItem bottomDivider>
								<ListItem.Content>
									<ListItem.Title
										style={{ color: lang === settings.lang ? primaryColor : blackColor }}
									>
										{languageMap[lang]}
									</ListItem.Title>
								</ListItem.Content>
							</ListItem>
						</TouchableOpacity>
					))}
				</View>,
			)
		} else if (type === 'currency') {
			setModalContent(
				<View>
					{currencyList.map((item) => (
						<TouchableOpacity key={item} onPress={() => changeCurrencyHandler(item)}>
							<ListItem bottomDivider>
								<ListItem.Content>
									<ListItem.Title
										style={{ color: item === settings.currency ? primaryColor : blackColor }}
									>
										{item}
									</ListItem.Title>
								</ListItem.Content>
							</ListItem>
						</TouchableOpacity>
					))}
				</View>,
			)
		} else if (type === 'clearTheDatabase') {
			setModalContent(
				<Text style={styles.clearTheDatabase}>{translations.clearTheDatabaseModal}</Text>,
			)
		}

		setModalType(type)
		setShowModal(true)
	}

	const toggleModal = (type?: ModalType) => {
		if (!showModal && type) {
			setModalContentHandler(type)
		} else {
			setShowModal(false)
		}
	}

	const showSuccessMessage = () => {
		const message: MessageOptions = {
			message: translations.clearTheDatabaseSuccess,
			type: 'success',
			icon: { icon: 'success', position: 'left' },
			duration: 2500,
		}

		showMessage(message)
	}

	return (
		<View style={styles.container}>
			<Header
				leftComponent={<Icon onPress={() => navigation.replace('Home')} variant='backIcon' />}
				centerComponent={<Text style={styles.headerTitle}>{translations.settings}</Text>}
			/>

			<Modal
				visible={showModal}
				toggleModal={toggleModal}
				title={translations[modalType]}
				buttons={
					modalType === 'clearTheDatabase'
						? [
								{ text: translations.yes, onPress: clearDatabaseHandler },
								{ text: translations.cancel, onPress: toggleModal },
						  ]
						: []
				}
			>
				{modalContent}
			</Modal>

			<View style={styles.settingsWrapper}>
				<InfoWindow
					color1={blackColor}
					color2={orangeGradient}
					title={translations.language}
					value={languageMap[settings.lang]}
					colorTitle={whiteColor}
					onPress={() => toggleModal('language')}
				/>
				<InfoWindow
					color1={blackColor}
					color2={redGradient}
					title={translations.currency}
					value={settings.currency}
					colorTitle={whiteColor}
					onPress={() => toggleModal('currency')}
				/>
				<TouchableOpacity style={styles.clear} onPress={() => toggleModal('clearTheDatabase')}>
					<Text style={styles.clearText}>{`${translations.clearTheDatabase}  `}</Text>
					<Icon
						onPress={() => toggleModal('clearTheDatabase')}
						size={28}
						name='trash-o'
						type='font-awesome'
					/>
				</TouchableOpacity>
			</View>

			<View style={styles.footerContainer}>
				<Text style={styles.versionText}>
					{translations.version}: {settings.version}
				</Text>
				<TouchableOpacity onPress={() => WebBrowser.openBrowserAsync(config.FOOD_API)}>
					<Text style={styles.linkText}>API: {config.FOOD_API}</Text>
				</TouchableOpacity>
				<TouchableOpacity onPress={() => WebBrowser.openBrowserAsync(config.WS_URL)}>
					<Text style={styles.linkText}>
						{translations.authors}: {config.WS_URL}
					</Text>
				</TouchableOpacity>
			</View>
		</View>
	)
}
Example #16
Source File: About.tsx    From wuhan2020-frontend-react-native-app with MIT License 4 votes vote down vote up
function About() {
  const [loadingWebview, setLoading] = useState(true);

  return (
    <StatusBarSafeLayout>
      <ScrollView>
        <View style={styles.container}>
          <View>
            <Text style={styles.header}>数据来源</Text>
            <Text
              style={styles.link}
              onPress={() =>
                Linking.openURL('https://github.com/wuhan2020/wuhan2020')
              }>
              https://github.com/wuhan2020/wuhan2020
            </Text>
            <Text
              style={styles.link}
              onPress={() =>
                Linking.openURL('https://3g.dxy.cn/newh5/view/pneumonia')
              }>
              丁香园
            </Text>
            <Text
              style={styles.link}
              onPress={() =>
                Linking.openURL('https://2019ncov.nosugartech.com/')
              }>
              https://2019ncov.nosugartech.com/
            </Text>
            <Text
              style={styles.link}
              onPress={() =>
                Linking.openURL('http://ncov.news.dragon-yuan.me/')
              }>
              http://ncov.news.dragon-yuan.me/
            </Text>
          </View>
          <Divider style={styles.divider} />
          <View>
            <Text style={styles.header}>wuhan2020</Text>
            <Text style={{ lineHeight: 18 }}>
              我们是 GitHub
              开源社区的志愿者核心团队,在抗击非冠病毒的战役中,我们希望通过共同构建一个开源信息共享项目,帮助武汉自组织救援工作更有效、更准确地开展。我们当前在做的事是:建立一个医院、工厂、采购等信息实时同步的数据服务,同时召集所有希望对这次抗击病毒战役进行贡献的人,让每个具有相关技能的人都可以参与相关主题的开发工作,用开源的社区文化,以自组织协作的方式完成。
            </Text>
          </View>
          <Divider style={styles.divider} />
          <View>
            <Text style={styles.header}>加入我们</Text>
            <Text style={{ lineHeight: 18 }}>
              如果你也想加入我们,可以通过以下方式:
            </Text>
            <View>
              <ListItem
                title="加入我们"
                rightAvatar={
                  <Text
                    style={styles.link}
                    onPress={() =>
                      Linking.openURL('https://github.com/wuhan2020/wuhan2020')
                    }>
                    点击此链接了解详情
                  </Text>
                }
              />
              <ListItem
                title="GitHub"
                rightAvatar={
                  <Text
                    style={styles.link}
                    onPress={() =>
                      Linking.openURL('https://github.com/wuhan2020/wuhan2020')
                    }>
                    GitHub
                  </Text>
                }
              />
            </View>
          </View>
          <Divider style={styles.divider} />
          <View>
            <Text style={styles.header}>建议</Text>
            <Text style={{ lineHeight: 18 }}>
              如果你有任何好的建议,无论是对我们的项目还是这个App都可以发邮件至
            </Text>
            <Text
              style={[styles.link, { marginVertical: 5 }]}
              onPress={() => Linking.openURL('mailto:[email protected]')}>
              [email protected]
            </Text>
          </View>
          <Divider style={styles.divider} />
          <View>
            <Text style={styles.header}>其他信息</Text>
            <ListItem title="版本" rightAvatar={<Text>1.0.0</Text>} />
            <ListItem title="技术" rightAvatar={<Text>React Native</Text>} />
            <ListItem
              title="代码库"
              rightAvatar={
                <Text
                  style={styles.link}
                  onPress={() =>
                    Linking.openURL(
                      'https://github.com/wuhan2020/wuhan2020-frontend-react-native-app',
                    )
                  }>
                  GitHub
                </Text>
              }
            />
            <ListItem
              title="作者"
              rightAvatar={
                <Text
                  style={styles.link}
                  onPress={() =>
                    Linking.openURL('https://github.com/geastwood')
                  }>
                  geastwood(飞)
                </Text>
              }
            />
          </View>
          <Divider style={styles.divider} />
        </View>
      </ScrollView>
    </StatusBarSafeLayout>
  );
}