work-sklizkiygad ec014db3f9 first commit
2023-02-01 17:36:25 +03:00

164 lines
4.3 KiB
Vue

<template>
<div class="menu">
<div class="menu__navigation">
<div class="menu__navigation-container">
<div
class="menu__navigation-item"
v-for="category in menuStore.categories"
:class="{ 'menu__navigation-item--active': selectedCategory === category }"
:key="category.id"
@click="changeCategory(category)"
:ref="(el)=>refCategories.push(el as Element)"
>
{{ category.title }}
</div>
</div>
</div>
<div class="menu__list" ref="refMenuList">
<TransitionGroup name="menu__list-item--transition">
<MenuItem
class="menu__list-item"
v-for="item in selectedMenuItems"
:key="Math.random() * (item.id + 1)"
:item="item"
></MenuItem>
</TransitionGroup>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from "vue";
import { category } from "@/types";
import { useMenuApi } from "@/composables/api";
import { useMenuStore } from "@/store";
import MenuItem from "./MenuItem.vue";
const menuStore = useMenuStore();
const menuApi = useMenuApi();
const refCategories = ref<Element[]>([]);
const refMenuList = ref<Element>();
init();
function init() {
menuStore.categories = menuApi.getCategories();
menuStore.menuItems = menuApi.getMenuItems();
}
const selectedMenuItems = computed(() =>
selectedCategory.value == null ? menuStore.menuItems : menuStore.menuItems.filter((x) => x.categoryId === selectedCategory.value?.id)
);
const selectedCategory = ref<category | undefined>(undefined);
function changeCategory(category: category) {
if (selectedCategory.value === category) {
selectedCategory.value = undefined;
} else {
selectedCategory.value = category;
const selectedCategoryElement = refCategories.value[menuStore.categories.indexOf(selectedCategory.value)];
selectedCategoryElement.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
}
setTimeout(() => {
refMenuList.value?.scroll(0, 0);
}, 180);
}
</script>
<style lang="scss">
.menu {
position: absolute;
top: 0;
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
overflow: hidden;
&__navigation {
position: relative;
flex: 0 1 auto;
background: color("main-background");
box-shadow: 0 r(4) r(18) 0 rgba(0, 0, 0, 0.12), 0 r(7) r(10) r(-5) rgba(0, 0, 0, 0.15);
z-index: 1;
user-select: none;
}
&__navigation-container {
display: flex;
overflow-x: auto;
padding: 0 r(35);
@media (max-width: $mobileWidth) {
-ms-overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
}
&__navigation-item {
position: relative;
padding: r(15);
font-size: r(24);
font-weight: 300;
text-transform: capitalize;
white-space: nowrap;
cursor: pointer;
&::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: r(4);
border-radius: r(2);
background: color("theme-color");
opacity: 0;
z-index: 1;
transition: opacity 0.18s ease;
}
&--active {
&::after {
opacity: 1;
}
}
}
&__list {
flex: 1;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
padding: r(10) 0 r(20) 0;
overflow: auto;
}
&__list-item {
flex: 0 0 auto;
--transition-duration: 0.18s;
&--transition {
&-enter-active {
transition: opacity var(--transition-duration) var(--transition-duration) ease;
}
&-leave-active {
transition: opacity var(--transition-duration) ease;
}
&-enter-from,
&-leave-to {
opacity: 0;
}
}
}
}
</style>