This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

feat: add takes per user api route

+70 -5
+3 -3
src/features/api/index.ts
··· 1 - import recentTakes from "./routes/recentTakes"; 1 + import { recentTakes, takesPerUser } from "./routes/recentTakes"; 2 2 import video from "./routes/video"; 3 3 4 4 export { default as video } from "./routes/video"; ··· 6 6 export async function apiRouter(url: URL) { 7 7 const path = url.pathname.split("/")[2]; 8 8 9 - console.log(`API path: ${path}`); 10 - 11 9 switch (path) { 12 10 case "video": 13 11 return video(url); 14 12 case "recentTakes": 15 13 return recentTakes(); 14 + case "takesPerUser": 15 + return takesPerUser(url.pathname.split("/")[3] as string); 16 16 default: 17 17 return new Response("404 Not Found", { status: 404 }); 18 18 }
+67 -2
src/features/api/routes/recentTakes.ts
··· 1 - import { eq, desc } from "drizzle-orm"; 1 + import { eq, desc, and } from "drizzle-orm"; 2 2 import { db } from "../../../libs/db"; 3 3 import { takes as takesTable } from "../../../libs/schema"; 4 4 5 - export default async function recentTakes(): Promise<Response> { 5 + export async function recentTakes(): Promise<Response> { 6 6 const recentTakes = await db 7 7 .select() 8 8 .from(takesTable) ··· 44 44 }, 45 45 ); 46 46 } 47 + 48 + export async function takesPerUser(userId: string): Promise<Response> { 49 + const rawTakes = await db 50 + .select() 51 + .from(takesTable) 52 + .where(and(eq(takesTable.userId, userId))) 53 + .orderBy(desc(takesTable.completedAt)); 54 + 55 + const takes = rawTakes.map((take) => ({ 56 + id: take.id, 57 + description: take.description, 58 + completedAt: take.completedAt, 59 + status: take.status, 60 + mp4Url: take.takeUrl, 61 + elapsedTime: take.elapsedTimeMs, 62 + })); 63 + 64 + const approvedTakes = rawTakes.reduce((acc, take) => { 65 + if (take.status !== "approved") return acc; 66 + const multiplier = Number.parseFloat(take.multiplier || "1.0"); 67 + return Number( 68 + ( 69 + acc + 70 + (take.elapsedTimeMs * multiplier) / (1000 * 60 * 60) 71 + ).toFixed(1), 72 + ); 73 + }, 0); 74 + 75 + const waitingTakes = rawTakes.reduce((acc, take) => { 76 + if (take.status !== "waitingUpload" && take.status !== "uploaded") 77 + return acc; 78 + const multiplier = Number.parseFloat(take.multiplier || "1.0"); 79 + return Number( 80 + ( 81 + acc + 82 + (take.elapsedTimeMs * multiplier) / (1000 * 60 * 60) 83 + ).toFixed(1), 84 + ); 85 + }, 0); 86 + 87 + const rejectedTakes = rawTakes.reduce((acc, take) => { 88 + if (take.status !== "rejected") return acc; 89 + const multiplier = Number.parseFloat(take.multiplier || "1.0"); 90 + return Number( 91 + ( 92 + acc + 93 + (take.elapsedTimeMs * multiplier) / (1000 * 60 * 60) 94 + ).toFixed(1), 95 + ); 96 + }, 0); 97 + 98 + return new Response( 99 + JSON.stringify({ 100 + approvedTakes, 101 + waitingTakes, 102 + rejectedTakes, 103 + takes, 104 + }), 105 + { 106 + headers: { 107 + "Content-Type": "application/json", 108 + }, 109 + }, 110 + ); 111 + }