@@ -22,77 +22,61 @@ export interface PaginatedCustomers {
22
22
}
23
23
}
24
24
25
- export interface CustomerStats {
26
- total : number
27
- active : number
28
- inactive : number
29
- topSpenders : Partial < CustomersTable > [ ]
30
- recentCustomers : Partial < CustomersTable > [ ]
31
- }
32
-
33
25
/**
34
- * Fetch all customers from the database
26
+ * Fetch a customer by ID
35
27
*/
36
- export async function fetchAll ( ) : Promise < CustomersTable [ ] > {
28
+ export async function fetchById ( id : number ) : Promise < CustomersTable | undefined > {
37
29
return await db
38
30
. selectFrom ( 'customers' )
31
+ . where ( 'id' , '=' , id )
39
32
. selectAll ( )
40
- . execute ( )
33
+ . executeTakeFirst ( )
41
34
}
42
35
43
36
/**
44
- * Fetch customers with pagination, sorting, and filtering options
37
+ * Fetch customers with simple pagination, sorting, and basic search
38
+ * A minimal implementation that works well while planning for Algolia/Meilisearch
45
39
*/
46
40
export async function fetchPaginated ( options : FetchCustomersOptions = { } ) : Promise < PaginatedCustomers > {
47
41
// Set default values
48
42
const page = options . page || 1
49
43
const limit = options . limit || 10
50
- const offset = ( page - 1 ) * limit
51
44
const sortBy = options . sortBy || 'created_at'
52
45
const sortOrder = options . sortOrder || 'desc'
53
46
54
47
// Start building the query
55
48
let query = db . selectFrom ( 'customers' )
56
49
let countQuery = db . selectFrom ( 'customers' )
57
50
58
- // Apply search filter if provided
59
- if ( options . search ) {
60
- const searchTerm = `%${ options . search } %`
61
- const searchFilter = eb => eb . or ( [
62
- eb ( 'name' , 'like' , searchTerm ) ,
63
- eb ( 'email' , 'like' , searchTerm ) ,
64
- eb ( 'phone' , 'like' , searchTerm ) ,
65
- ] )
66
-
67
- query = query . where ( searchFilter )
68
- countQuery = countQuery . where ( searchFilter )
51
+ // Simple name search if provided
52
+ if ( options . search && options . search . trim ( ) ) {
53
+ const searchTerm = `%${ options . search . trim ( ) } %`
54
+ query = query . where ( 'name' , 'like' , searchTerm )
55
+ countQuery = countQuery . where ( 'name' , 'like' , searchTerm )
69
56
}
70
57
71
- // Apply status filter if provided and not 'all'
58
+ // Basic status filter
72
59
if ( options . status && options . status !== 'all' ) {
73
60
query = query . where ( 'status' , '=' , options . status )
74
61
countQuery = countQuery . where ( 'status' , '=' , options . status )
75
62
}
76
63
77
- // Get total count for pagination
64
+ // Get total count
78
65
const countResult = await countQuery
79
66
. select ( eb => eb . fn . count ( 'id' ) . as ( 'total' ) )
80
67
. executeTakeFirst ( )
81
68
82
69
const total = Number ( countResult ?. total || 0 )
83
70
84
- // Apply sorting
85
- // Note: Ensure the column is valid to prevent SQL injection
86
- const validColumns = [ 'name' , 'email' , 'orders' , 'totalSpent' , 'lastOrder' , 'status' , 'created_at' , 'updated_at' ]
87
- const validSortBy = validColumns . includes ( sortBy ) ? sortBy : 'created_at'
88
-
89
- query = query . orderBy ( validSortBy , sortOrder )
71
+ // Basic sorting
72
+ query = query . orderBy ( sortBy , sortOrder )
90
73
91
- // Apply pagination
92
- query = query . limit ( limit ) . offset ( offset )
93
-
94
- // Execute the query
95
- const customers = await query . selectAll ( ) . execute ( )
74
+ // Basic pagination
75
+ const customers = await query
76
+ . selectAll ( )
77
+ . limit ( limit )
78
+ . offset ( ( page - 1 ) * limit )
79
+ . execute ( )
96
80
97
81
// Calculate pagination info
98
82
const totalPages = Math . ceil ( total / limit )
@@ -109,58 +93,3 @@ export async function fetchPaginated(options: FetchCustomersOptions = {}): Promi
109
93
} ,
110
94
}
111
95
}
112
-
113
- /**
114
- * Fetch a customer by ID
115
- */
116
- export async function fetchById ( id : number ) : Promise < CustomersTable | undefined > {
117
- return await db
118
- . selectFrom ( 'customers' )
119
- . where ( 'id' , '=' , id )
120
- . selectAll ( )
121
- . executeTakeFirst ( )
122
- }
123
-
124
- /**
125
- * Get customer statistics
126
- */
127
- export async function fetchStats ( ) : Promise < CustomerStats > {
128
- const totalCustomers = await db
129
- . selectFrom ( 'customers' )
130
- . select ( eb => eb . fn . count ( 'id' ) . as ( 'count' ) )
131
- . executeTakeFirst ( )
132
-
133
- const activeCustomers = await db
134
- . selectFrom ( 'customers' )
135
- . where ( 'status' , '=' , 'Active' )
136
- . select ( eb => eb . fn . count ( 'id' ) . as ( 'count' ) )
137
- . executeTakeFirst ( )
138
-
139
- const inactiveCustomers = await db
140
- . selectFrom ( 'customers' )
141
- . where ( 'status' , '=' , 'Inactive' )
142
- . select ( eb => eb . fn . count ( 'id' ) . as ( 'count' ) )
143
- . executeTakeFirst ( )
144
-
145
- const topSpenders = await db
146
- . selectFrom ( 'customers' )
147
- . select ( [ 'id' , 'name' , 'email' , 'total_spent' ] )
148
- . orderBy ( 'total_spent' , 'desc' )
149
- . limit ( 5 )
150
- . execute ( )
151
-
152
- const recentCustomers = await db
153
- . selectFrom ( 'customers' )
154
- . select ( [ 'id' , 'name' , 'email' , 'created_at' ] )
155
- . orderBy ( 'created_at' , 'desc' )
156
- . limit ( 5 )
157
- . execute ( )
158
-
159
- return {
160
- total : Number ( totalCustomers ?. count || 0 ) ,
161
- active : Number ( activeCustomers ?. count || 0 ) ,
162
- inactive : Number ( inactiveCustomers ?. count || 0 ) ,
163
- topSpenders,
164
- recentCustomers,
165
- }
166
- }
0 commit comments