fix: documents and users count in the table

This commit is contained in:
Ephraim Atta-Duncan
2025-08-13 11:00:44 +00:00
parent 38f3a52233
commit fdef6b0489
3 changed files with 37 additions and 24 deletions

View File

@ -59,12 +59,12 @@ export const OrganisationInsightsTable = ({
{ {
header: _(msg`Members`), header: _(msg`Members`),
accessorKey: 'memberCount', accessorKey: 'memberCount',
cell: ({ row }) => row.getValue('memberCount'), cell: ({ row }) => Number(row.getValue('memberCount')),
}, },
{ {
header: _(msg`Documents`), header: _(msg`Documents`),
accessorKey: 'documentCount', accessorKey: 'documentCount',
cell: ({ row }) => row.getValue('documentCount'), cell: ({ row }) => Number(row.getValue('documentCount')),
}, },
{ {
header: _(msg`Created`), header: _(msg`Created`),
@ -87,12 +87,12 @@ export const OrganisationInsightsTable = ({
{ {
header: _(msg`Documents Created`), header: _(msg`Documents Created`),
accessorKey: 'documentCount', accessorKey: 'documentCount',
cell: ({ row }) => row.getValue('documentCount'), cell: ({ row }) => Number(row.getValue('documentCount')),
}, },
{ {
header: _(msg`Documents Signed`), header: _(msg`Documents Signed`),
accessorKey: 'signedDocumentCount', accessorKey: 'signedDocumentCount',
cell: ({ row }) => row.getValue('signedDocumentCount'), cell: ({ row }) => Number(row.getValue('signedDocumentCount')),
}, },
{ {
header: _(msg`Joined`), header: _(msg`Joined`),
@ -170,16 +170,14 @@ export const OrganisationInsightsTable = ({
value: number; value: number;
subtitle?: string; subtitle?: string;
}) => ( }) => (
<div className="bg-card rounded-lg border p-4"> <div className="bg-card flex items-start gap-x-2 rounded-lg border px-4 py-3">
<div className="flex items-center space-x-2"> <Icon className="text-muted-foreground h-4 w-4 items-start" />
<Icon className="text-muted-foreground h-5 w-5" /> <div className="-mt-0.5 space-y-1">
<div className="flex-1">
<p className="text-muted-foreground text-sm font-medium">{title}</p> <p className="text-muted-foreground text-sm font-medium">{title}</p>
<p className="text-2xl font-bold">{value}</p> <p className="text-2xl font-bold">{value}</p>
{subtitle && <p className="text-muted-foreground text-xs">{subtitle}</p>} {subtitle && <p className="text-muted-foreground text-xs">{subtitle}</p>}
</div> </div>
</div> </div>
</div>
); );
return ( return (

View File

@ -1,6 +1,7 @@
import { Trans } from '@lingui/react/macro'; import { Trans } from '@lingui/react/macro';
import { getOrganisationDetailedInsights } from '@documenso/lib/server-only/admin/get-organisation-detailed-insights'; import { getOrganisationDetailedInsights } from '@documenso/lib/server-only/admin/get-organisation-detailed-insights';
import { getAdminOrganisation } from '@documenso/trpc/server/admin-router/get-admin-organisation';
import { OrganisationInsightsTable } from '~/components/tables/organisation-insights-table'; import { OrganisationInsightsTable } from '~/components/tables/organisation-insights-table';
@ -19,16 +20,20 @@ export async function loader({ params, request }: Route.LoaderArgs) {
| 'allTime'; | 'allTime';
const view = (url.searchParams.get('view') || 'teams') as 'teams' | 'users' | 'documents'; const view = (url.searchParams.get('view') || 'teams') as 'teams' | 'users' | 'documents';
const insights = await getOrganisationDetailedInsights({ const [insights, organisation] = await Promise.all([
getOrganisationDetailedInsights({
organisationId: id, organisationId: id,
page, page,
perPage, perPage,
dateRange, dateRange,
view, view,
}); }),
getAdminOrganisation({ organisationId: id }),
]);
return { return {
organisationId: id, organisationId: id,
organisationName: organisation.name,
insights, insights,
page, page,
perPage, perPage,
@ -38,13 +43,13 @@ export async function loader({ params, request }: Route.LoaderArgs) {
} }
export default function OrganisationInsights({ loaderData }: Route.ComponentProps) { export default function OrganisationInsights({ loaderData }: Route.ComponentProps) {
const { organisationId, insights, page, perPage, dateRange, view } = loaderData; const { insights, page, perPage, dateRange, view, organisationName } = loaderData;
return ( return (
<div> <div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h2 className="text-4xl font-semibold"> <h2 className="text-4xl font-semibold">
<Trans>Organisation Insights</Trans> <Trans>{organisationName}</Trans>
</h2> </h2>
</div> </div>
<div className="mt-8"> <div className="mt-8">

View File

@ -122,12 +122,16 @@ async function getTeamInsights(
.leftJoin('Document as d', (join) => .leftJoin('Document as d', (join) =>
join.onRef('t.id', '=', 'd.teamId').on('d.deletedAt', 'is', null), join.onRef('t.id', '=', 'd.teamId').on('d.deletedAt', 'is', null),
) )
.leftJoin('TeamGroup as tg', 'tg.teamId', 't.id')
.leftJoin('OrganisationGroup as og', 'og.id', 'tg.organisationGroupId')
.leftJoin('OrganisationGroupMember as ogm', 'ogm.groupId', 'og.id')
.leftJoin('OrganisationMember as om', 'om.id', 'ogm.organisationMemberId')
.where('t.organisationId', '=', organisationId) .where('t.organisationId', '=', organisationId)
.select([ .select([
't.id as id', 't.id as id',
't.name as name', 't.name as name',
't.createdAt as createdAt', 't.createdAt as createdAt',
sql<number>`0`.as('memberCount'), sql<number>`COUNT(DISTINCT om."userId")`.as('memberCount'),
sql<number>`COUNT(DISTINCT CASE WHEN d.id IS NOT NULL ${dateFilter} THEN d.id END)`.as( sql<number>`COUNT(DISTINCT CASE WHEN d.id IS NOT NULL ${dateFilter} THEN d.id END)`.as(
'documentCount', 'documentCount',
), ),
@ -163,14 +167,20 @@ async function getUserInsights(
const usersQuery = kyselyPrisma.$kysely const usersQuery = kyselyPrisma.$kysely
.selectFrom('OrganisationMember as om') .selectFrom('OrganisationMember as om')
.innerJoin('User as u', 'u.id', 'om.userId') .innerJoin('User as u', 'u.id', 'om.userId')
.leftJoin('Document as d', (join) =>
join.onRef('d.userId', '=', 'u.id').on('d.deletedAt', 'is', null),
)
.leftJoin('Recipient as r', (join) =>
join.onRef('r.email', '=', 'u.email').on('r.signedAt', 'is not', null),
)
.where('om.organisationId', '=', organisationId) .where('om.organisationId', '=', organisationId)
.select([ .select([
'u.id as id', 'u.id as id',
'u.name as name', 'u.name as name',
'u.email as email', 'u.email as email',
'u.createdAt as createdAt', 'u.createdAt as createdAt',
sql<number>`0`.as('documentCount'), sql<number>`COUNT(DISTINCT d.id)`.as('documentCount'),
sql<number>`0`.as('signedDocumentCount'), sql<number>`COUNT(DISTINCT r.id)`.as('signedDocumentCount'),
]) ])
.groupBy(['u.id', 'u.name', 'u.email', 'u.createdAt']) .groupBy(['u.id', 'u.name', 'u.email', 'u.createdAt'])
.orderBy('u.createdAt', 'desc') .orderBy('u.createdAt', 'desc')