diff --git a/frontend/src/app/dashboard/components/Leaderboard.tsx b/frontend/src/app/dashboard/components/Leaderboard.tsx index a3caf09..85f7235 100644 --- a/frontend/src/app/dashboard/components/Leaderboard.tsx +++ b/frontend/src/app/dashboard/components/Leaderboard.tsx @@ -1 +1,85 @@ -export function Leaderboard() { return null; } +"use client"; + +import { Clock, Egg, Medal, Trophy } from "lucide-react"; +import { useEffect, useState } from "react"; +import { userApi } from "@/lib/api"; +import { formatNumber } from "@/lib/utils"; + +export function Leaderboard() { + const [data, setData] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + userApi + .getLeaderboard() + .then((r) => setData(r.data)) + .finally(() => setLoading(false)); + }, []); + + if (loading) + return ( +
+ Checking pecking order... +
+ ); + + return ( +
+ {/* Top Earners */} +
+
+ +

+ Rich Birds +

+
+
+ {data?.topEarners?.map((u: any, i: number) => ( +
+
+
+ {i === 0 ? : i + 1} +
+
{u.plexUsername}
+
+
+ {formatNumber(u.totalEarned)} +
+
+ ))} +
+
+ + {/* Top Watchers */} +
+
+ +

+ Lazy Birds +

+
+
+ {data?.topWatchers?.map((u: any, i: number) => ( +
+
+
+ {i + 1} +
+
{u.plexUsername}
+
+
+ {formatNumber(u.watchTimeMinutes)} MINS +
+
+ ))} +
+
+
+ ); +} diff --git a/frontend/src/app/dashboard/components/WatchHistory.tsx b/frontend/src/app/dashboard/components/WatchHistory.tsx index afcd1f1..61ee384 100644 --- a/frontend/src/app/dashboard/components/WatchHistory.tsx +++ b/frontend/src/app/dashboard/components/WatchHistory.tsx @@ -1 +1,77 @@ -export function WatchHistory() { return null; } +"use client"; + +import { Clock, Egg, Film, Tv } from "lucide-react"; +import { useEffect, useState } from "react"; +import { userApi } from "@/lib/api"; +import { formatNumber } from "@/lib/utils"; + +export function WatchHistory() { + const [events, setEvents] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + userApi + .getWatchHistory(1, 50) + .then((r) => setEvents(r.data.events || [])) + .finally(() => setLoading(false)); + }, []); + + if (loading) + return ( +
Peeking at history...
+ ); + if (events.length === 0) + return ( +
+
🏜️
+
+ Nest is empty. Go watch something! +
+
+ ); + + return ( +
+ {events.map((e) => ( +
+
+
+ {e.contentType === "movie" ? ( + + ) : ( + + )} +
+
+
{e.title}
+ {e.grandparentTitle && ( +
+ {e.grandparentTitle} +
+ )} +
+ + {Math.floor(e.duration / 60)}{" "} + MINS + + + {e.percentComplete}% DONE +
+
+
+
+
+ +{formatNumber(e.creditsEarned)} +
+
+ {new Date(e.watchedAt).toLocaleDateString()} +
+
+
+ ))} +
+ ); +}