feat: Add default organization selection (#1991)

This commit is contained in:
HarikrishnanD
2025-10-31 20:21:49 +05:30
parent dadef000d5
commit a14cc09933
7 changed files with 216 additions and 7 deletions
+127 -2
View File
@@ -41,16 +41,90 @@ export const organizationRouter = createTRPCRouter({
});
}
// Check if this is the user's first organization
const existingMemberships = await db.query.member.findMany({
where: eq(member.userId, ctx.user.id),
});
const isFirstOrganization = existingMemberships.length === 0;
await db.insert(member).values({
organizationId: result.id,
role: "owner",
createdAt: new Date(),
userId: ctx.user.id,
isDefault: isFirstOrganization, // Mark as default if it's the first organization
});
return result;
}),
all: protectedProcedure.query(async ({ ctx }) => {
const memberResult = await db.query.organization.findMany({
// Get all memberships for the user with organization info
// Query memberships first to get the isDefault value correctly
const memberships = await db
.select({
organizationId: member.organizationId,
isDefault: member.isDefault,
createdAt: member.createdAt,
})
.from(member)
.where(eq(member.userId, ctx.user.id));
// If no default is set, set the oldest organization as default
const hasDefault = memberships.some((m) => m.isDefault === true);
if (!hasDefault && memberships.length > 0) {
// Find the oldest membership (first created)
const oldestMembership = memberships.reduce((oldest, current) =>
current.createdAt < oldest.createdAt ? current : oldest,
);
// Set it as default
await db
.update(member)
.set({ isDefault: true })
.where(
and(
eq(member.organizationId, oldestMembership.organizationId),
eq(member.userId, ctx.user.id),
),
);
// Update the memberships array
const updatedMemberships = memberships.map((m) =>
m.organizationId === oldestMembership.organizationId
? { ...m, isDefault: true }
: m,
);
// Get all organizations for the user
const organizations = await db.query.organization.findMany({
where: (organization) =>
exists(
db
.select()
.from(member)
.where(
and(
eq(member.organizationId, organization.id),
eq(member.userId, ctx.user.id),
),
),
),
});
// Create a map of organizationId to isDefault
const defaultMap = new Map(
updatedMemberships.map((m) => [m.organizationId, Boolean(m.isDefault)]),
);
// Map organizations with their isDefault flag
return organizations.map((org) => ({
...org,
isDefault: defaultMap.get(org.id) ?? false,
}));
}
// Get all organizations for the user
const organizations = await db.query.organization.findMany({
where: (organization) =>
exists(
db
@@ -64,7 +138,17 @@ export const organizationRouter = createTRPCRouter({
),
),
});
return memberResult;
// Create a map of organizationId to isDefault
const defaultMap = new Map(
memberships.map((m) => [m.organizationId, Boolean(m.isDefault)]),
);
// Map organizations with their isDefault flag
return organizations.map((org) => ({
...org,
isDefault: defaultMap.get(org.id) ?? false,
}));
}),
one: protectedProcedure
.input(
@@ -184,4 +268,45 @@ export const organizationRouter = createTRPCRouter({
.delete(invitation)
.where(eq(invitation.id, input.invitationId));
}),
setDefault: protectedProcedure
.input(
z.object({
organizationId: z.string(),
}),
)
.mutation(async ({ ctx, input }) => {
// Verify user is a member of this organization
const userMember = await db.query.member.findFirst({
where: and(
eq(member.organizationId, input.organizationId),
eq(member.userId, ctx.user.id),
),
});
if (!userMember) {
throw new TRPCError({
code: "FORBIDDEN",
message: "You are not a member of this organization",
});
}
// First, unset all defaults for this user
await db
.update(member)
.set({ isDefault: false })
.where(eq(member.userId, ctx.user.id));
// Then set this organization as default
await db
.update(member)
.set({ isDefault: true })
.where(
and(
eq(member.organizationId, input.organizationId),
eq(member.userId, ctx.user.id),
),
);
return { success: true };
}),
});