Skip to content

Commit

Permalink
finish reimplementation of activity table as a client component
Browse files Browse the repository at this point in the history
  • Loading branch information
jthrilly committed Feb 8, 2024
1 parent f11a36e commit 72a6b0a
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { DataTableSkeleton } from '~/components/data-table/data-table-skeleton';
import ActivityFeedTable from './ActivityFeedTable';
import { unstable_noStore } from 'next/cache';
import { api } from '~/trpc/client';
import { useSearchParamsTableState } from './useTableSearchParams';
import { useTableStateFromSearchParams } from './useTableStateFromSearchParams';

export const ActivityFeed = () => {
const { searchParams } = useSearchParamsTableState();
const { searchParams } = useTableStateFromSearchParams();

unstable_noStore();
const tableQuery = api.dashboard.getActivities.useQuery(searchParams);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ export default function ActivityFeedTable({
searchableColumns={searchableColumns}
filterableColumns={filterableColumns}
// floatingBarContent={TasksTableFloatingBarContent(dataTable)}
deleteRowsAction={(_event) => {
// eslint-disable-next-line no-console
console.log('deleteSelectedrows, dataTable, event');
}}
// deleteRowsAction={(_event) => {}}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import {
FilterParam,
pageSizes,
searchableFields,
sortOrder,
sortableFields,
} from '~/lib/data-table/types';
Expand All @@ -23,7 +24,7 @@ import {
* ways, such as in localStorage, in the URL, or even in a database.
*
*/
export const useSearchParamsTableState = () => {
export const useTableStateFromSearchParams = () => {
const [page, setPage] = useQueryState('page', parseAsInteger.withDefault(1));
const [perPage, setPerPage] = useQueryState(
'per_page',
Expand Down
18 changes: 9 additions & 9 deletions app/(dashboard)/dashboard/_components/ActivityFeed/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,22 @@ const generateMessageForActivityType = (type: ActivityType) => {
};

export const getBadgeColorsForActivityType = (type: ActivityType) => {
switch (type) {
case 'Protocol Installed':
switch (type.toLowerCase()) {
case 'protocol installed':
return 'bg-slate-blue hover:bg-slate-blue-dark';
case 'Protocol Uninstalled':
case 'protocol uninstalled':
return 'bg-neon-carrot hover:bg-neon-carrot-dark';
case 'Participant(s) Added':
case 'participant(s) added':
return 'bg-sea-green hover:bg-sea-green';
case 'Participant(s) Removed':
case 'participant(s) removed':
return 'bg-tomato hover:bg-tomato-dark';
case 'Interview Started':
case 'interview started':
return 'bg-sea-serpent hover:bg-sea-serpent-dark';
case 'Interview Completed':
case 'interview completed':
return 'bg-purple-pizazz hover:bg-purple-pizazz-dark';
case 'Interview(s) Deleted':
case 'interview(s) deleted':
return 'bg-paradise-pink hover:bg-paradise-pink-dark';
case 'Data Exported':
case 'data exported':
return 'bg-kiwi hover:bg-kiwi-dark';
}
};
Expand Down
2 changes: 1 addition & 1 deletion components/data-table/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ type DataTableProps<TData, TValue> = {
* @example deleteRowsAction={(event) => deleteSelectedRows(dataTable, event)}
*/
deleteRowsAction?: React.MouseEventHandler<HTMLButtonElement>;
}
};

export function DataTable<TData, TValue>({
dataTable,
Expand Down
38 changes: 30 additions & 8 deletions hooks/use-data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import type {
PageSize,
SortableField,
} from '~/lib/data-table/types';
import { useSearchParamsTableState } from '~/app/(dashboard)/dashboard/_components/ActivityFeed/useTableSearchParams';

import { useTableStateFromSearchParams } from '~/app/(dashboard)/dashboard/_components/ActivityFeed/useTableStateFromSearchParams';
import { debounce } from 'lodash';

type UseDataTableProps<TData, TValue> = {
/**
Expand Down Expand Up @@ -68,16 +70,14 @@ export function useDataTable<TData, TValue>({
searchableColumns = [],
filterableColumns = [],
}: UseDataTableProps<TData, TValue>) {
const { searchParams, setSearchParams } = useSearchParamsTableState();

const filterableColumnIds = filterableColumns.map((column) => column.id);
const { searchParams, setSearchParams } = useTableStateFromSearchParams();

// Table states
const [rowSelection, setRowSelection] = React.useState({});
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
searchParams.filterParams ?? [],
(searchParams.filterParams as ColumnFiltersState) ?? [],
);

const [{ pageIndex, pageSize }, setPagination] =
Expand All @@ -94,14 +94,38 @@ export function useDataTable<TData, TValue>({
[pageIndex, pageSize],
);

const debouncedUpdateFilterParams = debounce(
(columnFilters: ColumnFiltersState) => {
if (!columnFilters || columnFilters.length === 0) {
void setSearchParams.setFilterParams(null);
return;
}

void setSearchParams.setFilterParams(columnFilters);
// Changing the filter params should reset the page to 1
// void setSearchParams.setPage(1);
},
2000,
{
trailing: true,
leading: false,
},
);

// Sync any changes to columnFilters back to searchParams
React.useEffect(() => {
// If we are resetting, skip the debounce
if (!columnFilters || columnFilters.length === 0) {
void setSearchParams.setFilterParams(null);
return;
}

void setSearchParams.setFilterParams(columnFilters);
debouncedUpdateFilterParams(columnFilters);

// Changing the filter params should reset the page to 1
void setSearchParams.setPage(1);

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [columnFilters]);

React.useEffect(() => {
Expand Down Expand Up @@ -131,8 +155,6 @@ export function useDataTable<TData, TValue>({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [sorting]);

console.log({ columnFilters, filterableColumns, searchableColumns });

const dataTable = useReactTable({
data,
columns,
Expand Down
7 changes: 5 additions & 2 deletions lib/data-table/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,18 @@ export const sortableFields = [
'type',
'message',
] as const;

export type SortableField = (typeof sortableFields)[number];

// As above, this should be derivable from the column definition...
export const searchableFields = ['message'] as const;
export type SearchableField = (typeof searchableFields)[number];

export const pageSizes = [10, 20, 50, 100] as const;
export type PageSize = (typeof pageSizes)[number];

export const FilterParam = z.object({
id: z.string(),
value: z.array(z.string()),
value: z.union([z.string(), z.array(z.string())]),
});

export const SearchParamsSchema = z.object({
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
"tailwindcss-animate": "^1.0.7",
"ts-node": "^10.9.1",
"uploadthing": "^5.7.4",
"usehooks-ts": "^2.13.0",
"uuid": "^9.0.1",
"validator": "^13.11.0",
"zod": "^3.22.4"
Expand Down
14 changes: 13 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 8 additions & 12 deletions server/routers/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,18 @@ export const dashboardRouter = router({
.query(async ({ input }) => {
const { page, perPage, sort, sortField, filterParams } = input;

console.log(input);

// Fallback page for invalid page numbers
const pageAsNumber = Number(page);
const fallbackPage =
isNaN(pageAsNumber) || pageAsNumber < 1 ? 1 : pageAsNumber;

// Number of items to skip
const offset = fallbackPage > 0 ? (fallbackPage - 1) * perPage : 0;
const offset = page > 0 ? (page - 1) * perPage : 0;

const queryFilterParams = filterParams
? {
AND: [
...filterParams.map(({ id, value }) => ({
[id]: { in: value },
})),
OR: [
...filterParams.map(({ id, value }) => {
const operator = Array.isArray(value) ? 'in' : 'contains';
return {
[id]: { [operator]: value },
};
}),
],
}
: {};
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"checkJs": false,
"skipLibCheck": true,
"strict": true,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
Expand Down

0 comments on commit 72a6b0a

Please sign in to comment.