dn-react-router-toolkit 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/api/index.js +13 -4
  2. package/dist/api/index.mjs +14 -5
  3. package/dist/api/item_api_handler.d.mts +4 -2
  4. package/dist/api/item_api_handler.d.ts +4 -2
  5. package/dist/api/item_api_handler.js +13 -4
  6. package/dist/api/item_api_handler.mjs +14 -5
  7. package/dist/crud/crud_loader.js +34 -5
  8. package/dist/crud/crud_loader.mjs +36 -6
  9. package/dist/crud/crud_page.js +69 -19
  10. package/dist/crud/crud_page.mjs +69 -19
  11. package/dist/crud/index.js +109 -30
  12. package/dist/crud/index.mjs +111 -31
  13. package/dist/post/index.js +6 -6
  14. package/dist/post/index.mjs +8 -7
  15. package/dist/post/post_form_page.js +6 -6
  16. package/dist/post/post_form_page.mjs +8 -7
  17. package/dist/table/index.d.mts +1 -1
  18. package/dist/table/index.d.ts +1 -1
  19. package/dist/table/index.js +94 -20
  20. package/dist/table/index.mjs +95 -20
  21. package/dist/table/load_table.d.mts +7 -1
  22. package/dist/table/load_table.d.ts +7 -1
  23. package/dist/table/load_table.js +21 -1
  24. package/dist/table/load_table.mjs +22 -1
  25. package/dist/table/loader.d.mts +3 -0
  26. package/dist/table/loader.d.ts +3 -0
  27. package/dist/table/loader.js +21 -1
  28. package/dist/table/loader.mjs +22 -1
  29. package/dist/table/page.js +69 -19
  30. package/dist/table/page.mjs +69 -19
  31. package/dist/table/repository.d.mts +6 -4
  32. package/dist/table/repository.d.ts +6 -4
  33. package/dist/table/repository.js +4 -0
  34. package/dist/table/repository.mjs +4 -0
  35. package/dist/table/table.d.mts +4 -1
  36. package/dist/table/table.d.ts +4 -1
  37. package/dist/table/table.js +55 -6
  38. package/dist/table/table.mjs +55 -6
  39. package/dist/table/table_form.d.mts +2 -2
  40. package/dist/table/table_form.d.ts +2 -2
  41. package/dist/table/table_form.js +69 -19
  42. package/dist/table/table_form.mjs +69 -19
  43. package/dist/table/use_table.d.mts +3 -3
  44. package/dist/table/use_table.d.ts +3 -3
  45. package/dist/table/use_table.js +1 -10
  46. package/dist/table/use_table.mjs +1 -10
  47. package/package.json +2 -2
