109 lines
2.8 KiB
TypeScript
109 lines
2.8 KiB
TypeScript
import dayjs from "dayjs";
|
|
|
|
import {
|
|
and,
|
|
asc,
|
|
between,
|
|
count,
|
|
eq,
|
|
getOrderByFromSort,
|
|
ilike,
|
|
sql,
|
|
} from "@turbostarter/db";
|
|
import { organization, member } from "@turbostarter/db/schema";
|
|
import { db } from "@turbostarter/db/server";
|
|
|
|
import type { GetOrganizationsInput } from "../../../schema";
|
|
|
|
export const getOrganizationsCount = async () =>
|
|
db
|
|
.select({ count: count() })
|
|
.from(organization)
|
|
.then((res) => res[0]?.count ?? 0);
|
|
|
|
export const getOrganizations = async (input: GetOrganizationsInput) => {
|
|
const offset = (input.page - 1) * input.perPage;
|
|
|
|
const where = and(
|
|
input.q ? ilike(organization.name, `%${input.q}%`) : undefined,
|
|
input.createdAt
|
|
? between(
|
|
organization.createdAt,
|
|
dayjs(input.createdAt[0]).startOf("day").toDate(),
|
|
dayjs(input.createdAt[1]).endOf("day").toDate(),
|
|
)
|
|
: undefined,
|
|
);
|
|
|
|
const having = input.members
|
|
? between(
|
|
sql<number>`CAST(COUNT(${member.id}) AS INTEGER)`,
|
|
input.members[0],
|
|
input.members[1],
|
|
)
|
|
: undefined;
|
|
|
|
const orderBy =
|
|
input.sort && input.sort.length > 0
|
|
? input.sort.flatMap((s) => {
|
|
const field = s.id.split(/[_.]/).pop() ?? s.id;
|
|
if (field === "members") {
|
|
return [s.desc ? sql`members DESC` : sql`members ASC`];
|
|
}
|
|
return getOrderByFromSort({ sort: [s], defaultSchema: organization });
|
|
})
|
|
: [asc(organization.name)];
|
|
|
|
return db.transaction(async (tx) => {
|
|
const results = await tx
|
|
.select({
|
|
id: organization.id,
|
|
name: organization.name,
|
|
slug: organization.slug,
|
|
logo: organization.logo,
|
|
createdAt: organization.createdAt,
|
|
members: sql<number>`CAST(COUNT(${member.id}) AS INTEGER)`.as(
|
|
"members",
|
|
),
|
|
total: sql<number>`COUNT(*) OVER()`.mapWith(Number).as("total"),
|
|
})
|
|
.from(organization)
|
|
.leftJoin(member, eq(member.organizationId, organization.id))
|
|
.where(where)
|
|
.groupBy(organization.id)
|
|
.having(having)
|
|
.limit(input.perPage)
|
|
.offset(offset)
|
|
.orderBy(...orderBy);
|
|
|
|
const membersMax = await tx
|
|
.select({
|
|
members: sql<number>`CAST(COUNT(${member.id}) AS INTEGER)`.as(
|
|
"members",
|
|
),
|
|
})
|
|
.from(member)
|
|
.groupBy(member.organizationId)
|
|
.orderBy(sql`members DESC`)
|
|
.limit(1)
|
|
.then((res) => res[0]?.members ?? 0);
|
|
|
|
const data = results.map(({ total: _, ...rest }) => rest);
|
|
const total = results[0]?.total ?? 0;
|
|
|
|
return {
|
|
data,
|
|
total,
|
|
max: { members: membersMax },
|
|
};
|
|
});
|
|
};
|
|
|
|
export const getOrganization = async ({ id }: { id: string }) => {
|
|
return (
|
|
(await db.query.organization.findFirst({
|
|
where: eq(organization.id, id),
|
|
})) ?? null
|
|
);
|
|
};
|