- Add rules_engine.py with quantitative rules for all 8 workout types - Add quality gate retry loop in generate_single_workout() - Expand calibrate_structure_rules to all 120 combinations (8 types × 5 goals × 3 sections) - Wire WeeklySplitPattern DB records into _pick_weekly_split() - Enforce movement patterns from WorkoutStructureRule in exercise selection - Add straight-set strength support (single main lift, 4-6 rounds) - Add modality consistency check for duration-dominant workout types - Add InjuryStep component to onboarding and preferences - Add sibling exercise exclusion in regenerate and preview_day endpoints - Display generator warnings on dashboard - Expand fix_rep_durations, fix_exercise_flags, fix_movement_pattern_typo - Add audit_exercise_data and check_rules_drift management commands - Add Next.js frontend with dashboard, onboarding, preferences, history pages - Add generator app with ML-powered workout generation pipeline - 96 new tests across 7 test modules Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { usePathname, useRouter } from "next/navigation";
|
|
import { useAuth } from "@/lib/auth";
|
|
import { Button } from "@/components/ui/Button";
|
|
|
|
const navLinks = [
|
|
{ href: "/dashboard", label: "Dashboard" },
|
|
{ href: "/plans", label: "Plans" },
|
|
{ href: "/rules", label: "Rules" },
|
|
{ href: "/history", label: "History" },
|
|
];
|
|
|
|
export function Navbar() {
|
|
const pathname = usePathname();
|
|
const router = useRouter();
|
|
const { user, logout } = useAuth();
|
|
|
|
const handleLogout = () => {
|
|
logout();
|
|
router.push("/login");
|
|
};
|
|
|
|
return (
|
|
<nav className="fixed top-0 left-0 right-0 z-50 h-16 bg-zinc-900/80 backdrop-blur border-b border-zinc-800 px-6 flex items-center justify-between">
|
|
<Link href="/dashboard" className="text-[#39FF14] font-bold text-xl tracking-tight">
|
|
WERKOUT
|
|
</Link>
|
|
|
|
<div className="hidden md:flex items-center gap-6">
|
|
{navLinks.map((link) => {
|
|
const isActive =
|
|
pathname === link.href || pathname.startsWith(link.href + "/");
|
|
return (
|
|
<Link
|
|
key={link.href}
|
|
href={link.href}
|
|
className={`text-sm font-medium transition-colors duration-150 ${
|
|
isActive
|
|
? "text-[#39FF14]"
|
|
: "text-zinc-400 hover:text-zinc-100"
|
|
}`}
|
|
>
|
|
{link.label}
|
|
</Link>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
<div className="flex items-center gap-3">
|
|
{user && (
|
|
<span className="text-sm text-zinc-300 hidden sm:inline">
|
|
{user.first_name}
|
|
</span>
|
|
)}
|
|
<Link
|
|
href="/preferences"
|
|
className={`text-sm font-medium transition-colors duration-150 ${
|
|
pathname === "/preferences"
|
|
? "text-[#39FF14]"
|
|
: "text-zinc-400 hover:text-zinc-100"
|
|
}`}
|
|
>
|
|
Preferences
|
|
</Link>
|
|
<Button variant="ghost" size="sm" onClick={handleLogout}>
|
|
Logout
|
|
</Button>
|
|
</div>
|
|
</nav>
|
|
);
|
|
}
|