feat: custom show/hide datatable col

This commit is contained in:
pa
2026-03-04 23:12:41 +09:00
parent 1decec4c69
commit 1be9d13cd4
11 changed files with 400 additions and 104 deletions
+62 -35
View File
@@ -17,24 +17,27 @@ import {
const { t } = i18n.global;
const sortButton = ({ column, label, descFirst = false }) => (
<Button
variant="ghost"
size="sm"
class="-ml-2 h-8 px-2"
onClick={() => {
const sorted = column.getIsSorted();
if (!sorted && descFirst) {
column.toggleSorting(true);
return;
}
column.toggleSorting(sorted === 'asc');
}}
>
{label}
<ArrowUpDown class="ml-1 h-4 w-4" />
</Button>
);
const sortButton = ({ column, label, descFirst = false }) => {
const resolvedLabel = typeof label === 'function' ? label() : label;
return (
<Button
variant="ghost"
size="sm"
class="-ml-2 h-8 px-2"
onClick={() => {
const sorted = column.getIsSorted();
if (!sorted && descFirst) {
column.toggleSorting(true);
return;
}
column.toggleSorting(sorted === 'asc');
}}
>
{resolvedLabel}
<ArrowUpDown class="ml-1 h-4 w-4" />
</Button>
);
};
const compareNumbers = (a, b) => (a ?? 0) - (b ?? 0);
@@ -143,10 +146,11 @@ export const createColumns = ({
header: ({ column }) =>
sortButton({
column,
label: t('table.friendList.no'),
label: () => t('table.friendList.no'),
descFirst: true
}),
size: 100,
meta: { label: () => t('table.friendList.no') },
sortingFn: sortByNumber((row) => row?.$friendNumber ?? 0),
cell: ({ row }) => <span>{row.original?.$friendNumber || ''}</span>
},
@@ -156,6 +160,7 @@ export const createColumns = ({
header: () => t('table.friendList.avatar'),
size: 90,
enableSorting: false,
meta: { label: () => t('table.friendList.avatar') },
cell: ({ row }) => {
const src = userImage(row.original, true);
return src ? (
@@ -175,9 +180,10 @@ export const createColumns = ({
header: ({ column }) =>
sortButton({
column,
label: t('table.friendList.displayName')
label: () => t('table.friendList.displayName')
}),
size: 200,
meta: { label: () => t('table.friendList.displayName') },
sortingFn: sortByString((row) => row?.displayName ?? ''),
cell: ({ row }) => {
const style = randomUserColours?.value
@@ -196,9 +202,10 @@ export const createColumns = ({
header: ({ column }) =>
sortButton({
column,
label: t('table.friendList.rank')
label: () => t('table.friendList.rank')
}),
size: 140,
meta: { label: () => t('table.friendList.rank') },
sortingFn: sortByNumber((row) => row?.$trustSortNum ?? 0),
cell: ({ row }) => {
if (randomUserColours?.value) {
@@ -222,11 +229,15 @@ export const createColumns = ({
id: 'status',
accessorFn: (row) => row?.status,
header: ({ column }) =>
sortButton({ column, label: t('table.friendList.status') }),
sortButton({
column,
label: () => t('table.friendList.status')
}),
minSize: 200,
sortingFn: sortByStatus,
meta: {
stretch: true
stretch: true,
label: () => t('table.friendList.status')
},
cell: ({ row }) => {
const status = row.original?.status;
@@ -250,8 +261,12 @@ export const createColumns = ({
id: 'language',
accessorFn: (row) => row?.$languages,
header: ({ column }) =>
sortButton({ column, label: t('table.friendList.language') }),
sortButton({
column,
label: () => t('table.friendList.language')
}),
size: 130,
meta: { label: () => t('table.friendList.language') },
sortingFn: sortByLanguages,
cell: ({ row }) => (
<div class="flex items-center">
@@ -279,6 +294,7 @@ export const createColumns = ({
header: () => t('table.friendList.bioLink'),
size: 130,
enableSorting: false,
meta: { label: () => t('table.friendList.bioLink') },
cell: ({ row }) => (
<div class="flex items-center">
{(row.original?.bioLinks ?? [])
@@ -305,12 +321,13 @@ export const createColumns = ({
header: ({ column }) =>
sortButton({
column,
label: t('table.friendList.joinCount')
label: () => t('table.friendList.joinCount')
}),
size: 120,
sortingFn: sortByNumber((row) => row?.$joinCount ?? 0),
meta: {
class: 'text-right'
class: 'text-right',
label: () => t('table.friendList.joinCount')
}
},
{
@@ -319,12 +336,13 @@ export const createColumns = ({
header: ({ column }) =>
sortButton({
column,
label: t('table.friendList.timeTogether')
label: () => t('table.friendList.timeTogether')
}),
size: 140,
sortingFn: sortByNumber((row) => row?.$timeSpent ?? 0),
meta: {
class: 'text-right'
class: 'text-right',
label: () => t('table.friendList.timeTogether')
},
cell: ({ row }) => {
const time = row.original?.$timeSpent;
@@ -337,9 +355,10 @@ export const createColumns = ({
header: ({ column }) =>
sortButton({
column,
label: t('table.friendList.lastSeen')
label: () => t('table.friendList.lastSeen')
}),
size: 170,
meta: { label: () => t('table.friendList.lastSeen') },
sortingFn: sortByString((row) => row?.$lastSeen ?? ''),
cell: ({ row }) => {
const text = formatDateFilter(row.original?.$lastSeen, 'long');
@@ -352,12 +371,13 @@ export const createColumns = ({
header: ({ column }) =>
sortButton({
column,
label: t('table.friendList.mutualFriends')
label: () => t('table.friendList.mutualFriends')
}),
size: 120,
sortingFn: sortByNumber((row) => row?.$mutualCount ?? 0),
meta: {
class: 'text-right'
class: 'text-right',
label: () => t('table.friendList.mutualFriends')
},
cell: ({ row }) => {
const count = row.original?.$mutualCount;
@@ -370,9 +390,10 @@ export const createColumns = ({
header: ({ column }) =>
sortButton({
column,
label: t('table.friendList.lastActivity')
label: () => t('table.friendList.lastActivity')
}),
size: 200,
meta: { label: () => t('table.friendList.lastActivity') },
sortingFn: sortByString((row) => row?.last_activity ?? ''),
cell: ({ row }) => (
<span>
@@ -384,8 +405,12 @@ export const createColumns = ({
id: 'lastLogin',
accessorFn: (row) => row?.last_login,
header: ({ column }) =>
sortButton({ column, label: t('table.friendList.lastLogin') }),
sortButton({
column,
label: () => t('table.friendList.lastLogin')
}),
size: 200,
meta: { label: () => t('table.friendList.lastLogin') },
sortingFn: sortByString((row) => row?.last_login ?? ''),
cell: ({ row }) => (
<span>
@@ -399,9 +424,10 @@ export const createColumns = ({
header: ({ column }) =>
sortButton({
column,
label: t('table.friendList.dateJoined')
label: () => t('table.friendList.dateJoined')
}),
size: 120,
meta: { label: () => t('table.friendList.dateJoined') },
sortingFn: sortByString((row) => row?.date_joined ?? ''),
cell: ({ row }) => <span>{row.original?.date_joined ?? ''}</span>
},
@@ -411,7 +437,8 @@ export const createColumns = ({
size: 100,
enableSorting: false,
meta: {
class: 'text-center'
class: 'text-center',
label: t('table.friendList.unfriend')
},
cell: ({ row }) => (
// TODO(icon): verify unfollow icon replacement