refactor: move spa to frontend folder
This commit is contained in:
94
frontend/spa/src/views/Search.vue
Normal file
94
frontend/spa/src/views/Search.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div class="max-w-3xl mx-auto p-4 space-y-6 pb-20">
|
||||
<h2 class="text-2xl mb-5 text-center">Поиск</h2>
|
||||
|
||||
<div class="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
|
||||
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>
|
||||
|
||||
<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>
|
||||
<p>{{ product.price }}</p>
|
||||
</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>
|
||||
</div>
|
||||
</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";
|
||||
|
||||
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>
|
||||
Reference in New Issue
Block a user