import { type Component, createSignal, For, Match, Show, Switch } from "solid-js"; import { useNavigate, usePreloadRoute } from "@solidjs/router"; import { type ColumnFiltersState, createColumnHelper, createSolidTable, type FilterFn, flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, type SortDirection, type SortingState, } from "@tanstack/solid-table"; import { intlFormatDistance } from "date-fns"; import { ArrowDown, ArrowUp, ArrowUpDown } from "lucide-solid"; import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; import { Checkbox } from "~/components/ui/checkbox"; import { Label } from "~/components/ui/label"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table"; import { TextField, TextFieldInput } from "~/components/ui/text-field"; import { cn } from "~/lib/utils"; import { Flex } from "~/components/ui/flex"; import { dbLoaded, threadSentMessagesOverviewQuery } from "~/db"; export interface RoomOverview { threadId: number; recipientId: number; archived: boolean; messageCount: number; lastMessageDate: Date | undefined; name: string; isGroup: boolean; } const columnHelper = createColumnHelper(); const archivedFilterFn: FilterFn = (row, _columnId, filterValue) => { if (filterValue === true) { return true; } return !row.original.archived; }; const isGroupFilterFn: FilterFn = (row, _columnId, filterValue) => { if (filterValue === true) { return true; } return !row.original.isGroup; }; const rowIsAvailable = (threadId: number): boolean => { if (dbLoaded()) { return true; } if (threadSentMessagesOverviewQuery.hasCacheFor(threadId)) { return true; } return false; }; const SortingDisplay: Component<{ sorting: false | SortDirection; class?: string; activeClass?: string }> = (props) => { return ( ); }; export const columns = [ columnHelper.accessor("threadId", {}), columnHelper.accessor("name", { header: (props) => { const sorting = () => props.column.getIsSorted(); return ( ); }, cell: (props) => { const isArchived = props.row.getValue("archived"); const isGroup = props.row.getValue("isGroup"); const isNotAvailable = !rowIsAvailable(props.row.original.threadId); return ( {props.cell.getValue()} Archived Group Not available ); }, }), columnHelper.accessor("messageCount", { id: "messageCount", header: (props) => { const sorting = () => props.column.getIsSorted(); return ( ); }, sortingFn: "basic", }), columnHelper.accessor("lastMessageDate", { header: (props) => { const sorting = () => props.column.getIsSorted(); return ( ); }, sortingFn: "datetime", cell: (props) => { const value = props.cell.getValue(); if (value) { return intlFormatDistance(new Date(value), new Date()); } else { return ""; } }, }), columnHelper.accessor("archived", { id: "archived", header: "Archived", cell: (props) => { return ( Archived ); }, filterFn: archivedFilterFn, }), columnHelper.accessor("isGroup", { header: "isGroup", cell: (props) => { return ( Group ); }, filterFn: isGroupFilterFn, }), ]; interface OverviewTableProps { data: RoomOverview[]; } export const OverviewTable = (props: OverviewTableProps) => { const preload = usePreloadRoute(); const [sorting, setSorting] = createSignal([ { id: "messageCount", desc: true, }, ]); const [columnFilters, setColumnFilters] = createSignal([ { id: "archived", value: false, }, { id: "isGroup", value: false, }, ]); const table = createSolidTable({ get data() { return props.data; }, columns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), onSortingChange: setSorting, getSortedRowModel: getSortedRowModel(), onColumnFiltersChange: setColumnFilters, getFilteredRowModel: getFilteredRowModel(), state: { get sorting() { return sorting(); }, get columnFilters() { return columnFilters(); }, columnVisibility: { threadId: false, archived: false, isGroup: false, }, }, initialState: { pagination: { pageIndex: 0, pageSize: 25, }, }, }); const navigate = useNavigate(); return (
{ umami.track("Filter overview table"); table.getColumn("name")?.setFilterValue(value); }} >
{ umami.track("Filter overview table"); table.getColumn("archived")?.setFilterValue(value); }} />
{ umami.track("Filter overview table"); table.getColumn("isGroup")?.setFilterValue(value); }} />
{(headerGroup) => ( {(header) => ( {flexRender(header.column.columnDef.header, header.getContext())} )} )} No results. } > {(row) => ( { const threadId = row.original.threadId; const isGroup = row.original.isGroup; if (rowIsAvailable(threadId)) { const preloadTimeout = setTimeout(() => { preload(`/${isGroup ? "group" : "dm"}/${threadId.toString()}`, { preloadData: true, }); }, 50); event.currentTarget.addEventListener( "pointerout", () => { clearTimeout(preloadTimeout); }, { once: true, }, ); } }} onClick={() => { const threadId = row.original.threadId; const isGroup = row.original.isGroup; if (rowIsAvailable(threadId)) { umami.track("Load chat statistics"); navigate(`/${isGroup ? "group" : "dm"}/${threadId.toString()}`); } }} > {(cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} )} )}
); };