@@ -38,11 +38,22 @@ async function loadTable({
38
38
  const offset = Number(searchParams.get("offset") ?? "0");
39
39
  const orderBy = searchParams.get("orderBy") ?? defaultOrderBy;
40
40
  const direction = searchParams.get("direction") ?? defaultDirection;
41
+ const filterWhere = Object.entries(options.filters ?? {}).map(([key, value]) => {
42
+ const param = searchParams.get(key);
43
+ if (param) {
44
+ return (0, import_drizzle_orm.eq)(
45
+ repository.schema[key],
46
+ decodeURIComponent(param)
47
+ );
48
+ }
49
+ return void 0;
50
+ }).filter(Boolean);
41
51
  const whereClauses = (0, import_drizzle_orm.and)(
42
52
  searchKey && query ? (0, import_drizzle_orm.ilike)(
43
53
  repository.schema[searchKey],
44
54
  `%${query}%`
45
55
  ) : void 0,
56
+ ...filterWhere,
46
57
  ...where ?? []
47
58
  );
48
59
  const total = await repository.countTotal({ where: whereClauses });
@@ -53,6 +64,14 @@ async function loadTable({
53
64
  offset,
54
65
  where: whereClauses
55
66
  });
67
+ const filters = Object.fromEntries(
68
+ await Promise.all(
69
+ Object.keys(options.filters ?? {}).map(async (key) => {
70
+ const values = await repository.select(key);
71
+ return [key, values.filter(Boolean)];
72
+ })
73
+ )
74
+ );
56
75
  return {
57
76
  items,
58
77
  total,
@@ -60,7 +79,8 @@ async function loadTable({
60
79
  offset,
61
80
  orderBy,
62
81
  direction,
63
- searchKey
82
+ searchKey,
83
+ filters
64
84
  };
65
85
  }
66
86
 
@@ -1,6 +1,7 @@
1
1
  // src/table/load_table.tsx
2
2
  import {
3
3
  and,
4
+ eq,
4
5
  ilike
5
6
  } from "drizzle-orm";
6
7
  async function loadTable({
@@ -15,11 +16,22 @@ async function loadTable({
15
16
  const offset = Number(searchParams.get("offset") ?? "0");
16
17
  const orderBy = searchParams.get("orderBy") ?? defaultOrderBy;
17
18
  const direction = searchParams.get("direction") ?? defaultDirection;
19
+ const filterWhere = Object.entries(options.filters ?? {}).map(([key, value]) => {
20
+ const param = searchParams.get(key);
21
+ if (param) {
22
+ return eq(
23
+ repository.schema[key],
24
+ decodeURIComponent(param)
25
+ );
26
+ }
27
+ return void 0;
28
+ }).filter(Boolean);
18
29
  const whereClauses = and(
19
30
  searchKey && query ? ilike(
20
31
  repository.schema[searchKey],
21
32
  `%${query}%`
22
33
  ) : void 0,
34
+ ...filterWhere,
23
35
  ...where ?? []
24
36
  );
25
37
  const total = await repository.countTotal({ where: whereClauses });
@@ -30,6 +42,14 @@ async function loadTable({
30
42
  offset,
31
43
  where: whereClauses
32
44
  });
45
+ const filters = Object.fromEntries(
46
+ await Promise.all(
47
+ Object.keys(options.filters ?? {}).map(async (key) => {
48
+ const values = await repository.select(key);
49
+ return [key, values.filter(Boolean)];
50
+ })
51
+ )
52
+ );
33
53
  return {
34
54
  items,
35
55
  total,
@@ -37,7 +57,8 @@ async function loadTable({
37
57
  offset,
38
58
  orderBy,
39
59
  direction,
40
- searchKey
60
+ searchKey,
61
+ filters
41
62
  };
42
63
  }
43
64
 
@@ -43,7 +43,8 @@ function Table({
43
43
  limit,
44
44
  offset,
45
45
  orderBy,
46
- direction
46
+ direction,
47
+ filters
47
48
  }) {
48
49
  const keys = Object.entries(columns).filter((entry) => entry[1]).map(([key]) => key);
49
50
  const sortedArray = [...data];
@@ -51,7 +52,10 @@ function Table({
51
52
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
52
53
  "table",
53
54
  {
54
- className: (0, import_utils.cn)(className, "text-[15px] border-separate border-spacing-0"),
55
+ className: (0, import_utils.cn)(
56
+ className,
57
+ "text-[15px] border-separate border-spacing-0"
58
+ ),
55
59
  children: [
56
60
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: keys.map((key) => {
57
61
  const value = columns[key];
@@ -68,8 +72,8 @@ function Table({
68
72
  "button",
69
73
  {
70
74
  className: (0, import_utils.cn)(
71
- orderBy === key ? "text-neutral-900 font-medium" : "text-neutral-500",
72
- "px-4 h-14 flex items-center w-full"
75
+ orderBy === key ? "text-gray-900 font-medium" : "text-gray-500 font-medium",
76
+ "px-4 flex items-center w-full"
73
77
  ),
74
78
  onClick: () => {
75
79
  let newDirection = "asc";
@@ -90,14 +94,59 @@ function Table({
90
94
  }
91
95
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: reactNode });
92
96
  }
93
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: (0, import_utils.cn)("border-y font-normal"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Head, {}) }, key);
97
+ const filter = filters[key];
98
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
99
+ "th",
100
+ {
101
+ className: (0, import_utils.cn)(
102
+ "py-4 border-y font-normal align-top"
103
+ ),
104
+ children: [
105
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Head, {}),
106
+ filter && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-3 mt-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
107
+ "select",
108
+ {
109
+ className: "w-full h-10 px-1.5 border rounded-full outline-none",
110
+ onChange: (e) => {
111
+ const value2 = e.target.value;
112
+ setSearchParams((prev) => {
113
+ if (value2) {
114
+ prev.set(
115
+ key,
116
+ encodeURIComponent(
117
+ value2
118
+ )
119
+ );
120
+ } else {
121
+ prev.delete(key);
122
+ }
123
+ return prev;
124
+ });
125
+ },
126
+ children: [
127
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\uC804\uCCB4" }),
128
+ filter.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
129
+ "option",
130
+ {
131
+ value: option,
132
+ children: option
133
+ },
134
+ option
135
+ ))
136
+ ]
137
+ }
138
+ ) })
139
+ ]
140
+ },
141
+ key
142
+ );
94
143
  }) }) }),
95
144
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tbody", { children: [
96
145
  sortedArray.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
97
146
  "td",
98
147
  {
99
148
  colSpan: keys.length,
100
- className: "px-4 h-14 text-neutral-400 text-center",
149
+ className: "px-4 h-20 text-gray-400 text-center",
101
150
  children: "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
102
151
  }
103
152
  ) }),
