first commit

This commit is contained in:
2026-01-17 14:17:42 +05:30
commit 0f194eb9e7
328 changed files with 73544 additions and 0 deletions

View File

@@ -0,0 +1,195 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function DELETE(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
// Check if category exists
const existingCategory = await prisma.category.findUnique({
where: { id },
include: {
_count: {
select: {
products: true
}
}
}
})
if (!existingCategory) {
return NextResponse.json(
{ error: 'Category not found' },
{ status: 404 }
)
}
// Check if category has products
if (existingCategory._count.products > 0) {
return NextResponse.json(
{
error: 'Cannot delete category with associated products',
productCount: existingCategory._count.products
},
{ status: 400 }
)
}
// Delete the category
await prisma.category.delete({
where: { id }
})
return NextResponse.json({
message: 'Category deleted successfully',
deletedCategory: {
id: existingCategory.id,
name: existingCategory.name
}
})
} catch (error: any) {
console.error('Error deleting category:', error)
return NextResponse.json(
{ error: 'Failed to delete category' },
{ status: 500 }
)
}
}
export async function PATCH(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
const body = await request.json()
const { name, description, image, isActive } = body
// Check if category exists
const existingCategory = await prisma.category.findUnique({
where: { id }
})
if (!existingCategory) {
return NextResponse.json(
{ error: 'Category not found' },
{ status: 404 }
)
}
// If name is being updated, check for uniqueness
if (name && name !== existingCategory.name) {
const nameExists = await prisma.category.findUnique({
where: { name }
})
if (nameExists) {
return NextResponse.json(
{ error: 'Category name already exists' },
{ status: 400 }
)
}
}
// Update the category
const updatedCategory = await prisma.category.update({
where: { id },
data: {
...(name !== undefined && { name }),
...(description !== undefined && { description }),
...(image !== undefined && { image }),
...(isActive !== undefined && { isActive })
},
include: {
_count: {
select: {
products: true
}
}
}
})
return NextResponse.json(updatedCategory)
} catch (error: any) {
console.error('Error updating category:', error)
// Handle Prisma unique constraint errors
if (error.code === 'P2002') {
return NextResponse.json(
{ error: 'Category name already exists' },
{ status: 400 }
)
}
return NextResponse.json(
{ error: 'Failed to update category' },
{ status: 500 }
)
}
}
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
const category = await prisma.category.findUnique({
where: { id },
include: {
_count: {
select: {
products: true
}
},
products: {
select: {
id: true,
name: true,
price: true,
isActive: true
},
take: 10 // Limit to first 10 products for preview
}
}
})
if (!category) {
return NextResponse.json(
{ error: 'Category not found' },
{ status: 404 }
)
}
return NextResponse.json(category)
} catch (error: any) {
console.error('Error fetching category:', error)
return NextResponse.json(
{ error: 'Failed to fetch category' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,73 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { searchParams } = new URL(request.url)
const search = searchParams.get('search')
const categories = await prisma.category.findMany({
where: search ? {
name: {
contains: search,
mode: 'insensitive'
}
} : {},
include: {
_count: {
select: {
products: true
}
}
},
orderBy: {
createdAt: 'desc'
}
})
return NextResponse.json(categories)
} catch (error) {
console.error('Error fetching categories:', error)
return NextResponse.json(
{ error: 'Failed to fetch categories' },
{ status: 500 }
)
}
}
export async function POST(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const body = await request.json()
const { name, description, image, isActive } = body
const category = await prisma.category.create({
data: {
name,
description,
image,
isActive
}
})
return NextResponse.json(category)
} catch (error) {
console.error('Error creating category:', error)
return NextResponse.json(
{ error: 'Failed to create category' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,43 @@
import { NextRequest, NextResponse } from "next/server";
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET() {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const settings = await prisma.commissionSettings.findMany({
orderBy: { level: 'asc' },
})
return NextResponse.json(settings)
} catch (error) {
console.error('Commission settings API error:', error)
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}
}
export async function POST(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { level, percentage, isActive } = await request.json()
const setting = await prisma.commissionSettings.upsert({
where: { level },
update: { percentage, isActive },
create: { level, percentage, isActive },
})
return NextResponse.json(setting)
} catch (error) {
console.error('Create commission setting error:', error)
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}
}

View File

@@ -0,0 +1,37 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function PATCH(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id: commissionId } = await params
const { status } = await request.json()
// Validate status
if (!['PENDING', 'APPROVED', 'PAID', 'CANCELLED'].includes(status)) {
return NextResponse.json({ error: 'Invalid status' }, { status: 400 })
}
const commission = await prisma.commission.update({
where: { id: commissionId },
data: { status }
})
return NextResponse.json(commission)
} catch (error) {
console.error('Error updating commission:', error)
return NextResponse.json(
{ error: 'Failed to update commission' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,77 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET(request: NextRequest) {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const url = new URL(request.url)
const status = url.searchParams.get('status')
const type = url.searchParams.get('type')
const level = url.searchParams.get('level')
const page = parseInt(url.searchParams.get('page') || '1')
const limit = parseInt(url.searchParams.get('limit') || '50')
const where: any = {}
if (status && status !== 'all') {
where.status = status
}
if (type && type !== 'all') {
where.type = type
}
if (level && level !== 'all') {
where.level = parseInt(level)
}
const commissions = await prisma.commission.findMany({
where,
include: {
user: {
select: {
id: true,
name: true,
email: true
}
},
fromUser: {
select: {
id: true,
name: true,
email: true
}
}
},
orderBy: {
createdAt: 'desc'
},
skip: (page - 1) * limit,
take: limit
})
const total = await prisma.commission.count({ where })
return NextResponse.json({
commissions: commissions || [],
pagination: {
page,
limit,
total,
pages: Math.ceil(total / limit)
}
})
} catch (error) {
console.error('Error fetching admin commissions:', error)
return NextResponse.json({
commissions: [],
pagination: { page: 1, limit: 50, total: 0, pages: 0 }
})
}
}

View File

@@ -0,0 +1,36 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id: settingId } = await params
const { level, percentage, isActive } = await request.json()
const setting = await prisma.commissionSettings.update({
where: { id: settingId },
data: {
level,
percentage,
isActive
}
})
return NextResponse.json(setting)
} catch (error) {
console.error('Error updating commission setting:', error)
return NextResponse.json(
{ error: 'Failed to update commission setting' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,41 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
let settings = await prisma.commissionSettings.findMany({
orderBy: { level: 'asc' }
})
// If no settings exist, create default ones
if (settings.length === 0) {
const defaultSettings = [
{ level: 1, percentage: 10, isActive: true },
{ level: 2, percentage: 5, isActive: true },
{ level: 3, percentage: 3, isActive: true },
{ level: 4, percentage: 2, isActive: true },
{ level: 5, percentage: 1, isActive: true }
]
await prisma.commissionSettings.createMany({
data: defaultSettings
})
settings = await prisma.commissionSettings.findMany({
orderBy: { level: 'asc' }
})
}
return NextResponse.json({ settings: settings || [] })
} catch (error) {
console.error('Error fetching commission settings:', error)
return NextResponse.json({ settings: [] })
}
}

View File

@@ -0,0 +1,66 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Get total commissions count
const totalCommissions = await prisma.commission.count()
// Get amounts by status
const [pendingResult, approvedResult, paidResult] = await Promise.all([
prisma.commission.aggregate({
where: { status: 'PENDING' },
_sum: { amount: true }
}),
prisma.commission.aggregate({
where: { status: 'APPROVED' },
_sum: { amount: true }
}),
prisma.commission.aggregate({
where: { status: 'PAID' },
_sum: { amount: true }
})
])
// Get this month commissions
const startOfMonth = new Date()
startOfMonth.setDate(1)
startOfMonth.setHours(0, 0, 0, 0)
const thisMonthCommissions = await prisma.commission.count({
where: {
createdAt: { gte: startOfMonth }
}
})
// Calculate average commission
const totalAmount = (pendingResult._sum.amount || 0) + (approvedResult._sum.amount || 0) + (paidResult._sum.amount || 0)
const averageCommission = totalCommissions > 0 ? totalAmount / totalCommissions : 0
return NextResponse.json({
totalCommissions: totalCommissions || 0,
pendingAmount: pendingResult._sum.amount || 0,
approvedAmount: approvedResult._sum.amount || 0,
paidAmount: paidResult._sum.amount || 0,
thisMonthCommissions: thisMonthCommissions || 0,
averageCommission: averageCommission || 0
})
} catch (error) {
console.error('Error fetching commission stats:', error)
return NextResponse.json({
totalCommissions: 0,
pendingAmount: 0,
approvedAmount: 0,
paidAmount: 0,
thisMonthCommissions: 0,
averageCommission: 0
})
}
}

