269 lines
No EOL
5.5 KiB
Vue
269 lines
No EOL
5.5 KiB
Vue
<template>
|
|
<div class="catalog" ref="blockRef">
|
|
<button
|
|
@click="setBlock(!isBlockOpen)"
|
|
class="catalog__button"
|
|
:class="[{ active: isBlockOpen }]"
|
|
>
|
|
{{ t('header.catalog.title') }}
|
|
<span>▽</span>
|
|
</button>
|
|
<div class="container">
|
|
<div class="categories" :class="[{active: isBlockOpen}]">
|
|
<div class="categories__block" v-if="categories.length > 0">
|
|
<div class="categories__left">
|
|
<p
|
|
v-for="category in categories"
|
|
:key="category.node.uuid"
|
|
:class="[{ active: category.node.uuid === activeCategory.uuid }]"
|
|
@click="setActiveCategory(category.node)"
|
|
>
|
|
{{ category.node.name }}
|
|
</p>
|
|
</div>
|
|
<div class="categories__main">
|
|
<div
|
|
class="categories__main-block"
|
|
v-for="mainChildren in activeCategory.children"
|
|
:key="mainChildren.uuid"
|
|
>
|
|
<nuxt-link-locale
|
|
:to="`/catalog/${mainChildren.slug}`"
|
|
class="categories__main-link"
|
|
@click="setBlock(false)"
|
|
>
|
|
{{ mainChildren.name }}
|
|
</nuxt-link-locale>
|
|
<div class="categories__main-list">
|
|
<nuxt-link-locale
|
|
v-for="children in mainChildren.children"
|
|
:key="children.uuid"
|
|
:to="`/catalog/${children.slug}`"
|
|
@click="setBlock(false)"
|
|
>
|
|
{{ children.name }}
|
|
</nuxt-link-locale >
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="categories__empty" v-else><p>{{ t('header.catalog.empty') }}</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type {ICategory} from '@types';
|
|
import {onClickOutside} from '@vueuse/core';
|
|
|
|
const { t } = useI18n();
|
|
const categoryStore = useCategoryStore();
|
|
|
|
const categories = computed(() => categoryStore.categories);
|
|
|
|
const isBlockOpen = ref<boolean>(false);
|
|
const setBlock = (state: boolean) => {
|
|
isBlockOpen.value = state;
|
|
};
|
|
|
|
// TODO: add loading state
|
|
|
|
const blockRef = ref(null);
|
|
onClickOutside(blockRef, () => setBlock(false));
|
|
|
|
const activeCategory = ref<ICategory>(categories.value[0]?.node);
|
|
const setActiveCategory = (category: ICategory) => {
|
|
activeCategory.value = category;
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.catalog {
|
|
&__button {
|
|
cursor: pointer;
|
|
border-radius: $default_border_radius;
|
|
background-color: rgba($accent, 0.2);
|
|
border: 1px solid $accent;
|
|
padding: 5px 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
transition: 0.2s;
|
|
|
|
color: $accent;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
|
|
@include hover {
|
|
background-color: $accent;
|
|
color: $white;
|
|
}
|
|
|
|
& span {
|
|
transition: 0.2s;
|
|
font-size: 26px;
|
|
}
|
|
|
|
&.active {
|
|
background-color: $accent;
|
|
color: $white;
|
|
|
|
& span {
|
|
transform: rotate(-180deg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.container {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 110%;
|
|
transform: translateX(-50%);
|
|
width: 100%;
|
|
}
|
|
|
|
.categories {
|
|
border-radius: $default_border_radius;
|
|
width: 100%;
|
|
background-color: $white;
|
|
box-shadow: 0 0 15px 1px $accentLight;
|
|
display: grid;
|
|
grid-template-rows: 0fr;
|
|
transition: grid-template-rows 0.2s ease;
|
|
overflow: hidden;
|
|
|
|
&.active {
|
|
grid-template-rows: 1fr;
|
|
}
|
|
|
|
& > * {
|
|
min-height: 0;
|
|
}
|
|
|
|
&__block {
|
|
display: grid;
|
|
grid-template-columns: 20% 80%;
|
|
max-height: 50vh;
|
|
}
|
|
|
|
&__columns {
|
|
& div {
|
|
padding: 20px 50px;
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
grid-column-gap: 30px;
|
|
grid-row-gap: 5px;
|
|
|
|
& p {
|
|
cursor: pointer;
|
|
padding: 5px 20px;
|
|
transition: 0.2s;
|
|
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
|
|
@include hover {
|
|
color: $accent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
&__left {
|
|
flex-shrink: 0;
|
|
padding-block: 10px;
|
|
overflow: auto;
|
|
|
|
& p {
|
|
cursor: pointer;
|
|
transition: 0.2s;
|
|
flex-shrink: 0;
|
|
padding: 10px;
|
|
border-left: 3px solid $white;
|
|
font-weight: 700;
|
|
|
|
@include hover {
|
|
color: $accent;
|
|
}
|
|
|
|
&.active {
|
|
border-color: $accent;
|
|
color: $accent;
|
|
}
|
|
}
|
|
}
|
|
|
|
&__main {
|
|
padding: 20px;
|
|
border-left: 2px solid $accentDark;
|
|
overflow: auto;
|
|
|
|
&-block {
|
|
padding-bottom: 15px;
|
|
border-bottom: 1px solid #eeeeee;
|
|
margin-bottom: 15px;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
|
|
&-link {
|
|
position: relative;
|
|
width: fit-content;
|
|
cursor: pointer;
|
|
|
|
font-weight: 600;
|
|
font-size: 16px;
|
|
|
|
&::after {
|
|
content: "";
|
|
position: absolute;
|
|
bottom: -2px;
|
|
left: 0;
|
|
height: 2px;
|
|
width: 0;
|
|
transition: all .3s ease;
|
|
background-color: $accent;
|
|
}
|
|
|
|
@include hover {
|
|
&::after {
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
&-list {
|
|
margin-top: 10px;
|
|
display: grid;
|
|
grid-template-columns: repeat(3,1fr);
|
|
grid-column-gap: 30px;
|
|
grid-row-gap: 5px;
|
|
|
|
& a {
|
|
cursor: pointer;
|
|
transition: 0.1s;
|
|
|
|
font-size: 14px;
|
|
|
|
@include hover {
|
|
color: $accent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
&__empty {
|
|
& p {
|
|
padding: 20px;
|
|
text-align: center;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
}
|
|
</style> |