Ecom React Native Application

Ecom React Native Application


import React from 'react';
import ProductList from './components/ProductList';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import ProductDetails from './components/ProductDetails';
import { GestureHandlerRootView } from 'react-native-gesture-handler';


const Stack = createNativeStackNavigator();

function App(): React.JSX.Element {

  return (
    <Provider store={store}>
      <GestureHandlerRootView style={{ flex: 1 }}>
      <NavigationContainer>
        <Stack.Navigator>
          <Stack.Screen name="Home" component={ProductList} options={{headerShown:false}}/>
          <Stack.Screen name='details' component={ProductDetails} options={{headerShown:false}}/>
        </Stack.Navigator>
      </NavigationContainer>
      </GestureHandlerRootView>
    </Provider>
  );
}



export default App;

This is Landing Page

import { ScrollView, StyleSheet,FlatList, Text, View, TouchableOpacity } from 'react-native';
import React, { useEffect, useState } from 'react';
import { SafeAreaView } from 'react-native-safe-area-context';
import axios from 'axios';
import SingleProduct from './SingleProduct';
import { useSelector, useDispatch } from 'react-redux'
import { category } from '../slices/CategorySlice';
import { RootState } from '../store/store';

const ProductList = ({ navigation }) => {
  const [category, setCategory] = useState([]);
  const [allproduct , setAllProduct] = useState([]);
  const singlecategory = useSelector((state: RootState) => state.category.value)
  const dispatch = useDispatch()

  useEffect(() => {
    const fetchData = async () => {
      const data = await axios.get('https://fakestoreapi.com/products/categories');
      setCategory(data.data);
    };
    fetchData();
    fetch('https://fakestoreapi.com/products').then(res=>res.json()).then((data)=>{setAllProduct(data)})
  }, []);

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <View style={styles.maintitle}>
        <Text style={styles.title}>MY STORE</Text>
      </View>
      <View>
        <ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
          {category.map((data, index) => (
            <Text key={index} style={styles.each_cat}>{data}</Text>
          ))}
        </ScrollView>
      </View>

      <View style={{ flex: 1 }}>
          <FlatList
            data={allproduct}
            keyExtractor={(item)=>item.id}
            renderItem={({item}) =>item? <TouchableOpacity onPress={() => navigation.navigate('details',{item:item.id})}><SingleProduct data={item}/></TouchableOpacity>:null}
            numColumns={2}
            contentContainerStyle={styles.mylist}
          />
      </View>

    </SafeAreaView>
  );
};

export default ProductList;

const styles = StyleSheet.create({
  mylist: {
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
  },
  each_cat: {
    backgroundColor: '#3B1E54',
    height: 50,
    margin: 10,
    color: '#EEEEEE',
    textAlign: 'center',
    paddingTop: 15,
    borderRadius: 7,
    padding: 10,
    fontWeight: 'bold',
  },
  maintitle: {
    justifyContent: 'center',
    alignItems: 'center',
    margin: 10,
  },
  title: {
    height: 40,
    width: '100%',
    margin: 10,
    textAlign: 'center',
    lineHeight: 40,
    fontSize: 40,
    fontFamily: 'cursive',
    color: 'brown',
  },
});

This is Single Product Page

