source: database/drizzle/queries/builds.ts@ 226fbbb

main
Last change on this file since 226fbbb was c4dd17d, checked in by Tome <gjorgievtome@…>, 7 months ago

update queries

  • Property mode set to 100644
File size: 11.0 KB
RevLine 
[1ebac59]1import type { Database } from "../db";
[c4dd17d]2import {
3 buildComponentsTable,
4 buildsTable,
5 componentsTable,
6 favoriteBuildsTable,
7 ratingBuildsTable,
8 reviewsTable, usersTable
9} from "../schema";
[1ebac59]10import {eq, desc, and, sql, ilike} from "drizzle-orm";
11
12export async function getPendingBuilds(db: Database) {
13 const pendingBuildsList = await db
14 .select({
15 id: buildsTable.id,
16 user_id: buildsTable.userId,
17 name: buildsTable.name,
18 created_at: buildsTable.createdAt,
19 total_price: buildsTable.totalPrice
20 })
21 .from(buildsTable)
22 .where(
23 eq(buildsTable.isApproved, false)
24 );
25
26 return pendingBuildsList;
27}
28
29export async function getUserBuilds(db: Database, userId: number) {
30 const userBuildsList = await db
31 .select({
32 id: buildsTable.id,
33 user_id: buildsTable.userId,
34 name: buildsTable.name,
35 created_at: buildsTable.createdAt,
36 total_price: buildsTable.totalPrice
37 })
38 .from(buildsTable)
39 .where(
40 eq(buildsTable.userId, userId)
41 );
42
43 return userBuildsList;
44}
45
46export async function setBuildApprovalStatus(db: Database, buildId: number, isApproved: boolean){
47 const result = await db
48 .update(buildsTable)
49 .set({
50 isApproved: isApproved
51 })
52 .where(
53 eq(buildsTable.id, buildId)
54 );
55
56 return result.rowCount;
57}
58
59export async function getFavoriteBuilds(db: Database, userId: number) {
60 const favoriteBuildsList = await db
61 .select({
62 id: buildsTable.id,
63 user_id: buildsTable.userId,
64 name: buildsTable.name,
65 created_at: buildsTable.createdAt,
66 total_price: buildsTable.totalPrice
67 })
68 .from(buildsTable)
69 .innerJoin(
70 favoriteBuildsTable,
71 eq(buildsTable.id, favoriteBuildsTable.buildId)
72 )
73 .where(
74 eq(favoriteBuildsTable.userId, userId)
75 );
76
77 return favoriteBuildsList;
78}
79
80export async function getApprovedBuilds(db: Database, limit?: number, q?: string) {
[c4dd17d]81 let queryConditions = [eq(buildsTable.isApproved, true)];
[1ebac59]82
83 if (q) {
84 queryConditions.push(
85 ilike(buildsTable.name, `%${q}%`)
86 );
87 }
88
89 const approvedBuildsList = await db
90 .select({
91 id: buildsTable.id,
92 user_id: buildsTable.userId,
93 name: buildsTable.name,
94 created_at: buildsTable.createdAt,
95 total_price: buildsTable.totalPrice
96 })
97 .from(buildsTable)
98 .where(
99 and (
100 ...queryConditions
101 )
102 )
103 .orderBy(
104 desc(buildsTable.totalPrice)
105 )
106 .limit(limit || 100); // 100 placeholder
107
108 return approvedBuildsList;
109}
110
111export async function getHighestRankedBuilds(db: Database, limit? : number) {
112 const highestRankedBuildsList = await db
113 .select({
114 id: buildsTable.id,
115 user_id: buildsTable.userId,
116 name: buildsTable.name,
117 created_at: buildsTable.createdAt,
[c4dd17d]118 total_price: buildsTable.totalPrice,
119 avgRating: sql<number>`AVG(${ratingBuildsTable.value}::float)`
[1ebac59]120 })
121 .from(buildsTable)
122 .innerJoin(
123 ratingBuildsTable,
124 eq(buildsTable.id, ratingBuildsTable.buildId)
125 )
126 .where(
127 eq(buildsTable.isApproved, true)
128 )
[c4dd17d]129 .groupBy(buildsTable.id)
[1ebac59]130 .orderBy(
131 desc(sql<number>`AVG(${ratingBuildsTable.value}::float)`)
132 )
133 .limit(limit || 100); // 100 placeholder
134
135 return highestRankedBuildsList;
136}
137
[c4dd17d]138export async function getBuildDetails(db: Database, buildId: number, userId?: number) {
139 return db.transaction(async (tx) => {
140 const [buildDetails] = await tx
141 .select({
142 id: buildsTable.id,
143 userId: buildsTable.userId,
144 name: buildsTable.name,
145 createdAt: buildsTable.createdAt,
146 description: buildsTable.description,
147 totalPrice: buildsTable.totalPrice,
148 isApproved: buildsTable.isApproved,
149 creator: usersTable.username
150 })
151 .from(buildsTable)
152 .innerJoin(
153 usersTable,
154 eq(buildsTable.userId, usersTable.id)
155 )
156 .where(
157 eq(buildsTable.id, buildId)
158 )
159 .limit(1);
160
161 if (!buildDetails) return null;
162
163 const components = await tx
164 .select({
165 componentId: buildComponentsTable.componentId,
166 component: componentsTable
167 })
168 .from(buildComponentsTable)
169 .innerJoin(
170 componentsTable,
171 eq(buildComponentsTable.componentId, componentsTable.id)
172 )
173 .where(
174 eq(buildComponentsTable.buildId, buildId)
175 );
[1ebac59]176
[c4dd17d]177 const reviews = await tx
178 .select({
179 username: usersTable.username,
180 content: reviewsTable.content,
181 createdAt: reviewsTable.createdAt
182 })
183 .from(reviewsTable)
184 .innerJoin(
185 usersTable,
186 eq(reviewsTable.userId, usersTable.id)
187 )
188 .where(
189 eq(reviewsTable.buildId, buildId)
190 )
191 .orderBy(
192 desc(reviewsTable.createdAt)
193 );
194
195 let [ratingStatistics] = await tx
196 .select({
197 averageRating: sql<number>`COALESCE(AVG(${ratingBuildsTable.value}::float), 0)`.as("averageRating"),
198 ratingCount: sql<number>`COUNT(${ratingBuildsTable.value})`.as("ratingCount")
199 })
200 .from(ratingBuildsTable)
201 .where(
202 eq(ratingBuildsTable.buildId, buildId)
203 )
204 .groupBy(ratingBuildsTable.buildId);
205
206 ratingStatistics = {
207 averageRating: Number(ratingStatistics?.averageRating ?? 0),
208 ratingCount: Number(ratingStatistics?.ratingCount ?? 0),
209 }
210
211 let userRating = null;
212 let isFavorite = false;
213 let userReview = null;
214
215 if(userId) {
216 const [rating] = await tx
217 .select()
218 .from(ratingBuildsTable)
219 .where(
220 and(
221 eq(ratingBuildsTable.buildId, buildId),
222 eq(ratingBuildsTable.userId, userId)
223 )
224 )
225 .limit(1);
226
227 userRating = rating?.value ? Number(rating.value) : null;
228
229 const [favorite] = await tx
230 .select()
231 .from(favoriteBuildsTable)
232 .where(
233 and(
234 eq(favoriteBuildsTable.buildId, buildId),
235 eq(favoriteBuildsTable.userId, userId)
236 )
237 )
238 .limit(1);
239
240 isFavorite = !!favorite;
241
242 const [review] = await tx
243 .select()
244 .from(reviewsTable)
245 .where(
246 and(
247 eq(reviewsTable.buildId, buildId),
248 eq(reviewsTable.userId, userId)
249 )
250 )
251 .limit(1);
252
253 userReview = review?.content;
254 }
255
256 return {
257 ...buildDetails,
258 components: components.map(c => c.component),
259 reviews: reviews,
260 ratingStatistics: ratingStatistics,
261 userRating,
262 userReview,
263 isFavorite
264 };
265 });
[1ebac59]266}
267
268export async function toggleFavoriteBuild(db: Database, userId: number, buildId: number) {
269 const existing = await db
270 .select()
271 .from(favoriteBuildsTable)
272 .where(
273 and(
274 eq(favoriteBuildsTable.userId, userId),
275 eq(favoriteBuildsTable.buildId, buildId)
276 )
277 )
278 .limit(1);
279
280 if (existing.length) {
281 await db
282 .delete(favoriteBuildsTable)
283 .where(
284 and(
285 eq(favoriteBuildsTable.userId, userId),
286 eq(favoriteBuildsTable.buildId, buildId)
287 )
288 );
289
290 return { favorite: false };
291 }
292
293 await db
294 .insert(favoriteBuildsTable)
295 .values({
296 userId,
297 buildId,
298 });
299
300 return { favorite: true };
301}
302
303export async function setBuildRating(db: Database, userId: number, buildId: number, value: number) {
304 const result = await db
305 .insert(ratingBuildsTable)
306 .values({
307 userId,
308 buildId,
[c4dd17d]309 value: value
[1ebac59]310 })
311 .onConflictDoUpdate({
312 target: [ratingBuildsTable.userId, ratingBuildsTable.buildId],
313 set: {
[c4dd17d]314 value: value,
[1ebac59]315 },
316 });
317}
318
319export async function setBuildReview(db: Database, userId: number, buildId: number, content: string) {
320 const existing = await db
321 .select()
322 .from(reviewsTable)
323 .where(
324 and(
325 eq(reviewsTable.userId, userId),
326 eq(reviewsTable.buildId, buildId)
327 )
328 )
329 .limit(1);
330
331 if (existing.length) {
332 const result = await db
333 .update(reviewsTable)
334 .set({
335 content: content,
336 })
337 .where(
338 and(
339 eq(reviewsTable.userId, userId),
340 eq(reviewsTable.buildId, buildId)
341 )
342 );
343
344 return;
345 }
346
347 const result = await db
348 .insert(reviewsTable)
349 .values({
350 userId,
351 buildId,
352 content,
353 createdAt: new Date().toISOString().split('T')[0]
354 });
355}
356
357export async function cloneBuild(db: Database, userId: number, buildId: number) {
358 const [buildToClone] = await db
359 .select()
360 .from(buildsTable)
361 .where(
362 eq(buildsTable.id, buildId)
363 )
364 .limit(1);
365
366 if (!buildToClone) return null;
367
368 const [newBuild] = await db
369 .insert(buildsTable)
370 .values({
371 userId: userId,
372 name: `${buildToClone.name} (copy)`,
373 createdAt: new Date().toISOString().split('T')[0],
374 description: buildToClone.description,
375 totalPrice: buildToClone.totalPrice,
376 isApproved: false
377 })
378 .returning({ id: buildsTable.id });
379
380 const components = await db
381 .select()
382 .from(buildComponentsTable)
383 .where(
384 eq(buildComponentsTable.buildId, buildId)
385 );
386
387 if(components.length) {
388 await db
389 .insert(buildComponentsTable)
390 .values(
391 components.map(component => ({
392 buildId: newBuild.id,
393 componentId: component.componentId
394 }))
395 );
396 }
397
398 return newBuild.id;
399}
Note: See TracBrowser for help on using the repository browser.