feat(products-feed): replace fixed image dimensions with aspect ratio selection

- Added image aspect ratio selection (1:1, 4:5, 3:4, 2:3) to ProductsFeed block configuration in Admin panel
- Removed manual width/height input fields
- Updated ProductsFeed block in SPA to send aspect ratio parameter instead of dimensions
- Implemented backend logic to calculate image height based on selected aspect ratio and base width (300px)
- Updated default configuration for products_feed block
- Added descriptive help text for each aspect ratio option in the dropdown
This commit is contained in:
2025-12-06 15:46:37 +03:00
committed by Nikita Kiselev
parent 13e5bce8a5
commit cd060610fe
10 changed files with 99 additions and 17 deletions

View File

@@ -33,7 +33,7 @@ const hasMore = ref(false);
const isLoading = ref(false);
const isLoadingMore = ref(false);
const page = ref(1);
const perPage = 20;
const perPage = 10;
const props = defineProps({
block: {
@@ -45,17 +45,17 @@ const props = defineProps({
async function fetchProducts() {
try {
isLoading.value = true;
console.debug('Home: Load products for Main Page.');
console.debug('Home: Fetch products from server using filters: ', toRaw(filtersStore.applied));
console.debug('[Products Feed]: Start to load products for page 1. Filters: ', toRaw(filtersStore.applied));
const response = await ftch('products', null, toRaw({
page: page.value,
page: 1,
maxPages: props.block.data.max_page_count,
perPage: perPage,
filters: filtersStore.applied,
image_aspect_ratio: props.block.data.image_aspect_ratio,
}));
products.value = response.data;
hasMore.value = response.meta.hasMore;
console.debug('ProductsFeedBlock: Products for main page loaded.');
console.debug('[Products Feed]: Products loaded for page 1. Has More: ', hasMore.value);
yaMetrika.dataLayerPush({
ecommerce: {
@@ -84,18 +84,21 @@ async function fetchProducts() {
async function onLoadMore() {
try {
console.debug('ProductsFeedBlock: onLoadMore');
console.debug('[Products Feed]: onLoadMore');
if (isLoading.value === true || isLoadingMore.value === true || hasMore.value === false) return;
isLoadingMore.value = true;
page.value++;
console.debug('ProductsFeedBlock: Load more for page ', page.value, ' using filters: ', toRaw(filtersStore.applied));
console.debug('[Products Feed]: Load more for page ', page.value, ' using filters: ', toRaw(filtersStore.applied));
const response = await ftch('products', null, toRaw({
page: page.value,
perPage: perPage,
maxPages: props.block.data.max_page_count,
filters: filtersStore.applied,
image_aspect_ratio: props.block.data.image_aspect_ratio,
}));
products.value.push(...response.data);
hasMore.value = response.meta.hasMore;
console.debug(`[Products Feed]: Products loaded for page ${page.value}. Has More: `, hasMore.value);
} catch (error) {
console.error(error);
} finally {

View File

@@ -131,12 +131,13 @@ function productClick(product, index) {
useIntersectionObserver(
bottom,
([entry]) => {
console.debug('Check Intersection');
console.debug('[Product List]: Check Intersection: ', entry?.isIntersecting);
if (entry?.isIntersecting === true
&& props.hasMore === true
&& props.isLoading === false
&& props.isLoadingMore === false
) {
console.debug('[Product List]: Send Load More signal');
emits('loadMore');
}
},

View File

@@ -29,7 +29,7 @@ export const useSettingsStore = defineStore('settings', {
text_order_created_success: 'Заказ успешно оформлен.',
},
mainpage_blocks: [],
is_privacy_consented: false,
is_privacy_consented: true,
privacy_policy_link: false,
}),