@@ -136,16 +185,7 @@ function Table({
136
185
  var import_react_router2 = require("react-router");
137
186
  function useTable() {
138
187
  const { table } = (0, import_react_router2.useLoaderData)();
139
- const { items, total, limit, offset, orderBy, direction, searchKey } = table;
140
- return {
141
- items,
142
- total,
143
- limit,
144
- offset,
145
- orderBy,
146
- direction,
147
- searchKey
148
- };
188
+ return table;
149
189
  }
150
190
 
151
191
  // src/table/buttons.tsx
@@ -228,7 +268,16 @@ function TableForm({
228
268
  primaryKey = "id"
229
269
  }) {
230
270
  const { pathname } = (0, import_react_router4.useLocation)();
231
- const { items, total, limit, offset, orderBy, direction, searchKey } = useTable();
271
+ const {
272
+ items,
273
+ total,
274
+ limit,
275
+ offset,
276
+ orderBy,
277
+ direction,
278
+ searchKey,
279
+ filters
280
+ } = useTable();
232
281
  const navigate = (0, import_react_router4.useNavigate)();
233
282
  const search = (query) => {
234
283
  const searchParams2 = new URLSearchParams(window.location.search);
@@ -241,7 +290,7 @@ function TableForm({
241
290
  searchKey && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
242
291
  "form",
243
292
  {
244
- className: "h-18 px-4 flex items-center border-t",
293
+ className: "h-20 px-4 flex items-center border-t",
245
294
  onSubmit: (e) => {
246
295
  e.preventDefault();
247
296
  const formData = new FormData(e.currentTarget);
@@ -278,7 +327,8 @@ function TableForm({
278
327
  limit,
279
328
  offset,
280
329
  orderBy,
281
- direction
330
+ direction,
331
+ filters
282
332
  }
283
333
  ),
284
334
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -19,7 +19,8 @@ function Table({
19
19
  limit,
20
20
  offset,
21
21
  orderBy,
22
- direction
22
+ direction,
23
+ filters
23
24
  }) {
24
25
  const keys = Object.entries(columns).filter((entry) => entry[1]).map(([key]) => key);
25
26
  const sortedArray = [...data];
@@ -27,7 +28,10 @@ function Table({
27
28
  return /* @__PURE__ */ jsxs(
28
29
  "table",
29
30
  {
30
- className: cn(className, "text-[15px] border-separate border-spacing-0"),
31
+ className: cn(
32
+ className,
33
+ "text-[15px] border-separate border-spacing-0"
34
+ ),
31
35
  children: [
32
36
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: keys.map((key) => {
33
37
  const value = columns[key];
@@ -44,8 +48,8 @@ function Table({
44
48
  "button",
45
49
  {
46
50
  className: cn(
47
- orderBy === key ? "text-neutral-900 font-medium" : "text-neutral-500",
48
- "px-4 h-14 flex items-center w-full"
51
+ orderBy === key ? "text-gray-900 font-medium" : "text-gray-500 font-medium",
52
+ "px-4 flex items-center w-full"
49
53
  ),
50
54
  onClick: () => {
51
55
  let newDirection = "asc";
@@ -66,14 +70,59 @@ function Table({
66
70
  }
67
71
  return /* @__PURE__ */ jsx(Fragment, { children: reactNode });
68
72
  }
69
- return /* @__PURE__ */ jsx("th", { className: cn("border-y font-normal"), children: /* @__PURE__ */ jsx(Head, {}) }, key);
73
+ const filter = filters[key];
74
+ return /* @__PURE__ */ jsxs(
75
+ "th",
76
+ {
77
+ className: cn(
78
+ "py-4 border-y font-normal align-top"
79
+ ),
80
+ children: [
81
+ /* @__PURE__ */ jsx(Head, {}),
82
+ filter && /* @__PURE__ */ jsx("div", { className: "px-3 mt-4", children: /* @__PURE__ */ jsxs(
83
+ "select",
84
+ {
85
+ className: "w-full h-10 px-1.5 border rounded-full outline-none",
86
+ onChange: (e) => {
87
+ const value2 = e.target.value;
88
+ setSearchParams((prev) => {
89
+ if (value2) {
90
+ prev.set(
91
+ key,
92
+ encodeURIComponent(
93
+ value2
94
+ )
95
+ );
96
+ } else {
97
+ prev.delete(key);
98
+ }
99
+ return prev;
100
+ });
101
+ },
102
+ children: [
103
+ /* @__PURE__ */ jsx("option", { value: "", children: "\uC804\uCCB4" }),
104
+ filter.map((option) => /* @__PURE__ */ jsx(
105
+ "option",
106
+ {
107
+ value: option,
108
+ children: option
109
+ },
110
+ option
111
+ ))
112
+ ]
113
+ }
114
+ ) })
115
+ ]
116
+ },
117
+ key
118
+ );
70
119
  }) }) }),
71
120
  /* @__PURE__ */ jsxs("tbody", { children: [
72
121
  sortedArray.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
73
122
  "td",
74
123
  {
75
124
  colSpan: keys.length,
76
- className: "px-4 h-14 text-neutral-400 text-center",
125
+ className: "px-4 h-20 text-gray-400 text-center",
77
126
  children: "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
78
127
  }
79
128
  ) }),
@@ -112,16 +161,7 @@ function Table({
112
161
  import { useLoaderData } from "react-router";
113
162
  function useTable() {
114
163
  const { table } = useLoaderData();
115
- const { items, total, limit, offset, orderBy, direction, searchKey } = table;
116
- return {
117
- items,
118
- total,
119
- limit,
120
- offset,
121
- orderBy,
122
- direction,
123
- searchKey
124
- };
164
+ return table;
125
165
  }
126
166
 
127
167
  // src/table/buttons.tsx
@@ -204,7 +244,16 @@ function TableForm({
204
244
  primaryKey = "id"
205
245
  }) {
206
246
  const { pathname } = useLocation2();
207
- const { items, total, limit, offset, orderBy, direction, searchKey } = useTable();
247
+ const {
248
+ items,
249
+ total,
250
+ limit,
251
+ offset,
252
+ orderBy,
253
+ direction,
254
+ searchKey,
255
+ filters
256
+ } = useTable();
208
257
  const navigate = useNavigate();
209
258
  const search = (query) => {
210
259
  const searchParams2 = new URLSearchParams(window.location.search);
@@ -217,7 +266,7 @@ function TableForm({
217
266
  searchKey && /* @__PURE__ */ jsxs3(
218
267
  "form",
219
268
  {
220
- className: "h-18 px-4 flex items-center border-t",
269
+ className: "h-20 px-4 flex items-center border-t",
221
270
  onSubmit: (e) => {
222
271
  e.preventDefault();
223
272
  const formData = new FormData(e.currentTarget);
@@ -254,7 +303,8 @@ function TableForm({
254
303
  limit,
255
304
  offset,
256
305
  orderBy,
257
- direction
306
+ direction,
307
+ filters
258
308
  }
259
309
  ),
260
310
  /* @__PURE__ */ jsx3(
@@ -21,20 +21,22 @@ interface TableRepository<T extends PgTableWithColumns<any>, TSelect = InferSele
21
21
  findAll: (options: FindAllOptions<T>) => Promise<TSelect[]>;
22
22
  save: (values: InferInsertModel<T>) => Promise<TSelect>;
23
23
  delete: (id: string) => Promise<void>;
24
+ select(key: keyof InferSelectModel<T>): Promise<InferSelectModel<T>[typeof key][]>;
24
25
  }
25
26
  type SchemaOf<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"]> = TDatabase["_"]["fullSchema"][TSchemaKey];
26
- declare class BaseTableRepository<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"], TPrimaryKey extends keyof InferSelectModel<SchemaOf<TDatabase, TSchemaKey>> = "id" extends keyof InferSelectModel<SchemaOf<TDatabase, TSchemaKey>> ? "id" : never> implements TableRepository<SchemaOf<TDatabase, TSchemaKey>> {
27
+ declare class BaseTableRepository<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"], TSelect = InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> implements TableRepository<SchemaOf<TDatabase, TSchemaKey>> {
27
28
  db: TDatabase;
28
29
  schema: SchemaOf<TDatabase, TSchemaKey>;
29
30
  pk: TPrimaryKey;
30
31
  constructor(db: TDatabase, schema: TSchemaKey, pk?: TPrimaryKey);
31
- find(id: string): Promise<InferSelectModel<SchemaOf<TDatabase, TSchemaKey>> | undefined>;
32
+ find(id: string): Promise<TSelect | undefined>;
32
33
  countTotal({ where }: {
33
34
  where?: SQL<unknown>;
34
35
  }): Promise<number>;
35
- findAll(options: FindAllOptions<SchemaOf<TDatabase, TSchemaKey>>): Promise<InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>[]>;
36
- save(values: InferInsertModel<SchemaOf<TDatabase, TSchemaKey>>): Promise<InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>>;
36
+ findAll(options: FindAllOptions<SchemaOf<TDatabase, TSchemaKey>>): Promise<TSelect[]>;
37
+ save(values: InferInsertModel<SchemaOf<TDatabase, TSchemaKey>>): Promise<TSelect>;
37
38
  delete(pk: string): Promise<void>;
39
+ select(key: keyof InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>): Promise<InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>[typeof key][]>;
38
40
  }
39
41
 
40
42
  export { BaseTableRepository, type ColumnOf, type FindAllOptions, type InsertModelOf, type SchemaOf, type SelectModelOf, type TableRepository };
@@ -21,20 +21,22 @@ interface TableRepository<T extends PgTableWithColumns<any>, TSelect = InferSele
21
21
  findAll: (options: FindAllOptions<T>) => Promise<TSelect[]>;
22
22
  save: (values: InferInsertModel<T>) => Promise<TSelect>;
23
23
  delete: (id: string) => Promise<void>;
24
+ select(key: keyof InferSelectModel<T>): Promise<InferSelectModel<T>[typeof key][]>;
24
25
  }
25
26
  type SchemaOf<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"]> = TDatabase["_"]["fullSchema"][TSchemaKey];
26
- declare class BaseTableRepository<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"], TPrimaryKey extends keyof InferSelectModel<SchemaOf<TDatabase, TSchemaKey>> = "id" extends keyof InferSelectModel<SchemaOf<TDatabase, TSchemaKey>> ? "id" : never> implements TableRepository<SchemaOf<TDatabase, TSchemaKey>> {
27
+ declare class BaseTableRepository<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"], TSelect = InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> implements TableRepository<SchemaOf<TDatabase, TSchemaKey>> {
27
28
  db: TDatabase;
28
29
  schema: SchemaOf<TDatabase, TSchemaKey>;
29
30
  pk: TPrimaryKey;
30
31
  constructor(db: TDatabase, schema: TSchemaKey, pk?: TPrimaryKey);
31
- find(id: string): Promise<InferSelectModel<SchemaOf<TDatabase, TSchemaKey>> | undefined>;
32
+ find(id: string): Promise<TSelect | undefined>;
32
33
  countTotal({ where }: {
33
34
  where?: SQL<unknown>;
34
35
  }): Promise<number>;
35
- findAll(options: FindAllOptions<SchemaOf<TDatabase, TSchemaKey>>): Promise<InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>[]>;
36
- save(values: InferInsertModel<SchemaOf<TDatabase, TSchemaKey>>): Promise<InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>>;
36
+ findAll(options: FindAllOptions<SchemaOf<TDatabase, TSchemaKey>>): Promise<TSelect[]>;
37
+ save(values: InferInsertModel<SchemaOf<TDatabase, TSchemaKey>>): Promise<TSelect>;
37
38
  delete(pk: string): Promise<void>;
39
+ select(key: keyof InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>): Promise<InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>[typeof key][]>;
38
40
  }
39
41
 
40
42
  export { BaseTableRepository, type ColumnOf, type FindAllOptions, type InsertModelOf, type SchemaOf, type SelectModelOf, type TableRepository };
@@ -69,6 +69,10 @@ var BaseTableRepository = class {
69
69
  async delete(pk) {
70
70
  await this.db.delete(this.schema).where((0, import_drizzle_orm.eq)(this.schema[this.pk], pk));
71
71
  }
72
+ async select(key) {
73
+ const rows = await this.db.select({ value: this.schema[key] }).from(this.schema).groupBy(this.schema[key]);
74
+ return rows.map((row) => row.value);
75
+ }
72
76
  };
73
77
  // Annotate the CommonJS export names for ESM import in node:
74
78
  0 && (module.exports = {
@@ -50,6 +50,10 @@ var BaseTableRepository = class {
50
50
  async delete(pk) {
51
51
  await this.db.delete(this.schema).where(eq(this.schema[this.pk], pk));
52
52
  }
53
+ async select(key) {
54
+ const rows = await this.db.select({ value: this.schema[key] }).from(this.schema).groupBy(this.schema[key]);
55
+ return rows.map((row) => row.value);
56
+ }
53
57
  };
54
58
  export {
55
59
  BaseTableRepository
@@ -22,7 +22,10 @@ type OrderedTableProps<T> = DetailedHTMLProps<TableHTMLAttributes<HTMLTableEleme
22
22
  offset?: number;
23
23
  orderBy?: string;
24
24
  direction?: string;
25
+ filters: {
26
+ [key: string]: unknown[];
27
+ };
25
28
  };
26
- declare function Table<T>({ className, data, columns, mapper: Mapper, getLink, limit, offset, orderBy, direction, }: OrderedTableProps<T>): react_jsx_runtime.JSX.Element;
29
+ declare function Table<T>({ className, data, columns, mapper: Mapper, getLink, limit, offset, orderBy, direction, filters, }: OrderedTableProps<T>): react_jsx_runtime.JSX.Element;
27
30
 
28
31
  export { type OrderedTableProps, Table, type TableColumnOptions, type TableColumnProps };
@@ -22,7 +22,10 @@ type OrderedTableProps<T> = DetailedHTMLProps<TableHTMLAttributes<HTMLTableEleme
22
22
  offset?: number;
23
23
  orderBy?: string;
24
24
  direction?: string;
25
+ filters: {
26
+ [key: string]: unknown[];
27
+ };
25
28
  };
26
- declare function Table<T>({ className, data, columns, mapper: Mapper, getLink, limit, offset, orderBy, direction, }: OrderedTableProps<T>): react_jsx_runtime.JSX.Element;
29
+ declare function Table<T>({ className, data, columns, mapper: Mapper, getLink, limit, offset, orderBy, direction, filters, }: OrderedTableProps<T>): react_jsx_runtime.JSX.Element;
27
30
 
28
31
  export { type OrderedTableProps, Table, type TableColumnOptions, type TableColumnProps };
@@ -36,7 +36,8 @@ function Table({
36
36
  limit,
37
37
  offset,
38
38
  orderBy,
39
- direction
39
+ direction,
40
+ filters
40
41
  }) {
41
42
  const keys = Object.entries(columns).filter((entry) => entry[1]).map(([key]) => key);
42
43
  const sortedArray = [...data];
@@ -44,7 +45,10 @@ function Table({
44
45
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
45
46
  "table",
46
47
  {
47
- className: (0, import_utils.cn)(className, "text-[15px] border-separate border-spacing-0"),
48
+ className: (0, import_utils.cn)(
49
+ className,
50
+ "text-[15px] border-separate border-spacing-0"
51
+ ),
48
52
  children: [
49
53
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: keys.map((key) => {
50
54
  const value = columns[key];
@@ -61,8 +65,8 @@ function Table({
61
65
  "button",
62
66
  {
63
67
  className: (0, import_utils.cn)(
64
- orderBy === key ? "text-neutral-900 font-medium" : "text-neutral-500",
65
- "px-4 h-14 flex items-center w-full"
68
+ orderBy === key ? "text-gray-900 font-medium" : "text-gray-500 font-medium",
69
+ "px-4 flex items-center w-full"
66
70
  ),
67
71
  onClick: () => {
68
72
  let newDirection = "asc";
@@ -83,14 +87,59 @@ function Table({
83
87
  }
84
88
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: reactNode });
85
89
  }
86
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: (0, import_utils.cn)("border-y font-normal"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Head, {}) }, key);
90
+ const filter = filters[key];
91
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
92
+ "th",
93
+ {
94
+ className: (0, import_utils.cn)(
95
+ "py-4 border-y font-normal align-top"
96
+ ),
97
+ children: [
98
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Head, {}),
99
+ filter && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-3 mt-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
100
+ "select",
101
+ {
102
+ className: "w-full h-10 px-1.5 border rounded-full outline-none",
103
+ onChange: (e) => {
104
+ const value2 = e.target.value;
105
+ setSearchParams((prev) => {
106
+ if (value2) {
107
+ prev.set(
108
+ key,
109
+ encodeURIComponent(
110
+ value2
111
+ )
112
+ );
113
+ } else {
114
+ prev.delete(key);
115
+ }
116
+ return prev;
117
+ });
118
+ },
119
+ children: [
120
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\uC804\uCCB4" }),
121
+ filter.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
122
+ "option",
123
+ {
124
+ value: option,
125
+ children: option
126
+ },
127
+ option
128
+ ))
129
+ ]
130
+ }
131
+ ) })
132
+ ]
133
+ },
134
+ key
135
+ );
87
136
  }) }) }),
88
137
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tbody", { children: [
89
138
  sortedArray.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
90
139
  "td",
91
140
  {
92
141
  colSpan: keys.length,
93
- className: "px-4 h-14 text-neutral-400 text-center",
142
+ className: "px-4 h-20 text-gray-400 text-center",
94
143
  children: "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
95
144
  }
96
145
  ) }),