mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-02-05 14:40:33 +08:00
make sortable table sortable
This commit is contained in:
parent
2821bbf612
commit
a91af36ca8
@ -1,8 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { hasSlotContent } from "~/composables/useSlot";
|
||||
import Table from "~/components/design/Table.vue";
|
||||
import Button from "~/components/design/Button.vue";
|
||||
import { ref } from "vue";
|
||||
import { computed, reactive, ref } from "vue";
|
||||
|
||||
export interface Header {
|
||||
name: string;
|
||||
@ -18,20 +17,50 @@ const props = defineProps<{
|
||||
}>();
|
||||
|
||||
const expanded = ref<Record<number, boolean>>({});
|
||||
// TODO actually implement sorting
|
||||
const sorter = reactive<Record<string, number>>({});
|
||||
const sorted = ref<any[]>(props.items);
|
||||
|
||||
function sort() {
|
||||
sorted.value = [...props.items].sort((a, b) => {
|
||||
for (let field of Object.keys(sorter)) {
|
||||
if (sorter[field] === 0) continue;
|
||||
if (a[field] > b[field]) return sorter[field];
|
||||
if (a[field] < b[field]) return -sorter[field];
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
function click(header: Header) {
|
||||
if (header.sortable) {
|
||||
if (sorter[header.name] === 1) {
|
||||
sorter[header.name] = -1;
|
||||
} else if (sorter[header.name] === -1) {
|
||||
sorter[header.name] = 0;
|
||||
} else {
|
||||
sorter[header.name] = 1;
|
||||
}
|
||||
sort();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Table class="w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="header in headers" :key="header.name" :style="header.width ? 'width: ' + header.width : ''">
|
||||
{{ header.title }}
|
||||
<th v-for="header in headers" :key="header.name" :style="header.width ? 'width: ' + header.width : ''" @click="click(header)">
|
||||
<div class="items-center inline-flex" :cursor="header.sortable ? 'pointer' : 'auto'">
|
||||
<span class="mr-2"> {{ header.title }}</span>
|
||||
<IconMdiSortAscending v-if="sorter[header.name] === 1" />
|
||||
<IconMdiSortDescending v-else-if="sorter[header.name] === -1" />
|
||||
<IconMdiSort v-else-if="header.sortable" class="text-gray-400" />
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-for="(item, idx) in items" :key="idx">
|
||||
<template v-for="(item, idx) in sorted" :key="idx">
|
||||
<tr>
|
||||
<td v-for="header in headers" :key="header.name" :style="header.width ? 'width: ' + header.width : ''" @click="expanded[idx] = !expanded[idx]">
|
||||
<template v-if="hasSlotContent($slots['item_' + header.name], { item: item })">
|
||||
|
3
frontend-new/src/types/generated/icons.d.ts
vendored
3
frontend-new/src/types/generated/icons.d.ts
vendored
@ -28,6 +28,9 @@ declare module "vue" {
|
||||
IconMdiPlay: typeof import("~icons/mdi/play")["default"];
|
||||
IconMdiPlus: typeof import("~icons/mdi/plus")["default"];
|
||||
IconMdiRenameBox: typeof import("~icons/mdi/rename-box")["default"];
|
||||
IconMdiSort: typeof import("~icons/mdi/sort")["default"];
|
||||
IconMdiSortAscending: typeof import("~icons/mdi/sort-ascending")["default"];
|
||||
IconMdiSortDescending: typeof import("~icons/mdi/sort-descending")["default"];
|
||||
IconMdiSortVariant: typeof import("~icons/mdi/sort-variant")["default"];
|
||||
IconMdiStar: typeof import("~icons/mdi/star")["default"];
|
||||
IconMdiStarOutline: typeof import("~icons/mdi/star-outline")["default"];
|
||||
|
Loading…
Reference in New Issue
Block a user