feat: add filters to mainpage

This commit is contained in:
2025-10-03 00:26:13 +03:00
parent 023acee68f
commit 1e2a9bc705
168 changed files with 5367 additions and 662 deletions

View File

@@ -1,8 +1,22 @@
<template>
<div ref="goodsRef" class="safe-top">
<CategoriesInline/>
<SearchInput/>
<div class="flex justify-between px-5">
<button @click="showFilters" class="btn">
<IconFunnel/>
</button>
<SearchInput/>
</div>
<ProductsList/>
<Filters
v-if="isFiltersShow"
:filters="productsStore.filters"
@apply="applyFilters"
@reset="resetFilters"
@close="closeFilters"
/>
</div>
</template>
@@ -10,4 +24,58 @@
import ProductsList from "@/components/ProductsList.vue";
import CategoriesInline from "../components/CategoriesInline.vue";
import SearchInput from "@/components/SearchInput.vue";
import Filters from "@/components/ProductFilters/Filters.vue";
import {onMounted, onUnmounted, ref} from "vue";
import {useProductsStore} from "@/stores/ProductsStore.js";
import IconFunnel from "@/components/Icons/IconFunnel.vue";
import {useProductFiltersStore} from "@/stores/ProductFiltersStore.js";
import {FILTERS_MAIN_PAGE_DEFAULT} from "@/components/ProductFilters/filters.js";
import {useRoute} from "vue-router";
const route = useRoute();
const productsStore = useProductsStore();
const isFiltersShow = ref(false);
const backButton = window.Telegram.WebApp.BackButton;
function showFilters() {
isFiltersShow.value = true;
backButton.show();
}
function closeFilters() {
isFiltersShow.value = false;
}
async function applyFilters(newFilters) {
closeFilters();
console.log("Load products with new filters: ", newFilters);
productsStore.page = 1;
await productsStore.loadProducts(newFilters);
}
async function resetFilters() {
closeFilters();
productsStore.reset();
await productsStore.loadProducts(FILTERS_MAIN_PAGE_DEFAULT);
}
function handleClickOutside(e) {
if (!e.target.closest('input, textarea')) {
document.activeElement?.blur()
}
}
onUnmounted(() => document.removeEventListener('click', handleClickOutside));
onMounted(async () => {
document.addEventListener('click', handleClickOutside);
if (productsStore.filtersFullUrl !== route.fullPath) {
productsStore.filtersFullUrl = route.fullPath;
await productsStore.loadProducts(FILTERS_MAIN_PAGE_DEFAULT);
} else {
await productsStore.loadProducts(productsStore.filters ?? FILTERS_MAIN_PAGE_DEFAULT);
}
});
</script>

View File

@@ -8,4 +8,58 @@
<script setup>
import ProductsList from "@/components/ProductsList.vue";
import SearchInput from "@/components/SearchInput.vue";
import {onMounted} from "vue";
import {useRoute} from "vue-router";
import {useProductsStore} from "@/stores/ProductsStore.js";
const route = useRoute();
const productsStore = useProductsStore();
const categoryId = route.params.category_id ?? null;
onMounted(async () => {
console.debug("Load products for category: ", categoryId);
if (productsStore.filtersFullUrl === route.fullPath) {
await productsStore.loadProducts(productsStore.filters ?? {
operand: "AND",
rules: {
RULE_PRODUCT_CATEGORIES: {
criteria: {
product_category_ids: {
type: "product_categories",
params: {
operator: "contains",
value: [
categoryId
]
}
}
}
}
},
});
} else {
productsStore.reset();
productsStore.filtersFullUrl = route.fullPath;
await productsStore.loadProducts({
operand: "AND",
rules: {
RULE_PRODUCT_CATEGORIES: {
criteria: {
product_category_ids: {
type: "product_categories",
params: {
operator: "contains",
value: [
categoryId
]
}
}
}
}
},
});
}
});
</script>