import { useSuspenseQuery } from '@tanstack/react-query'; import { createFileRoute, Link } from '@tanstack/react-router'; import { UsersIcon } from 'lucide-react'; import FullPageLoadingState from '@/components/full-page-loading-state'; import { GroupMemberGrowth } from '@/components/groups/group-member-growth'; import { OverviewMetricCard } from '@/components/overview/overview-metric-card'; import { WidgetHead, WidgetTitle } from '@/components/overview/overview-widget'; import { MostEvents } from '@/components/profiles/most-events'; import { PopularRoutes } from '@/components/profiles/popular-routes'; import { ProfileActivity } from '@/components/profiles/profile-activity'; import { KeyValueGrid } from '@/components/ui/key-value-grid'; import { Widget, WidgetBody, WidgetEmptyState } from '@/components/widget'; import { WidgetTable } from '@/components/widget-table'; import { useTRPC } from '@/integrations/trpc/react'; import { formatDateTime, formatTimeAgoOrDateTime } from '@/utils/date'; import { createProjectTitle } from '@/utils/title'; const MEMBERS_PREVIEW_LIMIT = 13; export const Route = createFileRoute( '/_app/$organizationId/$projectId/groups_/$groupId/_tabs/' )({ component: Component, loader: async ({ context, params }) => { await Promise.all([ context.queryClient.prefetchQuery( context.trpc.group.activity.queryOptions({ id: params.groupId, projectId: params.projectId, }) ), ]); }, pendingComponent: FullPageLoadingState, head: () => ({ meta: [{ title: createProjectTitle('Group') }], }), }); function Component() { const { projectId, organizationId, groupId } = Route.useParams(); const trpc = useTRPC(); const group = useSuspenseQuery( trpc.group.byId.queryOptions({ id: groupId, projectId }) ); const metrics = useSuspenseQuery( trpc.group.metrics.queryOptions({ id: groupId, projectId }) ); const activity = useSuspenseQuery( trpc.group.activity.queryOptions({ id: groupId, projectId }) ); const members = useSuspenseQuery( trpc.group.members.queryOptions({ id: groupId, projectId }) ); const mostEvents = useSuspenseQuery( trpc.group.mostEvents.queryOptions({ id: groupId, projectId }) ); const popularRoutes = useSuspenseQuery( trpc.group.popularRoutes.queryOptions({ id: groupId, projectId }) ); const memberGrowth = useSuspenseQuery( trpc.group.memberGrowth.queryOptions({ id: groupId, projectId }) ); const g = group.data; const m = metrics.data; if (!g) { return null; } const properties = g.properties as Record; return (
{/* Metrics */} {m && (
)} {/* Properties */}
Group Information
v !== undefined && v !== '') .map(([k, v]) => ({ name: k, value: String(v), })), ]} />
{/* Activity heatmap */}
{/* Member growth */}
{/* Top events */}
{/* Popular routes */}
{/* Members preview */}
Members {members.data.length === 0 ? ( ) : ( ( {member.profileId} ), }, { key: 'events', name: 'Events', width: '60px', className: 'text-muted-foreground', render: (member) => member.eventCount, }, { key: 'lastSeen', name: 'Last Seen', width: '150px', className: 'text-muted-foreground', render: (member) => formatTimeAgoOrDateTime(new Date(member.lastSeen)), }, ]} data={members.data.slice(0, MEMBERS_PREVIEW_LIMIT)} keyExtractor={(member) => member.profileId} /> )} {members.data.length > MEMBERS_PREVIEW_LIMIT && (

{`${members.data.length} members found. View all in Members tab`}

)}
); }