🚧 Switch to swell-js to handle Shop cart
swell-node was relying too much on Node packages like crypto or events to be used with Cloudflare Pages or Vercel Edge Functions
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { cartId } from '$utils/stores/shop'
|
||||
import { addToCart } from '$utils/functions/shop'
|
||||
import { capitalizeFirstLetter } from '$utils/functions'
|
||||
// Components
|
||||
@@ -83,7 +82,7 @@
|
||||
text={hasStock ? 'Add to cart' : 'Sold out'}
|
||||
color="pinklight"
|
||||
disabled={!hasStock}
|
||||
on:click={() => addToCart($cartId, shopProduct)}
|
||||
on:click={() => addToCart(shopProduct)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { cartId } from '$utils/stores/shop'
|
||||
import { addToCart } from '$utils/functions/shop'
|
||||
import { smoothScroll } from '$utils/functions'
|
||||
// Components
|
||||
@@ -43,7 +42,7 @@
|
||||
size="xsmall"
|
||||
text="Add to cart"
|
||||
color="pink"
|
||||
on:click={() => addToCart($cartId, product)}
|
||||
on:click={() => addToCart(product)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -6,7 +6,8 @@
|
||||
import { onMount } from 'svelte'
|
||||
import { fade, fly } from 'svelte/transition'
|
||||
import { quartOut } from 'svelte/easing'
|
||||
import { cartOpen, cartId, cartData, cartAmount, cartIsUpdating } from '$utils/stores/shop'
|
||||
import { cartOpen, cartData, cartAmount, cartIsUpdating } from '$utils/stores/shop'
|
||||
import { initSwell, getCart, updateCartItem, removeCartItem } from '$utils/functions/shop'
|
||||
// Components
|
||||
import Button from '$components/atoms/Button.svelte'
|
||||
import Icon from '$components/atoms/Icon.svelte'
|
||||
@@ -14,62 +15,6 @@
|
||||
import ShopLocationSwitcher from '$components/molecules/ShopLocationSwitcher.svelte'
|
||||
|
||||
|
||||
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()
|
||||
|
||||
// Cart is active / has not been ordered
|
||||
if (cart.active || !cart.order_id) {
|
||||
// Keep current cart
|
||||
$cartId = cart.id
|
||||
$cartData = cart
|
||||
return
|
||||
}
|
||||
|
||||
// Cart is inactive / has been ordered
|
||||
const newCart = await fetch('/api/swell', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
action: 'createCart'
|
||||
})
|
||||
})
|
||||
if (newCart.ok) {
|
||||
const cart = await newCart.json()
|
||||
// Save new cart
|
||||
$cartId = cart.id
|
||||
$cartData = cart
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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('Created new cart:', localStorage.getItem('cartId'))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// Closing the cart
|
||||
const handleCloseCart = () => {
|
||||
$cartOpen = false
|
||||
@@ -80,19 +25,11 @@
|
||||
// Cart is now updating
|
||||
$cartIsUpdating = true
|
||||
|
||||
// Get updated cart
|
||||
const updatedCart = await fetch('/api/swell', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
action: 'updateCartItem',
|
||||
cartId: $cartId,
|
||||
productId: id,
|
||||
quantity,
|
||||
})
|
||||
})
|
||||
if (updatedCart.ok) {
|
||||
const cart = await updatedCart.json()
|
||||
$cartData = cart
|
||||
// Update cart item
|
||||
const updatedCart = await updateCartItem(id, quantity)
|
||||
if (updatedCart) {
|
||||
// Store new cart data
|
||||
$cartData = updatedCart
|
||||
// Cart is updated
|
||||
$cartIsUpdating = false
|
||||
}
|
||||
@@ -104,28 +41,31 @@
|
||||
$cartIsUpdating = true
|
||||
|
||||
// Remove item from cart
|
||||
const updatedCart = await fetch('/api/swell', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
action: 'removeCartItem',
|
||||
cartId: $cartId,
|
||||
productId: id,
|
||||
})
|
||||
})
|
||||
if (updatedCart.ok) {
|
||||
const cart = await updatedCart.json()
|
||||
$cartData = cart
|
||||
const updatedCart = await removeCartItem(id)
|
||||
if (updatedCart) {
|
||||
// Store new cart data
|
||||
$cartData = updatedCart
|
||||
// Cart is updated
|
||||
$cartIsUpdating = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onMount(async () => {
|
||||
// Init Swell
|
||||
initSwell()
|
||||
|
||||
// Fetch cart
|
||||
const cart = await getCart()
|
||||
if (cart) {
|
||||
// Store cart data
|
||||
$cartData = cart
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if $cartOpen}
|
||||
<div class="cart-switcher"
|
||||
in:fly={{ y: -24, duration: 1000, easing: quartOut }}
|
||||
out:fly={{ y: -24, duration: 1000, easing: quartOut }}
|
||||
>
|
||||
<div class="cart-switcher" transition:fly={{ y: -24, duration: 1000, easing: quartOut }}>
|
||||
<ShopLocationSwitcher isOver={true} />
|
||||
</div>
|
||||
|
||||
@@ -155,10 +95,10 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !$cartData || $cartIsUpdating}
|
||||
{#if (!$cartData && $cartData !== 'null') || $cartIsUpdating}
|
||||
<div class="cart__update"
|
||||
in:fly={{ y: -4, duration: 600, easing: quartOut }}
|
||||
out:fly={{ y: 4, duration: 600, easing: quartOut }}
|
||||
in:fly={{ y: 8, duration: 600, easing: quartOut }}
|
||||
out:fly={{ y: -8, duration: 600, easing: quartOut }}
|
||||
>
|
||||
<p>Updating…</p>
|
||||
</div>
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { RequestHandler } from './$types'
|
||||
import * as swell from '$utils/functions/swell'
|
||||
|
||||
|
||||
export const POST: RequestHandler = async ({ request }) => {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const { action, cartId, productId } = body
|
||||
let result = {}
|
||||
|
||||
if (body) {
|
||||
switch (action) {
|
||||
case 'getProducts': {
|
||||
result = await swell.getProducts(body.category)
|
||||
break
|
||||
}
|
||||
case 'getProduct': {
|
||||
result = await swell.getProduct(productId)
|
||||
break
|
||||
}
|
||||
case 'createCart': {
|
||||
result = await swell.createCart()
|
||||
break
|
||||
}
|
||||
case 'fetchCart': {
|
||||
result = await swell.fetchCart(cartId)
|
||||
break
|
||||
}
|
||||
case 'addToCart': {
|
||||
result = await swell.addToCart(cartId, productId, body.quantity)
|
||||
break
|
||||
}
|
||||
case 'updateCartItem': {
|
||||
result = await swell.updateCartItem(cartId, productId, body.quantity)
|
||||
break
|
||||
}
|
||||
case 'removeCartItem': {
|
||||
result = await swell.removeCartItem(cartId, productId)
|
||||
break
|
||||
}
|
||||
default: break
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
...result
|
||||
}))
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err.message || `Can't fetch query`)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
import { getProducts } from '$utils/functions/swell'
|
||||
import { getProducts } from '$utils/functions/shop'
|
||||
|
||||
export const load: PageServerLoad = async () => {
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
import { getProduct } from '$utils/functions/swell'
|
||||
import { getProduct } from '$utils/functions/shop'
|
||||
import { getRandomItem } from '$utils/functions'
|
||||
|
||||
export const load: PageServerLoad = async ({}) => {
|
||||
@@ -36,7 +36,7 @@ export const load: PageServerLoad = async ({}) => {
|
||||
}`)
|
||||
|
||||
if (data) {
|
||||
const randomPoster = getRandomItem(data.data.posters)
|
||||
const randomPoster: any = getRandomItem(data.data.posters)
|
||||
|
||||
// Fetch Swell API for product
|
||||
const shopProduct = await getProduct(randomPoster.product_id)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
import { getProduct } from '$utils/functions/swell'
|
||||
import { getProduct } from '$utils/functions/shop'
|
||||
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
try {
|
||||
|
||||
@@ -1,34 +1,99 @@
|
||||
import swell from 'swell-js'
|
||||
import { addNotification } from '$utils/functions/notifications'
|
||||
import { cartData } from '$utils/stores/shop'
|
||||
import { PUBLIC_SWELL_STORE_ID, PUBLIC_SWELL_API_PUBLIC_TOKEN } from '$env/static/public'
|
||||
|
||||
|
||||
// Init Swell
|
||||
export const initSwell = () => {
|
||||
swell.init(PUBLIC_SWELL_STORE_ID, PUBLIC_SWELL_API_PUBLIC_TOKEN)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get current cart
|
||||
*/
|
||||
export const getCart = async () => {
|
||||
const cart = await swell.cart.get()
|
||||
|
||||
if (cart) {
|
||||
return cart
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a product to a cart
|
||||
*/
|
||||
export const addToCart = async (cartId: string, product: any, quantity: number = 1) => {
|
||||
if (cartId && cartId !== 'null') {
|
||||
const updatedCart = await fetch('/api/swell', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
action: 'addToCart',
|
||||
cartId,
|
||||
productId: product.id,
|
||||
quantity,
|
||||
})
|
||||
export const addToCart = async (product: any, quantity: number = 1) => {
|
||||
const updatedCart = await swell.cart.addItem({
|
||||
product_id: product.id,
|
||||
quantity,
|
||||
})
|
||||
|
||||
if (updatedCart) {
|
||||
// Update cart data
|
||||
cartData.set(updatedCart)
|
||||
|
||||
// Show notification
|
||||
addNotification({
|
||||
title: 'Added to cart',
|
||||
name: `${product.name} - x1`,
|
||||
image: product.images[0].file.url,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (updatedCart.ok) {
|
||||
const newCart = await updatedCart.json()
|
||||
cartData.set(newCart)
|
||||
/**
|
||||
* Update Cart item
|
||||
*/
|
||||
export const updateCartItem = async (productId: string, quantity: number) => {
|
||||
const updatedCart = await swell.cart.updateItem(productId, {
|
||||
quantity,
|
||||
})
|
||||
|
||||
// Show notification
|
||||
addNotification({
|
||||
title: 'Added to cart',
|
||||
name: `${product.name} - x1`,
|
||||
image: product.images[0].file.url,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
console.log('No active cart')
|
||||
if (updatedCart) {
|
||||
return updatedCart
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Cart item
|
||||
*/
|
||||
export const removeCartItem = async (productId: string) => {
|
||||
const updatedCart = await swell.cart.removeItem(productId)
|
||||
|
||||
if (updatedCart) {
|
||||
return updatedCart
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch products
|
||||
*/
|
||||
export const getProducts = async (category?: string, limit: number = 25, page: number = 1) => {
|
||||
const products = await swell.products.list({
|
||||
where: {
|
||||
active: true,
|
||||
},
|
||||
category,
|
||||
limit,
|
||||
page
|
||||
})
|
||||
|
||||
if (products) {
|
||||
return products
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a product
|
||||
*/
|
||||
export const getProduct = async (id: string) => {
|
||||
const product = await swell.products.get(id)
|
||||
|
||||
if (product) {
|
||||
return product
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
import swell from 'swell-node'
|
||||
import { SWELL_API_TOKEN, SWELL_STORE_ID } from '$env/static/private'
|
||||
|
||||
// Init Swell
|
||||
swell.init(SWELL_STORE_ID, SWELL_API_TOKEN)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch products
|
||||
*/
|
||||
export const getProducts = async (category?: string, limit: number = 25, page: number = 1) => {
|
||||
const products = await swell.get('/products', {
|
||||
where: {
|
||||
active: true,
|
||||
},
|
||||
category,
|
||||
limit,
|
||||
page
|
||||
})
|
||||
|
||||
if (products) {
|
||||
return products
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a product
|
||||
*/
|
||||
export const getProduct = async (id: string) => {
|
||||
const product = await swell.get('/products/{id}', {
|
||||
id
|
||||
})
|
||||
|
||||
if (product) {
|
||||
return product
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a cart
|
||||
*/
|
||||
export const createCart = async () => {
|
||||
const cart = await swell.post('/carts')
|
||||
|
||||
if (cart) {
|
||||
return cart
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve cart
|
||||
*/
|
||||
export const fetchCart = async (id: string) => {
|
||||
const cart = await swell.get('/carts/{id}', {
|
||||
id,
|
||||
expand: [
|
||||
'items.product',
|
||||
'items.variant',
|
||||
]
|
||||
})
|
||||
|
||||
if (cart) {
|
||||
return cart
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add product to cart
|
||||
*/
|
||||
export const addToCart = async (cartId: string, productId: string, quantity: number) => {
|
||||
// Fetch current cart data
|
||||
const currentCart = await fetchCart(cartId)
|
||||
|
||||
// Updated cart with new items
|
||||
const updatedCart = await swell.put('/carts/{id}', {
|
||||
id: cartId,
|
||||
items: [
|
||||
...currentCart.items || [],
|
||||
{
|
||||
product_id: productId,
|
||||
quantity,
|
||||
}
|
||||
],
|
||||
})
|
||||
if (updatedCart) {
|
||||
// Fetch latest cart with updates
|
||||
const cart = await fetchCart(cartId)
|
||||
if (cart) {
|
||||
return cart
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update cart item
|
||||
*/
|
||||
export const updateCartItem = async (cartId: string, productId: string, quantity: number) => {
|
||||
// Fetch current cart data
|
||||
const currentCart = await fetchCart(cartId)
|
||||
|
||||
// Updated items with replacing new item quantity
|
||||
const updatedCartItems = currentCart.items.map((item: any) => {
|
||||
// Replace item quantity with selected one
|
||||
if (item.id === productId) {
|
||||
item.quantity = quantity
|
||||
}
|
||||
return item
|
||||
})
|
||||
|
||||
const updatedCart = await swell.put('/carts/{id}', {
|
||||
id: cartId,
|
||||
$set: {
|
||||
items: updatedCartItems,
|
||||
}
|
||||
})
|
||||
if (updatedCart) {
|
||||
// Fetch latest cart with updates
|
||||
const cart = await fetchCart(cartId)
|
||||
if (cart) {
|
||||
return cart
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove cart item
|
||||
*/
|
||||
export const removeCartItem = async (cartId: string, productId: string) => {
|
||||
// Fetch current cart data
|
||||
const currentCart = await fetchCart(cartId)
|
||||
|
||||
// Updated items and remove selected item
|
||||
const updatedCartItems = [...currentCart.items.filter((item: any) => {
|
||||
return item.id !== productId
|
||||
})]
|
||||
|
||||
const updatedCart = await swell.put('/carts/{id}', {
|
||||
id: cartId,
|
||||
$set: {
|
||||
items: updatedCartItems,
|
||||
}
|
||||
})
|
||||
if (updatedCart) {
|
||||
// Fetch latest cart with updates
|
||||
const cart = await fetchCart(cartId)
|
||||
if (cart) {
|
||||
return cart
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,9 @@ import { writable, derived, type Writable, type Readable } from 'svelte/store'
|
||||
*/
|
||||
export const shopCurrentProductSlug: Writable<string> = writable(null)
|
||||
|
||||
/** Notifications */
|
||||
export const cartNotifications: Writable<any[]> = writable([])
|
||||
|
||||
|
||||
/**
|
||||
* Cart
|
||||
@@ -13,17 +16,6 @@ export const shopCurrentProductSlug: Writable<string> = writable(null)
|
||||
/** Cart open state */
|
||||
export const cartOpen: Writable<boolean> = writable(false)
|
||||
|
||||
/** Cart open state */
|
||||
export const cartId: Writable<string> = writable(null)
|
||||
|
||||
// Write to localStorage when changing cartId
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
const id = localStorage.getItem('cartId')
|
||||
id && cartId.set(id ? id : null)
|
||||
|
||||
cartId.subscribe(value => localStorage.setItem('cartId', value))
|
||||
}
|
||||
|
||||
/** Raw Cart data */
|
||||
export const cartData: Writable<any> = writable(null)
|
||||
|
||||
@@ -33,10 +25,4 @@ export const cartIsUpdating: Writable<boolean> = writable(false)
|
||||
/** Amount of products present in cart */
|
||||
export const cartAmount: Readable<number> = derived(cartData, ($cart) => {
|
||||
return $cart && $cart.item_quantity > 0 ? $cart.item_quantity : 0
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Notifications
|
||||
*/
|
||||
export const cartNotifications: Writable<any[]> = writable([])
|
||||
})
|
||||
Reference in New Issue
Block a user