Skip to content

Commit

Permalink
feat(website, api): fetch paginated events on /admin/event-log
Browse files Browse the repository at this point in the history
  • Loading branch information
Khenziii committed Sep 20, 2024
1 parent cc29f32 commit 2432637
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 33 deletions.
98 changes: 72 additions & 26 deletions src/app/admin/event-log/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
"use client";

import {
useState,
useEffect,
useCallback,
useRef,
} from "react";
import { type AdminEvent } from "@khenzii-dev/server/backend";
import {
Flex,
Header,
Expand All @@ -12,10 +19,48 @@ import {
import { api } from "@khenzii-dev/providers";

const AdminEventLog = () => {
const {
data: eventsData,
isLoading: eventsAreLoading,
} = api.eventLog.getEvents.useQuery();
const loadingRef = useRef(null);
const [firstFetchFinished, setFirstFetchFinished] = useState(false);
const [eventsOffset, setEventsOffset] = useState(0);
const [events, setEvents] = useState<AdminEvent[]>([]);
const [fetchedAllEvents, setFetchedAllEvents] = useState(false);
const { data: eventsData } = api.eventLog.getEvents.useQuery({ offset: eventsOffset });

const fetchMoreEvents = useCallback(() => {
if (fetchedAllEvents) return;
if (!firstFetchFinished) return;

setEventsOffset((currentOffset) => currentOffset + 1);
}, [fetchedAllEvents, firstFetchFinished]);

useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (!entry) return;
if (!entry.isIntersecting) return;

fetchMoreEvents();
},
{ threshold: 0.1 },
);

const ref = loadingRef.current;
if (!ref) return;

observer.observe(ref);
return () => {
observer.unobserve(ref);
};
}, [fetchMoreEvents]);

useEffect(() => {
if (!eventsData) return;
if (eventsData.length < 20) setFetchedAllEvents(true);

setFirstFetchFinished(true);

setEvents((currentEvents) => [...currentEvents, ...eventsData]);
}, [eventsData]);

return (
<Flex
Expand All @@ -26,29 +71,30 @@ const AdminEventLog = () => {

<Paragraph fontSize={1.5}><i>TIP: Click the button next to entries to copy the full JSON to your clipboard.</i></Paragraph>

{( eventsAreLoading || eventsData === undefined)
? (
{events.map((event, index) => (
<Flex key={`event-${index}`} id={`event-${index}`}>
<Paragraph fontSize={1.5}>
<CodeBlock>
title: {event.title} <br />
created_at: {event.created_at.toString()} <br />
json: {JSON.stringify(event.json).length < 50
? JSON.stringify(event.json)
: `${JSON.stringify(event.json).slice(0, 50)} [...]`
}
</CodeBlock>
</Paragraph>

<Button onClick={() => navigator.clipboard.writeText(JSON.stringify(event.json))}>
<Icon iconName={"clipboard-fill"} size={1.5} />
</Button>
</Flex>
))}

{!fetchedAllEvents && (
<div ref={loadingRef}>
<Loading size={100} />
)
: eventsData.map((event, index) => (
<Flex key={`event-${index}`} id={`event-${index}`}>
<Paragraph fontSize={1.5}>
<CodeBlock>
title: {event.title} <br />
created_at: {event.created_at.toString()} <br />
json: {JSON.stringify(event.json).length < 50
? JSON.stringify(event.json)
: `${JSON.stringify(event.json).slice(0, 50)} [...]`
}
</CodeBlock>
</Paragraph>

<Button onClick={() => navigator.clipboard.writeText(JSON.stringify(event.json))}>
<Icon iconName={"clipboard-fill"} size={1.5} />
</Button>
</Flex>
))
}
</div>
)}
</Flex>
);
};
Expand Down
12 changes: 7 additions & 5 deletions src/server/api/routers/event_log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import {
createTRPCRouter,
publicProcedure,
} from "@khenzii-dev/server/api/trpc";
import { EventLogService } from "@khenzii-dev/server/backend";
import { getEventsInput, EventLogService } from "@khenzii-dev/server/backend";


export const eventLogRouter = createTRPCRouter({
getEvents: publicProcedure.query(async ({ ctx }) => {
const handler = new EventLogService(ctx);
return await handler.getEvents();
}),
getEvents: publicProcedure
.input(getEventsInput)
.query(async ({ ctx, input }) => {
const handler = new EventLogService(ctx);
return await handler.getEvents(input);
}),
});
21 changes: 19 additions & 2 deletions src/server/backend/event_log/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
export * from "./event";

import { BaseService } from "..";
import { BaseService } from "@khenzii-dev/server/backend";
import type { JsonValue } from "@prisma/client/runtime/library";
import { z } from "zod";

export const getEventsInput = z.object({
offset: z.number().min(0).optional(),
}).optional();

type getEventsInputType = z.infer<typeof getEventsInput>;

export type AdminEvent = {
id: string;
title: string;
json: JsonValue;
created_at: Date;
};

export class EventLogService extends BaseService {
async getEvents() {
async getEvents(input: getEventsInputType): Promise<AdminEvent[]> {
return await this.ctx.db.event.findMany({
orderBy: { created_at: "desc" },
skip: (input?.offset ?? 0) * 20,
take: 20,
});
}
}
Expand Down

0 comments on commit 2432637

Please sign in to comment.