wip: product filters
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
<template>
|
||||
<div class="app-container h-full">
|
||||
<FullscreenViewport v-if="platform === 'ios' || platform === 'android'"/>
|
||||
<RouterView v-slot="{ Component, route }">
|
||||
<Transition name="route" appear>
|
||||
<component :is="Component" :key="route.fullPath"/>
|
||||
</Transition>
|
||||
</RouterView>
|
||||
<CartButton v-if="settings.store_enabled"/>
|
||||
<header class="app-header w-full" v-if="platform === 'ios'"></header>
|
||||
|
||||
<section class="safe-top">
|
||||
<FullscreenViewport v-if="platform === 'ios' || platform === 'android'"/>
|
||||
<RouterView v-slot="{ Component, route }">
|
||||
<Transition name="route" appear>
|
||||
<component :is="Component" :key="route.fullPath"/>
|
||||
</Transition>
|
||||
</RouterView>
|
||||
<CartButton v-if="settings.store_enabled"/>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -50,3 +54,21 @@ watch(
|
||||
{immediate: true}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* route transitions */
|
||||
.route-enter-active,
|
||||
.route-leave-active {
|
||||
transition: opacity 0.25s ease, transform 0.25s ease;
|
||||
}
|
||||
|
||||
.route-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
|
||||
.route-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
</style>
|
||||
@@ -2,7 +2,7 @@
|
||||
<div v-if="isCartBtnShow" class="fixed right-2 bottom-30 z-50 opacity-90">
|
||||
<div class="indicator">
|
||||
<span class="indicator-item indicator-top indicator-start badge badge-secondary">{{ cart.productsCount }}</span>
|
||||
<button class="btn btn-primary btn-lg btn-circle" @click="openCart">
|
||||
<button class="btn btn-primary btn-xl btn-circle" @click="openCart">
|
||||
<span v-if="cart.isLoading" class="loading loading-spinner"></span>
|
||||
<template v-else>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
v-for="category in categoriesStore.topCategories"
|
||||
class="btn btn-md max-w-[12rem]"
|
||||
:to="{name: 'product.categories.show', params: {category_id: category.id}}"
|
||||
@click="onCategoryClick"
|
||||
>
|
||||
<span class="overflow-hidden text-ellipsis whitespace-nowrap">{{ category.name }}</span>
|
||||
</RouterLink>
|
||||
@@ -20,4 +21,8 @@
|
||||
<script setup>
|
||||
import {useCategoriesStore} from "@/stores/CategoriesStore.js";
|
||||
const categoriesStore = useCategoriesStore();
|
||||
|
||||
function onCategoryClick() {
|
||||
window.Telegram.WebApp.HapticFeedback.impactOccurred('soft');
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div style="z-index: 99999" class="fixed top-0 left-0 w-full h-full bg-base-100">
|
||||
<div style="z-index: 99999" class="fixed left-0 w-full h-full bg-base-100 top-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<span class="loading loading-infinity loading-xl"></span>
|
||||
<h1>{{ text }}</h1>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="search-wrapper px-5 w-full">
|
||||
<div class="search-wrapper w-full">
|
||||
<label class="input w-full">
|
||||
<svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<g
|
||||
@@ -15,7 +15,7 @@
|
||||
</svg>
|
||||
<input
|
||||
readonly
|
||||
class="grow input-lg"
|
||||
class="grow input-lg w-full"
|
||||
placeholder="Поиск по магазину"
|
||||
@click="showSearchPage"
|
||||
/>
|
||||
@@ -32,6 +32,7 @@ const router = useRouter();
|
||||
function showSearchPage() {
|
||||
router.push({name: 'search'});
|
||||
useSearchStore().reset();
|
||||
window.Telegram.WebApp.HapticFeedback.impactOccurred('medium');
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ export const useSettingsStore = defineStore('settings', {
|
||||
'--product_list_title_max_lines': 2,
|
||||
}
|
||||
},
|
||||
noMoreProductsMessage: '🔚 Ну всё, разгрузили всё, что было. Даже кладовщика разбудить не удалось.',
|
||||
noMoreProductsMessage: '🔚 Это всё по текущему запросу. Попробуйте уточнить фильтры или поиск.',
|
||||
}),
|
||||
|
||||
actions: {
|
||||
|
||||
@@ -30,7 +30,7 @@ html {
|
||||
}
|
||||
|
||||
.app-container {
|
||||
/*padding-top: var(--tg-safe-area-inset-top);*/
|
||||
/*padding-top: calc(var(--tg-content-safe-area-inset-top) + var(--tg-safe-area-inset-top));*/
|
||||
padding-bottom: var(--tg-safe-area-inset-bottom);
|
||||
padding-left: var(--tg-safe-area-inset-left);
|
||||
padding-right: var(--tg-safe-area-inset-right);
|
||||
@@ -40,6 +40,18 @@ html {
|
||||
padding-top: calc(var(--tg-content-safe-area-inset-top) + var(--tg-safe-area-inset-top));
|
||||
}
|
||||
|
||||
.app-header {
|
||||
z-index: 100;
|
||||
position: fixed;
|
||||
background: var(--color-primary);
|
||||
padding-top: calc(var(--tg-content-safe-area-inset-top) + var(--tg-safe-area-inset-top));
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-shadow: 0px -1px 3px 1px #000000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.swiper-pagination-bullets > .swiper-pagination-bullet {
|
||||
background-color: red;
|
||||
color: red;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="max-w-3xl mx-auto p-4 space-y-6 pb-30 safe-top">
|
||||
<div class="max-w-3xl mx-auto p-4 space-y-6 pb-30">
|
||||
<h2 class="text-2xl">
|
||||
Корзина
|
||||
<span v-if="cart.isLoading" class="loading loading-spinner loading-md"></span>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="mx-auto max-w-2xl px-4 py-4 sm:px-6 sm:py-24 lg:max-w-7xl lg:px-8 mb-5 safe-top">
|
||||
<div class="mx-auto max-w-2xl px-4 py-4 sm:px-6 sm:py-24 lg:max-w-7xl lg:px-8 mb-5">
|
||||
<h2 class="text-3xl mb-5">Категории</h2>
|
||||
|
||||
<div v-if="categoriesStore.isLoading" class="flex flex-col gap-4">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="max-w-3xl mx-auto space-y-6 pb-30 safe-top">
|
||||
<div class="max-w-3xl mx-auto space-y-6 pb-30">
|
||||
<h2 class="text-2xl text-center">
|
||||
Оформление заказа
|
||||
</h2>
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<div ref="goodsRef" class="safe-top">
|
||||
<div ref="goodsRef">
|
||||
<CategoriesInline/>
|
||||
|
||||
<div class="flex justify-between px-5">
|
||||
<button @click="showFilters" class="btn">
|
||||
<IconFunnel/>
|
||||
</button>
|
||||
<SearchInput/>
|
||||
<div class="px-5 fixed z-50 w-full opacity-90" style="bottom: var(--tg-safe-area-inset-bottom);">
|
||||
<div class="bg-base-300 flex justify-between p-2 rounded-xl shadow-md">
|
||||
<button @click="showFilters" class="btn mr-3">
|
||||
<IconFunnel/>
|
||||
</button>
|
||||
<SearchInput/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ProductsList/>
|
||||
@@ -28,7 +30,6 @@ 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";
|
||||
|
||||
@@ -39,11 +40,13 @@ const isFiltersShow = ref(false);
|
||||
const backButton = window.Telegram.WebApp.BackButton;
|
||||
|
||||
function showFilters() {
|
||||
window.Telegram.WebApp.HapticFeedback.impactOccurred('soft');
|
||||
isFiltersShow.value = true;
|
||||
backButton.show();
|
||||
}
|
||||
|
||||
function closeFilters() {
|
||||
window.Telegram.WebApp.HapticFeedback.impactOccurred('rigid');
|
||||
isFiltersShow.value = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="safe-top max-w-3xl mx-auto p-4 space-y-6 pb-30 flex flex-col items-center h-full justify-center">
|
||||
<div class="max-w-3xl mx-auto p-4 space-y-6 pb-30 flex flex-col items-center h-full justify-center">
|
||||
<div class="flex flex-col justify-center items-center px-5">
|
||||
<div class="mb-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-25 text-success">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="safe-top">
|
||||
<div>
|
||||
<div>
|
||||
<swiper-container ref="swiperEl" init="false">
|
||||
<swiper-slide
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<div ref="goodsRef" class="safe-top">
|
||||
<SearchInput/>
|
||||
<div ref="goodsRef">
|
||||
<div class="px-5 fixed z-50 w-full opacity-90" style="bottom: var(--tg-safe-area-inset-bottom);">
|
||||
<div class="bg-base-300 flex justify-between p-2 rounded-xl shadow-md">
|
||||
<SearchInput/>
|
||||
</div>
|
||||
</div>
|
||||
<ProductsList/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -11,6 +15,7 @@ import SearchInput from "@/components/SearchInput.vue";
|
||||
import {onMounted} from "vue";
|
||||
import {useRoute} from "vue-router";
|
||||
import {useProductsStore} from "@/stores/ProductsStore.js";
|
||||
import IconFunnel from "@/components/Icons/IconFunnel.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const productsStore = useProductsStore();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="max-w-3xl mx-auto p-4 space-y-6 pb-20 safe-top">
|
||||
<div class="max-w-3xl mx-auto p-4 space-y-6 pb-20">
|
||||
<h2 class="text-2xl mb-3">Поиск</h2>
|
||||
|
||||
<div class="w-full">
|
||||
|
||||
Reference in New Issue
Block a user