Skip to content

Commit 4030f09

Browse files
committed
First push on this branch. At about 29 minutes in the video for Issue #71.
1 parent 414f19f commit 4030f09

File tree

9 files changed

+119
-36
lines changed

9 files changed

+119
-36
lines changed

personal-dashboard/package-lock.json

+24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

personal-dashboard/package.json

+7-5
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,21 @@
99
"lint": "next lint"
1010
},
1111
"dependencies": {
12+
"@upstash/redis": "^1.28.4",
13+
"date-fns": "^3.4.0",
14+
"next": "14.1.3",
1215
"react": "^18",
13-
"react-dom": "^18",
14-
"next": "14.1.3"
16+
"react-dom": "^18"
1517
},
1618
"devDependencies": {
17-
"typescript": "^5",
1819
"@types/node": "^20",
1920
"@types/react": "^18",
2021
"@types/react-dom": "^18",
2122
"autoprefixer": "^10.0.1",
23+
"eslint": "^8",
24+
"eslint-config-next": "14.1.3",
2225
"postcss": "^8",
2326
"tailwindcss": "^3.3.0",
24-
"eslint": "^8",
25-
"eslint-config-next": "14.1.3"
27+
"typescript": "^5"
2628
}
2729
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const Page = ()=>{
2+
return <p>Hello world</p>
3+
}
4+
5+
export default Page;
-30
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,3 @@
11
@tailwind base;
22
@tailwind components;
33
@tailwind utilities;
4-
5-
:root {
6-
--foreground-rgb: 0, 0, 0;
7-
--background-start-rgb: 214, 219, 220;
8-
--background-end-rgb: 255, 255, 255;
9-
}
10-
11-
@media (prefers-color-scheme: dark) {
12-
:root {
13-
--foreground-rgb: 255, 255, 255;
14-
--background-start-rgb: 0, 0, 0;
15-
--background-end-rgb: 0, 0, 0;
16-
}
17-
}
18-
19-
body {
20-
color: rgb(var(--foreground-rgb));
21-
background: linear-gradient(
22-
to bottom,
23-
transparent,
24-
rgb(var(--background-end-rgb))
25-
)
26-
rgb(var(--background-start-rgb));
27-
}
28-
29-
@layer utilities {
30-
.text-balance {
31-
text-wrap: balance;
32-
}
33-
}

personal-dashboard/src/app/layout.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default function RootLayout({
1616
}>) {
1717
return (
1818
<html lang="en">
19-
<body className={inter.className}>{children}</body>
19+
<body className={'${inter.className} dark bg-[#020817]'}>{children}</body>
2020
</html>
2121
);
2222
}

personal-dashboard/src/lib/redis.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// NOTE: @about 17:00 - minutes
2+
3+
import { Redis } from "@upstash/redis";
4+
5+
export const redis = new Redis({
6+
url: "https://us1-sharing-oryx-41733.upstash.io",
7+
token: process.env.REDIS_KEY!,
8+
});
9+
10+
// const data = await redis.set("foo", "bar");

personal-dashboard/src/middleware.ts

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// NOTE: @about 6:00 minutes
2+
import { NextRequest, NextResponse } from "next/server";
3+
import { analytics } from "./utils/analytics";
4+
5+
export default async function middleware(req: NextRequest) {
6+
// Anytime the url is `http://localhost:3000/`, `req.nextUrl.pathname === "/"` will evaluates to `true`, it is truthy.
7+
if (req.nextUrl.pathname === "/") {
8+
// track analytics event
9+
// console.log("Tracking");
10+
// NOTE: @about ?:00 - minutes
11+
try {
12+
// what are we going to track?
13+
// pageview is our namespace that we are going to track
14+
// namespace fancy word for event name
15+
analytics.track("pageview", { page: "/", country: req.geo?.country });
16+
} catch (error) {
17+
// fail silently
18+
console.log(error);
19+
}
20+
}
21+
return NextResponse.next();
22+
}
23+
24+
// See NextJS documentation for why this is needed.
25+
// https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
26+
export const matcher = {
27+
matcher: ["/"],
28+
};
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// NOTE: @about 11:00 - minutes
2+
3+
import { redis } from "@/lib/redis";
4+
import { getDate } from "@/utils/";
5+
6+
type AnalyticsArgs = {
7+
retention?: number;
8+
};
9+
10+
type TrackOptions = { persist?: boolean };
11+
12+
export class Analytics {
13+
private retention: number = 60 * 60 * 24 * 7;
14+
15+
constructor(opts?: AnalyticsArgs) {
16+
if (opts?.retention) this.retention = opts.retention;
17+
}
18+
19+
async track(namespace: string, event: object = {}, opts?: TrackOptions) {
20+
let key = `analytics::${namespace}`;
21+
22+
if (!opts?.persist) {
23+
key += `::${getDate()}`;
24+
}
25+
26+
// db call to persist this event
27+
await redis.hincrby(key, JSON.stringify(event), 1);
28+
29+
if (!opts?.persist) await redis.expire(key, this.retention);
30+
}
31+
}
32+
33+
export const analytics = new Analytics();
34+
35+
// analytics.track()

personal-dashboard/src/utils/index.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// NOTE: @about 25:00 - minutes
2+
3+
import { format, subDays } from "date-fns";
4+
5+
export const getDate = (sub: number = 0) => {
6+
const dateXDaysAgo = subDays(new Date(), sub);
7+
8+
return format(dateXDaysAgo, "dd/MM/yyyy");
9+
};

0 commit comments

Comments
 (0)