= {
);
},
+ loading(props) {
+ return (
+
+ );
+ },
};
diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx
index 93a82d9..829269f 100644
--- a/src/components/ui/card.tsx
+++ b/src/components/ui/card.tsx
@@ -7,7 +7,7 @@ function Card({ className, ...props }: React.ComponentProps<"div">) {
{
+ const group = await ctx.db.query.groups.findFirst({
+ where: eq(groups.id, input.id),
+ with: {
+ members: {
+ with: {
+ user: true,
+ },
+ },
+ },
+ });
+ if (group?.members?.find((member) => member.userId === ctx.auth.userId))
+ return group;
+ return undefined;
+ }),
+ getAll: protectedProcedure.query(async ({ ctx }) => {
+ const membersShips = await ctx.db.query.groupMembers.findMany({
+ where: eq(groupMembers.userId, ctx.auth.userId),
+ with: {
+ group: true,
+ },
+ });
+ return membersShips?.map(({ group }) => group!) ?? [];
+ }),
+
+ // mutations
+ create: protectedProcedure
+ .input(z.object({ group: groupSchema }))
+ .mutation(async ({ ctx, input }) => {
+ const [group] = await ctx.db
+ .insert(groups)
+ .values({
+ ...input.group,
+ createdById: ctx.auth.userId,
+ })
+ .returning({ id: groups.id });
+ if (!group?.id?.length) throw new Error("Group cant get created");
+ await ctx.db.insert(groupMembers).values({
+ groupId: group.id,
+ userId: ctx.auth.userId,
+ });
+ return group;
+ }),
+
+ update: protectedProcedure
+ .input(z.object({ group: groupSchema, groupId: z.string() }))
+ .mutation(async ({ ctx, input }) => {
+ console.log("Check if groupmember is admin!!");
+ return await ctx.db
+ .update(groups)
+ .set(input.group)
+ .where(eq(groups.id, input.groupId))
+ .returning({ id: groups.id });
+ }),
+
+ addMember: protectedProcedure
+ .input(z.object({ groupId: z.string(), userId: z.string() }))
+ .mutation(async ({ ctx, input }) => {
+ await ctx.db.insert(groupMembers).values({
+ groupId: input.groupId,
+ userId: input.userId,
+ });
+ revalidatePath(`/group/${input.groupId}`);
+ }),
+
+ removeMember: protectedProcedure
+ .input(z.object({ groupId: z.string(), userId: z.string() }))
+ .mutation(async ({ ctx, input }) => {
+ await ctx.db
+ .delete(groupMembers)
+ .where(
+ and(
+ eq(groupMembers.groupId, input.groupId),
+ eq(groupMembers.userId, input.userId)
+ )
+ );
+ revalidatePath(`/group/${input.groupId}`);
+ }),
+});
diff --git a/src/server/api/routers/index.ts b/src/server/api/routers/index.ts
index 8d75cc1..cf99525 100644
--- a/src/server/api/routers/index.ts
+++ b/src/server/api/routers/index.ts
@@ -1,3 +1,4 @@
export { friendRouter } from "./friend";
export { expenseRouter } from "./expense";
export { userRouter } from "./user";
+export { groupRouter } from "./group";
diff --git a/src/server/api/routers/user.ts b/src/server/api/routers/user.ts
index 32be565..6f6f109 100644
--- a/src/server/api/routers/user.ts
+++ b/src/server/api/routers/user.ts
@@ -1,6 +1,7 @@
-import { eq } from "drizzle-orm";
+import { and, eq, ilike, inArray, not } from "drizzle-orm";
import { createTRPCRouter, protectedProcedure } from "../trpc";
import { users } from "@/server/db/schema";
+import { z } from "zod";
export const userRouter = createTRPCRouter({
getSessionUser: protectedProcedure.query(async ({ ctx }) => {
@@ -9,4 +10,27 @@ export const userRouter = createTRPCRouter({
});
return user;
}),
+
+ search: protectedProcedure
+ .input(
+ z.object({
+ search: z.string(),
+ excludedIds: z.array(z.string()).optional(),
+ })
+ )
+ .query(async ({ ctx, input }) => {
+ const userId = ctx.auth.userId;
+ const searchResult = await ctx.db.query.users.findMany({
+ where: and(
+ not(eq(users.id, userId)),
+ ilike(users.name, `%${input.search}%`),
+ input.excludedIds?.length
+ ? not(inArray(users.id, input.excludedIds))
+ : undefined
+ ),
+ });
+ console.log("search results", searchResult);
+
+ return searchResult;
+ }),
});
diff --git a/src/server/db/schema.ts b/src/server/db/schema.ts
index fd4c41a..a1102bc 100644
--- a/src/server/db/schema.ts
+++ b/src/server/db/schema.ts
@@ -151,6 +151,7 @@ export const groups = createTable(
(d) => ({
id: d.varchar().primaryKey().$defaultFn(createId),
name: d.varchar({ length: 255 }).notNull(),
+ description: d.text(),
createdById: d
.varchar()
.notNull()
@@ -189,6 +190,11 @@ export const groupMembers = createTable(
.varchar()
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
+ role: d
+ .varchar({ length: 10 })
+ .notNull()
+ .$type()
+ .default("admin"),
joinedAt: d
.timestamp({ withTimezone: true })
.default(sql`CURRENT_TIMESTAMP`)