react-native-elements#ThemeContext TypeScript Examples

The following examples show how to use react-native-elements#ThemeContext. 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: ProductListItem.tsx    From magento_react_native_graphql with MIT License 6 votes vote down vote up
ProductListItem = ({
  item,
  index,
  horizontalMode = false,
  onPress,
}: Props): React.ReactElement => {
  const { theme } = useContext(ThemeContext);
  const renderImage = () => {
    const uri = `${item.smallImage.url}?width=${COLUMN_WIDTH}`;
    return <Image source={{ uri }} style={styles.image} />;
  };

  return (
    <TouchableOpacity onPress={() => onPress(index)}>
      <View
        style={[
          styles.container,
          {
            borderColor: theme.colors?.divider,
            backgroundColor: theme.colors?.white,
          },
          horizontalMode && styles.topBorder,
          (horizontalMode || index % 2 !== 0) && styles.leftBorder,
        ]}
      >
        {renderImage()}
        <Text style={styles.name}>{item.name}</Text>
        <Text style={styles.price}>
          {formatPrice(item.priceRange.maximumPrice.finalPrice)}
        </Text>
      </View>
    </TouchableOpacity>
  );
}
Example #2
Source File: Spinner.tsx    From magento_react_native_graphql with MIT License 6 votes vote down vote up
Spinner = ({
  size = 'large',
  color,
  style = {},
}: Props): React.ReactElement => {
  const { theme } = useContext(ThemeContext);
  return (
    <ActivityIndicator
      style={style}
      size={size}
      color={color ?? theme.colors?.primary}
    />
  );
}
Example #3
Source File: CartFooter.tsx    From magento_react_native_graphql with MIT License 6 votes vote down vote up
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: useSort.ts    From magento_react_native_graphql with MIT License 5 votes vote down vote up
useSort = ({ onPress }: Props): Result => {
  const [state, setState] = useReducer<
    React.Reducer<SortState, { isVisible?: boolean; selectedIndex?: number }>
  >((prevState, newState) => ({ ...prevState, ...newState }), {
    isVisible: false,
    selectedIndex: -1,
  });
  const { theme } = useContext(ThemeContext);
  const sortOptions = useMemo(
    () => [
      {
        title: translate('common.aToZ'),
        onPress: () => {
          onPress({ name: SortEnum.ASC });
          setState({ isVisible: false, selectedIndex: 0 });
        },
      },
      {
        title: translate('common.zToA'),
        onPress: () => {
          onPress({ name: SortEnum.DESC });
          setState({ isVisible: false, selectedIndex: 1 });
        },
      },
      {
        title: translate('common.lowToHigh'),
        onPress: () => {
          onPress({ price: SortEnum.ASC });
          setState({ isVisible: false, selectedIndex: 2 });
        },
      },
      {
        title: translate('common.highToLow'),
        onPress: () => {
          onPress({ price: SortEnum.DESC });
          setState({ isVisible: false, selectedIndex: 3 });
        },
      },
      {
        title: translate('common.cancel'),
        containerStyle: { backgroundColor: theme.colors?.error },
        titleStyle: { color: 'white' },
        onPress: () => setState({ isVisible: false }),
      },
    ],
    [theme, onPress],
  );

  const setVisible = (visible: boolean) => setState({ isVisible: visible });

  return {
    isVisible: state.isVisible,
    selectedIndex: state.selectedIndex,
    setVisible,
    sortOptions,
  };
}
Example #5
Source File: BottomTabNavigator.tsx    From magento_react_native_graphql with MIT License 5 votes vote down vote up
BottomTabNavigator = ({ navigation }: Props) => {
  const { data } = useQuery<IsLoggedInDataType>(IS_LOGGED_IN);
  const { cartCount } = useCart();
  const { theme } = useContext(ThemeContext);

  return (
    <Tab.Navigator>
      <Tab.Screen
        name={Routes.NAVIGATION_TO_HOME_SCREEN}
        component={HomeScreen}
        options={{
          tabBarLabel: translate('homeScreen.appbarTitle'),
          tabBarIcon: ({ color, size }) => (
            <Icon name="home" color={color} size={size} />
          ),
        }}
      />
      <Tab.Screen
        name={Routes.NAVIGATION_TO_PROFILE_SCREEN}
        component={ProfileScreen}
        options={{
          tabBarLabel: translate('profileScreen.appbarTitle'),
          tabBarIcon: ({ color, size }) => (
            <Icon name="person" color={color} size={size} />
          ),
        }}
        listeners={{
          tabPress: e => {
            if (!data?.isLoggedIn) {
              // Prevent default action
              e.preventDefault();
              showLoginPrompt(
                translate('profileScreen.guestUserPromptMessage'),
                navigation,
              );
            }
          },
        }}
      />
      <Tab.Screen
        name={Routes.NAVIGATION_TO_CART_SCREEN}
        component={CartScreen}
        options={{
          tabBarLabel: translate('cartScreen.appbarTitle'),
          tabBarIcon: ({ color, size }) => (
            <Icon name="shopping-cart" color={color} size={size} />
          ),
          tabBarBadgeStyle: {
            backgroundColor: theme.colors?.error,
          },
          ...(cartCount !== '' && { tabBarBadge: cartCount }),
        }}
        listeners={{
          tabPress: e => {
            if (!data?.isLoggedIn) {
              // Prevent default action
              e.preventDefault();
              showLoginPrompt(
                translate('cartScreen.guestUserPromptMessage'),
                navigation,
              );
            }
          },
        }}
      />
    </Tab.Navigator>
  );
}
Example #6
Source File: FeaturedProductList.tsx    From magento_react_native_graphql with MIT License 5 votes vote down vote up
FeaturedProductList = ({
  name,
  categoryId,
}: Props): React.ReactElement => {
  const { data, networkStatus, error } = useCategoryProducts({ categoryId });
  const { theme } = useContext(ThemeContext);
  const navigation = useNavigation();

  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}
        horizontalMode
        onPress={onProductItemClicked}
      />
    );
  };

  if (error?.message) {
    return (
      <View>
        <Text>{error.message}</Text>
      </View>
    );
  }

  if (networkStatus === NetworkStatus.loading) {
    return (
      <View style={styles.loadingBox(theme)}>
        <Spinner />
      </View>
    );
  }

  return (
    <View style={styles.container(theme)}>
      {name && (
        <Text h2 h2Style={styles.title}>
          {name}
        </Text>
      )}
      <FlatList
        horizontal
        showsHorizontalScrollIndicator={false}
        data={data?.products?.items ?? []}
        renderItem={renderItem}
        keyExtractor={item => `productListItem${item.sku}`}
      />
    </View>
  );
}
Example #7
Source File: ConfigurableOptionValues.tsx    From magento_react_native_graphql with MIT License 5 votes vote down vote up
ConfigurableOptionValues = ({
  values,
  optionCode,
  selectedIndex,
  handleSelectedConfigurableOptions,
}: Props): React.ReactElement => {
  const { theme } = useContext(ThemeContext);

  const renderValue = (value: ConfigurableProductOptionValueType) => {
    const selected = selectedIndex === value.valueIndex;
    switch (value.swatchData.__typename) {
      case 'ColorSwatchData': {
        return (
          <>
            <View
              style={{
                width:
                  DIMENS.productDetailScreen.configurableOptionValueBoxSize,
                height:
                  DIMENS.productDetailScreen.configurableOptionValueBoxSize,
                backgroundColor: value.swatchData.value,
              }}
            />
            {selected ? (
              <View style={styles.selectedColor}>
                <Icon type="ionicon" name="checkmark" size={24} />
              </View>
            ) : null}
          </>
        );
      }
      case 'TextSwatchData': {
        return (
          <View
            style={[
              styles.selectedText,
              {
                backgroundColor: selected
                  ? theme.colors?.black
                  : theme.colors?.white,
              },
            ]}
          >
            <Text
              style={{
                color: selected ? theme.colors?.white : theme.colors?.black,
              }}
            >
              {value.swatchData.value}
            </Text>
          </View>
        );
      }
      default: {
        return null;
      }
    }
  };

  return (
    <View style={styles.container}>
      {values.map(value => (
        <TouchableOpacity
          key={String(value.valueIndex)}
          onPress={() =>
            handleSelectedConfigurableOptions(optionCode, value.valueIndex)
          }
        >
          <View style={styles.valueContainer}>{renderValue(value)}</View>
        </TouchableOpacity>
      ))}
    </View>
  );
}
Example #8
Source File: ProductDetailsScreen.tsx    From magento_react_native_graphql with MIT License 4 votes vote down vote up
ProductDetailsScreen = ({
  navigation,
  route: {
    params: { sku },
  },
}: Props): React.ReactElement => {
  const {
    error,
    loading,
    priceRange,
    mediaGallery,
    productDetails,
    selectedConfigurableProductOptions,
    handleSelectedConfigurableOptions,
  } = useProductDetails({
    sku,
  });
  const {
    cartCount,
    isLoggedIn,
    addProductsToCart,
    addToCartLoading,
  } = useCart();
  const { theme } = useContext(ThemeContext);

  useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => (
        <CustomHeaderButtons>
          <CustomHeaderItem
            title={translate('common.cart')}
            iconName="shopping-cart"
            onPress={() =>
              navigation.navigate(Routes.NAVIGATION_TO_CART_SCREEN)
            }
          />
          {cartCount !== '' && (
            <Badge
              value={cartCount}
              status="error"
              textStyle={styles.badgeText}
              containerStyle={styles.badge}
            />
          )}
        </CustomHeaderButtons>
      ),
    });
  }, [navigation, cartCount]);

  const handleAddToCart = () => {
    if (!isLoggedIn) {
      showLoginPrompt(
        translate('productDetailsScreen.guestUserPromptMessage'),
        navigation,
      );
      return;
    }

    if (
      productDetails?.type === ProductTypeEnum.SIMPLE ||
      productDetails?.type === ProductTypeEnum.GROUPED
    ) {
      addProductsToCart({
        quantity: 1,
        sku: productDetails.sku,
      });
    } else {
      showMessage({
        message: translate('common.attention'),
        description: translate('productDetailsScreen.productTypeNotSupported'),
        type: 'warning',
      });
    }
  };

  const renderPrice = (): React.ReactNode => {
    if (productDetails && priceRange) {
      return (
        <Text h2 style={styles.price}>
          {formatPrice(priceRange.maximumPrice.finalPrice)}
        </Text>
      );
    }
    return null;
  };

  const renderOptions = (): React.ReactNode => {
    if (productDetails?.type === ProductTypeEnum.CONFIGURED) {
      return (
        <ConfigurableProductOptions
          options={productDetails?.configurableOptions}
          selectedConfigurableProductOptions={
            selectedConfigurableProductOptions
          }
          handleSelectedConfigurableOptions={handleSelectedConfigurableOptions}
        />
      );
    }
    return null;
  };

  const renderDiscription = (): React.ReactNode => {
    if (productDetails) {
      return (
        <HTML
          source={{ html: productDetails.description.html }}
          contentWidth={Dimensions.get('window').width}
          containerStyle={styles.description}
          baseFontStyle={{ color: theme.colors?.black }}
        />
      );
    }
    return null;
  };

  return (
    <GenericTemplate
      scrollable
      loading={loading}
      errorMessage={error?.message}
      footer={
        <Button
          loading={addToCartLoading}
          containerStyle={styles.noBorderRadius}
          buttonStyle={styles.noBorderRadius}
          title={translate('productDetailsScreen.addToCart')}
          onPress={handleAddToCart}
        />
      }
    >
      <View>
        <MediaGallery items={mediaGallery} />
        <Text h1 style={styles.name}>
          {productDetails?.name}
        </Text>
        {renderPrice()}
        {renderOptions()}
        {renderDiscription()}
      </View>
    </GenericTemplate>
  );
}
Example #9
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 #10
Source File: SearchScreen.tsx    From magento_react_native_graphql with MIT License 4 votes vote down vote up
SearchScreen = ({ navigation }: Props): React.ReactElement => {
  const {
    searchText,
    handleChange,
    networkStatus,
    called,
    loadMore,
    data: { products: { items: products = [] } = {} } = {},
  } = useSearch();
  const { theme } = useContext(ThemeContext);
  const loadingProps = useMemo(() => ({ color: theme.colors?.primary }), [
    theme,
  ]);

  const handleBackPress = () => navigation.pop();

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

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

  // FIXME: Don't show when previous search result was empty, and user is typing
  // create a separate state
  const renderEmptyComponent = () =>
    (searchText.length >= LIMITS.searchTextMinLength &&
      products.length === 0 &&
      called &&
      networkStatus !== NetworkStatus.loading && (
        <View style={styles.center}>
          <Text>
            {translate('searchScreen.noProductsFound', { searchText })}
          </Text>
        </View>
      )) || <></>;

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

  return (
    <GenericTemplate>
      <SearchBar
        placeholder={translate('searchScreen.searchBarHint')}
        onChangeText={handleChange}
        value={searchText}
        showLoading={networkStatus === NetworkStatus.loading}
        searchIcon={{
          name: 'arrow-back',
          onPress: handleBackPress,
        }}
        loadingProps={loadingProps}
        containerStyle={styles.searchBarContainer}
      />
      <FlatList
        numColumns={2}
        data={products}
        renderItem={renderItem}
        keyExtractor={item => `productListItem${item.sku}`}
        ListEmptyComponent={renderEmptyComponent}
        ListFooterComponent={renderFooterComponent}
        onEndReached={loadMore}
      />
    </GenericTemplate>
  );
}