Show a notification when adding a product to Cart

This commit is contained in:
2021-11-07 20:18:19 +01:00
parent 03cc79da69
commit e1c259164f
7 changed files with 92 additions and 24 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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
*/ */

View 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))
}

View File

@@ -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([])