-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #601 from evershopcommerce/dev
Dev
- Loading branch information
Showing
17 changed files
with
440 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
154 changes: 154 additions & 0 deletions
154
packages/evershop/src/components/frontStore/checkout/cart/items/Quantity.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { useAppDispatch } from '@components/common/context/app'; | ||
import { toast } from 'react-toastify'; | ||
|
||
export default function Quantity({ qty, api }) { | ||
const AppContextDispatch = useAppDispatch(); | ||
const [quantity, setQuantity] = React.useState(qty); | ||
const previousQuantity = React.useRef(qty); | ||
const [debounceTimer, setDebounceTimer] = React.useState(null); | ||
const [isLoading, setIsLoading] = React.useState(false); | ||
|
||
const updateQuantity = (newQuantity) => { | ||
setQuantity(newQuantity); | ||
if (debounceTimer) { | ||
clearTimeout(debounceTimer); | ||
} | ||
const timer = setTimeout(() => { | ||
callUpdateAPI(newQuantity); | ||
}, 500); | ||
setDebounceTimer(timer); | ||
}; | ||
|
||
const callUpdateAPI = async (qty) => { | ||
setIsLoading(true); | ||
try { | ||
const response = await fetch(api, { | ||
method: 'PATCH', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify({ | ||
qty: Math.abs(previousQuantity.current - qty), | ||
action: qty > quantity ? 'increase' : 'decrease' | ||
}), | ||
credentials: 'same-origin' | ||
}); | ||
const json = await response.json(); | ||
if (!json.error) { | ||
const url = new URL(window.location.href); | ||
url.searchParams.set('ajax', true); | ||
await AppContextDispatch.fetchPageData(url); | ||
previousQuantity.current = qty; | ||
} else { | ||
setQuantity(previousQuantity.current); | ||
toast.error(json.error.message); | ||
} | ||
} catch (error) { | ||
setQuantity(previousQuantity.current); | ||
toast.error(error.message); | ||
} finally { | ||
setIsLoading(false); | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="qty-box grid grid-cols-3 border border-[#ccc]"> | ||
<button | ||
className="flex justify-center items-center" | ||
onClick={() => updateQuantity(Math.max(quantity - 1, 0))} | ||
disabled={isLoading} | ||
type="button" | ||
> | ||
{isLoading && ( | ||
<svg | ||
ariaHidden="true" | ||
focusable="false" | ||
role="presentation" | ||
className="spinner" | ||
viewBox="0 0 66 66" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<circle | ||
className="path" | ||
fill="none" | ||
strokeWidth="6" | ||
cx="33" | ||
cy="33" | ||
r="30" | ||
/> | ||
</svg> | ||
)} | ||
{!isLoading && ( | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
ariaHidden="true" | ||
focusable="false" | ||
role="presentation" | ||
className="icon icon-minus" | ||
fill="none" | ||
viewBox="0 0 10 2" | ||
> | ||
<path | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="M.5 1C.5.7.7.5 1 .5h8a.5.5 0 110 1H1A.5.5 0 01.5 1z" | ||
fill="currentColor" | ||
/> | ||
</svg> | ||
)} | ||
</button> | ||
<input type="text" value={quantity} /> | ||
<button | ||
className="flex justify-center items-center" | ||
onClick={() => updateQuantity(quantity + 1)} | ||
disabled={isLoading} | ||
type="button" | ||
> | ||
{isLoading && ( | ||
<svg | ||
ariaHidden="true" | ||
focusable="false" | ||
role="presentation" | ||
className="spinner" | ||
viewBox="0 0 66 66" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<circle | ||
className="path" | ||
fill="none" | ||
strokeWidth="6" | ||
cx="33" | ||
cy="33" | ||
r="30" | ||
/> | ||
</svg> | ||
)} | ||
{!isLoading && ( | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
ariaHidden="true" | ||
focusable="false" | ||
role="presentation" | ||
className="icon icon-plus" | ||
fill="none" | ||
viewBox="0 0 10 10" | ||
> | ||
<path | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="M1 4.51a.5.5 0 000 1h3.5l.01 3.5a.5.5 0 001-.01V5.5l3.5-.01a.5.5 0 00-.01-1H5.5L5.49.99a.5.5 0 00-1 .01v3.5l-3.5.01H1z" | ||
fill="currentColor" | ||
/> | ||
</svg> | ||
)} | ||
</button> | ||
</div> | ||
); | ||
} | ||
|
||
Quantity.propTypes = { | ||
qty: PropTypes.number.isRequired, | ||
api: PropTypes.string.isRequired | ||
}; |
49 changes: 49 additions & 0 deletions
49
packages/evershop/src/modules/checkout/api/updateCartItemQty/[bodyParser]updateQty.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
const { | ||
INVALID_PAYLOAD, | ||
INTERNAL_SERVER_ERROR, | ||
OK | ||
} = require('@evershop/evershop/src/lib/util/httpStatus'); | ||
const { | ||
translate | ||
} = require('@evershop/evershop/src/lib/locale/translate/translate'); | ||
const { error } = require('@evershop/evershop/src/lib/log/logger'); | ||
const { getCartByUUID } = require('../../services/getCartByUUID'); | ||
const { saveCart } = require('../../services/saveCart'); | ||
|
||
module.exports = async (request, response, delegate, next) => { | ||
try { | ||
const { cart_id, item_id } = request.params; | ||
const cart = await getCartByUUID(cart_id); | ||
if (!cart) { | ||
response.status(INVALID_PAYLOAD); | ||
response.json({ | ||
error: { | ||
message: translate('Invalid cart'), | ||
status: INVALID_PAYLOAD | ||
} | ||
}); | ||
return; | ||
} | ||
const { action, qty } = request.body; | ||
const item = await cart.updateItemQty(item_id, qty, action); | ||
await saveCart(cart); | ||
response.status(OK); | ||
response.$body = { | ||
data: { | ||
item: item.export(), | ||
count: cart.getItems().length, | ||
cartId: cart.getData('uuid') | ||
} | ||
}; | ||
next(); | ||
} catch (err) { | ||
error(err); | ||
response.status(INTERNAL_SERVER_ERROR); | ||
response.json({ | ||
error: { | ||
status: INTERNAL_SERVER_ERROR, | ||
message: err.message | ||
} | ||
}); | ||
} | ||
}; |
5 changes: 5 additions & 0 deletions
5
packages/evershop/src/modules/checkout/api/updateCartItemQty/[context]bodyParser[auth].js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const bodyParser = require('body-parser'); | ||
|
||
module.exports = (request, response, delegate, next) => { | ||
bodyParser.json({ inflate: false })(request, response, next); | ||
}; |
21 changes: 21 additions & 0 deletions
21
packages/evershop/src/modules/checkout/api/updateCartItemQty/payloadSchema.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"type": "object", | ||
"properties": { | ||
"action": { | ||
"type": "string", | ||
"enum": ["increase", "decrease"] | ||
}, | ||
"qty": { | ||
"type": ["string", "integer"], | ||
"pattern": "^[1-9][0-9]*$" | ||
} | ||
}, | ||
"required": ["action", "qty"], | ||
"additionalProperties": true, | ||
"errorMessage": { | ||
"properties": { | ||
"action": "Action is required. It must be either 'increase' or 'decrease'", | ||
"qty": "Qty is invalid" | ||
} | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
packages/evershop/src/modules/checkout/api/updateCartItemQty/route.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"methods": ["PATCH"], | ||
"path": "/cart/:cart_id/items/:item_id", | ||
"access": "public" | ||
} |
5 changes: 5 additions & 0 deletions
5
...ages/evershop/src/modules/checkout/api/updateMineCartItemQty/[context]bodyParser[auth].js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const bodyParser = require('body-parser'); | ||
|
||
module.exports = (request, response, delegate, next) => { | ||
bodyParser.json({ inflate: false })(request, response, next); | ||
}; |
51 changes: 51 additions & 0 deletions
51
...s/evershop/src/modules/checkout/api/updateMineCartItemQty/[detectCurrentCart]updateQty.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
const { | ||
INVALID_PAYLOAD, | ||
INTERNAL_SERVER_ERROR, | ||
OK | ||
} = require('@evershop/evershop/src/lib/util/httpStatus'); | ||
const { | ||
translate | ||
} = require('@evershop/evershop/src/lib/locale/translate/translate'); | ||
const { error } = require('@evershop/evershop/src/lib/log/logger'); | ||
const { getCartByUUID } = require('../../services/getCartByUUID'); | ||
const { saveCart } = require('../../services/saveCart'); | ||
const { getContextValue } = require('../../../graphql/services/contextHelper'); | ||
|
||
module.exports = async (request, response, delegate, next) => { | ||
try { | ||
const { item_id } = request.params; | ||
const cartId = getContextValue(request, 'cartId'); | ||
const cart = await getCartByUUID(cartId); | ||
if (!cart) { | ||
response.status(INVALID_PAYLOAD); | ||
response.json({ | ||
error: { | ||
message: translate('Invalid cart'), | ||
status: INVALID_PAYLOAD | ||
} | ||
}); | ||
return; | ||
} | ||
const { action, qty } = request.body; | ||
const item = await cart.updateItemQty(item_id, qty, action); | ||
await saveCart(cart); | ||
response.status(OK); | ||
response.$body = { | ||
data: { | ||
item: item.export(), | ||
count: cart.getItems().length, | ||
cartId: cart.getData('uuid') | ||
} | ||
}; | ||
next(); | ||
} catch (err) { | ||
error(err); | ||
response.status(INTERNAL_SERVER_ERROR); | ||
response.json({ | ||
error: { | ||
status: INTERNAL_SERVER_ERROR, | ||
message: err.message | ||
} | ||
}); | ||
} | ||
}; |
Oops, something went wrong.