SneakerShop Tutorial : Home Screen โจ๐โจ
Majuran SIVAKUMAR
Posted on April 7, 2023
Hello team ๐, I hope you are all doing well!
In our last post, we made some great progress by configuring our project and successfully navigating between screens.
In today's post, we have some amazing things to showcase on our home screen!
Home Screen ๐
For the home screen, I want:
- A simple header with the project name and a shopping bag icon displaying the number of products in the cart.
- A button to navigate to Filter screen
- A product list that includes a picture, model name, brand name, and price.
To populate this data, I created a JSON file that mocks an API fetch.
// /api/index.js
import { data } from "./data.json";
export const getProducts = () => Promise.resolve(data)
The mock data object is like :
{
"data": [
{
"id": 11,
"brand": "Nike Sportswear",
"model": "AIR FORCE 1",
"imageUrl": "https://img01.ztat.net/article/spp-media-p1/b83f2fe8dfd14010b0f07f919710380d/64888efd8c034688aa9c7677151fba44.jpg",
"price": 119.95,
"description": "Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.",
"color": [
{
"name": "White",
"hex": "#ffffff"
}
]
},
{
"id": 9,
"brand": "Nike Sportswear",
"model": "DUNK RETRO SE DC",
"imageUrl": "https://img01.ztat.net/article/spp-media-p1/d5bf785592bb477db8d8208c984dfc86/eee0aab7b764448ca86050955de6ee02.jpg",
"price": 109.95,
"description": "Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.",
"color": [
{
"name": "Gray",
"hex": "#808080"
}
]
},
// ....
// I let you mock the data as you need
]
}
The Home Screen becomes :
// /screens/HomeScreen.js
import React, { useEffect } from "react";
import { useNavigation } from "@react-navigation/native";
import { Text, SafeAreaView, View, ScrollView, TouchableOpacity, Image} from "react-native";
import { ShoppingBagIcon, AdjustmentsIcon } from "react-native-heroicons/outline";
import { useSelector, useDispatch } from "react-redux";
import { getProducts } from "../api";
import { nbItemsInCart } from "../store/features/cart/cartSlice";
import { selectNbOfFilters, selectProducts, setProducts } from "../store/features/products/productsSlice";
const HomeScreen = () => {
// ๐ get informations from store
const products = useSelector(selectProducts);
const itemsInCart = useSelector(nbItemsInCart);
const filterItems = useSelector(selectNbOfFilters);
const dispatch = useDispatch();
const { navigate } = useNavigation();
useEffect(() => {
/* ๐ Fetch data from api on init */
async function getData() {
const datas = await getProducts();
dispatch(setProducts(datas));
}
getData();
}, []);
const goToDetails = (item) => navigate("Detail", item);
const goToCart = () => navigate("Cart");
const goToFilter = () => navigate("Filter");
return (
<SafeAreaView className="bg-white">
{/* ๐ HEADER */}
<View className="relative flex-row justify-between px-5 py-2">
<Text className="uppercase text-xl font-bold">Sneakershop</Text>
<TouchableOpacity onPress={goToCart}>
<ShoppingBagIcon color="black" size="32" strokeWidth={1.5} />
{/* ๐ SHOW NUMBER OF ITEM IN CART */}
{!!itemsInCart && (
<View className="absolute bg-red-400 px-1 rounded-full bottom-0 right-0">
<Text className="text-white text-xs font-bold">
{itemsInCart}
</Text>
</View>
)}
</TouchableOpacity>
</View>
<View className="flex-row justify-between px-5 py-2 mb-2">
<Text className="text-lg font-bold">Products</Text>
<View className="flex-row justify-between">
{/* ๐ Filter button to go to Filter Screen */}
<TouchableOpacity
className="relative border border-slate-400 p-1"
onPress={goToFilter}
>
<AdjustmentsIcon color="black" size="30" strokeWidth="1.5" />
{/* ๐ Show number of filter applied */}
{!!filterItems && (
<View className="absolute bg-slate-900 px-1 rounded-full -bottom-1 -right-1">
<Text className="text-white text-xs font-bold">
{filterItems}
</Text>
</View>
)}
</TouchableOpacity>
</View>
</View>
{/* ๐ ScrollView to show products */}
<ScrollView className="h-full bg-white">
<View className="flex flex-row flex-wrap justify-between pb-32 px-0.5">
{/* Map on products to show a product card*/}
{products.map((item) => (
<TouchableOpacity key={item.id} onPress={() => goToDetails(item)}>
<View className="flex w-48 h-60 pb-4 bg-white">
<View className="flex-1 bg-slate-200">
<Image
className="flex-1"
resizeMode="cover"
source={{
uri:
item.imageUrl +
"?imwidth=1080&filter=packshot&imformat=jpeg",
}}
></Image>
</View>
<View className="p-1">
<Text className="uppercase text-s font-bold">
{item.model}
</Text>
<Text className="capitalize">{item.brand}</Text>
<Text className="text-xs text-slate-500 mt-1">
{item.price} โฌ
</Text>
</View>
</View>
</TouchableOpacity>
))}
{products.length === 0 && <Text>No results</Text>}
</View>
</ScrollView>
</SafeAreaView>
);
};
export default HomeScreen;
Next ๐
I'm really excited about the progress we're making and can't wait to see what we will accomplish next.
Now that our Home Screen is done, we are going to start the FilterScreen in next post ๐
Hopefully you enjoyed the article as wellโif so, please let me know in the comment section below! ๐ฌ
Source code ๐จโ๐ป
Feel free to checkout the source code there ๐ Github
Posted on April 7, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.