Extract save button logic
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
// imports
|
||||||
|
|
||||||
|
import { useAuth } from "~/composables/api/auth/useAuth";
|
||||||
|
import useGetProduct from "~/composables/api/product/useGetProduct";
|
||||||
|
import useSaveProduct from "~/composables/api/product/useSaveProduct";
|
||||||
|
import { QUERY_KEYS } from "~/constants";
|
||||||
|
|
||||||
|
// states
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const id = route.params.id as string | undefined;
|
||||||
|
|
||||||
|
const { $queryClient: queryClient } = useNuxtApp();
|
||||||
|
|
||||||
|
const { token } = useAuth();
|
||||||
|
|
||||||
|
const { mutateAsync: saveProduct, isPending: isSaveProductPending } = useSaveProduct();
|
||||||
|
const { data: product, refetch: refetchProduct, isFetching: isFetchingPending } = useGetProduct(id);
|
||||||
|
|
||||||
|
// methods
|
||||||
|
|
||||||
|
const saveProductHandler = async () => {
|
||||||
|
await saveProduct({ product_slug: product.value!.slug });
|
||||||
|
await queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.product] });
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<button
|
||||||
|
@click="saveProductHandler"
|
||||||
|
:disabled="isSaveProductPending || isFetchingPending || !token"
|
||||||
|
class="size-10 bg-slate-50 border-slate-200 border rounded-lg flex-center"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
v-if="isSaveProductPending || isFetchingPending"
|
||||||
|
name="ci:svg-spinners-180-ring-with-bg"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
v-else
|
||||||
|
:class="product?.added_to_favorites ? '**:fill-blue-400' : ''"
|
||||||
|
:name="product?.added_to_favorites ? 'bi-bookmark-fill' : 'ci:bi-bookmark'"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
@@ -5,8 +5,6 @@ import useGetProduct from "~/composables/api/product/useGetProduct";
|
|||||||
import type { ProductVariantProvideType } from "~/pages/product/[id].vue";
|
import type { ProductVariantProvideType } from "~/pages/product/[id].vue";
|
||||||
import useAddCartItem from "~/composables/api/orders/useAddCartItem";
|
import useAddCartItem from "~/composables/api/orders/useAddCartItem";
|
||||||
import { useAuth } from "~/composables/api/auth/useAuth";
|
import { useAuth } from "~/composables/api/auth/useAuth";
|
||||||
import useSaveProduct from "~/composables/api/product/useSaveProduct";
|
|
||||||
import { QUERY_KEYS } from "~/constants";
|
|
||||||
|
|
||||||
// state
|
// state
|
||||||
|
|
||||||
@@ -14,11 +12,9 @@ const route = useRoute();
|
|||||||
const id = route.params.id as string | undefined;
|
const id = route.params.id as string | undefined;
|
||||||
|
|
||||||
const { token } = useAuth();
|
const { token } = useAuth();
|
||||||
const { $queryClient: queryClient } = useNuxtApp();
|
|
||||||
|
|
||||||
const { data: product, refetch: refetchProduct, isFetching: isFetchingPending } = useGetProduct(id);
|
const { data: product, refetch: refetchProduct, isFetching: isFetchingPending } = useGetProduct(id);
|
||||||
const { mutateAsync: addCartItem, isPending: isAddCartItemPending } = useAddCartItem();
|
const { mutateAsync: addCartItem, isPending: isAddCartItemPending } = useAddCartItem();
|
||||||
const { mutateAsync: saveProduct, isPending: isSaveProductPending } = useSaveProduct();
|
|
||||||
|
|
||||||
const selectedVariantId = ref(product.value!.variants[0].id);
|
const selectedVariantId = ref(product.value!.variants[0].id);
|
||||||
const selectedQuantity = ref(1);
|
const selectedQuantity = ref(1);
|
||||||
@@ -40,11 +36,6 @@ const addItemToCart = async () => {
|
|||||||
await refetchProduct();
|
await refetchProduct();
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveProductHandler = async () => {
|
|
||||||
await saveProduct({ product_slug: product.value!.slug });
|
|
||||||
await queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.product] });
|
|
||||||
};
|
|
||||||
|
|
||||||
// watch
|
// watch
|
||||||
|
|
||||||
watch([selectedVariantId, product], ([selectedVariantId, product]) => {
|
watch([selectedVariantId, product], ([selectedVariantId, product]) => {
|
||||||
@@ -99,22 +90,7 @@ watch(
|
|||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<SaveButton />
|
||||||
@click="saveProductHandler"
|
|
||||||
:disabled="isSaveProductPending || isFetchingPending || !token"
|
|
||||||
class="size-10 bg-slate-50 border-slate-200 border rounded-lg flex-center"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
v-if="isSaveProductPending || isFetchingPending"
|
|
||||||
name="ci:svg-spinners-180-ring-with-bg"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Icon
|
|
||||||
v-else
|
|
||||||
:class="product?.added_to_favorites ? '**:fill-blue-400' : ''"
|
|
||||||
:name="product?.added_to_favorites ? 'bi-bookmark-fill' : 'ci:bi-bookmark'"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<h1 class="typo-h-6 xs:typo-h-5 sm:typo-h-4 lg:typo-h-2">
|
<h1 class="typo-h-6 xs:typo-h-5 sm:typo-h-4 lg:typo-h-2">
|
||||||
{{ product!.name }}
|
{{ product!.name }}
|
||||||
@@ -178,22 +154,7 @@ watch(
|
|||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<SaveButton />
|
||||||
@click="saveProductHandler"
|
|
||||||
:disabled="isSaveProductPending || isFetchingPending || !token"
|
|
||||||
class="size-10 bg-slate-50 border-slate-200 border rounded-lg flex-center"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
v-if="isSaveProductPending || isFetchingPending"
|
|
||||||
name="ci:svg-spinners-180-ring-with-bg"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Icon
|
|
||||||
v-else
|
|
||||||
:class="product?.added_to_favorites ? '**:fill-blue-400' : ''"
|
|
||||||
:name="product?.added_to_favorites ? 'bi-bookmark-fill' : 'ci:bi-bookmark'"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<h1 class="typo-h-4 xl:typo-h-3 max-lg:hidden">
|
<h1 class="typo-h-4 xl:typo-h-3 max-lg:hidden">
|
||||||
{{ product!.name }}
|
{{ product!.name }}
|
||||||
@@ -365,7 +326,7 @@ watch(
|
|||||||
|
|
||||||
<InfoCard />
|
<InfoCard />
|
||||||
|
|
||||||
<Share />
|
<Share :product="product!" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ProductDescription
|
<ProductDescription
|
||||||
|
|||||||
Reference in New Issue
Block a user