first commit

This commit is contained in:
a.alinaghipour
2026-04-05 15:53:20 +03:30
commit aa9ed69dd2
96 changed files with 7721 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { calculateMatchPoints } from "@/lib/points";
export async function POST(_: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const events = await db.matchEvent.findMany({
where: { matchId: params.id },
include: { player: true },
});
// گروه‌بندی رویدادها بر اساس بازیکن
const playerEvents: Record<string, { player: any; events: any[] }> = {};
for (const ev of events) {
if (!playerEvents[ev.playerId]) playerEvents[ev.playerId] = { player: ev.player, events: [] };
playerEvents[ev.playerId].events.push(ev);
}
const results = [];
for (const [playerId, { player, events: evs }] of Object.entries(playerEvents)) {
const goals = evs.filter((e) => e.type === "GOAL").length;
const assists = evs.filter((e) => e.type === "ASSIST").length;
const yellowCards = evs.filter((e) => e.type === "YELLOW_CARD" || e.type === "SECOND_YELLOW").length;
const redCards = evs.filter((e) => e.type === "RED_CARD" || e.type === "SECOND_YELLOW").length;
const cleanSheet = evs.some((e) => e.type === "CLEAN_SHEET");
const penaltySaved = evs.filter((e) => e.type === "PENALTY_SAVED").length;
const penaltyMissed = evs.filter((e) => e.type === "PENALTY_MISSED").length;
const ownGoals = evs.filter((e) => e.type === "OWN_GOAL").length;
const isMotm = evs.some((e) => e.type === "MOTM");
const extraTimeBonus = evs.filter((e) => e.type === "EXTRA_TIME_BONUS").length;
// دقیقه بازی: اگه تعویض شده کمتر از ۹۰، وگرنه ۹۰
const subOut = evs.find((e) => e.type === "SUBSTITUTION_OUT");
const subIn = evs.find((e) => e.type === "SUBSTITUTION_IN");
const injury = evs.find((e) => e.type === "INJURY_NO_SUB");
let minutesPlayed = 90;
if (subOut?.minute) minutesPlayed = subOut.minute;
else if (injury?.minute) minutesPlayed = injury.minute;
if (subIn?.minute) minutesPlayed = 90 - subIn.minute;
const points = await calculateMatchPoints({
position: player.position,
goals, assists, yellowCards, redCards, minutesPlayed,
cleanSheet, penaltySaved, penaltyMissed, ownGoals, isMotm, extraTimeBonus,
});
const stat = await db.playerMatchStat.upsert({
where: { playerId_matchId: { playerId, matchId: params.id } },
update: { goals, assists, yellowCards, redCards, minutesPlayed, cleanSheet, penaltySaved, penaltyMissed, ownGoals, isMotm, extraTimeBonus, points },
create: { playerId, matchId: params.id, goals, assists, yellowCards, redCards, minutesPlayed, cleanSheet, penaltySaved, penaltyMissed, ownGoals, isMotm, extraTimeBonus, points },
});
// آپدیت totalPoints بازیکن
const agg = await db.playerMatchStat.aggregate({ where: { playerId }, _sum: { points: true } });
await db.player.update({ where: { id: playerId }, data: { totalPoints: agg._sum.points ?? 0 } });
results.push(stat);
}
// آپدیت امتیاز تیم‌های فانتزی
const teams = await db.team.findMany({ include: { players: { include: { player: true } } } });
for (const team of teams) {
let total = 0;
for (const tp of team.players) {
const mult = tp.isCaptain ? 2 : tp.isViceCaptain ? 1.5 : 1;
total += tp.player.totalPoints * mult;
}
await db.team.update({ where: { id: team.id }, data: { totalPoints: Math.round(total) } });
}
return NextResponse.json({ calculated: results.length });
}

View File

