Merge branch 'main' of https://github.com/Byeto-Company/hossein_por_shop
This commit is contained in:
@@ -12,6 +12,7 @@ from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
|
|||||||
from rest_framework.permissions import AllowAny
|
from rest_framework.permissions import AllowAny
|
||||||
from order.serializers import OrderItemSerailzier
|
from order.serializers import OrderItemSerailzier
|
||||||
from order.models import OrderModel
|
from order.models import OrderModel
|
||||||
|
from django.db.models import Min, Max
|
||||||
# class APIView(APIView):
|
# class APIView(APIView):
|
||||||
# def __init__(self, *args, **kwargs):
|
# def __init__(self, *args, **kwargs):
|
||||||
# super().__init__(*args, **kwargs)
|
# super().__init__(*args, **kwargs)
|
||||||
@@ -177,15 +178,16 @@ class AllProductsView(APIView):
|
|||||||
if search_query:
|
if search_query:
|
||||||
products = products.filter(Q(name__icontains=search_query) | Q(description__icontains=search_query))
|
products = products.filter(Q(name__icontains=search_query) | Q(description__icontains=search_query))
|
||||||
|
|
||||||
# # Price filters
|
# Price filters
|
||||||
price_gte = request.query_params.get('price_gte', None)
|
price_gte = request.query_params.get('price_gte', None)
|
||||||
price_lte = request.query_params.get('price_lte', None)
|
price_lte = request.query_params.get('price_lte', None)
|
||||||
|
|
||||||
if price_gte:
|
|
||||||
products = products.filter(variants__price__gte=price_gte)
|
|
||||||
if price_lte:
|
|
||||||
products = products.filter(variants__price__lte=price_lte)
|
|
||||||
|
|
||||||
|
products = products.annotate(min_price=Min('variants__price'), max_price=Max('variants__price'))
|
||||||
|
|
||||||
|
if price_gte:
|
||||||
|
products = products.filter(max_price__gte=price_gte)
|
||||||
|
if price_lte:
|
||||||
|
products = products.filter(min_price__lte=price_lte)
|
||||||
# Sorting
|
# Sorting
|
||||||
sort_by = request.query_params.get('sort', None)
|
sort_by = request.query_params.get('sort', None)
|
||||||
if sort_by in ['name', '-name', 'created_at', '-created_at']:
|
if sort_by in ['name', '-name', 'created_at', '-created_at']:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
@utility persian-number {
|
@utility persian-number {
|
||||||
-moz-font-feature-settings: "ss03";
|
-moz-font-feature-settings: "ss02";
|
||||||
-webkit-font-feature-settings: "ss03";
|
-webkit-font-feature-settings: "ss02";
|
||||||
font-feature-settings: "ss03";
|
font-feature-settings: "ss02";
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility text-gradient {
|
@utility text-gradient {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const createdAt = usePersianTimeAgo(new Date(date.value));
|
|||||||
|
|
||||||
<Tag
|
<Tag
|
||||||
v-if="variant === 'lg'"
|
v-if="variant === 'lg'"
|
||||||
class="bg-success-500 absolute left-6 top-6 z-20"
|
class="bg-slate-950 absolute left-6 top-6 z-20"
|
||||||
>
|
>
|
||||||
{{ category.name }}
|
{{ category.name }}
|
||||||
</Tag>
|
</Tag>
|
||||||
@@ -49,7 +49,7 @@ const createdAt = usePersianTimeAgo(new Date(date.value));
|
|||||||
class="aspect-square w-full rounded-150 overflow-hidden relative"
|
class="aspect-square w-full rounded-150 overflow-hidden relative"
|
||||||
>
|
>
|
||||||
<Tag
|
<Tag
|
||||||
class="bg-success-500 absolute z-20 left-4 sm:left-6 top-4 sm:top-6 max-sm:text-xs"
|
class="bg-slate-950 absolute z-20 left-4 sm:left-6 top-4 sm:top-6 max-sm:text-xs"
|
||||||
>
|
>
|
||||||
{{ category.name }}
|
{{ category.name }}
|
||||||
</Tag>
|
</Tag>
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ const isHomePage = computed(() => route.path === "/");
|
|||||||
|
|
||||||
<div class="header-navbar-item flex items-center justify-end h-full">
|
<div class="header-navbar-item flex items-center justify-end h-full">
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
src="/logo/logo-row.png"
|
src="/img/heymlz/heymlz-logomotion.gif"
|
||||||
class="h-2/3"
|
class="h-2/3"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ onMounted(() => {
|
|||||||
src="/img/heymlz/heymlz-text-logo.png"
|
src="/img/heymlz/heymlz-text-logo.png"
|
||||||
class="invert w-[250px]"
|
class="invert w-[250px]"
|
||||||
/>
|
/>
|
||||||
<div class="bg-slate-800 w-[400px] h-1 rounded-full overflow-hidden">
|
<div class="bg-slate-800 w-[300px] sm:w-[400px] h-1 rounded-full overflow-hidden">
|
||||||
<div
|
<div
|
||||||
class="bg-slate-100 h-full w-full transition-all duration-250"
|
class="bg-slate-100 h-full w-full transition-all duration-250"
|
||||||
:style="progressStyle"
|
:style="progressStyle"
|
||||||
|
|||||||
@@ -97,7 +97,9 @@ const changeSlide = (id: number) => {
|
|||||||
:key="slide"
|
:key="slide"
|
||||||
class="py-4"
|
class="py-4"
|
||||||
>
|
>
|
||||||
<div class="brightness-[97%] bg-white aspect-square rounded-[12px] md:rounded-200 w-full" />
|
<div class="brightness-[97%] flex-center bg-white aspect-square rounded-[12px] md:rounded-200 w-full">
|
||||||
|
<Icon name="ci:image-slash" class="size-[40px] sm:size-[60px] **:fill-black/20" />
|
||||||
|
</div>
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
</Swiper>
|
</Swiper>
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,17 @@ type Props = {
|
|||||||
// props
|
// props
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
const { id } = toRefs(props);
|
const { id, colors } = toRefs(props);
|
||||||
|
|
||||||
// state
|
// state
|
||||||
|
|
||||||
const { colorObject } = useImageColor(`#product-image-${id.value}`);
|
const { colorObject } = useImageColor(`#product-image-${id.value}`);
|
||||||
|
|
||||||
|
// computed
|
||||||
|
|
||||||
|
const limitedColors = computed(() => {
|
||||||
|
return colors.value.slice(0, 3);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -51,33 +57,26 @@ const { colorObject } = useImageColor(`#product-image-${id.value}`);
|
|||||||
<div
|
<div
|
||||||
class="flex justify-between items-center absolute px-4 @[280px]:px-6 pt-4 @[280px]:pt-6 top-0 w-full inset-x-0"
|
class="flex justify-between items-center absolute px-4 @[280px]:px-6 pt-4 @[280px]:pt-6 top-0 w-full inset-x-0"
|
||||||
>
|
>
|
||||||
<Rate v-if="rate" :rate="rate" />
|
<Rate
|
||||||
|
v-if="rate"
|
||||||
|
:rate="rate"
|
||||||
|
/>
|
||||||
<Tag v-if="tag">
|
<Tag v-if="tag">
|
||||||
{{ tag }}
|
{{ tag }}
|
||||||
</Tag>
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:class="
|
:class="colorObject?.isLight && !darkLayer ? 'text-black' : 'text-white'"
|
||||||
colorObject?.isLight && !darkLayer
|
|
||||||
? 'text-black'
|
|
||||||
: 'text-white'
|
|
||||||
"
|
|
||||||
class="absolute inset-x-0 bottom-0 pb-4 @[280px]:pb-6 px-4 @[280px]:px-6 flex flex-row-reverse justify-between items-end z-10"
|
class="absolute inset-x-0 bottom-0 pb-4 @[280px]:pb-6 px-4 @[280px]:px-6 flex flex-row-reverse justify-between items-end z-10"
|
||||||
>
|
>
|
||||||
<div class="flex flex-col gap-2 items-start w-full">
|
<div class="flex flex-col gap-2 items-start w-full">
|
||||||
<span
|
<span class="@max-[280px]:hidden typo-sub-h-md @[280px]:typo-sub-h-lg truncate w-full">
|
||||||
class="@max-[280px]:hidden typo-sub-h-md @[280px]:typo-sub-h-lg truncate w-full"
|
|
||||||
>
|
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div class="flex items-center justify-between w-full mt-1">
|
||||||
class="flex items-center justify-between w-full mt-1"
|
<div class="flex items-center gap-2 @[280px]:mt-1">
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex items-center gap-2 @[280px]:mt-1"
|
|
||||||
>
|
|
||||||
<ColorCircle
|
<ColorCircle
|
||||||
v-for="color in colors"
|
v-for="color in limitedColors"
|
||||||
:key="color"
|
:key="color"
|
||||||
:style="{ backgroundColor: color }"
|
:style="{ backgroundColor: color }"
|
||||||
class="!size-5 @[280px]:!size-6"
|
class="!size-5 @[280px]:!size-6"
|
||||||
@@ -93,18 +92,12 @@ const { colorObject } = useImageColor(`#product-image-${id.value}`);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="flex flex-col gap-1 px-2 items-start w-full text-black mt-4 @[280px]:hidden">
|
||||||
class="flex flex-col gap-1 px-2 items-start w-full text-black mt-4 @[280px]:hidden"
|
|
||||||
>
|
|
||||||
<span class="typo-sub-h-sm w-full truncate">
|
<span class="typo-sub-h-sm w-full truncate">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div class="@[280px]:hidden flex items-center justify-between w-full mt-1">
|
||||||
class="@[280px]:hidden flex items-center justify-between w-full mt-1"
|
<span class="typo-p-xs !font-semibold whitespace-nowrap">
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="typo-p-xs !font-semibold whitespace-nowrap"
|
|
||||||
>
|
|
||||||
{{ price }}
|
{{ price }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -98,7 +98,19 @@ const limitedComments = computed(() => {
|
|||||||
:username="'منصور مرزبان'"
|
:username="'منصور مرزبان'"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="flex items-center justify-center w-full">
|
<div
|
||||||
|
class="h-[400px] lg:flex-grow w-full border-[0.5px] flex-col-center border-slate-200 bg-white rounded-xl"
|
||||||
|
>
|
||||||
|
<NuxtImg
|
||||||
|
src="/img/heymlz/heymlz-contact-us.gif"
|
||||||
|
class="w-[200px] lg:w-[300px] translate-y-[-25px]"
|
||||||
|
/>
|
||||||
|
<span class="text-xl text-black font-semibold translate-y-[-25px]"> هیچ نظری ثبت نشده است </span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="comments!.count > 0"
|
||||||
|
class="flex items-center justify-center w-full"
|
||||||
|
>
|
||||||
<Pagination
|
<Pagination
|
||||||
v-if="showMoreComments"
|
v-if="showMoreComments"
|
||||||
:total="comments!.count"
|
:total="comments!.count"
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ watch(
|
|||||||
(newValue) => {
|
(newValue) => {
|
||||||
selectedQuantity.value = 1;
|
selectedQuantity.value = 1;
|
||||||
selectedSlide.value = newValue.images[0].id;
|
selectedSlide.value = newValue.images[0].id;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
@@ -180,7 +183,7 @@ watch(
|
|||||||
|
|
||||||
<div class="flex items-center gap-6 flex-wrap">
|
<div class="flex items-center gap-6 flex-wrap">
|
||||||
<ProductVariant
|
<ProductVariant
|
||||||
@click="variant.in_stock > 0 ? (selectedVariantId = variant.id) : undefined"
|
@click="selectedVariantId = variant.id"
|
||||||
v-for="variant in product!.variants.filter(p => p.color === selectedColor)"
|
v-for="variant in product!.variants.filter(p => p.color === selectedColor)"
|
||||||
:key="variant.id"
|
:key="variant.id"
|
||||||
:variantDetail="variant"
|
:variantDetail="variant"
|
||||||
@@ -190,57 +193,67 @@ watch(
|
|||||||
|
|
||||||
<div class="w-full flex flex-col gap-6 mt-10">
|
<div class="w-full flex flex-col gap-6 mt-10">
|
||||||
<RemainQuantity
|
<RemainQuantity
|
||||||
|
v-if="selectedVariant!.in_stock > 0"
|
||||||
:showSlider="selectedVariant!.cart_quantity === 0"
|
:showSlider="selectedVariant!.cart_quantity === 0"
|
||||||
:maxQuantity="selectedVariant!.in_stock"
|
:maxQuantity="selectedVariant!.in_stock"
|
||||||
:quantity="selectedQuantity"
|
:quantity="selectedQuantity"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="w-full flex gap-3">
|
<div class="w-full flex gap-3">
|
||||||
<template v-if="token">
|
<template v-if="selectedVariant!.in_stock > 0">
|
||||||
<Button
|
<template v-if="token">
|
||||||
v-if="selectedVariant!.cart_quantity === 0"
|
<Button
|
||||||
@click="addItemToCart"
|
v-if="selectedVariant!.cart_quantity === 0"
|
||||||
:loading="isAddCartItemPending"
|
@click="addItemToCart"
|
||||||
:disabled="isAddCartItemPending"
|
:loading="isAddCartItemPending"
|
||||||
class="w-full rounded-full max-sm:h-[48px]"
|
:disabled="isAddCartItemPending"
|
||||||
end-icon="ci:plus"
|
class="w-full rounded-full max-sm:h-[48px]"
|
||||||
>
|
end-icon="ci:plus"
|
||||||
افزودن به سبد خرید
|
>
|
||||||
</Button>
|
افزودن به سبد خرید
|
||||||
|
</Button>
|
||||||
|
<NuxtLink
|
||||||
|
v-else
|
||||||
|
to="/cart"
|
||||||
|
class="w-full"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
class="w-full rounded-full h-full max-sm:h-[48px]"
|
||||||
|
end-icon="ci:cart"
|
||||||
|
>
|
||||||
|
مشاهده در سبد خرید
|
||||||
|
</Button>
|
||||||
|
</NuxtLink>
|
||||||
|
</template>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-else
|
v-else
|
||||||
to="/cart"
|
to="/signin"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
class="w-full rounded-full h-full max-sm:h-[48px]"
|
class="w-full rounded-full h-full max-sm:h-[48px]"
|
||||||
end-icon="ci:cart"
|
end-icon="ci:user"
|
||||||
>
|
>
|
||||||
مشاهده در سبد خرید
|
ابتدا وارد شوید
|
||||||
</Button>
|
</Button>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
<NuxtLink
|
|
||||||
|
<Button
|
||||||
v-else
|
v-else
|
||||||
to="/signin"
|
class="w-full !cursor-default rounded-full h-full max-sm:h-[48px]"
|
||||||
class="w-full"
|
end-icon="ci:cart"
|
||||||
>
|
>
|
||||||
<Button
|
اتمام موجودی
|
||||||
class="w-full rounded-full h-full max-sm:h-[48px]"
|
</Button>
|
||||||
end-icon="ci:user"
|
|
||||||
>
|
|
||||||
ابتدا وارد شوید
|
|
||||||
</Button>
|
|
||||||
</NuxtLink>
|
|
||||||
|
|
||||||
<QuantityCounter
|
<QuantityCounter
|
||||||
v-if="selectedVariant!.cart_quantity === 0"
|
v-if="selectedVariant!.in_stock > 0 && selectedVariant!.cart_quantity === 0"
|
||||||
:disable="isAddCartItemPending"
|
:disable="isAddCartItemPending"
|
||||||
v-model="selectedQuantity"
|
v-model="selectedQuantity"
|
||||||
:max="selectedVariant!.in_stock"
|
:max="selectedVariant!.in_stock"
|
||||||
/>
|
/>
|
||||||
|
<UpdateQuantity v-else-if="selectedVariant!.in_stock > 0" />
|
||||||
<UpdateQuantity v-else />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<InfoCard />
|
<InfoCard />
|
||||||
|
|||||||
@@ -13,22 +13,12 @@ defineProps<Props>();
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="[
|
:class="isSelected ? 'border-blue-500' : 'border-slate-300'"
|
||||||
isSelected ? 'border-blue-500' : 'border-slate-300',
|
class="transition-all min-w-[350px] w-full duration-100 p-4 rounded-150 border-[2px] flex gap-4 cursor-pointer"
|
||||||
variantDetail.in_stock > 0 ? 'cursor-pointer' : '!border-slate-100',
|
|
||||||
]"
|
|
||||||
class="transition-all min-w-[350px] w-full duration-100 p-4 rounded-150 border-[2px] flex gap-4"
|
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
:class="[
|
:class="isSelected ? 'ring-blue-500 bg-blue-500' : 'ring-slate-300 bg-slate-300'"
|
||||||
isSelected
|
|
||||||
? 'ring-blue-500 bg-blue-500'
|
|
||||||
: 'ring-slate-300 bg-slate-300',
|
|
||||||
variantDetail.in_stock > 0
|
|
||||||
? ''
|
|
||||||
: '!ring-slate-100 !bg-slate-300-100',
|
|
||||||
]"
|
|
||||||
class="size-3 mt-2 ring-2 ring-offset-2 rounded-full"
|
class="size-3 mt-2 ring-2 ring-offset-2 rounded-full"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -38,27 +28,25 @@ defineProps<Props>();
|
|||||||
{{ variantDetail.price }}
|
{{ variantDetail.price }}
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
v-if="variantDetail.discount > 0"
|
v-if="variantDetail.in_stock > 0 && variantDetail.discount > 0"
|
||||||
:class="
|
class="text-white mb-1 px-3 py-1 bg-blue-500 text-xs rounded-full w-fit flex items-center justify-center gap-1"
|
||||||
variantDetail.in_stock > 0
|
|
||||||
? 'bg-blue-500'
|
|
||||||
: 'bg-slate-400/60'
|
|
||||||
"
|
|
||||||
class="text-white mb-1 px-3 py-1 text-xs rounded-full w-fit flex items-center justify-center gap-1"
|
|
||||||
>
|
>
|
||||||
<template v-if="variantDetail.in_stock > 0">
|
<Icon
|
||||||
<Icon name="bi:percent" class="size-3.5" />
|
name="bi:percent"
|
||||||
<span class="mt-px">
|
class="size-3.5"
|
||||||
{{ variantDetail.discount }}
|
/>
|
||||||
</span>
|
<span class="mt-px">
|
||||||
</template>
|
{{ variantDetail.discount }}
|
||||||
|
</span>
|
||||||
<span v-else class="mt-px"> اتمام موجودی </span>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="variantDetail.in_stock === 0"
|
||||||
|
class="text-slate-700 mb-1 px-3 py-1 bg-slate-200 text-xs rounded-full w-fit flex items-center justify-center gap-1"
|
||||||
|
>
|
||||||
|
اتمام موجودی
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="w-full flex items-center flex-wrap gap-3 max-w-[400px] mt-4">
|
||||||
class="w-full flex items-center flex-wrap gap-3 max-w-[400px] mt-4"
|
|
||||||
>
|
|
||||||
<!-- <div-->
|
<!-- <div-->
|
||||||
<!-- class="flex items-center gap-2 text-sm rounded-full border border-slate-400 px-4 h-[40px]"-->
|
<!-- class="flex items-center gap-2 text-sm rounded-full border border-slate-400 px-4 h-[40px]"-->
|
||||||
<!-- >-->
|
<!-- >-->
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ const contactWays = ref([
|
|||||||
</div>
|
</div>
|
||||||
<div class="w-full lg:w-4/12 h-full flex-center">
|
<div class="w-full lg:w-4/12 h-full flex-center">
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
src="/img/heymlz/contact-us.gif"
|
src="/img/heymlz/heymlz-contact-us.gif"
|
||||||
class="size-2/3 -mt-5 lg:scale-150 drop-shadow-2xl"
|
class="size-2/3 -mt-5 lg:scale-150 drop-shadow-2xl"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ const handleSubmit = (withValidation: boolean) => {
|
|||||||
</DataField>
|
</DataField>
|
||||||
<DataField
|
<DataField
|
||||||
id="personal-data-birth-date"
|
id="personal-data-birth-date"
|
||||||
label="تاریخ تولد"
|
label="تاریsخ تولد"
|
||||||
:error="formValidator$.birth_date"
|
:error="formValidator$.birth_date"
|
||||||
>
|
>
|
||||||
<Datepicker
|
<Datepicker
|
||||||
|
|||||||
@@ -1,24 +1,18 @@
|
|||||||
import axiosOriginal from "axios";
|
import axiosOriginal from "axios";
|
||||||
import { useAuth } from "~/composables/api/auth/useAuth";
|
import { useAuth } from "~/composables/api/auth/useAuth";
|
||||||
import { API_ENDPOINTS } from "~/constants";
|
import { API_ENDPOINTS } from "~/constants";
|
||||||
import Logger from "~/tools/logger";
|
|
||||||
|
|
||||||
export default defineNuxtPlugin(() => {
|
export default defineNuxtPlugin(() => {
|
||||||
const config = useRuntimeConfig();
|
const config = useRuntimeConfig();
|
||||||
const { token } = useAuth();
|
const { token } = useAuth();
|
||||||
|
|
||||||
const axios = axiosOriginal.create({
|
const axios = axiosOriginal.create({
|
||||||
baseURL: config.public.API_BASE_URL
|
baseURL: config.public.API_BASE_URL,
|
||||||
});
|
});
|
||||||
|
|
||||||
axios.interceptors.request.use((config) => {
|
axios.interceptors.request.use((config) => {
|
||||||
if (
|
if (!config.url?.includes(API_ENDPOINTS.auth.signin) && !config.url?.includes(API_ENDPOINTS.account.send_otp)) {
|
||||||
!config.url?.includes(API_ENDPOINTS.auth.signin) &&
|
config.headers.Authorization = token.value ? `Bearer ${token.value}` : undefined;
|
||||||
!config.url?.includes(API_ENDPOINTS.account.send_otp)
|
|
||||||
) {
|
|
||||||
config.headers.Authorization = token.value
|
|
||||||
? `Bearer ${token.value}`
|
|
||||||
: undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
@@ -28,19 +22,14 @@ export default defineNuxtPlugin(() => {
|
|||||||
(response) => {
|
(response) => {
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
async function(error) {
|
async function (error) {
|
||||||
|
|
||||||
if (config.public.DEBUG === "true" && import.meta.server) {
|
|
||||||
await Logger.axiosErrorLog(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
provide: {
|
provide: {
|
||||||
axios
|
axios,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
export default defineNuxtPlugin((nuxtApp) => {
|
|
||||||
// Also possible
|
|
||||||
nuxtApp.hook('vue:error', (error, instance, info) => {
|
|
||||||
// handle error, e.g. report to a service
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc. --><defs><style>.fa-secondary{opacity:.4}</style></defs><path class="fa-secondary" d="M64 146.4L64 416c0 35.3 28.7 64 64 64l359.4 0-81.2-64L320 416l-72 0-96 0c-9.3 0-17.8-5.4-21.8-13.9s-2.6-18.5 3.5-25.6l88-104c.3-.4 .6-.7 1-1.1L64 146.4zM89.5 44.9c23.1 18.1 46.2 36.2 69.3 54.3c5.3-2 11.1-3.2 17.2-3.2c26.5 0 48 21.5 48 48c0 2-.1 4-.4 6c34.8 27.3 69.7 54.6 104.5 81.9l20-29.4c4.5-6.6 11.9-10.5 19.8-10.5s15.4 3.9 19.8 10.5L499.4 366.1l75.9 59.5c.5-3.1 .7-6.3 .7-9.6l0-320c0-35.3-28.7-64-64-64L128 32c-14.4 0-27.8 4.8-38.5 12.9z"/><path class="fa-primary" d="M5.1 9.2C13.3-1.2 28.4-3.1 38.8 5.1l592 464c10.4 8.2 12.3 23.3 4.1 33.7s-23.3 12.3-33.7 4.1L9.2 42.9C-1.2 34.7-3.1 19.6 5.1 9.2z"/></svg>
|
||||||
|
After Width: | Height: | Size: 923 B |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 648 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB |
@@ -1,40 +0,0 @@
|
|||||||
import fs from "fs/promises";
|
|
||||||
import { ensureFileExists } from "~/utils";
|
|
||||||
|
|
||||||
class Logger {
|
|
||||||
public static async axiosErrorLog(error: any) {
|
|
||||||
const errorJson = error.toJSON();
|
|
||||||
|
|
||||||
const nowDate = new Date();
|
|
||||||
|
|
||||||
const logData: AxiosLogType = {
|
|
||||||
url: errorJson.config.url,
|
|
||||||
code: errorJson.code!,
|
|
||||||
status: errorJson.status!,
|
|
||||||
method: errorJson.config.method,
|
|
||||||
response: error?.response?.data,
|
|
||||||
requestHeaders: errorJson.config.headers,
|
|
||||||
// responseHeaders: error.response.headers,
|
|
||||||
payload: errorJson.config.data ? JSON.parse(errorJson.config.data) : undefined,
|
|
||||||
params: errorJson.config.params ?? undefined,
|
|
||||||
date: nowDate.toString()
|
|
||||||
};
|
|
||||||
|
|
||||||
const logFilePath = ".logs/log.json";
|
|
||||||
|
|
||||||
try {
|
|
||||||
await ensureFileExists(logFilePath, "[]");
|
|
||||||
|
|
||||||
const oldLogs = await fs.readFile(logFilePath, "utf-8");
|
|
||||||
const oldLogsJson = JSON.parse(oldLogs) as Record<any, any>[];
|
|
||||||
|
|
||||||
oldLogsJson.push(logData);
|
|
||||||
|
|
||||||
await fs.writeFile(logFilePath, JSON.stringify(oldLogsJson, null, 2));
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Logger;
|
|
||||||
Reference in New Issue
Block a user