Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
T
test-webshop
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Artem
test-webshop
Commits
cc0489ae
Commit
cc0489ae
authored
May 16, 2020
by
Artem
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
improve shopping cart using ajax
parent
833c0e38
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
194 additions
and
67 deletions
+194
-67
Cart.php
app/Cart.php
+25
-21
CartController.php
app/Http/Controllers/CartController.php
+32
-7
OrderController.php
app/Http/Controllers/OrderController.php
+2
-1
cart.js
public/js/cart.js
+124
-30
cart.blade.php
resources/views/cart.blade.php
+7
-7
web.php
routes/web.php
+4
-1
No files found.
app/Cart.php
View file @
cc0489ae
...
...
@@ -14,24 +14,21 @@ class Cart /*extends Model*/
$this
->
total_price
=
0
;
}
public
function
updateTotal
Qty
()
public
function
updateTotal
PosAmount
()
{
$result
=
0
;
foreach
(
$this
->
items
as
$item
)
{
$result
+=
$item
[
'qty'
];
}
$this
->
total_qty
=
$result
;
$this
->
total_qty
=
count
(
$this
->
items
);
}
public
function
update
TotalPrice
()
public
function
update
Prices
()
{
$
result
=
0
;
foreach
(
$this
->
items
as
$item
)
$
total_price
=
0
;
foreach
(
$this
->
items
as
$i
d
=>
$i
tem
)
{
$result
+=
$item
[
'qty'
]
*
$item
[
'item'
]
->
price
;
$subtotal_price
=
$item
[
'qty'
]
*
$item
[
'item'
]
->
price
;
$this
->
items
[
$id
][
'subtotal_price'
]
=
$subtotal_price
;
$total_price
+=
$subtotal_price
;
}
$this
->
total_price
=
$
result
;
$this
->
total_price
=
$
total_price
;
}
public
function
addItem
(
$id
)
...
...
@@ -42,27 +39,34 @@ class Cart /*extends Model*/
$this
->
items
[
$id
]
=
[
'qty'
=>
1
];
}
$this
->
total_qty
++
;
$this
->
updateTotalPosAmount
()
;
}
public
function
updateQty
(
$product
s
_qty
)
public
function
updateQty
(
$product
_id
,
$changed
_qty
)
{
foreach
(
$products_qty
as
$id
=>
$qty
)
{
if
(
$qty
<=
0
)
{
$this
->
removeItem
(
$id
);
if
(
array_key_exists
(
$product_id
,
$this
->
items
)
)
{
if
(
$
changed_
qty
<=
0
)
{
$this
->
removeItem
(
$
product_
id
);
}
else
{
$this
->
items
[
$id
][
'qty'
]
=
(
int
)
$qty
;
$this
->
updateTotalQty
();
$this
->
items
[
$product_id
][
'qty'
]
=
$changed_qty
;
}
}
else
{
$this
->
addItem
(
$product_id
);
$this
->
items
[
$product_id
][
'qty'
]
=
$changed_qty
;
}
$this
->
updateCurrentItems
();
$this
->
updatePrices
();
}
public
function
removeItem
(
$id
)
{
unset
(
$this
->
items
[
$id
]);
$this
->
updateTotal
Qty
();
$this
->
updateTotal
PosAmount
();
}
public
function
updateCurrentItems
()
...
...
@@ -81,6 +85,6 @@ class Cart /*extends Model*/
$this
->
items
[
$product
->
id
][
'item'
]
=
$product
;
}
$this
->
update
TotalPrice
();
$this
->
update
Prices
();
}
}
app/Http/Controllers/CartController.php
View file @
cc0489ae
...
...
@@ -17,11 +17,11 @@ class CartController extends Controller
}
$cart
=
Session
::
get
(
'cart'
);
// need to take products from database because product data may change
$cart
->
updateCurrentItems
();
$products
=
$cart
->
items
;
return
view
(
'cart'
,
compact
(
'cart'
,
'products'
));
return
view
(
'cart'
,
compact
(
'cart'
));
}
public
function
addToCart
(
Product
$product
)
...
...
@@ -36,14 +36,17 @@ class CartController extends Controller
}
return
$cart
->
total_qty
;
}
public
function
updateQtyInCart
(
Request
$request
)
{
$products_qty
=
json_decode
(
$request
->
productsQty
,
true
);
if
(
!
Session
::
has
(
'cart'
))
{
return
route
(
'homepage'
);
}
$cart
=
Session
::
get
(
'cart'
);
$cart
->
updateQty
(
$products_qty
);
$cart
->
updateQty
(
$request
->
productId
,
$request
->
changedQty
);
if
(
!
$cart
->
total_qty
)
{
Session
::
forget
(
'cart'
);
...
...
@@ -51,17 +54,18 @@ class CartController extends Controller
}
}
public
function
removeFromCart
(
Product
$produc
t
)
public
function
removeFromCart
(
Request
$reques
t
)
{
$cart
=
Session
::
get
(
'cart'
);
$cart
->
removeItem
(
$
product
->
i
d
);
$cart
->
removeItem
(
$
request
->
productI
d
);
if
(
!
$cart
->
total_qty
)
{
Session
::
forget
(
'cart'
);
return
route
(
'homepage'
);
}
$cart
->
updateCurrentItems
();
}
public
function
clearCart
()
...
...
@@ -69,4 +73,25 @@ class CartController extends Controller
Session
::
forget
(
'cart'
);
return
redirect
(
route
(
'homepage'
));
}
public
function
getItems
()
{
$cart
=
Session
::
get
(
'cart'
);
// make array of products in order to get correct order of items in js
$cart_products
=
[];
foreach
(
$cart
->
items
as
$item
)
{
$cart_products
[]
=
$item
;
}
$response
=
[
'cart'
=>
$cart
,
'products'
=>
$cart_products
,
'update_item_url'
=>
route
(
'cart.updateQtyInCart'
),
'remove_item_url'
=>
route
(
'cart.removeFromCart'
),
'item_url'
=>
'/product/'
];
return
json_encode
(
$response
);
}
}
app/Http/Controllers/OrderController.php
View file @
cc0489ae
...
...
@@ -37,7 +37,8 @@ class OrderController extends Controller
'ordered_reference'
=>
$product
->
reference
,
'ordered_price'
=>
$product
->
price
,
'ordered_qty'
=>
$item
[
'qty'
],
'subtotal_price'
=>
$product
->
price
*
$item
[
'qty'
],
'subtotal_price'
=>
$item
[
'subtotal_price'
],
// 'subtotal_price' => $product->price * $item['qty'],
]);
}
...
...
public/js/cart.js
View file @
cc0489ae
function
setUpdateCartQtyEventListener
()
{
document
.
querySelector
(
'.js-update-qty-btn'
).
addEventListener
(
'click'
,
function
(
e
)
{
class
Cart
{
constructor
(
cartElem
)
{
this
.
cartHtmlElem
=
cartElem
;
this
.
getItemsUrl
=
cartElem
.
dataset
.
getItemsUrl
;
}
const
actionUrl
=
this
.
dataset
.
action
;
generateProductRow
(
product
)
{
return
`<tr>
<td>
<div class="row">
<div class="col-sm-3 hidden-xs"><img src="/img/
${
product
.
item
.
type
}
.jpg" width="100" height="100" alt="
${
product
.
item
.
reference
}
" class="img-responsive"/></div>
<div class="col-sm-9">
<h4 class="nomargin"><a href="
${
this
.
itemUrl
+
product
.
item
.
id
}
">
${
product
.
item
.
reference
}
</a></h4>
<p>
${
product
.
item
.
description_short
}
</p>
</div>
</div>
</td>
<td>€
${
product
.
item
.
price
}
</td>
<td>
<input type="number"
min="0"
class="js-qty-input form-control text-center"
data-product-id="
${
product
.
item
.
id
}
"
value="
${
product
.
qty
}
">
</td>
<td class="text-center">€
${
product
.
subtotal_price
}
</td>
<td class="actions text-right">
<button class="js-remove-btn btn btn-danger btn-sm"
data-action="
${
this
.
removeItemUrl
}
"
data-product-id="
${
product
.
item
.
id
}
"
>Remove</button>
</td>
</tr>`
;
}
const
qtyInputs
=
document
.
querySelectorAll
(
'.js-qty-input'
);
showProducts
()
{
let
productsList
=
''
;
const
productsQty
=
{};
for
(
const
item
in
this
.
products
)
{
const
product
=
this
.
products
[
item
];
productsList
+=
this
.
generateProductRow
(
product
);
}
qtyInputs
.
forEach
(
item
=>
{
const
productId
=
item
.
dataset
.
product_id
;
productsQty
[
productId
]
=
item
.
value
;
});
this
.
cartHtmlElem
.
innerHTML
=
productsList
;
document
.
querySelector
(
'.amount-in-cart'
).
textContent
=
this
.
positionsAmount
;
document
.
querySelector
(
'.js-total-cart-price'
).
textContent
=
'Total € '
+
this
.
totalPrice
;
}
removeItemFromCart
(
e
)
{
if
(
!
e
.
target
.
classList
.
contains
(
'js-remove-btn'
))
return
;
const
actionUrl
=
e
.
target
.
dataset
.
action
;
const
productId
=
e
.
target
.
dataset
.
productId
;
axios
.
post
(
actionUrl
,
{
product
sQty
:
JSON
.
stringify
(
productsQty
)
product
Id
:
productId
,
})
.
then
(
function
(
response
)
{
.
then
(
(
response
)
=>
{
const
redirectLinkWhenCartIsEmpty
=
response
.
data
;
if
(
redirectLinkWhenCartIsEmpty
)
{
window
.
location
.
replace
(
redirectLinkWhenCartIsEmpty
);
}
else
{
document
.
location
.
reload
(
true
);
document
.
querySelector
(
'.js-cart'
).
removeEventListener
(
'click'
,
this
.
removeItemFromCart
);
cart
.
show
();
toastr
.
success
(
'Product deleted'
);
}
})
.
catch
(
function
(
error
)
{
console
.
log
(
error
);
toastr
.
error
(
'Error, something went wrong'
);
});
});
}
}
function
setRemoveItemEventListener
()
{
document
.
querySelector
(
'.js-products-in-cart'
).
addEventListener
(
'click'
,
function
(
e
)
{
if
(
!
e
.
target
.
classList
.
contains
(
'js-remove-btn'
))
return
;
const
actionUrl
=
e
.
target
.
dataset
.
action
;
setUpdateItemQtyEventListener
()
{
document
.
querySelectorAll
(
'.js-qty-input'
).
forEach
(
changeQtyInput
=>
{
let
isChanged
;
changeQtyInput
.
addEventListener
(
'input'
,
(
event
)
=>
{
if
(
isChanged
)
{
return
;
}
axios
.
post
(
actionUrl
)
.
then
(
function
(
response
)
{
const
redirectLinkWhenCartIsEmpty
=
response
.
data
;
// this.show();
isChanged
=
true
;
const
actionUrl
=
this
.
updateItemUrl
;
const
productId
=
event
.
target
.
dataset
.
productId
;
if
(
redirectLinkWhenCartIsEmpty
)
{
window
.
location
.
replace
(
redirectLinkWhenCartIsEmpty
);
}
else
{
document
.
location
.
reload
(
true
);
}
setTimeout
(()
=>
{
axios
.
post
(
actionUrl
,
{
productId
:
productId
,
changedQty
:
event
.
target
.
value
,
})
.
then
(
(
response
)
=>
{
const
redirectLinkWhenCartIsEmpty
=
response
.
data
;
if
(
redirectLinkWhenCartIsEmpty
)
{
window
.
location
.
replace
(
redirectLinkWhenCartIsEmpty
);
}
else
{
cart
.
show
();
toastr
.
success
(
'Quantity updated'
);
}
})
.
catch
(
function
(
error
)
{
console
.
log
(
error
);
toastr
.
error
(
'Error, something went wrong'
);
});
isChanged
=
false
;
},
1000
);
});
});
}
events
()
{
document
.
querySelector
(
'.js-cart'
).
addEventListener
(
'click'
,
this
.
removeItemFromCart
);
this
.
setUpdateItemQtyEventListener
();
}
show
()
{
axios
.
get
(
this
.
getItemsUrl
)
.
then
(
response
=>
{
// this.products = response.data.cart.items;
this
.
products
=
response
.
data
.
products
;
this
.
positionsAmount
=
response
.
data
.
cart
.
total_qty
;
this
.
totalPrice
=
response
.
data
.
cart
.
total_price
;
this
.
updateItemUrl
=
response
.
data
.
update_item_url
;
this
.
removeItemUrl
=
response
.
data
.
remove_item_url
;
this
.
itemUrl
=
response
.
data
.
item_url
;
this
.
showProducts
();
this
.
events
();
})
.
catch
(
function
(
error
)
{
console
.
log
(
error
);
toastr
.
error
(
'Error, s
omething went wrong'
);
alert
(
'S
omething went wrong'
);
});
}
);
}
}
setUpdateCartQtyEventListener
();
setRemoveItemEventListener
();
const
cartElem
=
document
.
querySelector
(
'.js-cart'
);
const
cart
=
new
Cart
(
cartElem
);
cart
.
show
();
resources/views/cart.blade.php
View file @
cc0489ae
...
...
@@ -61,8 +61,8 @@
</
tr
>
</
thead
>
<
tbody
class
="
js
-
products
-
in
-
cart
">
@foreach(
$products
as
$product
)
<
tbody
class
="
js
-
cart
" data-get-items-url="
{{
route
(
'cart.getItems'
)
}}
">
{{--
@foreach(
$products
as
$product
)
<tr>
<td>
<div class="
row
">
...
...
@@ -88,7 +88,7 @@
>Remove</button>
</td>
</tr>
@endforeach
@endforeach
--}}
</tbody>
<tfoot>
...
...
@@ -97,11 +97,11 @@
<a href="
{{
route
(
'homepage'
)
}}
" class="
btn
btn
-
primary
"> Continue Shopping</a>
</td>
<td colspan="
2
" class="
text
-
right
">
<button class="
js
-
update
-
qty
-
btn
btn
btn
-
warning
"
data-action="
{{
route
(
'cart.updateQtyInCart'
)
}}
"
>Update quantity</button>
{{-- <button class="
js
-
update
-
qty
-
btn
btn
btn
-
warning
"--}}
{{-- data-action="
{{
route
(
'cart.updateQtyInCart'
)
}}
"--}}
{{-- >Update quantity</button>--}}
</td>
<td class="
hidden
-
xs
text
-
center
"><b
>Total € {{
$cart->total_price
}}
</b></td>
<td class="
hidden
-
xs
text
-
center
"><b
class="
js
-
total
-
cart
-
price
">
</b></td>
<td>
<button class="
btn
btn
-
success
btn
-
block
" data-toggle="
modal
" data-target="
#placeOrderModal">
Send
order
...
...
routes/web.php
View file @
cc0489ae
...
...
@@ -30,8 +30,11 @@ Route::prefix('cart')->group(function() {
Route
::
get
(
'/'
,
'CartController@index'
)
->
name
(
'cart.index'
);
Route
::
post
(
'/add/{product}'
,
'CartController@addToCart'
)
->
name
(
'cart.addToCart'
);
Route
::
post
(
'/update'
,
'CartController@updateQtyInCart'
)
->
name
(
'cart.updateQtyInCart'
);
Route
::
post
(
'/remove/{product}'
,
'CartController@removeFromCart'
)
->
name
(
'cart.removeFromCart'
);
// Route::post('/remove/{product}', 'CartController@removeFromCart')->name('cart.removeFromCart');
Route
::
post
(
'/remove'
,
'CartController@removeFromCart'
)
->
name
(
'cart.removeFromCart'
);
Route
::
post
(
'/clear'
,
'CartController@clearCart'
)
->
name
(
'cart.clearCart'
);
Route
::
get
(
'/getItems'
,
'CartController@getItems'
)
->
name
(
'cart.getItems'
);
});
Route
::
middleware
(
'auth'
)
->
prefix
(
'profile'
)
->
group
(
function
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment