@devlider001/washlab-backend 1.0.4 → 1.0.5
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.
- package/convex/_generated/api.d.ts +2 -0
- package/convex/audit.d.ts +39 -0
- package/convex/notifications.d.ts +170 -0
- package/convex/schema.d.ts +51 -0
- package/dist/convex/admin.d.ts +377 -0
- package/dist/convex/admin.d.ts.map +1 -0
- package/dist/convex/admin.js +959 -0
- package/dist/convex/admin.js.map +1 -0
- package/dist/convex/analytics.d.ts +87 -0
- package/dist/convex/analytics.d.ts.map +1 -0
- package/dist/convex/analytics.js +361 -0
- package/dist/convex/analytics.js.map +1 -0
- package/dist/convex/attendants.d.ts +140 -0
- package/dist/convex/attendants.d.ts.map +1 -0
- package/dist/convex/attendants.js +337 -0
- package/dist/convex/attendants.js.map +1 -0
- package/dist/convex/audit.d.ts +158 -0
- package/dist/convex/audit.d.ts.map +1 -0
- package/dist/convex/audit.js +184 -0
- package/dist/convex/audit.js.map +1 -0
- package/dist/convex/clerk.d.ts +53 -0
- package/dist/convex/clerk.d.ts.map +1 -0
- package/dist/convex/clerk.js +316 -0
- package/dist/convex/clerk.js.map +1 -0
- package/dist/convex/customers.d.ts +224 -0
- package/dist/convex/customers.d.ts.map +1 -0
- package/dist/convex/customers.js +504 -0
- package/dist/convex/customers.js.map +1 -0
- package/dist/convex/http.d.ts +3 -0
- package/dist/convex/http.d.ts.map +1 -0
- package/dist/convex/http.js +115 -0
- package/dist/convex/http.js.map +1 -0
- package/dist/convex/lib/audit.d.ts +36 -0
- package/dist/convex/lib/audit.d.ts.map +1 -0
- package/dist/convex/lib/audit.js +59 -0
- package/dist/convex/lib/audit.js.map +1 -0
- package/dist/convex/lib/auth.d.ts +96 -0
- package/dist/convex/lib/auth.d.ts.map +1 -0
- package/dist/convex/lib/auth.js +94 -0
- package/dist/convex/lib/auth.js.map +1 -0
- package/dist/convex/lib/utils.d.ts +38 -0
- package/dist/convex/lib/utils.d.ts.map +1 -0
- package/dist/convex/lib/utils.js +71 -0
- package/dist/convex/lib/utils.js.map +1 -0
- package/dist/convex/loyalty.d.ts +82 -0
- package/dist/convex/loyalty.d.ts.map +1 -0
- package/dist/convex/loyalty.js +286 -0
- package/dist/convex/loyalty.js.map +1 -0
- package/dist/convex/orders.d.ts +326 -0
- package/dist/convex/orders.d.ts.map +1 -0
- package/dist/convex/orders.js +570 -0
- package/dist/convex/orders.js.map +1 -0
- package/dist/convex/payments.d.ts +134 -0
- package/dist/convex/payments.d.ts.map +1 -0
- package/dist/convex/payments.js +360 -0
- package/dist/convex/payments.js.map +1 -0
- package/dist/convex/resources.d.ts +119 -0
- package/dist/convex/resources.d.ts.map +1 -0
- package/dist/convex/resources.js +283 -0
- package/dist/convex/resources.js.map +1 -0
- package/dist/convex/schema.d.ts +450 -0
- package/dist/convex/schema.d.ts.map +1 -0
- package/dist/convex/schema.js +347 -0
- package/dist/convex/schema.js.map +1 -0
- package/dist/convex/vouchers.d.ts +187 -0
- package/dist/convex/vouchers.d.ts.map +1 -0
- package/dist/convex/vouchers.js +464 -0
- package/dist/convex/vouchers.js.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
import { query, mutation } from "./_generated/server";
|
|
2
|
+
import { v } from "convex/values";
|
|
3
|
+
import { getClerkIdentity, getCurrentCustomer } from "./lib/auth";
|
|
4
|
+
import { createAuditLog } from "./lib/audit";
|
|
5
|
+
import { getCurrentTimestamp } from "./lib/utils";
|
|
6
|
+
/**
|
|
7
|
+
* Customer Functions
|
|
8
|
+
*
|
|
9
|
+
* Handles customer profile management, registration, and lookups.
|
|
10
|
+
* Customers can be guests (walk-in, no account) or registered (with Clerk account).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Get customer by phone number
|
|
14
|
+
* Used by POS for walk-in customer lookup
|
|
15
|
+
*/
|
|
16
|
+
export const getByPhone = query({
|
|
17
|
+
args: {
|
|
18
|
+
phoneNumber: v.string(),
|
|
19
|
+
},
|
|
20
|
+
handler: async (ctx, args) => {
|
|
21
|
+
const user = await ctx.db
|
|
22
|
+
.query("users")
|
|
23
|
+
.withIndex("by_phone", (q) => q.eq("phoneNumber", args.phoneNumber))
|
|
24
|
+
.first();
|
|
25
|
+
if (!user || user.isDeleted) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return user;
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* Get current customer profile (from authenticated Clerk session)
|
|
33
|
+
*/
|
|
34
|
+
export const getProfile = query({
|
|
35
|
+
args: {},
|
|
36
|
+
handler: async (ctx) => {
|
|
37
|
+
const user = await getCurrentCustomer(ctx);
|
|
38
|
+
// Get order count for summary
|
|
39
|
+
const orders = await ctx.db
|
|
40
|
+
.query("orders")
|
|
41
|
+
.withIndex("by_customer", (q) => q.eq("customerId", user._id))
|
|
42
|
+
.collect();
|
|
43
|
+
const completedOrders = orders.filter((o) => !o.isDeleted && o.status === "completed").length;
|
|
44
|
+
return {
|
|
45
|
+
...user,
|
|
46
|
+
orderCount: orders.length,
|
|
47
|
+
completedOrderCount: completedOrders,
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* Get customer order history - Paginated
|
|
53
|
+
* Supports usePaginatedQuery for infinite scroll
|
|
54
|
+
*/
|
|
55
|
+
export const getOrders = query({
|
|
56
|
+
args: {
|
|
57
|
+
cursor: v.optional(v.string()),
|
|
58
|
+
numItems: v.optional(v.number()),
|
|
59
|
+
},
|
|
60
|
+
handler: async (ctx, args) => {
|
|
61
|
+
const user = await getCurrentCustomer(ctx);
|
|
62
|
+
const numItems = args.numItems ?? 20;
|
|
63
|
+
const result = await ctx.db
|
|
64
|
+
.query("orders")
|
|
65
|
+
.withIndex("by_customer", (q) => q.eq("customerId", user._id))
|
|
66
|
+
.order("desc")
|
|
67
|
+
.filter((q) => q.eq(q.field("isDeleted"), false))
|
|
68
|
+
.paginate({
|
|
69
|
+
cursor: args.cursor ?? null,
|
|
70
|
+
numItems,
|
|
71
|
+
});
|
|
72
|
+
return {
|
|
73
|
+
page: result.page,
|
|
74
|
+
isDone: result.isDone,
|
|
75
|
+
continueCursor: result.continueCursor,
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
/**
|
|
80
|
+
* Get customer loyalty points balance
|
|
81
|
+
*/
|
|
82
|
+
export const getLoyaltyPoints = query({
|
|
83
|
+
args: {},
|
|
84
|
+
handler: async (ctx) => {
|
|
85
|
+
const user = await getCurrentCustomer(ctx);
|
|
86
|
+
const loyaltyPoints = await ctx.db
|
|
87
|
+
.query("loyaltyPoints")
|
|
88
|
+
.withIndex("by_customer", (q) => q.eq("customerId", user._id))
|
|
89
|
+
.first();
|
|
90
|
+
if (!loyaltyPoints || loyaltyPoints.isDeleted) {
|
|
91
|
+
return {
|
|
92
|
+
points: 0,
|
|
93
|
+
totalEarned: 0,
|
|
94
|
+
totalRedeemed: 0,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
points: loyaltyPoints.points,
|
|
99
|
+
totalEarned: loyaltyPoints.totalEarned,
|
|
100
|
+
totalRedeemed: loyaltyPoints.totalRedeemed,
|
|
101
|
+
lastEarnedAt: loyaltyPoints.lastEarnedAt,
|
|
102
|
+
lastRedeemedAt: loyaltyPoints.lastRedeemedAt,
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
/**
|
|
107
|
+
* Create guest customer (walk-in, no Clerk account)
|
|
108
|
+
* Used when creating walk-in orders at POS
|
|
109
|
+
*/
|
|
110
|
+
export const createGuest = mutation({
|
|
111
|
+
args: {
|
|
112
|
+
name: v.string(),
|
|
113
|
+
phoneNumber: v.string(),
|
|
114
|
+
},
|
|
115
|
+
handler: async (ctx, args) => {
|
|
116
|
+
// Check if customer already exists
|
|
117
|
+
const existing = await ctx.db
|
|
118
|
+
.query("users")
|
|
119
|
+
.withIndex("by_phone", (q) => q.eq("phoneNumber", args.phoneNumber))
|
|
120
|
+
.first();
|
|
121
|
+
if (existing) {
|
|
122
|
+
if (!existing.isDeleted) {
|
|
123
|
+
return existing._id;
|
|
124
|
+
}
|
|
125
|
+
// If deleted, reactivate the account
|
|
126
|
+
await ctx.db.patch(existing._id, {
|
|
127
|
+
isDeleted: false,
|
|
128
|
+
name: args.name,
|
|
129
|
+
});
|
|
130
|
+
return existing._id;
|
|
131
|
+
}
|
|
132
|
+
// Create new guest customer
|
|
133
|
+
const userId = await ctx.db.insert("users", {
|
|
134
|
+
name: args.name,
|
|
135
|
+
phoneNumber: args.phoneNumber,
|
|
136
|
+
clerkUserId: undefined,
|
|
137
|
+
isRegistered: false,
|
|
138
|
+
isVerified: false,
|
|
139
|
+
status: "active",
|
|
140
|
+
createdAt: getCurrentTimestamp(),
|
|
141
|
+
isDeleted: false,
|
|
142
|
+
});
|
|
143
|
+
await createAuditLog({
|
|
144
|
+
ctx,
|
|
145
|
+
actorId: "system",
|
|
146
|
+
actorType: "admin",
|
|
147
|
+
actorRole: "system",
|
|
148
|
+
action: "customer.guest_created",
|
|
149
|
+
entityType: "user",
|
|
150
|
+
entityId: userId,
|
|
151
|
+
details: JSON.stringify({ phoneNumber: args.phoneNumber, name: args.name }),
|
|
152
|
+
});
|
|
153
|
+
return userId;
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
/**
|
|
157
|
+
* Register customer (link Clerk account to customer profile)
|
|
158
|
+
* Called after customer signs up via Clerk
|
|
159
|
+
*/
|
|
160
|
+
export const register = mutation({
|
|
161
|
+
args: {
|
|
162
|
+
name: v.string(),
|
|
163
|
+
phoneNumber: v.string(),
|
|
164
|
+
email: v.optional(v.string()),
|
|
165
|
+
},
|
|
166
|
+
handler: async (ctx, args) => {
|
|
167
|
+
const identity = await getClerkIdentity(ctx);
|
|
168
|
+
const clerkUserId = identity.subject;
|
|
169
|
+
// Check if customer already exists with this Clerk ID
|
|
170
|
+
const existingByClerk = await ctx.db
|
|
171
|
+
.query("users")
|
|
172
|
+
.withIndex("by_clerk_user", (q) => q.eq("clerkUserId", clerkUserId))
|
|
173
|
+
.first();
|
|
174
|
+
if (existingByClerk && !existingByClerk.isDeleted) {
|
|
175
|
+
throw new Error("Customer account already registered");
|
|
176
|
+
}
|
|
177
|
+
// Check if guest customer exists with this phone number
|
|
178
|
+
const existingByPhone = await ctx.db
|
|
179
|
+
.query("users")
|
|
180
|
+
.withIndex("by_phone", (q) => q.eq("phoneNumber", args.phoneNumber))
|
|
181
|
+
.first();
|
|
182
|
+
let userId;
|
|
183
|
+
if (existingByPhone && !existingByPhone.isDeleted) {
|
|
184
|
+
// Update existing guest customer with Clerk ID
|
|
185
|
+
userId = existingByPhone._id;
|
|
186
|
+
await ctx.db.patch(userId, {
|
|
187
|
+
clerkUserId,
|
|
188
|
+
isRegistered: true,
|
|
189
|
+
isVerified: identity.emailVerified ?? false,
|
|
190
|
+
email: args.email ?? existingByPhone.email,
|
|
191
|
+
name: args.name,
|
|
192
|
+
lastLoginAt: getCurrentTimestamp(),
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
else if (existingByPhone && existingByPhone.isDeleted) {
|
|
196
|
+
// Reactivate deleted account
|
|
197
|
+
userId = existingByPhone._id;
|
|
198
|
+
await ctx.db.patch(userId, {
|
|
199
|
+
clerkUserId,
|
|
200
|
+
isRegistered: true,
|
|
201
|
+
isVerified: identity.emailVerified ?? false,
|
|
202
|
+
email: args.email,
|
|
203
|
+
name: args.name,
|
|
204
|
+
isDeleted: false,
|
|
205
|
+
lastLoginAt: getCurrentTimestamp(),
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
// Create new registered customer
|
|
210
|
+
userId = await ctx.db.insert("users", {
|
|
211
|
+
name: args.name,
|
|
212
|
+
phoneNumber: args.phoneNumber,
|
|
213
|
+
email: args.email,
|
|
214
|
+
clerkUserId,
|
|
215
|
+
isRegistered: true,
|
|
216
|
+
isVerified: identity.emailVerified ?? false,
|
|
217
|
+
status: "active",
|
|
218
|
+
createdAt: getCurrentTimestamp(),
|
|
219
|
+
lastLoginAt: getCurrentTimestamp(),
|
|
220
|
+
isDeleted: false,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
await createAuditLog({
|
|
224
|
+
ctx,
|
|
225
|
+
actorId: clerkUserId,
|
|
226
|
+
actorType: "customer",
|
|
227
|
+
actorRole: "customer",
|
|
228
|
+
action: "customer.registered",
|
|
229
|
+
entityType: "user",
|
|
230
|
+
entityId: userId,
|
|
231
|
+
details: JSON.stringify({ phoneNumber: args.phoneNumber, email: args.email }),
|
|
232
|
+
});
|
|
233
|
+
return userId;
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
/**
|
|
237
|
+
* Update customer profile
|
|
238
|
+
*/
|
|
239
|
+
export const updateProfile = mutation({
|
|
240
|
+
args: {
|
|
241
|
+
name: v.optional(v.string()),
|
|
242
|
+
email: v.optional(v.string()),
|
|
243
|
+
preferredBranchId: v.optional(v.id("branches")),
|
|
244
|
+
},
|
|
245
|
+
handler: async (ctx, args) => {
|
|
246
|
+
const user = await getCurrentCustomer(ctx);
|
|
247
|
+
const identity = await getClerkIdentity(ctx);
|
|
248
|
+
const updates = {};
|
|
249
|
+
if (args.name !== undefined) {
|
|
250
|
+
updates.name = args.name;
|
|
251
|
+
}
|
|
252
|
+
if (args.email !== undefined) {
|
|
253
|
+
updates.email = args.email;
|
|
254
|
+
}
|
|
255
|
+
if (args.preferredBranchId !== undefined) {
|
|
256
|
+
// Verify branch exists
|
|
257
|
+
const branch = await ctx.db.get(args.preferredBranchId);
|
|
258
|
+
if (!branch || branch.isDeleted) {
|
|
259
|
+
throw new Error("Branch not found");
|
|
260
|
+
}
|
|
261
|
+
updates.preferredBranchId = args.preferredBranchId;
|
|
262
|
+
}
|
|
263
|
+
updates.lastLoginAt = getCurrentTimestamp();
|
|
264
|
+
await ctx.db.patch(user._id, updates);
|
|
265
|
+
await createAuditLog({
|
|
266
|
+
ctx,
|
|
267
|
+
actorId: identity.subject,
|
|
268
|
+
actorType: "customer",
|
|
269
|
+
actorRole: "customer",
|
|
270
|
+
action: "customer.profile_updated",
|
|
271
|
+
entityType: "user",
|
|
272
|
+
entityId: user._id,
|
|
273
|
+
details: JSON.stringify(updates),
|
|
274
|
+
});
|
|
275
|
+
return user._id;
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
/**
|
|
279
|
+
* Create test user (DEV ONLY)
|
|
280
|
+
*
|
|
281
|
+
* This mutation allows creating test users in development without requiring
|
|
282
|
+
* Clerk authentication. Useful for testing and development.
|
|
283
|
+
*
|
|
284
|
+
* WARNING: This should only be used in development environments.
|
|
285
|
+
* In production, users should be created via Clerk webhooks or the register mutation.
|
|
286
|
+
*/
|
|
287
|
+
export const createTestUser = mutation({
|
|
288
|
+
args: {
|
|
289
|
+
name: v.string(),
|
|
290
|
+
phoneNumber: v.string(),
|
|
291
|
+
email: v.optional(v.string()),
|
|
292
|
+
clerkUserId: v.optional(v.string()), // Optional: can simulate Clerk user
|
|
293
|
+
isRegistered: v.optional(v.boolean()), // Default: true if clerkUserId provided
|
|
294
|
+
isVerified: v.optional(v.boolean()), // Default: false
|
|
295
|
+
},
|
|
296
|
+
handler: async (ctx, args) => {
|
|
297
|
+
// Check if customer already exists by phone
|
|
298
|
+
const existingByPhone = await ctx.db
|
|
299
|
+
.query("users")
|
|
300
|
+
.withIndex("by_phone", (q) => q.eq("phoneNumber", args.phoneNumber))
|
|
301
|
+
.first();
|
|
302
|
+
if (existingByPhone && !existingByPhone.isDeleted) {
|
|
303
|
+
throw new Error("Customer with this phone number already exists");
|
|
304
|
+
}
|
|
305
|
+
// Check if customer exists by Clerk ID (if provided)
|
|
306
|
+
if (args.clerkUserId) {
|
|
307
|
+
const existingByClerk = await ctx.db
|
|
308
|
+
.query("users")
|
|
309
|
+
.withIndex("by_clerk_user", (q) => q.eq("clerkUserId", args.clerkUserId))
|
|
310
|
+
.first();
|
|
311
|
+
if (existingByClerk && !existingByClerk.isDeleted) {
|
|
312
|
+
throw new Error("Customer with this Clerk ID already exists");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const now = getCurrentTimestamp();
|
|
316
|
+
const isRegistered = args.isRegistered ?? (args.clerkUserId !== undefined);
|
|
317
|
+
const isVerified = args.isVerified ?? false;
|
|
318
|
+
// If existing but deleted, reactivate
|
|
319
|
+
if (existingByPhone && existingByPhone.isDeleted) {
|
|
320
|
+
await ctx.db.patch(existingByPhone._id, {
|
|
321
|
+
name: args.name,
|
|
322
|
+
email: args.email,
|
|
323
|
+
clerkUserId: args.clerkUserId,
|
|
324
|
+
isRegistered,
|
|
325
|
+
isVerified,
|
|
326
|
+
isDeleted: false,
|
|
327
|
+
lastLoginAt: now,
|
|
328
|
+
});
|
|
329
|
+
await createAuditLog({
|
|
330
|
+
ctx,
|
|
331
|
+
actorId: args.clerkUserId || "system",
|
|
332
|
+
actorType: "admin",
|
|
333
|
+
actorRole: "system",
|
|
334
|
+
action: "customer.test_user_created",
|
|
335
|
+
entityType: "user",
|
|
336
|
+
entityId: existingByPhone._id,
|
|
337
|
+
details: JSON.stringify({
|
|
338
|
+
phoneNumber: args.phoneNumber,
|
|
339
|
+
email: args.email,
|
|
340
|
+
isTestUser: true
|
|
341
|
+
}),
|
|
342
|
+
});
|
|
343
|
+
return existingByPhone._id;
|
|
344
|
+
}
|
|
345
|
+
// Create new test user
|
|
346
|
+
const userId = await ctx.db.insert("users", {
|
|
347
|
+
name: args.name,
|
|
348
|
+
phoneNumber: args.phoneNumber,
|
|
349
|
+
email: args.email,
|
|
350
|
+
clerkUserId: args.clerkUserId,
|
|
351
|
+
isRegistered,
|
|
352
|
+
isVerified,
|
|
353
|
+
status: "active",
|
|
354
|
+
createdAt: now,
|
|
355
|
+
lastLoginAt: now,
|
|
356
|
+
isDeleted: false,
|
|
357
|
+
});
|
|
358
|
+
await createAuditLog({
|
|
359
|
+
ctx,
|
|
360
|
+
actorId: args.clerkUserId || "system",
|
|
361
|
+
actorType: "admin",
|
|
362
|
+
actorRole: "system",
|
|
363
|
+
action: "customer.test_user_created",
|
|
364
|
+
entityType: "user",
|
|
365
|
+
entityId: userId,
|
|
366
|
+
details: JSON.stringify({
|
|
367
|
+
phoneNumber: args.phoneNumber,
|
|
368
|
+
email: args.email,
|
|
369
|
+
isTestUser: true
|
|
370
|
+
}),
|
|
371
|
+
});
|
|
372
|
+
return userId;
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
/**
|
|
376
|
+
* Search customers by name or phone number
|
|
377
|
+
* Used by POS for customer lookup
|
|
378
|
+
*/
|
|
379
|
+
export const search = query({
|
|
380
|
+
args: {
|
|
381
|
+
query: v.string(),
|
|
382
|
+
limit: v.optional(v.number()),
|
|
383
|
+
},
|
|
384
|
+
handler: async (ctx, args) => {
|
|
385
|
+
// Allow both attendants and admins
|
|
386
|
+
try {
|
|
387
|
+
const { getCurrentAttendant } = await import("./lib/auth");
|
|
388
|
+
await getCurrentAttendant(ctx);
|
|
389
|
+
}
|
|
390
|
+
catch {
|
|
391
|
+
const { getCurrentAdmin } = await import("./lib/auth");
|
|
392
|
+
await getCurrentAdmin(ctx);
|
|
393
|
+
}
|
|
394
|
+
const limit = args.limit ?? 20;
|
|
395
|
+
const searchQuery = args.query.toLowerCase().trim();
|
|
396
|
+
if (searchQuery.length < 2) {
|
|
397
|
+
return [];
|
|
398
|
+
}
|
|
399
|
+
// Get all customers
|
|
400
|
+
const allCustomers = await ctx.db
|
|
401
|
+
.query("users")
|
|
402
|
+
.filter((q) => q.eq(q.field("isDeleted"), false))
|
|
403
|
+
.collect();
|
|
404
|
+
// Filter by name or phone
|
|
405
|
+
const filtered = allCustomers.filter((c) => {
|
|
406
|
+
const nameMatch = c.name.toLowerCase().includes(searchQuery);
|
|
407
|
+
const phoneMatch = c.phoneNumber.includes(searchQuery);
|
|
408
|
+
return nameMatch || phoneMatch;
|
|
409
|
+
});
|
|
410
|
+
// Sort by relevance (exact phone match first, then name match)
|
|
411
|
+
const sorted = filtered.sort((a, b) => {
|
|
412
|
+
const aPhoneExact = a.phoneNumber === searchQuery;
|
|
413
|
+
const bPhoneExact = b.phoneNumber === searchQuery;
|
|
414
|
+
if (aPhoneExact && !bPhoneExact)
|
|
415
|
+
return -1;
|
|
416
|
+
if (!aPhoneExact && bPhoneExact)
|
|
417
|
+
return 1;
|
|
418
|
+
const aNameStarts = a.name.toLowerCase().startsWith(searchQuery);
|
|
419
|
+
const bNameStarts = b.name.toLowerCase().startsWith(searchQuery);
|
|
420
|
+
if (aNameStarts && !bNameStarts)
|
|
421
|
+
return -1;
|
|
422
|
+
if (!aNameStarts && bNameStarts)
|
|
423
|
+
return 1;
|
|
424
|
+
return a.name.localeCompare(b.name);
|
|
425
|
+
});
|
|
426
|
+
// Get order counts for each customer
|
|
427
|
+
const customersWithStats = await Promise.all(sorted.slice(0, limit).map(async (customer) => {
|
|
428
|
+
const orders = await ctx.db
|
|
429
|
+
.query("orders")
|
|
430
|
+
.withIndex("by_customer", (q) => q.eq("customerId", customer._id))
|
|
431
|
+
.collect();
|
|
432
|
+
const completedOrders = orders.filter((o) => !o.isDeleted && o.status === "completed").length;
|
|
433
|
+
const totalSpent = orders
|
|
434
|
+
.filter((o) => !o.isDeleted && o.paymentStatus === "paid")
|
|
435
|
+
.reduce((sum, o) => sum + o.finalPrice, 0);
|
|
436
|
+
// Get last order date
|
|
437
|
+
const lastOrder = orders
|
|
438
|
+
.filter((o) => !o.isDeleted)
|
|
439
|
+
.sort((a, b) => b.createdAt - a.createdAt)[0];
|
|
440
|
+
return {
|
|
441
|
+
...customer,
|
|
442
|
+
orderCount: orders.filter((o) => !o.isDeleted).length,
|
|
443
|
+
completedOrderCount: completedOrders,
|
|
444
|
+
totalSpent: Math.round(totalSpent * 100) / 100,
|
|
445
|
+
lastOrderDate: lastOrder?.createdAt,
|
|
446
|
+
};
|
|
447
|
+
}));
|
|
448
|
+
return customersWithStats;
|
|
449
|
+
},
|
|
450
|
+
});
|
|
451
|
+
/**
|
|
452
|
+
* Get customer details with full order history
|
|
453
|
+
*/
|
|
454
|
+
export const getDetails = query({
|
|
455
|
+
args: {
|
|
456
|
+
customerId: v.id("users"),
|
|
457
|
+
},
|
|
458
|
+
handler: async (ctx, args) => {
|
|
459
|
+
// Allow both attendants and admins
|
|
460
|
+
try {
|
|
461
|
+
const { getCurrentAttendant } = await import("./lib/auth");
|
|
462
|
+
await getCurrentAttendant(ctx);
|
|
463
|
+
}
|
|
464
|
+
catch {
|
|
465
|
+
const { getCurrentAdmin } = await import("./lib/auth");
|
|
466
|
+
await getCurrentAdmin(ctx);
|
|
467
|
+
}
|
|
468
|
+
const customer = await ctx.db.get(args.customerId);
|
|
469
|
+
if (!customer || customer.isDeleted) {
|
|
470
|
+
throw new Error("Customer not found");
|
|
471
|
+
}
|
|
472
|
+
// Get all orders
|
|
473
|
+
const orders = await ctx.db
|
|
474
|
+
.query("orders")
|
|
475
|
+
.withIndex("by_customer", (q) => q.eq("customerId", args.customerId))
|
|
476
|
+
.collect();
|
|
477
|
+
const activeOrders = orders.filter((o) => !o.isDeleted);
|
|
478
|
+
const completedOrders = activeOrders.filter((o) => o.status === "completed");
|
|
479
|
+
const totalSpent = activeOrders
|
|
480
|
+
.filter((o) => o.paymentStatus === "paid")
|
|
481
|
+
.reduce((sum, o) => sum + o.finalPrice, 0);
|
|
482
|
+
// Get loyalty points
|
|
483
|
+
const loyaltyPoints = await ctx.db
|
|
484
|
+
.query("loyaltyPoints")
|
|
485
|
+
.withIndex("by_customer", (q) => q.eq("customerId", args.customerId))
|
|
486
|
+
.first();
|
|
487
|
+
// Get last order
|
|
488
|
+
const lastOrder = activeOrders
|
|
489
|
+
.sort((a, b) => b.createdAt - a.createdAt)[0];
|
|
490
|
+
return {
|
|
491
|
+
...customer,
|
|
492
|
+
orderCount: activeOrders.length,
|
|
493
|
+
completedOrderCount: completedOrders.length,
|
|
494
|
+
totalSpent: Math.round(totalSpent * 100) / 100,
|
|
495
|
+
averageOrderValue: activeOrders.length > 0
|
|
496
|
+
? Math.round((totalSpent / activeOrders.length) * 100) / 100
|
|
497
|
+
: 0,
|
|
498
|
+
loyaltyPoints: loyaltyPoints?.points || 0,
|
|
499
|
+
lastOrderDate: lastOrder?.createdAt,
|
|
500
|
+
lastOrderNumber: lastOrder?.orderNumber,
|
|
501
|
+
};
|
|
502
|
+
},
|
|
503
|
+
});
|
|
504
|
+
//# sourceMappingURL=customers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customers.js","sourceRoot":"","sources":["../../convex/customers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../convex/http.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,IAAI,oCAAe,CAAA;AA0IzB,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { httpRouter } from "convex/server";
|
|
2
|
+
import { httpAction } from "./_generated/server";
|
|
3
|
+
import { internal } from "./_generated/api";
|
|
4
|
+
const http = httpRouter();
|
|
5
|
+
/**
|
|
6
|
+
* Clerk Webhook Handler
|
|
7
|
+
*
|
|
8
|
+
* Handles webhook events from Clerk to keep user data in sync.
|
|
9
|
+
*
|
|
10
|
+
* Required Clerk webhook events:
|
|
11
|
+
* - user.created
|
|
12
|
+
* - user.updated
|
|
13
|
+
* - user.deleted
|
|
14
|
+
*
|
|
15
|
+
* Setup in Clerk Dashboard:
|
|
16
|
+
* 1. Go to Webhooks section
|
|
17
|
+
* 2. Add endpoint: https://your-deployment.convex.site/clerk-webhook
|
|
18
|
+
* 3. Subscribe to: user.created, user.updated, user.deleted
|
|
19
|
+
* 4. Copy the signing secret and set as CLERK_WEBHOOK_SECRET in Convex
|
|
20
|
+
*/
|
|
21
|
+
http.route({
|
|
22
|
+
path: "/clerk-webhook",
|
|
23
|
+
method: "POST",
|
|
24
|
+
handler: httpAction(async (ctx, request) => {
|
|
25
|
+
// Verify webhook signature (optional but recommended)
|
|
26
|
+
const webhookSecret = process.env.CLERK_WEBHOOK_SECRET;
|
|
27
|
+
if (webhookSecret) {
|
|
28
|
+
const signature = request.headers.get("svix-signature");
|
|
29
|
+
if (!signature) {
|
|
30
|
+
return new Response("Missing signature", { status: 401 });
|
|
31
|
+
}
|
|
32
|
+
// Note: For production, implement proper signature verification
|
|
33
|
+
// using svix library or similar
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const event = await request.json();
|
|
37
|
+
// Handle different webhook event types
|
|
38
|
+
switch (event.type) {
|
|
39
|
+
case "user.created": {
|
|
40
|
+
const userData = event.data;
|
|
41
|
+
// Extract user information
|
|
42
|
+
const clerkUserId = userData.id;
|
|
43
|
+
const email = userData.email_addresses?.[0]?.email_address;
|
|
44
|
+
const phoneNumber = userData.phone_numbers?.[0]?.phone_number;
|
|
45
|
+
const firstName = userData.first_name || "";
|
|
46
|
+
const lastName = userData.last_name || "";
|
|
47
|
+
const name = `${firstName} ${lastName}`.trim() || email || phoneNumber || "User";
|
|
48
|
+
const emailVerified = userData.email_addresses?.[0]?.verification?.status === "verified";
|
|
49
|
+
// Determine user type from Clerk metadata or roles
|
|
50
|
+
// You can customize this based on your Clerk setup
|
|
51
|
+
const userType = userData.public_metadata?.userType ||
|
|
52
|
+
userData.private_metadata?.userType ||
|
|
53
|
+
"customer"; // Default to customer
|
|
54
|
+
// Sync user to database
|
|
55
|
+
await ctx.runMutation(internal.clerk.syncUserCreated, {
|
|
56
|
+
clerkUserId,
|
|
57
|
+
email,
|
|
58
|
+
phoneNumber,
|
|
59
|
+
name,
|
|
60
|
+
emailVerified,
|
|
61
|
+
userType,
|
|
62
|
+
});
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
case "user.updated": {
|
|
66
|
+
const userData = event.data;
|
|
67
|
+
const clerkUserId = userData.id;
|
|
68
|
+
const email = userData.email_addresses?.[0]?.email_address;
|
|
69
|
+
const phoneNumber = userData.phone_numbers?.[0]?.phone_number;
|
|
70
|
+
const firstName = userData.first_name || "";
|
|
71
|
+
const lastName = userData.last_name || "";
|
|
72
|
+
const name = `${firstName} ${lastName}`.trim() || email || phoneNumber || "User";
|
|
73
|
+
const emailVerified = userData.email_addresses?.[0]?.verification?.status === "verified";
|
|
74
|
+
// Check if userType changed in metadata
|
|
75
|
+
const userType = userData.public_metadata?.userType ||
|
|
76
|
+
userData.private_metadata?.userType ||
|
|
77
|
+
undefined;
|
|
78
|
+
await ctx.runMutation(internal.clerk.syncUserUpdated, {
|
|
79
|
+
clerkUserId,
|
|
80
|
+
email,
|
|
81
|
+
phoneNumber,
|
|
82
|
+
name,
|
|
83
|
+
emailVerified,
|
|
84
|
+
userType,
|
|
85
|
+
});
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case "user.deleted": {
|
|
89
|
+
const userData = event.data;
|
|
90
|
+
const clerkUserId = userData.id;
|
|
91
|
+
await ctx.runMutation(internal.clerk.syncUserDeleted, {
|
|
92
|
+
clerkUserId,
|
|
93
|
+
});
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
default:
|
|
97
|
+
// Ignore unknown event types
|
|
98
|
+
console.log(`Unknown webhook event type: ${event.type}`);
|
|
99
|
+
}
|
|
100
|
+
return new Response(JSON.stringify({ received: true }), {
|
|
101
|
+
status: 200,
|
|
102
|
+
headers: { "Content-Type": "application/json" },
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
console.error("Webhook error:", error);
|
|
107
|
+
return new Response(JSON.stringify({ error: "Webhook processing failed" }), {
|
|
108
|
+
status: 500,
|
|
109
|
+
headers: { "Content-Type": "application/json" },
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}),
|
|
113
|
+
});
|
|
114
|
+
export default http;
|
|
115
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../convex/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE3C,MAAM,IAAI,GAAG,UAAU,EAAE,CAAA;AAEzB;;;;;;;;;;;;;;;GAeG;AACH,IAAI,CAAC,KAAK,CAAC;IACT,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,MAAM;IACd,OAAO,EAAE,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QACzC,sDAAsD;QACtD,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAA;QACtD,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;YACvD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,IAAI,QAAQ,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YAC3D,CAAC;YACD,gEAAgE;YAChE,gCAAgC;QAClC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,EAG/B,CAAA;YAED,uCAAuC;YACvC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;gBACnB,KAAK,cAAc,CAAC,CAAC,CAAC;oBACpB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAA;oBAE3B,2BAA2B;oBAC3B,MAAM,WAAW,GAAG,QAAQ,CAAC,EAAE,CAAA;oBAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,CAAA;oBAC1D,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,CAAA;oBAC7D,MAAM,SAAS,GAAG,QAAQ,CAAC,UAAU,IAAI,EAAE,CAAA;oBAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,IAAI,EAAE,CAAA;oBACzC,MAAM,IAAI,GACR,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,WAAW,IAAI,MAAM,CAAA;oBACrE,MAAM,aAAa,GACjB,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,KAAK,UAAU,CAAA;oBAEpE,mDAAmD;oBACnD,mDAAmD;oBACnD,MAAM,QAAQ,GACZ,QAAQ,CAAC,eAAe,EAAE,QAAQ;wBAClC,QAAQ,CAAC,gBAAgB,EAAE,QAAQ;wBACnC,UAAU,CAAA,CAAC,sBAAsB;oBAEnC,wBAAwB;oBACxB,MAAM,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,eAAe,EAAE;wBACpD,WAAW;wBACX,KAAK;wBACL,WAAW;wBACX,IAAI;wBACJ,aAAa;wBACb,QAAQ;qBACT,CAAC,CAAA;oBAEF,MAAK;gBACP,CAAC;gBAED,KAAK,cAAc,CAAC,CAAC,CAAC;oBACpB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAA;oBAC3B,MAAM,WAAW,GAAG,QAAQ,CAAC,EAAE,CAAA;oBAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,CAAA;oBAC1D,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,CAAA;oBAC7D,MAAM,SAAS,GAAG,QAAQ,CAAC,UAAU,IAAI,EAAE,CAAA;oBAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,IAAI,EAAE,CAAA;oBACzC,MAAM,IAAI,GACR,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,WAAW,IAAI,MAAM,CAAA;oBACrE,MAAM,aAAa,GACjB,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,KAAK,UAAU,CAAA;oBAEpE,wCAAwC;oBACxC,MAAM,QAAQ,GACZ,QAAQ,CAAC,eAAe,EAAE,QAAQ;wBAClC,QAAQ,CAAC,gBAAgB,EAAE,QAAQ;wBACnC,SAAS,CAAA;oBAEX,MAAM,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,eAAe,EAAE;wBACpD,WAAW;wBACX,KAAK;wBACL,WAAW;wBACX,IAAI;wBACJ,aAAa;wBACb,QAAQ;qBACT,CAAC,CAAA;oBAEF,MAAK;gBACP,CAAC;gBAED,KAAK,cAAc,CAAC,CAAC,CAAC;oBACpB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAA;oBAC3B,MAAM,WAAW,GAAG,QAAQ,CAAC,EAAE,CAAA;oBAE/B,MAAM,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,eAAe,EAAE;wBACpD,WAAW;qBACZ,CAAC,CAAA;oBAEF,MAAK;gBACP,CAAC;gBAED;oBACE,6BAA6B;oBAC7B,OAAO,CAAC,GAAG,CAAC,+BAA+B,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;YAC5D,CAAC;YAED,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE;gBACtD,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;aAChD,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAA;YACtC,OAAO,IAAI,QAAQ,CACjB,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC,EACtD;gBACE,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;aAChD,CACF,CAAA;QACH,CAAC;IACH,CAAC,CAAC;CACH,CAAC,CAAA;AAEF,eAAe,IAAI,CAAA"}
|