From 2fe7fa000573ce9f7ff095a596bde8263bd7c5c3 Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Tue, 6 Jan 2026 14:10:48 +0330 Subject: [PATCH] add main_image field to product serializers and update components to use it --- backend/product/serializers.py | 24 +++++++++++++++++-- frontend/components/global/ProductsGrid.vue | 2 +- .../global/product-detail/ProductsSlider.vue | 2 +- frontend/types/global.d.ts | 5 ++-- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/backend/product/serializers.py b/backend/product/serializers.py index 7e6c0e0..9d41a85 100644 --- a/backend/product/serializers.py +++ b/backend/product/serializers.py @@ -67,9 +67,12 @@ class ProductVariantSerialzier(serializers.ModelSerializer): cart_quantity = serializers.SerializerMethodField() price = serializers.SerializerMethodField() price_after_discount = serializers.SerializerMethodField() + special_discount_amount = serializers.SerializerMethodField() + special_discount_link = serializers.SerializerMethodField() + class Meta: model = ProductVariant - exclude = ('min_price', 'sell', 'currency', 'product', 'input_price', 'price_in_dollor') + exclude = ('min_price', 'sell', 'currency', 'product', 'input_price', 'price_in_dollor', 'profit', 'special_discount_percent') def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -77,6 +80,16 @@ class ProductVariantSerialzier(serializers.ModelSerializer): if view_type == 'list': self.fields.pop('in_pack_items', None) + def get_special_discount_amount(self, obj): + if obj.special_discount_percent: + special_discount_amount = obj.profit * (obj.special_discount_percent / 100) + return f'{special_discount_amount:,.0f} تومانءءء' + else: + return None + + def get_special_discount_link(self, obj): + return 'https://' + def get_price_after_discount(self, obj): return f'{obj.price_after_discount:,.0f} تومانءءء' @@ -139,6 +152,7 @@ class DynamicProductSerializer(serializers.ModelSerializer): best_deal_price_before_discount = serializers.SerializerMethodField() best_deal_price_after_discount = serializers.SerializerMethodField() best_deal_discount = serializers.SerializerMethodField() + main_image = serializers.SerializerMethodField() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) view_type = self.context.get('view_type', 'all') @@ -154,11 +168,17 @@ class DynamicProductSerializer(serializers.ModelSerializer): model = ProductModel fields = "__all__" view_type = { - 'list': ['id', 'name', 'rating', 'slug', 'category', 'variants', 'colors', 'image', 'best_deal_price_before_discount', 'best_deal_price_after_discount', 'best_deal_discount', ], + 'list': ['id', 'name', 'rating', 'slug', 'category', 'colors', 'image', 'best_deal_price_before_discount', 'best_deal_price_after_discount', 'best_deal_discount', 'main_image'], 'slider': ['id', 'name', 'rating', 'slug', 'category', 'variants', 'colors', 'image', 'best_deal_price_before_discount', 'best_deal_price_after_discount', 'best_deal_discount', ], 'instance': ['id', 'name', 'description', 'rating', 'slug', 'meta_description', 'meta_keywords', 'meta_rating', 'category', 'related_products', 'in_pack_items', 'variants', 'colors', 'added_to_favorites', 'image'], 'chat': ['id', 'name', 'description', 'variants', 'image'] } + + def get_main_image(self, obj): + if obj.image: + return obj.image.url + return obj.variants.first().images.first().image.url if obj.variants.exists() and obj.variants.first().images.exists() else None + def get_best_deal_price_before_discount(self, obj): best_deal = obj.get_best_deal_variant() if best_deal: diff --git a/frontend/components/global/ProductsGrid.vue b/frontend/components/global/ProductsGrid.vue index c14342e..0e41d22 100644 --- a/frontend/components/global/ProductsGrid.vue +++ b/frontend/components/global/ProductsGrid.vue @@ -45,7 +45,7 @@ withDefaults(defineProps(), { :id="product.id" :slug="product.slug" :title="product.name" - :picture="product.image ?? product.variants[0].images[0].image" + :picture="product.main_image" :colors="product.colors" :price="product.best_deal_price_before_discount" :rate="product.rating" diff --git a/frontend/components/global/product-detail/ProductsSlider.vue b/frontend/components/global/product-detail/ProductsSlider.vue index 2c13e33..d2593c2 100644 --- a/frontend/components/global/product-detail/ProductsSlider.vue +++ b/frontend/components/global/product-detail/ProductsSlider.vue @@ -91,7 +91,7 @@ const onSwiper = (swiper: SwiperClass) => { :id="product.id" :slug="product.slug" :title="product.name" - :picture="product.image ?? product.variants[0].images[0].image" + :picture="product.main_image" :colors="product.colors" :rate="product.rating" :dark-layer="true" diff --git a/frontend/types/global.d.ts b/frontend/types/global.d.ts index 1875336..f08da02 100644 --- a/frontend/types/global.d.ts +++ b/frontend/types/global.d.ts @@ -106,7 +106,7 @@ declare global { category: SubCategory; colors: string[]; added_to_favorites: boolean; - image: string | null; + main_image: string; best_deal_price_before_discount: string; best_deal_price_after_discount: string; best_deal_discount: number; @@ -115,13 +115,12 @@ declare global { type ProductListItem = Pick< Product, | "id" - | "variants" | "name" | "rating" | "slug" | "category" | "colors" - | "image" + | "main_image" | "best_deal_discount" | "best_deal_price_after_discount" | "best_deal_price_before_discount"