Skip to content

Commit 624a14c

Browse files
committed
Stats loading changes
1 parent de1d011 commit 624a14c

File tree

2 files changed

+107
-9
lines changed

2 files changed

+107
-9
lines changed

src/components/activity/StatsView.tsx

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState } from 'react';
1+
import { useEffect, useState } from 'react';
22
import { Flex, Grid, GridItem, Input, Spinner, Text } from '@chakra-ui/react';
33
import { Select } from 'chakra-react-select';
44
import StatsGraph from './StatsGraph';
@@ -93,19 +93,38 @@ const StatsView = () => {
9393
const [globalStartDate, setGlobalStartDate] = useState<Date>();
9494
const [personalStartDate, setPersonalStartDate] = useState<Date>();
9595

96-
const { isLoading: isStatsLoading } = trpc.stats.getTicketStats.useQuery(undefined, {
96+
const { isFetching: isFetchingStats, fetchNextPage: fetchNextStatsPage, hasNextPage: statsHasNextPage } =
97+
trpc.stats.getInfiniteTicketStats.useInfiniteQuery({ limit: 10000 }, {
9798
refetchOnWindowFocus: false,
9899
onSuccess: data => {
99-
setTicketStats(data);
100+
setTicketStats(data.pages.map(p => p.items).reduce((a, b) => a.concat(b)));
100101
},
102+
getNextPageParam: (lastPage) => lastPage.nextCursor
101103
});
102-
const { isLoading: isPersonalStatsLoading } = trpc.stats.getTicketStatsHelpedByUser.useQuery(undefined, {
104+
105+
useEffect(() => {
106+
if (statsHasNextPage) {
107+
fetchNextStatsPage();
108+
}
109+
}, [ticketStats])
110+
111+
const { isFetching: isFetchingPersonalStats, fetchNextPage: fetchNextPersonalStatsPage, hasNextPage: personalStatsHasNextPage } =
112+
trpc.stats.getInfiniteTicketStats.useInfiniteQuery({ limit: 10000 }, {
103113
refetchOnWindowFocus: false,
104114
onSuccess: data => {
105-
setPersonalTicketStats(data);
115+
setPersonalTicketStats(data.pages.map(p => p.items).reduce((a, b) => a.concat(b)));
106116
},
117+
getNextPageParam: (lastPage) => lastPage.nextCursor
107118
});
108119

120+
useEffect(() => {
121+
if (personalStatsHasNextPage) {
122+
fetchNextPersonalStatsPage();
123+
}
124+
}, [personalTicketStats])
125+
126+
const isStatsLoading = isFetchingStats || statsHasNextPage || isFetchingPersonalStats || personalStatsHasNextPage;
127+
109128
const getStartDateFromCurrent = (timeRangeOption: TimeRangeType) => {
110129
let start = new Date();
111130
switch (timeRangeOption.type) {
@@ -142,7 +161,6 @@ const StatsView = () => {
142161
switch (timeRangeOption.type) {
143162
case 'day':
144163
end.setDate(start.getDate() + 1);
145-
console.log(startDate, start, end);
146164
return { type: timeRangeOption, startTime: start, endTime: end };
147165
case 'week':
148166
end.setDate(start.getDate() + 7);
@@ -194,7 +212,7 @@ const StatsView = () => {
194212
<StatsGraph timeRange={getTimeRange(globalTimeRangeOption?.value, globalStartDate)} stats={ticketStats} />
195213
</GridItem>
196214
<GridItem mt={4} rowSpan={1} colSpan={2}>
197-
{isStatsLoading || isPersonalStatsLoading ? (
215+
{isStatsLoading ? (
198216
<Spinner />
199217
) : (
200218
<StatsPanel timeRange={getTimeRange(globalTimeRangeOption?.value, globalStartDate)} stats={ticketStats} />
@@ -234,7 +252,7 @@ const StatsView = () => {
234252
<StatsGraph timeRange={getTimeRange(personalTimeRangeOption?.value, personalStartDate)} stats={personalTicketStats} />
235253
</GridItem>
236254
<GridItem mt={4} rowSpan={1} colSpan={2}>
237-
{isStatsLoading || isPersonalStatsLoading ? (
255+
{isStatsLoading ? (
238256
<Spinner />
239257
) : (
240258
<StatsPanel

src/server/trpc/router/stats.ts

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,44 @@ export const statsRouter = router({
1818
},
1919
});
2020
}),
21+
getInfiniteTicketStats: publicProcedure
22+
.input(z.object({
23+
limit: z.number().min(1).max(10000).nullish(),
24+
cursor: z.number().nullish(),
25+
}))
26+
.query(async ({ input, ctx }) => {
27+
const limit = input.limit ?? 1000;
28+
const { cursor } = input;
29+
const items = await ctx.prisma.ticket.findMany({
30+
take: limit + 1,
31+
select: {
32+
id: true,
33+
createdAt: true,
34+
helpedAt: true,
35+
resolvedAt: true,
36+
status: true,
37+
ticketType: true,
38+
description: true,
39+
isPublic: true,
40+
locationId: true,
41+
assignmentId: true,
42+
},
43+
cursor: cursor ? { id: cursor } : undefined,
44+
orderBy: {
45+
id: 'asc',
46+
},
47+
})
48+
let nextCursor: typeof cursor | undefined = undefined;
49+
if (items.length > limit) {
50+
const nextItem = items.pop()
51+
nextCursor = nextItem?.id;
52+
}
53+
return {
54+
items,
55+
nextCursor,
56+
};
57+
}
58+
),
2159
getTicketStatsHelpedByUser: protectedNotStudentProcedure
2260
.query(async ({ ctx }) => {
2361
return ctx.prisma.ticket.findMany({
@@ -36,7 +74,49 @@ export const statsRouter = router({
3674
helpedByUserId: ctx.session?.user?.id
3775
},
3876
});
39-
}),
77+
}
78+
),
79+
getInfiniteTicketStatsHelpedByUser: publicProcedure
80+
.input(z.object({
81+
limit: z.number().min(1).max(10000).nullish(),
82+
cursor: z.number().nullish(),
83+
}))
84+
.query(async ({ input, ctx }) => {
85+
const limit = input.limit ?? 1000;
86+
const { cursor } = input;
87+
const items = await ctx.prisma.ticket.findMany({
88+
take: limit + 1,
89+
select: {
90+
id: true,
91+
createdAt: true,
92+
helpedAt: true,
93+
resolvedAt: true,
94+
status: true,
95+
ticketType: true,
96+
description: true,
97+
isPublic: true,
98+
locationId: true,
99+
assignmentId: true,
100+
},
101+
where: {
102+
helpedByUserId: ctx.session?.user?.id
103+
},
104+
cursor: cursor ? { id: cursor } : undefined,
105+
orderBy: {
106+
id: 'asc',
107+
},
108+
})
109+
let nextCursor: typeof cursor | undefined = undefined;
110+
if (items.length > limit) {
111+
const nextItem = items.pop()
112+
nextCursor = nextItem?.id;
113+
}
114+
return {
115+
items,
116+
nextCursor,
117+
};
118+
}
119+
),
40120
});
41121

42122
export interface TicketStats {

0 commit comments

Comments
 (0)