2025-04-04 12:33:03 +02:00

122 lines
3.5 KiB
TypeScript

import { z } from "zod";
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
import { friendships, users } from "@/server/db/schema";
import { and, eq, ilike, inArray, not, or } from "drizzle-orm";
import { revalidatePath } from "next/cache";
export const friendRouter = createTRPCRouter({
// queries
getAll: protectedProcedure.query(async ({ ctx }) => {
const friends = await ctx.db.query.friendships.findMany({
where: or(
eq(friendships.userOneId, ctx.session.user.id),
eq(friendships.userTwoId, ctx.session.user.id)
),
with: {
userOne: true,
userTwo: true,
},
});
const returnOne = friends.map((f) => ({
id: f.id,
status: f.status,
requestedBy: ctx.session.user.id === f.userOneId ? "me" : "them",
user: ctx.session.user.id === f.userOneId ? f.userTwo : f.userOne,
}));
console.log(returnOne[0]);
return returnOne;
}),
getPendingFriendRequests: protectedProcedure.query(
async ({ ctx }) =>
await ctx.db.query.friendships.findMany({
where: and(
or(
eq(friendships.userOneId, ctx.session.user.id),
eq(friendships.userTwoId, ctx.session.user.id)
),
eq(friendships.status, "pending")
),
})
),
search: protectedProcedure
.input(z.object({ search: z.string() }))
.query(async ({ ctx, input }) => {
const userId = ctx.session.user.id;
const friendIds = await ctx.db.query.friendships.findMany({
where: and(
or(
eq(friendships.userOneId, userId),
eq(friendships.userTwoId, userId)
)
),
columns: {
userOneId: true,
userTwoId: true,
status: true,
},
});
const excludedIds = [
userId,
...friendIds
.filter((f) => f.status !== "pending")
.flatMap((f) => [f.userOneId === userId ? f.userTwoId : f.userOneId]),
];
const pendingIds = friendIds
.filter((f) => f.status === "pending")
.flatMap((f) => [f.userOneId === userId ? f.userTwoId : f.userOneId]);
const searchResult = await ctx.db.query.users.findMany({
where: and(
ilike(users.name, `%${input.search}%`),
not(inArray(users.id, excludedIds))
),
columns: {
image: true,
name: true,
id: true,
},
});
return searchResult.map((user) => {
const pending = pendingIds.includes(user.id);
return {
user,
pending,
};
});
}),
// mutations
add: protectedProcedure
.input(z.object({ userId: z.string() }))
.mutation(async ({ ctx, input }) => {
await ctx.db.insert(friendships).values({
userOneId: ctx.session.user.id,
userTwoId: input.userId,
status: "pending",
});
revalidatePath("/friend");
}),
accept: protectedProcedure
.input(z.object({ friendshipId: z.string() }))
.mutation(async ({ ctx, input }) => {
await ctx.db
.update(friendships)
.set({
status: "accepted",
})
.where(eq(friendships.id, input.friendshipId));
revalidatePath("/friend");
}),
cancel: protectedProcedure
.input(z.object({ friendshipId: z.string() }))
.mutation(async ({ ctx, input }) => {
await ctx.db
.delete(friendships)
.where(eq(friendships.id, input.friendshipId));
}),
});