@@ -0,0 +1,13 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function DELETE(_: NextRequest, { params }: { params: { id: string; eventId: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
await db.matchEvent.delete({ where: { id: params.eventId } });
return NextResponse.json({ success: true });
}

View File

@@ -0,0 +1,18 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function POST(req: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const { playerId, type, minute, extraInfo } = await req.json();
const event = await db.matchEvent.create({
data: { matchId: params.id, playerId, type, minute: minute ?? null, extraInfo: extraInfo || null },
});
return NextResponse.json(event, { status: 201 });
}

View File

@@ -0,0 +1,23 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function POST(req: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const lineups: Array<{ countryId: string; formation: string; playerIds: string[] }> = await req.json();
// حذف ترکیب‌های قبلی
await db.matchLineup.deleteMany({ where: { matchId: params.id } });
for (const l of lineups) {
await db.matchLineup.create({
data: { matchId: params.id, countryId: l.countryId, formation: l.formation, playerIds: l.playerIds },
});
}
return NextResponse.json({ success: true });
}

View File

@@ -0,0 +1,22 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function PUT(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const rules: Array<{ position: string; eventType: string; points: number }> = await req.json();
for (const rule of rules) {
await db.scoringRule.upsert({
where: { position_eventType: { position: rule.position as any, eventType: rule.eventType as any } },
update: { points: rule.points, updatedBy: (session.user as any).id },
create: { position: rule.position as any, eventType: rule.eventType as any, points: rule.points, updatedBy: (session.user as any).id },
});
}
return NextResponse.json({ success: true });
}

View File

@@ -0,0 +1,17 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function PUT(req: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const { status } = await req.json();
const team = await db.team.update({
where: { id: params.id },
data: { status },
});
return NextResponse.json(team);
}

View File

@@ -0,0 +1,20 @@
import { NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function GET() {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const teams = await db.team.findMany({
include: {
user: { select: { name: true, email: true } },
_count: { select: { players: true } },
},
orderBy: { createdAt: "desc" },
});
return NextResponse.json(teams);
}

View File

@@ -0,0 +1,5 @@
import NextAuth from "next-auth";
import { authOptions } from "@/lib/auth";
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

View File

@@ -0,0 +1,23 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import bcrypt from "bcryptjs";
export async function POST(req: NextRequest) {
const { name, email, password } = await req.json();
if (!email || !password) {
return NextResponse.json({ error: "ایمیل و رمز عبور الزامی است" }, { status: 400 });
}
const existing = await db.user.findUnique({ where: { email } });
if (existing) {
return NextResponse.json({ error: "این ایمیل قبلاً ثبت شده" }, { status: 400 });
}
const hashed = await bcrypt.hash(password, 10);
const user = await db.user.create({
data: { name, email, password: hashed },
});
return NextResponse.json({ id: user.id }, { status: 201 });
}

View File

@@ -0,0 +1,23 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function PUT(req: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const body = await req.json();
const country = await db.country.update({ where: { id: params.id }, data: body });
return NextResponse.json(country);
}
export async function DELETE(_: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
await db.country.delete({ where: { id: params.id } });
return NextResponse.json({ success: true });
}

View File

@@ -0,0 +1,22 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function GET() {
const countries = await db.country.findMany({
include: { group: true },
orderBy: { name: "asc" },
});
return NextResponse.json(countries);
}
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const body = await req.json();
const country = await db.country.create({ data: body });
return NextResponse.json(country, { status: 201 });
}

View File

@@ -0,0 +1,16 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function POST(_: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
// غیرفعال کردن همه
await db.gameweek.updateMany({ data: { isActive: false } });
// فعال کردن این هفته
const gw = await db.gameweek.update({ where: { id: params.id }, data: { isActive: true } });
return NextResponse.json(gw);
}

View File

@@ -0,0 +1,19 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function GET() {
const gameweeks = await db.gameweek.findMany({ orderBy: { number: "asc" } });
return NextResponse.json(gameweeks);
}
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const body = await req.json();
const gw = await db.gameweek.create({ data: body });
return NextResponse.json(gw, { status: 201 });
}

View File

@@ -0,0 +1,20 @@
import { NextResponse } from "next/server";
import { db } from "@/lib/db";
export async function GET() {
const teams = await db.team.findMany({
orderBy: { totalPoints: "desc" },
include: { user: { select: { name: true, email: true } } },
take: 50,
});
return NextResponse.json(
teams.map((t, i) => ({
rank: i + 1,
teamName: t.name,
userName: t.user.name ?? t.user.email,
totalPoints: t.totalPoints,
budget: t.budget,
}))
);
}

View File

@@ -0,0 +1,32 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function GET(_: NextRequest, { params }: { params: { id: string } }) {
const match = await db.match.findUnique({
where: { id: params.id },
include: { homeTeam: true, awayTeam: true, playerStats: { include: { player: true } } },
});
if (!match) return NextResponse.json({ error: "Not found" }, { status: 404 });
return NextResponse.json(match);
}
export async function PUT(req: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const body = await req.json();
const match = await db.match.update({ where: { id: params.id }, data: body });
return NextResponse.json(match);
}
export async function DELETE(_: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
await db.match.delete({ where: { id: params.id } });
return NextResponse.json({ success: true });
}

View File

@@ -0,0 +1,65 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { calculatePoints } from "@/lib/points";
export async function POST(req: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const stats: Array<{
playerId: string;
goals: number;
assists: number;
yellowCards: number;
redCards: number;
minutesPlayed: number;
cleanSheet: boolean;
}> = await req.json();
const results = [];
for (const stat of stats) {
const player = await db.player.findUnique({ where: { id: stat.playerId } });
if (!player) continue;
const points = calculatePoints({ position: player.position, ...stat });
const record = await db.playerMatchStat.upsert({
where: { playerId_matchId: { playerId: stat.playerId, matchId: params.id } },
update: { ...stat, points },
create: { ...stat, matchId: params.id, points },
});
// آپدیت امتیاز کل بازیکن
const totalPoints = await db.playerMatchStat.aggregate({
where: { playerId: stat.playerId },
_sum: { points: true },
});
await db.player.update({
where: { id: stat.playerId },
data: { totalPoints: totalPoints._sum.points ?? 0 },
});
results.push(record);
}
// آپدیت امتیاز تیم‌های فانتزی
await recalcTeamPoints();
return NextResponse.json(results);
}
async function recalcTeamPoints() {
const teams = await db.team.findMany({ include: { players: { include: { player: true } } } });
for (const team of teams) {
let total = 0;
for (const tp of team.players) {
const multiplier = tp.isCaptain ? 2 : 1;
total += tp.player.totalPoints * multiplier;
}
await db.team.update({ where: { id: team.id }, data: { totalPoints: total } });
}
}

29
app/api/matches/route.ts Normal file
View File

@@ -0,0 +1,29 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function GET() {
const matches = await db.match.findMany({
include: {
homeTeam: true,
awayTeam: true,
gameweek: true,
},
orderBy: { matchDate: "asc" },
});
return NextResponse.json(matches);
}
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const body = await req.json();
const match = await db.match.create({
data: body,
include: { homeTeam: true, awayTeam: true },
});
return NextResponse.json(match, { status: 201 });
}

