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,56 @@
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) {
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 skip = (page - 1) * limit
const [commissions, total] = await Promise.all([
prisma.commission.findMany({
where: { userId: session.user.id },
include: {
fromUser: {
select: {
name: true,
email: true
}
}
},
orderBy: { createdAt: 'desc' },
skip,
take: limit
}),
prisma.commission.count({ where: { userId: session.user.id } })
])
return NextResponse.json({
commissions: commissions.map(commission => ({
id: commission.id,
amount: commission.amount,
level: commission.level,
type: commission.type,
status: commission.status,
createdAt: commission.createdAt,
fromUser: commission.fromUser
})),
total,
pages: Math.ceil(total / limit)
})
} catch (error) {
console.error('Error fetching commissions:', error)
return NextResponse.json(
{ error: 'Failed to fetch commissions' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,171 @@
import { NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
interface TeamMember {
id: string
name: string
email: string
joinedAt: string
totalEarnings: number
directReferrals: number
level: number
children?: TeamMember[]
}
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const userId = session.user.id
// Build genealogy tree
const genealogyTree = await buildGenealogyTree(userId, 0)
// Calculate stats
const teamSize = await calculateTeamSize(userId)
const totalVolume = await calculateTeamVolume(userId)
const levels = await calculateNetworkLevels(userId)
return NextResponse.json({
user: genealogyTree,
teamSize,
totalVolume,
levels
})
} catch (error) {
console.error('Error fetching genealogy data:', error)
return NextResponse.json(
{ error: 'Failed to fetch genealogy data' },
{ status: 500 }
)
}
}
async function buildGenealogyTree(userId: string, level: number): Promise<TeamMember> {
const user = await prisma.user.findUnique({
where: { id: userId },
include: {
wallet: true,
referrals: {
select: {
id: true,
name: true,
email: true,
joinedAt: true
}
}
}
})
if (!user) {
throw new Error('User not found')
}
// Get direct referrals count
const directReferrals = await prisma.user.count({
where: { referrerId: userId }
})
const teamMember: TeamMember = {
id: user.id,
name: user.name || 'Unknown',
email: user.email,
joinedAt: user.joinedAt.toISOString(),
totalEarnings: user.wallet?.totalEarnings || 0,
directReferrals,
level,
children: []
}
// Recursively build children (limit to 5 levels to prevent infinite recursion)
if (level < 5 && user.referrals.length > 0) {
for (const referral of user.referrals) {
const childTree = await buildGenealogyTree(referral.id, level + 1)
teamMember.children!.push(childTree)
}
}
return teamMember
}
async function calculateTeamSize(userId: string): Promise<number> {
const getAllTeamMembers = async (id: string): Promise<string[]> => {
const directReferrals = await prisma.user.findMany({
where: { referrerId: id },
select: { id: true }
})
let allMembers = directReferrals.map(r => r.id)
for (const referral of directReferrals) {
const subTeam = await getAllTeamMembers(referral.id)
allMembers = [...allMembers, ...subTeam]
}
return allMembers
}
const teamMembers = await getAllTeamMembers(userId)
return teamMembers.length
}
async function calculateTeamVolume(userId: string): Promise<number> {
const getAllTeamMembers = async (id: string): Promise<string[]> => {
const directReferrals = await prisma.user.findMany({
where: { referrerId: id },
select: { id: true }
})
let allMembers = directReferrals.map(r => r.id)
for (const referral of directReferrals) {
const subTeam = await getAllTeamMembers(referral.id)
allMembers = [...allMembers, ...subTeam]
}
return allMembers
}
const teamMembers = await getAllTeamMembers(userId)
if (teamMembers.length === 0) return 0
const volume = await prisma.order.aggregate({
where: {
userId: { in: teamMembers },
status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] }
},
_sum: { total: true }
})
return volume._sum.total || 0
}
async function calculateNetworkLevels(userId: string): Promise<number> {
const getMaxLevel = async (id: string, currentLevel: number): Promise<number> => {
const directReferrals = await prisma.user.findMany({
where: { referrerId: id },
select: { id: true }
})
if (directReferrals.length === 0) {
return currentLevel
}
let maxLevel = currentLevel + 1
for (const referral of directReferrals) {
const level = await getMaxLevel(referral.id, currentLevel + 1)
maxLevel = Math.max(maxLevel, level)
}
return maxLevel
}
return await getMaxLevel(userId, 0)
}

