diff --git a/src/components/ItemList.svelte b/src/components/ItemList.svelte index 2311f4440e78af3422792bb1844ac0c2112704b4..bc330365f6dc2b982e8290f2cac8422c3a93399a 100644 --- a/src/components/ItemList.svelte +++ b/src/components/ItemList.svelte @@ -3,9 +3,9 @@ import ItemIcon from "./ItemIcon.svelte"; export let items; - export let priceModifier; export let onClick; export let inView; + export let cartWorth, balance, cantGoNegative; let element; </script> @@ -34,17 +34,23 @@ .item__premium { font-size: .8em; } + + .disabled { + opacity: 0.5; + cursor: not-allowed; + } </style> <IntersectionObserver {element} bind:intersecting={inView} rootMargin="0px 0px -50% 0px"> <div class="available-items" bind:this={element}> {#each items as item} - <div class="item" on:click={()=>onClick(item)}> + {@const disabled = cantGoNegative && item.price+item.premium>balance-cartWorth} + <div class="item" class:disabled on:click={()=>onClick(item)}> <ItemIcon icon={item.image} name={item.name} size="100%" containerStyle="margin-bottom:.5em" /> <div class="item__name">{item.name}</div> - <div class="item__price">{(priceModifier(item.price)/100).toFixed(2)}€</div> + <div class="item__price">{(item.price/100).toFixed(2)}€</div> {#if item.premium} - <div class="item__premium">+{(priceModifier(item.premium)/100).toFixed(2)}€</div> + <div class="item__premium">+{(item.premium/100).toFixed(2)}€</div> {/if} </div> {/each} diff --git a/src/lib/flags.js b/src/lib/flags.js index a9b331f2168188899186790b39128a5d0b3f74e8..0edc7617ee560219f088c8769e832840ce149840 100644 --- a/src/lib/flags.js +++ b/src/lib/flags.js @@ -3,4 +3,5 @@ export const Flags = { NO_PREMIUM: 1<<1, NO_BALANCE: 1<<2, CANT_TRANSFER: 1<<3, + CANT_GO_NEGATIVE: 1<<4, }; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 65e13044d123ed99d565fc0b7ed0e21c37fe3a16..80efc51a30c09cb78aacddafd4177cfe73df963a 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -23,13 +23,14 @@ let isFetchingBuy = false; let cart = []; - $: cartItems = cart.map(item => { + function getItemFromRaw(item){ if(item.type === "article") return Object.assign({type: "article"}, items.find(i => i.code === item.code)); else if(item.type === "custom") return {type: "custom", name: "Manuell", price: item.price, premium: 0, code: item.code}; else if(item.type === "pfand") return {type: "pfand", name: "Pfand", price: item.price, premium: 0, code: item.code}; else if(item.type === "voucher") return {type: "voucher", name: "Gutschein", price: item.price, premium: 0, code: item.code}; else return addMessage(MessageType.ERROR, "Unbekannter Artikeltyp: " + item.type); - }); + } + $: cartItems = cart.map(item => getItemFromRaw(item)); function emptyCart(){ if(isFetchingBuy) return addMessage(MessageType.ERROR, "Der Kauf wird gerade ausgeführt. Bitte warten..."); cart = []; @@ -37,6 +38,8 @@ } function addToCart(item){ if(isFetchingBuy) return addMessage(MessageType.ERROR, "Der Kauf wird gerade ausgeführt. Bitte warten..."); + let article = getItemFromRaw(item); + if(cartItems.reduce((acc, item)=>acc+item.price+item.premium, 0) + article.price + article.premium > data.user.balance && data.user.perms & Flags.CANT_GO_NEGATIVE) return addMessage(MessageType.WARN, "Nicht genügend Guthaben"); cart = [...cart, item]; resetTimer(); } @@ -313,7 +316,7 @@ {#each categories as category, i} <h2 bind:this={categoryElements[i].element}>{category.name}</h2> <div class="item-list"> - <ItemList items={items.filter(item=>item.categoryId===category.id&&item.show)} onClick={item=>addToCart({type: "article", code: item.code})} priceModifier={x=>x} bind:inView={elementsInView[i]} /> + <ItemList items={items.filter(item=>item.categoryId===category.id&&item.show)} onClick={item=>addToCart({type: "article", code: item.code})} bind:inView={elementsInView[i]} cartWorth={cartItems.reduce((acc,item)=>acc+item.price+item.premium,0)} balance={data.user.balance} cantGoNegative={!!(data.user.perms&Flags.CANT_GO_NEGATIVE)} /> </div> {/each} </div> diff --git a/src/routes/api/[slug]/+server.js b/src/routes/api/[slug]/+server.js index 666681df16b25c9123b76c372802717e148d1c49..d172f416d9a3388d5ec5cb3fd8eef66147f5b0b2 100644 --- a/src/routes/api/[slug]/+server.js +++ b/src/routes/api/[slug]/+server.js @@ -41,6 +41,7 @@ export async function POST(event) { const priceModifier = getPriceModifier(user.balance, !!(user.perms & Flags.NO_PREMIUM)); if(!isValidCart(data.items, articles, data.vouchers, vouchers, priceModifier)) return new Response(JSON.stringify({message: "Invalid cart"}), {headers: {'content-type': 'application/json', 'status': 400}}); const items = [...data.items, ...data.vouchers.map(voucher => ({...voucher, code: Codes.Voucher}))]; + if(user.perms & Flags.CANT_GO_NEGATIVE && items.reduce((acc, item) => acc + item.price + item.premium, 0) > user.balance) return new Response(JSON.stringify({message: "Not enough balance"}), {headers: {'content-type': 'application/json', 'status': 400}}); const res = await buyArticles(user.id, user.card, items, data.vouchers, !!(user.perms & Flags.NO_BALANCE)); return new Response(JSON.stringify(res), {headers: {'content-type': 'application/json', 'status': 200}}); }catch(e){