Skip to content

Commit 5e98b6b

Browse files
committed
chore(template): update cart behaviour
Signed-off-by: Frederik Bußmann <[email protected]>
1 parent d2c1aa3 commit 5e98b6b

File tree

6 files changed

+59
-18
lines changed

6 files changed

+59
-18
lines changed

.github/renovate.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@
88
"automerge": true,
99
"autodiscover": true,
1010
"rangeStrategy": "bump",
11-
"commitMessagePrefix": "chore:"
11+
"commitMessagePrefix": "chore:",
12+
"lockFileMaintenance": {
13+
"enabled": true
14+
}
1215
}

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
[![Github Actions][github-actions-src]][github-actions-href]
66
[![NPM version][npm-version-src]][npm-version-href]
7-
[![NPM downloads][npm-downloads-src]][npm-downloads-href]
87
[![NPM last update][npm-last-update-src]][npm-last-update-href]
98
[![License][license-src]][license-href]
109

@@ -390,9 +389,6 @@ Published under the [MIT License](https://github.com/nuxt-modules/shopify/tree/m
390389
[npm-version-src]: https://img.shields.io/npm/v/@nuxtjs/shopify/latest.svg?style=flat&colorA=18181B&colorB=31C553
391390
[npm-version-href]: https://npmjs.com/package/@nuxtjs/shopify
392391

393-
[npm-downloads-src]: https://img.shields.io/npm/dm/@nuxtjs/shopify.svg?style=flat&colorA=18181B&colorB=31C553
394-
[npm-downloads-href]: https://npmjs.com/package/@nuxtjs/shopify
395-
396392
[npm-last-update-src]: https://img.shields.io/npm/last-update/%40nuxtjs%2Fshopify.svg?style=flat&colorA=18181B&colorB=31C553
397393
[npm-last-update-href]: https://npmjs.com/package/@nuxtjs/shopify
398394

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<script setup lang="ts">
2+
import type { ButtonProps } from '#ui/types'
3+
4+
const props = defineProps<ButtonProps & {
5+
variantId: string
6+
quantity?: number
7+
}>()
8+
9+
const { add } = useCart()
10+
const { t } = useI18n()
11+
12+
const loading = ref(false)
13+
14+
const addToCart = async (variantId: string, quantity = 1) => {
15+
loading.value = true
16+
17+
add(variantId, quantity).then(() => loading.value = false)
18+
}
19+
</script>
20+
21+
<template>
22+
<UButton
23+
v-bind="props"
24+
:label="t('product.addToCart')"
25+
:ui="{
26+
trailingIcon: props.ui?.trailingIcon + (loading ? ' animate-spin' : ''),
27+
}"
28+
:disabled="props.disabled || loading"
29+
:trailing-icon="loading ? 'i-lucide-loader-circle' : 'i-lucide-shopping-cart'"
30+
@click="addToCart(props.variantId, props.quantity)"
31+
/>
32+
</template>

template/app/components/content/Product.vue

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ const props = defineProps<{
44
}>()
55
66
const { country, language } = useLocalization()
7-
const { add } = useCart()
8-
const { t } = useI18n()
97
108
const { data: product } = await useStorefrontData(`product-${props.handle}`, `#graphql
119
query FetchProduct($handle: String, $language: LanguageCode, $country: CountryCode)
@@ -79,14 +77,13 @@ const state = reactive({
7977
/>
8078
</UFormField>
8179

82-
<UButton
80+
<AddToCart
8381
v-if="state.selectedVariant"
84-
:label="t('product.addToCart')"
85-
trailing-icon="i-lucide-shopping-cart"
86-
size="xl"
82+
:variant-id="state.selectedVariant.id"
83+
:quantity="state.quantity"
8784
:ui="{ trailingIcon: 'size-5' }"
8885
:disabled="!state.selectedVariant.availableForSale"
89-
@click="add(state.selectedVariant.id, state.quantity)"
86+
size="xl"
9087
/>
9188
</div>
9289
</div>

template/app/components/product/Card.vue

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ const props = defineProps<{
88
}>()
99
1010
const localePath = useLocalePath()
11-
const { add } = useCart()
12-
const { t } = useI18n()
1311
1412
const url = computed(() => localePath(`/product/${props.product.handle}`))
1513
const variant = computed(() => props.product.variants.edges[0]?.node)
@@ -68,13 +66,12 @@ const state = reactive<z.infer<typeof schema>>({
6866
/>
6967
</UFormField>
7068

71-
<UButton
69+
<AddToCart
7270
v-if="variant"
73-
trailing-icon="i-lucide-shopping-cart"
74-
:label="t('product.addToCart')"
71+
:variant-id="variant.id"
72+
:quantity="state.quantity"
7573
:disabled="!variant.availableForSale"
7674
:ui="{ trailingIcon: 'size-4' }"
77-
@click="add(variant.id, state.quantity)"
7875
/>
7976
</div>
8077
</UForm>

template/app/composables/cart.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export const useCart = () => {
99
const cart = useState<CartFieldsFragment | undefined>('shopify-cart', () => undefined)
1010
const loading = useState('shopify-cart-loading', () => ref(false))
1111
const open = useState('shopify-cart-open', () => ref(false))
12+
1213
const id = useCookie<string>('shopify-cart-id', undefined)
1314

1415
const lines = computed(() => flattenConnection(cart.value?.lines))
@@ -18,6 +19,17 @@ export const useCart = () => {
1819

1920
const setLoading = async (value: boolean) => loading.value = value
2021

22+
const getAvatar = (variantId: string, lines?: CartFieldsFragment['lines']) => {
23+
const line = lines?.edges?.find(line => line.node.merchandise.id === variantId)
24+
25+
return line?.node.merchandise.image
26+
? {
27+
src: line.node.merchandise.image.url + '?width=88&height=88',
28+
alt: line.node.merchandise.image.altText || undefined,
29+
}
30+
: undefined
31+
}
32+
2133
const init = () => setLoading(true).then(() => storefront.request(`#graphql
2234
mutation CreateCart($language: LanguageCode, $country: CountryCode)
2335
@inContext(language: $language, country: $country) {
@@ -99,10 +111,12 @@ export const useCart = () => {
99111

100112
if (!open.value) toast.add({
101113
title: t('cart.toast.add'),
114+
avatar: getAvatar(variantId, data?.cartLinesAdd?.cart?.lines),
102115
actions: [
103116
{ label: t('cart.toast.view'), onClick: () => { open.value = true } },
104117
],
105118
color: 'success',
119+
ui: { avatar: 'rounded-sm size-14' },
106120
})
107121
}).catch(() => toast.add({
108122
title: t('cart.toast.error.add'),
@@ -144,10 +158,12 @@ export const useCart = () => {
144158

145159
if (!open.value) toast.add({
146160
title: t('cart.toast.update'),
161+
avatar: getAvatar(variantId, data?.cartLinesUpdate?.cart?.lines),
147162
actions: [
148163
{ label: t('cart.toast.view'), onClick: () => { open.value = true } },
149164
],
150165
color: 'success',
166+
ui: { avatar: 'rounded-sm size-14' },
151167
})
152168
}).catch(() => toast.add({
153169
title: t('cart.toast.error.update'),

0 commit comments

Comments
 (0)