This commit is contained in:
Aleksandar 2025-12-06 21:24:19 +01:00
parent ddb6933e42
commit bf741d6d00
9 changed files with 378 additions and 93 deletions

View File

@ -2,9 +2,17 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
/* Sports Theme Colors */
:root {
--primary-blue: #2563eb;
--secondary-orange: #fb7a1b;
--accent-green: #22c55e;
}
@layer base { @layer base {
:root { :root {
--background: 0 0% 100%; /* Light Mode - Sports Theme */
--background: 0 0% 98%;
--foreground: 222.2 84% 4.9%; --foreground: 222.2 84% 4.9%;
--card: 0 0% 100%; --card: 0 0% 100%;
@ -13,56 +21,63 @@
--popover: 0 0% 100%; --popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%; --popover-foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%; /* Electric Blue Primary */
--primary-foreground: 210 40% 98%; --primary: 217 91.2% 59.8%;
--primary-foreground: 0 0% 100%;
--secondary: 210 40% 96.1%; /* Vibrant Orange Secondary */
--secondary-foreground: 222.2 47.4% 11.2%; --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: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%; --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: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%; --destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%; --border: 214.3 31.8% 91.4%;
--input: 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 {
/* Dark Mode - Sports Theme */
--background: 222.2 84% 4.9%; --background: 222.2 84% 4.9%;
--foreground: 210 40% 98%; --foreground: 210 40% 98%;
--card: 222.2 84% 4.9%; --card: 225.7 29.5% 15.3%;
--card-foreground: 210 40% 98%; --card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%; --popover: 225.7 29.5% 15.3%;
--popover-foreground: 210 40% 98%; --popover-foreground: 210 40% 98%;
--primary: 210 40% 98%; /* Electric Blue Primary */
--primary-foreground: 222.2 47.4% 11.2%; --primary: 217 91.2% 59.8%;
--primary-foreground: 225.7 29.5% 15.3%;
--secondary: 217.2 32.6% 17.5%; /* Vibrant Orange Secondary */
--secondary-foreground: 210 40% 98%; --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: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%; --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: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%; --destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%; --border: 217.2 32.6% 17.5%;
--input: 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; @apply border-border;
} }
body { 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;
} }
} }

View File