View File

@@ -0,0 +1,35 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { requestPayment } from "@/lib/zarinpal";
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const { packageId } = await req.json();
const userId = (session.user as any).id;
const pkg = await db.package.findUnique({ where: { id: packageId } });
if (!pkg || !pkg.isActive) return NextResponse.json({ error: "پکیج پیدا نشد" }, { status: 404 });
const callbackUrl = `${process.env.NEXTAUTH_URL}/api/payment/verify`;
const result = await requestPayment(pkg.price, `خرید ${pkg.name} - فانتزی جام جهانی`, callbackUrl);
if (!result.success) return NextResponse.json({ error: result.error }, { status: 400 });
// ذخیره پرداخت در دیتابیس
await db.payment.create({
data: {
userId,
packageId,
amount: pkg.price,
authority: result.authority,
status: "PENDING",
},
});
return NextResponse.json({ paymentUrl: result.paymentUrl });
}

View File

@@ -0,0 +1,43 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { verifyPayment } from "@/lib/zarinpal";
export async function GET(req: NextRequest) {
const { searchParams } = new URL(req.url);
const authority = searchParams.get("Authority");
const status = searchParams.get("Status");
if (!authority) return NextResponse.redirect(new URL("/shop?status=error", req.url));
const payment = await db.payment.findUnique({
where: { authority },
include: { package: true, user: true },
});
if (!payment) return NextResponse.redirect(new URL("/shop?status=error", req.url));
if (status !== "OK") {
await db.payment.update({ where: { id: payment.id }, data: { status: "FAILED" } });
return NextResponse.redirect(new URL("/shop?status=cancelled", req.url));
}
const result = await verifyPayment(authority, payment.amount);
if (!result.success) {
await db.payment.update({ where: { id: payment.id }, data: { status: "FAILED" } });
return NextResponse.redirect(new URL("/shop?status=failed", req.url));
}
// پرداخت موفق - آپدیت بودجه تیم
await db.payment.update({
where: { id: payment.id },
data: { status: "SUCCESS", refId: result.refId },
});
await db.team.updateMany({
where: { userId: payment.userId },
data: { budget: { increment: payment.package.budgetBonus } },
});
return NextResponse.redirect(new URL(`/shop?status=success&refId=${result.refId}`, req.url));
}

