refactor(frontend): decouple catalog components and api routes from appwrite stub
This commit is contained in:
parent
48a54a616e
commit
a1eb0efc72
6 changed files with 213 additions and 334 deletions
|
|
@ -1,56 +1,63 @@
|
|||
// @ts-nocheck
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { databases } from "@/lib/appwrite";
|
||||
import { Query } from "@/lib/appwrite";
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { Client, Databases, Query } from 'node-appwrite';
|
||||
|
||||
export const runtime = "edge";
|
||||
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...");
|
||||
console.log('[API] Debug registro usuario...');
|
||||
|
||||
try {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const userId = searchParams.get("userId");
|
||||
const userId = searchParams.get('userId');
|
||||
|
||||
if (!userId) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: "userId é obrigatório" },
|
||||
{ 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 collectionId = process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_USUARIOS_ID!;
|
||||
const databases = createDatabasesClient();
|
||||
|
||||
console.log("🔠[API] Buscando usuário com auth-id-appwrite:", userId);
|
||||
console.log('[API] Buscando usuário com auth-id-appwrite:', userId);
|
||||
|
||||
// Buscar usuário pelo auth-id-appwrite
|
||||
const response = await databases.listDocuments(databaseId, collectionId, [
|
||||
Query.equal("auth-id-appwrite", userId),
|
||||
Query.equal('auth-id-appwrite', userId),
|
||||
Query.limit(1),
|
||||
]);
|
||||
|
||||
if (response.documents.length === 0) {
|
||||
console.log("⌠[API] Usuário não encontrado");
|
||||
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",
|
||||
message: 'Usuário não encontrado na base de dados',
|
||||
});
|
||||
}
|
||||
|
||||
const usuario = response.documents[0];
|
||||
const usuario = response.documents[0] as Record<string, any>;
|
||||
|
||||
console.log("✅ [API] Usuário encontrado:", usuario.$id);
|
||||
|
||||
// Análise detalhada dos dados
|
||||
const analise = {
|
||||
id: usuario.$id,
|
||||
"auth-id-appwrite": usuario["auth-id-appwrite"],
|
||||
"nome-civil": {
|
||||
valor: usuario["nome-civil"],
|
||||
preenchido: !!usuario["nome-civil"],
|
||||
'auth-id-appwrite': usuario['auth-id-appwrite'],
|
||||
'nome-civil': {
|
||||
valor: usuario['nome-civil'],
|
||||
preenchido: !!usuario['nome-civil'],
|
||||
},
|
||||
cpf: {
|
||||
valor: usuario.cpf,
|
||||
|
|
@ -64,9 +71,7 @@ export async function GET(request: NextRequest) {
|
|||
valido:
|
||||
Array.isArray(usuario.enderecos) &&
|
||||
usuario.enderecos.length > 0 &&
|
||||
usuario.enderecos.some(
|
||||
(endereco) => endereco && endereco.trim() !== ""
|
||||
),
|
||||
usuario.enderecos.some((endereco: string) => endereco && endereco.trim() !== ''),
|
||||
},
|
||||
empresas_array: {
|
||||
valor: usuario.empresas_array,
|
||||
|
|
@ -80,29 +85,22 @@ export async function GET(request: NextRequest) {
|
|||
},
|
||||
};
|
||||
|
||||
const dadosFaltantes = [];
|
||||
const dadosFaltantes: string[] = [];
|
||||
|
||||
// Verificar cada campo
|
||||
if (!analise["nome-civil"].preenchido || !analise.cpf.preenchido) {
|
||||
dadosFaltantes.push("Dados pessoais");
|
||||
if (!analise['nome-civil'].preenchido || !analise.cpf.preenchido) {
|
||||
dadosFaltantes.push('Dados pessoais');
|
||||
}
|
||||
|
||||
if (!analise.enderecos.valido) {
|
||||
dadosFaltantes.push("Endereço");
|
||||
dadosFaltantes.push('Endereço');
|
||||
}
|
||||
|
||||
if (!analise.empresas_array.valido) {
|
||||
dadosFaltantes.push("Empresa");
|
||||
dadosFaltantes.push('Empresa');
|
||||
}
|
||||
|
||||
const isCompleto = dadosFaltantes.length === 0;
|
||||
|
||||
console.log("📋 [API] Análise completa:", {
|
||||
isCompleto,
|
||||
dadosFaltantes,
|
||||
analise,
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
found: true,
|
||||
|
|
@ -112,11 +110,10 @@ export async function GET(request: NextRequest) {
|
|||
dadosCompletos: usuario,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("⌠[API] Erro ao debugar registro:", error);
|
||||
console.error('[API] Erro ao debugar registro:', error);
|
||||
return NextResponse.json(
|
||||
{ success: false, error: "Erro ao verificar registro" },
|
||||
{ success: false, error: 'Erro ao verificar registro' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,85 +1,74 @@
|
|||
// @ts-nocheck
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { databases, Query } from "@/lib/appwrite";
|
||||
// @ts-nocheck
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { Client, Databases, Query } from 'node-appwrite';
|
||||
|
||||
// Runtime edge para melhor performance
|
||||
export const runtime = "edge";
|
||||
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 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);
|
||||
};
|
||||
|
||||
// Mapeamento de produtos para categorias
|
||||
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",
|
||||
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 {
|
||||
console.log("🔗 [API] Iniciando relacionamento de categorias...");
|
||||
const databases = createDatabasesClient();
|
||||
|
||||
// 1. Buscar todas as categorias
|
||||
const categoriasResponse = await databases.listDocuments(
|
||||
DATABASE_ID,
|
||||
COLLECTION_CATEGORIAS,
|
||||
[Query.limit(100)]
|
||||
);
|
||||
|
||||
console.log(
|
||||
`📋 [API] Encontradas ${categoriasResponse.documents.length} categorias`
|
||||
);
|
||||
|
||||
const categorias = categoriasResponse.documents;
|
||||
const categoriasPorNome: { [key: string]: string } = {};
|
||||
|
||||
categorias.forEach((cat) => {
|
||||
categoriasPorNome[cat.nome.toLowerCase()] = cat.$id;
|
||||
categorias.forEach((cat: any) => {
|
||||
categoriasPorNome[String(cat.nome).toLowerCase()] = cat.$id;
|
||||
});
|
||||
|
||||
console.log(
|
||||
"📋 [API] Categorias disponÃveis:",
|
||||
Object.keys(categoriasPorNome)
|
||||
);
|
||||
|
||||
// 2. Buscar todos os produtos do catálogo
|
||||
const produtosResponse = await databases.listDocuments(
|
||||
DATABASE_ID,
|
||||
COLLECTION_CATALOGO,
|
||||
[Query.limit(100)]
|
||||
);
|
||||
|
||||
console.log(
|
||||
`📦 [API] Encontrados ${produtosResponse.documents.length} produtos`
|
||||
);
|
||||
|
||||
const produtos = produtosResponse.documents;
|
||||
const resultados = [];
|
||||
|
||||
// 3. Para cada produto, determinar e atribuir categoria
|
||||
for (const produto of produtos) {
|
||||
const descricao = produto.descricao.toLowerCase();
|
||||
for (const produto of produtos as any[]) {
|
||||
const descricao = String(produto.descricao || '').toLowerCase();
|
||||
let categoriaEncontrada = null;
|
||||
let nomeCategoria = "";
|
||||
let nomeCategoria = '';
|
||||
|
||||
// Tentar encontrar categoria por palavra-chave
|
||||
for (const [palavra, nomeCategoriaMapeada] of Object.entries(
|
||||
mapeamentoCategorias
|
||||
)) {
|
||||
for (const [palavra, nomeCategoriaMapeada] of Object.entries(mapeamentoCategorias)) {
|
||||
if (descricao.includes(palavra)) {
|
||||
const categoriaId =
|
||||
categoriasPorNome[nomeCategoriaMapeada.toLowerCase()];
|
||||
const categoriaId = categoriasPorNome[nomeCategoriaMapeada.toLowerCase()];
|
||||
if (categoriaId) {
|
||||
categoriaEncontrada = categoriaId;
|
||||
nomeCategoria = nomeCategoriaMapeada;
|
||||
|
|
@ -88,26 +77,17 @@ export async function POST(request: NextRequest) {
|
|||
}
|
||||
}
|
||||
|
||||
// Se não encontrou, usar RX como padrão
|
||||
if (!categoriaEncontrada) {
|
||||
categoriaEncontrada =
|
||||
categoriasPorNome["rx"] || categoriasPorNome["medicamento"];
|
||||
nomeCategoria = "RX";
|
||||
categoriaEncontrada = categoriasPorNome['rx'] || categoriasPorNome['medicamento'];
|
||||
nomeCategoria = 'RX';
|
||||
}
|
||||
|
||||
console.log(
|
||||
`📦 [API] Produto: ${produto.descricao} → Categoria: ${nomeCategoria}`
|
||||
);
|
||||
|
||||
try {
|
||||
// Atualizar produto com categoria
|
||||
await databases.updateDocument(
|
||||
DATABASE_ID,
|
||||
COLLECTION_CATALOGO,
|
||||
produto.$id,
|
||||
{
|
||||
categorias: categoriaEncontrada,
|
||||
}
|
||||
{ categorias: categoriaEncontrada }
|
||||
);
|
||||
|
||||
resultados.push({
|
||||
|
|
@ -116,63 +96,47 @@ export async function POST(request: NextRequest) {
|
|||
categoria: nomeCategoria,
|
||||
sucesso: true,
|
||||
});
|
||||
|
||||
console.log(
|
||||
`✅ [API] Produto ${produto.$id} atualizado com categoria ${nomeCategoria}`
|
||||
);
|
||||
} catch (updateError) {
|
||||
console.error(
|
||||
`⌠[API] Erro ao atualizar produto ${produto.$id}:`,
|
||||
updateError
|
||||
);
|
||||
|
||||
resultados.push({
|
||||
produtoId: produto.$id,
|
||||
descricao: produto.descricao,
|
||||
categoria: nomeCategoria,
|
||||
sucesso: false,
|
||||
erro:
|
||||
updateError instanceof Error
|
||||
? updateError.message
|
||||
: String(updateError),
|
||||
erro: updateError instanceof Error ? updateError.message : String(updateError),
|
||||
});
|
||||
}
|
||||
|
||||
// Pequena pausa para não sobrecarregar
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
console.log("✅ [API] Processo de relacionamento concluÃdo!");
|
||||
|
||||
return NextResponse.json({
|
||||
sucesso: true,
|
||||
mensagem: "Relacionamento de categorias concluÃdo",
|
||||
mensagem: 'Relacionamento de categorias concluído',
|
||||
totalProdutos: produtos.length,
|
||||
resultados: resultados,
|
||||
resultados,
|
||||
categoriasDisponiveis: Object.keys(categoriasPorNome),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("⌠[API] Erro no relacionamento:", 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",
|
||||
mensagem: 'Erro ao relacionar categorias',
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
export async function GET(_request: NextRequest) {
|
||||
return NextResponse.json({
|
||||
mensagem: "Use POST para executar o relacionamento de categorias",
|
||||
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",
|
||||
'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',
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,35 +1,36 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { databases } from "@/lib/appwrite";
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { Client, Databases } from 'node-appwrite';
|
||||
|
||||
// Runtime edge para melhor performance
|
||||
export const runtime = "edge";
|
||||
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_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();
|
||||
|
||||
console.log("🔗 [API] Relacionando produto com categoria:", {
|
||||
produtoId,
|
||||
categoriaId,
|
||||
subcategoriaId,
|
||||
});
|
||||
|
||||
if (!produtoId?.trim()) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
sucesso: false,
|
||||
erro: "ID do produto é obrigatório",
|
||||
},
|
||||
{ sucesso: false, erro: 'ID do produto é obrigatório' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Preparar dados para atualização
|
||||
const updateData: any = {};
|
||||
const updateData: Record<string, string> = {};
|
||||
|
||||
if (categoriaId?.trim()) {
|
||||
updateData.categoria = categoriaId.trim();
|
||||
|
|
@ -41,15 +42,12 @@ export async function POST(request: NextRequest) {
|
|||
|
||||
if (Object.keys(updateData).length === 0) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
sucesso: false,
|
||||
erro: "Pelo menos uma categoria ou subcategoria deve ser fornecida",
|
||||
},
|
||||
{ sucesso: false, erro: 'Pelo menos uma categoria ou subcategoria deve ser fornecida' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Atualizar produto no catálogo
|
||||
const databases = createDatabasesClient();
|
||||
const produtoAtualizado = await databases.updateDocument(
|
||||
DATABASE_ID,
|
||||
COLLECTION_CATALOGO,
|
||||
|
|
@ -57,24 +55,19 @@ export async function POST(request: NextRequest) {
|
|||
updateData
|
||||
);
|
||||
|
||||
console.log(
|
||||
"✅ [API] Produto relacionado com sucesso:",
|
||||
produtoAtualizado.$id
|
||||
);
|
||||
|
||||
return NextResponse.json({
|
||||
sucesso: true,
|
||||
produto: produtoAtualizado,
|
||||
mensagem: "Produto relacionado com categoria/subcategoria com sucesso!",
|
||||
mensagem: 'Produto relacionado com categoria/subcategoria com sucesso!',
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("❌ [API] Erro ao relacionar produto:", 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",
|
||||
erro: error instanceof Error ? error.message : 'Erro desconhecido',
|
||||
mensagem: 'Erro ao relacionar produto com categoria',
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
// @ts-nocheck
|
||||
// @ts-nocheck
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Models } from '@/lib/appwrite';
|
||||
import { ShoppingCartIcon, MinusIcon } from '@heroicons/react/24/outline';
|
||||
import { useCatalogoProdutos } from '@/hooks/useCatalogoProdutos';
|
||||
import { CatalogoProdutoDocument } from '@/types/legacyEntities';
|
||||
|
||||
interface ItemCarrinho {
|
||||
produto: Models.Document;
|
||||
produto: CatalogoProdutoDocument;
|
||||
quantidade: number;
|
||||
}
|
||||
|
||||
|
|
@ -14,16 +14,16 @@ interface CatalogoComCarrinhoProps {
|
|||
}
|
||||
|
||||
const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAoCarrinho }) => {
|
||||
const { catalogoProdutos, loading, listarCatalogo, totalCatalogoProdutos, currentPage } = useCatalogoProdutos();
|
||||
const { catalogoProdutos, loading, listarCatalogo, totalCatalogoProdutos } = useCatalogoProdutos();
|
||||
const [carrinho, setCarrinho] = useState<ItemCarrinho[]>([]);
|
||||
const [termoBusca, setTermoBusca] = useState('');
|
||||
const [quantidades, setQuantidades] = useState<Record<string, number>>({});
|
||||
|
||||
useEffect(() => {
|
||||
listarCatalogo(1, termoBusca);
|
||||
}, [termoBusca]);
|
||||
}, [termoBusca, listarCatalogo]);
|
||||
|
||||
const adicionarAoCarrinho = (produto: Models.Document) => {
|
||||
const adicionarAoCarrinho = (produto: CatalogoProdutoDocument) => {
|
||||
const quantidade = quantidades[produto.$id] || 1;
|
||||
const itemExistente = carrinho.find(item => item.produto.$id === produto.$id);
|
||||
|
||||
|
|
@ -39,7 +39,6 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
setCarrinho([...carrinho, novoItem]);
|
||||
}
|
||||
|
||||
// Reset quantidade para 1 após adicionar
|
||||
setQuantidades(prev => ({ ...prev, [produto.$id]: 1 }));
|
||||
|
||||
if (onAdicionarAoCarrinho) {
|
||||
|
|
@ -47,8 +46,6 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const removerDoCarrinho = (produtoId: string) => {
|
||||
setCarrinho(carrinho.filter(item => item.produto.$id !== produtoId));
|
||||
};
|
||||
|
|
@ -60,12 +57,10 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
}, 0);
|
||||
};
|
||||
|
||||
const formatarPreco = (preco: number) => {
|
||||
return new Intl.NumberFormat('pt-BR', {
|
||||
style: 'currency',
|
||||
currency: 'BRL'
|
||||
}).format(preco);
|
||||
};
|
||||
const formatarPreco = (preco: number) => new Intl.NumberFormat('pt-BR', {
|
||||
style: 'currency',
|
||||
currency: 'BRL'
|
||||
}).format(preco);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
|
|
@ -77,7 +72,6 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Barra de Busca */}
|
||||
<div className="bg-white p-4 rounded-lg shadow">
|
||||
<div className="flex gap-4">
|
||||
<input
|
||||
|
|
@ -94,11 +88,10 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* Lista de Produtos */}
|
||||
<div className="lg:col-span-2">
|
||||
<div className="bg-white rounded-lg shadow">
|
||||
<div className="p-4 border-b border-gray-200">
|
||||
<h2 className="text-lg font-semibold text-gray-900">Catálogo de Produtos</h2>
|
||||
<h2 className="text-lg font-semibold text-gray-900">Catálogo de Produtos</h2>
|
||||
<p className="text-sm text-gray-500">{totalCatalogoProdutos} produtos encontrados</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -111,14 +104,10 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
<div key={produto.$id} className="p-4 hover:bg-gray-50 transition-colors">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1">
|
||||
<h3 className="font-medium text-gray-900 mb-1">
|
||||
{produto.descricao}
|
||||
</h3>
|
||||
<h3 className="font-medium text-gray-900 mb-1">{produto.descricao}</h3>
|
||||
<div className="flex items-center gap-4 text-sm text-gray-500">
|
||||
<span>Código: {produto['codigo-interno']}</span>
|
||||
{produto['codigo-ean'] && (
|
||||
<span>EAN: {produto['codigo-ean']}</span>
|
||||
)}
|
||||
<span>Código: {produto['codigo-interno']}</span>
|
||||
{produto['codigo-ean'] && <span>EAN: {produto['codigo-ean']}</span>}
|
||||
{produto.laboratorios?.length > 0 ? (
|
||||
<span>Lab: {produto.laboratorios[0].nome || produto.laboratorios[0]}</span>
|
||||
) : produto.laboratorio && (
|
||||
|
|
@ -131,29 +120,21 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
)}
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<span className="text-lg font-bold text-green-600">
|
||||
{formatarPreco(preco)}
|
||||
</span>
|
||||
<span className="text-lg font-bold text-green-600">{formatarPreco(preco)}</span>
|
||||
{produto['preco-fabrica'] && produto.pmc && produto['preco-fabrica'] !== produto.pmc && (
|
||||
<span className="ml-2 text-sm text-gray-500 line-through">
|
||||
{formatarPreco(produto['preco-fabrica'])}
|
||||
</span>
|
||||
<span className="ml-2 text-sm text-gray-500 line-through">{formatarPreco(produto['preco-fabrica'])}</span>
|
||||
)}
|
||||
{produto['desconto-comercial'] && produto['desconto-comercial'] > 0 && (
|
||||
<div className="text-xs text-orange-600 mt-1">
|
||||
Desconto: {formatarPreco(produto['desconto-comercial'])}
|
||||
</div>
|
||||
<div className="text-xs text-orange-600 mt-1">Desconto: {formatarPreco(produto['desconto-comercial'])}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Quantidade */}
|
||||
<div className="flex items-center border border-gray-300 rounded-lg px-3 py-1">
|
||||
<span className="text-sm font-medium">Qtd: {quantidade}</span>
|
||||
</div>
|
||||
|
||||
{/* Botão Adicionar ao Carrinho */}
|
||||
<button
|
||||
onClick={() => adicionarAoCarrinho(produto)}
|
||||
className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
|
||||
|
|
@ -170,7 +151,6 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Carrinho */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="bg-white rounded-lg shadow sticky top-4">
|
||||
<div className="p-4 border-b border-gray-200">
|
||||
|
|
@ -190,17 +170,11 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
return (
|
||||
<div key={item.produto.$id} className="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-sm text-gray-900 line-clamp-2">
|
||||
{item.produto.descricao}
|
||||
</h4>
|
||||
<p className="text-xs text-gray-500">
|
||||
{formatarPreco(preco)} x {item.quantidade}
|
||||
</p>
|
||||
<h4 className="font-medium text-sm text-gray-900 line-clamp-2">{item.produto.descricao}</h4>
|
||||
<p className="text-xs text-gray-500">{formatarPreco(preco)} x {item.quantidade}</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-medium text-green-600">
|
||||
{formatarPreco(preco * item.quantidade)}
|
||||
</span>
|
||||
<span className="font-medium text-green-600">{formatarPreco(preco * item.quantidade)}</span>
|
||||
<button
|
||||
onClick={() => removerDoCarrinho(item.produto.$id)}
|
||||
className="text-red-500 hover:text-red-700 transition-colors"
|
||||
|
|
@ -215,9 +189,7 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
<div className="border-t border-gray-200 pt-3 mt-4">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<span className="font-semibold text-gray-900">Total:</span>
|
||||
<span className="font-bold text-lg text-green-600">
|
||||
{formatarPreco(calcularTotal())}
|
||||
</span>
|
||||
<span className="font-bold text-lg text-green-600">{formatarPreco(calcularTotal())}</span>
|
||||
</div>
|
||||
|
||||
<button className="w-full bg-green-600 text-white py-3 rounded-lg hover:bg-green-700 transition-colors font-medium">
|
||||
|
|
@ -235,4 +207,3 @@ const CatalogoComCarrinho: React.FC<CatalogoComCarrinhoProps> = ({ onAdicionarAo
|
|||
};
|
||||
|
||||
export default CatalogoComCarrinho;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
// @ts-nocheck
|
||||
// @ts-nocheck
|
||||
'use client';
|
||||
import React, { useState } from 'react';
|
||||
import { Models } from '@/lib/appwrite';
|
||||
import { useCarrinho } from '@/contexts/CarrinhoContext';
|
||||
import { ShoppingCartIcon, PlusIcon, CheckIcon } from '@heroicons/react/24/outline';
|
||||
import { ShoppingCartIcon, CheckIcon } from '@heroicons/react/24/outline';
|
||||
import { CatalogoProdutoDocument } from '@/types/legacyEntities';
|
||||
|
||||
interface CatalogoProdutosComprasProps {
|
||||
produtos: Models.Document[];
|
||||
produtos: CatalogoProdutoDocument[];
|
||||
loading: boolean;
|
||||
isChangingPage?: boolean;
|
||||
totalProdutos: number;
|
||||
|
|
@ -14,7 +14,7 @@ interface CatalogoProdutosComprasProps {
|
|||
pageSize: number;
|
||||
onPrevPage: () => void;
|
||||
onNextPage: () => void;
|
||||
onRowClick?: (produto: Models.Document) => void;
|
||||
onRowClick?: (produto: CatalogoProdutoDocument) => void;
|
||||
}
|
||||
|
||||
const CatalogoProdutosCompras: React.FC<CatalogoProdutosComprasProps> = ({
|
||||
|
|
@ -31,27 +31,23 @@ const CatalogoProdutosCompras: React.FC<CatalogoProdutosComprasProps> = ({
|
|||
const { adicionarItem } = useCarrinho();
|
||||
const [produtosAdicionados, setProdutosAdicionados] = useState<Set<string>>(new Set());
|
||||
|
||||
const formatarPreco = (preco: number) => {
|
||||
return new Intl.NumberFormat('pt-BR', {
|
||||
style: 'currency',
|
||||
currency: 'BRL'
|
||||
}).format(preco);
|
||||
};
|
||||
const formatarPreco = (preco: number) => new Intl.NumberFormat('pt-BR', {
|
||||
style: 'currency',
|
||||
currency: 'BRL'
|
||||
}).format(preco);
|
||||
|
||||
const obterPreco = (produto: Models.Document) => {
|
||||
const obterPreco = (produto: CatalogoProdutoDocument) => {
|
||||
return produto['preco-unitario'] || produto['preco-fabrica'] || produto.pmc || 0;
|
||||
};
|
||||
|
||||
const obterQuantidadeDisponivel = (produto: Models.Document) => {
|
||||
// Usar quantidade real do produto ou retornar 0 se não informado
|
||||
return (produto as any).quantidade || (produto as any).estoque || 0;
|
||||
const obterQuantidadeDisponivel = (produto: CatalogoProdutoDocument) => {
|
||||
return produto.quantidade || produto.estoque || 0;
|
||||
};
|
||||
|
||||
const handleAdicionarAoCarrinho = (produto: Models.Document, event: React.MouseEvent) => {
|
||||
event.stopPropagation(); // Evita que o clique no botão dispare o onRowClick
|
||||
adicionarItem(produto, 1);
|
||||
const handleAdicionarAoCarrinho = (produto: CatalogoProdutoDocument, event: React.MouseEvent) => {
|
||||
event.stopPropagation();
|
||||
adicionarItem(produto as any, 1);
|
||||
|
||||
// Adicionar feedback visual temporário
|
||||
setProdutosAdicionados(prev => new Set(prev).add(produto.$id));
|
||||
setTimeout(() => {
|
||||
setProdutosAdicionados(prev => {
|
||||
|
|
@ -79,7 +75,6 @@ const CatalogoProdutosCompras: React.FC<CatalogoProdutosComprasProps> = ({
|
|||
|
||||
return (
|
||||
<div className="bg-white rounded-lg shadow-sm">
|
||||
{/* Grid de Produtos */}
|
||||
<div className="p-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
||||
{produtos.map(produto => {
|
||||
|
|
@ -100,7 +95,6 @@ const CatalogoProdutosCompras: React.FC<CatalogoProdutosComprasProps> = ({
|
|||
}`}
|
||||
onClick={() => onRowClick && onRowClick(produto)}
|
||||
>
|
||||
{/* Indicador de Estoque Baixo */}
|
||||
{estoqueStatus === 'baixo' && (
|
||||
<div className="absolute top-2 right-2">
|
||||
<span className="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-red-100 text-red-800">
|
||||
|
|
@ -111,36 +105,25 @@ const CatalogoProdutosCompras: React.FC<CatalogoProdutosComprasProps> = ({
|
|||
{estoqueStatus === 'medio' && (
|
||||
<div className="absolute top-2 right-2">
|
||||
<span className="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800">
|
||||
Estoque Médio
|
||||
Estoque Médio
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{/* Header do Card */}
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div className={`flex-1 ${estoqueStatus !== 'alto' ? 'pr-20' : ''}`}>
|
||||
<h3 className="text-sm font-semibold text-gray-900 line-clamp-2 mb-1">
|
||||
{produto.descricao}
|
||||
</h3>
|
||||
<p className="text-xs text-gray-500">
|
||||
Código: {produto['codigo-interno']}
|
||||
</p>
|
||||
<h3 className="text-sm font-semibold text-gray-900 line-clamp-2 mb-1">{produto.descricao}</h3>
|
||||
<p className="text-xs text-gray-500">Código: {produto['codigo-interno']}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Informações do Produto */}
|
||||
<div className="space-y-3 mb-4">
|
||||
{produto['codigo-ean'] && (
|
||||
<p className="text-xs text-gray-500">
|
||||
EAN: {produto['codigo-ean']}
|
||||
</p>
|
||||
)}
|
||||
{produto['codigo-ean'] && <p className="text-xs text-gray-500">EAN: {produto['codigo-ean']}</p>}
|
||||
|
||||
{/* Laboratório */}
|
||||
{produto.laboratorios?.length > 0 ? (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{produto.laboratorios.slice(0, 2).map((lab: any) => (
|
||||
<span key={lab.$id} className="inline-block bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs">
|
||||
{lab.nome}
|
||||
{produto.laboratorios.slice(0, 2).map((lab: any, index: number) => (
|
||||
<span key={lab.$id || index} className="inline-block bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs">
|
||||
{lab.nome || lab}
|
||||
</span>
|
||||
))}
|
||||
{produto.laboratorios.length > 2 && (
|
||||
|
|
@ -148,19 +131,17 @@ const CatalogoProdutosCompras: React.FC<CatalogoProdutosComprasProps> = ({
|
|||
)}
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-xs text-gray-400">Sem laboratório</span>
|
||||
<span className="text-xs text-gray-400">Sem laboratório</span>
|
||||
)}
|
||||
|
||||
{/* Categoria */}
|
||||
{produto.categorias && (
|
||||
<span className="inline-block bg-blue-100 text-blue-700 px-2 py-1 rounded text-xs">
|
||||
{produto.categorias.nome}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/* Quantidade DisponÃvel */}
|
||||
<div className="flex items-center justify-between text-xs">
|
||||
<span className="text-gray-600">DisponÃvel:</span>
|
||||
<span className="text-gray-600">Disponível:</span>
|
||||
<span className={`font-medium ${
|
||||
estoqueStatus === 'alto'
|
||||
? 'text-green-600'
|
||||
|
|
@ -173,44 +154,32 @@ const CatalogoProdutosCompras: React.FC<CatalogoProdutosComprasProps> = ({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Seção de Preços */}
|
||||
<div className="space-y-2 mb-4">
|
||||
{/* Preço Principal */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-600">Preço:</span>
|
||||
<span className="text-sm text-gray-600">Preço:</span>
|
||||
{preco > 0 ? (
|
||||
<span className="text-lg font-bold text-green-600">
|
||||
{formatarPreco(preco)}
|
||||
</span>
|
||||
<span className="text-lg font-bold text-green-600">{formatarPreco(preco)}</span>
|
||||
) : (
|
||||
<span className="text-sm text-gray-400">
|
||||
Não informado
|
||||
</span>
|
||||
<span className="text-sm text-gray-400">Não informado</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Preços Adicionais */}
|
||||
<div className="grid grid-cols-2 gap-2 text-xs">
|
||||
{produto['preco-fabrica'] && produto['preco-fabrica'] !== preco && (
|
||||
<div className="text-center">
|
||||
<span className="block text-gray-500">Fábrica</span>
|
||||
<span className="font-medium text-gray-700">
|
||||
{formatarPreco(produto['preco-fabrica'])}
|
||||
</span>
|
||||
<span className="block text-gray-500">Fábrica</span>
|
||||
<span className="font-medium text-gray-700">{formatarPreco(produto['preco-fabrica'])}</span>
|
||||
</div>
|
||||
)}
|
||||
{produto.pmc && produto.pmc !== preco && (
|
||||
<div className="text-center">
|
||||
<span className="block text-gray-500">PMC</span>
|
||||
<span className="font-medium text-gray-700">
|
||||
{formatarPreco(produto.pmc)}
|
||||
</span>
|
||||
<span className="font-medium text-gray-700">{formatarPreco(produto.pmc)}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Botão de Ação */}
|
||||
<div className="flex justify-center">
|
||||
<button
|
||||
onClick={(e) => handleAdicionarAoCarrinho(produto, e)}
|
||||
|
|
@ -241,17 +210,15 @@ const CatalogoProdutosCompras: React.FC<CatalogoProdutosComprasProps> = ({
|
|||
})}
|
||||
</div>
|
||||
|
||||
{/* Mensagem quando não há produtos */}
|
||||
{produtos.length === 0 && (
|
||||
<div className="text-center py-12">
|
||||
<ShoppingCartIcon className="w-12 h-12 text-gray-300 mx-auto mb-4" />
|
||||
<h3 className="text-lg font-medium text-gray-900 mb-2">Nenhum produto encontrado</h3>
|
||||
<p className="text-gray-500">Tente ajustar os filtros de busca ou verifique se há produtos cadastrados.</p>
|
||||
<p className="text-gray-500">Tente ajustar os filtros de busca ou verifique se há produtos cadastrados.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Paginação */}
|
||||
{produtos.length > 0 && (
|
||||
<div className="bg-gray-50 border-t border-gray-200 px-6 py-4">
|
||||
<div className="flex items-center justify-between">
|
||||
|
|
@ -263,15 +230,13 @@ const CatalogoProdutosCompras: React.FC<CatalogoProdutosComprasProps> = ({
|
|||
>
|
||||
Anterior
|
||||
</button>
|
||||
<span className="px-3 py-2 text-sm text-gray-700 font-medium">
|
||||
Página {currentPage} de {totalPages}
|
||||
</span>
|
||||
<span className="px-3 py-2 text-sm text-gray-700 font-medium">Página {currentPage} de {totalPages}</span>
|
||||
<button
|
||||
onClick={onNextPage}
|
||||
disabled={currentPage >= totalPages || isChangingPage}
|
||||
className="px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200"
|
||||
>
|
||||
Próxima
|
||||
Próxima
|
||||
</button>
|
||||
</div>
|
||||
<div className="text-sm text-gray-700 font-medium">
|
||||
|
|
|
|||
|
|
@ -1,18 +1,8 @@
|
|||
import { Models } from "@/lib/appwrite";
|
||||
import { CatalogoProdutoDocument } from '@/types/legacyEntities';
|
||||
|
||||
export interface CatalogoProdutoData extends Models.Document {
|
||||
descricao: string;
|
||||
nome?: string;
|
||||
"codigo-interno"?: string;
|
||||
"codigo-ean"?: string;
|
||||
"preco-original"?: number;
|
||||
"preco-atual"?: number;
|
||||
"preco-fabrica"?: number;
|
||||
pmc?: number;
|
||||
quantidade?: number;
|
||||
laboratorio?: string;
|
||||
categoria?: string;
|
||||
subcategoria?: string;
|
||||
export interface CatalogoProdutoData extends CatalogoProdutoDocument {
|
||||
'preco-original'?: number;
|
||||
'preco-atual'?: number;
|
||||
}
|
||||
|
||||
export interface ApiResponse<T = unknown> {
|
||||
|
|
@ -28,14 +18,14 @@ export interface PaginatedResponse<T> extends ApiResponse<T[]> {
|
|||
}
|
||||
|
||||
class CatalogoProdutoService {
|
||||
private readonly baseUrl = "/api/catalogo-produtos";
|
||||
private readonly baseUrl = '/api/catalogo-produtos';
|
||||
|
||||
private async parseResponse<T>(response: Response): Promise<T> {
|
||||
const data = await response.json().catch(() => ({}));
|
||||
|
||||
if (!response.ok) {
|
||||
const message =
|
||||
typeof data?.error === "string"
|
||||
typeof data?.error === 'string'
|
||||
? data.error
|
||||
: `Erro HTTP ${response.status}`;
|
||||
throw new Error(message);
|
||||
|
|
@ -44,36 +34,36 @@ class CatalogoProdutoService {
|
|||
return data as T;
|
||||
}
|
||||
|
||||
async listar(page = 1, limit = 10, termo = ""): Promise<PaginatedResponse<CatalogoProdutoData>> {
|
||||
async listar(page = 1, limit = 10, termo = ''): Promise<PaginatedResponse<CatalogoProdutoData>> {
|
||||
const params = new URLSearchParams({
|
||||
page: String(page),
|
||||
limit: String(limit),
|
||||
});
|
||||
|
||||
if (termo.trim()) {
|
||||
params.set("q", termo.trim());
|
||||
params.set('q', termo.trim());
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.baseUrl}?${params.toString()}`, {
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
method: 'GET',
|
||||
cache: 'no-store',
|
||||
});
|
||||
|
||||
const data = await this.parseResponse<Partial<PaginatedResponse<CatalogoProdutoData>>>(response);
|
||||
|
||||
const documents = Array.isArray(data.documents) ? data.documents : [];
|
||||
const filteredDocuments = termo.trim()
|
||||
? documents.filter((produto) => {
|
||||
? documents.filter(produto => {
|
||||
const values = [
|
||||
produto.descricao,
|
||||
produto.nome,
|
||||
produto["codigo-interno"],
|
||||
produto["codigo-ean"],
|
||||
produto['codigo-interno'],
|
||||
produto['codigo-ean'],
|
||||
]
|
||||
.filter(Boolean)
|
||||
.map((value) => String(value).toLowerCase());
|
||||
.map(value => String(value).toLowerCase());
|
||||
|
||||
return values.some((value) => value.includes(termo.trim().toLowerCase()));
|
||||
return values.some(value => value.includes(termo.trim().toLowerCase()));
|
||||
})
|
||||
: documents;
|
||||
|
||||
|
|
@ -90,8 +80,8 @@ class CatalogoProdutoService {
|
|||
|
||||
async obterPorId(id: string): Promise<ApiResponse<CatalogoProdutoData>> {
|
||||
const response = await fetch(`${this.baseUrl}/${id}`, {
|
||||
method: "GET",
|
||||
cache: "no-store",
|
||||
method: 'GET',
|
||||
cache: 'no-store',
|
||||
});
|
||||
|
||||
const data = await this.parseResponse<ApiResponse<CatalogoProdutoData>>(response);
|
||||
|
|
@ -103,9 +93,9 @@ class CatalogoProdutoService {
|
|||
|
||||
async criar(produtoData: Partial<CatalogoProdutoData>): Promise<ApiResponse<CatalogoProdutoData>> {
|
||||
const response = await fetch(this.baseUrl, {
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(produtoData),
|
||||
});
|
||||
|
|
@ -119,9 +109,9 @@ class CatalogoProdutoService {
|
|||
|
||||
async atualizar(id: string, produtoData: Partial<CatalogoProdutoData>): Promise<ApiResponse<CatalogoProdutoData>> {
|
||||
const response = await fetch(`${this.baseUrl}/${id}`, {
|
||||
method: "PATCH",
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(produtoData),
|
||||
});
|
||||
|
|
@ -135,7 +125,7 @@ class CatalogoProdutoService {
|
|||
|
||||
async deletar(id: string): Promise<ApiResponse<null>> {
|
||||
const response = await fetch(`${this.baseUrl}/${id}`, {
|
||||
method: "DELETE",
|
||||
method: 'DELETE',
|
||||
});
|
||||
|
||||
await this.parseResponse<ApiResponse<null>>(response);
|
||||
|
|
@ -145,4 +135,3 @@ class CatalogoProdutoService {
|
|||
|
||||
export const catalogoProdutoService = new CatalogoProdutoService();
|
||||
export type ProdutoData = CatalogoProdutoData;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue