Skip to content

Commit

Permalink
feat(web): react query implementation on admin dashboard page
Browse files Browse the repository at this point in the history
  • Loading branch information
mrevanzak committed May 27, 2024
1 parent 85fbc0f commit d8cc40d
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 88 deletions.
91 changes: 3 additions & 88 deletions apps/web/src/app/(app)/@admin/page.tsx
Original file line number Diff line number Diff line change
@@ -1,97 +1,12 @@
import { AreaChart } from "@/components/area-chart";
import { StatisticsContainer } from "@/components/statistics-container";
import { api } from "@/trpc/server";
import { Chip, Divider, Tooltip } from "@nextui-org/react";
import moment from "moment";

import { Card, CardContent, CardHeader, CardTitle } from "@tanya.in/ui/card";

export default async function HomePage() {
const analytics = await api.analytics.get();
const data = analytics.map((item) => ({
date: item.key,
"Page Views": item.total,
Visitors: item.devices,
}));

const { visitors, pageViews } = analytics.reduce(
(acc, { devices, total }) => {
acc.visitors += devices;
acc.pageViews += total;
return acc;
},
{
visitors: 0,
pageViews: 0,
},
);
const { visitorsLastWeek, pageViewsLastWeek } = analytics.reduce(
(acc, { devices, total, key }) => {
if (moment(key).isSameOrBefore(moment().subtract(1, "week"))) {
acc.visitorsLastWeek += devices;
acc.pageViewsLastWeek += total;
}
return acc;
},
{
visitorsLastWeek: 0,
pageViewsLastWeek: 0,
},
);
const data = await api.analytics.get();

return (
<div className="flex flex-1 flex-wrap gap-4">
<Card className="w-full">
<CardHeader>
<CardTitle>Statistics</CardTitle>
</CardHeader>
<AreaChart
data={data}
index="date"
categories={["Page Views", "Visitors"]}
colors={["blue", "yellow"]}
showLegend={false}
showYAxis={false}
startEndOnly={true}
className="h-[calc(100vh-28rem)]"
/>
<CardContent className="space-y-4 p-6">
<div className="flex flex-row items-center justify-between">
<div className="flex items-center gap-3">
<div className="h-0.5 w-8 bg-primary-its" />
<p>{pageViews}</p>
<Tooltip
content={`${Math.abs(pageViews - pageViewsLastWeek)} ${pageViews > pageViewsLastWeek ? "more" : "less"} page views than last week`}
color="foreground"
>
<Chip color="success" radius="sm" variant="flat">
{pageViews > pageViewsLastWeek
? "↑ " + Math.abs(pageViews - pageViewsLastWeek)
: "↓ " + Math.abs(pageViews - pageViewsLastWeek)}
</Chip>
</Tooltip>
</div>
<p>Page Views</p>
</div>
<Divider />
<div className="flex flex-row items-center justify-between">
<div className="flex items-center gap-3">
<div className="h-0.5 w-8 bg-accent-its" />
<p>{visitors}</p>
<Tooltip
content={`${Math.abs(visitors - visitorsLastWeek)} ${visitors > visitorsLastWeek ? "more" : "less"} visitors than last week`}
color="foreground"
>
<Chip color="success" radius="sm" variant="flat">
{visitors > visitorsLastWeek
? "↑ " + Math.abs(visitors - visitorsLastWeek)
: "↓ " + Math.abs(visitors - visitorsLastWeek)}
</Chip>
</Tooltip>
</div>
<p>Visitors</p>
</div>
</CardContent>
</Card>
<StatisticsContainer initialData={data} />
</div>
);
}
100 changes: 100 additions & 0 deletions apps/web/src/components/statistics-container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"use client";

import type { Analytics } from "@/server/api/routers/analytics/analytics.schema";
import { AreaChart } from "@/components/area-chart";
import { api } from "@/trpc/react";
import { Chip, Divider, Tooltip } from "@nextui-org/react";
import moment from "moment";

import { Card, CardContent, CardHeader, CardTitle } from "@tanya.in/ui/card";

export function StatisticsContainer(props: { initialData: Analytics[] }) {
const { data } = api.analytics.get.useQuery(undefined, {
initialData: props.initialData,
});
const mappedData = data.map((item) => ({
date: item.key,
"Page Views": item.total,
Visitors: item.devices,
}));

const { visitors, pageViews } = data.reduce(
(acc, { devices, total }) => {
acc.visitors += devices;
acc.pageViews += total;
return acc;
},
{
visitors: 0,
pageViews: 0,
},
);
const { visitorsLastWeek, pageViewsLastWeek } = data.reduce(
(acc, { devices, total, key }) => {
if (moment(key).isSameOrBefore(moment().subtract(1, "week"))) {
acc.visitorsLastWeek += devices;
acc.pageViewsLastWeek += total;
}
return acc;
},
{
visitorsLastWeek: 0,
pageViewsLastWeek: 0,
},
);

return (
<Card className="w-full">
<CardHeader>
<CardTitle>Statistics</CardTitle>
</CardHeader>
<AreaChart
data={mappedData}
index="date"
categories={["Page Views", "Visitors"]}
colors={["blue", "yellow"]}
showLegend={false}
showYAxis={false}
startEndOnly={true}
className="h-[calc(100vh-28rem)]"
/>
<CardContent className="space-y-4 p-6">
<div className="flex flex-row items-center justify-between">
<div className="flex items-center gap-3">
<div className="h-0.5 w-8 bg-primary-its" />
<p>{pageViews}</p>
<Tooltip
content={`${Math.abs(pageViews - pageViewsLastWeek)} ${pageViews > pageViewsLastWeek ? "more" : "less"} page views than last week`}
color="foreground"
>
<Chip color="success" radius="sm" variant="flat">
{pageViews > pageViewsLastWeek
? "↑ " + Math.abs(pageViews - pageViewsLastWeek)
: "↓ " + Math.abs(pageViews - pageViewsLastWeek)}
</Chip>
</Tooltip>
</div>
<p>Page Views</p>
</div>
<Divider />
<div className="flex flex-row items-center justify-between">
<div className="flex items-center gap-3">
<div className="h-0.5 w-8 bg-accent-its" />
<p>{visitors}</p>
<Tooltip
content={`${Math.abs(visitors - visitorsLastWeek)} ${visitors > visitorsLastWeek ? "more" : "less"} visitors than last week`}
color="foreground"
>
<Chip color="success" radius="sm" variant="flat">
{visitors > visitorsLastWeek
? "↑ " + Math.abs(visitors - visitorsLastWeek)
: "↓ " + Math.abs(visitors - visitorsLastWeek)}
</Chip>
</Tooltip>
</div>
<p>Visitors</p>
</div>
</CardContent>
</Card>
);
}
2 changes: 2 additions & 0 deletions apps/web/src/server/api/routers/analytics/analytics.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export const analyticsSchema = z.object({
total: z.number().int(),
devices: z.number().int(),
});

export type Analytics = z.infer<typeof analyticsSchema>;

0 comments on commit d8cc40d

Please sign in to comment.