Unify section search headers
This commit is contained in:
@@ -433,37 +433,11 @@ function decrementSelected(group: ProductGroup) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="space-y-5">
|
<section class="space-y-5">
|
||||||
<h1 class="text-3xl font-extrabold text-[#0f2f20]">Каталог</h1>
|
<UiSectionSearchHero
|
||||||
|
|
||||||
<label class="input input-bordered flex w-full items-center gap-3 rounded-full bg-white">
|
|
||||||
<svg
|
|
||||||
class="h-4 w-4 shrink-0 text-base-content/45"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M14.1667 14.1667L17.5 17.5"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="1.6"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
/>
|
|
||||||
<circle
|
|
||||||
cx="8.75"
|
|
||||||
cy="8.75"
|
|
||||||
r="5.83333"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="1.6"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<input
|
|
||||||
v-model="search"
|
v-model="search"
|
||||||
type="text"
|
title="Каталог"
|
||||||
class="grow"
|
search-placeholder="Поиск по артикулу, типу товара или параметрам"
|
||||||
placeholder="Поиск по артикулу, типу товара или параметрам"
|
/>
|
||||||
>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div v-if="loading" class="alert surface-card border-0">Загрузка каталога...</div>
|
<div v-if="loading" class="alert surface-card border-0">Загрузка каталога...</div>
|
||||||
<div v-else-if="error" class="alert alert-error">{{ error.message }}</div>
|
<div v-else-if="error" class="alert alert-error">{{ error.message }}</div>
|
||||||
|
|||||||
54
app/components/ui/SectionSearchHero.vue
Normal file
54
app/components/ui/SectionSearchHero.vue
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
title: string;
|
||||||
|
modelValue: string;
|
||||||
|
searchPlaceholder: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [value: string];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
function updateValue(event: Event) {
|
||||||
|
emit('update:modelValue', (event.target as HTMLInputElement).value);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="space-y-5">
|
||||||
|
<h1 class="text-3xl font-extrabold text-[#0f2f20]">{{ props.title }}</h1>
|
||||||
|
|
||||||
|
<label class="input input-bordered flex w-full items-center gap-3 rounded-full bg-white">
|
||||||
|
<svg
|
||||||
|
class="h-4 w-4 shrink-0 text-base-content/45"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M14.1667 14.1667L17.5 17.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.6"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
<circle
|
||||||
|
cx="8.75"
|
||||||
|
cy="8.75"
|
||||||
|
r="5.83333"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.6"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<input
|
||||||
|
:value="props.modelValue"
|
||||||
|
type="text"
|
||||||
|
class="grow"
|
||||||
|
:placeholder="props.searchPlaceholder"
|
||||||
|
@input="updateValue"
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -41,18 +41,15 @@ const filteredTransactions = computed(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="space-y-6">
|
<section class="space-y-6">
|
||||||
<div class="flex flex-col gap-3 md:flex-row md:items-end md:justify-between">
|
<UiSectionSearchHero
|
||||||
<div class="manager-hero">
|
v-model="search"
|
||||||
<p class="manager-eyebrow">Бонусы</p>
|
title="Бонусы"
|
||||||
<h1 class="manager-title">Отдельный раздел для бонусной системы</h1>
|
search-placeholder="Пользователь, причина, заказ или сумма"
|
||||||
<p class="manager-copy">Здесь остаются история начислений и заявки на вывод, без смешивания с клиентами.</p>
|
>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2">
|
<div class="flex flex-wrap gap-2">
|
||||||
<NuxtLink to="/bonus-system/referrals/new" class="btn btn-secondary border-0">Создать связь</NuxtLink>
|
<NuxtLink to="/bonus-system/referrals/new" class="btn btn-secondary border-0">Создать связь</NuxtLink>
|
||||||
<NuxtLink to="/bonus-system/transactions/new" class="btn btn-primary border-0">Добавить бонус</NuxtLink>
|
<NuxtLink to="/bonus-system/transactions/new" class="btn btn-primary border-0">Добавить бонус</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid gap-4 lg:grid-cols-3">
|
<div class="grid gap-4 lg:grid-cols-3">
|
||||||
<div class="manager-stat-card">
|
<div class="manager-stat-card">
|
||||||
@@ -68,18 +65,7 @@ const filteredTransactions = computed(() => {
|
|||||||
<p class="manager-stat-value">{{ withdrawals.length }}</p>
|
<p class="manager-stat-value">{{ withdrawals.length }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</UiSectionSearchHero>
|
||||||
<div class="surface-card rounded-3xl p-4 md:p-5">
|
|
||||||
<label class="form-control">
|
|
||||||
<span class="label-text">Search</span>
|
|
||||||
<input
|
|
||||||
v-model="search"
|
|
||||||
type="text"
|
|
||||||
class="input manager-field w-full"
|
|
||||||
placeholder="Пользователь, причина, заказ или сумма"
|
|
||||||
>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid gap-4 xl:grid-cols-[1.1fr_0.9fr]">
|
<div class="grid gap-4 xl:grid-cols-[1.1fr_0.9fr]">
|
||||||
<div class="surface-card rounded-3xl p-5">
|
<div class="surface-card rounded-3xl p-5">
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ async function submitCart() {
|
|||||||
<div class="surface-card rounded-3xl p-4 md:p-5">
|
<div class="surface-card rounded-3xl p-4 md:p-5">
|
||||||
<h2 class="text-lg font-bold text-[#123824]">Адрес доставки</h2>
|
<h2 class="text-lg font-bold text-[#123824]">Адрес доставки</h2>
|
||||||
|
|
||||||
<div v-if="deliveryAddressesQuery.loading" class="alert mt-3 surface-card">
|
<div v-if="deliveryAddressesQuery.loading.value" class="alert mt-3 surface-card">
|
||||||
Загружаем адреса...
|
Загружаем адреса...
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="!hasDeliveryAddresses" class="alert alert-warning mt-3">
|
<div v-else-if="!hasDeliveryAddresses" class="alert alert-warning mt-3">
|
||||||
|
|||||||
@@ -54,24 +54,13 @@ const filteredOrders = computed(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="space-y-6">
|
<section class="space-y-6">
|
||||||
<div class="manager-hero">
|
<UiSectionSearchHero
|
||||||
<p class="manager-eyebrow">Заказы клиентов</p>
|
v-model="search"
|
||||||
<h1 class="manager-title">Только список заказов и быстрый поиск</h1>
|
title="Заказы клиентов"
|
||||||
<p class="manager-copy">Карточки заказов без форм на странице списка. Детали и действия открываются внутри заказа.</p>
|
search-placeholder="Номер заказа, клиент, адрес или товар"
|
||||||
</div>
|
>
|
||||||
|
|
||||||
<div class="surface-card rounded-3xl p-4 md:p-5">
|
<div class="surface-card rounded-3xl p-4 md:p-5">
|
||||||
<div class="grid gap-3 md:grid-cols-[1fr_auto]">
|
<div class="grid gap-3 md:grid-cols-[1fr_auto]">
|
||||||
<label class="form-control">
|
|
||||||
<span class="label-text">Search</span>
|
|
||||||
<input
|
|
||||||
v-model="search"
|
|
||||||
type="text"
|
|
||||||
class="input manager-field w-full"
|
|
||||||
placeholder="Номер заказа, клиент, адрес или товар"
|
|
||||||
>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label class="form-control md:min-w-60">
|
<label class="form-control md:min-w-60">
|
||||||
<span class="label-text">Фильтр</span>
|
<span class="label-text">Фильтр</span>
|
||||||
<select v-model="statusFilter" class="select manager-field w-full">
|
<select v-model="statusFilter" class="select manager-field w-full">
|
||||||
@@ -83,6 +72,7 @@ const filteredOrders = computed(() => {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</UiSectionSearchHero>
|
||||||
|
|
||||||
<div v-if="ordersQuery.loading.value" class="manager-empty-state">
|
<div v-if="ordersQuery.loading.value" class="manager-empty-state">
|
||||||
Загружаем заказы...
|
Загружаем заказы...
|
||||||
|
|||||||
@@ -60,35 +60,21 @@ const filteredClients = computed(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="space-y-6">
|
<section class="space-y-6">
|
||||||
<div class="flex flex-col gap-3 md:flex-row md:items-end md:justify-between">
|
<UiSectionSearchHero
|
||||||
<div class="manager-hero">
|
v-model="search"
|
||||||
<p class="manager-eyebrow">Клиенты</p>
|
title="Клиенты"
|
||||||
<h1 class="manager-title">Карточки клиентов без лишней нагрузки</h1>
|
search-placeholder="Компания, контакт, email или ИНН"
|
||||||
<p class="manager-copy">Список заявок и клиентов, с которыми менеджер уже работает.</p>
|
>
|
||||||
|
<div class="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
|
||||||
|
<div class="manager-mini-card text-sm text-[#123824] md:w-56">
|
||||||
|
Всего карточек: <span class="font-semibold">{{ filteredClients.length }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<NuxtLink to="/clients/invite" class="btn btn-primary border-0">
|
<NuxtLink to="/clients/invite" class="btn btn-primary border-0">
|
||||||
Пригласить клиента
|
Пригласить клиента
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
|
</UiSectionSearchHero>
|
||||||
<div class="surface-card rounded-3xl p-4 md:p-5">
|
|
||||||
<div class="grid gap-3 md:grid-cols-[1fr_auto] md:items-end">
|
|
||||||
<label class="form-control">
|
|
||||||
<span class="label-text">Search</span>
|
|
||||||
<input
|
|
||||||
v-model="search"
|
|
||||||
type="text"
|
|
||||||
class="input manager-field w-full"
|
|
||||||
placeholder="Компания, контакт, email или ИНН"
|
|
||||||
>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="manager-mini-card text-sm text-[#123824] md:w-56">
|
|
||||||
Всего карточек: <span class="font-semibold">{{ filteredClients.length }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="clientsQuery.loading.value" class="manager-empty-state">
|
<div v-if="clientsQuery.loading.value" class="manager-empty-state">
|
||||||
Загружаем клиентов...
|
Загружаем клиентов...
|
||||||
|
|||||||
@@ -48,20 +48,13 @@ const filteredOrders = computed(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="space-y-6">
|
<section class="space-y-6">
|
||||||
<h1 class="text-3xl font-extrabold text-[#0f2f20]">Заказы</h1>
|
<UiSectionSearchHero
|
||||||
|
v-model="search"
|
||||||
|
title="Мои заказы"
|
||||||
|
search-placeholder="Номер заказа или товар"
|
||||||
|
>
|
||||||
<div class="surface-card rounded-3xl p-4 md:p-5">
|
<div class="surface-card rounded-3xl p-4 md:p-5">
|
||||||
<div class="grid gap-3 md:grid-cols-[1fr_auto]">
|
<div class="grid gap-3 md:grid-cols-[1fr_auto]">
|
||||||
<label class="form-control">
|
|
||||||
<span class="label-text">Поиск</span>
|
|
||||||
<input
|
|
||||||
v-model="search"
|
|
||||||
type="text"
|
|
||||||
class="input input-bordered w-full"
|
|
||||||
placeholder="Номер заказа или товар"
|
|
||||||
>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label class="form-control md:min-w-60">
|
<label class="form-control md:min-w-60">
|
||||||
<span class="label-text">Фильтр</span>
|
<span class="label-text">Фильтр</span>
|
||||||
<select v-model="statusFilter" class="select select-bordered w-full">
|
<select v-model="statusFilter" class="select select-bordered w-full">
|
||||||
@@ -73,6 +66,7 @@ const filteredOrders = computed(() => {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</UiSectionSearchHero>
|
||||||
|
|
||||||
<div v-if="allOrders.loading.value" class="alert surface-card border-0">Загрузка заказов...</div>
|
<div v-if="allOrders.loading.value" class="alert surface-card border-0">Загрузка заказов...</div>
|
||||||
<div v-else-if="filteredOrders.length === 0" class="alert surface-card border-0">
|
<div v-else-if="filteredOrders.length === 0" class="alert surface-card border-0">
|
||||||
|
|||||||
Reference in New Issue
Block a user