basic stracture and auth

in memory db :)
This commit is contained in:
dimitar committed 2025-11-07 20:59:56 +01:00
commit 3a554ba434
71 files changed
+28535

No files matched your search

+11
View File
@@ -0,0 +1,11 @@
import { AnalyticsDashboard } from '@/components/analytics/AnalyticsDashboard'
export default function AnalyticsPage() {
return (
<main className="min-h-screen bg-gray-50">
<div className="container mx-auto px-4 py-8">
<AnalyticsDashboard />
</div>
</main>
)
}
@@ -0,0 +1,47 @@
import { NextRequest, NextResponse } from 'next/server'
import bcrypt from 'bcryptjs'
import { users } from '../../../../lib/database'
export async function POST(request: NextRequest) {
try {
const { email, password } = await request.json()
if (!email || !password) {
return NextResponse.json(
{ error: 'Email and password are required' },
{ status: 400 }
)
}
const user = users.find(u => u.email === email)
if (!user) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
)
}
const isValidPassword = await bcrypt.compare(password, user.password)
if (!isValidPassword) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
)
}
const { password: _, ...userWithoutPassword } = user
return NextResponse.json({
message: 'Login successful',
user: userWithoutPassword
})
} catch (error) {
console.error('Login error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}
@@ -0,0 +1,73 @@
import { NextRequest, NextResponse } from 'next/server'
import bcrypt from 'bcryptjs'
import { users, clients } from '../../../../lib/database'
export async function POST(request: NextRequest) {
try {
const { email, password, firstName, lastName, phone } = await request.json()
if (!email || !password || !firstName || !lastName) {
return NextResponse.json(
{ error: 'Missing required fields' },
{ status: 400 }
)
}
const existingUser = users.find(u => u.email === email)
if (existingUser) {
return NextResponse.json(
{ error: 'User already exists' },
{ status: 409 }
)
}
const hashedPassword = await bcrypt.hash(password, 10)
const userId = Math.random().toString(36).substr(2, 9)
const newUser = {
id: userId,
email,
firstName,
lastName,
password: hashedPassword,
phone,
role: 'client',
createdAt: new Date(),
updatedAt: new Date(),
}
users.push(newUser)
const newClient = {
id: Math.random().toString(36).substr(2, 9),
userId,
membershipType: 'basic',
membershipStatus: 'active',
joinDate: new Date(),
}
clients.push(newClient)
const { password: _, ...userWithoutPassword } = newUser
return NextResponse.json(
{
message: 'User registered successfully',
user: { ...userWithoutPassword, client: newClient }
},
{ status: 201 }
)
} catch (error) {
console.error('Registration error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}
export async function GET() {
const usersWithoutPassword = users.map(({ password: _, ...user }) => user)
return NextResponse.json({ users: usersWithoutPassword })
}
+28
View File
@@ -0,0 +1,28 @@
import { NextRequest, NextResponse } from 'next/server'
import { users, clients } from '../../../lib/database'
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const role = searchParams.get('role')
let filteredUsers = users
if (role) {
filteredUsers = users.filter(user => user.role === role)
}
const usersWithClients = filteredUsers.map(({ password: _, ...user }) => {
const client = clients.find(c => c.userId === user.id)
return { ...user, client }
})
return NextResponse.json({ users: usersWithClients })
} catch (error) {
console.error('Get users error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}
+3
View File
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
+22
View File
@@ -0,0 +1,22 @@
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'FitAI Admin',
description: 'Fitness management admin dashboard',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
)
}
+64
View File
@@ -0,0 +1,64 @@
'use client'
import Link from 'next/link'
import { UserManagement } from '@/components/users/UserManagement'
import { AnalyticsDashboard } from '@/components/analytics/AnalyticsDashboard'
export default function Home() {
return (
<main className="min-h-screen bg-gray-50">
<div className="container mx-auto px-4 py-8">
<div className="flex justify-between items-center mb-8">
<h1 className="text-4xl font-bold text-gray-900">
FitAI Admin Dashboard
</h1>
<nav className="flex gap-4">
<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
href="/analytics"
className="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors"
>
Analytics
</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>
</div>
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-xl font-semibold mb-4">Payment Tracking</h2>
<p className="text-gray-600">Monitor payments and subscriptions</p>
</div>
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-xl font-semibold mb-4">Attendance</h2>
<p className="text-gray-600">Track client attendance and habits</p>
</div>
</div>
<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">
<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">
<AnalyticsDashboard />
</div>
</div>
</div>
</div>
</main>
)
}
+11
View File
@@ -0,0 +1,11 @@
import { UserManagement } from '@/components/users/UserManagement'
export default function UsersPage() {
return (
<main className="min-h-screen bg-gray-50">
<div className="container mx-auto px-4 py-8">
<UserManagement />
</div>
</main>
)
}