<template> <div class="row"> <div class="col-lg-3 col-xl-2"> </div> <div class="col-lg-9 col-xl-8"> <div class="w-100" v-for="(group, index) in grouped_items" :key="index"> <div v-if="group.length>0" class="card card-list-item bg-dark w-100 mb-3"> <div class="card-header" :class="'bg-'+sections[index].color" @click="toggle(index)"> <font-awesome-icon icon="angle-right" style="width: 1em;" v-if="collapsed[index]"/> <font-awesome-icon icon="angle-down" style="width: 1em;" v-else/> <slot name="section_header" :index="index" :section="sections[index]" :count="group.length"/> </div> <table class="card-body collapse table table-striped table-dark" :class="{show: !collapsed[index]}"> <slot class="row" v-for="item in group" name="section_body" :item="item"/> </table> </div> </div> </div> </div> </template> <script> import {mapGetters} from "vuex"; export default { name: 'CollapsableCards', props: { columns: { type: Array, required: true, }, items: { type: Array, required: true, }, sections: { type: Array, required: true, }, keyName: { type: String, required: true, }, }, data() { return { collapsed: [], symbols: ['▲', '▼', '▶', '◀'], }; }, created() { const query = this.route ? (this.route.query ? this.route.query.collapsed : null) : null; if (query !== null && query !== undefined) { this.collapsed = this.unpackInt(parseInt(query), this.sections.length); } else { this.collapsed = this.sections.map(() => true); } }, computed: { grouped_items() { return this.sections.map(section => this.items.filter(item => item[this.keyName] === section.slug)); }, ...mapGetters(['route']), }, methods: { packInt(arr) { return arr.reduce((a, e, i) => a + (e ? 0 : 2 ** i), 0); }, unpackInt(n, l) { return [...Array(l)].map((e, i) => (n & 2 ** i) === 0); }, toggle(index) { const collapsed = [...this.collapsed] collapsed[index] = !collapsed[index]; this.collapsed = collapsed; }, }, watch: { collapsed: { handler() { const encoded = this.packInt(this.collapsed).toString() if (this.route.query.collapsed !== encoded) this.$router.push({ ...this.route, query: {...this.route.query, collapsed: encoded} }); }, deep: true, }, }, }; </script>