feat: implement market page with QueryProvider and dynamic listings
- wrap root layout with QueryProvider for React Query - replace market UnderConstruction placeholder with MarketClient and real data fetching - implement search, pagination, and sort via search params using getActiveListings - add necessary client components and queries - update dependencies (e.g., prisma, pkg-types)
This commit is contained in:
1 parent
55eebde0ba
commit
ab37b477df
106 files changed
+15261
-301
No files matched your search
@@ -14,14 +14,15 @@ import {
|
||||
import {
|
||||
getUserByEmail,
|
||||
getUserByUsername,
|
||||
} from "@/lib/db/queries/users";
|
||||
} from "@/lib/prisma/queries/users";
|
||||
import {
|
||||
isServerActive,
|
||||
incrementUsersForServers,
|
||||
} from "@/lib/db/queries/servers";
|
||||
} from "@/lib/prisma/queries/servers";
|
||||
import { setSession } from "@/lib/redis/session";
|
||||
import { randomUUID } from "crypto";
|
||||
import { getPool } from "@/lib/db";
|
||||
import { createUser } from "@/lib/prisma/queries/users";
|
||||
import { createCharacter } from "@/lib/prisma/queries/characters";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
@@ -110,90 +111,82 @@ export async function POST(request: NextRequest) {
|
||||
// Hash da senha
|
||||
const passwordHash = await hashPassword(validatedData.password);
|
||||
|
||||
// Criar usuário e personagens em transação atômica
|
||||
const pool = getPool();
|
||||
const client = await pool.connect();
|
||||
|
||||
// Criar usuário e personagens em transação atômica usando Prisma
|
||||
const { prisma } = await import("@/lib/prisma/app");
|
||||
|
||||
let newUser: { userId: number; username: string; email: string };
|
||||
const createdCharacters: Array<{ characterName: string; serverName: string }> = [];
|
||||
|
||||
try {
|
||||
await client.query("BEGIN");
|
||||
// Usar transação Prisma
|
||||
await prisma.$transaction(async (tx) => {
|
||||
// Criar usuário
|
||||
const user = await tx.user.create({
|
||||
data: {
|
||||
username: validatedData.username,
|
||||
email: validatedData.email,
|
||||
password_hash: passwordHash,
|
||||
first_name: validatedData.firstName,
|
||||
last_name: validatedData.lastName,
|
||||
phone: validatedData.phone || null,
|
||||
cpf: null, // CPF não é mais obrigatório
|
||||
},
|
||||
select: {
|
||||
user_id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Criar usuário
|
||||
const userResult = await client.query<{
|
||||
user_id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
}>(
|
||||
`
|
||||
INSERT INTO users (username, email, password_hash, first_name, last_name, phone, cpf)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING user_id, username, email
|
||||
`,
|
||||
[
|
||||
validatedData.username,
|
||||
validatedData.email,
|
||||
passwordHash,
|
||||
validatedData.firstName,
|
||||
validatedData.lastName,
|
||||
validatedData.phone || null,
|
||||
null, // CPF não é mais obrigatório
|
||||
]
|
||||
);
|
||||
newUser = {
|
||||
userId: user.user_id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
};
|
||||
|
||||
newUser = {
|
||||
userId: userResult.rows[0].user_id,
|
||||
username: userResult.rows[0].username,
|
||||
email: userResult.rows[0].email,
|
||||
};
|
||||
// Criar personagens (primeiro é main por padrão)
|
||||
for (let i = 0; i < validatedData.servers.length; i++) {
|
||||
const serverData = validatedData.servers[i];
|
||||
const isMain = i === 0 || serverData.isMain === true;
|
||||
|
||||
// Criar personagens (primeiro é main por padrão)
|
||||
for (let i = 0; i < validatedData.servers.length; i++) {
|
||||
const serverData = validatedData.servers[i];
|
||||
const isMain = i === 0 || serverData.isMain === true;
|
||||
// Se este personagem será main e não é o primeiro, desmarcar outros
|
||||
if (isMain && i > 0) {
|
||||
await tx.userCharacter.updateMany({
|
||||
where: { user_id: newUser.userId },
|
||||
data: { is_main: false },
|
||||
});
|
||||
}
|
||||
|
||||
// Se este personagem será main e não é o primeiro, desmarcar outros
|
||||
if (isMain && i > 0) {
|
||||
await client.query(
|
||||
`
|
||||
UPDATE user_characters
|
||||
SET is_main = FALSE
|
||||
WHERE user_id = $1
|
||||
`,
|
||||
[newUser.userId]
|
||||
);
|
||||
// Inserir personagem
|
||||
const character = await tx.userCharacter.create({
|
||||
data: {
|
||||
user_id: newUser.userId,
|
||||
character_name: serverData.characterName,
|
||||
server_name: serverData.serverName,
|
||||
is_main: isMain,
|
||||
},
|
||||
});
|
||||
|
||||
createdCharacters.push({
|
||||
characterName: character.character_name,
|
||||
serverName: character.server_name,
|
||||
});
|
||||
}
|
||||
|
||||
// Inserir personagem
|
||||
const charResult = await client.query<{
|
||||
character_id: number;
|
||||
character_name: string;
|
||||
server_name: string;
|
||||
}>(
|
||||
`
|
||||
INSERT INTO user_characters (user_id, character_name, server_name, is_main)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING character_id, character_name, server_name
|
||||
`,
|
||||
[newUser.userId, serverData.characterName, serverData.serverName, isMain]
|
||||
);
|
||||
|
||||
createdCharacters.push({
|
||||
characterName: charResult.rows[0].character_name,
|
||||
serverName: charResult.rows[0].server_name,
|
||||
// Incrementar total_users dos servidores (dentro da transação)
|
||||
await tx.server.updateMany({
|
||||
where: {
|
||||
server_name: { in: uniqueServerNames },
|
||||
},
|
||||
data: {
|
||||
total_users: { increment: 1 },
|
||||
last_activity_at: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Incrementar total_users dos servidores
|
||||
await incrementUsersForServers(uniqueServerNames);
|
||||
|
||||
await client.query("COMMIT");
|
||||
});
|
||||
} catch (error) {
|
||||
await client.query("ROLLBACK");
|
||||
// Prisma já faz rollback automático em caso de erro
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
|
||||
// Gerar tokens
|
||||
|
||||
Reference in new issue
Block a user