admin crud ops implemented partialy
This commit is contained in:
dimitar committed 2025-11-09 18:11:40 +01:00
1 parent c357de515f
commit 9d2bfda0ca
21 files changed
+6108 -3172

No files matched your search

+148 -18
View File
@@ -1,32 +1,162 @@
import { NextRequest, NextResponse } from 'next/server'
import { getDatabase } from '../../../lib/database/index'
import { NextRequest, NextResponse } from "next/server";
import { getDatabase } from "../../../lib/database/index";
import bcrypt from "bcryptjs";
export async function GET(request: NextRequest) {
try {
const db = await getDatabase()
const { searchParams } = new URL(request.url)
const role = searchParams.get('role')
const db = await getDatabase();
const { searchParams } = new URL(request.url);
const role = searchParams.get("role");
let users = await db.getAllUsers()
let users = await db.getAllUsers();
if (role) {
users = users.filter(user => user.role === role)
users = users.filter((user) => user.role === role);
}
const usersWithClients = await Promise.all(
users.map(async (user) => {
const { password: _, ...userWithoutPassword } = user
const client = await db.getClientByUserId(user.id)
return { ...userWithoutPassword, client }
})
)
const { password: _, ...userWithoutPassword } = user;
const client = await db.getClientByUserId(user.id);
return { ...userWithoutPassword, client };
}),
);
return NextResponse.json({ users: usersWithClients })
return NextResponse.json({ users: usersWithClients });
} catch (error) {
console.error('Get users error:', error)
console.error("Get users error:", error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
{ error: "Internal server error" },
{ status: 500 },
);
}
}
}
export async function POST(request: NextRequest) {
try {
const db = await getDatabase();
const body = await request.json();
const { email, password, firstName, lastName, role, phone } = body;
if (!email || !password || !firstName || !lastName || !role) {
return NextResponse.json(
{ error: "Missing required fields" },
{ status: 400 },
);
}
// Check if user already exists
const existingUser = await db.getUserByEmail(email);
if (existingUser) {
return NextResponse.json(
{ error: "User with this email already exists" },
{ status: 409 },
);
}
// Hash password
const hashedPassword = await bcrypt.hash(password, 12);
// Create user
const userId = await db.createUser({
email,
password: hashedPassword,
firstName,
lastName,
role,
phone,
});
return NextResponse.json({ userId }, { status: 201 });
} catch (error) {
console.error("Create user error:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 },
);
}
}
export async function PUT(request: NextRequest) {
try {
const db = await getDatabase();
const body = await request.json();
const { id, email, firstName, lastName, role, phone } = body;
if (!id) {
return NextResponse.json(
{ error: "User ID is required" },
{ status: 400 },
);
}
// Get existing user
const existingUser = await db.getUserById(id);
if (!existingUser) {
return NextResponse.json({ error: "User not found" }, { status: 404 });
}
// Check if email is being changed and if it's already taken
if (email && email !== existingUser.email) {
const userWithEmail = await db.getUserByEmail(email);
if (userWithEmail) {
return NextResponse.json(
{ error: "Email already in use" },
{ status: 409 },
);
}
}
// Update user
await db.updateUser(id, {
email: email || existingUser.email,
firstName: firstName || existingUser.firstName,
lastName: lastName || existingUser.lastName,
role: role || existingUser.role,
phone: phone !== undefined ? phone : existingUser.phone,
});
return NextResponse.json({ success: true });
} catch (error) {
console.error("Update user error:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 },
);
}
}
export async function DELETE(request: NextRequest) {
try {
const db = await getDatabase();
const { searchParams } = new URL(request.url);
const id = searchParams.get("id");
const body = await request.json().catch(() => ({}));
const { ids } = body;
if (ids && Array.isArray(ids)) {
// Bulk delete
await Promise.all(ids.map((userId: string) => db.deleteUser(userId)));
return NextResponse.json({ success: true, deleted: ids.length });
} else if (id) {
// Single delete
const user = await db.getUserById(id);
if (!user) {
return NextResponse.json({ error: "User not found" }, { status: 404 });
}
await db.deleteUser(id);
return NextResponse.json({ success: true });
} else {
return NextResponse.json(
{ error: "User ID or IDs array required" },
{ status: 400 },
);
}
} catch (error) {
console.error("Delete user error:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 },
);
}
}
+18 -14
View File
@@ -1,8 +1,8 @@
'use client'
"use client";
import Link from 'next/link'
import { UserManagement } from '@/components/users/UserManagement'
import { AnalyticsDashboard } from '@/components/analytics/AnalyticsDashboard'
import Link from "next/link";
import { UserManagement } from "@/components/users/UserManagement";
import { AnalyticsDashboard } from "@/components/analytics/AnalyticsDashboard";
export default function Home() {
return (
@@ -13,13 +13,13 @@ export default function Home() {
FitAI Admin Dashboard
</h1>
<nav className="flex gap-4">
<Link
<Link
href="/users"
className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
>
User Management
</Link>
<Link
<Link
href="/analytics"
className="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors"
>
@@ -27,11 +27,13 @@ export default function Home() {
</Link>
</nav>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-xl font-semibold mb-4">Client Management</h2>
<p className="text-gray-600">Manage fitness clients and their profiles</p>
<p className="text-gray-600">
Manage fitness clients and their profiles
</p>
</div>
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-xl font-semibold mb-4">Payment Tracking</h2>
@@ -45,20 +47,22 @@ export default function Home() {
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-2xl font-semibold mb-6">Recent User Activity</h2>
<div className="h-96">
<h2 className="text-2xl font-semibold mb-6">
Recent User Activity
</h2>
<div>
<UserManagement />
</div>
</div>
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-2xl font-semibold mb-6">Quick Analytics</h2>
<div className="h-96">
<div>
<AnalyticsDashboard />
</div>
</div>
</div>
</div>
</main>
)
}
);
}