View File

@@ -0,0 +1,28 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function PUT(req: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN") {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const body = await req.json();
const player = await db.player.update({
where: { id: params.id },
data: body,
});
return NextResponse.json(player);
}
export async function DELETE(req: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN") {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
await db.player.delete({ where: { id: params.id } });
return NextResponse.json({ success: true });
}

32
app/api/players/route.ts Normal file
View File

@@ -0,0 +1,32 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function GET(req: NextRequest) {
const { searchParams } = new URL(req.url);
const position = searchParams.get("position");
const countryId = searchParams.get("countryId");
const players = await db.player.findMany({
where: {
...(position ? { position: position as any } : {}),
...(countryId ? { countryId } : {}),
},
include: { country: true },
orderBy: { totalPoints: "desc" },
});
return NextResponse.json(players);
}
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN") {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const body = await req.json();
const player = await db.player.create({ data: body });
return NextResponse.json(player, { status: 201 });
}

View File

@@ -0,0 +1,14 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function POST(_: NextRequest, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
await db.round.updateMany({ data: { isActive: false } });
const round = await db.round.update({ where: { id: params.id }, data: { isActive: true } });
return NextResponse.json(round);
}

25
app/api/rounds/route.ts Normal file
View File

@@ -0,0 +1,25 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function GET() {
const rounds = await db.round.findMany({ orderBy: { number: "asc" } });
return NextResponse.json(rounds);
}
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session || (session.user as any).role !== "ADMIN")
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const { number, name, deadline } = await req.json();
const existing = await db.round.findUnique({ where: { number } });
if (existing) return NextResponse.json({ error: "این شماره دور قبلاً ثبت شده" }, { status: 400 });
const round = await db.round.create({
data: { number, name, deadline: new Date(deadline) },
});
return NextResponse.json(round, { status: 201 });
}

View File

@@ -0,0 +1,23 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function PUT(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const { playerId, type } = await req.json();
const team = await db.team.findUnique({ where: { userId: (session.user as any).id } });
if (!team) return NextResponse.json({ error: "تیم پیدا نشد" }, { status: 404 });
if (type === "captain") {
await db.teamPlayer.updateMany({ where: { teamId: team.id }, data: { isCaptain: false } });
await db.teamPlayer.update({ where: { teamId_playerId: { teamId: team.id, playerId } }, data: { isCaptain: true } });
} else {
await db.teamPlayer.updateMany({ where: { teamId: team.id }, data: { isViceCaptain: false } });
await db.teamPlayer.update({ where: { teamId_playerId: { teamId: team.id, playerId } }, data: { isViceCaptain: true } });
}
return NextResponse.json({ success: true });
}

View File

@@ -0,0 +1,29 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { getFormationChangeIssues, FORMATIONS } from "@/lib/teamValidation";
export async function PUT(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const { formation } = await req.json();
if (!FORMATIONS[formation]) return NextResponse.json({ error: "ترکیب نامعتبر" }, { status: 400 });
const team = await db.team.findUnique({
where: { userId: (session.user as any).id },
include: { players: { include: { player: true } } },
});
if (!team) return NextResponse.json({ error: "تیم پیدا نشد" }, { status: 404 });
const playerList = team.players.map((tp) => ({ position: tp.player.position, isBench: tp.isBench }));
const issues = getFormationChangeIssues(playerList, team.formation, formation);
if (issues.length > 0) {
return NextResponse.json({ error: issues.join(" | "), issues }, { status: 400 });
}
const updated = await db.team.update({ where: { id: team.id }, data: { formation } });
return NextResponse.json(updated);
}