View File

@@ -0,0 +1,73 @@
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?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { amount, bankDetails } = await request.json()
// Check wallet balance
const wallet = await prisma.wallet.findUnique({
where: { userId: session.user.id }
})
if (!wallet || wallet.balance < amount) {
return NextResponse.json({ error: 'Insufficient balance' }, { status: 400 })
}
// Create payout request
const payout = await prisma.payout.create({
data: {
userId: session.user.id,
amount,
bankDetails,
status: 'PENDING'
}
})
// Update wallet balance (deduct the requested amount)
await prisma.wallet.update({
where: { userId: session.user.id },
data: {
balance: { decrement: amount }
}
})
return NextResponse.json(payout)
} catch (error) {
console.error('Error creating payout request:', error)
return NextResponse.json(
{ error: 'Failed to create payout request' },
{ status: 500 }
)
}
}
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const payouts = await prisma.payout.findMany({
where: { userId: session.user.id },
orderBy: { createdAt: 'desc' }
})
return NextResponse.json(payouts)
} catch (error) {
console.error('Error fetching payouts:', error)
return NextResponse.json(
{ error: 'Failed to fetch payouts' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,80 @@
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
import { CommissionService } from '@/lib/commission'
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { id } = await params
// Get user profile
const user = await prisma.user.findUnique({
where: { id },
select: {
id: true,
name: true,
email: true,
phone: true,
address: true,
joinedAt: true,
role: true,
referralCode: true,
isActive: true
}
})
if (!user) {
return NextResponse.json({ error: 'User not found' }, { status: 404 })
}
// Get team stats
const stats = await CommissionService.getTeamStats(id)
// Get wallet info
const wallet = await prisma.wallet.findUnique({
where: { userId: id }
})
// Get recent commissions
const recentCommissions = await prisma.commission.findMany({
where: { userId: id },
orderBy: { createdAt: 'desc' },
take: 5,
select: {
id: true,
amount: true,
level: true,
type: true,
status: true,
createdAt: true
}
})
const profile = {
...user,
stats: {
...stats,
totalEarnings: wallet?.totalEarnings || 0,
walletBalance: wallet?.balance || 0
},
recentCommissions
}
return NextResponse.json(profile)
} catch (error) {
console.error('Error fetching user profile:', error)
return NextResponse.json(
{ error: 'Failed to fetch profile' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,70 @@
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) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Get user's direct referrals
const referrals = await prisma.user.findMany({
where: {
referrerId: session.user.id
},
select: {
id: true,
name: true,
email: true,
phone: true,
joinedAt: true,
isActive: true,
orders: {
where: {
status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] }
},
select: {
total: true
}
},
// Get commissions earned from this referral
commissionsFrom: {
where: {
userId: session.user.id,
status: { in: ['APPROVED', 'PAID'] }
},
select: {
amount: true
}
}
}
})
const formattedReferrals = referrals.map(referral => ({
id: referral.id,
name: referral.name || 'User',
email: referral.email,
phone: referral.phone,
joinedAt: referral.joinedAt,
isActive: referral.isActive,
totalOrders: referral.orders.length,
totalSpent: referral.orders.reduce((sum, order) => sum + order.total, 0),
commissionEarned: referral.commissionsFrom.reduce((sum, comm) => sum + comm.amount, 0),
status: referral.isActive ? 'ACTIVE' : 'INACTIVE'
}))
return NextResponse.json({
referrals: formattedReferrals
})
} catch (error) {
console.error('Error fetching referrals:', error)
return NextResponse.json(
{ error: 'Failed to fetch referrals' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,89 @@
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) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const userId = session.user.id
// Get total referrals
const totalReferrals = await prisma.user.count({
where: { referrerId: userId }
})
// Get active referrals
const activeReferrals = await prisma.user.count({
where: {
referrerId: userId,
isActive: true
}
})
// Get pending referrals
const pendingReferrals = await prisma.user.count({
where: {
referrerId: userId,
isActive: false
}
})
// Get total commission earned from referrals
const totalCommissionResult = await prisma.commission.aggregate({
where: {
userId,
status: { in: ['APPROVED', 'PAID'] }
},
_sum: {
amount: true
}
})
// Get this month's stats
const now = new Date()
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
const thisMonthReferrals = await prisma.user.count({
where: {
referrerId: userId,
joinedAt: {
gte: startOfMonth
}
}
})
const thisMonthCommissionResult = await prisma.commission.aggregate({
where: {
userId,
status: { in: ['APPROVED', 'PAID'] },
createdAt: {
gte: startOfMonth
}
},
_sum: {
amount: true
}
})
return NextResponse.json({
totalReferrals,
activeReferrals,
pendingReferrals,
totalCommissionEarned: totalCommissionResult._sum.amount || 0,
thisMonthReferrals,
thisMonthCommission: thisMonthCommissionResult._sum.amount || 0
})
} catch (error) {
console.error('Error fetching referral stats:', error)
return NextResponse.json(
{ error: 'Failed to fetch referral stats' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,159 @@
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) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { searchParams } = new URL(request.url)
const range = parseInt(searchParams.get('range') || '30')
const type = searchParams.get('type') || 'all'
const userId = session.user.id
const startDate = new Date()
startDate.setDate(startDate.getDate() - range)
// Get commission data
const commissions = await prisma.commission.findMany({
where: {
userId,
createdAt: { gte: startDate }
},
include: {
fromUser: {
select: { name: true, email: true }
}
},
orderBy: { createdAt: 'desc' }
})
const totalCommissions = commissions.reduce((sum, c) => sum + c.amount, 0)
// Calculate commission growth
const previousPeriodStart = new Date(startDate)
previousPeriodStart.setDate(previousPeriodStart.getDate() - range)
const previousCommissions = await prisma.commission.findMany({
where: {
userId,
createdAt: {
gte: previousPeriodStart,
lt: startDate
}
}
})
const previousTotal = previousCommissions.reduce((sum, c) => sum + c.amount, 0)
const growth = previousTotal > 0 ? ((totalCommissions - previousTotal) / previousTotal) * 100 : 0
// Commission by level
const commissionsByLevel = commissions.reduce((acc, c) => {
const existing = acc.find(item => item.level === c.level)
if (existing) {
existing.amount += c.amount
existing.count += 1
} else {
acc.push({ level: c.level, amount: c.amount, count: 1 })
}
return acc
}, [] as { level: number; amount: number; count: number }[])
// Get team data
const directReferrals = await prisma.user.findMany({
where: { referrerId: userId },
select: {
id: true,
joinedAt: true,
orders: {
where: {
createdAt: { gte: startDate },
status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] }
}
}
}
})
// Get all team members recursively
const getAllTeamMembers = async (id: string): Promise<string[]> => {
const refs = await prisma.user.findMany({
where: { referrerId: id },
select: { id: true }
})
let allMembers = refs.map(r => r.id)
for (const ref of refs) {
const subTeam = await getAllTeamMembers(ref.id)
allMembers = [...allMembers, ...subTeam]
}
return allMembers
}
const allTeamMemberIds = await getAllTeamMembers(userId)
// Team metrics
const activeMembers = directReferrals.filter(r => r.orders.length > 0).length
const newThisMonth = directReferrals.filter(r =>
new Date(r.joinedAt) >= new Date(new Date().getFullYear(), new Date().getMonth(), 1)
).length
// Sales data
const userOrders = await prisma.order.findMany({
where: {
userId,
createdAt: { gte: startDate },
status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] }
}
})
const teamOrders = await prisma.order.findMany({
where: {
userId: { in: allTeamMemberIds },
createdAt: { gte: startDate },
status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] }
}
})
const personalVolume = userOrders.reduce((sum, o) => sum + o.total, 0)
const teamVolume = teamOrders.reduce((sum, o) => sum + o.total, 0)
const reportData = {
commissions: {
total: totalCommissions,
thisMonth: commissions.filter(c =>
new Date(c.createdAt) >= new Date(new Date().getFullYear(), new Date().getMonth(), 1)
).reduce((sum, c) => sum + c.amount, 0),
lastMonth: previousTotal,
growth,
byLevel: commissionsByLevel.sort((a, b) => a.level - b.level),
recent: commissions.slice(0, 10)
},
team: {
totalMembers: allTeamMemberIds.length,
activeMembers,
newThisMonth,
byLevel: [{ level: 1, count: directReferrals.length }] // Simplified for now
},
sales: {
totalVolume: personalVolume + teamVolume,
personalVolume,
teamVolume,
ordersCount: userOrders.length + teamOrders.length
}
}
return NextResponse.json(reportData)
} catch (error) {
console.error('Error fetching reports:', error)
return NextResponse.json(
{ error: 'Failed to fetch reports' },
{ status: 500 }
)
}
}

