Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions apps/api/src/modules/call/call.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { and, desc, eq, isNotNull } from "drizzle-orm";
import { formatDistanceStrict } from "date-fns";
import {
createTypiRouter,
createTypiRoute,
createTypiRouteHandler,
} from "@repo/typiserver";
import { db } from "@repo/database";
import { callParticipants, calls, chats, users } from "@repo/database/schema";
import authMiddleware from "@repo/api/middlewares/auth";

const callRouter = createTypiRouter({
"/": createTypiRoute({
get: createTypiRouteHandler({
middlewares: [authMiddleware],
handler: async (ctx) => {
const userId = ctx.data.userId;

const userCalls = await db
.select({
call: calls,
chat: chats,
self: callParticipants,
})
.from(calls)
.innerJoin(callParticipants, eq(callParticipants.callId, calls.id))
.innerJoin(chats, eq(calls.chatId, chats.id))
.where(
and(
eq(callParticipants.userId, userId),
isNotNull(callParticipants.joinedAt),
isNotNull(callParticipants.leftAt)
)
)
.orderBy(desc(callParticipants.joinedAt));

const result = await Promise.all(
userCalls.map(async (call) => {
const participants = await db
.select({
user: users,
callParticipant: callParticipants,
})
.from(callParticipants)
.innerJoin(users, eq(callParticipants.userId, users.id))
.where(eq(callParticipants.callId, call.call.id));

const duration = formatDistanceStrict(
call.self.leftAt || new Date(),
call.self.joinedAt || new Date()
);

const isCaller = call.call.createdBy === userId;
const status = isCaller
? participants.some(
(p) =>
p.user.id !== userId &&
p.callParticipant.status === "answered"
)
? "answered"
: "missed"
: participants.find((p) => p.user.id === userId)?.callParticipant
.status || "missed";

const participantsWithoutSelf = participants.filter(
(participant) => participant.user.id !== userId
);

return {
call: {
...call.call,
status,
duration: duration,
},
chat: call.chat,
participants: participantsWithoutSelf,
self: call.self,
};
})
);

return ctx.success({
calls: result,
});
},
}),
}),
});

export default callRouter;
2 changes: 2 additions & 0 deletions apps/api/src/modules/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { createTypiRouter } from "@repo/typiserver";
import blockRouter from "./block/block.route";
import authRouter from "./auth/auth.route";
import callRouter from "./call/call.route";
import chatRouter from "./chat/chat.route";
import friendsRouter from "./friends/friends.route";
import userRouter from "./user/user.route";

const rootRouter = createTypiRouter({
"/auth": authRouter,
"/block": blockRouter,
"/call": callRouter,
"/chat": chatRouter,
"/friends": friendsRouter,
"/user": userRouter,
Expand Down
Loading