View File

@@ -0,0 +1,65 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
// اضافه کردن بازیکن به تیم
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const { playerId, isBench } = await req.json();
const userId = (session.user as any).id;
const team = await db.team.findUnique({
where: { userId },
include: { players: { include: { player: true } } },
});
if (!team) return NextResponse.json({ error: "ابتدا تیم بساز" }, { status: 400 });
const player = await db.player.findUnique({ where: { id: playerId } });
if (!player) return NextResponse.json({ error: "بازیکن پیدا نشد" }, { status: 404 });
// چک بودجه
const spent = team.players.reduce((s, tp) => s + tp.player.price, 0);
if (spent + player.price > team.budget)
return NextResponse.json({ error: "بودجه کافی نیست" }, { status: 400 });
// چک تعداد (۱۵ نفر: ۱۱ اصلی + ۴ ذخیره)
if (team.players.length >= 15)
return NextResponse.json({ error: "تیم پر است (حداکثر ۱۵ بازیکن)" }, { status: 400 });
// چک تکراری
const exists = team.players.find((tp) => tp.playerId === playerId);
if (exists) return NextResponse.json({ error: "این بازیکن قبلاً انتخاب شده" }, { status: 400 });
// چک حداکثر ۳ بازیکن از یک تیم ملی
const sameCountry = team.players.filter((tp) => tp.player.countryId === player.countryId).length;
if (sameCountry >= 3)
return NextResponse.json({ error: "حداکثر ۳ بازیکن از یک تیم ملی" }, { status: 400 });
const tp = await db.teamPlayer.create({
data: { teamId: team.id, playerId, isBench: isBench ?? false },
});
return NextResponse.json(tp, { status: 201 });
}
// حذف بازیکن از تیم
export async function DELETE(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const { playerId } = await req.json();
const userId = (session.user as any).id;
const team = await db.team.findUnique({ where: { userId } });
if (!team) return NextResponse.json({ error: "تیم پیدا نشد" }, { status: 404 });
await db.teamPlayer.delete({
where: { teamId_playerId: { teamId: team.id, playerId } },
});
return NextResponse.json({ success: true });
}

34
app/api/team/route.ts Normal file
View File

@@ -0,0 +1,34 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function GET() {
const session = await getServerSession(authOptions);
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const team = await db.team.findUnique({
where: { userId: (session.user as any).id },
include: {
players: {
include: { player: true },
},
},
});
return NextResponse.json(team);
}
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const { name } = await req.json();
const userId = (session.user as any).id;
const existing = await db.team.findUnique({ where: { userId } });
if (existing) return NextResponse.json({ error: "Team already exists" }, { status: 400 });
const team = await db.team.create({ data: { name, userId } });
return NextResponse.json(team, { status: 201 });
}

View File

@@ -0,0 +1,33 @@
import { NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { validateTeamComposition } from "@/lib/teamValidation";
export async function POST() {
const session = await getServerSession(authOptions);
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const team = await db.team.findUnique({
where: { userId: (session.user as any).id },
include: { players: { include: { player: true } } },
});
if (!team) return NextResponse.json({ error: "تیم پیدا نشد" }, { status: 404 });
const playerList = team.players.map((tp) => ({
position: tp.player.position,
isBench: tp.isBench,
}));
const { valid, errors } = validateTeamComposition(playerList, team.formation);
if (!valid) return NextResponse.json({ error: errors.join(" | ") }, { status: 400 });
// مستقیم ACTIVE میشه - نیازی به تایید ادمین نیست
const updated = await db.team.update({
where: { id: team.id },
data: { status: "ACTIVE" },
});
return NextResponse.json(updated);
}

View File

@@ -0,0 +1,16 @@
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
export async function PUT(req: NextRequest) {
const session = await getServerSession(authOptions);
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
const { name } = await req.json();
const user = await db.user.update({
where: { id: (session.user as any).id },
data: { name },
});
return NextResponse.json({ name: user.name });
}