183 lines
6.1 KiB
Vue
183 lines
6.1 KiB
Vue
<script setup lang="ts">
|
|
import { computed, reactive, ref } from 'vue'
|
|
import TableComponent from '~/pages/widgets/TableComponent.vue'
|
|
import Component from '#models/component'
|
|
import ComponentType from '#models/component_type'
|
|
import { usePage } from '@inertiajs/vue3'
|
|
|
|
const { props } = usePage<{ components: Component[] }>()
|
|
const { components } = props
|
|
|
|
const usageDropdownOpen = ref(false)
|
|
const typeDropdownOpen = ref(false)
|
|
|
|
function toggleDropdown(dropdown: any) {
|
|
if (dropdown === 'usage') {
|
|
usageDropdownOpen.value = !usageDropdownOpen.value
|
|
typeDropdownOpen.value = false
|
|
} else if (dropdown === 'type') {
|
|
typeDropdownOpen.value = !typeDropdownOpen.value
|
|
usageDropdownOpen.value = false
|
|
}
|
|
}
|
|
|
|
const componentTypes = computed(() => {
|
|
const types = new Map<number, ComponentType>()
|
|
components.forEach((component) => {
|
|
if (!types.has(component.type.id)) {
|
|
types.set(component.type.id, component.type)
|
|
}
|
|
})
|
|
return Array.from(types.values())
|
|
})
|
|
|
|
// D├®finir le type de l'objet filters
|
|
interface Filters {
|
|
showUsed: boolean
|
|
showUnused: boolean
|
|
types: { [key: number]: boolean }
|
|
}
|
|
|
|
const filters = reactive<Filters>({
|
|
showUsed: false,
|
|
showUnused: true,
|
|
types: componentTypes.value.reduce(
|
|
(acc, type) => {
|
|
acc[type.id] = true
|
|
return acc
|
|
},
|
|
{} as { [key: number]: boolean }
|
|
),
|
|
})
|
|
|
|
const filteredComponents = computed(() => {
|
|
return components.filter((component) => {
|
|
const isUsed = filters.showUsed && component.computerId !== null
|
|
const isUnused = filters.showUnused && component.computerId === null
|
|
const isTypeSelected = filters.types[component.type.id]
|
|
return (isUsed || isUnused) && isTypeSelected
|
|
})
|
|
})
|
|
</script>
|
|
<template>
|
|
<div>
|
|
<!-- Dropdown pour les filtres -->
|
|
<div class="relative">
|
|
<h4 class="text-xl underline">Filters</h4>
|
|
<div class="flex gap-2">
|
|
<!-- Usage Dropdown -->
|
|
<div id="usage-selector" class="relative" style="width: fit-content">
|
|
<button
|
|
@click="toggleDropdown('usage')"
|
|
class="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-blue-700 transition text-center inline-flex items-center"
|
|
type="button"
|
|
>
|
|
Usage
|
|
<svg
|
|
class="w-4 h-4 ml-2"
|
|
aria-hidden="true"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M19 9l-7 7-7-7"
|
|
></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Dropdown menu -->
|
|
<div
|
|
v-show="usageDropdownOpen"
|
|
class="absolute right-0 z-20 py-2 mt-2 bg-white rounded-md shadow-xl"
|
|
>
|
|
<ul class="space-y-2 text-sm px-4 py-2">
|
|
<li class="flex items-center">
|
|
<input
|
|
id="unused"
|
|
type="checkbox"
|
|
v-model="filters.showUnused"
|
|
class="w-4 h-4 bg-gray-100 border-gray-300 rounded text-primary-600 focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500"
|
|
/>
|
|
<label
|
|
for="unused"
|
|
class="ml-2 text-sm font-medium text-gray-900 dark:text-gray-100"
|
|
>
|
|
Unused
|
|
</label>
|
|
</li>
|
|
<li class="flex items-center">
|
|
<input
|
|
id="used"
|
|
type="checkbox"
|
|
v-model="filters.showUsed"
|
|
class="w-4 h-4 bg-gray-100 border-gray-300 rounded text-primary-600 focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500"
|
|
/>
|
|
<label for="used" class="ml-2 text-sm font-medium text-gray-900 dark:text-gray-100">
|
|
Used
|
|
</label>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Type Dropdown -->
|
|
<div id="type-selector" class="relative" style="width: fit-content">
|
|
<button
|
|
@click="toggleDropdown('type')"
|
|
class="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-blue-700 transition text-center inline-flex items-center"
|
|
type="button"
|
|
>
|
|
Types
|
|
<svg
|
|
class="w-4 h-4 ml-2"
|
|
aria-hidden="true"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M19 9l-7 7-7-7"
|
|
></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Dropdown menu -->
|
|
<div
|
|
v-show="typeDropdownOpen"
|
|
class="absolute right-0 z-20 py-2 mt-2 bg-white rounded-md shadow-xl"
|
|
>
|
|
<ul class="space-y-2 text-sm px-4 py-2">
|
|
<li class="flex items-center" v-for="type in componentTypes" :key="type.id">
|
|
<input
|
|
:id="`type-${type.id}`"
|
|
type="checkbox"
|
|
v-model="filters.types[type.id]"
|
|
class="w-4 h-4 bg-gray-100 border-gray-300 rounded text-primary-600 focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500"
|
|
/>
|
|
<label
|
|
:for="`type-${type.id}`"
|
|
class="ml-2 text-sm font-medium text-gray-900 dark:text-gray-100"
|
|
>
|
|
{{ type.name }}
|
|
</label>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tableau des composants filtr├®s -->
|
|
<TableComponent :components="filteredComponents" />
|
|
</div>
|
|
</template>
|