feat: ajout tableau dynamiques

This commit is contained in:
Kazhnuz 2023-02-08 20:42:54 +01:00
parent ce2fdfc08f
commit 52807890ec

View file

@ -0,0 +1,224 @@
<script lang="ts" setup>
import { computed, ref, onMounted } from "vue";
import type { PropType } from "vue";
import axios from "axios";
interface TableField {
key: string;
label: string;
canBeFiltered?: boolean;
}
interface Filters {
[key: string]: boolean;
}
interface FilterList {
[key: string]: { title: string; filters: Filters };
}
interface TableItem {
[key: string]: unknown;
}
const props = defineProps({
fields: {
type: Array as PropType<TableField[]>,
default: () => [],
},
files: {
type: Array as PropType<string[]>,
default: () => [],
},
});
const items = ref([] as TableItem[]);
const filters = ref({} as FilterList);
const pageNumber = ref(0);
const elemByPage = ref(10);
const displayedFieldKeys = computed(() => {
return Object.entries(props.fields).map(([key, value]) => value.key);
});
function haveFilter(filterName: string) {
for (const val in filters.value[filterName].filters) {
if (
Object.prototype.hasOwnProperty.call(
filters.value[filterName].filters,
val
)
) {
if (filters.value[filterName].filters[val]) {
console.log(filterName, true);
return true;
}
}
}
console.log(filterName, false);
return false;
}
const filteredItems = computed(() => {
var filteredItem = items.value as TableItem[];
for (const filter in filters.value) {
if (haveFilter(filter)) {
filteredItem = filteredItem.filter((value) => {
return filters.value[filter].filters[value[filter] as string];
});
}
}
return filteredItem;
});
const paginatedList = computed(() => {
var filteredItem = filteredItems.value as TableItem[];
filteredItem = filteredItem.filter((value, index) => {
const pageBegin = pageNumber.value * elemByPage.value;
return index >= pageBegin && index < pageBegin + elemByPage.value;
});
return filteredItem;
});
onMounted(() => {
for (const field of props.fields) {
if (field.canBeFiltered) {
filters.value[field.key] = {
title: field.label,
filters: {} as Filters,
};
}
}
for (const file of props.files) {
const listItems = `/jdr/objets/${file}.json`;
axios.get(listItems).then((response) => {
items.value = items.value.concat(response.data);
response.data.forEach((element: TableItem) => {
for (const key in element) {
if (Object.prototype.hasOwnProperty.call(element, key)) {
if (filters.value[key]) {
filters.value[key].filters[element[key] as string] = false;
}
}
}
});
});
}
});
function switchFilter(filterSet: string | number, filterName: string | number) {
if (filters.value[filterSet]?.filters[filterName] !== undefined) {
filters.value[filterSet].filters[filterName] =
!filters.value[filterSet].filters[filterName];
}
setPage(0);
}
function removeFilter(filterSet: string | number) {
for (const val in filters.value[filterSet].filters) {
if (
Object.prototype.hasOwnProperty.call(
filters.value[filterSet].filters,
val
)
) {
filters.value[filterSet].filters[val] = false;
}
}
setPage(0);
}
const getTotalPage = computed(() => {
return Math.floor((filteredItems.value.length - 1) / elemByPage.value);
});
function setPage(page: number) {
pageNumber.value = page;
}
function canGo(rel: number) {
return (
pageNumber.value + rel >= 0 && pageNumber.value + rel <= getTotalPage.value
);
}
function go(rel: number) {
if (canGo(rel)) {
setPage(pageNumber.value + rel);
}
}
</script>
<template>
<div class="small-text" v-for="(filter, key) in filters" :key="key">
<strong>{{ filter.title }} : </strong>
<button
v-for="(isTrue, filterName) in filter.filters"
:key="filterName"
class="btn-small mb-0"
:class="{ 'btn-grey': !isTrue, 'btn-primary': isTrue }"
@click="switchFilter(key, filterName)"
>
{{ filterName }}
</button>
<button class="btn-small btn-secondary mb-0" @click="removeFilter(key)">
Vider filtres
</button>
</div>
<table class="pb-0 table-auto">
<thead>
<tr>
<th v-for="field in fields" :key="field.key">
{{ field.label }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) of paginatedList" :key="index">
<td v-for="(key, index2) in displayedFieldKeys" :key="index2">
{{ item[key] }}
</td>
</tr>
</tbody>
</table>
<div class="d-flex f-between f-middle nextprevious small-text">
<div>
<strong class="btn m-0 pages pl-0">
Page {{ pageNumber + 1 }} / {{ getTotalPage + 1 }}
</strong>
</div>
<div>
<button
class="btn btn-grey m-0 mr-1"
:class="{ 'bg-grey': !canGo(-1), 'btn-secondary': canGo(-1) }"
@click="go(-1)"
>
Page précédante
</button>
<button
class="btn btn-grey m-0"
:class="{ 'bg-grey': !canGo(1), 'btn-secondary': canGo(1) }"
@click="go(1)"
>
Page suivante
</button>
</div>
</div>
</template>
<style lang="scss" scoped>
.small-text {
font-size: 0.8rem;
padding-bottom: 0.5rem;
}
.pages {
font-weight: 600;
}
</style>