diff --git a/react-frontend/bun.lockb b/react-frontend/bun.lockb index 8fac02e..3d48552 100755 Binary files a/react-frontend/bun.lockb and b/react-frontend/bun.lockb differ diff --git a/react-frontend/package.json b/react-frontend/package.json index ca4fe96..dfd613d 100644 --- a/react-frontend/package.json +++ b/react-frontend/package.json @@ -21,6 +21,7 @@ "lucide-react": "^0.274.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "recharts": "^2.8.0", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.7" }, diff --git a/react-frontend/src/pages/dashboard.tsx b/react-frontend/src/pages/dashboard.tsx index e52578f..466c24c 100644 --- a/react-frontend/src/pages/dashboard.tsx +++ b/react-frontend/src/pages/dashboard.tsx @@ -1,15 +1,43 @@ import { Navbar } from '@/App' import { ThemeProvider } from '@/components/theme-provider' +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { useParams } from 'react-router-dom' import { useEffect, useState } from 'react' +import { Bar, BarChart, ResponsiveContainer, XAxis, YAxis } from 'recharts' + type Shortener = { id: number link: string code: string + visitors: { + visited_at: Date + country: string + }[] } +const months = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec', +] as const + +type VisitorData = { name: string; total: number } +let visitor_data: VisitorData[] = [] +months.forEach((months) => { + visitor_data.push({ name: months, total: 0 }) +}) + const backend_url = import.meta.env.VITE_BACKEND_URL ?? 'http://192.168.100.40:3000' @@ -18,6 +46,8 @@ export default function Dashboard() { const [isLoading, setIsLoading] = useState(false) const { shortenerId } = useParams() + const [visitorData, setVisitorData] = useState(visitor_data) + const getShorteners = async () => { setIsLoading(true) const response = await fetch(backend_url + '/link/' + shortenerId, { @@ -27,20 +57,125 @@ export default function Dashboard() { const data = (await response.json()).shorteners as Shortener[] setShorteners(data) + calculateShortenerData(data[0]) setIsLoading(false) } + const calculateShortenerData = (shortener: Shortener) => { + const visitors = shortener.visitors + let data: VisitorData[] = [] + months.forEach((months) => { + data.push({ name: months, total: 0 }) + }) + let visitor_data_copy = data + + visitors.forEach((visitor) => { + const month = new Date(visitor.visited_at).getMonth() + visitor_data_copy[month] = { + ...visitor_data_copy[month], + total: visitor_data_copy[month].total + 1, + } + setVisitorData(visitor_data_copy) + }) + console.log(visitorData) + } + useEffect(() => { if (!shorteners.length) { getShorteners() } }, []) + const thisMonth = new Date().getMonth() + return ( +
+
+
+ {backend_url + '/' + shortenerId} +
+
+
+ + + + This Month's Visitors + + + + + + +
+ {visitorData[thisMonth]?.total ?? 0} +
+

+ {`+ ${ + visitorData[thisMonth]?.total ?? + 0 - + visitorData[thisMonth - 1] + ?.total ?? + 0 + } since last month`} +

+
+
+
+
+ + + Visitors + + + + + +
+
+
+
) } + +export function Overview({ visitorData }: { visitorData: VisitorData[] }) { + return ( + + + + + + + + ) +}