refactor(frontend): proxy legacy app api routes to backend

This commit is contained in:
Tiago Yamamoto 2026-03-07 10:12:37 -06:00
parent 5b1687c310
commit 6bf6a96036
27 changed files with 157 additions and 2809 deletions

View file

@ -8,6 +8,14 @@ const nextConfig: NextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
webpack: (config) => {
config.resolve = config.resolve || {};
config.resolve.alias = {
...(config.resolve.alias || {}),
'node-appwrite': require('path').resolve(__dirname, 'src/lib/appwrite.ts'),
};
return config;
},
};
export default nextConfig;

View file

@ -0,0 +1,62 @@
import { NextRequest, NextResponse } from 'next/server'
import { API_V1_BASE_URL } from '@/lib/apiBase'
const buildUpstreamUrl = (request: NextRequest) => {
const suffix = request.nextUrl.pathname.replace(/^\/api/, '')
return `${API_V1_BASE_URL}${suffix}${request.nextUrl.search}`
}
const buildHeaders = (request: NextRequest) => {
const headers = new Headers()
const contentType = request.headers.get('content-type')
const authorization = request.headers.get('authorization')
const accept = request.headers.get('accept')
if (contentType) headers.set('content-type', contentType)
if (authorization) headers.set('authorization', authorization)
if (accept) headers.set('accept', accept)
return headers
}
const proxy = async (request: NextRequest) => {
try {
const method = request.method
const headers = buildHeaders(request)
const upstreamUrl = buildUpstreamUrl(request)
const init: RequestInit = {
method,
headers,
cache: 'no-store',
}
if (!['GET', 'HEAD'].includes(method)) {
init.body = await request.text()
}
const response = await fetch(upstreamUrl, init)
const text = await response.text()
return new NextResponse(text, {
status: response.status,
headers: {
'content-type': response.headers.get('content-type') || 'application/json',
},
})
} catch (error) {
return NextResponse.json(
{
success: false,
error: 'Falha ao comunicar com o backend principal',
details: error instanceof Error ? error.message : 'unknown_error',
},
{ status: 502 }
)
}
}
export const GET = proxy
export const POST = proxy
export const PUT = proxy
export const PATCH = proxy
export const DELETE = proxy

View file

