I need to keep the shopping cart updated with the products that are added. With jQuery I could find the way to add them locally but I can not persist them and / or keep them in a session. What I need is that when surfing, keep those products and only ask me to login when wanting to "checkout" the added products.
I'll give you the community code, thank you.
controller.php
/**
* @Route("/ajax", name="ajax")
* @Method({"GET"})
*/
public function ajaxAction(Request $request)
{
if($request->isXmlHttpRequest())
{
$encoders = array(new JsonEncoder());
$normalizers = array(new ObjectNormalizer());
$serializer = new Serializer($normalizers, $encoders);
$em = $this->getDoctrine()->getManager();
$items = $em->getRepository('AppBundle:Cart')->findOneBy(array('id'=> $this->getUser()->getId()));
if ($items){
$response = new JsonResponse();
$response->setStatusCode(200);
$response->setData(array(
'response' => 'success',
'items' => $serializer->serialize($items, 'json')
));
return $response;
}
}
return new Response('No ajax', 400);
}
/**
* @Route("/ajax_save", name="ajax_save")
* @Method({"GET","POST"})
*/
public function ajaxsaveAction(Request $request)
{
if ($request->isXMLHttpRequest()) {
$user = $this->getUser();
if ($user){
$em = $this->getDoctrine()->getManager();
$content = $request->getContent();
$params = json_decode($content, true);
$cart = $em->getRepository('AppBundle:Cart')->findOneBy(array('user'=> $user, 'product'=> $params['id']));
if ($cart){
$cart->setQuantity($cart->getQuantity() + $params['quantity']);
$em->persist($cart);
$em->flush();
} else {
$cart_new = new Cart();
$cart_new->setUser($user);
$cart_new->setQuantity($params['quantity']);
$cart_new->setProduct($em->getRepository('AppBundle:Product')->find($params['id']));
$em->persist($cart_new);
$em->flush();
}
}
return new JsonResponse(array('data' => 'OK'));
}
return new Response('No es ajax!', 400);
}
base.html.twig
$(function () {
$.ajax({
method: "GET",
url: "{{ path('ajax') }}",
dataType: 'json',
success: function (data) {
console.log(data);
}
});
var goToCartIcon = function($addTocartBtn){
var $cartIcon = $(".my-cart-icon");
var $image = $('<img width="40px" height="40px" src="' + $addTocartBtn.data("image") + '"/>').css({"position": "fixed", "z-index": "999"});
$addTocartBtn.prepend($image);
var position = $cartIcon.position();
$image.animate({
top: position.top,
left: position.left
}, 800 , "linear", function() {
$image.remove();
});
};
window.prod = [];
$('.my-cart-btn').myCart({
currencySymbol: '$',
classCartIcon: 'my-cart-icon',
classCartBadge: 'my-cart-badge',
classProductQuantity: 'my-product-quantity',
classProductRemove: 'my-product-remove',
classCheckoutCart: 'my-cart-checkout',
affixCartIcon: true,
showCheckoutModal: true,
numberOfDecimals: 2,
cartItems: [
],
clickOnAddToCart: function($addTocart){
goToCartIcon($addTocart);
},
afterAddOnCart: function(products, totalPrice, totalQuantity) {
console.log("despues de adherir", products, totalPrice, totalQuantity);
$.ajax({
type: "POST",
url: "{{ path('ajax_save') }}",
data: {
id: this.id, name: this.name, summary: this.summary, price: this.price, quantity: this.quantity, image: this.image
},
dataType: "json",
success: function(data) {
console.log(data);
}
});
},
clickOnCartIcon: function($cartIcon, products, totalPrice, totalQuantity) {
console.log("cart icon clicked", $cartIcon, products, totalPrice, totalQuantity);
},
checkoutCart: function(products, totalPrice, totalQuantity) {
var checkoutString = "Total Price: " + totalPrice + "\nTotal Quantity: " + totalQuantity;
checkoutString += "\n\n id \t name \t summary \t price \t quantity \t image path";
$.each(products, function(){
checkoutString += ("\n " + this.id + " \t " + this.name + " \t " + this.summary + " \t " + this.price + " \t " + this.quantity + " \t " + this.image);
});
alert(checkoutString);
console.log("checking out", products, totalPrice, totalQuantity);
},
getDiscountPrice: function(products, totalPrice, totalQuantity) {
console.log("calculando descuento", products, totalPrice, totalQuantity);
return totalPrice;
}
});
});
jqueryMyCart.js
(function ($) {
"use strict";
var OptionManager = (function () { var objToReturn = {};
var _options = null;
var DEFAULT_OPTIONS = {
currencySymbol: '$',
classCartIcon: 'my-cart-icon',
classCartBadge: 'my-cart-badge',
classProductQuantity: 'my-product-quantity',
classProductRemove: 'my-product-remove',
classCheckoutCart: 'my-cart-checkout',
affixCartIcon: true,
showCheckoutModal: true,
numberOfDecimals: 2,
cartItems: [],
clickOnAddToCart: function($addTocart) { },
afterAddOnCart: function(products, totalPrice, totalQuantity) { },
clickOnCartIcon: function($cartIcon, products, totalPrice, totalQuantity) { },
checkoutCart: function(products, totalPrice, totalQuantity) { },
getDiscountPrice: function(products, totalPrice, totalQuantity) { return null; }
};
var loadOptions = function (customOptions) {
_options = $.extend({}, DEFAULT_OPTIONS);
if (typeof customOptions === 'object') {
$.extend(_options, customOptions);
}
}
var getOptions = function () {
return _options;
}
objToReturn.loadOptions = loadOptions;
objToReturn.getOptions = getOptions;
return objToReturn;
} ());
var MathHelper = (function () { var objToReturn = {}; var getRoundedNumber = function (number) { var options = OptionManager.getOptions (); return number.toFixed (options.numberOfDecimals); } objToReturn.getRoundedNumber = getRoundedNumber; return objToReturn; } ());
var ProductManager = (function () { var objToReturn = {};
/*
PRIVATE
*/
localStorage.products = localStorage.products ? localStorage.products : "";
var getIndexOfProduct = function(id){
var productIndex = -1;
var products = getAllProducts();
$.each(products, function(index, value){
if(value.id == id){
productIndex = index;
return;
}
});
return productIndex;
}
var setAllProducts = function(products){
localStorage.products = JSON.stringify(products);
}
var addProduct = function(id, name, summary, price, quantity, image) {
var products = getAllProducts();
products.push({
id: id,
name: name,
summary: summary,
price: price,
quantity: quantity,
image: image
});
setAllProducts(products);
}
/*
PUBLIC
*/
var getAllProducts = function(){
try {
var products = JSON.parse(localStorage.products);
return products;
} catch (e) {
return [];
}
}
var updatePoduct = function(id, quantity) {
var productIndex = getIndexOfProduct(id);
if(productIndex < 0){
return false;
}
var products = getAllProducts();
products[productIndex].quantity = typeof quantity === "undefined" ? products[productIndex].quantity * 1 + 1 : quantity;
setAllProducts(products);
return true;
}
var setProduct = function(id, name, summary, price, quantity, image) {
if(typeof id === "undefined"){
console.error("id requerido")
return false;
}
if(typeof name === "undefined"){
console.error("nombre requerido")
return false;
}
if(typeof image === "undefined"){
console.error("imagen requerida")
return false;
}
if(!$.isNumeric(price)){
console.error("el precio no es un número")
return false;
}
if(!$.isNumeric(quantity)) {
console.error("cantidad no es un número");
return false;
}
summary = typeof summary === "undefined" ? "" : summary;
if(!updatePoduct(id)){
addProduct(id, name, summary, price, quantity, image);
}
}
var clearProduct = function(){
setAllProducts([]);
}
var removeProduct = function(id){
var products = getAllProducts();
products = $.grep(products, function(value, index) {
return value.id != id;
});
setAllProducts(products);
}
var getTotalQuantity = function(){
var total = 0;
var products = getAllProducts();
$.each(products, function(index, value){
total += value.quantity * 1;
});
return total;
}
var getTotalPrice = function(){
var products = getAllProducts();
var total = 0;
$.each(products, function(index, value){
total += value.quantity * value.price;
total = MathHelper.getRoundedNumber(total) * 1;
});
return total;
}
objToReturn.getAllProducts = getAllProducts;
objToReturn.updatePoduct = updatePoduct;
objToReturn.setProduct = setProduct;
objToReturn.clearProduct = clearProduct;
objToReturn.removeProduct = removeProduct;
objToReturn.getTotalQuantity = getTotalQuantity;
objToReturn.getTotalPrice = getTotalPrice;
return objToReturn;
} ());
var loadMyCartEvent = function () {
var options = OptionManager.getOptions();
var $cartIcon = $("." + options.classCartIcon);
var $cartBadge = $("." + options.classCartBadge);
var classProductQuantity = options.classProductQuantity;
var classProductRemove = options.classProductRemove;
var classCheckoutCart = options.classCheckoutCart;
var idCartModal = 'my-cart-modal';
var idCartTable = 'my-cart-table';
var idGrandTotal = 'my-cart-grand-total';
var idEmptyCartMessage = 'my-cart-empty-message';
var idDiscountPrice = 'my-cart-discount-price';
var classProductTotal = 'my-product-total';
var classAffixMyCartIcon = 'my-cart-icon-affix';
if(options.cartItems && options.cartItems.constructor === Array) {
ProductManager.clearProduct();
$.each(options.cartItems, function() {
ProductManager.setProduct(this.id, this.name, this.summary, this.price, this.quantity, this.image);
});
}
$cartBadge.text(ProductManager.getTotalQuantity());
if(!$("#" + idCartModal).length) {
$('body').append(
'<div class="modal fade" id="' + idCartModal + '" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">' +
'<div class="modal-dialog" role="document">' +
'<div class="modal-content">' +
'<div class="modal-header">' +
'<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>' +
'<h4 class="modal-title" id="myModalLabel"><i class="fa fa-shopping-cart"></i> Mi Carrito</h4>' +
'</div>' +
'<div class="modal-body">' +
'<table class="table table-hover table-responsive" id="' + idCartTable + '"></table>' +
'</div>' +
'<div class="modal-footer">' +
'<button type="button" class="btn btn-default" data-dismiss="modal">Cerrar</button>' +
'<button type="button" class="btn btn-primary ' + classCheckoutCart + '">Comprar</button>' +
'</div>' +
'</div>' +
'</div>' +
'</div>'
);
}
var drawTable = function(){
var $cartTable = $("#" + idCartTable);
$cartTable.empty();
var products = ProductManager.getAllProducts();
$.each(products, function(){
var total = this.quantity * this.price;
$cartTable.append(
'<tr title="' + this.summary + '" data-id="' + this.id + '" data-price="' + this.price + '">' +
'<td class="text-center" style="width: 40px;"><img width="40px" height="40px" src="' + this.image + '"/></td>' +
'<td>' + this.name + '</td>' +
'<td title="PrecioUnitario">' + options.currencySymbol + MathHelper.getRoundedNumber(this.price) + '</td>' +
'<td title="Cantidad"><input type="number" min="1" style="width: 70px;" class="' + classProductQuantity + '" value="' + this.quantity + '"/></td>' +
'<td title="Total" class="' + classProductTotal + '">' + options.currencySymbol + MathHelper.getRoundedNumber(total) + '</td>' +
'<td title="Eliminar del Carrito" class="text-center" style="width: 30px;"><a href="javascript:void(0);" class="btn btn-xs btn-danger ' + classProductRemove + '">X</a></td>' +
'</tr>'
);
});
$cartTable.append(products.length ?
'<tr>' +
'<td></td>' +
'<td><strong>Total</strong></td>' +
'<td></td>' +
'<td></td>' +
'<td><strong id="' + idGrandTotal + '"></strong></td>' +
'<td></td>' +
'</tr>'
: '<div class="alert alert-danger" role="alert" id="' + idEmptyCartMessage + '">Tu Carro está Vacío</div>'
);
var discountPrice = options.getDiscountPrice(products, ProductManager.getTotalPrice(), ProductManager.getTotalQuantity());
if(products.length && discountPrice !== null) {
$cartTable.append(
'<tr style="color: red">' +
'<td></td>' +
'<td><strong>Total (Incluyendo Descuentos)</strong></td>' +
'<td></td>' +
'<td></td>' +
'<td><strong id="' + idDiscountPrice + '"></strong></td>' +
'<td></td>' +
'</tr>'
);
}
showGrandTotal();
showDiscountPrice();
}
var showModal = function(){
drawTable();
$("#" + idCartModal).modal('show');
}
var updateCart = function(){
$.each($("." + classProductQuantity), function(){
var id = $(this).closest("tr").data("id");
ProductManager.updatePoduct(id, $(this).val());
});
}
var showGrandTotal = function(){
$("#" + idGrandTotal).text(options.currencySymbol + MathHelper.getRoundedNumber(ProductManager.getTotalPrice()));
}
var showDiscountPrice = function(){
$("#" + idDiscountPrice).text(options.currencySymbol + MathHelper.getRoundedNumber(options.getDiscountPrice(ProductManager.getAllProducts(), ProductManager.getTotalPrice(), ProductManager.getTotalQuantity())));
}
/*
EVENT
*/
if(options.affixCartIcon) {
var cartIconBottom = $cartIcon.offset().top * 1 + $cartIcon.css("height").match(/\d+/) * 1;
var cartIconPosition = $cartIcon.css('position');
$(window).scroll(function () {
$(window).scrollTop() >= cartIconBottom ? $cartIcon.addClass(classAffixMyCartIcon) : $cartIcon.removeClass(classAffixMyCartIcon);
});
}
$cartIcon.click(function(){
options.showCheckoutModal ? showModal() : options.clickOnCartIcon($cartIcon, ProductManager.getAllProducts(), ProductManager.getTotalPrice(), ProductManager.getTotalQuantity());
});
$(document).on("input", "." + classProductQuantity, function () {
var price = $(this).closest("tr").data("price");
var id = $(this).closest("tr").data("id");
var quantity = $(this).val();
$(this).parent("td").next("." + classProductTotal).text(options.currencySymbol + MathHelper.getRoundedNumber(price * quantity));
ProductManager.updatePoduct(id, quantity);
$cartBadge.text(ProductManager.getTotalQuantity());
showGrandTotal();
showDiscountPrice();
});
$(document).on('keypress', "." + classProductQuantity, function(evt){
if(evt.keyCode == 38 || evt.keyCode == 40){
return ;
}
evt.preventDefault();
});
$(document).on('click', "." + classProductRemove, function(){
var $tr = $(this).closest("tr");
var id = $tr.data("id");
$tr.hide(500, function(){
ProductManager.removeProduct(id);
drawTable();
$cartBadge.text(ProductManager.getTotalQuantity());
});
});
$("." + classCheckoutCart).click(function(){
var products = ProductManager.getAllProducts();
if(!products.length) {
$("#" + idEmptyCartMessage).fadeTo('fast', 0.5).fadeTo('fast', 1.0);
return ;
}
updateCart();
options.checkoutCart(ProductManager.getAllProducts(), ProductManager.getTotalPrice(), ProductManager.getTotalQuantity());
ProductManager.clearProduct();
$cartBadge.text(ProductManager.getTotalQuantity());
$("#" + idCartModal).modal("hide");
});
}
var MyCart = function (target) { / * PRIVATE * / var $ target = $ (target); var options = OptionManager.getOptions (); var $ cartIcon = $ ("." + options.classCartIcon); var $ cartBadge = $ ("." + options.classCartBadge);
/*
EVENT
*/
$target.click(function(){
options.clickOnAddToCart($target);
var id = $target.data('id');
var name = $target.data('name');
var summary = $target.data('summary');
var price = $target.data('price');
var quantity = $target.data('quantity');
var image = $target.data('image');
ProductManager.setProduct(id, name, summary, price, quantity, image);
$cartBadge.text(ProductManager.getTotalQuantity());
options.afterAddOnCart(ProductManager.getAllProducts(), ProductManager.getTotalPrice(), ProductManager.getTotalQuantity());
});
}
$. fn.myCart = function (userOptions) { OptionManager.loadOptions (userOptions); loadMyCartEvent (); return $ .each (this, function () { new MyCart (this); }); }
}) (jQuery);