diff --git a/apps/admin/src/app/globals.css b/apps/admin/src/app/globals.css index b219a46..31d4e38 100644 --- a/apps/admin/src/app/globals.css +++ b/apps/admin/src/app/globals.css @@ -1,10 +1,18 @@ @tailwind base; @tailwind components; @tailwind utilities; + +/* Sports Theme Colors */ +:root { + --primary-blue: #2563eb; + --secondary-orange: #fb7a1b; + --accent-green: #22c55e; +} @layer base { :root { - --background: 0 0% 100%; + /* Light Mode - Sports Theme */ + --background: 0 0% 98%; --foreground: 222.2 84% 4.9%; --card: 0 0% 100%; @@ -13,56 +21,63 @@ --popover: 0 0% 100%; --popover-foreground: 222.2 84% 4.9%; - --primary: 222.2 47.4% 11.2%; - --primary-foreground: 210 40% 98%; + /* Electric Blue Primary */ + --primary: 217 91.2% 59.8%; + --primary-foreground: 0 0% 100%; - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; + /* Vibrant Orange Secondary */ + --secondary: 24.6 97.4% 54.3%; + --secondary-foreground: 0 0% 100%; + + /* Emerald Green Accent */ + --accent: 142.1 70.6% 45.3%; + --accent-foreground: 0 0% 100%; --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; - --destructive: 0 84.2% 60.2%; --destructive-foreground: 210 40% 98%; --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; - --ring: 222.2 84% 4.9%; + --ring: 217 91.2% 59.8%; - --radius: 0.5rem; + --radius: 0.75rem; } .dark { + /* Dark Mode - Sports Theme */ --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; - --card: 222.2 84% 4.9%; + --card: 225.7 29.5% 15.3%; --card-foreground: 210 40% 98%; - --popover: 222.2 84% 4.9%; + --popover: 225.7 29.5% 15.3%; --popover-foreground: 210 40% 98%; - --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 11.2%; + /* Electric Blue Primary */ + --primary: 217 91.2% 59.8%; + --primary-foreground: 225.7 29.5% 15.3%; - --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; + /* Vibrant Orange Secondary */ + --secondary: 24.6 97.4% 54.3%; + --secondary-foreground: 225.7 29.5% 15.3%; + + /* Emerald Green Accent */ + --accent: 142.1 70.6% 45.3%; + --accent-foreground: 225.7 29.5% 15.3%; --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; - --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; - --destructive: 0 62.8% 30.6%; --destructive-foreground: 210 40% 98%; --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; - --ring: 212.7 26.8% 83.9%; + --ring: 217 91.2% 59.8%; } } @@ -71,6 +86,28 @@ @apply border-border; } body { - @apply bg-background text-foreground; + @apply bg-background text-foreground transition-colors duration-300; + } + + h1, h2, h3, h4, h5, h6 { + @apply font-bold text-foreground; + } +} + +@layer components { + .sports-gradient { + @apply bg-gradient-to-r from-[#2563eb] via-[#fb7a1b] to-[#22c55e]; + } + + .card-modern { + @apply bg-white dark:bg-slate-800 rounded-2xl shadow-lg border border-slate-200 dark:border-slate-700; + } + + .btn-sports { + @apply bg-gradient-to-r from-[#2563eb] to-[#fb7a1b] hover:shadow-lg transform hover:scale-105 transition-all duration-200 text-white font-bold; + } + + .text-gradient { + @apply bg-gradient-to-r from-[#2563eb] to-[#fb7a1b] bg-clip-text text-transparent; } } \ No newline at end of file diff --git a/apps/admin/src/app/page.tsx b/apps/admin/src/app/page.tsx index a0d682a..90f582c 100644 --- a/apps/admin/src/app/page.tsx +++ b/apps/admin/src/app/page.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; -import { Users, CreditCard, CalendarCheck, TrendingUp } from "lucide-react"; +import { Users, CreditCard, CalendarCheck, TrendingUp, Brain, Calendar, User } from "lucide-react"; import { StatsCard } from "@/components/ui/StatsCard"; import { UserManagement } from "@/components/users/UserManagement"; import { AnalyticsDashboard } from "@/components/analytics/AnalyticsDashboard"; @@ -14,6 +14,27 @@ interface DashboardStats { revenueGrowth: number; } +type TabType = "overview" | "users" | "analytics" | "recommendations" | "attendance" | "profile"; + +interface Recommendation { + id: string; + userId: string; + content: string; + activityPlan: string; + dietPlan: string; + status: string; + createdAt: Date; +} + +interface AttendanceRecord { + id: string; + clientId: string; + checkInTime: string; + checkOutTime?: string; + type: string; + notes?: string; +} + export default function Home() { const [stats, setStats] = useState({ totalUsers: 0, @@ -22,6 +43,11 @@ export default function Home() { revenueGrowth: 0, }); const [loading, setLoading] = useState(true); + const [activeTab, setActiveTab] = useState("overview"); + const [recommendations, setRecommendations] = useState([]); + const [attendance, setAttendance] = useState([]); + const [recommendationsLoading, setRecommendationsLoading] = useState(false); + const [attendanceLoading, setAttendanceLoading] = useState(false); useEffect(() => { const fetchStats = async () => { @@ -38,6 +64,46 @@ export default function Home() { fetchStats(); }, []); + // Fetch recommendations when tab changes + useEffect(() => { + if (activeTab === "recommendations") { + fetchRecommendations(); + } + }, [activeTab]); + + // Fetch attendance when tab changes + useEffect(() => { + if (activeTab === "attendance") { + fetchAttendance(); + } + }, [activeTab]); + + const fetchRecommendations = async () => { + setRecommendationsLoading(true); + try { + const response = await fetch("/api/recommendations"); + const data = await response.json(); + setRecommendations(data.recommendations || []); + } catch (error) { + console.error("Error fetching recommendations:", error); + } finally { + setRecommendationsLoading(false); + } + }; + + const fetchAttendance = async () => { + setAttendanceLoading(true); + try { + const response = await fetch("/api/admin/attendance"); + const data = await response.json(); + setAttendance(data || []); + } catch (error) { + console.error("Error fetching attendance:", error); + } finally { + setAttendanceLoading(false); + } + }; + const formatCurrency = (value: number) => { return new Intl.NumberFormat("en-US", { style: "currency", @@ -45,58 +111,240 @@ export default function Home() { }).format(value); }; + const tabs: { id: TabType; label: string; icon: React.ReactNode }[] = [ + { id: "overview", label: "Overview", icon: }, + { id: "users", label: "Users", icon: }, + { id: "analytics", label: "Analytics", icon: }, + { id: "recommendations", label: "Recommendations", icon: }, + { id: "attendance", label: "Attendance", icon: }, + { id: "profile", label: "Profile", icon: }, + ]; + return ( -
-
-

Dashboard

-

Welcome back, here's what's happening today.

-
- -
- - - 0 ? "+" : ""}${stats.revenueGrowth}%`} - trend={stats.revenueGrowth >= 0 ? "up" : "down"} - icon={CreditCard} - color="purple" - /> - -
- -
-
-

Recent Activity

- +
+
+ {/* Header Section */} +
+
+
+

💪 FitAI Elite

+
+

Admin Dashboard

+

Manage your fitness platform with complete control.

-
-

Quick Analytics

- + {/* Tab Navigation */} +
+
+ {tabs.map((tab) => ( + + ))} +
+ + {/* Overview Tab */} + {activeTab === "overview" && ( +
+ {/* Stats Cards - Responsive Grid */} +
+ + + 0 ? "+" : ""}${stats.revenueGrowth}%`} + trend={stats.revenueGrowth >= 0 ? "up" : "down"} + icon={CreditCard} + color="purple" + /> + +
+ + {/* Quick Stats Section */} +
+
+

