Files
proof-of-work/workout-planner/app/main/dashboard/page.tsx
T
2026-02-28 09:27:26 -06:00

195 lines
7.3 KiB
TypeScript

import { redirect } from "next/navigation";
import Link from "next/link";
import { getCurrentUser } from "@/lib/auth";
import {
getWeeklyWorkoutCount,
getMonthlyWorkoutCount,
getYearlyWorkoutCount,
getWeeklyVolume,
} from "@/lib/db/stats";
import { getRecentWorkouts } from "@/lib/db/workouts";
import { ActivitySquare, Calendar, CalendarDays, History, Plus } from "lucide-react";
export default async function DashboardPage() {
const user = await getCurrentUser();
if (!user) {
redirect("/auth/login");
}
const [weeklyCount, monthlyCount, yearlyCount, _weeklyVolume, recentWorkouts] =
await Promise.all([
getWeeklyWorkoutCount(user.id),
getMonthlyWorkoutCount(user.id),
getYearlyWorkoutCount(user.id),
getWeeklyVolume(user.id),
getRecentWorkouts(user.id, 5),
]);
return (
<div className="min-h-screen bg-[#0A0A0A]">
{/* Header with greeting */}
<div className="px-4 py-6 sm:px-6 lg:px-8">
<div className="max-w-7xl mx-auto">
<h1 className="text-4xl font-bold text-white">
Welcome back, {user.name || "Trainer"}!
</h1>
<p className="text-zinc-400 mt-2">
Keep pushing your limits and achieving your goals.
</p>
</div>
</div>
{/* Main content */}
<div className="max-w-7xl mx-auto px-4 py-6 sm:px-6 lg:px-8">
{/* Stats Cards */}
<div className="grid grid-cols-3 gap-3 sm:gap-4 mb-8">
{/* This Week */}
<div className="bg-zinc-900 border border-zinc-800 rounded-lg p-4 sm:p-6">
<div className="flex items-start justify-between">
<div>
<p className="text-zinc-400 text-xs sm:text-sm font-medium">
This Week
</p>
<p className="text-3xl sm:text-4xl font-bold text-white mt-1 sm:mt-2">
{weeklyCount}
</p>
<p className="text-zinc-500 text-[10px] sm:text-xs mt-1 sm:mt-2">
workouts
</p>
</div>
<div className="bg-zinc-800 p-2 sm:p-3 rounded-lg hidden sm:block">
<ActivitySquare className="text-white w-5 h-5 sm:w-6 sm:h-6" />
</div>
</div>
</div>
{/* This Month */}
<div className="bg-zinc-900 border border-zinc-800 rounded-lg p-4 sm:p-6">
<div className="flex items-start justify-between">
<div>
<p className="text-zinc-400 text-xs sm:text-sm font-medium">
This Month
</p>
<p className="text-3xl sm:text-4xl font-bold text-white mt-1 sm:mt-2">
{monthlyCount}
</p>
<p className="text-zinc-500 text-[10px] sm:text-xs mt-1 sm:mt-2">
workouts
</p>
</div>
<div className="bg-zinc-800 p-2 sm:p-3 rounded-lg hidden sm:block">
<Calendar className="text-white w-5 h-5 sm:w-6 sm:h-6" />
</div>
</div>
</div>
{/* This Year */}
<div className="bg-zinc-900 border border-zinc-800 rounded-lg p-4 sm:p-6">
<div className="flex items-start justify-between">
<div>
<p className="text-zinc-400 text-xs sm:text-sm font-medium">
This Year
</p>
<p className="text-3xl sm:text-4xl font-bold text-white mt-1 sm:mt-2">
{yearlyCount}
</p>
<p className="text-zinc-500 text-[10px] sm:text-xs mt-1 sm:mt-2">
workouts
</p>
</div>
<div className="bg-zinc-800 p-2 sm:p-3 rounded-lg hidden sm:block">
<CalendarDays className="text-white w-5 h-5 sm:w-6 sm:h-6" />
</div>
</div>
</div>
</div>
{/* Quick Actions */}
<div className="flex flex-col sm:flex-row gap-4 mb-8">
<Link
href="/main/workouts/new"
className="flex-1 bg-white hover:bg-gray-100 text-black font-medium py-3 px-4 rounded-lg flex items-center justify-center gap-2 transition"
>
<Plus className="w-5 h-5" />
Log Workout
</Link>
<Link
href="/main/workouts"
className="flex-1 bg-zinc-800 hover:bg-zinc-700 text-white font-medium py-3 px-4 rounded-lg flex items-center justify-center gap-2 transition"
>
<History className="w-5 h-5" />
View History
</Link>
</div>
{/* Recent Workouts */}
<div className="bg-zinc-900 border border-zinc-800 rounded-lg">
<div className="px-6 py-4 border-b border-zinc-800">
<h2 className="text-lg font-bold text-white">
Recent Workouts
</h2>
</div>
{recentWorkouts.length === 0 ? (
<div className="px-6 py-12 text-center">
<ActivitySquare className="w-12 h-12 text-zinc-600 mx-auto mb-4" />
<h3 className="text-lg font-semibold text-white mb-2">
No workouts yet
</h3>
<p className="text-zinc-400 mb-6">
Start your fitness journey by logging your first workout!
</p>
<Link
href="/main/workouts/new"
className="inline-block bg-white hover:bg-gray-100 text-black font-medium py-2 px-4 rounded-lg transition"
>
Log First Workout
</Link>
</div>
) : (
<div className="divide-y divide-zinc-800">
{recentWorkouts.map((workout) => (
<Link
key={workout.id}
href={`/main/workouts/${workout.id}`}
className="px-6 py-4 hover:bg-zinc-800 transition block"
>
<div className="flex items-start justify-between">
<div>
<h3 className="font-semibold text-white">
{workout.name || "Unnamed Workout"}
</h3>
<p className="text-sm text-zinc-400 mt-1">
{new Date(workout.date).toLocaleDateString("en-US", {
weekday: "short",
month: "short",
day: "numeric",
year: "numeric",
})}
</p>
<p className="text-sm text-zinc-500 mt-1">
{(workout as any).setLogs.length} sets
{workout.durationMinutes &&
` · ${workout.durationMinutes} min`}
</p>
</div>
<div className="text-right">
<div className="text-2xl font-bold text-white">
{(workout as any).setLogs.length}
</div>
<p className="text-xs text-zinc-400 mt-1">
{(workout as any).setLogs.length === 1 ? "set" : "sets"}
</p>
</div>
</div>
</Link>
))}
</div>
)}
</div>
</div>
</div>
);
}