Refactoring Move PillRadioButtons and Dropdown to ui components

This commit is contained in:
Lorenz Padberg 2023-08-21 10:41:29 +02:00
parent 040064c68b
commit 0648497d50
3 changed files with 97 additions and 84 deletions

View File

@ -1,18 +1,23 @@
<template> <template>
<div class="module-filter"> <div class="module-filter">
<div class="module-filter__filterselection"> <div class="module-filter__filterselection">
<ModuleFilterDropdown class="module-filter__dropdown" <Dropdown class="module-filter__dropdown"
:selected-item="selectedCategory" :selected-item="selectedCategory"
:items="firstLevelCategories" :items="firstLevelCategories"
@update:selectedItem="newItem => selectedCategory = newItem" @update:selectedItem="newItem => selectedCategory = newItem"
></ModuleFilterDropdown> ></Dropdown>
<ModuleFilterDropdown <Dropdown
class="module-filter__dropdown" class="module-filter__dropdown"
:selected-item="selectedLernfeld" :selected-item="selectedLernfeld"
:items="lernfeldOptions" :items="lernfeldOptions"
@update:selectedItem="newItem => selectedLernfeld = newItem" @update:selectedItem="newItem => selectedLernfeld = newItem"
></ModuleFilterDropdown> ></Dropdown>
<pill-radio-buttons :selectableItems="languageOptions"
:defaultSelectedItem="initialLanguage"
class="module-filter__language-selection"
@update:selectedItem="item => selectedLanguage = item"/>
</div> </div>
<div class="topic__modules"> <div class="topic__modules">
<module-teaser <module-teaser
@ -31,14 +36,27 @@
import ModuleTeaser from "@/components/modules/ModuleTeaser.vue"; import ModuleTeaser from "@/components/modules/ModuleTeaser.vue";
import gql from "graphql-tag"; import gql from "graphql-tag";
import {useQuery, useMutation} from "@vue/apollo-composable"; import {useQuery, useMutation} from "@vue/apollo-composable";
import ModuleFilterDropdown from "@/components/modules/ModuleFilterDropdown.vue"; import Dropdown from "@/components/ui/Dropdown.vue";
import PillRadioButtons from "@/components/ui/PillRadioButtons.vue";
// TODO: Fix console warnings... onBeforeUnmount is called when there is no active component instance to be associated with.
// TODO: Improve Typing
const props = defineProps<{ const props = defineProps<{
modules: Object; modules: Array<Object>;
me: any; me: any;
}>(); }>();
const languageOptions: Array<{ id: number, label: string }> = ref([
{id: 1, label: 'De'},
{id: 2, label: 'Fr'},
{id: 3, label: 'En'}
])
const initialLanguage = languageOptions.value[0]
const selectedLanguage = ref(initialLanguage)
const {result: moduleCategoriesResult} = useQuery(gql` const {result: moduleCategoriesResult} = useQuery(gql`
query ModuleCategoriesQuery { query ModuleCategoriesQuery {
@ -86,8 +104,6 @@
return filterModules(); return filterModules();
}); });
// "$flavor.textInstrumentFilterShowAll"
function loadDefaultCategory(me) { function loadDefaultCategory(me) {
return me?.lastModuleCategory || nullCategory; return me?.lastModuleCategory || nullCategory;
} }
@ -115,14 +131,18 @@
}); });
} }
updateLastModuleCategory(selectedCategory.value); updateLastModuleCategory(selectedCategory.value);
filteredModules = filterByLanguage(selectedLanguage.value, filteredModules);
return filteredModules; return filteredModules;
}
function filterByLanguage(language: Object, modules: Object) {
console.log("selectedLanguage", selectedLanguage.value);
return modules
} }
function updateLastModuleCategory(moduleCategory) { function updateLastModuleCategory(moduleCategory: Object) {
console.log(moduleCategory); console.log(moduleCategory);
const {mutate: updateLastModuleCategory} = useMutation(gql` const {mutate: updateLastModuleCategory} = useMutation(gql`
@ -150,58 +170,65 @@
@import 'styles/helpers'; @import 'styles/helpers';
.module-filter { .module-filter {
// TODO: how do I correcty set the with of the whole thig including the grid for the modules?
width: 75%;
&__filterselection { &__filterselection {
@include desktop;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-between;
} }
&__dropdown { &__dropdown {
margin-right: 20px; margin-right: 20px;
width: 100%; width: 300px;
@include desktop {
width: 300px;
}
} }
&__module-filter { &__language-selection {
width: 100%; margin-left: auto;
}
.topic {
display: grid;
padding: $large-spacing $small-spacing;
@include desktop {
padding: $large-spacing 0;
}
grid-template-columns: 1fr;
@include desktop {
grid-template-columns: 300px 1fr;
}
&__modules {
margin-top: 40px;
display: flex;
flex-wrap: wrap;
@supports (display: grid) {
display: grid;
}
grid-column-gap: $large-spacing;
grid-row-gap: $large-spacing;
@include desktop {
grid-template-columns: repeat(3, minmax(auto, 380px));
}
}
&__teaser {
color: $color-charcoal-dark;
width: 90%;
@include lead-paragraph;
margin-bottom: $large-spacing;
}
} }
} }
.topic {
display: grid;
padding: $large-spacing $small-spacing;
@include desktop {
padding: $large-spacing 0;
}
grid-template-columns: 1fr;
@include desktop {
grid-template-columns: 300px 1fr;
}
&__modules {
margin-top: 40px;
display: flex;
flex-wrap: wrap;
@supports (display: grid) {
display: grid;
}
grid-column-gap: $large-spacing;
grid-row-gap: $large-spacing;
@include desktop {
grid-template-columns: repeat(3, minmax(auto, 380px));
}
}
&__teaser {
color: $color-charcoal-dark;
width: 90%;
@include lead-paragraph;
margin-bottom: $large-spacing;
}
}
</style> </style>

View File

@ -27,8 +27,7 @@
v-for="item in items" v-for="item in items"
:key="item.id" :key="item.id"
@click="updateSelectedItem(item)" @click="updateSelectedItem(item)"
> ><span>{{ item.name }}</span>
<i v-if="selectedItem === item">A</i><span>{{ item.name }}</span>
</li> </li>
@ -43,7 +42,6 @@
import ChevronDown from "@/components/icons/ChevronDown.vue"; import ChevronDown from "@/components/icons/ChevronDown.vue";
const props = defineProps<{ const props = defineProps<{
mobile: boolean,
selectedItem: Object, selectedItem: Object,
items: Object[], items: Object[],
}>(); }>();
@ -55,7 +53,6 @@
} }
function updateSelectedItem(item: Object) { function updateSelectedItem(item: Object) {
console.log('updateSelectedItem', item);
emit('update:selectedItem', item); emit('update:selectedItem', item);
showPopover.value = false; showPopover.value = false;
} }
@ -118,6 +115,7 @@
.widget-popover { .widget-popover {
width: 100%; width: 100%;
border-radius: 12px; border-radius: 12px;
margin-top: 4px;
.popover-links__link { .popover-links__link {
&:hover { &:hover {

View File

@ -1,48 +1,36 @@
<template> <template>
<div class="pill-radio"> <div class="pill-radio">
<button <button
:class="['pill-radio__button', { 'pill-radio__button--active': item.id === selectedId }]" :class="['pill-radio__button', { 'pill-radio__button--active': item === selectedItem }]"
v-for="item in items" v-for="item in props.selectableItems"
:key="item.id" :key="item.id"
@click="selectButton(item.id)" @click="updateSelectedItem(item)"
> >
{{ item.label }} {{ item.label }}
</button> </button>
</div> </div>
</template> </template>
<script lang="ts" setup> <script setup lang="ts">
import {ref, watch, PropType} from 'vue'; import {ref} from 'vue';
const emit = defineEmits(['update:selectedItem']);
// const { items } = defineProps({ const props = defineProps<{
// items: { selectableItems: Object;
// type: Array as PropType<{ id: number; label: string }[]>, defaultSelectedItem: Object;
// required: true }>();
// }
// });
const selectedItem = ref(props.defaultSelectedItem)
const items = ref([ function updateSelectedItem(item: object) {
{id: 1, label: 'De'}, emit('update:selectedItem', item);
{id: 2, label: 'Fr'}, selectedItem.value = item
{id: 3, label: 'En'}
])
const selectedId = ref(1)
function selectButton(id: number) {
selectedId.value = id
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.pill-radio { .pill-radio {
display: flex; display: flex;
overflow: hidden; overflow: hidden;