Quick Overview

+
+
+
+
+

Total Revenue

+

{formatCurrency(stats.totalRevenue)}

+
+
+

Active Members

+

{stats.activeClients}

+
+
+

Platform Users

+

{stats.totalUsers}

+
+
+
+
+
+ )} + + {/* Users Tab */} + {activeTab === "users" && ( +
+
+
+

+ + User Management +

+
+
+ +
+
+
+ )} + + {/* Analytics Tab */} + {activeTab === "analytics" && ( +
+
+
+

+ + Analytics Dashboard +

+
+
+ +
+
+
+ )} + + {/* Other Tabs - Coming Soon */} + {activeTab === "recommendations" && ( +
+
+

+ + AI Recommendations +

+
+
+ {recommendationsLoading ? ( +
Loading recommendations...
+ ) : recommendations.length > 0 ? ( +
+
+ {recommendations.slice(0, 6).map((rec) => ( +
+
+

User ID: {rec.userId}

+ + {rec.status} + +
+

{rec.content}

+

Activity: {rec.activityPlan.substring(0, 50)}...

+
+ ))} +
+
+ ) : ( +
No recommendations yet
+ )} +
+
+ )} + + {/* Attendance Tab */} + {activeTab === "attendance" && ( +
+
+

+ + Attendance Monitoring +

+
+
+ {attendanceLoading ? ( +
Loading attendance data...
+ ) : attendance.length > 0 ? ( + + + + + + + + + + + {attendance.slice(0, 10).map((record) => ( + + + + + + + ))} + +
Client IDCheck InCheck OutType
{record.clientId}{new Date(record.checkInTime).toLocaleString()}{record.checkOutTime ? new Date(record.checkOutTime).toLocaleString() : '-'} + + {record.type} + +
+ ) : ( +
No attendance records
+ )} +
+
+ )} + + {/* Profile Tab */} + {activeTab === "profile" && ( +
+
+

+ + Admin Profile +

+
+
+

Profile management coming soon!

+
+
+ )}
); diff --git a/apps/admin/src/app/profile/page.tsx b/apps/admin/src/app/profile/page.tsx index 646ae54..43533e2 100644 --- a/apps/admin/src/app/profile/page.tsx +++ b/apps/admin/src/app/profile/page.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { useUser } from "@clerk/nextjs"; -import { Button } from "@/components/ui/Button"; +import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; interface UserProfile { diff --git a/apps/admin/src/components/Navigation.tsx b/apps/admin/src/components/Navigation.tsx index 9faa549..8762d83 100644 --- a/apps/admin/src/components/Navigation.tsx +++ b/apps/admin/src/components/Navigation.tsx @@ -6,7 +6,7 @@ import { usePathname } from "next/navigation"; import { Home, Users, BarChart3, User, Brain } from "lucide-react"; import { SignedIn, UserButton } from "@clerk/nextjs"; import { cn } from "@/lib/utils"; -import { Button } from "@/components/ui/Button"; +import { Button } from "@/components/ui/button"; interface NavItem { href: string; diff --git a/apps/admin/src/components/ui/StatsCard.tsx b/apps/admin/src/components/ui/StatsCard.tsx index 76cb699..567d4e8 100644 --- a/apps/admin/src/components/ui/StatsCard.tsx +++ b/apps/admin/src/components/ui/StatsCard.tsx @@ -19,19 +19,19 @@ export function StatsCard({ title, value, change, trend, icon: Icon, color = "bl }; return ( - + - + {title} -
+
- -
{value}
+ +
{value}
{change && ( -

+

-

+
+
setSearchQuery(e.target.value)} /> -
+
{...gridOptions} ref={gridRef} />
diff --git a/apps/admin/src/components/users/UserManagement.tsx b/apps/admin/src/components/users/UserManagement.tsx index 15b7066..b1640a1 100644 --- a/apps/admin/src/components/users/UserManagement.tsx +++ b/apps/admin/src/components/users/UserManagement.tsx @@ -2,7 +2,7 @@ import { useState, useEffect } from "react"; import { UserGrid } from "@/components/users/UserGrid"; -import { Button } from "@/components/ui/Button"; +import { Button } from "@/components/ui/button"; import { Card, CardHeader, CardContent } from "@/components/ui/card"; interface User {