Ionic Shopping Cart App (FoodKart V0.2)

This is a follow up of the tutorial series on How to build HTML5 Shopping Cart app using Ionic Cordova. If you don’t follow this article, make sure that you have read all the previous article in this series.

[wpi_designer_button text=’Download’ link=’https://github.com/arjunsk/shopping-cart’ style_id=’48’ icon=’github’ target=’_blank’]

UPDATE (10-07-16):

Latest FoodKart V0.3 is released. Read the complete tutorial here.

fk-latest

What’s New:

  1. Added Image Slider to show the featured product (ie food items)
  2. Added lazy load feature for product listing (ie it loads products list only when you scroll down )
  3. Cart Bug fixed (Earlier the cart values would decrement to -ve )
  4. Added more products in the menu list

Bugs to be Fixed:

  1. The lazy load list is based on state change listener. So it load more products every time you change the page (ie if you go to cart page and then come back to menu page, it would add 3 products to the product list )

Feature to be Added:

  1. Easy login/registration with phone number verification
  2. Back-end to handle orders
  3. Dynamically get the featured listing
  4. Push notification service to show the order status.

Potential Usage:

  1. In food courts you could host a local WiFi, with its default page as FoodKart. Then when the user need to order a product, he could easily connect to the WiFi and place the order.

That’s about it ! Now lets see the modified code.

1. Image Slider

image slidder

Added the code in menu.html (this loads the elements from the slide_items array)

<!--Automatically loops back from the beginning -->
<ion-slide-box auto-play ="true" does-continue="true" show-pager="true"  >

	<!-- width: 100% height 50% to fill the slider image according to the layout -->
   <ion-slide class="swiper-slide swiper-slide-active" style="width:100%; height: 50%; "  ng-repeat="slide in slide_items" >
      <div>
         <img  ng-src="{{'img/'+ slide.p_image_id +'.jpg'}}"  ng-click="showProductInfo(slide.p_id,slide.p_description,slide.p_image_id,slide.p_name,slide.p_price)" >
      </div>
   </ion-slide >
   
</ion-slide-box>

In the menuCtrl create the array for the featured listing. Here i have hard codded the array. You can dynamically obtain this array from the server.

	$scope.slide_items=[    {"p_id":"1",
							 "p_name":"New Chicken Maharaja",
							 "p_description":"Product Description",
							 "p_image_id":"slide_1",
							 "p_price":"183.20"},
						    
							{"p_id":"2",
							"p_name":"Big Spicy Chicken Wrap",
							"p_description":"Product Description",
							"p_image_id":"slide_2",
							"p_price":"171.75"},
							
							{"p_id":"3",
							"p_name":"Big Spicy Paneer Wrap",
							"p_description":"Product Description",
							"p_image_id":"slide_3",
							"p_price":"167.17"}
					   ];

2. Lazy Load

lazy load

Add ion-infinite scroll to the end of menu list in menu.html

		<ion-infinite-scroll 
		ng-if="!noMoreItemsAvailable" 
		on-infinite="loadMore()" 
		distance="10%">
			<ion-infinite-scroll-content
			loadingSpinner="bubbles">
		</ion-infinite-scroll>

Now in the controller, ie menuCtrl, we check if there are more list items yet to be loaded. If yes, we load them 5 at a time, in successive calls.

controller.js –> menuCtrl

	$scope.noMoreItemsAvailable = false; // lazy load list
	
				
  	//loads the menu----onload event
	$scope.$on('$stateChangeSuccess', function() {
		$scope.loadMore();  //Added Infine Scroll
	});
	 
	// Loadmore() called inorder to load the list 
	$scope.loadMore = function() {
		
			str=sharedFilterService.getUrl();
			$http.get(str).success(function (response){
				$scope.menu_items = response.records;
				$scope.hasmore=response.has_more;	//"has_more": 0	or number of items left
				$scope.$broadcast('scroll.infiniteScrollComplete');
			});	
			
			//more data can be loaded or not
			if ( $scope.hasmore == 0 ) {
			  $scope.noMoreItemsAvailable = true;
			}
	};

In the sharedFilterService, where we get the request URL, we add a new parameter till . till=10 means that we have to load the list till 10 items.

So in the service.js –> sharedFilterService   make the following changes.

.factory('sharedFilterService', [function(){

	var obj = {};
    obj.str = "http://www.yoursite.com/foodcart/server_side/food_menu.php?till=";
	obj.sort = "";
	obj.search = "";
	obj.category = "";
	obj.till=0;
	
	
	
	obj.getUrl=function(){
		
		obj.till=obj.till + 5;
		obj.str="http://www.yoursite.com/foodcart/server_side/food_menu.php?till="+obj.till; // pass the value to url
		
		if(obj.sort!="" && obj.category!=""){
			obj.str= obj.str+"&category="+obj.category+"&sort="+obj.sort;
		}
		else if(obj.category!="" ){
			obj.str= obj.str+"&category="+obj.category;
		}
		else if(obj.sort!=""){  
			obj.str= obj.str+"&sort="+obj.sort;
		}
		console.log("URL",obj.str);
		return obj.str;
	};
	return obj;
}])

Now we need to modify the PHP, to accept the new parameter.

foodmenu.php

	$till=10;

	if(isset($_GET["till"]) && !empty($_GET["till"]) ){
		$till = $_GET["till"];
		$till = $conn->real_escape_string($till);
	}

	$query="SELECT p_id,p_name,p_description,p_image_id,p_price FROM products where p_id<=".$till." and p_available=1 ";

	if(isset($_GET["category"]) && !empty($_GET["category"]) ){
	
		$cat = $_GET["category"];
		$cat = stripslashes($cat);
		$cat = $conn->real_escape_string($cat);
		$query=$query."and p_category like ".$cat." ";
	}

	

	if( isset($_GET["sort"]) && !empty($_GET["sort"]) ){
	
		$s = $_GET["sort"];
		if($s=="n"){	$query.="order by p_name";}
		else if($s=="plh"){	$query.="order by p_price";}
		else if($s=="phl"){	$query.="order by p_price desc";}
	}


$result = $conn->query($query);
$outp = "";
while($rs = $result->fetch_array(MYSQLI_ASSOC)) {

    if ($outp != "") {$outp .= ",";}

    $outp .= '{"p_id":"'  . $rs["p_id"] . '",';

    $outp .= '"p_name":"'   . $rs["p_name"]        . '",';

	$outp .= '"p_description":"'   . $rs["p_description"]        . '",';

	$outp .= '"p_image_id":"'   . $rs["p_image_id"]        . '",';

	$outp .= '"p_price":"'. $rs["p_price"]     . '"}';

}





// Adding has more

$result=$conn->query("SELECT count(*) as total from products");

$data=$result->fetch_array(MYSQLI_ASSOC);

$total = $data['total'];



if(($total-$till)>0){$has_more=$total-$till;}

			    else{$has_more=0;}


$outp ='{"has_more":'.$has_more.',"records":['.$outp.']}';


$conn->close();

echo($outp);

3. Fix to Cart Bug

cart_fix

There was bug in the sharedCartServices decrement() function.

Fix:

	cartObj.cart.decrement=function(id){
		
		 cartObj.total_qty-= 1;
		 cartObj.total_amount-= parseInt( cartObj.cart[cartObj.cart.find(id)].cart_item_price) ;
		 

		 if(cartObj.cart[cartObj.cart.find(id)].cart_item_qty == 1){  // if the cart item was only 1 in qty
			cartObj.cart.splice( cartObj.cart.find(id) , 1);  //edited
		 }else{
			cartObj.cart[cartObj.cart.find(id)].cart_item_qty-=1;
		 }
	
	};

4. More Menu items

SQL

INSERT INTO `products` (`p_id`, `p_name`, `p_description`, `p_category`, `p_image_id`, `p_price`, `p_available`, `p_stock`) VALUES
('1', 'New Chicken Maharaja', 'Product Description', '1', 'chicken_maharaja', 183, 1, 100),
('2', 'Big Spicy Chicken Wrap', 'Product Description', '1', 'big_spicy_chicken_wrap', 172, 1, 100),
('3', 'Big Spicy Paneer Wrap', 'Product Description', '1', 'big_spicy_paneer_wrap', 167, 1, 100),
('4', 'Veg Maharaja Mac', 'Product Description', '1', 'veg_maharaja', 177, 1, 100),
('5', 'McSpicy Chicken', 'Product Description', '1', 'Mcspicy_chicken', 123, 1, 100),
('6', 'McSpicy Paneer', 'Product Description', '1', 'McSpicy_paneer', 147, 1, 100),
('7', 'Filet-O-Fish', 'Product Description', '1', 'filet_o_fish', 167, 1, 100),
('8', 'Salad wrap', 'Product Description', '1', 'salad_wrap', 127, 1, 100),
('9', 'McChicken', 'Product Description', '1', 'mc_chicken', 167, 1, 100),
('10', 'McVeggie', 'Product Description', '1', 'mc_veggie', 127, 1, 100),
('11', 'Chicken McGrill', 'Product Description', '1', 'chick_mc_grill', 267, 1, 100),
('12', 'McEgg Burger', 'Product Description', '1', 'mc_egg_burger', 147, 1, 100),
('13', 'McAloo Tikki', 'Product Description', '1', 'mc_aloo_tikki', 165, 1, 100),
('14', 'Smoothie', 'Product Description', '2', 'Smoothie', 127, 1, 100),
('15', 'Double Chocolate Frappe', 'Product Description', '2', 'double_chocolate_frappe', 267, 1, 100),
('16', 'McCafe Frappe', 'Product Description', '2', 'mc_cafe_Frappe', 234, 1, 100),
('17', 'Hazelnut Coffee', 'Product Description', '2', 'McCafe_Hazelnut_Cold', 167, 1, 100),
('18', 'McCafe Classic Coffee', 'Product Description', '2', 'McCafe_Classic_coffee', 127, 2, 100),
('19', 'McCafe Ice Coffee', 'Product Description', '2', 'mccafe_ice_coffee', 117, 1, 100),
('20', 'McCafe Ice Tea', 'Product Description', '2', 'mccafe_ice_tea', 134, 1, 100),
('21', 'Iced splash', 'Product Description', '2', 'iced_splash', 290, 1, 100),
('22', 'Coke', 'Product Description', '2', 'coke', 147, 1, 100),
('23', 'Fanta', 'Product Description', '2', 'fanta', 27, 1, 100),
('24', 'Sprite', 'Product Description', '2', 'sprite', 37, 1, 100),
('25', 'Thums Up', 'Product Description', '2', 'thumsup', 30, 1, 100),
('26', 'Coke Zero', 'Product Description', '2', 'coke_zero', 30, 1, 100),
('27', 'Kinley', 'Product Description', '2', 'kinley', 30, 1, 100);

IMAGES

Respective menu image can be downloaded from github.

If you find this worthy. Please subscribe to my blog and follow me on GitHub.

UPDATE: ( 31-07-2016)

Here is a video demo of setting up Ionic Cart!

 

Advertisement

2 thoughts on “Ionic Shopping Cart App (FoodKart V0.2)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s