import { Button, Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
import React from 'react'
import { SafeAreaView } from 'react-native-safe-area-context'

const SingleProduct = ({data}) => {
  return (
    <SafeAreaView>
        <View style={styles.card_view}>
            <View  style={styles.image_view}>
                <Image
                    style={styles.image}
                    source={{ uri: `${data.image}` }}
                />
            </View>
            <Text style={{fontSize:17,fontWeight:'500',paddingLeft:10,}}>{data.title.slice(0,21)}</Text>
            <Text style={{fontSize:17,fontWeight:'500',paddingLeft:10, backgroundColor:'#D7C3F1', width:'60%', borderColor:'#C8A1E0',borderWidth:3, borderRadius:4,marginLeft:8,marginTop:5}}>$ {data.price}</Text>
            <View style={styles.start_count}>
                <Text style={{marginLeft:4}}>({data.rating.rate})</Text>
                <Image source={require('../assets/icons/fill_star.png')} style={styles.star_img}/>
                <Text style={{marginLeft:4}}>({data.rating.count})</Text>
            </View>
      </View>
    </SafeAreaView>
  )
}

export default SingleProduct

const styles = StyleSheet.create({
    buttons:{
        height:10,
        width:40
    },
    card_view:{
        shadowColor: 'red',
        backgroundColor:'white',
        borderColor:'gery',
        borderRadius:10,
        borderWidth:1,
        width: 160,
        margin:5
    },
    image_view :{
        alignItems:'center',
        justifyContent:'center',
        marginTop:5,
    },
    image:{
        height:140,
        width:'90%',
        borderBlockColor:"black",
        margin:3,
        borderRadius:10,
        objectFit:'contain',
        aspectRatio:'1/1',
    },
    star_img:{
        height:20,
        width:20
    },
    start_count:{
        flexDirection:'row',
        alignItems:'center',
        justifyContent:'flex-start',
        marginTop:8,
        marginBottom:5,
        marginLeft:5,

    }
})

This is Product Details Page

import { StyleSheet, Text, View ,Image, ActivityIndicator} from 'react-native'
import React, { useState,useEffect } from 'react';
import { useRoute } from '@react-navigation/native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { ScrollView } from 'react-native-gesture-handler';


const ProductDetails = () => {
  const route = useRoute()
  const id = route.params?.item
  const [details , setDetails] = useState([]); 
  const [isLoading, setIsLoading] = useState(true); // Loading state
  useEffect(() => {
    // Fetch product details when the component mounts
    fetch(`https://fakestoreapi.com/products/${id}`)
      .then((response) => response.json())
      .then((data) => {
        setDetails(data);
        setIsLoading(false); // Set loading state to false once data is fetched
      })
      .catch((error) => {
        console.error("Error fetching product details:", error);
        setIsLoading(false); // Set loading state to false in case of error
      });
  }, [id]);
  if (isLoading) {
    return (
      <SafeAreaView style={{flex:1,justifyContent:'center'}}>
        <ActivityIndicator size="large" color="grey" />
      </SafeAreaView>
    );
  }

  return (
    <SafeAreaView>
      <View style={{backgroundColor:'white',alignItems:'center'}}>
        <Image source={{ uri: details?.image }} resizeMode="contain" height={350}  width={350} />
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.title}>{details.title}</Text>
      </View>
      <View style={styles.ratingContainer}>
        <View style={{backgroundColor:'green' , flexDirection:'row',alignItems:'center',padding:5,borderRadius:5,height:30,}}>
          <Text style={{width:30, color:'white',}}>{details?.rating.rate}</Text>
          <Image source={require('../assets/icons/fill_star.png')} style={{width:15,height:15}}/>
        </View>
        <Text style={{margin:5,fontSize:20,color:'grey'}}>{`(${details?.rating.count})`}</Text>
        <Text style={{fontSize:18,fontWeight:500,backgroundColor:'#FADA7A', borderColor:'#F29F58',borderWidth:3,borderRadius:7,padding:3}}>{details?.category}</Text>
      </View>
      <View>
        <Text style={styles.price}>{`$${details.price}`}</Text>
      </View>
      <View style={styles.descriptionContainer}>
        <Text style={styles.descriptionTitle}>Description</Text>
        <ScrollView style={{height:150,padding:9}}>
          <Text style={styles.descriptionText}>{details.description}</Text>
        </ScrollView>
      </View>
    </SafeAreaView>
  )
}

export default ProductDetails

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 10,
  },
  imageContainer: {
    alignItems: 'center',
    marginBottom: 20,
  },
  image: {
    width: 350,
    height: 350,
  },
  textContainer: {
    flexDirection:'row',
    alignItems: 'center',
    marginBottom: 3,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginLeft:10,
    marginTop:10,
    marginBottom:10
  },
  price: {
    marginLeft:10,
    fontWeight:800,
    fontSize: 20,
    color: 'black',
  },
  ratingContainer: {
    flexDirection:'row',
    width:'100%',
    marginBottom: 5,
    marginLeft:10,
    alignItems:'center'
  },
  descriptionContainer: {

  },
  descriptionTitle: {
    fontWeight: 700,
    marginLeft:10,
    fontSize:17,
    marginTop:5
  },
  descriptionText: {
    margin:10,
    fontSize: 16,
    color: 'gray',
  },
});