Skip to content

Commit 168acc0

Browse files
committed
feat: implement query of data tables
Fixed DBP-112
1 parent 4916e9b commit 168acc0

File tree

24 files changed

+331
-86
lines changed

24 files changed

+331
-86
lines changed

app/(admin)/(activity-management)/events/_components/data-table.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@
33
import { CursorDataTable } from "@/components/data-table/cursor";
44
import type { Direction } from "@/components/data-table/pagination";
55
import { useSuspenseQuery } from "@apollo/client/react";
6+
import type { VariablesOf } from "@graphql-typed-document-node/core";
67
import { useState } from "react";
78
import { columns, type Event } from "./data-table-columns";
89
import { EVENTS_TABLE_QUERY } from "./query";
910

10-
export function EventsDataTable() {
11+
export function EventsDataTable({ query }: { query?: string }) {
1112
const PAGE_SIZE = 20;
1213
const [cursors, setCursors] = useState<(string | null)[]>([null]);
1314
const [currentIndex, setCurrentIndex] = useState(0);
1415

1516
const after = cursors[currentIndex];
16-
const variables = { first: PAGE_SIZE, after };
17+
18+
const variables = {
19+
first: PAGE_SIZE,
20+
after,
21+
where: query ? { typeContains: query } : undefined,
22+
} satisfies VariablesOf<typeof EVENTS_TABLE_QUERY>;
1723

1824
const { data } = useSuspenseQuery(EVENTS_TABLE_QUERY, {
1925
variables,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"use client";
2+
3+
import { Input } from "@/components/ui/input";
4+
5+
import { DataTableSkeleton } from "@/components/data-table/skeleton";
6+
import { useDebouncedValue } from "foxact/use-debounced-value";
7+
import { Suspense, useState } from "react";
8+
import { EventsDataTable } from "./data-table";
9+
10+
export default function FilterableDataTable() {
11+
const [query, setQuery] = useState("");
12+
const debouncedQuery = useDebouncedValue(query, 200);
13+
14+
return (
15+
<div className="flex flex-col">
16+
<div className="mb-4 flex items-center gap-4">
17+
<Input
18+
placeholder="搜尋事件類型"
19+
value={query}
20+
onChange={(e) => setQuery(e.target.value)}
21+
/>
22+
</div>
23+
24+
<Suspense fallback={<DataTableSkeleton />}>
25+
<EventsDataTable query={debouncedQuery} />
26+
</Suspense>
27+
</div>
28+
);
29+
}

app/(admin)/(activity-management)/events/_components/query.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ export const EVENTS_TABLE_QUERY = graphql(`
66
$after: Cursor
77
$last: Int
88
$before: Cursor
9+
$where: EventWhereInput
910
) {
10-
events(first: $first, after: $after, last: $last, before: $before, orderBy: { field: TRIGGERED_AT, direction: DESC }) {
11+
events(first: $first, after: $after, last: $last, before: $before, where: $where, orderBy: { field: TRIGGERED_AT, direction: DESC }) {
1112
edges {
1213
node {
1314
id

app/(admin)/(activity-management)/events/page.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import { DataTableSkeleton } from "@/components/data-table/skeleton";
21
import { SiteHeader } from "@/components/site-header";
32
import type { Metadata } from "next";
4-
import { Suspense } from "react";
5-
import { EventsDataTable } from "./_components/data-table";
3+
import FilterableDataTable from "./_components/filterable-data-table";
64

75
export const metadata: Metadata = {
86
title: "事件管理",
@@ -25,9 +23,7 @@ export default function Page() {
2523
</div>
2624
</div>
2725
<div>
28-
<Suspense fallback={<DataTableSkeleton />}>
29-
<EventsDataTable />
30-
</Suspense>
26+
<FilterableDataTable />
3127
</div>
3228
</main>
3329
</>

app/(admin)/(activity-management)/points/_components/data-table.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@
33
import { CursorDataTable } from "@/components/data-table/cursor";
44
import type { Direction } from "@/components/data-table/pagination";
55
import { useSuspenseQuery } from "@apollo/client/react";
6+
import type { VariablesOf } from "@graphql-typed-document-node/core";
67
import { useState } from "react";
78
import { columns, type Point } from "./data-table-columns";
89
import { POINTS_TABLE_QUERY } from "./query";
910

10-
export function PointsDataTable() {
11+
export function PointsDataTable({ query }: { query?: string }) {
1112
const PAGE_SIZE = 20;
1213
const [cursors, setCursors] = useState<(string | null)[]>([null]);
1314
const [currentIndex, setCurrentIndex] = useState(0);
1415

1516
const after = cursors[currentIndex];
16-
const variables = { first: PAGE_SIZE, after };
17+
18+
const variables = {
19+
first: PAGE_SIZE,
20+
after,
21+
where: query ? { descriptionContains: query } : undefined,
22+
} satisfies VariablesOf<typeof POINTS_TABLE_QUERY>;
1723

1824
const { data } = useSuspenseQuery(POINTS_TABLE_QUERY, {
1925
variables,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"use client";
2+
3+
import { Input } from "@/components/ui/input";
4+
5+
import { DataTableSkeleton } from "@/components/data-table/skeleton";
6+
import { useDebouncedValue } from "foxact/use-debounced-value";
7+
import { Suspense, useState } from "react";
8+
import { PointsDataTable } from "./data-table";
9+
10+
export default function FilterableDataTable() {
11+
const [query, setQuery] = useState("");
12+
const debouncedQuery = useDebouncedValue(query, 200);
13+
14+
return (
15+
<div className="flex flex-col">
16+
<div className="mb-4 flex items-center gap-4">
17+
<Input
18+
placeholder="搜尋描述"
19+
value={query}
20+
onChange={(e) => setQuery(e.target.value)}
21+
/>
22+
</div>
23+
24+
<Suspense fallback={<DataTableSkeleton />}>
25+
<PointsDataTable query={debouncedQuery} />
26+
</Suspense>
27+
</div>
28+
);
29+
}

app/(admin)/(activity-management)/points/_components/query.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ export const POINTS_TABLE_QUERY = graphql(`
66
$after: Cursor
77
$last: Int
88
$before: Cursor
9+
$where: PointWhereInput
910
) {
10-
points(first: $first, after: $after, last: $last, before: $before, orderBy: { field: GRANTED_AT, direction: DESC }) {
11+
points(first: $first, after: $after, last: $last, before: $before, where: $where, orderBy: { field: GRANTED_AT, direction: DESC }) {
1112
edges {
1213
node {
1314
id

app/(admin)/(activity-management)/points/page.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import { DataTableSkeleton } from "@/components/data-table/skeleton";
21
import { SiteHeader } from "@/components/site-header";
32
import type { Metadata } from "next";
4-
import { Suspense } from "react";
5-
import { PointsDataTable } from "./_components/data-table";
3+
import FilterableDataTable from "./_components/filterable-data-table";
64

75
export const metadata: Metadata = {
86
title: "積分管理",
@@ -25,9 +23,7 @@ export default function Page() {
2523
</div>
2624
</div>
2725
<div>
28-
<Suspense fallback={<DataTableSkeleton />}>
29-
<PointsDataTable />
30-
</Suspense>
26+
<FilterableDataTable />
3127
</div>
3228
</main>
3329
</>

app/(admin)/(question-management)/database/_components/data-table.tsx

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,35 @@ import { useSuspenseQuery } from "@apollo/client/react";
55
import { columns, type Database } from "./data-table-columns";
66
import { DATABASES_TABLE_QUERY } from "./query";
77

8-
export function DatabaseDataTable() {
8+
export function DatabaseDataTable({ query }: { query?: string }) {
99
const { data } = useSuspenseQuery(DATABASES_TABLE_QUERY);
1010

11-
const databaseList = data?.databases?.map((database) => ({
12-
id: database.id,
13-
slug: database.slug,
14-
description: database.description,
15-
schema: database.schema,
16-
relationFigure: database.relationFigure,
17-
} satisfies Database)) ?? [];
11+
const databaseList = data?.databases
12+
?.map(
13+
(database) => ({
14+
id: database.id,
15+
slug: database.slug,
16+
description: database.description,
17+
schema: database.schema,
18+
relationFigure: database.relationFigure,
19+
} satisfies Database),
20+
)
21+
.filter((database) => {
22+
if (query && database.slug.includes(query)) {
23+
return true;
24+
}
25+
26+
if (query && database.description?.includes(query)) {
27+
return true;
28+
}
29+
30+
// If no query is provided, return all databases
31+
if (!query) {
32+
return true;
33+
}
34+
35+
return false;
36+
}) ?? [];
1837

1938
return (
2039
<GeneralDataTable
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"use client";
2+
3+
import { Input } from "@/components/ui/input";
4+
5+
import { DataTableSkeleton } from "@/components/data-table/skeleton";
6+
import { useDebouncedValue } from "foxact/use-debounced-value";
7+
import { Suspense, useState } from "react";
8+
import { DatabaseDataTable } from "./data-table";
9+
10+
export default function FilterableDataTable() {
11+
const [query, setQuery] = useState("");
12+
const debouncedQuery = useDebouncedValue(query, 200);
13+
14+
return (
15+
<div className="flex flex-col">
16+
<div className="mb-4 flex items-center gap-4">
17+
<Input
18+
placeholder="搜尋資料庫 slug 或描述"
19+
value={query}
20+
onChange={(e) => setQuery(e.target.value)}
21+
/>
22+
</div>
23+
24+
<Suspense fallback={<DataTableSkeleton />}>
25+
<DatabaseDataTable query={debouncedQuery} />
26+
</Suspense>
27+
</div>
28+
);
29+
}

0 commit comments

Comments
 (0)