✨ Show a notification when adding a product to Cart
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { capitalizeFirstLetter } from '$utils/functions'
|
import { capitalizeFirstLetter } from '$utils/functions'
|
||||||
|
import { cartId, cartData } from '$utils/store'
|
||||||
|
import { addNotification } from '$utils/notifications'
|
||||||
// Components
|
// Components
|
||||||
import Button from '$components/atoms/Button.svelte'
|
import Button from '$components/atoms/Button.svelte'
|
||||||
import Image from '$components/atoms/Image.svelte'
|
import Image from '$components/atoms/Image.svelte'
|
||||||
import Carousel from '$components/organisms/Carousel.svelte'
|
import Carousel from '$components/organisms/Carousel.svelte'
|
||||||
import { cartData, cartId } from '$utils/store';
|
|
||||||
|
|
||||||
export let product: any
|
export let product: any
|
||||||
export let productShop: any
|
export let productShop: any
|
||||||
@@ -59,12 +60,7 @@ import { cartData, cartId } from '$utils/store';
|
|||||||
* Handling add to cart
|
* Handling add to cart
|
||||||
*/
|
*/
|
||||||
const addToCart = async () => {
|
const addToCart = async () => {
|
||||||
// const addedReturn = await swell.cart.addItem({
|
const updatedCart = await fetch('/api/swell', {
|
||||||
// product_id: product.product_id,
|
|
||||||
// quantity: 1,
|
|
||||||
// })
|
|
||||||
|
|
||||||
const addedReturn = await fetch('/api/swell', {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
action: 'addToCart',
|
action: 'addToCart',
|
||||||
@@ -73,11 +69,16 @@ import { cartData, cartId } from '$utils/store';
|
|||||||
quantity: 1,
|
quantity: 1,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
if (updatedCart.ok) {
|
||||||
if (addedReturn.ok) {
|
const newCart = await updatedCart.json()
|
||||||
const newCart = await addedReturn.json()
|
|
||||||
$cartData = newCart
|
$cartData = newCart
|
||||||
console.log('Show mini product added to cart')
|
|
||||||
|
// Show notification
|
||||||
|
addNotification({
|
||||||
|
title: 'Added to cart',
|
||||||
|
name: `${productShop.name} - x1`,
|
||||||
|
image: productShop.images[0].file.url,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,19 +1,28 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext } from 'svelte'
|
import { fly } from 'svelte/transition'
|
||||||
// Components
|
import { quartOut } from 'svelte/easing'
|
||||||
import Button from '$components/atoms/Button.svelte'
|
import { cartOpen } from '$utils/store'
|
||||||
import Image from '$components/atoms/Image.svelte'
|
|
||||||
|
|
||||||
const { locations, shop } = getContext('global')
|
export let title: string
|
||||||
|
export let name: string
|
||||||
|
export let image: string
|
||||||
|
|
||||||
|
|
||||||
|
const closeNotification = () => {
|
||||||
|
// Open cart
|
||||||
|
$cartOpen = true
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<aside class="notification-cart shadow-small">
|
<div class="notification-cart shadow-small"
|
||||||
|
on:click={closeNotification}
|
||||||
|
transition:fly={{ y: 20, duration: 700, easing: quartOut }}
|
||||||
|
>
|
||||||
<div class="notification-cart__left">
|
<div class="notification-cart__left">
|
||||||
<img src="/images/issue-1.jpg" width={58} height={88} alt="">
|
<img src={image} width={58} height={88} alt={title}>
|
||||||
</div>
|
</div>
|
||||||
<div class="notification-cart__right">
|
<div class="notification-cart__right">
|
||||||
<h3>Added to cart</h3>
|
<h3>{title}</h3>
|
||||||
<p>Houses Of Melbourne</p>
|
<p>{name}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte'
|
import { onMount } from 'svelte'
|
||||||
|
import { cartNotifications } from '$utils/store'
|
||||||
// Components
|
// Components
|
||||||
import Metas from '$components/Metas.svelte'
|
import Metas from '$components/Metas.svelte'
|
||||||
import SiteTitle from '$components/atoms/SiteTitle.svelte'
|
import SiteTitle from '$components/atoms/SiteTitle.svelte'
|
||||||
@@ -105,7 +106,13 @@
|
|||||||
<ButtonCart />
|
<ButtonCart />
|
||||||
|
|
||||||
<div class="shop-location__notifications">
|
<div class="shop-location__notifications">
|
||||||
<NotificationCart />
|
{#each $cartNotifications as { id, title, name, image } (id)}
|
||||||
|
<NotificationCart
|
||||||
|
title={title}
|
||||||
|
name={name}
|
||||||
|
image={image}
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,11 @@
|
|||||||
// Visible state
|
// Visible state
|
||||||
&.is-visible {
|
&.is-visible {
|
||||||
transform: translate3d(0,0,0);
|
transform: translate3d(0,0,0);
|
||||||
|
|
||||||
|
.shop-location__notifications {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Left
|
// Left
|
||||||
@@ -93,6 +98,9 @@
|
|||||||
z-index: 100;
|
z-index: 100;
|
||||||
top: 72px;
|
top: 72px;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.7s var(--ease-quart);
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
&:not(:last-child) {
|
&:not(:last-child) {
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ export const clamp = (num: number, a: number, b: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a random element from an array
|
* Return a random element from an array
|
||||||
*/
|
*/
|
||||||
|
|||||||
39
src/utils/notifications.ts
Normal file
39
src/utils/notifications.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { cartNotifications } from './store'
|
||||||
|
|
||||||
|
interface Notification {
|
||||||
|
title: string
|
||||||
|
name: string
|
||||||
|
image: string
|
||||||
|
timeout?: number
|
||||||
|
id?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a notification
|
||||||
|
*/
|
||||||
|
export const addNotification = (notification: Notification) => {
|
||||||
|
const id = Math.floor(Math.random() * 10000)
|
||||||
|
|
||||||
|
// Add ID and default timeout
|
||||||
|
notification = {
|
||||||
|
id,
|
||||||
|
timeout: notification.timeout || 3000,
|
||||||
|
...notification,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the notifications to the top of the list of notificationss
|
||||||
|
cartNotifications.update((all) => [notification, ...all])
|
||||||
|
|
||||||
|
// If notification is dismissible, dismiss it after an amount of time (timeout)
|
||||||
|
if (notification.timeout) {
|
||||||
|
setTimeout(() => dismissNotification(id), notification.timeout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dismiss a notification
|
||||||
|
*/
|
||||||
|
export const dismissNotification = (id: number) => {
|
||||||
|
cartNotifications.update((all) => all.filter((t) => t.id !== id))
|
||||||
|
}
|
||||||
@@ -25,3 +25,8 @@ export const cartData = writable(null)
|
|||||||
export const cartAmount = derived(cartData, ($cart) => {
|
export const cartAmount = derived(cartData, ($cart) => {
|
||||||
return $cart && $cart.item_quantity > 0 ? $cart.item_quantity : 0
|
return $cart && $cart.item_quantity > 0 ? $cart.item_quantity : 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifications
|
||||||
|
*/
|
||||||
|
export const cartNotifications = writable([])
|
||||||
Reference in New Issue
Block a user