-
Simon Malesys authoredSimon Malesys authored
AdvancedSearch.vue 5.12 KiB
<template>
<div class="advanced-search">
<div class="active-filters">
<div
v-for="filter in allFilters"
:key="filter.join('-')"
class="filter-chip"
>
<span>{{ filter[1] }}</span>
<button
class="remove-button"
type="button"
@click="removeFilter(filter)"
>
✖
</button>
</div>
</div>
<button
class="advanced-search-button"
type="button"
@click="displayAdvancedSearch"
>
ADVANCED SEARCH
</button>
</div>
<AppDialog
v-model="advancedSearchVisible"
class="advanced-search-dialog"
@close="updateFilters"
>
<header>
<h2>ADVANCED SEARCH</h2>
</header>
<div class="options-group">
<h3>ORGANISM</h3>
<div class="checkbox-list">
<div
v-for="spe in speciesList"
:key="spe"
class="checkbox"
>
<input
:id="spe.replace(' ', '-') + '-checkbox'"
v-model="filters.species"
:value="spe"
type="checkbox"
>
<label :for="spe.replace(' ', '-') + '-checkbox'">
{{ spe }}
</label>
</div>
</div>
</div>
<div class="options-group">
<h3>SOURCES</h3>
<div class="checkbox-list">
<div
v-for="source in sourcesList"
:key="source"
class="checkbox"
>
<input
:id="source + '-checkbox'"
v-model="filters.sources"
:value="source"
type="checkbox"
>
<label :for="source + '-checkbox'">
{{ source }}
</label>
</div>
</div>
</div>
<footer>
<button
class="search-button"
type="button"
@click="closeAdvancedSearch"
>
SEARCH
</button>
</footer>
</AppDialog>
</template>
<script setup lang="ts">
import { type Ref, computed, onMounted, ref } from 'vue'
import AppDialog from './AppDialog.vue'
import { useStore } from '../store'
import { type AdvancedFilters, type FilterChip } from '../types'
onMounted(() => {
if (store.antibodiesSources.length === 0) {
store.getAntibodiesSources()
store.getAntibodiesSpecies()
}
})
const emit = defineEmits<{
filtersUpdate: [filters: AdvancedFilters]
}>()
const store = useStore()
const advancedSearchVisible: Ref<boolean> = ref(false)
const filters: Ref<AdvancedFilters> = ref({
species: [],
sources: []
})
const sourcesList = computed(() => store.antibodiesSources)
const speciesList = computed(() => store.antibodiesSpecies)
const allFilters = computed(() => {
const filterChips: FilterChip[] = []
filters.value.species.forEach(value => {
filterChips.push(['species', value])
})
filters.value.sources.forEach(value => {
filterChips.push(['sources', value])
})
return filterChips
})
/**
* Open the dialog box.
*/
function displayAdvancedSearch (): void {
advancedSearchVisible.value = true
}
/**
* Close the dialog box.
*/
function closeAdvancedSearch (): void {
advancedSearchVisible.value = false
}
/**
* On dialog close, emit the new filters to
* the parent component.
*/
function updateFilters (): void {
emit('filtersUpdate', filters.value)
}
/**
* Remove one of the filter chips and re-emit
* the filters immediately.
* @param filterChip - The data of the filter chip to remove
*/
function removeFilter (filterChip: FilterChip): void {
const valueIndex: number = filters.value[filterChip[0]].indexOf(filterChip[1])
filters.value[filterChip[0]].splice(valueIndex, 1)
emit('filtersUpdate', filters.value)
}
</script>
<style scoped>
.active-filters {
display: flex;
flex-flow: row wrap;
gap: calc((var(--spacing)) / 2);
padding-top: calc((var(--spacing)) / 2);
}
.filter-chip {
border: 1px solid var(--primary);
border-radius: 16px;
color: var(--primary);
display: flex;
align-items: center;
padding-left: 8px;
}
.filter-chip .remove-button {
color: inherit;
padding: 6px;
background: none;
border: none;
cursor: pointer;
}
.advanced-search {
display: flex;
}
.advanced-search-button {
background: none;
border: none;
color: var(--white);
cursor: pointer;
margin-left: auto;
padding-top: calc(var(--spacing) / 2);
}
.advanced-search-button:hover {
color: var(--primary);
}
.advanced-search-dialog h2 {
margin-bottom: calc(var(--spacing) * 2);
margin-top: 0;
}
.options-group .checkbox-list {
display: flex;
flex-flow: row wrap;
gap: var(--spacing);
padding-left: var(--spacing);
max-width: 800px;
}
.checkbox {
display: flex;
gap: calc(var(--spacing) / 2);
}
.checkbox:hover {
color: var(--primary);
}
.checkbox input,
.checkbox label {
cursor: pointer;
}
.checkbox input:checked+label {
color: var(--primary);
}
.advanced-search-dialog footer {
align-items: center;
display: flex;
justify-content: flex-end;
margin-top: var(--spacing);
}
.search-button {
background-color: var(--primary);
border-radius: var(--radius);
border: none;
color: var(--white);
cursor: pointer;
font-weight: 700;
height: 40px;
padding: 7px var(--spacing);
}
</style>