@ -1,99 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
export async function GET(request: NextRequest) {
console.log('📋 [API] Listando carrinhos...');
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error('❌ [API] APPWRITE_API_KEY não configurada');
return NextResponse.json(
{ success: false, error: 'Configuração do servidor ausente' },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CARRINHOS_ID!;
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get('limit')) || 10;
const page = Number(searchParams.get('page')) || 1;
const termoBuscado = searchParams.get('termoBuscado') || '';
const offset = (page - 1) * limit;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
const queries = [
termoBuscado ? Query.equal('usuarios', termoBuscado) : Query.limit(limit),
Query.limit(limit),
Query.offset(offset)
];
const response = await databases.listDocuments(databaseId, collectionId, queries);
console.log(`✅ [API] ${response.total} carrinhos carregados!`);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total
});
} catch (error) {
console.error('💥 [API] Erro ao listar carrinhos:', error);
return NextResponse.json(
{ success: false, error: 'Erro ao carregar carrinhos' },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
console.log('âž• [API] Criando novo carrinho...');
try {
const body = await request.json();
console.log('📤 [API] Dados recebidos:', body);
const response = await fetch(
`${process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!}/databases/${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!}/collections/${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CARRINHOS_ID!}/documents`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
'X-Appwrite-Key': process.env.APPWRITE_API_KEY!
},
body: JSON.stringify(body)
}
);
const data = await response.json();
if (response.status === 201 || response.status === 409) {
console.log('✅ [API] Carrinho criado com sucesso!');
return NextResponse.json({ success: true, data });
} else {
console.error('❌ [API] Erro ao criar:', response.status, data);
return NextResponse.json(
{ success: false, error: 'Erro ao criar carrinho', details: data },
{ status: response.status }
);
}
} catch (error) {
console.error('💥 [API] Erro na criação:', error);
return NextResponse.json(
{ success: false, error: 'Erro interno do servidor' },
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,99 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../../_backendProxy'
export const runtime = 'edge';
export async function GET(request: NextRequest) {
console.log('📋 [API] Listando carrinhos...');
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error('❌ [API] APPWRITE_API_KEY não configurada');
return NextResponse.json(
{ success: false, error: 'Configuração do servidor ausente' },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CARRINHOS_ID!;
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get('limit')) || 10;
const page = Number(searchParams.get('page')) || 1;
const termoBuscado = searchParams.get('termoBuscado') || '';
const offset = (page - 1) * limit;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
const queries = [
termoBuscado ? Query.equal('usuarios', termoBuscado) : Query.limit(limit),
Query.limit(limit),
Query.offset(offset)
];
const response = await databases.listDocuments(databaseId, collectionId, queries);
console.log(`✅ [API] ${response.total} carrinhos carregados!`);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total
});
} catch (error) {
console.error('💥 [API] Erro ao listar carrinhos:', error);
return NextResponse.json(
{ success: false, error: 'Erro ao carregar carrinhos' },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
console.log('âž• [API] Criando novo carrinho...');
try {
const body = await request.json();
console.log('📤 [API] Dados recebidos:', body);
const response = await fetch(
`${process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!}/databases/${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!}/collections/${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CARRINHOS_ID!}/documents`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
'X-Appwrite-Key': process.env.APPWRITE_API_KEY!
},
body: JSON.stringify(body)
}
);
const data = await response.json();
if (response.status === 201 || response.status === 409) {
console.log('✅ [API] Carrinho criado com sucesso!');
return NextResponse.json({ success: true, data });
} else {
console.error('❌ [API] Erro ao criar:', response.status, data);
return NextResponse.json(
{ success: false, error: 'Erro ao criar carrinho', details: data },
{ status: response.status }
);
}
} catch (error) {
console.error('💥 [API] Erro na criação:', error);
return NextResponse.json(
{ success: false, error: 'Erro interno do servidor' },
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,217 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
// 🔍 GET - Listar produtos do catálogo
export async function GET(request: NextRequest) {
console.log("📋 [API] Listando produtos do catálogo...");
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error("❌ [API] APPWRITE_API_KEY não configurada");
return NextResponse.json(
{ success: false, error: "Configuração do servidor ausente" },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CATALOGO_PRODUTOS_ID!;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
const { searchParams } = new URL(request.url);
const termoBuscado = searchParams.get('q') || '';
const page = parseInt(searchParams.get('page') || '1', 10);
const limit = parseInt(searchParams.get('limit') || '10', 10);
const offset = (page - 1) * limit;
// Por enquanto, fazer busca simples sem filtros complexos
const response = await databases.listDocuments(
databaseId,
collectionId,
// queries básicas por enquanto
);
console.log(`✅ [API] ${response.documents.length} produtos carregados!`);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total,
});
} catch (error: any) {
console.error('❌ [API] Erro ao listar produtos do catálogo:', error);
// Tratamento específico para erros do Appwrite
if (error.code) {
return NextResponse.json(
{
success: false,
error: `Erro do Appwrite: ${error.message}`,
details: {
code: error.code,
type: error.type,
message: error.message
}
},
{ status: error.code === 401 ? 401 : 500 }
);
}
return NextResponse.json(
{
success: false,
error: "Erro interno do servidor",
details: error instanceof Error ? error.message : String(error)
},
{ status: 500 }
);
}
}
// ➕ POST - Criar produto no catálogo
export async function POST(request: NextRequest) {
console.log("➕ [API] Criando produto no catálogo...");
try {
const body = await request.json();
console.log("📤 [API] Dados recebidos:", body);
// Validação dos dados obrigatórios
if (!body.descricao && !body.nome) {
console.error("❌ [API] Nome ou descrição do produto é obrigatório");
return NextResponse.json(
{ success: false, error: "Nome ou descrição do produto é obrigatório" },
{ status: 400 }
);
}
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error("❌ [API] APPWRITE_API_KEY não configurada");
return NextResponse.json(
{ success: false, error: "Configuração do servidor ausente" },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CATALOGO_PRODUTOS_ID!;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
// Preparar dados para criação - usando object flexible para aceitar campos dinâmicos
const dadosProduto: any = {
descricao: body.descricao || body.nome,
nome: body.nome || body.descricao,
};
// Adicionar campos opcionais se fornecidos
if (body['codigo-ean']) {
dadosProduto['codigo-ean'] = body['codigo-ean'];
}
if (body['codigo-interno']) {
dadosProduto['codigo-interno'] = body['codigo-interno'];
}
if (body.observacoes) {
dadosProduto.observacoes = body.observacoes;
}
if (body.laboratorio) {
dadosProduto.laboratorio = body.laboratorio;
}
console.log("📝 [API] Dados preparados para criação:", dadosProduto);
// Tentar criar com dados completos primeiro
try {
const novoProduto = await databases.createDocument(
databaseId,
collectionId,
'unique()', // ID único
dadosProduto
);
console.log("✅ [API] Produto criado com sucesso!");
return NextResponse.json({
success: true,
data: novoProduto,
mensagem: "Produto criado com sucesso!",
});
} catch (createError: any) {
console.warn("⚠️ [API] Primeira tentativa falhou, tentando com dados simplificados:", createError.message);
// Se falhar, tentar apenas com dados essenciais
try {
const dadosSimplesProduto = {
descricao: body.descricao || body.nome,
};
console.log("📝 [API] Tentando com dados simplificados:", dadosSimplesProduto);
const novoProduto = await databases.createDocument(
databaseId,
collectionId,
'unique()',
dadosSimplesProduto
);
console.log("✅ [API] Produto criado com dados simplificados!");
return NextResponse.json({
success: true,
data: novoProduto,
mensagem: "Produto criado com sucesso (modo simplificado)!",
});
} catch (secondError: any) {
console.error("❌ [API] Segunda tentativa também falhou:", secondError);
throw secondError; // Deixar o catch principal tratar
}
}
} catch (error: any) {
console.error("💥 [API] Erro na criação:", error);
// Tratamento específico para erros do Appwrite
if (error.code) {
return NextResponse.json(
{
success: false,
error: `Erro do Appwrite: ${error.message}`,
details: {
code: error.code,
type: error.type,
message: error.message
}
},
{ status: error.code === 400 ? 400 : 500 }
);
}
return NextResponse.json(
{
success: false,
error: "Erro interno do servidor",
details: error instanceof Error ? error.message : String(error)
},
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,217 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../../_backendProxy'
export const runtime = 'edge';
// 🔍 GET - Listar produtos do catálogo
export async function GET(request: NextRequest) {
console.log("📋 [API] Listando produtos do catálogo...");
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error("❌ [API] APPWRITE_API_KEY não configurada");
return NextResponse.json(
{ success: false, error: "Configuração do servidor ausente" },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CATALOGO_PRODUTOS_ID!;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
const { searchParams } = new URL(request.url);
const termoBuscado = searchParams.get('q') || '';
const page = parseInt(searchParams.get('page') || '1', 10);
const limit = parseInt(searchParams.get('limit') || '10', 10);
const offset = (page - 1) * limit;
// Por enquanto, fazer busca simples sem filtros complexos
const response = await databases.listDocuments(
databaseId,
collectionId,
// queries básicas por enquanto
);
console.log(`✅ [API] ${response.documents.length} produtos carregados!`);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total,
});
} catch (error: any) {
console.error('❌ [API] Erro ao listar produtos do catálogo:', error);
// Tratamento específico para erros do Appwrite
if (error.code) {
return NextResponse.json(
{
success: false,
error: `Erro do Appwrite: ${error.message}`,
details: {
code: error.code,
type: error.type,
message: error.message
}
},
{ status: error.code === 401 ? 401 : 500 }
);
}
return NextResponse.json(
{
success: false,
error: "Erro interno do servidor",
details: error instanceof Error ? error.message : String(error)
},
{ status: 500 }
);
}
}
// ➕ POST - Criar produto no catálogo
export async function POST(request: NextRequest) {
console.log("➕ [API] Criando produto no catálogo...");
try {
const body = await request.json();
console.log("📤 [API] Dados recebidos:", body);
// Validação dos dados obrigatórios
if (!body.descricao && !body.nome) {
console.error("❌ [API] Nome ou descrição do produto é obrigatório");
return NextResponse.json(
{ success: false, error: "Nome ou descrição do produto é obrigatório" },
{ status: 400 }
);
}
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error("❌ [API] APPWRITE_API_KEY não configurada");
return NextResponse.json(
{ success: false, error: "Configuração do servidor ausente" },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CATALOGO_PRODUTOS_ID!;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
// Preparar dados para criação - usando object flexible para aceitar campos dinâmicos
const dadosProduto: any = {
descricao: body.descricao || body.nome,
nome: body.nome || body.descricao,
};
// Adicionar campos opcionais se fornecidos
if (body['codigo-ean']) {
dadosProduto['codigo-ean'] = body['codigo-ean'];
}
if (body['codigo-interno']) {
dadosProduto['codigo-interno'] = body['codigo-interno'];
}
if (body.observacoes) {
dadosProduto.observacoes = body.observacoes;
}
if (body.laboratorio) {
dadosProduto.laboratorio = body.laboratorio;
}
console.log("📝 [API] Dados preparados para criação:", dadosProduto);
// Tentar criar com dados completos primeiro
try {
const novoProduto = await databases.createDocument(
databaseId,
collectionId,
'unique()', // ID único
dadosProduto
);
console.log("✅ [API] Produto criado com sucesso!");
return NextResponse.json({
success: true,
data: novoProduto,
mensagem: "Produto criado com sucesso!",
});
} catch (createError: any) {
console.warn("⚠️ [API] Primeira tentativa falhou, tentando com dados simplificados:", createError.message);
// Se falhar, tentar apenas com dados essenciais
try {
const dadosSimplesProduto = {
descricao: body.descricao || body.nome,
};
console.log("📝 [API] Tentando com dados simplificados:", dadosSimplesProduto);
const novoProduto = await databases.createDocument(
databaseId,
collectionId,
'unique()',
dadosSimplesProduto
);
console.log("✅ [API] Produto criado com dados simplificados!");
return NextResponse.json({
success: true,
data: novoProduto,
mensagem: "Produto criado com sucesso (modo simplificado)!",
});
} catch (secondError: any) {
console.error("❌ [API] Segunda tentativa também falhou:", secondError);
throw secondError; // Deixar o catch principal tratar
}
}
} catch (error: any) {
console.error("💥 [API] Erro na criação:", error);
// Tratamento específico para erros do Appwrite
if (error.code) {
return NextResponse.json(
{
success: false,
error: `Erro do Appwrite: ${error.message}`,
details: {
code: error.code,
type: error.type,
message: error.message
}
},
{ status: error.code === 400 ? 400 : 500 }
);
}
return NextResponse.json(
{
success: false,
error: "Erro interno do servidor",
details: error instanceof Error ? error.message : String(error)
},
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,91 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, ID, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
// Configurar cliente do servidor
const getServerClient = () => {
const client = new Client()
.setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!)
.setKey(process.env.APPWRITE_API_KEY!);
return new Databases(client);
};
export async function POST(request: NextRequest) {
try {
const { authId } = await request.json();
if (!authId) {
return NextResponse.json(
{ success: false, error: 'Auth ID é obrigatório' },
{ status: 400 }
);
}
const databases = getServerClient();
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const empresaCollectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_EMPRESAS_DADOS_ID!;
const usuariosCollectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
// 1. Criar empresa padrão
const empresaData = {
cnpj: "12345678000199",
"razao-social": "Farmácia SaveInMed Demo",
"nome-fantasia": "SaveInMed Demo"
};
console.log('Criando empresa padrão:', empresaData);
const empresaResponse = await databases.createDocument(
databaseId,
empresaCollectionId,
ID.unique(),
empresaData
);
console.log('Empresa criada:', empresaResponse.$id);
// 2. Buscar documento do usuário
const userQuery = await databases.listDocuments(
databaseId,
usuariosCollectionId,
[Query.equal("auth-id-appwrite", authId), Query.limit(1)]
);
if (userQuery.documents.length === 0) {
return NextResponse.json(
{ success: false, error: 'Usuário não encontrado' },
{ status: 404 }
);
}
const userDoc = userQuery.documents[0];
// 3. Associar empresa ao usuário
await databases.updateDocument(
databaseId,
usuariosCollectionId,
userDoc.$id,
{
empresas_array: [empresaData['razao-social']]
}
);
console.log('Empresa associada ao usuário');
return NextResponse.json({
success: true,
empresa: empresaResponse,
message: 'Empresa criada e associada com sucesso'
});
} catch (error: any) {
console.error('Erro ao configurar empresa:', error);
return NextResponse.json(
{ success: false, error: error.message || 'Erro interno do servidor' },
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,119 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
const createDatabasesClient = () => {
const apiKey = process.env.APPWRITE_API_KEY;
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID;
if (!apiKey || !endpoint || !projectId) {
throw new Error('Configuração do Appwrite ausente');
}
const client = new Client().setEndpoint(endpoint).setProject(projectId).setKey(apiKey);
return new Databases(client);
};
export async function GET(request: NextRequest) {
console.log('[API] Debug registro usuario...');
try {
const { searchParams } = new URL(request.url);
const userId = searchParams.get('userId');
if (!userId) {
return NextResponse.json(
{ success: false, error: 'userId é obrigatório' },
{ status: 400 }
);
}
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
const databases = createDatabasesClient();
console.log('[API] Buscando usuário com auth-id-appwrite:', userId);
const response = await databases.listDocuments(databaseId, collectionId, [
Query.equal('auth-id-appwrite', userId),
Query.limit(1),
]);
if (response.documents.length === 0) {
console.log('[API] Usuário não encontrado');
return NextResponse.json({
success: true,
found: false,
message: 'Usuário não encontrado na base de dados',
});
}
const usuario = response.documents[0] as Record<string, any>;
const analise = {
id: usuario.$id,
'auth-id-appwrite': usuario['auth-id-appwrite'],
'nome-civil': {
valor: usuario['nome-civil'],
preenchido: !!usuario['nome-civil'],
},
cpf: {
valor: usuario.cpf,
preenchido: !!usuario.cpf,
},
enderecos: {
valor: usuario.enderecos,
tipo: typeof usuario.enderecos,
isArray: Array.isArray(usuario.enderecos),
length: usuario.enderecos?.length || 0,
valido:
Array.isArray(usuario.enderecos) &&
usuario.enderecos.length > 0 &&
usuario.enderecos.some((endereco: string) => endereco && endereco.trim() !== ''),
},
empresas_array: {
valor: usuario.empresas_array,
tipo: typeof usuario.empresas_array,
isArray: Array.isArray(usuario.empresas_array),
length: usuario.empresas_array?.length || 0,
valido:
usuario.empresas_array &&
Array.isArray(usuario.empresas_array) &&
usuario.empresas_array.length > 0,
},
};
const dadosFaltantes: string[] = [];
if (!analise['nome-civil'].preenchido || !analise.cpf.preenchido) {
dadosFaltantes.push('Dados pessoais');
}
if (!analise.enderecos.valido) {
dadosFaltantes.push('Endereço');
}
if (!analise.empresas_array.valido) {
dadosFaltantes.push('Empresa');
}
const isCompleto = dadosFaltantes.length === 0;
return NextResponse.json({
success: true,
found: true,
isCompleto,
dadosFaltantes,
analise,
dadosCompletos: usuario,
});
} catch (error) {
console.error('[API] Erro ao debugar registro:', error);
return NextResponse.json(
{ success: false, error: 'Erro ao verificar registro' },
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,102 +1,3 @@
import { NextRequest, NextResponse } from "next/server";
import { Client, Databases, Query } from "node-appwrite";
import { UserRole } from "@/types/auth";
export const runtime = "edge";
// Função para obter cliente Appwrite do servidor
function getServerClient() {
const client = new Client()
.setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!)
.setKey(process.env.APPWRITE_API_KEY!);
return new Databases(client);
}
// GET - Listar empresas com filtro por nível de usuário
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const userRole = searchParams.get("userRole");
const userId = searchParams.get("userId");
console.log(
`📋 [API] Listando empresas - UserRole: ${userRole}, UserId: ${userId}`
);
const databases = getServerClient();
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_EMPRESAS_DADOS_ID!;
let queries = [];
// Se for admin (não superadmin), buscar apenas empresas associadas ao usuário
if (userRole === UserRole.ADMIN && userId) {
// Primeiro, buscar o usuário para obter suas empresas associadas
const usuarioCollectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
const userResponse = await databases.listDocuments(
databaseId,
usuarioCollectionId,
[Query.equal("$id", userId), Query.limit(1)]
);
if (userResponse.documents.length > 0) {
const userData = userResponse.documents[0];
const empresasAssociadas = userData.empresas_array || [];
if (empresasAssociadas.length > 0) {
// Filtrar empresas pelos nomes/IDs associados ao usuário
// Como empresas_array pode conter nomes, vamos buscar por nome fantasia ou razão social
const empresaQueries = empresasAssociadas.map((empresa) =>
Query.or([
Query.equal("nomeFantasia", empresa),
Query.equal("razaoSocial", empresa),
])
);
queries = empresaQueries;
} else {
// Usuário admin sem empresas associadas - retornar lista vazia
return NextResponse.json({
success: true,
documents: [],
total: 0,
});
}
}
}
const response = await databases.listDocuments(
databaseId,
collectionId,
queries
);
console.log(
`✅ [API] ${response.total} empresas carregadas para userRole: ${userRole}`
);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total,
});
} catch (error: any) {
console.error("💥 [API] Erro ao listar empresas filtradas:", error);
return NextResponse.json(
{
success: false,
error: "Erro ao carregar empresas",
details: {
message: error.message || error,
code: error.code || null,
type: error.type || null,
},
},
{ status: 500 }
);
}
}
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,161 +1,3 @@
// @ts-nocheck
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, ID } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
const getServerClient = () => {
const client = new Client()
.setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!)
.setKey(process.env.APPWRITE_API_KEY!);
return new Databases(client);
};
export async function GET(request: NextRequest) {
console.log('[API] Listando empresas...');
try {
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get('limit')) || 10;
const page = Number(searchParams.get('page')) || 1;
const offset = (page - 1) * limit;
const apiKey = process.env.APPWRITE_API_KEY!;
const url = new URL('https://nyc.cloud.appwrite.io/v1/databases/marketplace/collections/empresas/documents');
url.searchParams.append('queries[]', `limit(${limit})`);
url.searchParams.append('queries[]', `offset(${offset})`);
const upstreamResponse = await fetch(url.toString(), {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': 'saveinmed-api',
'X-Appwrite-Key': apiKey,
},
});
const data = await upstreamResponse.json().catch(() => ({}));
if (upstreamResponse.ok) {
console.log(`[API] ${data.total} empresas carregadas!`);
return NextResponse.json({
success: true,
documents: data.documents,
total: data.total,
});
}
const databases = getServerClient();
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_EMPRESAS_DADOS_ID!;
console.log(`[API] Usando Database: ${databaseId}, Collection: ${collectionId}`);
const appwriteResponse = await databases.listDocuments(databaseId, collectionId);
console.log(`[API] ${appwriteResponse.total} empresas carregadas!`);
return NextResponse.json({
success: true,
documents: appwriteResponse.documents,
total: appwriteResponse.total,
});
} catch (error: any) {
console.error('[API] Erro ao listar:', error);
return NextResponse.json(
{
success: false,
error: 'Erro ao carregar empresas',
details: {
message: error.message || error,
code: error.code || null,
type: error.type || null,
},
},
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
console.log('[API] Criando nova empresa...');
try {
const requiredEnvs = [
'NEXT_PUBLIC_APPWRITE_ENDPOINT',
'NEXT_PUBLIC_APPWRITE_PROJECT_ID',
'NEXT_PUBLIC_APPWRITE_DATABASE_ID',
'NEXT_PUBLIC_APPWRITE_COLLECTION_EMPRESAS_DADOS_ID',
'APPWRITE_API_KEY',
];
for (const env of requiredEnvs) {
if (!process.env[env]) {
console.error(`[API] Variavel ${env} nao configurada`);
return NextResponse.json(
{ success: false, error: `Configuracao ausente: ${env}` },
{ status: 500 }
);
}
}
const body = await request.json();
console.log('[API] Dados recebidos:', body);
if (!body.data) {
return NextResponse.json(
{ success: false, error: 'Dados da empresa sao obrigatorios' },
{ status: 400 }
);
}
const { data } = body;
if (!data.cnpj || !data['razao-social']) {
return NextResponse.json(
{ success: false, error: 'CNPJ e Razao Social sao obrigatorios' },
{ status: 400 }
);
}
const databases = getServerClient();
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_EMPRESAS_DADOS_ID!;
console.log(`[API] Criando em Database: ${databaseId}, Collection: ${collectionId}`);
const response = await databases.createDocument(databaseId, collectionId, ID.unique(), data);
console.log('[API] Empresa criada com sucesso!', response.$id);
return NextResponse.json({ success: true, data: response }, { status: 201 });
} catch (error: any) {
console.error('[API] Erro na criacao:', error);
let errorMessage = 'Erro interno do servidor';
let statusCode = 500;
if (error.code === 409) {
errorMessage = 'Empresa ja existe com estes dados';
statusCode = 409;
} else if (error.code === 400) {
errorMessage = 'Dados invalidos fornecidos';
statusCode = 400;
} else if (error.message) {
errorMessage = error.message;
}
return NextResponse.json(
{
success: false,
error: errorMessage,
details: {
message: error.message || error,
code: error.code || null,
type: error.type || null,
},
},
{ status: statusCode }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,102 +1,3 @@
import { NextRequest, NextResponse } from "next/server";
import { Client, Databases, Query } from "node-appwrite";
import { UserRole } from "@/types/auth";
export const runtime = "edge";
// Função para obter cliente Appwrite do servidor
function getServerClient() {
const client = new Client()
.setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!)
.setKey(process.env.APPWRITE_API_KEY!);
return new Databases(client);
}
// GET - Listar empresas com filtro por nível de usuário
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const userRole = searchParams.get("userRole");
const userId = searchParams.get("userId");
console.log(
`📋 [API] Listando empresas - UserRole: ${userRole}, UserId: ${userId}`
);
const databases = getServerClient();
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_EMPRESAS_DADOS_ID!;
let queries = [];
// Se for admin (não superadmin), buscar apenas empresas associadas ao usuário
if (userRole === UserRole.ADMIN && userId) {
// Primeiro, buscar o usuário para obter suas empresas associadas
const usuarioCollectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
const userResponse = await databases.listDocuments(
databaseId,
usuarioCollectionId,
[Query.equal("$id", userId), Query.limit(1)]
);
if (userResponse.documents.length > 0) {
const userData = userResponse.documents[0];
const empresasAssociadas = userData.empresas_array || [];
if (empresasAssociadas.length > 0) {
// Filtrar empresas pelos nomes/IDs associados ao usuário
// Como empresas_array pode conter nomes, vamos buscar por nome fantasia ou razão social
const empresaQueries = empresasAssociadas.map((empresa) =>
Query.or([
Query.equal("nomeFantasia", empresa),
Query.equal("razaoSocial", empresa),
])
);
queries = empresaQueries;
} else {
// Usuário admin sem empresas associadas - retornar lista vazia
return NextResponse.json({
success: true,
documents: [],
total: 0,
});
}
}
}
const response = await databases.listDocuments(
databaseId,
collectionId,
queries
);
console.log(
`✅ [API] ${response.total} empresas carregadas para userRole: ${userRole}`
);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total,
});
} catch (error: any) {
console.error("💥 [API] Erro ao listar empresas filtradas:", error);
return NextResponse.json(
{
success: false,
error: "Erro ao carregar empresas",
details: {
message: error.message || error,
code: error.code || null,
type: error.type || null,
},
},
{ status: 500 }
);
}
}
import { DELETE, GET, PATCH, POST, PUT } from '../../_backendProxy'
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,103 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
export async function GET(request: NextRequest) {
console.log('📋 [API] Listando endereços...');
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error('❌ [API] APPWRITE_API_KEY não configurada');
return NextResponse.json(
{ success: false, error: 'Configuração do servidor ausente' },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_ENDERECOS_ID!;
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get('limit')) || 10;
const page = Number(searchParams.get('page')) || 1;
const termoBuscado = searchParams.get('termoBuscado') || '';
const offset = (page - 1) * limit;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
const queries = [
Query.or([
Query.search('titulo', termoBuscado),
Query.search('cep', termoBuscado),
Query.search('cidade', termoBuscado)
]),
Query.limit(limit),
Query.offset(offset)
];
const response = await databases.listDocuments(databaseId, collectionId, queries);
console.log(`✅ [API] ${response.total} endereços carregados!`);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total
});
} catch (error) {
console.error('💥 [API] Erro ao listar endereços:', error);
return NextResponse.json(
{ success: false, error: 'Erro ao carregar endereços' },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
console.log('➕ [API] Criando novo endereço...');
try {
const body = await request.json();
console.log('📤 [API] Dados recebidos:', body);
const response = await fetch(
`${process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!}/databases/${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!}/collections/${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_ENDERECOS_ID!}/documents`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
'X-Appwrite-Key': process.env.APPWRITE_API_KEY!
},
body: JSON.stringify(body)
}
);
const data = await response.json();
if (response.status === 201 || response.status === 409) {
console.log('✅ [API] Endereço criado com sucesso!');
return NextResponse.json({ success: true, data });
} else {
console.error('❌ [API] Erro ao criar:', response.status, data);
return NextResponse.json(
{ success: false, error: 'Erro ao criar endereço', details: data },
{ status: response.status }
);
}
} catch (error) {
console.error('💥 [API] Erro na criação:', error);
return NextResponse.json(
{ success: false, error: 'Erro interno do servidor' },
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,103 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../../_backendProxy'
export const runtime = 'edge';
export async function GET(request: NextRequest) {
console.log('📋 [API] Listando endereços...');
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error('❌ [API] APPWRITE_API_KEY não configurada');
return NextResponse.json(
{ success: false, error: 'Configuração do servidor ausente' },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_ENDERECOS_ID!;
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get('limit')) || 10;
const page = Number(searchParams.get('page')) || 1;
const termoBuscado = searchParams.get('termoBuscado') || '';
const offset = (page - 1) * limit;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
const queries = [
Query.or([
Query.search('titulo', termoBuscado),
Query.search('cep', termoBuscado),
Query.search('cidade', termoBuscado)
]),
Query.limit(limit),
Query.offset(offset)
];
const response = await databases.listDocuments(databaseId, collectionId, queries);
console.log(`✅ [API] ${response.total} endereços carregados!`);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total
});
} catch (error) {
console.error('💥 [API] Erro ao listar endereços:', error);
return NextResponse.json(
{ success: false, error: 'Erro ao carregar endereços' },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
console.log('➕ [API] Criando novo endereço...');
try {
const body = await request.json();
console.log('📤 [API] Dados recebidos:', body);
const response = await fetch(
`${process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!}/databases/${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!}/collections/${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_ENDERECOS_ID!}/documents`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
'X-Appwrite-Key': process.env.APPWRITE_API_KEY!
},
body: JSON.stringify(body)
}
);
const data = await response.json();
if (response.status === 201 || response.status === 409) {
console.log('✅ [API] Endereço criado com sucesso!');
return NextResponse.json({ success: true, data });
} else {
console.error('❌ [API] Erro ao criar:', response.status, data);
return NextResponse.json(
{ success: false, error: 'Erro ao criar endereço', details: data },
{ status: response.status }
);
}
} catch (error) {
console.error('💥 [API] Erro na criação:', error);
return NextResponse.json(
{ success: false, error: 'Erro interno do servidor' },
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,67 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
export async function GET(request: NextRequest) {
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
return NextResponse.json({ success: false, error: 'Configuração do servidor ausente' }, { status: 500 });
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_FATURAS_ID!;
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get('limit')) || 10;
const page = Number(searchParams.get('page')) || 1;
const termoBuscado = searchParams.get('termoBuscado') || '';
const offset = (page - 1) * limit;
const client = new Client().setEndpoint(endpoint).setProject(projectId).setKey(apiKey);
const databases = new Databases(client);
const queries = [Query.search('empresas', termoBuscado), Query.limit(limit), Query.offset(offset)];
const response = await databases.listDocuments(databaseId, collectionId, queries);
return NextResponse.json({ success: true, documents: response.documents, total: response.total });
} catch (error) {
console.error('Erro ao listar faturas:', error);
return NextResponse.json({ success: false, error: 'Erro ao carregar faturas' }, { status: 500 });
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const response = await fetch(
`${process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!}/databases/${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!}/collections/${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_FATURAS_ID!}/documents`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
'X-Appwrite-Key': process.env.APPWRITE_API_KEY!
},
body: JSON.stringify(body)
}
);
const data = await response.json();
if (response.status === 201 || response.status === 409) {
return NextResponse.json({ success: true, data });
}
return NextResponse.json(
{ success: false, error: 'Erro ao criar fatura', details: data },
{ status: response.status }
);
} catch (error) {
console.error('Erro na criação da fatura:', error);
return NextResponse.json({ success: false, error: 'Erro interno do servidor' }, { status: 500 });
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,165 +1,3 @@
// @ts-nocheck
import { NextRequest, NextResponse } from "next/server";
import { Client, Databases, Query } from "node-appwrite";
import { UserRole } from "@/types/auth";
export const runtime = "edge";
// Função para obter cliente Appwrite do servidor
function getServerClient() {
const client = new Client()
.setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!)
.setKey(process.env.APPWRITE_API_KEY!);
return new Databases(client);
}
// GET - Listar usuários com filtro por empresa para admins
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const userRole = searchParams.get("userRole");
const empresaId = searchParams.get("empresaId");
const databases = getServerClient();
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
const queries = [];
// Se for admin (admin), filtrar apenas usuários da mesma empresa
if (userRole === UserRole.ADMIN && empresaId) {
queries.push(Query.contains("empresas_array", empresaId));
}
// Não mostrar admins para admins comuns
if (userRole === UserRole.ADMIN) {
queries.push(Query.notEqual("nivel", UserRole.ADMIN));
}
const response = await databases.listDocuments(
databaseId,
collectionId,
queries
);
return NextResponse.json({
success: true,
data: response.documents,
total: response.total,
});
} catch (error: any) {
console.error("Erro ao listar usuários:", error);
return NextResponse.json(
{ success: false, error: "Erro ao carregar usuários" },
{ status: 500 }
);
}
}
// POST - Criar novo usuário (apenas admins)
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const {
nome,
email,
senha,
cpf,
nivel,
empresaId,
userRole, // Role do usuário que está criando
} = body;
// Validações
if (!nome || !email || !senha || !cpf || !nivel) {
return NextResponse.json(
{ success: false, error: "Todos os campos são obrigatórios" },
{ status: 400 }
);
}
// Verificar permissões
if (userRole !== UserRole.ADMIN && userRole !== UserRole.ADMIN) {
return NextResponse.json(
{ success: false, error: "Permissão insuficiente" },
{ status: 403 }
);
}
// Admin só pode criar employees e delivery
if (
userRole === UserRole.ADMIN &&
![UserRole.EMPLOYEE, UserRole.DELIVERY].includes(nivel)
) {
return NextResponse.json(
{
success: false,
error: "Admins só podem criar employees e delivery",
},
{ status: 403 }
);
}
const databases = getServerClient();
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
// Verificar se já existe usuário com este email
const existingUsers = await databases.listDocuments(
databaseId,
collectionId,
[Query.equal("email", email)]
);
if (existingUsers.documents.length > 0) {
return NextResponse.json(
{ success: false, error: "Já existe um usuário com este email" },
{ status: 400 }
);
}
// Criar conta no Appwrite Auth (isso precisaria ser feito via SDK de servidor)
// Por enquanto, vamos simular a criação retornando um ID único
const authId = `user_${Date.now()}_${Math.random()
.toString(36)
.substr(2, 9)}`;
// Preparar dados do usuário
const usuarioData = {
"nome-civil": nome,
cpf: cpf,
"auth-id-appwrite": authId,
email: email,
nivel: nivel,
enderecos: [],
empresas_array: userRole === UserRole.ADMIN ? [empresaId] : [],
};
// Criar documento do usuário
const response = await databases.createDocument(
databaseId,
collectionId,
"unique()",
usuarioData
);
return NextResponse.json({
success: true,
data: response,
message: "Usuário criado com sucesso",
});
} catch (error: any) {
console.error("Erro ao criar usuário:", error);
return NextResponse.json(
{ success: false, error: "Erro interno do servidor" },
{ status: 500 }
);
}
}
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,165 +1,3 @@
// @ts-nocheck
import { NextRequest, NextResponse } from "next/server";
import { Client, Databases, Query } from "node-appwrite";
import { UserRole } from "@/types/auth";
export const runtime = "edge";
// Função para obter cliente Appwrite do servidor
function getServerClient() {
const client = new Client()
.setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!)
.setKey(process.env.APPWRITE_API_KEY!);
return new Databases(client);
}
// GET - Listar usuários com filtro por empresa para admins
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const userRole = searchParams.get("userRole");
const empresaId = searchParams.get("empresaId");
const databases = getServerClient();
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
const queries = [];
// Se for admin (admin), filtrar apenas usuários da mesma empresa
if (userRole === UserRole.ADMIN && empresaId) {
queries.push(Query.contains("empresas_array", empresaId));
}
// Não mostrar admins para admins comuns
if (userRole === UserRole.ADMIN) {
queries.push(Query.notEqual("nivel", UserRole.ADMIN));
}
const response = await databases.listDocuments(
databaseId,
collectionId,
queries
);
return NextResponse.json({
success: true,
data: response.documents,
total: response.total,
});
} catch (error: any) {
console.error("Erro ao listar usuários:", error);
return NextResponse.json(
{ success: false, error: "Erro ao carregar usuários" },
{ status: 500 }
);
}
}
// POST - Criar novo usuário (apenas admins)
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const {
nome,
email,
senha,
cpf,
nivel,
empresaId,
userRole, // Role do usuário que está criando
} = body;
// Validações
if (!nome || !email || !senha || !cpf || !nivel) {
return NextResponse.json(
{ success: false, error: "Todos os campos são obrigatórios" },
{ status: 400 }
);
}
// Verificar permissões
if (userRole !== UserRole.ADMIN && userRole !== UserRole.ADMIN) {
return NextResponse.json(
{ success: false, error: "Permissão insuficiente" },
{ status: 403 }
);
}
// Admin só pode criar employees e delivery
if (
userRole === UserRole.ADMIN &&
![UserRole.EMPLOYEE, UserRole.DELIVERY].includes(nivel)
) {
return NextResponse.json(
{
success: false,
error: "Admins só podem criar employees e delivery",
},
{ status: 403 }
);
}
const databases = getServerClient();
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
// Verificar se já existe usuário com este email
const existingUsers = await databases.listDocuments(
databaseId,
collectionId,
[Query.equal("email", email)]
);
if (existingUsers.documents.length > 0) {
return NextResponse.json(
{ success: false, error: "Já existe um usuário com este email" },
{ status: 400 }
);
}
// Criar conta no Appwrite Auth (isso precisaria ser feito via SDK de servidor)
// Por enquanto, vamos simular a criação retornando um ID único
const authId = `user_${Date.now()}_${Math.random()
.toString(36)
.substr(2, 9)}`;
// Preparar dados do usuário
const usuarioData = {
"nome-civil": nome,
cpf: cpf,
"auth-id-appwrite": authId,
email: email,
nivel: nivel,
enderecos: [],
empresas_array: userRole === UserRole.ADMIN ? [empresaId] : [],
};
// Criar documento do usuário
const response = await databases.createDocument(
databaseId,
collectionId,
"unique()",
usuarioData
);
return NextResponse.json({
success: true,
data: response,
message: "Usuário criado com sucesso",
});
} catch (error: any) {
console.error("Erro ao criar usuário:", error);
return NextResponse.json(
{ success: false, error: "Erro interno do servidor" },
{ status: 500 }
);
}
}
import { DELETE, GET, PATCH, POST, PUT } from '../../_backendProxy'
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,82 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
export async function GET(request: NextRequest) {
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
return NextResponse.json(
{ success: false, error: 'Configuração do servidor ausente' },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_PAGAMENTOS_ID!;
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get('limit')) || 10;
const page = Number(searchParams.get('page')) || 1;
const search = searchParams.get('search') || '';
const offset = (page - 1) * limit;
const client = new Client().setEndpoint(endpoint).setProject(projectId).setKey(apiKey);
const databases = new Databases(client);
const queries = [Query.limit(limit), Query.offset(offset)];
if (search) queries.push(Query.search('status', search));
const response = await databases.listDocuments(
databaseId,
collectionId,
queries
);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total
});
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Erro ao carregar pagamentos' },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const response = await fetch(`${process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!}/databases/${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!}/collections/${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_PAGAMENTOS_ID!}/documents`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
'X-Appwrite-Key': process.env.APPWRITE_API_KEY!
},
body: JSON.stringify(body)
});
const data = await response.json();
if (response.status === 201 || response.status === 409) {
return NextResponse.json({ success: true, data });
} else {
return NextResponse.json(
{ success: false, error: 'Erro ao criar pagamento', details: data },
{ status: response.status }
);
}
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Erro interno do servidor' },
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,82 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../../_backendProxy'
export const runtime = 'edge';
export async function GET(request: NextRequest) {
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
return NextResponse.json(
{ success: false, error: 'Configuração do servidor ausente' },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_PAGAMENTOS_ID!;
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get('limit')) || 10;
const page = Number(searchParams.get('page')) || 1;
const search = searchParams.get('search') || '';
const offset = (page - 1) * limit;
const client = new Client().setEndpoint(endpoint).setProject(projectId).setKey(apiKey);
const databases = new Databases(client);
const queries = [Query.limit(limit), Query.offset(offset)];
if (search) queries.push(Query.search('status', search));
const response = await databases.listDocuments(
databaseId,
collectionId,
queries
);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total
});
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Erro ao carregar pagamentos' },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const response = await fetch(`${process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!}/databases/${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!}/collections/${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_PAGAMENTOS_ID!}/documents`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
'X-Appwrite-Key': process.env.APPWRITE_API_KEY!
},
body: JSON.stringify(body)
});
const data = await response.json();
if (response.status === 201 || response.status === 409) {
return NextResponse.json({ success: true, data });
} else {
return NextResponse.json(
{ success: false, error: 'Erro ao criar pagamento', details: data },
{ status: response.status }
);
}
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Erro interno do servidor' },
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,105 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
export async function GET(request: NextRequest) {
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
return NextResponse.json(
{ success: false, error: 'Configuração do servidor ausente' },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_PEDIDOS_ID!;
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get('limit')) || 10;
const page = Number(searchParams.get('page')) || 1;
const status = searchParams.get('status') || '';
const search = searchParams.get('search') || '';
const offset = (page - 1) * limit;
const client = new Client().setEndpoint(endpoint).setProject(projectId).setKey(apiKey);
const databases = new Databases(client);
const queries = [Query.limit(limit), Query.offset(offset)];
if (status) queries.push(Query.equal('status', status));
if (search) queries.push(Query.search('comprador', search));
const response = await databases.listDocuments(databaseId, collectionId, queries);
return NextResponse.json({ success: true, documents: response.documents, total: response.total });
} catch (error) {
return NextResponse.json({ success: false, error: 'Erro ao carregar pedidos' }, { status: 500 });
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
// Validar campos obrigatórios
if (!body.compradorID) {
return NextResponse.json(
{ success: false, error: 'Campo compradorID é obrigatório' },
{ status: 400 }
);
}
if (!body.status) {
return NextResponse.json(
{ success: false, error: 'Campo status é obrigatório' },
{ status: 400 }
);
}
// Estruturar dados para o Appwrite
const documentData = {
documentId: 'unique()',
data: {
compradorID: body.compradorID,
status: body.status,
// Campos opcionais
'valor-total': body['valor-total'] || 0,
itens: Array.isArray(body.itens) ? body.itens : (body.itens ? [body.itens] : []),
quantidade: Array.isArray(body.quantidade) ? body.quantidade :
(Array.isArray(body.qtdade) ? body.qtdade :
(body.quantidade ? [body.quantidade] : [1]))
}
};
const response = await fetch(
`${process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!}/databases/${process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!}/collections/${process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_PEDIDOS_ID!}/documents`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!,
'X-Appwrite-Key': process.env.APPWRITE_API_KEY!,
},
body: JSON.stringify(documentData),
}
);
const data = await response.json();
if (response.status === 201 || response.status === 409) {
return NextResponse.json({ success: true, data });
}
return NextResponse.json(
{ success: false, error: 'Erro ao criar pedido', details: data },
{ status: response.status }
);
} catch (error) {
console.error('Erro na API de pedidos:', error);
return NextResponse.json({ success: false, error: 'Erro interno do servidor' }, { status: 500 });
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,65 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
export const runtime = 'edge';
export async function GET(request: NextRequest) {
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
return NextResponse.json({ success: false, error: 'Configuração do servidor ausente' }, { status: 500 });
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_PRODUTOS_ID!;
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get('limit')) || 10;
const page = Number(searchParams.get('page')) || 1;
const offset = (page - 1) * limit;
const client = new Client().setEndpoint(endpoint).setProject(projectId).setKey(apiKey);
const databases = new Databases(client);
const response = await databases.listDocuments(databaseId, collectionId, [
Query.limit(limit),
Query.offset(offset)
]);
return NextResponse.json({ success: true, documents: response.documents, total: response.total });
} catch (error) {
console.error('Erro ao listar produtos:', error);
return NextResponse.json({ success: false, error: 'Erro ao carregar produtos' }, { status: 500 });
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const response = await fetch('https://nyc.cloud.appwrite.io/v1/databases/marketplace/collections/produtos/documents', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Appwrite-Project': 'saveinmed-api',
'X-Appwrite-Key': process.env.APPWRITE_API_KEY!
},
body: JSON.stringify(body)
});
const data = await response.json();
if (response.status === 201 || response.status === 409) {
return NextResponse.json({ success: true, data });
} else {
return NextResponse.json({ success: false, error: 'Erro ao criar produto', details: data }, { status: response.status });
}
} catch (error) {
console.error('Erro na criação do produto:', error);
return NextResponse.json({ success: false, error: 'Erro interno do servidor' }, { status: 500 });
}
}
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,142 +1,3 @@
// @ts-nocheck
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases, Query } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
const DATABASE_ID = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const COLLECTION_CATALOGO = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CATALOGO_PRODUTOS_ID!;
const COLLECTION_CATEGORIAS = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CATEGORIAS_ID!;
const createDatabasesClient = () => {
const apiKey = process.env.APPWRITE_API_KEY;
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID;
if (!apiKey || !endpoint || !projectId) {
throw new Error('Configuração do Appwrite ausente');
}
const client = new Client().setEndpoint(endpoint).setProject(projectId).setKey(apiKey);
return new Databases(client);
};
const mapeamentoCategorias: { [key: string]: string } = {
dipirona: 'RX',
cetaphil: 'Dermo',
sabonete: 'Dermo',
dermo: 'Dermo',
vitamina: 'Nutrição',
suplemento: 'Nutrição',
generico: 'Genérico',
diabetes: 'Diabetes',
insulina: 'Diabetes',
medicamento: 'RX',
remedio: 'RX',
};
export async function POST(request: NextRequest) {
try {
const databases = createDatabasesClient();
const categoriasResponse = await databases.listDocuments(
DATABASE_ID,
COLLECTION_CATEGORIAS,
[Query.limit(100)]
);
const categorias = categoriasResponse.documents;
const categoriasPorNome: { [key: string]: string } = {};
categorias.forEach((cat: any) => {
categoriasPorNome[String(cat.nome).toLowerCase()] = cat.$id;
});
const produtosResponse = await databases.listDocuments(
DATABASE_ID,
COLLECTION_CATALOGO,
[Query.limit(100)]
);
const produtos = produtosResponse.documents;
const resultados = [];
for (const produto of produtos as any[]) {
const descricao = String(produto.descricao || '').toLowerCase();
let categoriaEncontrada = null;
let nomeCategoria = '';
for (const [palavra, nomeCategoriaMapeada] of Object.entries(mapeamentoCategorias)) {
if (descricao.includes(palavra)) {
const categoriaId = categoriasPorNome[nomeCategoriaMapeada.toLowerCase()];
if (categoriaId) {
categoriaEncontrada = categoriaId;
nomeCategoria = nomeCategoriaMapeada;
break;
}
}
}
if (!categoriaEncontrada) {
categoriaEncontrada = categoriasPorNome['rx'] || categoriasPorNome['medicamento'];
nomeCategoria = 'RX';
}
try {
await databases.updateDocument(
DATABASE_ID,
COLLECTION_CATALOGO,
produto.$id,
{ categorias: categoriaEncontrada }
);
resultados.push({
produtoId: produto.$id,
descricao: produto.descricao,
categoria: nomeCategoria,
sucesso: true,
});
} catch (updateError) {
resultados.push({
produtoId: produto.$id,
descricao: produto.descricao,
categoria: nomeCategoria,
sucesso: false,
erro: updateError instanceof Error ? updateError.message : String(updateError),
});
}
await new Promise((resolve) => setTimeout(resolve, 100));
}
return NextResponse.json({
sucesso: true,
mensagem: 'Relacionamento de categorias concluído',
totalProdutos: produtos.length,
resultados,
categoriasDisponiveis: Object.keys(categoriasPorNome),
});
} catch (error) {
console.error('[API] Erro no relacionamento:', error);
return NextResponse.json(
{
sucesso: false,
erro: error instanceof Error ? error.message : String(error),
mensagem: 'Erro ao relacionar categorias',
},
{ status: 500 }
);
}
}
export async function GET(_request: NextRequest) {
return NextResponse.json({
mensagem: 'Use POST para executar o relacionamento de categorias',
instrucoes: [
'1. Faça uma requisição POST para esta rota',
'2. O sistema irá relacionar automaticamente produtos com categorias',
'3. Após a execução, vá em /produtos para verificar',
],
});
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,75 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export const runtime = 'edge';
const DATABASE_ID = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const COLLECTION_CATALOGO = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CATALOGO_PRODUTOS_ID!;
const createDatabasesClient = () => {
const apiKey = process.env.APPWRITE_API_KEY;
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID;
if (!apiKey || !endpoint || !projectId) {
throw new Error('Configuração do Appwrite ausente');
}
const client = new Client().setEndpoint(endpoint).setProject(projectId).setKey(apiKey);
return new Databases(client);
};
export async function POST(request: NextRequest) {
try {
const { produtoId, categoriaId, subcategoriaId } = await request.json();
if (!produtoId?.trim()) {
return NextResponse.json(
{ sucesso: false, erro: 'ID do produto é obrigatório' },
{ status: 400 }
);
}
const updateData: Record<string, string> = {};
if (categoriaId?.trim()) {
updateData.categoria = categoriaId.trim();
}
if (subcategoriaId?.trim()) {
updateData.subcategoria = subcategoriaId.trim();
}
if (Object.keys(updateData).length === 0) {
return NextResponse.json(
{ sucesso: false, erro: 'Pelo menos uma categoria ou subcategoria deve ser fornecida' },
{ status: 400 }
);
}
const databases = createDatabasesClient();
const produtoAtualizado = await databases.updateDocument(
DATABASE_ID,
COLLECTION_CATALOGO,
produtoId,
updateData
);
return NextResponse.json({
sucesso: true,
produto: produtoAtualizado,
mensagem: 'Produto relacionado com categoria/subcategoria com sucesso!',
});
} catch (error) {
console.error('[API] Erro ao relacionar produto:', error);
return NextResponse.json(
{
sucesso: false,
erro: error instanceof Error ? error.message : 'Erro desconhecido',
mensagem: 'Erro ao relacionar produto com categoria',
},
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,75 +1,3 @@
import { NextRequest, NextResponse } from 'next/server';
import { Client, Databases } from 'node-appwrite';
import { DELETE, GET, PATCH, POST, PUT } from '../../_backendProxy'
export const runtime = 'edge';
const DATABASE_ID = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const COLLECTION_CATALOGO = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_CATALOGO_PRODUTOS_ID!;
const createDatabasesClient = () => {
const apiKey = process.env.APPWRITE_API_KEY;
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID;
if (!apiKey || !endpoint || !projectId) {
throw new Error('Configuração do Appwrite ausente');
}
const client = new Client().setEndpoint(endpoint).setProject(projectId).setKey(apiKey);
return new Databases(client);
};
export async function POST(request: NextRequest) {
try {
const { produtoId, categoriaId, subcategoriaId } = await request.json();
if (!produtoId?.trim()) {
return NextResponse.json(
{ sucesso: false, erro: 'ID do produto é obrigatório' },
{ status: 400 }
);
}
const updateData: Record<string, string> = {};
if (categoriaId?.trim()) {
updateData.categoria = categoriaId.trim();
}
if (subcategoriaId?.trim()) {
updateData.subcategoria = subcategoriaId.trim();
}
if (Object.keys(updateData).length === 0) {
return NextResponse.json(
{ sucesso: false, erro: 'Pelo menos uma categoria ou subcategoria deve ser fornecida' },
{ status: 400 }
);
}
const databases = createDatabasesClient();
const produtoAtualizado = await databases.updateDocument(
DATABASE_ID,
COLLECTION_CATALOGO,
produtoId,
updateData
);
return NextResponse.json({
sucesso: true,
produto: produtoAtualizado,
mensagem: 'Produto relacionado com categoria/subcategoria com sucesso!',
});
} catch (error) {
console.error('[API] Erro ao relacionar produto:', error);
return NextResponse.json(
{
sucesso: false,
erro: error instanceof Error ? error.message : 'Erro desconhecido',
mensagem: 'Erro ao relacionar produto com categoria',
},
{ status: 500 }
);
}
}
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,208 +1,3 @@
// @ts-nocheck
import { NextRequest, NextResponse } from "next/server";
import { Client, Databases, Query } from "node-appwrite";
// Runtime edge para melhor performance
export const runtime = "edge";
// 🔍 GET - Listar subcategorias
export async function GET(request: NextRequest) {
console.log("📋 [API] Listando subcategorias...");
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error("❌ [API] APPWRITE_API_KEY não configurada");
return NextResponse.json(
{ sucesso: false, erro: "Configuração do servidor ausente" },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_SUBCATEGORIAS_ID!;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
const { searchParams } = new URL(request.url);
const categoriaId = searchParams.get("categoriaId");
const queries = [];
if (categoriaId) {
queries.push(Query.equal("categoria", categoriaId));
}
const response = await databases.listDocuments(
databaseId,
collectionId,
queries
);
console.log(
`✅ [API] ${response.documents.length} subcategorias carregadas!`
);
return NextResponse.json({
sucesso: true,
subcategorias: response.documents,
total: response.total,
});
} catch (error) {
console.error("💥 [API] Erro ao listar subcategorias:", error);
return NextResponse.json(
{ sucesso: false, erro: "Erro ao carregar subcategorias" },
{ status: 500 }
);
}
}
// âž• POST - Criar subcategoria
export async function POST(request: NextRequest) {
console.log("âž• [API] Criando nova subcategoria...");
try {
const body = await request.json();
console.log("📤 [API] Dados recebidos:", body);
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error("❌ [API] APPWRITE_API_KEY não configurada");
return NextResponse.json(
{ sucesso: false, erro: "Configuração do servidor ausente" },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_SUBCATEGORIAS_ID!;
// Validação dos dados obrigatórios
if (!body.nome?.trim()) {
console.error("❌ [API] Nome da subcategoria é obrigatório");
return NextResponse.json(
{ sucesso: false, erro: "Nome da subcategoria é obrigatório" },
{ status: 400 }
);
}
if (!body.categoria?.trim()) {
console.error("❌ [API] Categoria pai é obrigatória");
return NextResponse.json(
{ sucesso: false, erro: "Categoria pai é obrigatória" },
{ status: 400 }
);
}
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
// Preparar dados para criação - estrutura robusta
const dadosSubcategoria = {
nome: body.nome.trim(),
categoria: body.categoria.trim(),
descricao: body.descricao?.trim() || "",
slug: body.slug?.trim() || body.nome.toLowerCase().replace(/\s+/g, "-"),
};
console.log("📝 [API] Dados preparados para criação:", dadosSubcategoria);
// Tentar criar com dados completos primeiro
try {
const novaSubcategoria = await databases.createDocument(
databaseId,
collectionId,
'unique()', // Usar string em vez de ID.unique()
dadosSubcategoria
);
console.log("✅ [API] Subcategoria criada com sucesso:", novaSubcategoria.$id);
return NextResponse.json({
sucesso: true,
success: true, // Compatibilidade dupla
subcategoria: novaSubcategoria,
data: novaSubcategoria,
mensagem: `Subcategoria "${body.nome}" criada com sucesso!`,
});
} catch (createError: any) {
console.warn("⚠️ [API] Primeira tentativa falhou, tentando com dados simplificados:", createError.message);
// Se falhar, tentar apenas com dados essenciais
try {
const dadosSimplesSubcategoria = {
nome: body.nome.trim(),
categoria: body.categoria.trim(),
};
console.log("📝 [API] Tentando com dados simplificados:", dadosSimplesSubcategoria);
const novaSubcategoria = await databases.createDocument(
databaseId,
collectionId,
'unique()',
dadosSimplesSubcategoria
);
console.log("✅ [API] Subcategoria criada com dados simplificados!");
return NextResponse.json({
sucesso: true,
success: true,
subcategoria: novaSubcategoria,
data: novaSubcategoria,
mensagem: `Subcategoria "${body.nome}" criada com sucesso (modo simplificado)!`,
});
} catch (secondError: any) {
console.error("❌ [API] Segunda tentativa também falhou:", secondError);
throw secondError; // Deixar o catch principal tratar
}
}
} catch (error: any) {
console.error("💥 [API] Erro na criação:", error);
// Tratamento específico para erros do Appwrite
if (error.code) {
return NextResponse.json(
{
sucesso: false,
success: false,
erro: `Erro do Appwrite: ${error.message}`,
details: {
code: error.code,
type: error.type,
message: error.message
}
},
{ status: error.code === 400 ? 400 : 500 }
);
}
return NextResponse.json(
{
sucesso: false,
success: false,
erro: "Erro interno do servidor",
details: error instanceof Error ? error.message : String(error)
},
{ status: 500 }
);
}
}
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -1,188 +1,3 @@
// @ts-nocheck
import { NextRequest, NextResponse } from "next/server";
import { Client, Databases, Query, ID } from "node-appwrite";
export const runtime = 'edge';
// Força recompilação para aplicar mudanças de fallback
export async function GET(request: NextRequest) {
console.log("📋 [API] Listando usuários...");
try {
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error("❌ [API] APPWRITE_API_KEY não configurada");
return NextResponse.json(
{ success: false, error: "Configuração do servidor ausente" },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
const { searchParams } = new URL(request.url);
const limit = Number(searchParams.get("limit")) || 10;
const page = Number(searchParams.get("page")) || 1;
const termoBuscado = searchParams.get("termoBuscado") || "";
const authId = searchParams.get("authId");
const offset = (page - 1) * limit;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
const queries = [];
if (authId) {
// Buscar por auth-id-appwrite específico
queries.push(Query.equal("auth-id-appwrite", authId));
queries.push(Query.limit(1));
} else {
// Busca normal com paginação
if (termoBuscado) {
queries.push(Query.search("nome-civil", termoBuscado));
}
queries.push(Query.limit(limit));
queries.push(Query.offset(offset));
}
const response = await databases.listDocuments(
databaseId,
collectionId,
queries
);
console.log(`✅ [API] ${response.total} usuários carregados!`);
return NextResponse.json({
success: true,
documents: response.documents,
total: response.total,
});
} catch (error) {
console.error("💥 [API] Erro ao listar usuários:", error);
return NextResponse.json(
{ success: false, error: "Erro ao carregar usuários" },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
console.log("➕ [API] Criando novo usuário...");
try {
const body = await request.json();
console.log("📤 [API] Dados recebidos:", body);
const apiKey = process.env.APPWRITE_API_KEY;
if (!apiKey) {
console.error("❌ [API] APPWRITE_API_KEY não configurada");
return NextResponse.json(
{ success: false, error: "Configuração do servidor ausente" },
{ status: 500 }
);
}
const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!;
const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!;
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID!;
const collectionId =
process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
const client = new Client()
.setEndpoint(endpoint)
.setProject(projectId)
.setKey(apiKey);
const databases = new Databases(client);
try {
// Verificar se já existe um usuário com o mesmo auth-id-appwrite
const existingUsers = await databases.listDocuments(
databaseId,
collectionId,
[Query.equal("auth-id-appwrite", body["auth-id-appwrite"])]
);
if (existingUsers.documents.length > 0) {
console.log("⚠️ [API] Usuário já existe com este auth-id-appwrite");
return NextResponse.json({
success: true,
data: existingUsers.documents[0],
message: "Usuário já existe",
});
}
// Criar novo documento usando o SDK
const response = await databases.createDocument(
databaseId,
collectionId,
ID.unique(),
body
);
console.log("✅ [API] Usuário criado com sucesso!");
return NextResponse.json({ success: true, data: response });
} catch (appwriteError: any) {
// Se for erro de autorização, usar fallback local
if (appwriteError.code === 401 || appwriteError.type === 'user_unauthorized') {
console.log('⚠️ [API] Erro de autorização detectado, usando fallback local...');
// Simular criação bem-sucedida para desenvolvimento
const mockResponse = {
$id: 'mock-' + Date.now(),
$createdAt: new Date().toISOString(),
$updatedAt: new Date().toISOString(),
$permissions: [],
$databaseId: databaseId,
$collectionId: collectionId,
...body
};
console.log('✅ [API] Usuário simulado criado com sucesso (fallback)!');
return NextResponse.json({
success: true,
data: mockResponse,
message: 'Usuário criado usando fallback local (desenvolvimento)',
fallback: true
});
}
// Para outros tipos de erro, relançar
throw appwriteError;
}
} catch (error: any) {
console.error("💥 [API] Erro na criação:", error);
// Se for erro de documento duplicado, retornar sucesso
if (
error.code === 409 ||
error.message?.includes("Document with the requested ID already exists")
) {
console.log("⚠️ [API] Documento já existe, retornando sucesso");
return NextResponse.json({
success: true,
message: "Usuário já existe",
});
}
return NextResponse.json(
{
success: false,
error: "Erro interno do servidor",
details: error.message,
},
{ status: 500 }
);
}
}
import { DELETE, GET, PATCH, POST, PUT } from '../_backendProxy'
export { DELETE, GET, PATCH, POST, PUT }

View file

@ -25,6 +25,44 @@ export namespace Models {
}
}
export class Client {
setEndpoint(_value: string) {
return this;
}
setProject(_value: string) {
return this;
}
setKey(_value: string) {
return this;
}
}
export class Databases {
constructor(_client?: Client) {}
listDocuments(..._args: any[]) {
return Promise.resolve({ documents: [], total: 0 });
}
getDocument(..._args: any[]) {
return Promise.resolve(null);
}
createDocument(..._args: any[]) {
return Promise.resolve({});
}
updateDocument(..._args: any[]) {
return Promise.resolve({});
}
deleteDocument(..._args: any[]) {
return Promise.resolve({ success: true });
}
}
export const client: any = {};
export const databases: any = {
listDocuments: (..._args: any[]) => Promise.resolve({ documents: [], total: 0 }),

View file

@ -2,6 +2,9 @@
"compilerOptions": {
"baseUrl": ".",
"paths": {
"node-appwrite": [
"src/lib/appwrite"
],
"@/*": [
"src/*"
]