Initial commit for Start9 packaging
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user