@ -1,7 +1,7 @@
"use client"; "use client";
import { useEffect, useState } from "react"; 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 { StatsCard } from "@/components/ui/StatsCard";
import { UserManagement } from "@/components/users/UserManagement"; import { UserManagement } from "@/components/users/UserManagement";
import { AnalyticsDashboard } from "@/components/analytics/AnalyticsDashboard"; import { AnalyticsDashboard } from "@/components/analytics/AnalyticsDashboard";
@ -14,6 +14,27 @@ interface DashboardStats {
revenueGrowth: number; 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() { export default function Home() {
const [stats, setStats] = useState<DashboardStats>({ const [stats, setStats] = useState<DashboardStats>({
totalUsers: 0, totalUsers: 0,
@ -22,6 +43,11 @@ export default function Home() {
revenueGrowth: 0, revenueGrowth: 0,
}); });
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [activeTab, setActiveTab] = useState<TabType>("overview");
const [recommendations, setRecommendations] = useState<Recommendation[]>([]);
const [attendance, setAttendance] = useState<AttendanceRecord[]>([]);
const [recommendationsLoading, setRecommendationsLoading] = useState(false);
const [attendanceLoading, setAttendanceLoading] = useState(false);
useEffect(() => { useEffect(() => {
const fetchStats = async () => { const fetchStats = async () => {
@ -38,6 +64,46 @@ export default function Home() {
fetchStats(); 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) => { const formatCurrency = (value: number) => {
return new Intl.NumberFormat("en-US", { return new Intl.NumberFormat("en-US", {
style: "currency", style: "currency",
@ -45,58 +111,240 @@ export default function Home() {
}).format(value); }).format(value);
}; };
const tabs: { id: TabType; label: string; icon: React.ReactNode }[] = [
{ id: "overview", label: "Overview", icon: <TrendingUp size={18} /> },
{ id: "users", label: "Users", icon: <Users size={18} /> },
{ id: "analytics", label: "Analytics", icon: <TrendingUp size={18} /> },
{ id: "recommendations", label: "Recommendations", icon: <Brain size={18} /> },
{ id: "attendance", label: "Attendance", icon: <Calendar size={18} /> },
{ id: "profile", label: "Profile", icon: <User size={18} /> },
];
return ( return (
<div className="space-y-8"> <div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-slate-100 dark:from-slate-950 dark:via-slate-900 dark:to-slate-950">
<div> <div className="w-full px-4 sm:px-6 lg:px-8 py-6 sm:py-8">
<h2 className="text-3xl font-bold text-slate-900">Dashboard</h2> {/* Header Section */}
<p className="text-slate-500 mt-2">Welcome back, here's what's happening today.</p> <div className="mb-8 sm:mb-10">
</div> <div className="flex items-center gap-3 mb-3">
<div className="h-1 w-12 bg-gradient-to-r from-[#2563eb] to-[#fb7a1b] rounded-full"></div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"> <h1 className="text-3xl sm:text-4xl font-bold text-slate-900 dark:text-white">💪 FitAI Elite</h1>
<StatsCard </div>
title="Total Users" <h2 className="text-2xl sm:text-3xl font-bold text-slate-900 dark:text-white mt-4">Admin Dashboard</h2>
value={loading ? "..." : stats.totalUsers} <p className="text-slate-600 dark:text-slate-400 mt-2 text-sm sm:text-base">Manage your fitness platform with complete control.</p>
change="+12%" // Placeholder for now as we don't track historical growth yet
trend="up"
icon={Users}
color="blue"
/>
<StatsCard
title="Active Clients"
value={loading ? "..." : stats.activeClients}
change="+5%"
trend="up"
icon={CalendarCheck}
color="green"
/>
<StatsCard
title="Revenue"
value={loading ? "..." : formatCurrency(stats.totalRevenue)}
change={`${stats.revenueGrowth > 0 ? "+" : ""}${stats.revenueGrowth}%`}
trend={stats.revenueGrowth >= 0 ? "up" : "down"}
icon={CreditCard}
color="purple"
/>
<StatsCard
title="Growth"
value="24%" // Placeholder
change="-2%"
trend="down"
icon={TrendingUp}
color="orange"
/>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-2 bg-white rounded-xl shadow-sm border border-slate-100 p-6">
<h3 className="text-xl font-bold text-slate-900 mb-6">Recent Activity</h3>
<UserManagement />
</div> </div>
<div className="bg-white rounded-xl shadow-sm border border-slate-100 p-6"> {/* Tab Navigation */}
<h3 className="text-xl font-bold text-slate-900 mb-6">Quick Analytics</h3> <div className="mb-8 overflow-x-auto">
<AnalyticsDashboard /> <div className="flex gap-2 pb-4 min-w-min">
{tabs.map((tab) => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`flex items-center gap-2 px-4 py-2 rounded-lg font-medium whitespace-nowrap transition-all ${
activeTab === tab.id
? "bg-gradient-to-r from-[#2563eb] to-[#fb7a1b] text-white shadow-lg"
: "bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-300 border border-slate-200 dark:border-slate-700 hover:bg-slate-50 dark:hover:bg-slate-700"
}`}
>
{tab.icon}
{tab.label}
</button>
))}
</div>
</div> </div>
{/* Overview Tab */}
{activeTab === "overview" && (
<div className="space-y-8">
{/* Stats Cards - Responsive Grid */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-5 lg:gap-6">
<StatsCard
title="Total Users"
value={loading ? "..." : stats.totalUsers}
change="+12%"
trend="up"
icon={Users}
color="blue"
/>
<StatsCard
title="Active Clients"
value={loading ? "..." : stats.activeClients}
change="+5%"
trend="up"
icon={CalendarCheck}
color="green"
/>
<StatsCard
title="Revenue"
value={loading ? "..." : formatCurrency(stats.totalRevenue)}
change={`${stats.revenueGrowth > 0 ? "+" : ""}${stats.revenueGrowth}%`}
trend={stats.revenueGrowth >= 0 ? "up" : "down"}
icon={CreditCard}
color="purple"
/>
<StatsCard
title="Growth"
value="24%"
change="-2%"
trend="down"
icon={TrendingUp}
color="orange"
/>
</div>
{/* Quick Stats Section */}
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
<div className="bg-gradient-to-r from-[#2563eb] to-[#fb7a1b] p-6 sm:p-8">
<h3 className="text-xl sm:text-2xl font-bold text-white">Quick Overview</h3>
</div>
<div className="p-6 sm:p-8">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
<div className="text-center p-4 bg-slate-50 dark:bg-slate-700 rounded-lg">
<p className="text-slate-600 dark:text-slate-400 mb-2">Total Revenue</p>
<p className="text-3xl font-bold text-[#2563eb]">{formatCurrency(stats.totalRevenue)}</p>
</div>
<div className="text-center p-4 bg-slate-50 dark:bg-slate-700 rounded-lg">
<p className="text-slate-600 dark:text-slate-400 mb-2">Active Members</p>
<p className="text-3xl font-bold text-[#22c55e]">{stats.activeClients}</p>
</div>
<div className="text-center p-4 bg-slate-50 dark:bg-slate-700 rounded-lg">
<p className="text-slate-600 dark:text-slate-400 mb-2">Platform Users</p>
<p className="text-3xl font-bold text-[#fb7a1b]">{stats.totalUsers}</p>
</div>
</div>
</div>
</div>
</div>
)}
{/* Users Tab */}
{activeTab === "users" && (
<div className="space-y-6 sm:space-y-8">
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
<div className="bg-gradient-to-r from-[#2563eb] to-[#fb7a1b] p-6 sm:p-8">
<h3 className="text-xl sm:text-2xl font-bold text-white flex items-center gap-2">
<Users size={28} />
User Management
</h3>
</div>
<div className="p-6 sm:p-8 w-full overflow-hidden">
<UserManagement />
</div>
</div>
</div>
)}
{/* Analytics Tab */}
{activeTab === "analytics" && (
<div className="space-y-6 sm:space-y-8">
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
<div className="bg-gradient-to-r from-[#fb7a1b] to-[#22c55e] p-6 sm:p-8">
<h3 className="text-xl sm:text-2xl font-bold text-white flex items-center gap-2">
<TrendingUp size={28} />
Analytics Dashboard
</h3>
</div>
<div className="p-6 sm:p-8 w-full overflow-hidden">
<AnalyticsDashboard />
</div>
</div>
</div>
)}
{/* Other Tabs - Coming Soon */}
{activeTab === "recommendations" && (
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
<div className="bg-gradient-to-r from-[#2563eb] via-[#fb7a1b] to-[#22c55e] p-6 sm:p-8">
<h3 className="text-xl sm:text-2xl font-bold text-white flex items-center gap-2">
<Brain size={28} />
AI Recommendations
</h3>
</div>
<div className="p-6 sm:p-8">
{recommendationsLoading ? (
<div className="text-center py-8">Loading recommendations...</div>
) : recommendations.length > 0 ? (
<div className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{recommendations.slice(0, 6).map((rec) => (
<div key={rec.id} className="p-4 border border-slate-200 dark:border-slate-600 rounded-lg hover:shadow-lg transition-all">
<div className="flex justify-between items-start mb-2">
<h4 className="font-bold text-sm line-clamp-1">User ID: {rec.userId}</h4>
<span className={`text-xs px-2 py-1 rounded ${rec.status === 'pending' ? 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200' : 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'}`}>
{rec.status}
</span>
</div>
<p className="text-sm text-slate-600 dark:text-slate-400 line-clamp-2 mb-2">{rec.content}</p>
<p className="text-xs text-slate-500">Activity: {rec.activityPlan.substring(0, 50)}...</p>
</div>
))}
</div>
</div>
) : (
<div className="text-center py-8 text-slate-600 dark:text-slate-400">No recommendations yet</div>
)}
</div>
</div>
)}
{/* Attendance Tab */}
{activeTab === "attendance" && (
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
<div className="bg-gradient-to-r from-[#fb7a1b] to-[#22c55e] p-6 sm:p-8">
<h3 className="text-xl sm:text-2xl font-bold text-white flex items-center gap-2">
<Calendar size={28} />
Attendance Monitoring
</h3>
</div>
<div className="p-6 sm:p-8 overflow-x-auto">
{attendanceLoading ? (
<div className="text-center py-8">Loading attendance data...</div>
) : attendance.length > 0 ? (
<table className="w-full text-sm">
<thead>
<tr className="border-b border-slate-200 dark:border-slate-600">
<th className="text-left py-2 px-4 font-bold">Client ID</th>
<th className="text-left py-2 px-4 font-bold">Check In</th>
<th className="text-left py-2 px-4 font-bold">Check Out</th>
<th className="text-left py-2 px-4 font-bold">Type</th>
</tr>
</thead>
<tbody>
{attendance.slice(0, 10).map((record) => (
<tr key={record.id} className="border-b border-slate-100 dark:border-slate-700 hover:bg-slate-50 dark:hover:bg-slate-700">
<td className="py-3 px-4 line-clamp-1">{record.clientId}</td>
<td className="py-3 px-4">{new Date(record.checkInTime).toLocaleString()}</td>
<td className="py-3 px-4">{record.checkOutTime ? new Date(record.checkOutTime).toLocaleString() : '-'}</td>
<td className="py-3 px-4">
<span className="px-2 py-1 rounded-full text-xs font-bold bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200">
{record.type}
</span>
</td>
</tr>
))}
</tbody>
</table>
) : (
<div className="text-center py-8 text-slate-600 dark:text-slate-400">No attendance records</div>
)}
</div>
</div>
)}
{/* Profile Tab */}
{activeTab === "profile" && (
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
<div className="bg-gradient-to-r from-[#22c55e] to-[#2563eb] p-6 sm:p-8">
<h3 className="text-xl sm:text-2xl font-bold text-white flex items-center gap-2">
<User size={28} />
Admin Profile
</h3>
</div>
<div className="p-6 sm:p-8">
<p className="text-slate-600 dark:text-slate-400 text-lg">Profile management coming soon!</p>
</div>
</div>
)}
</div> </div>
</div> </div>
); );

View File

@ -2,7 +2,7 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useUser } from "@clerk/nextjs"; import { useUser } from "@clerk/nextjs";
import { Button } from "@/components/ui/Button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
interface UserProfile { interface UserProfile {

View File

@ -6,7 +6,7 @@ import { usePathname } from "next/navigation";
import { Home, Users, BarChart3, User, Brain } from "lucide-react"; import { Home, Users, BarChart3, User, Brain } from "lucide-react";
import { SignedIn, UserButton } from "@clerk/nextjs"; import { SignedIn, UserButton } from "@clerk/nextjs";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/Button"; import { Button } from "@/components/ui/button";
interface NavItem { interface NavItem {
href: string; href: string;

View File

@ -19,19 +19,19 @@ export function StatsCard({ title, value, change, trend, icon: Icon, color = "bl
}; };
return ( return (
<Card> <Card className="overflow-hidden h-full">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground"> <CardTitle className="text-sm font-medium text-muted-foreground line-clamp-2 break-words flex-1 pr-2">
{title} {title}
</CardTitle> </CardTitle>
<div className={`p-2 rounded-lg ${colorStyles[color]}`}> <div className={`p-2 rounded-lg ${colorStyles[color]} flex-shrink-0`}>
<Icon size={16} /> <Icon size={16} />
</div> </div>
</CardHeader> </CardHeader>
<CardContent> <CardContent className="overflow-hidden">
<div className="text-2xl font-bold">{value}</div> <div className="text-2xl font-bold line-clamp-2 break-words">{value}</div>
{change && ( {change && (
<p className="text-xs text-muted-foreground mt-1"> <p className="text-xs text-muted-foreground mt-1 line-clamp-1 break-words">
<span <span
className={`font-medium ${trend === "up" className={`font-medium ${trend === "up"
? "text-green-600" ? "text-green-600"

View File

@ -9,7 +9,7 @@ const Card = React.forwardRef<
<div <div
ref={ref} ref={ref}
className={cn( className={cn(
"rounded-xl border bg-card text-card-foreground shadow", "rounded-xl border bg-card text-card-foreground shadow overflow-hidden",
className className
)} )}
{...props} {...props}

View File

@ -1,7 +1,7 @@
"use client"; "use client";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Button } from "@/components/ui/Button"; import { Button } from "@/components/ui/button";
import { Card, CardHeader, CardContent } from "@/components/ui/card"; import { Card, CardHeader, CardContent } from "@/components/ui/card";
interface Recommendation { interface Recommendation {

View File

@ -265,42 +265,42 @@ export function UserGrid({
}; };
return ( return (
<div> <div className="w-full overflow-hidden">
<div className="flex justify-between items-center mb-4"> <div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-4">
<input <input
type="text" type="text"
placeholder="Search users..." placeholder="Search users..."
className="border border-gray-300 rounded px-4 py-2" className="border border-gray-300 dark:border-slate-600 dark:bg-slate-700 dark:text-white rounded px-4 py-2 flex-1 sm:flex-none w-full sm:w-auto"
value={searchQuery} value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)} onChange={(e) => setSearchQuery(e.target.value)}
/> />
<div className="flex gap-2"> <div className="flex gap-2 flex-wrap">
<button <button
className="bg-green-500 text-white px-4 py-2 rounded disabled:opacity-50" className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded disabled:opacity-50 text-sm"
onClick={handleEdit} onClick={handleEdit}
disabled={selectedUsers.length !== 1} disabled={selectedUsers.length !== 1}
> >
Edit User Edit
</button> </button>
<button <button
className="bg-red-500 text-white px-4 py-2 rounded disabled:opacity-50" className="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded disabled:opacity-50 text-sm"
onClick={handleDelete} onClick={handleDelete}
disabled={selectedUsers.length !== 1} disabled={selectedUsers.length !== 1}
> >
Delete User Delete
</button> </button>
<button <button
className="bg-yellow-500 text-white px-4 py-2 rounded disabled:opacity-50" className="bg-orange-500 hover:bg-orange-600 text-white px-4 py-2 rounded disabled:opacity-50 text-sm"
onClick={handleBulkDelete} onClick={handleBulkDelete}
disabled={selectedUsers.length === 0} disabled={selectedUsers.length === 0}
> >
Bulk Delete Bulk
</button> </button>
</div> </div>
</div> </div>
<div <div
className="ag-theme-alpine" className="ag-theme-alpine dark:ag-theme-alpine-dark w-full overflow-hidden rounded-lg"
style={{ height: "600px", width: "100%" }} style={{ height: "400px", width: "100%" }}
> >
<AgGridReact<User> {...gridOptions} ref={gridRef} /> <AgGridReact<User> {...gridOptions} ref={gridRef} />
</div> </div>

View File

@ -2,7 +2,7 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { UserGrid } from "@/components/users/UserGrid"; 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"; import { Card, CardHeader, CardContent } from "@/components/ui/card";
interface User { interface User {