Files
interview-demo-code/frontend/spa/src/stores/SearchStore.js
Nikita Kiselev 01458e3b4c
Some checks failed
Telegram Mini App Shop Builder / Compute version metadata (push) Has been cancelled
Telegram Mini App Shop Builder / Run Frontend tests (push) Has been cancelled
Telegram Mini App Shop Builder / Run Backend tests (push) Has been cancelled
Telegram Mini App Shop Builder / Run PHP_CodeSniffer (push) Has been cancelled
Telegram Mini App Shop Builder / Build module. (push) Has been cancelled
Telegram Mini App Shop Builder / release (push) Has been cancelled
Squashed commit message
2026-03-11 22:33:34 +03:00

133 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {defineStore} from "pinia";
import ftch from "@/utils/ftch.js";
import {YA_METRIKA_GOAL} from "@/constants/yaMetrikaGoals.js";
import {useYaMetrikaStore} from "@/stores/yaMetrikaStore.js";
import {toRaw} from "vue";
export const useSearchStore = defineStore('search', {
state: () => ({
search: '',
page: 1,
products: {
data: [],
meta: {},
},
isLoading: false,
isLoadingMore: false,
isSearchPerformed: false,
hasMore: false,
// Placeholder товары для пустого состояния поиска
placeholderProducts: {
data: [],
total: 0,
},
isLoadingPlaceholder: false,
}),
actions: {
reset() {
this.search = '';
this.isSearchPerformed = false;
this.isLoading = false;
this.page = 1;
this.products = {
data: [],
meta: {},
};
},
async fetchProducts(search, page = 1, perPage = 5) {
return await ftch('products', null, {
page,
perPage: perPage,
search,
});
},
async performSearch() {
if (!this.search) {
return this.reset();
}
useYaMetrikaStore().reachGoal(YA_METRIKA_GOAL.PERFORM_SEARCH, {
keyword: this.search,
});
try {
this.page = 1;
this.isLoading = true;
const response = await this.fetchProducts(this.search, this.page, 10);
console.debug('[Search] Perform Search: ', response);
this.products = response;
this.hasMore = response?.meta?.hasMore || false;
} catch (error) {
console.error(error);
} finally {
this.isLoading = false;
this.isSearchPerformed = true;
}
},
async loadMore() {
try {
if (this.isLoading === true || this.isLoadingMore === true || this.hasMore === false) return;
this.isLoadingMore = true;
this.page++;
const data = toRaw({
page: this.page,
perPage: 10,
search: this.search,
});
console.debug('[Search] Loading more products: ', data);
const response = await ftch('products', null, data);
console.debug('[Search] Search results: ', response);
this.products.data.push(...response.data);
this.products.meta = response.meta;
this.hasMore = response.meta.hasMore;
} catch (error) {
console.error(error);
} finally {
this.isLoading = false;
this.isLoadingMore = false;
this.isSearchPerformed = true;
}
},
async loadSearchPlaceholder() {
// Если данные уже есть в store, возвращаем их
if (this.placeholderProducts.data.length > 0) {
return {
data: this.placeholderProducts.data,
meta: {
total: this.placeholderProducts.total,
},
};
}
try {
this.isLoadingPlaceholder = true;
// Иначе загружаем с сервера
const response = await ftch('productsSearchPlaceholder');
this.placeholderProducts.data = response.data.slice(0, 3);
this.placeholderProducts.total = response?.meta?.total || 0;
return {
data: this.placeholderProducts.data,
meta: {
total: this.placeholderProducts.total,
},
};
} finally {
this.isLoadingPlaceholder = false;
}
},
},
});