@cnamts/vue-dot
Version:
Implementation of our Design System for the French Health Insurance
184 lines (146 loc) • 3.93 kB
text/typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
import Vue, { PropType } from 'vue';
import Component from 'vue-class-component';
import { FilterItem } from './types';
import { deepCopy } from '../../helpers/deepCopy';
import { ChipItem } from '../../elements/ChipList/types';
import slugify from 'slugify';
const Props = Vue.extend({
props: {
value: {
type: Array as PropType<FilterItem[]>,
default: () => []
}
}
});
<Filterable>({
model: {
prop: 'value',
event: 'update:value'
},
watch: {
value: {
handler(newValue: FilterItem[]) {
this.filters = deepCopy(newValue);
},
immediate: true
}
}
})
export class Filterable extends Props {
filters: FilterItem[] = [];
getFilterCount(filter: FilterItem): number {
return this.getChips(filter).length;
}
formatFilterName(name: string): string {
return slugify(name, { lower: true });
}
getChips({ value, formatChip }: FilterItem): ChipItem[] {
if (value !== undefined && formatChip) {
return formatChip(value);
}
const isString = typeof value === 'string';
const isNumber = typeof value === 'number';
const isObject = typeof value === 'object';
const isArray = Array.isArray(value);
if (isString || isNumber) {
if (value === '') {
return [];
}
return [{
text: value.toString(),
value
}];
}
if (isArray) {
return value.map(item => {
if (typeof item !== 'object') {
return {
text: item.toString(),
value: item
};
}
return {
text: item.text || item.value.toString(),
value: item
};
});
}
if (isObject && value !== null) {
const typedValue: Record<string, any> = value;
const isPeriodField = typedValue.from !== undefined && typedValue.to !== undefined;
if (isPeriodField) {
if (typedValue.from === null || typedValue.to === null) {
return [];
}
return [{
text: `${typedValue.from} – ${typedValue.to}`,
value: typedValue
}];
}
// Any object
return Object.keys(typedValue).map(key => {
// Use text property if it exists, else use value property or default to key value
const text = typedValue[key].text || typedValue[key].value?.toString() || typedValue[key].toString();
return {
text,
value: typedValue[key]
};
});
}
return [];
}
removeChip(filter: FilterItem, chip: ChipItem): void {
const value = filter.value;
const isString = typeof value === 'string';
const isNumber = typeof value === 'number';
const isObject = typeof value === 'object';
const isArray = Array.isArray(value);
if (isString || isNumber) {
this.$set(filter, 'value', undefined);
}
if (isArray) {
const typedValue = value;
const chipValue = chip.value as any;
const filteredValue = typedValue.filter(item => {
if (Array.isArray(chipValue)) {
return !chipValue.includes(item);
}
if (typeof item === 'object' && item !== null) {
return item.value !== chipValue.value;
}
return item !== chipValue;
});
const newValue = filteredValue.length ? filteredValue : undefined;
this.$set(filter, 'value', newValue);
this.updateValue();
return;
}
if (isObject) {
const typedValue = value as Record<string, any>;
const chipValue = chip.value as any;
const isPeriodField = typedValue.from !== undefined && typedValue.to !== undefined;
if (isPeriodField) {
this.$set(filter, 'value', undefined);
this.updateValue();
return;
}
delete typedValue[chipValue];
this.$set(filter, 'value', typedValue);
}
this.updateValue();
}
resetFilter(filter: FilterItem): void {
this.$set(filter, 'value', undefined);
this.updateValue();
}
resetAllFilters(): void {
this.filters.forEach(filter => {
this.$set(filter, 'value', undefined);
});
this.updateValue();
}
updateValue(): void {
this.$emit('update:value', this.filters);
}
}