UI коструктора отчетов
This commit is contained in:
104
resources/js/Pages/Analytics/Components/TemplatePickerModal.vue
Normal file
104
resources/js/Pages/Analytics/Components/TemplatePickerModal.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { NModal, NInput, NScrollbar, NGrid, NGi, NText } from 'naive-ui'
|
||||
import { TbSearch } from 'vue-icons-plus/tb'
|
||||
import PresetCard from './PresetCard.vue'
|
||||
|
||||
const props = defineProps({
|
||||
show: { type: Boolean, default: false },
|
||||
presets: { type: Array, default: () => [] },
|
||||
categories: { type: Array, default: () => [] },
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:show', 'select'])
|
||||
|
||||
const search = ref('')
|
||||
const activeCategory = ref('Все')
|
||||
|
||||
const filtered = computed(() => props.presets.filter((p) => {
|
||||
const byCat = activeCategory.value === 'Все' || p.category === activeCategory.value || p.key === 'blank'
|
||||
const byText = !search.value || p.label.toLowerCase().includes(search.value.toLowerCase())
|
||||
return byCat && byText
|
||||
}))
|
||||
|
||||
const pick = (preset) => {
|
||||
emit('select', preset)
|
||||
emit('update:show', false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NModal
|
||||
:show="show"
|
||||
preset="card"
|
||||
title="Шаблоны для отчёта"
|
||||
style="width: 860px; max-width: 94vw;"
|
||||
class="h-[580px]"
|
||||
@update:show="emit('update:show', $event)"
|
||||
>
|
||||
<template #header-extra>
|
||||
<NText depth="3" style="font-size: 13px;">Создавайте отчёт по шаблонам</NText>
|
||||
</template>
|
||||
|
||||
<div class="picker">
|
||||
<div class="picker-side">
|
||||
<NInput v-model:value="search" placeholder="Поиск" clearable size="small">
|
||||
<template #prefix><TbSearch :size="14" /></template>
|
||||
</NInput>
|
||||
<div class="cat-list">
|
||||
<div
|
||||
v-for="cat in categories"
|
||||
:key="cat"
|
||||
class="cat-item"
|
||||
:class="{ active: cat === activeCategory }"
|
||||
@click="activeCategory = cat"
|
||||
>
|
||||
{{ cat }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NScrollbar style="max-height: 60vh;" class="picker-main">
|
||||
<NGrid responsive="screen" cols="2 s:3" :x-gap="12" :y-gap="12" class="pt-0.5">
|
||||
<NGi v-for="preset in filtered" :key="preset.key">
|
||||
<PresetCard :preset="preset" @click="pick(preset)" />
|
||||
</NGi>
|
||||
</NGrid>
|
||||
</NScrollbar>
|
||||
</div>
|
||||
</NModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.picker {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
.picker-side {
|
||||
width: 180px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.cat-list {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
.cat-item {
|
||||
padding: 7px 10px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
.cat-item:hover {
|
||||
background: color-mix(in srgb, var(--primary-color) 8%, transparent);
|
||||
}
|
||||
.cat-item.active {
|
||||
background: color-mix(in srgb, var(--primary-color) 14%, transparent);
|
||||
color: var(--primary-color);
|
||||
font-weight: 600;
|
||||
}
|
||||
.picker-main {
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user