[wip] 🔥 Integrate Swell into the shop
Create a custom and internal API for fetching and updating content to Swell Admin API (using swell-node)
This commit is contained in:
@@ -4,8 +4,10 @@
|
||||
import Button from '$components/atoms/Button.svelte'
|
||||
import Image from '$components/atoms/Image.svelte'
|
||||
import Carousel from '$components/organisms/Carousel.svelte'
|
||||
import { cartData, cartId } from '$utils/store';
|
||||
|
||||
export let product: any
|
||||
export let productShop: any
|
||||
|
||||
|
||||
/**
|
||||
@@ -51,6 +53,33 @@
|
||||
ratio: 0.68,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
/**
|
||||
* Handling add to cart
|
||||
*/
|
||||
const addToCart = async () => {
|
||||
// const addedReturn = await swell.cart.addItem({
|
||||
// product_id: product.product_id,
|
||||
// quantity: 1,
|
||||
// })
|
||||
|
||||
const addedReturn = await fetch('/api/swell', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
action: 'addToCart',
|
||||
cartId: $cartId,
|
||||
productId: product.product_id,
|
||||
quantity: 1,
|
||||
})
|
||||
})
|
||||
|
||||
if (addedReturn.ok) {
|
||||
const newCart = await addedReturn.json()
|
||||
$cartData = newCart
|
||||
console.log('Show mini product added to cart')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="poster-layout grid">
|
||||
@@ -62,11 +91,12 @@
|
||||
<div class="poster-layout__info">
|
||||
<dl>
|
||||
<dt>{capitalizeFirstLetter(product.type)}</dt>
|
||||
<dd>{product.name} – 30€</dd>
|
||||
<dd>{productShop.name} – {productShop.price}€</dd>
|
||||
</dl>
|
||||
<Button
|
||||
text="Add to cart"
|
||||
color="pinklight"
|
||||
on:click={addToCart}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
49
src/components/molecules/CartItem.svelte
Normal file
49
src/components/molecules/CartItem.svelte
Normal file
@@ -0,0 +1,49 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let item: any
|
||||
|
||||
// console.log(item)
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
||||
// When changing item quantity
|
||||
const updateQuantity = ({ target: { value }}: any) => {
|
||||
dispatch('updatedQuantity', {
|
||||
id: item.id,
|
||||
quantity: Number(value)
|
||||
})
|
||||
}
|
||||
|
||||
// When removing item
|
||||
const removeItem = () => {
|
||||
dispatch('removed', item.id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<aside class="cart-item shadow-small">
|
||||
<div class="cart-item__left">
|
||||
<img
|
||||
src={item.product.images[0].file.url}
|
||||
width={200}
|
||||
height={300}
|
||||
alt={item.product.name}
|
||||
>
|
||||
</div>
|
||||
<div class="cart-item__right">
|
||||
<h3>Poster</h3>
|
||||
<p>{item.product.name} – {item.price_total}€</p>
|
||||
|
||||
{#if item && item.product}
|
||||
<div class="select">
|
||||
<select on:change={updateQuantity}>
|
||||
{#each Array(5) as _, index}
|
||||
<option value={index + 1} selected={item.quantity - 1 === index}>{index + 1}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<button on:click={removeItem}>Remove</button>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -1,31 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
// Components
|
||||
import Button from '$components/atoms/Button.svelte'
|
||||
import Image from '$components/atoms/Image.svelte'
|
||||
import Select from './Select.svelte'
|
||||
|
||||
const { locations, shop } = getContext('global')
|
||||
|
||||
</script>
|
||||
|
||||
<aside class="poster-cart">
|
||||
<div class="poster-cart__left">
|
||||
<img src="/images/issue-1.jpg" alt="">
|
||||
</div>
|
||||
<div class="poster-cart__right">
|
||||
<h3>Poster</h3>
|
||||
<p>Houses Of Melbourne – 30€</p>
|
||||
<Select
|
||||
name="quantity" id="filter_country"
|
||||
options={[
|
||||
{
|
||||
value: '1',
|
||||
name: '1',
|
||||
default: true,
|
||||
selected: true,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -1,49 +1,151 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import { fade, fly } from 'svelte/transition'
|
||||
import { cartOpen } from '$utils/store'
|
||||
import { quartOut } from 'svelte/easing'
|
||||
import { cartOpen, cartId, cartData, cartAmount } from '$utils/store'
|
||||
// Components
|
||||
import Button from '$components/atoms/Button.svelte'
|
||||
import PosterCart from '$components/molecules/PosterCart.svelte'
|
||||
import CartItem from '$components/molecules/CartItem.svelte'
|
||||
|
||||
let open = false
|
||||
|
||||
|
||||
onMount(async () => {
|
||||
// Cart already exists
|
||||
if ($cartId && $cartId !== 'null') {
|
||||
// Fetch stored cart
|
||||
const existantCart = await fetch('/api/swell', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
action: 'fetchCart',
|
||||
cartId: $cartId
|
||||
})
|
||||
})
|
||||
if (existantCart.ok) {
|
||||
const cart = await existantCart.json()
|
||||
$cartId = cart.id
|
||||
$cartData = cart
|
||||
console.log('fetched existant cart:', $cartId, $cartData)
|
||||
}
|
||||
}
|
||||
// Cart doesn't exists
|
||||
else {
|
||||
// Create a new cart and store it
|
||||
const newCart = await fetch('/api/swell', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
action: 'createCart'
|
||||
})
|
||||
})
|
||||
if (newCart.ok) {
|
||||
const cart = await newCart.json()
|
||||
$cartId = cart.id
|
||||
$cartData = cart
|
||||
console.log('new cart:', localStorage.getItem('cartId'))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// Closing the cart
|
||||
const handleCloseCart = () => {
|
||||
$cartOpen = false
|
||||
}
|
||||
|
||||
// Item quantity changed
|
||||
const changedQuantity = async ({ detail: { id, quantity } }) => {
|
||||
// Update item in cart
|
||||
// const updatedCart = await swell.cart.updateItem(id, {
|
||||
// quantity
|
||||
// })
|
||||
// if (updatedCart) {
|
||||
// $cartData = updatedCart
|
||||
// }
|
||||
|
||||
const updatedCart = await fetch('/api/swell', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
action: 'updateCartItem',
|
||||
cartId: $cartId,
|
||||
productId: id,
|
||||
quantity: quantity
|
||||
})
|
||||
})
|
||||
|
||||
if (updatedCart.ok) {
|
||||
// const cart = await updatedCart.json()
|
||||
// $cartData = cart
|
||||
// console.log('updated cart:', $cartData.items)
|
||||
}
|
||||
}
|
||||
|
||||
// Item removed
|
||||
const removedItem = async ({ detail: id }) => {
|
||||
// Remove item from cart
|
||||
// const removedItem = await swell.cart.removeItem(id)
|
||||
// if (removedItem) {
|
||||
// $cartData = removedItem
|
||||
// }
|
||||
}
|
||||
</script>
|
||||
|
||||
<aside class="cart"
|
||||
transition:fly={{ x: 48, duration: 600, easing: quartOut }}
|
||||
>
|
||||
<header class="cart__heading">
|
||||
<h2>Cart</h2>
|
||||
<button class="text-label" on:click={handleCloseCart}>Close</button>
|
||||
</header>
|
||||
{#if $cartOpen}
|
||||
<aside class="cart shadow-box-dark"
|
||||
transition:fly={{ x: 48, duration: 600, easing: quartOut }}
|
||||
>
|
||||
<header class="cart__heading">
|
||||
<h2>Cart</h2>
|
||||
<button class="text-label" on:click={handleCloseCart}>Close</button>
|
||||
</header>
|
||||
|
||||
<div class="cart__content">
|
||||
<PosterCart />
|
||||
<PosterCart />
|
||||
</div>
|
||||
<div class="cart__content">
|
||||
{#if $cartAmount > 0}
|
||||
{#each $cartData.items as item}
|
||||
<CartItem {item}
|
||||
on:updatedQuantity={changedQuantity}
|
||||
on:removed={removedItem}
|
||||
/>
|
||||
{/each}
|
||||
{:else}
|
||||
<div class="cart__message shadow-small">
|
||||
<div class="icon">
|
||||
|
||||
<footer class="cart__total">
|
||||
<div class="cart__total--sum">
|
||||
<h3>Total</h3>
|
||||
<span>3 articles</span>
|
||||
<p>90€</p>
|
||||
</div>
|
||||
<p>Your cart is empty</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="cart__total--checkout">
|
||||
<p>Shipping will be calculated from the delivery address during the checkout process</p>
|
||||
<Button
|
||||
text="Checkout"
|
||||
color="pink"
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
</footer>
|
||||
</aside>
|
||||
|
||||
<div class="cart-overlay"
|
||||
transition:fade={{ duration: 600, easing: quartOut }}
|
||||
on:click={handleCloseCart}
|
||||
/>
|
||||
<footer class="cart__total">
|
||||
<div class="cart__total--sum">
|
||||
<h3>Total</h3>
|
||||
{#if $cartData}
|
||||
<span>{$cartAmount} item{$cartAmount > 1 ? 's' : ''}</span>
|
||||
<p>{$cartData.sub_total ? $cartData.sub_total : 0}€</p>
|
||||
{:else}
|
||||
<span>0 item</span>
|
||||
<p>0€</p>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="cart__total--checkout">
|
||||
<p>Shipping will be calculated from the delivery address during the checkout process</p>
|
||||
{#if $cartData && $cartAmount > 0 && $cartData.checkout_url}
|
||||
<div transition:fly={{ y: 8, duration: 600, easing: quartOut }}>
|
||||
<Button
|
||||
url={$cartData && $cartData.checkout_url}
|
||||
text="Checkout"
|
||||
color="pink"
|
||||
size="small"
|
||||
disabled={!$cartData}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</footer>
|
||||
</aside>
|
||||
|
||||
<div class="cart-overlay"
|
||||
transition:fade={{ duration: 600, easing: quartOut }}
|
||||
on:click={handleCloseCart}
|
||||
/>
|
||||
{/if}
|
||||
Reference in New Issue
Block a user