119
app/api/dashboard/route.ts Normal file
View File

@@ -0,0 +1,119 @@
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) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const userId = session.user.id
// Get user's wallet
const wallet = await prisma.wallet.findUnique({
where: { userId }
})
// Get commission stats
const [totalEarnings, pendingCommissions, thisMonthEarnings] = await Promise.all([
prisma.commission.aggregate({
where: {
userId,
status: { in: ['APPROVED', 'PAID'] }
},
_sum: { amount: true }
}),
prisma.commission.aggregate({
where: {
userId,
status: 'PENDING'
},
_sum: { amount: true }
}),
prisma.commission.aggregate({
where: {
userId,
status: { in: ['APPROVED', 'PAID'] },
createdAt: {
gte: new Date(new Date().getFullYear(), new Date().getMonth(), 1)
}
},
_sum: { amount: true }
})
])
// Get referral stats
const [totalReferrals, activeReferrals] = await Promise.all([
prisma.user.count({
where: { referrerId: userId }
}),
prisma.user.count({
where: {
referrerId: userId,
isActive: true
}
})
])
// Get order stats
const totalOrders = await prisma.order.count({
where: { userId }
})
// Get recent commissions
const recentCommissions = await prisma.commission.findMany({
where: { userId },
include: {
fromUser: {
select: {
name: true,
email: true
}
}
},
orderBy: { createdAt: 'desc' },
take: 5
})
// Get recent orders
const recentOrders = await prisma.order.findMany({
where: { userId },
include: {
orderItems: {
include: {
product: {
select: {
name: true
}
}
}
}
},
orderBy: { createdAt: 'desc' },
take: 5
})
const stats = {
totalEarnings: totalEarnings._sum.amount || 0,
pendingCommissions: pendingCommissions._sum.amount || 0,
thisMonthEarnings: thisMonthEarnings._sum.amount || 0,
currentBalance: wallet?.balance || 0,
totalReferrals,
activeReferrals,
totalOrders,
recentCommissions,
recentOrders
}
return NextResponse.json({ stats })
} 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,48 @@
import { NextResponse } from 'next/server'
import { auth } from '@/auth'
import { CommissionService } from '@/lib/commission'
import { prisma } from '@/lib/prisma'
export async function GET() {
try {
const session = await auth()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const userId = session.user.id
// Get team stats
const teamStats = await CommissionService.getTeamStats(userId)
// Get wallet info
const wallet = await prisma.wallet.findUnique({
where: { userId }
})
// Get pending commissions
const pendingCommissions = await prisma.commission.aggregate({
where: {
userId,
status: 'PENDING'
},
_sum: { amount: true }
})
const stats = {
...teamStats,
totalEarnings: wallet?.totalEarnings || 0,
walletBalance: wallet?.balance || 0,
pendingCommissions: pendingCommissions._sum.amount || 0
}
return NextResponse.json(stats)
} catch (error) {
console.error('Error fetching dashboard stats:', error)
return NextResponse.json(
{ error: 'Failed to fetch stats' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,100 @@
import { 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) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const userId = session.user.id
// Get direct referrals
const directReferrals = await prisma.user.findMany({
where: { referrerId: userId },
select: {
id: true,
name: true,
email: true,
role: true,
joinedAt: true,
referrals: {
select: {
id: true
}
}
},
orderBy: { joinedAt: 'desc' }
})
// Get team statistics by levels
const getAllTeamMembers = async (id: string, level: number = 1, maxLevel: number = 5): Promise<string[]> => {
if (level > maxLevel) return []
const refs = await prisma.user.findMany({
where: { referrerId: id },
select: { id: true }
})
let allMembers = refs.map(r => r.id)
if (level < maxLevel) {
for (const ref of refs) {
const subTeam = await getAllTeamMembers(ref.id, level + 1, maxLevel)
allMembers = [...allMembers, ...subTeam]
}
}
return allMembers
}
// Calculate team size per level
const levels = []
for (let level = 1; level <= 5; level++) {
if (level === 1) {
levels.push({ level, count: directReferrals.length })
} else {
// Get members at specific level
const getLevelMembers = async (parentIds: string[], targetLevel: number, currentLevel: number = 1): Promise<string[]> => {
if (currentLevel === targetLevel) return parentIds
const nextLevel = await prisma.user.findMany({
where: { referrerId: { in: parentIds } },
select: { id: true }
})
if (nextLevel.length === 0 || currentLevel >= targetLevel) return []
return getLevelMembers(nextLevel.map(u => u.id), targetLevel, currentLevel + 1)
}
const levelMemberIds = await getLevelMembers([userId], level)
levels.push({ level, count: levelMemberIds.length })
}
}
const allTeamMemberIds = await getAllTeamMembers(userId)
const teamData = {
directReferrals: directReferrals.map(ref => ({
...ref,
referrals: ref.referrals || []
})),
teamStats: {
totalTeamSize: allTeamMemberIds.length,
levels
}
}
return NextResponse.json(teamData)
} catch (error) {
console.error('Error fetching team data:', error)
return NextResponse.json(
{ error: 'Failed to fetch team data' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,71 @@
import { 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) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const userId = session.user.id
// Get wallet info
const wallet = await prisma.wallet.findUnique({
where: { userId }
})
// Mock transaction history (you can implement proper transaction tracking)
const commissions = await prisma.commission.findMany({
where: { userId },
orderBy: { createdAt: 'desc' },
take: 20,
include: {
fromUser: {
select: { name: true }
}
}
})
const payouts = await prisma.payout.findMany({
where: { userId },
orderBy: { createdAt: 'desc' },
take: 20
})
// Combine and format transactions
const transactions = [
...commissions.map(commission => ({
id: commission.id,
type: 'COMMISSION' as const,
amount: commission.amount,
description: `Level ${commission.level} commission from ${commission.fromUser.name}`,
status: commission.status,
createdAt: commission.createdAt
})),
...payouts.map(payout => ({
id: payout.id,
type: 'PAYOUT' as const,
amount: payout.amount,
description: 'Withdrawal request',
status: payout.status,
createdAt: payout.createdAt
}))
].sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())
return NextResponse.json({
balance: wallet?.balance || 0,
totalEarnings: wallet?.totalEarnings || 0,
totalWithdrawn: wallet?.totalWithdrawn || 0,
transactions
})
} catch (error) {
console.error('Error fetching wallet data:', error)
return NextResponse.json(
{ error: 'Failed to fetch wallet data' },
{ status: 500 }
)
}
}