93 lines
3.1 KiB
Vue
93 lines
3.1 KiB
Vue
<template>
|
|
<BaseViewWrapper title="Поиск">
|
|
<label class="input w-full mb-4">
|
|
<svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
<g
|
|
stroke-linejoin="round"
|
|
stroke-linecap="round"
|
|
stroke-width="2.5"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
>
|
|
<circle cx="11" cy="11" r="8"></circle>
|
|
<path d="m21 21-4.3-4.3"></path>
|
|
</g>
|
|
</svg>
|
|
<input
|
|
ref="searchInput"
|
|
type="search"
|
|
class="grow input-lg"
|
|
placeholder="Поиск по магазину"
|
|
v-model="searchStore.search"
|
|
@search="debouncedSearch"
|
|
@input="debouncedSearch"
|
|
/>
|
|
</label>
|
|
|
|
<div v-if="searchStore.isLoading === false && searchStore.products.data.length > 0">
|
|
<RouterLink
|
|
v-for="product in searchStore.products.data"
|
|
:key="product.id"
|
|
class="flex mb-5"
|
|
:to="{name: 'product.show', params: {id: product.id}}"
|
|
>
|
|
<div v-if="product.images && product.images.length > 0" class="avatar">
|
|
<div class="w-24 rounded">
|
|
<img :src="product.images[0].url" :alt="product.images[0].alt"/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ml-5 p-0">
|
|
<h2 class="card-title">{{ product.name }}</h2>
|
|
<Price :price="product.price" :special="product.special"/>
|
|
</div>
|
|
</RouterLink>
|
|
</div>
|
|
|
|
<div v-if="searchStore.isLoading === true">
|
|
<div v-for="n in 3" class="flex w-full gap-4 mb-3">
|
|
<div class="skeleton h-32 w-32"></div>
|
|
<div class="flex flex-col gap-2 w-full">
|
|
<div class="skeleton h-4 w-full"></div>
|
|
<div class="skeleton h-4 w-28"></div>
|
|
<div class="skeleton h-4 w-28"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
v-if="searchStore.isSearchPerformed && searchStore.isLoading === false && searchStore.products.data.length === 0"
|
|
class="flex flex-col items-center justify-center text-center py-16"
|
|
>
|
|
<span class="text-5xl mb-4">🛒</span>
|
|
<h2 class="text-xl font-semibold mb-2">Товары не найдены</h2>
|
|
<p class="text-sm mb-4">Попробуйте изменить или уточнить запрос</p>
|
|
</div>
|
|
</BaseViewWrapper>
|
|
</template>
|
|
|
|
<script setup>
|
|
import {useSearchStore} from "@/stores/SearchStore.js";
|
|
import {useDebounceFn} from "@vueuse/core";
|
|
import {onMounted, ref} from "vue";
|
|
import {useYaMetrikaStore} from "@/stores/yaMetrikaStore.js";
|
|
import {useRoute} from "vue-router";
|
|
import {YA_METRIKA_GOAL} from "@/constants/yaMetrikaGoals.js";
|
|
import BaseViewWrapper from "@/views/BaseViewWrapper.vue";
|
|
import Price from "@/components/ProductItem/Price.vue";
|
|
|
|
const route = useRoute();
|
|
const yaMetrika = useYaMetrikaStore();
|
|
const searchStore = useSearchStore();
|
|
const searchInput = ref(null);
|
|
const debouncedSearch = useDebounceFn(() => searchStore.performSearch(), 500);
|
|
|
|
onMounted(async () => {
|
|
window.document.title = 'Поиск';
|
|
yaMetrika.pushHit(route.path, {
|
|
title: 'Поиск',
|
|
});
|
|
yaMetrika.reachGoal(YA_METRIKA_GOAL.VIEW_SEARCH);
|
|
});
|
|
</script>
|