View File

@@ -0,0 +1,34 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const orders = await prisma.order.findMany({
take: 10,
orderBy: { createdAt: 'desc' },
include: {
user: {
select: {
name: true,
email: true
}
}
}
})
return NextResponse.json({ orders })
} catch (error) {
console.error('Error fetching recent orders:', error)
return NextResponse.json(
{ error: 'Failed to fetch recent orders' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,128 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Get current date ranges
const now = new Date()
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
const startOfLastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1)
const endOfLastMonth = new Date(now.getFullYear(), now.getMonth(), 0)
// Get current totals
const [totalUsers, totalProducts, totalOrders, totalRevenueResult] = await Promise.all([
prisma.user.count(),
prisma.product.count({ where: { isActive: true } }),
prisma.order.count(),
prisma.order.aggregate({
where: { status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] } },
_sum: { total: true }
})
])
// Get last month data for comparison
const [lastMonthUsers, lastMonthProducts, lastMonthOrders, lastMonthRevenueResult] = await Promise.all([
prisma.user.count({
where: {
joinedAt: {
gte: startOfLastMonth,
lte: endOfLastMonth
}
}
}),
prisma.product.count({
where: {
isActive: true,
createdAt: {
gte: startOfLastMonth,
lte: endOfLastMonth
}
}
}),
prisma.order.count({
where: {
createdAt: {
gte: startOfLastMonth,
lte: endOfLastMonth
}
}
}),
prisma.order.aggregate({
where: {
status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] },
createdAt: {
gte: startOfLastMonth,
lte: endOfLastMonth
}
},
_sum: { total: true }
})
])
// Get this month data
const [thisMonthUsers, thisMonthProducts, thisMonthOrders, thisMonthRevenueResult] = await Promise.all([
prisma.user.count({
where: {
joinedAt: { gte: startOfMonth }
}
}),
prisma.product.count({
where: {
isActive: true,
createdAt: { gte: startOfMonth }
}
}),
prisma.order.count({
where: {
createdAt: { gte: startOfMonth }
}
}),
prisma.order.aggregate({
where: {
status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] },
createdAt: { gte: startOfMonth }
},
_sum: { total: true }
})
])
// Calculate growth percentages
const calculateGrowth = (current: number, previous: number) => {
if (previous === 0) return current > 0 ? 100 : 0
return ((current - previous) / previous) * 100
}
const totalRevenue = totalRevenueResult._sum.total || 0
const lastMonthRevenue = lastMonthRevenueResult._sum.total || 0
const thisMonthRevenue = thisMonthRevenueResult._sum.total || 0
const userGrowth = calculateGrowth(thisMonthUsers, lastMonthUsers)
const productGrowth = calculateGrowth(thisMonthProducts, lastMonthProducts)
const orderGrowth = calculateGrowth(thisMonthOrders, lastMonthOrders)
const revenueGrowth = calculateGrowth(thisMonthRevenue, lastMonthRevenue)
return NextResponse.json({
totalUsers,
totalProducts,
totalOrders,
totalRevenue,
userGrowth,
productGrowth,
orderGrowth,
revenueGrowth
})
} catch (error) {
console.error('Error fetching dashboard stats:', error)
return NextResponse.json(
{ error: 'Failed to fetch dashboard stats' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,59 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Get top products by order count this month
const startOfMonth = new Date()
startOfMonth.setDate(1)
startOfMonth.setHours(0, 0, 0, 0)
const topProducts = await prisma.product.findMany({
take: 5,
include: {
orderItems: {
where: {
order: {
createdAt: { gte: startOfMonth },
status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] }
}
},
select: {
quantity: true,
price: true
}
}
}
})
const productsWithStats = topProducts.map(product => {
const orderCount = product.orderItems.reduce((sum, item) => sum + item.quantity, 0)
const totalRevenue = product.orderItems.reduce((sum, item) => sum + (item.price * item.quantity), 0)
return {
id: product.id,
name: product.name,
price: product.price,
orderCount,
totalRevenue
}
}).filter(product => product.orderCount > 0)
.sort((a, b) => b.orderCount - a.orderCount)
.slice(0, 5)
return NextResponse.json({ products: productsWithStats })
} catch (error) {
console.error('Error fetching top products:', error)
return NextResponse.json(
{ error: 'Failed to fetch top products' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,148 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
const order = await prisma.order.findUnique({
where: { id },
include: {
user: {
select: {
id: true,
name: true,
email: true,
phone: true
}
},
orderItems: {
include: {
product: {
select: {
id: true,
name: true,
images: true,
sku: true,
price: true
}
}
}
},
shippingAddress: {
select: {
firstName: true,
lastName: true,
company: true,
address1: true,
address2: true,
city: true,
state: true,
zipCode: true,
country: true,
phone: true
}
}
}
})
if (!order) {
return NextResponse.json({ error: 'Order not found' }, { status: 404 })
}
return NextResponse.json(order)
} catch (error) {
console.error('Error fetching order:', error)
return NextResponse.json(
{ error: 'Failed to fetch order' },
{ status: 500 }
)
}
}
export async function PATCH(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
const body = await request.json()
const { status } = body
if (!['PENDING', 'PAID', 'SHIPPED', 'DELIVERED', 'CANCELLED'].includes(status)) {
return NextResponse.json(
{ error: 'Invalid status' },
{ status: 400 }
)
}
const order = await prisma.order.update({
where: { id },
data: {
status,
updatedAt: new Date()
},
include: {
user: {
select: {
id: true,
name: true,
email: true,
phone: true
}
},
orderItems: {
include: {
product: {
select: {
id: true,
name: true,
images: true,
sku: true,
price: true
}
}
}
},
shippingAddress: {
select: {
firstName: true,
lastName: true,
company: true,
address1: true,
address2: true,
city: true,
state: true,
zipCode: true,
country: true,
phone: true
}
}
}
})
return NextResponse.json(order)
} catch (error) {
console.error('Error updating order:', error)
return NextResponse.json(
{ error: 'Failed to update order' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,48 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function PATCH(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const body = await request.json()
const { orderIds, status } = body
if (!orderIds || !Array.isArray(orderIds) || orderIds.length === 0) {
return NextResponse.json(
{ error: 'Order IDs are required' },
{ status: 400 }
)
}
if (!['PENDING', 'PAID', 'SHIPPED', 'DELIVERED', 'CANCELLED'].includes(status)) {
return NextResponse.json(
{ error: 'Invalid status' },
{ status: 400 }
)
}
await prisma.order.updateMany({
where: {
id: { in: orderIds }
},
data: {
status,
updatedAt: new Date()
}
})
return NextResponse.json({ success: true })
} catch (error) {
console.error('Error in bulk order update:', error)
return NextResponse.json(
{ error: 'Failed to perform bulk update' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,72 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { searchParams } = new URL(request.url)
const search = searchParams.get('search')
const status = searchParams.get('status')
const page = parseInt(searchParams.get('page') || '1')
const limit = parseInt(searchParams.get('limit') || '20')
const skip = (page - 1) * limit
const where: any = {}
if (search) {
where.OR = [
{ id: { contains: search, mode: 'insensitive' } },
{ razorpayOrderId: { contains: search, mode: 'insensitive' } },
{ user: { name: { contains: search, mode: 'insensitive' } } },
{ user: { email: { contains: search, mode: 'insensitive' } } }
]
}
if (status) {
where.status = status
}
const orders = await prisma.order.findMany({
where,
include: {
user: {
select: {
id: true,
name: true,
email: true
}
},
orderItems: {
include: {
product: {
select: {
id: true,
name: true,
images: true
}
}
}
}
},
orderBy: {
createdAt: 'desc'
},
skip,
take: limit
})
return NextResponse.json(orders)
} catch (error) {
console.error('Error fetching orders:', error)
return NextResponse.json(
{ error: 'Failed to fetch orders' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,66 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id: payoutId } = await params
const { status, adminNotes } = await request.json()
// Validate status
if (!['APPROVED', 'REJECTED', 'PAID'].includes(status)) {
return NextResponse.json({ error: 'Invalid status' }, { status: 400 })
}
const result = await prisma.$transaction(async (tx) => {
// Get the payout
const payout = await tx.payout.findUnique({
where: { id: payoutId },
include: { user: true }
})
if (!payout) {
throw new Error('Payout not found')
}
// Update payout
const updatedPayout = await tx.payout.update({
where: { id: payoutId },
data: {
status,
adminNotes,
updatedAt: new Date()
}
})
// If rejecting, restore the amount to user's wallet
if (status === 'REJECTED') {
await tx.wallet.update({
where: { userId: payout.userId },
data: {
balance: { increment: payout.amount }
}
})
}
return updatedPayout
})
return NextResponse.json(result)
} catch (error) {
console.error('Error updating payout:', error)
return NextResponse.json(
{ error: error instanceof Error ? error.message : 'Failed to update payout' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,59 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET(request: NextRequest) {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const url = new URL(request.url)
const status = url.searchParams.get('status')
const page = parseInt(url.searchParams.get('page') || '1')
const limit = parseInt(url.searchParams.get('limit') || '50')
const where: any = {}
if (status && status !== 'all') {
where.status = status
}
const payouts = await prisma.payout.findMany({
where,
include: {
user: {
select: {
id: true,
name: true,
email: true
}
}
},
orderBy: {
createdAt: 'desc'
},
skip: (page - 1) * limit,
take: limit
})
const total = await prisma.payout.count({ where })
return NextResponse.json({
payouts,
pagination: {
page,
limit,
total,
pages: Math.ceil(total / limit)
}
})
} catch (error) {
console.error('Error fetching admin payouts:', error)
return NextResponse.json(
{ error: 'Failed to fetch payouts' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,45 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Get total requests
const totalRequests = await prisma.payout.count()
// Get amounts by status
const [pendingResult, approvedResult, paidResult] = await Promise.all([
prisma.payout.aggregate({
where: { status: 'PENDING' },
_sum: { amount: true }
}),
prisma.payout.aggregate({
where: { status: 'APPROVED' },
_sum: { amount: true }
}),
prisma.payout.aggregate({
where: { status: 'PAID' },
_sum: { amount: true }
})
])
return NextResponse.json({
totalRequests,
pendingAmount: pendingResult._sum.amount || 0,
approvedAmount: approvedResult._sum.amount || 0,
paidAmount: paidResult._sum.amount || 0
})
} catch (error) {
console.error('Error fetching payout stats:', error)
return NextResponse.json(
{ error: 'Failed to fetch payout stats' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,114 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
const product = await prisma.product.findUnique({
where: { id },
include: {
category: {
select: {
id: true,
name: true
}
}
}
})
if (!product) {
return NextResponse.json({ error: 'Product not found' }, { status: 404 })
}
return NextResponse.json(product)
} catch (error) {
console.error('Error fetching product:', error)
return NextResponse.json(
{ error: 'Failed to fetch product' },
{ status: 500 }
)
}
}
export async function PUT(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
const body = await request.json()
const { name, description, price, discount, images, stock, sku, isActive, categoryId, weight } = body
const product = await prisma.product.update({
where: { id },
data: {
name,
description,
price,
discount,
images,
stock,
sku,
isActive,
categoryId,
weight,
slug: name.toLowerCase().replace(/[^a-z0-9\s-]/g, '').replace(/\s+/g, '-').replace(/-+/g, '-') + '-' + Date.now()
},
include: {
category: true
}
})
return NextResponse.json(product)
} catch (error) {
console.error('Error updating product:', error)
return NextResponse.json(
{ error: 'Failed to update product' },
{ status: 500 }
)
}
}
export async function DELETE(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
await prisma.product.delete({
where: { id }
})
return NextResponse.json({ success: true })
} catch (error) {
console.error('Error deleting product:', error)
return NextResponse.json(
{ error: 'Failed to delete product' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,61 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function PATCH(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const body = await request.json()
const { productIds, action } = body
if (!productIds || !Array.isArray(productIds) || productIds.length === 0) {
return NextResponse.json(
{ error: 'Product IDs are required' },
{ status: 400 }
)
}
let updateData: any = {}
switch (action) {
case 'activate':
updateData = { isActive: true }
break
case 'deactivate':
updateData = { isActive: false }
break
case 'delete':
await prisma.product.deleteMany({
where: {
id: { in: productIds }
}
})
return NextResponse.json({ success: true })
default:
return NextResponse.json(
{ error: 'Invalid action' },
{ status: 400 }
)
}
await prisma.product.updateMany({
where: {
id: { in: productIds }
},
data: updateData
})
return NextResponse.json({ success: true })
} catch (error) {
console.error('Error in bulk action:', error)
return NextResponse.json(
{ error: 'Failed to perform bulk action' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,195 @@
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
import { auth } from '@/auth'
export async function GET(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json(
{ success: false, message: 'Unauthorized' },
{ status: 401 }
)
}
const { searchParams } = new URL(request.url)
const selectedColumns = searchParams.get('columns')?.split(',') || []
const categoryId = searchParams.get('categoryId') || ''
const isActive = searchParams.get('isActive') || ''
const limit = parseInt(searchParams.get('limit') || '10000')
// Build where clause based on filters
const whereClause: any = {}
if (categoryId && categoryId !== '') {
whereClause.categoryId = categoryId
}
if (isActive && isActive !== '') {
whereClause.isActive = isActive === 'true'
}
// Fetch products with category information
const products = await prisma.product.findMany({
where: whereClause,
include: {
category: {
select: { name: true }
}
},
take: limit,
orderBy: { createdAt: 'desc' }
})
// Transform data based on selected columns
const transformedData = products.map(product => {
const baseData = {
id: product.id,
name: product.name,
description: product.description || '',
price: product.price,
discount: product.discount,
stock: product.stock,
sku: product.sku,
slug: product.slug,
isActive: product.isActive,
categoryName: product.category?.name || '',
categoryId: product.categoryId || '',
brand: product.brand || '',
origin: product.origin || '',
weight: product.weight || '',
images: product.images.join(', '),
createdAt: product.createdAt.toISOString(),
updatedAt: product.updatedAt.toISOString(),
// Calculated fields
finalPrice: product.price - (product.price * product.discount / 100),
discountAmount: product.price * product.discount / 100,
stockStatus: product.stock > 10 ? 'In Stock' : product.stock > 0 ? 'Low Stock' : 'Out of Stock',
status: product.isActive ? 'Active' : 'Inactive'
}
// Filter by selected columns if specified
if (selectedColumns.length > 0) {
const filteredData: any = {}
selectedColumns.forEach(column => {
if (column in baseData) {
filteredData[column] = (baseData as any)[column]
}
})
return filteredData
}
return baseData
})
return NextResponse.json({
success: true,
data: transformedData,
count: transformedData.length
})
} catch (error) {
console.error('Product export error:', error)
return NextResponse.json(
{ success: false, message: 'Internal server error' },
{ status: 500 }
)
}
}
export async function POST(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json(
{ success: false, message: 'Unauthorized' },
{ status: 401 }
)
}
const { columns = [], filters = {} } = await request.json()
const selectedColumns = columns || []
const categoryId = filters.categoryId || ''
const isActive = filters.isActive || ''
const limit = parseInt(filters.limit || '10000')
// Build where clause based on filters
const whereClause: any = {}
if (categoryId && categoryId !== '') {
whereClause.categoryId = categoryId
}
if (isActive && isActive !== '') {
whereClause.isActive = isActive === 'true'
}
// Fetch products with category information
const products = await prisma.product.findMany({
where: whereClause,
include: {
category: {
select: { name: true }
}
},
take: limit,
orderBy: { createdAt: 'desc' }
})
// Transform data based on selected columns
const transformedData = products.map(product => {
const baseData = {
id: product.id,
name: product.name,
description: product.description || '',
price: product.price,
discount: product.discount,
stock: product.stock,
sku: product.sku,
slug: product.slug,
isActive: product.isActive,
categoryName: product.category?.name || '',
categoryId: product.categoryId || '',
brand: product.brand || '',
origin: product.origin || '',
weight: product.weight || '',
images: product.images.join(', '),
createdAt: product.createdAt.toISOString(),
updatedAt: product.updatedAt.toISOString(),
// Calculated fields
finalPrice: product.price - (product.price * product.discount / 100),
discountAmount: product.price * product.discount / 100,
stockStatus: product.stock > 10 ? 'In Stock' : product.stock > 0 ? 'Low Stock' : 'Out of Stock',
status: product.isActive ? 'Active' : 'Inactive'
}
// Filter by selected columns if specified
if (selectedColumns.length > 0) {
const filteredData: any = {}
selectedColumns.forEach((column: string) => {
if (column in baseData) {
filteredData[column] = (baseData as any)[column]
}
})
return filteredData
}
return baseData
})
return NextResponse.json({
success: true,
data: transformedData,
count: transformedData.length
})
} catch (error) {
console.error('Product export error:', error)
return NextResponse.json(
{ success: false, message: 'Internal server error' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,162 @@
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
import { auth } from '@/auth'
export async function POST(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json(
{ success: false, message: 'Unauthorized' },
{ status: 401 }
)
}
const { data } = await request.json()
if (!Array.isArray(data) || data.length === 0) {
return NextResponse.json(
{ success: false, message: 'No products provided' },
{ status: 400 }
)
}
let successCount = 0
let errorCount = 0
const errors: string[] = []
// Process products in batches to avoid overwhelming the database
const batchSize = 50
const batches: any[][] = []
for (let i = 0; i < data.length; i += batchSize) {
batches.push(data.slice(i, i + batchSize))
}
for (let batchIndex = 0; batchIndex < batches.length; batchIndex++) {
const batch = batches[batchIndex]
try {
const productsToCreate: any[] = []
const productsToUpdate: any[] = []
for (let index = 0; index < batch.length; index++) {
const productData = batch[index]
try {
// Validate required fields
if (!productData.name || !productData.price) {
errors.push(`Row ${batchIndex * batchSize + index + 1}: Missing required fields (name, price)`)
errorCount++
continue
}
// Check if category exists
let categoryId: string | undefined = undefined
if (productData.categoryId) {
const category = await prisma.category.findUnique({
where: { id: productData.categoryId }
})
if (category) {
categoryId = category.id
} else {
errors.push(`Row ${batchIndex * batchSize + index + 1}: Category with ID '${productData.categoryId}' not found`)
errorCount++
continue
}
}
// Generate SKU if not provided
const sku = productData.sku || `PROD-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
// Prepare product data
const productPayload = {
name: productData.name.trim(),
description: productData.description || '',
price: parseFloat(productData.price) || 0,
discount: parseFloat(productData.discount) || 0,
stock: parseInt(productData.stock) || 0,
sku: sku,
slug: productData.slug || productData.name.toLowerCase().replace(/[^a-z0-9]+/g, '-'),
isActive: productData.active === 'true' || productData.active === true || productData.active === '1' || true,
...(categoryId && { categoryId }),
brand: productData.brand || '',
origin: productData.origin || '',
weight: productData.weight || '',
images: productData.images ? (typeof productData.images === 'string' ? productData.images.split(',').map((img: string) => img.trim()) : []) : []
}
// Check if product exists (by SKU)
const existingProduct = await prisma.product.findUnique({
where: { sku: productPayload.sku }
})
if (existingProduct) {
// Update existing product - create update data without null categoryId
const updatePayload = { ...productPayload }
if (!categoryId) {
delete updatePayload.categoryId
}
productsToUpdate.push({
where: { id: existingProduct.id },
data: updatePayload
})
} else {
// Create new product
productsToCreate.push(productPayload)
}
} catch (error) {
errors.push(`Row ${batchIndex * batchSize + index + 1}: ${error instanceof Error ? error.message : 'Processing error'}`)
errorCount++
}
}
// Create new products
if (productsToCreate.length > 0) {
try {
await prisma.product.createMany({
data: productsToCreate,
skipDuplicates: true
})
successCount += productsToCreate.length
} catch (error) {
errors.push(`Batch ${batchIndex + 1}: Failed to create products - ${error instanceof Error ? error.message : 'Unknown error'}`)
errorCount += productsToCreate.length
}
}
// Update existing products
for (const updateData of productsToUpdate) {
try {
await prisma.product.update(updateData)
successCount++
} catch (error) {
errors.push(`Failed to update product: ${error instanceof Error ? error.message : 'Unknown error'}`)
errorCount++
}
}
} catch (error) {
errors.push(`Batch ${batchIndex + 1}: ${error instanceof Error ? error.message : 'Batch processing error'}`)
errorCount += batch.length
}
}
return NextResponse.json({
success: errorCount === 0,
message: errorCount === 0 ?
`Successfully imported ${successCount} products` :
`Import completed with errors. ${successCount} successful, ${errorCount} failed.`,
successCount,
errorCount,
errors: errors.slice(0, 50) // Limit to first 50 errors
})
} catch (error) {
console.error('Product import error:', error)
return NextResponse.json(
{ success: false, message: 'Internal server error' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,54 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function POST(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const body = await request.json()
const { name, description, price, discount, images, stock, sku, isActive, categoryId } = body
// Check if SKU already exists
const existingSku = await prisma.product.findUnique({
where: { sku }
})
if (existingSku) {
return NextResponse.json(
{ error: 'SKU already exists' },
{ status: 400 }
)
}
const product = await prisma.product.create({
data: {
name,
description,
price,
discount,
images,
stock,
sku,
isActive,
categoryId,
slug: name.toLowerCase().replace(/[^a-z0-9\s-]/g, '').replace(/\s+/g, '-').replace(/-+/g, '-') + '-' + Date.now()
},
include: {
category: true
}
})
return NextResponse.json(product)
} catch (error) {
console.error('Error creating product:', error)
return NextResponse.json(
{ error: 'Failed to create product' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,35 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
interface Props {
params: Promise<{ id: string }>
}
export async function POST(
request: NextRequest,
{ params }: Props
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
const review = await prisma.review.update({
where: { id },
data: { isApproved: true }
})
return NextResponse.json({ review })
} catch (error) {
console.error('Error approving review:', error)
return NextResponse.json(
{ error: 'Failed to approve review' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,35 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
interface Props {
params: Promise<{ id: string }>
}
export async function POST(
request: NextRequest,
{ params }: Props
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
const review = await prisma.review.update({
where: { id },
data: { isApproved: false }
})
return NextResponse.json({ review })
} catch (error) {
console.error('Error rejecting review:', error)
return NextResponse.json(
{ error: 'Failed to reject review' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,44 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
interface Props {
params: Promise<{ id: string }>
}
export async function DELETE(
request: NextRequest,
{ params }: Props
) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
// Delete related records first
await prisma.reviewHelpfulVote.deleteMany({
where: { reviewId: id }
})
await prisma.reviewReport.deleteMany({
where: { reviewId: id }
})
// Delete the review
await prisma.review.delete({
where: { id }
})
return NextResponse.json({ success: true })
} catch (error) {
console.error('Error deleting review:', error)
return NextResponse.json(
{ error: 'Failed to delete review' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,91 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { searchParams } = new URL(request.url)
const page = parseInt(searchParams.get('page') || '1')
const limit = parseInt(searchParams.get('limit') || '20')
const search = searchParams.get('search') || ''
const approved = searchParams.get('approved')
const skip = (page - 1) * limit
const where: any = {}
if (search) {
where.OR = [
{ title: { contains: search, mode: 'insensitive' } },
{ comment: { contains: search, mode: 'insensitive' } },
{ user: { name: { contains: search, mode: 'insensitive' } } },
{ product: { name: { contains: search, mode: 'insensitive' } } }
]
}
if (approved !== null && approved !== undefined) {
where.isApproved = approved === 'true'
}
const [reviews, total] = await Promise.all([
prisma.review.findMany({
where,
include: {
user: {
select: {
id: true,
name: true,
email: true
}
},
product: {
select: {
id: true,
name: true
}
},
_count: {
select: {
helpfulVotedBy: true,
reportedBy: true
}
}
},
orderBy: {
createdAt: 'desc'
},
skip,
take: limit
}),
prisma.review.count({ where })
])
const reviewsWithCounts = reviews.map(review => ({
...review,
helpfulVotes: review._count.helpfulVotedBy,
reportCount: review._count.reportedBy
}))
return NextResponse.json({
reviews: reviewsWithCounts,
pagination: {
page,
limit,
total,
pages: Math.ceil(total / limit)
}
})
} catch (error) {
console.error('Error fetching admin reviews:', error)
return NextResponse.json(
{ error: 'Failed to fetch reviews' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,62 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const categories = await prisma.category.findMany({
include: {
_count: {
select: {
products: true
}
}
},
orderBy: { name: 'asc' }
})
const categoriesWithCount = categories.map(category => ({
id: category.id,
name: category.name,
description: category.description,
image: category.image,
isActive: category.isActive,
productCount: category._count.products
}))
return NextResponse.json({ categories: categoriesWithCount })
} catch (error) {
console.error('Error fetching categories:', error)
return NextResponse.json({ categories: [] })
}
}
export async function POST(request: NextRequest) {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { name, description, image, isActive } = await request.json()
const category = await prisma.category.create({
data: { name, description, image, isActive }
})
return NextResponse.json(category)
} catch (error) {
console.error('Error creating category:', error)
return NextResponse.json(
{ error: 'Failed to create category' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,46 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const settings = await prisma.commissionSettings.findMany({
orderBy: { level: 'asc' }
})
return NextResponse.json({ settings })
} catch (error) {
console.error('Error fetching commission settings:', error)
return NextResponse.json({ settings: [] })
}
}
export async function POST(request: NextRequest) {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { level, percentage, isActive } = await request.json()
const setting = await prisma.commissionSettings.create({
data: { level, percentage, isActive }
})
return NextResponse.json(setting)
} catch (error) {
console.error('Error creating commission setting:', error)
return NextResponse.json(
{ error: 'Failed to create commission setting' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,128 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
import { clearSettingsCache } from '@/lib/settings'
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Get or create system settings
let settings = await prisma.systemSettings.findFirst()
if (!settings) {
// Create default settings if none exist
settings = await prisma.systemSettings.create({
data: {
siteName: 'Padmaaja Rasooi',
siteDescription: 'Premium Rice Products & Quality Grains',
supportEmail: 'support@padmaajarasooi.com',
minimumPayout: 100,
enableReferrals: true,
enableCommissions: true,
maintenanceMode: false,
allowRegistration: true
}
})
}
return NextResponse.json({
siteName: settings.siteName,
siteDescription: settings.siteDescription,
supportEmail: settings.supportEmail,
minimumPayout: settings.minimumPayout,
enableReferrals: settings.enableReferrals,
enableCommissions: settings.enableCommissions,
maintenanceMode: settings.maintenanceMode,
allowRegistration: settings.allowRegistration
})
} catch (error) {
console.error('Error fetching system settings:', error)
return NextResponse.json(
{ error: 'Failed to fetch system settings' },
{ status: 500 }
)
}
}
export async function PUT(request: NextRequest) {
try {
const session = await auth()
if (!session?.user?.id || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const {
siteName,
siteDescription,
supportEmail,
minimumPayout,
enableReferrals,
enableCommissions,
maintenanceMode,
allowRegistration
} = await request.json()
// Get or create system settings
let settings = await prisma.systemSettings.findFirst()
if (!settings) {
// Create new settings
settings = await prisma.systemSettings.create({
data: {
siteName,
siteDescription,
supportEmail,
minimumPayout,
enableReferrals,
enableCommissions,
maintenanceMode,
allowRegistration
}
})
} else {
// Update existing settings
settings = await prisma.systemSettings.update({
where: { id: settings.id },
data: {
siteName,
siteDescription,
supportEmail,
minimumPayout,
enableReferrals,
enableCommissions,
maintenanceMode,
allowRegistration
}
})
}
// Clear the settings cache so new values are fetched
clearSettingsCache()
return NextResponse.json({
success: true,
settings: {
siteName: settings.siteName,
siteDescription: settings.siteDescription,
supportEmail: settings.supportEmail,
minimumPayout: settings.minimumPayout,
enableReferrals: settings.enableReferrals,
enableCommissions: settings.enableCommissions,
maintenanceMode: settings.maintenanceMode,
allowRegistration: settings.allowRegistration
}
})
} catch (error) {
console.error('Error updating system settings:', error)
return NextResponse.json(
{ error: 'Failed to update system settings' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,76 @@
import { NextRequest, NextResponse } from "next/server";
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
export async function GET(request: NextRequest) {
try {
const session = await auth()
if (!session?.user || session.user.role !== 'ADMIN') {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { searchParams } = new URL(request.url)
const page = parseInt(searchParams.get('page') || '1')
const limit = parseInt(searchParams.get('limit') || '10')
const search = searchParams.get('search')
const role = searchParams.get('role')
const skip = (page - 1) * limit
const where: any = {}
if (search) {
where.OR = [
{ name: { contains: search, mode: 'insensitive' } },
{ email: { contains: search, mode: 'insensitive' } },
]
}
if (role) {
where.role = role
}
const [users, total] = await Promise.all([
prisma.user.findMany({
where,
select: {
id: true,
name: true,
email: true,
role: true,
isActive: true,
joinedAt: true,
referralCode: true,
referrer: {
select: {
name: true,
email: true,
},
},
_count: {
select: {
referrals: true,
orders: true,
},
},
},
skip,
take: limit,
orderBy: { joinedAt: 'desc' },
}),
prisma.user.count({ where }),
])
return NextResponse.json({
users,
pagination: {
page,
limit,
total,
pages: Math.ceil(total / limit),
},
})
} catch (error) {
console.error('Admin users API error:', error)
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}
}