initial commit
This commit is contained in:
28
app/admin/analytics/page.tsx
Normal file
28
app/admin/analytics/page.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
'use client'
|
||||
|
||||
import AdminLayout from '@/components/admin/AdminLayout'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
|
||||
export default function AdminAnalyticsPage() {
|
||||
return (
|
||||
<AdminLayout>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">Analytics</h1>
|
||||
<p className="text-gray-600 mt-2">Advanced analytics and insights</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Analytics Dashboard</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex items-center justify-center h-64">
|
||||
<p className="text-gray-500">Analytics dashboard coming soon...</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</AdminLayout>
|
||||
)
|
||||
}
|
||||
19
app/admin/billing/page.tsx
Normal file
19
app/admin/billing/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
'use client'
|
||||
|
||||
import AdminLayout from '@/components/admin/AdminLayout'
|
||||
import BillingManagement from '@/components/admin/BillingManagement'
|
||||
|
||||
export default function AdminBillingPage() {
|
||||
return (
|
||||
<AdminLayout>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">Billing Management</h1>
|
||||
<p className="text-gray-600 mt-2">Manage billing records, payments, and refunds</p>
|
||||
</div>
|
||||
|
||||
<BillingManagement />
|
||||
</div>
|
||||
</AdminLayout>
|
||||
)
|
||||
}
|
||||
256
app/admin/page.tsx
Normal file
256
app/admin/page.tsx
Normal file
@@ -0,0 +1,256 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import AdminLayout from '@/components/admin/AdminLayout'
|
||||
import DashboardStats from '@/components/admin/DashboardStats'
|
||||
import RecentActivity from '@/components/admin/RecentActivity'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { toast } from '@/hooks/use-toast'
|
||||
|
||||
interface DashboardData {
|
||||
users: {
|
||||
total: number
|
||||
active: number
|
||||
newThisMonth: number
|
||||
verified: number
|
||||
verificationRate: string
|
||||
}
|
||||
revenue: {
|
||||
total: number
|
||||
monthly: number
|
||||
weekly: number
|
||||
}
|
||||
transactions: {
|
||||
total: number
|
||||
monthly: number
|
||||
}
|
||||
services: {
|
||||
total: number
|
||||
active: number
|
||||
breakdown: Array<{
|
||||
_id: string
|
||||
count: number
|
||||
revenue: number
|
||||
}>
|
||||
}
|
||||
developerRequests: {
|
||||
total: number
|
||||
pending: number
|
||||
}
|
||||
recentActivity: {
|
||||
users: Array<{
|
||||
_id: string
|
||||
name: string
|
||||
email: string
|
||||
siliconId: string
|
||||
createdAt: string
|
||||
}>
|
||||
transactions: Array<{
|
||||
_id: string
|
||||
type: string
|
||||
amount: number
|
||||
description: string
|
||||
status: string
|
||||
createdAt: string
|
||||
userId: {
|
||||
name: string
|
||||
email: string
|
||||
siliconId: string
|
||||
}
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export default function AdminDashboard() {
|
||||
const [data, setData] = useState<DashboardData | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
fetchDashboardData()
|
||||
}, [])
|
||||
|
||||
const fetchDashboardData = async () => {
|
||||
try {
|
||||
const token =
|
||||
localStorage.getItem('token') ||
|
||||
document.cookie
|
||||
.split('; ')
|
||||
.find((row) => row.startsWith('token='))
|
||||
?.split('=')[1]
|
||||
|
||||
const response = await fetch('/api/admin/dashboard', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch dashboard data')
|
||||
}
|
||||
|
||||
const dashboardData = await response.json()
|
||||
setData(dashboardData)
|
||||
} catch (error) {
|
||||
console.error('Dashboard fetch error:', error)
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: 'Failed to load dashboard data',
|
||||
variant: 'destructive',
|
||||
})
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<AdminLayout>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">Dashboard</h1>
|
||||
<p className="text-gray-600 mt-2">Overview of your SiliconPin platform</p>
|
||||
</div>
|
||||
|
||||
{/* Loading skeletons */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{Array.from({ length: 6 }).map((_, i) => (
|
||||
<Card key={i}>
|
||||
<CardHeader>
|
||||
<Skeleton className="h-4 w-24" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Skeleton className="h-8 w-16 mb-2" />
|
||||
<Skeleton className="h-3 w-32" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<Skeleton className="h-6 w-32" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
{Array.from({ length: 3 }).map((_, i) => (
|
||||
<div key={i} className="flex justify-between">
|
||||
<div>
|
||||
<Skeleton className="h-4 w-24 mb-1" />
|
||||
<Skeleton className="h-3 w-32" />
|
||||
</div>
|
||||
<Skeleton className="h-3 w-16" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<Skeleton className="h-6 w-32" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
{Array.from({ length: 3 }).map((_, i) => (
|
||||
<div key={i} className="flex justify-between">
|
||||
<div>
|
||||
<Skeleton className="h-4 w-24 mb-1" />
|
||||
<Skeleton className="h-3 w-32" />
|
||||
</div>
|
||||
<Skeleton className="h-3 w-16" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</AdminLayout>
|
||||
)
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return (
|
||||
<AdminLayout>
|
||||
<div className="flex items-center justify-center h-64">
|
||||
<p className="text-gray-500">Failed to load dashboard data</p>
|
||||
</div>
|
||||
</AdminLayout>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<AdminLayout>
|
||||
<div className="space-y-6">
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="w-10 h-10 bg-gradient-to-r from-blue-500 to-indigo-600 rounded-xl flex items-center justify-center">
|
||||
<span className="text-white font-bold">📊</span>
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">Dashboard</h1>
|
||||
<p className="text-gray-600 dark:text-gray-400 mt-1">
|
||||
Overview of your SiliconPin platform
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Stats Cards */}
|
||||
<DashboardStats stats={data} />
|
||||
|
||||
{/* Service Breakdown */}
|
||||
<Card className="border border-gray-200 dark:border-gray-700 shadow-lg bg-white dark:bg-gray-800">
|
||||
<CardHeader className="pb-4">
|
||||
<CardTitle className="text-xl font-semibold text-gray-800 dark:text-white flex items-center space-x-2">
|
||||
<span>🔧</span>
|
||||
<span>Service Breakdown</span>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{data.services.breakdown.map((service, index) => {
|
||||
const colors = [
|
||||
'from-blue-500 to-blue-600',
|
||||
'from-indigo-500 to-indigo-600',
|
||||
'from-purple-500 to-purple-600',
|
||||
'from-pink-500 to-pink-600',
|
||||
'from-red-500 to-red-600',
|
||||
'from-orange-500 to-orange-600',
|
||||
'from-yellow-500 to-yellow-600',
|
||||
'from-green-500 to-green-600',
|
||||
'from-teal-500 to-teal-600',
|
||||
'from-cyan-500 to-cyan-600',
|
||||
]
|
||||
const colorClass = colors[index % colors.length]
|
||||
|
||||
return (
|
||||
<div
|
||||
key={service._id}
|
||||
className={`bg-gradient-to-br ${colorClass} p-5 rounded-xl text-white shadow-lg hover:shadow-xl transition-all duration-200 hover:scale-105`}
|
||||
>
|
||||
<h3 className="font-semibold text-white capitalize text-sm">
|
||||
{service._id.replace('_', ' ')}
|
||||
</h3>
|
||||
<p className="text-2xl font-bold text-white mt-2">{service.count}</p>
|
||||
<p className="text-sm text-white/90 mt-1">
|
||||
₹{service.revenue.toLocaleString()} revenue
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Recent Activity */}
|
||||
<RecentActivity
|
||||
recentUsers={data.recentActivity.users}
|
||||
recentTransactions={data.recentActivity.transactions}
|
||||
/>
|
||||
</div>
|
||||
</AdminLayout>
|
||||
)
|
||||
}
|
||||
19
app/admin/reports/page.tsx
Normal file
19
app/admin/reports/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
'use client'
|
||||
|
||||
import AdminLayout from '@/components/admin/AdminLayout'
|
||||
import ReportsManagement from '@/components/admin/ReportsManagement'
|
||||
|
||||
export default function AdminReportsPage() {
|
||||
return (
|
||||
<AdminLayout>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">Reports & Analytics</h1>
|
||||
<p className="text-gray-600 mt-2">Generate and export comprehensive system reports</p>
|
||||
</div>
|
||||
|
||||
<ReportsManagement />
|
||||
</div>
|
||||
</AdminLayout>
|
||||
)
|
||||
}
|
||||
21
app/admin/services/page.tsx
Normal file
21
app/admin/services/page.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
'use client'
|
||||
|
||||
import AdminLayout from '@/components/admin/AdminLayout'
|
||||
import ServiceManagement from '@/components/admin/ServiceManagement'
|
||||
|
||||
export default function AdminServicesPage() {
|
||||
return (
|
||||
<AdminLayout>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">Service Management</h1>
|
||||
<p className="text-gray-600 mt-2">
|
||||
Manage deployments, developer requests, and service status
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ServiceManagement />
|
||||
</div>
|
||||
</AdminLayout>
|
||||
)
|
||||
}
|
||||
19
app/admin/settings/page.tsx
Normal file
19
app/admin/settings/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
'use client'
|
||||
|
||||
import AdminLayout from '@/components/admin/AdminLayout'
|
||||
import SystemSettings from '@/components/admin/SystemSettings'
|
||||
|
||||
export default function AdminSettingsPage() {
|
||||
return (
|
||||
<AdminLayout>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">System Settings</h1>
|
||||
<p className="text-gray-600 mt-2">Configure system-wide settings and preferences</p>
|
||||
</div>
|
||||
|
||||
<SystemSettings />
|
||||
</div>
|
||||
</AdminLayout>
|
||||
)
|
||||
}
|
||||
19
app/admin/users/page.tsx
Normal file
19
app/admin/users/page.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
'use client'
|
||||
|
||||
import AdminLayout from '@/components/admin/AdminLayout'
|
||||
import UserManagement from '@/components/admin/UserManagement'
|
||||
|
||||
export default function AdminUsersPage() {
|
||||
return (
|
||||
<AdminLayout>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">User Management</h1>
|
||||
<p className="text-gray-600 mt-2">Manage users, roles, and permissions</p>
|
||||
</div>
|
||||
|
||||
<UserManagement />
|
||||
</div>
|
||||
</AdminLayout>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user