Skip to content
Snippets Groups Projects
Commit 2631a6b6 authored by Дмитрий Малюгин's avatar Дмитрий Малюгин :clock4:
Browse files

feat: add sort for Table (only simple)

parent aed1cb4c
No related branches found
No related tags found
1 merge request!3Table (partially), Checkbox, Tag, Select and Knob
......@@ -6,6 +6,7 @@ export interface ITableColumn {
editable?: boolean;
filterable?: boolean;
sortable?: boolean;
initSort?: 'up' | 'down' | 'none';
padding?: string;
}
......@@ -16,6 +17,7 @@ export interface ITableItem {
export type TTableColumnType =
| 'checkbox'
| 'number'
| 'text'
| 'date'
| 'tag'
......
......@@ -22,15 +22,16 @@ import type {
export interface ITableProps {
columns: ITableColumn[];
data: ITableItem[][];
theme?: TThemeColor;
textColor?: TThemeColor;
darknessTheme?: TDarkness;
darknessTextColor?: TDarkness;
multipleSort?: boolean;
gap?: string;
fontSize?: string;
showAllLines?: boolean;
stripedRows?: boolean;
center?: boolean;
fontSize?: string;
theme?: TThemeColor;
textColor?: TThemeColor;
darknessTheme?: TDarkness;
darknessTextColor?: TDarkness;
}
export interface ITLProps {
......
......@@ -21,6 +21,7 @@ const meta: Meta = {
showAllLines: { control: 'boolean' },
stripedRows: { control: 'boolean' },
center: { control: 'boolean' },
multipleSort: { control: 'boolean' },
darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] },
darknessTextColor: {
control: 'select',
......@@ -200,6 +201,20 @@ export const Full: Story = {
value: 'Russia',
},
],
[
{
value: 'Ксюша',
},
{
value: '32',
},
{
value: 'Backend',
},
{
value: 'Russia',
},
],
],
fontSize: '20px',
......
<script setup lang="ts">
import type { ITableProps } from '@interfaces/componentsProps';
import { computed, ref } from 'vue';
import { computed, ref, watch } from 'vue';
import { convertThemeToColor, convertThemeToSecondaryColor, convertThemeToTextColor } from '@helpers/common';
import type { ITableItem } from '@interfaces/componentsProp';
import FilterIcon from '@stories/icons/Mono/FilterIcon.vue';
......@@ -14,10 +14,10 @@ const props = withDefaults(defineProps<ITableProps>(), {
darknessTheme: '500',
fontSize: '16px',
});
const columns = ref(props.columns);
watch(props.columns, () => (columns.value = props.columns));
const gap = computed(() => props.gap);
// const emit = defineEmits(['']);
const data = defineModel('data') as ITableItem[][];
// watch(, () => {});
const data = defineModel<ITableItem[][]>('data');
const themeColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme));
const color = computed(() =>
props.textColor
......@@ -27,20 +27,57 @@ const color = computed(() =>
const secondaryColor = computed(() => convertThemeToSecondaryColor(props.theme, props.darknessTheme));
const darkCellColor = computed(() => convertThemeToSecondaryColor(props.theme, String(+props.darknessTheme + 300)));
const sortState = ref<string[]>(
(() => {
const columns = props.columns;
const result = [];
for (const column of columns) {
result.push(column.sortable ? 'none' : '');
}
return result;
})(),
);
// ['', 'up', 'none', '', 'none', ...]
const sortState = computed<string[]>(() => {
const result = [];
for (const column of columns.value) {
result.push(column.sortable ? (column.initSort ?? 'none') : '');
}
return result;
});
const sortStateActive = ref([]);
const rows = computed<ITableItem[][]>(() => {
// ['up', 'down', ...]
const rows = [...data.value];
if (!sortStateActive.value.length) return rows;
if (props.multipleSort) {
// let indexColumn = sortState.value.findIndex((state) => state && state !== 'none');
// let lastColumnIndexSorted = indexColumn;
// console.log('indexColumn: ', indexColumn);
// for (const sortItem of sortStateActive.value) {
// rows.sort((a, b) =>
// sortItem.split('$')[1] === 'down'
// ? a[indexColumn].value.localeCompare(b[indexColumn].value)
// : b[indexColumn].value.localeCompare(a[indexColumn].value),
// );
// indexColumn = sortState.value.findIndex(
// (state, index) => state && state !== 'none' && index !== lastColumnIndexSorted,
// );
// lastColumnIndexSorted = indexColumn;
// }
// return rows;
} else {
const index = sortStateActive.value[0];
const value = sortStateActive.value[1];
return rows.sort((a, b) =>
value === 'down' ? a[index].value.localeCompare(b[index].value) : b[index].value.localeCompare(a[index].value),
);
}
});
const changeColumnSortMode = (index: number) => {
const cur = sortState.value[index];
sortState.value[index] = cur === 'none' ? 'down' : cur === 'down' ? 'up' : 'none';
const newValue = cur === 'none' ? 'down' : cur === 'down' ? 'up' : 'none';
if (cur === 'up') {
sortStateActive.value = [];
} else {
sortStateActive.value[0] = index;
sortStateActive.value[1] = newValue;
}
if (!props.multipleSort) columns.value.forEach((column) => (column.initSort = 'none'));
columns.value[index].initSort = newValue;
};
</script>
......@@ -76,7 +113,11 @@ const changeColumnSortMode = (index: number) => {
<h3>
{{ column.name }}
</h3>
<button v-if="column.sortable" @click.prevent="changeColumnSortMode(index)">
<button
v-if="column.sortable"
@click.prevent="changeColumnSortMode(index)"
style="min-width: 20px; min-height: 20px"
>
<SortVerticalIcon
v-show="sortState[index] === 'none'"
:color="textColor"
......@@ -106,7 +147,7 @@ const changeColumnSortMode = (index: number) => {
</tr>
</thead>
<tbody>
<tr v-for="(row, index) of data" :key="index">
<tr v-for="(row, index) of rows" :key="index">
<td
:class="{
leftBorder: showAllLines,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment