Quickstarters
Como Construir um Backend de E-Commerce?
90 min
neste tutorial prático, você criará uma aplicação de e commerce robusta e completa do zero usando um backend como serviço ao longo do caminho, você dominará autenticação de usuário segura, garantindo que apenas compradores e administradores autorizados tenham acesso modelos de dados intuitivos, projetados para alimentar catálogos de produtos, perfis de clientes e históricos de pedidos apis restful e em tempo real, para que seu frontend esteja sempre sincronizado com o inventário, carrinhos e status de checkout pipelines de implantação automatizadas, permitindo que você envie atualizações com confiança e reverta se algo der errado ao final, você terá não apenas uma vitrine pronta para produção, mas também o conhecimento arquitetônico para estender, escalar e proteger qualquer aplicação web explore a aplicação de e commerce finalizada em ação em web e commerce app vamos começar! principais conclusões configuração rápida de backend lance e configure um modelo de dados completo de e‑commerce em minutos com a plataforma de low code da back4app fluxos de usuário seguros implemente um registro, login e logout robustos usando cloud code e tokens de sessão desenvolvimento com api first acesse seus dados através de endpoints rest/graphql gerados automaticamente e o sdk parse para qualquer cliente lógica de negócios em cloud code centralize operações principais—crud de produtos, gerenciamento de carrinho e checkout—enquanto aplica permissões implantação de frontend containerizado empacote e implante sua loja next js na implantação web da back4app para hospedagem consistente e escalável pré requisitos e configuração do ambiente para seguir este tutorial, certifique se de ter o seguinte uma conta back4app você pode se inscrever gratuitamente no site da back4app https //www back4app com/signup node js instalado, permitindo que você gerencie dependências com npm ou yarn familiaridade com javascript para escrever código de nuvem personalizado e aproveitar o sdk da back4app compreensão básica de conceitos de e commerce, como autenticação de usuário, gerenciamento de catálogo de produtos e processamento de pedidos git para controle de versão, para que você possa rastrear alterações, reverter se necessário e colaborar sem problemas garantir que você tenha os itens acima ajudará a maximizar as capacidades do back4app e implementar recursos chave de e commerce sem se sentir sobrecarregado criando e configurando sua conta back4app para começar a configurar seu backend de e commerce no back4app, visite back4app https //www back4app com e clique em inscrever se digite seu endereço de e mail, escolha uma senha forte e forneça os detalhes necessários assim que você verificar seu e mail, terá acesso ao painel do back4app página de inscrição do back4app dentro do painel, selecione criar novo app ou criar novo app e dê um nome ao seu projeto—algo descritivo para que você possa localizá lo facilmente mais tarde confirme suas escolhas e, em seguida, aguarde o processo de criação do aplicativo terminar o painel do projeto exibirá classes, análises e configurações criando um aplicativo back4app com esses passos, você criou uma plataforma de e commerce na próxima seção, você irá projetar seu esquema de dados e se preparar para gerenciamento de produtos, manuseio de pedidos e autenticação de usuários projetando seu esquema de dados de e commerce para implementar um backend escalável e sustentável para sua plataforma de e commerce, você organizará seus dados em torno de sete tabelas principais usuário , comprador , vendedor , produto , carrinho , pedido , e detalhesdopedido cada tabela desempenha um papel focado em apoiar a funcionalidade geral do sistema, e juntas formam um esquema normalizado e eficiente comece com a user tabela, que serve como a base para todas as identidades de usuário cada pessoa em sua plataforma—independentemente de seu papel—se autenticará usando esta tabela inclua campos como username , password , e email para gerenciar o login básico adicione emailverified para rastrear o status de verificação, e authdata se você planeja suportar logins de terceiros ou fluxos oauth para distinguir entre compradores e vendedores, defina um campo usertype este campo permite que você controle o acesso, gerencie visualizações e separe funcionalidades com base nos papéis dos usuários, mantendo ainda um sistema de login único e consistente em vez de misturar todos os tipos de usuários em uma tabela, crie tabelas separadas de buyer e seller que referenciam user via o campo userid isso permite que você armazene dados específicos de função sem sobrecarregar a tabela principal de usuários a tabela buyer pode conter campos relacionados a compras, como paymentinfo e shippingaddress , que são essenciais para os processos de checkout e entrega em contraste, a tabela seller rastreia atributos relevantes para comerciantes, como storename , bio , e phonenumber com essa separação, você pode gerenciar e consultar compradores e vendedores de forma independente, enquanto ainda os vincula de volta à sua identidade compartilhada em user sua produto tabela é onde os itens à venda são armazenados cada produto deve incluir informações descritivas básicas, como um nome, uma descrição detalhada e uma ou mais imagens para gerenciamento de preços e inventário, você também vai querer incluir campos para preço, status de disponibilidade via um booleano isactive , e quantidade em estoque sob quantityavailable crucialmente, cada produto deve estar vinculado ao vendedor que o listou para estabelecer essa relação, adicione uma sellerid chave estrangeira que referencia a seller tabela essa estrutura garante que cada item em seu catálogo esteja vinculado a um comerciante verificado e torna o filtragem específica do vendedor simples para lidar com o comportamento pré compra, introduza uma cart tabela cada carrinho pertence a um usuário, então inclua um userid campo que se conecta de volta ao user armazene um array de itens , cada um representando um produto que o usuário pretende comprar, junto com qualquer metadado que você precisar, como quantidade ou opções selecionadas rastrear o totalprice do carrinho permite que você exiba rapidamente resumos de checkout sem recalcular valores em cada solicitação essa configuração suporta a funcionalidade básica do carrinho e simplifica a persistência da sessão se você achar a estrutura de array limitante—particularmente se precisar registrar dados mais complexos em nível de item—você sempre pode refatorar os itens em uma tabela separada mais tarde quando um comprador faz um pedido, você registrará a transação na order tabela cada pedido está vinculado a um buyerid , referenciando a buyer tabela para garantir que o comprador seja válido e autorizado além desse link, armazene a orderdate , o atual orderstatus , e o valor monetário total sob o campo total isso lhe dá um resumo claro da compra e suporta fluxos de trabalho como rastreamento e cumprimento de pedidos uma vez que cada pedido pode conter múltiplos produtos, você precisará de uma orderdetails tabela para gerenciar os itens individuais essa tabela conecta cada item de volta ao seu pedido pai através de orderid , e ao produto comprado usando productid para registrar com precisão o estado da compra, inclua a quantidade comprada e o preçounitário no momento da venda separar os detalhes do pedido dessa forma permite que você crie relatórios, gere faturas e lide com devoluções ou ajustes com precisão este esquema, com sua clara separação de preocupações e integridade relacional, forma uma base sólida para o seu sistema de e commerce com o modelo de dados agora alinhado aos fluxos de trabalho do mundo real da sua plataforma, você está pronto para começar a implementá lo em seu backend comece configurando as tabelas user , comprador , e vendedor e construa a partir daí configurando classes no painel siga os passos abaixo para criar e vincular suas entidades no back4app você definirá classes para usuário , comprador , vendedor , carrinho , produto , pedido , e detalhesdopedido , e então estabelecerá ponteiros para representar relacionamentos como herança, um para muitos e muitos para muitos acesse o navegador de banco de dados abra o painel do seu aplicativo e crie uma nova classe chamada usuário clique em banco de dados no menu à esquerda back4app dashboard criando a classe “usuário” o back4app cria automaticamente uma classe user a user classe vem com as seguintes colunas nome de usuário senha email etc para adicionar a coluna tipodeusuário selecione adicionar uma nova coluna add new column forneça o nome da coluna, tipo de dado, valor padrão, etc add usertype column nota no parse, cada classe inclui um objectid campo padrão, que funciona como a chave primária isso significa que objectid servirá efetivamente como userid no seu modelo relacional criando a classe “comprador” para criar a classe comprador, volte para o database browser e selecione adicionar classe create new class escolha personalizado e nomeie como comprador add buyer class adicione uma coluna pointer chamada user , apontando para a classe user create userid class isso simula a “herança” referenciando o objectid , do usuário base 3\ adicione as seguintes colunas endereçodeentrega (string) informaçõesdepagamento (string) quando você cria um novo objeto comprador, você o vincula a um registro de usuário existente definindo buyer user para o objectid desse usuário criando a classe “vendedor” repita o mesmo processo para criar uma vendedor classe adicione uma coluna ponteiro chamada user referenciando a classe user adicione estas colunas adicionais nomedaloja (string) bio (string) númerodetelefone (número) criando a classe “produto” selecione criar uma classe novamente, nomeando a produto adicione uma coluna de ponteiro chamada vendedor apontando para a classe vendedor (isso impõe um relacionamento de um para muitos onde um vendedor pode ter muitos produtos) adicione as seguintes colunas nome (string) descrição (string) preço (número) quantidadedisponível (número) estáativo (booleano) imagens (array) armazena objetos que representam imagens do produto criando a classe “carrinho” clique em criar uma classe , nomeie a classe carrinho adicione uma coluna de ponteiro chamada usuário apontando para a classe usuário (isso vincula cada carrinho a um usuário específico) em seguida, adicione as seguintes colunas para representar os itens no carrinho itens (array) armazena objetos que representam cada item do carrinho cada item pode ser um objeto como { produto ponteiro para produto, quantidade número } preçototal (número) criando a classe “pedido” crie uma nova classe chamada order adicione uma coluna pointer chamada buyer que aponta para a classe buyer (indicando que um comprador pode ter muitos pedidos) inclua estas colunas orderdate (data ou string, dependendo da sua preferência) orderstatus (string) criando a classe “orderdetails” finalmente, crie uma classe chamada orderdetails adicione duas colunas pointer order → referencia order product → referencia product em seguida, adicione as colunas restantes quantity (número) unitprice (número) essa configuração permite um relacionamento muitos para muitos entre order e product através de orderdetails , uma vez que cada pedido pode incluir vários produtos, e cada produto pode aparecer em vários pedidos visualizando os relacionamentos aqui está um diagrama de entidade relacionamento (erd) simplificado refletindo as classes e seus ponteiros dbschema2 uma vez que essas classes estejam em vigor, você pode gerenciar inscrições e logins através da classe user , criar registros especializados de comprador ou vendedor para diferentes tipos de usuários, e armazenar informações de produtos ou pedidos com referências de chave estrangeira claras ao estruturar seu banco de dados dessa forma, você ganha um design limpo e de fácil manutenção para qualquer aplicação de e commerce com seu esquema em vigor, você está pronto para configurar autenticação e autorização para restringir quem pode listar produtos, fazer pedidos ou realizar tarefas administrativas o próximo passo mostrará como configurar fluxos de inscrição e login seguros que se baseiam nos papéis e classes que você acabou de definir implementando autenticação com back4app a autenticação segura é central para qualquer plataforma de e commerce, ajudando a proteger contas de usuários, detalhes de pagamento e dados pessoais o back4app simplifica isso com múltiplos métodos—desde combinações clássicas de nome de usuário/senha até logins sociais ou fluxos baseados em token—garantindo que você possa oferecer aos seus compradores uma experiência simples e segura para configurar a autenticação em sua aplicação de e commerce, você fará uso de código em nuvem o código em nuvem estende suas capacidades de backend permitindo que você escreva lógica de negócios personalizada sem hospedar seus próprios servidores isso significa que você pode validar pedidos, calcular taxas ou acionar notificações em eventos específicos—totalmente dentro da infraestrutura do back4app é uma maneira ideal de lidar com transações sensíveis ou processos de dados que precisam de controle rigoroso e execução rápida para habilitar o código em nuvem no back4app, abra o painel do seu aplicativo e localize a seção de código em nuvem find cloud code quando você clicar em código em nuvem , você verá um main js onde você pode começar a implementar funções personalizadas cloud code para implementar o fluxo de autenticação no back4app, você precisará implantar algumas funções no seu código em nuvem para cadastrar usuários, fazer login e logout registrar um novo usuário (comprador por padrão) para registrar um novo usuário, use o método de cadastro do parse defina campos padrão como username , password , e email , e inclua um campo personalizado para indicar o papel seja buyer ou seller por padrão, novos usuários são atribuídos ao papel de buyer até que escolham mudá lo para começar, crie um auth js arquivo no diretório de nuvem do seu código em nuvem e adicione o bloco de código abaixo parse cloud define('signupuser', async (request) => { const { name, password, confirmpassword, email, shippingaddress, paymentinfo } = request params; // validate password match if (password !== confirmpassword) { throw new error('passwords do not match'); } const user = new parse user(); user set('username', name); user set('password', password); user set('email', email); user set('usertype', "buyer"); try { // sign up the user const signedupuser = await user signup(); console log('user registered ', signedupuser id); // create a buyer record linked to the new user const buyer = parse object extend('buyer'); const buyer = new buyer(); buyer set('user', signedupuser); buyer set('shippingaddress', shippingaddress); buyer set('paymentinfo', paymentinfo); const savedbuyer = await buyer save(); console log('buyer created ', savedbuyer id); return { success true, message 'user registered and buyer created', userid signedupuser id, buyerid savedbuyer id }; } catch (error) { console error('sign up failed ', error); throw new error('sign up failed ' + error message); } }); esta função em nuvem lida com o registro de usuários para compradores ela valida a entrada, cria um novo usuário parse, atribui um papel ( buyer ), e armazena dados específicos do comprador em uma classe comprador separada fazer login usuários para autenticar usuários, chame o método embutido parse user login do parse e retorne o token de sessão para o cliente adicione o seguinte código ao seu auth js arquivo para implementar essa lógica no seu backend de código em nuvem parse cloud define("loginuser", async (request) => { const { email, password } = request params; try { const user = await parse user login(email, password); // example block users with disabled flag if (user get("isdisabled")) { throw new parse error(403, "account is disabled"); } return { sessiontoken user getsessiontoken(), userid user id, }; } catch (error) { throw new parse error(101, "invalid credentials"); } }); esta função recebe um email e uma senha do cliente, tenta autenticar o usuário e retorna o token de sessão se for bem sucedida se a conta estiver marcada como desativada, ela bloqueia o acesso e lança um erro claro sair para implementar a função de logout para seu backend, adicione o bloco de código abaixo ao seu auth js arquivo parse cloud define('logoutuser', async (request) => { const sessiontoken = request headers\['x parse session token']; if (!sessiontoken) { throw new error('session token required'); } const sessionquery = new parse query(' session'); sessionquery equalto('sessiontoken', sessiontoken); const session = await sessionquery first({ usemasterkey true }); if (session) { await session destroy({ usemasterkey true }); } return { success true, message 'session invalidated' }; }); isso encerra a sessão de forma segura no backend, impedindo o uso posterior do token com essas funções de cloud code em vigor, você agora tem um sistema de autenticação seguro que registra usuários com lógica baseada em funções autentica e autoriza o acesso usando tokens de sessão vincula contas de usuários a registros específicos de compradores suporta fluxos de login e logout limpos aproveita as ferramentas de verificação de sessão e e mail integradas do back4app construindo a lógica de negócios para seu app de ecommerce para gerenciar usuários, produtos, carrinhos e transações em sua plataforma de e commerce, você definirá uma série de funções de cloud code no back4app essas funções permitem que você crie, leia, atualize e exclua (crud) recursos como vendedores, produtos e pedidos, mantendo o controle de acesso seguro vinculado a funções de usuário abaixo está um conjunto de funções de cloud que demonstra como trabalhar com entidades chave vendedor , produto , carrinho , pedido , e detalhesdopedido cada função lida com uma operação específica do backend e garante que as permissões sejam aplicadas por meio da validação de usuários e verificações de funções vendedor crie um perfil de vendedor para um usuário que deseja oferecer produtos na plataforma criando um vendedor esta função atualiza o papel do usuário atual para vendedor e cria um vendedor registro com informações da loja para implementar isso no seu código em nuvem, primeiro crie um seller js arquivo e adicione o bloco de código abaixo a ele parse cloud define('createseller', async (request) => { const currentuser = request user; // get the current logged in user if (!currentuser) { throw new error('user is not logged in'); } try { // check and update the user type const usertype = currentuser get('usertype'); if (usertype === 'buyer') { currentuser set('usertype', 'seller'); await currentuser save(); } // create the seller object const { businessname, bio, phone } = request params; const seller = parse object extend('seller'); const seller = new seller(); seller set('user', currentuser); seller set('storename', businessname); seller set('bio', bio); seller set('phonenumber', number(phone)); const newseller = await seller save(); console log('seller created ', newseller id); return { success true, message 'seller account created', sellerid newseller id }; } catch (error) { console error('error creating seller ', error); throw new error('error creating seller ' + error message); } }); isso garante que apenas usuários autenticados possam se tornar vendedores, e vincula o vendedor registro ao usuário correspondente por meio de um ponteiro produto os produtos são listados por vendedores e podem ser navegados, consultados e comprados por compradores essas funções permitem que os vendedores criem, recuperem, atualizem e excluam seus produtos, e também fornecem acesso ao produto para os compradores criando um produto essa função adiciona um novo produto para um vendedor logado e anexa até três imagens do produto para implementar em seu código de nuvem, crie um product js arquivo e adicione o bloco de código abaixo a ele parse cloud define("addproduct", async (request) => { // destructure parameters sent from the client const { name, description, price, quantityavailable, isactive, imagefiles } = request params; // optional check if user is logged in (request user is available when an active session exists) const currentuser = request user; if (!currentuser) { throw new error("unauthorized you must be logged in to add a product "); } // ensure the user is indeed a seller by checking their usertype const usertype = currentuser get("usertype"); if (usertype != "seller") { throw new error("this user is not a seller "); } const seller = parse object extend("seller"); const query = new parse query(seller); query equalto("userid", currentuser); // match the pointer field in seller const sellerobj = await query first({ usemasterkey true }); if (!sellerobj) { throw new error("no matching 'seller' object found for this user "); } if(!array isarray(imagefiles) || imagefiles length > 3) { throw new error("a maximum of 3 images are provided"); } // create the new product object const product = parse object extend("product"); const product = new product(); product set("seller", sellerobj); // pointer to the seller product set("name", name); product set("description", description); product set("price", number(price)); product set("quantityavailable", number(quantityavailable)); product set("isactive", isactive); product set("images", imagefiles); // save the product to the database try { const savedproduct = await product save(null, { usemasterkey true }); return savedproduct; } catch (error) { throw new error(`could not create product ${error message}`); } }); esta função verifica se o usuário está logado e tem um papel de vendedor, se um seller correspondente existe e se não são enviadas mais de três imagens uma vez validado, armazena o produto e o vincula ao vendedor consultando todos os produtos esta função recupera todos os produtos no sistema, que podem ser usados para construir uma vitrine pública para implementar isso no seu código em nuvem, adicione o bloco de código abaixo ao seu products js arquivo parse cloud define("fetchallproducts", async (request) => { try { const product = parse object extend("product"); const query = new parse query(product); const products = await query find({ usemasterkey true }); // return products in a json friendly format return products map((product) => ({ id product id, sellerid product get("seller")? id, name product get("name"), description product get("description"), price product get("price"), quantityavailable product get("quantityavailable"), isactive product get("isactive"), createdat product createdat, updatedat product updatedat, })); } catch (error) { throw new error(`error fetching products ${error message}`); } }); esta função busca produtos com a usemasterkey flag e os formata para consumo no frontend consultando um único produto use esta função ao exibir informações detalhadas do produto para os compradores para implementar isso no seu código em nuvem, adicione o bloco de código abaixo ao seu products js arquivo parse cloud define("getsingleproduct", async (request) => { const { productid } = request params; const currentuser = request user; // ensure user is logged in if (!currentuser) { throw new error("you must be logged in to retrieve product information "); } if (!productid) { throw new error("missing required parameter productid "); } // query the product class const product = parse object extend("product"); const query = new parse query(product); query equalto("objectid", productid); try { const product = await query first({ usemasterkey true }); if (!product) { throw new error("product not found "); } // return a json friendly object return { objectid product id, name product get("name"), description product get("description"), price product get("price"), quantityavailable product get("quantityavailable"), isactive product get("isactive"), // optionally return more fields like images, category, etc }; } catch (error) { throw new error(`error fetching product ${error message}`); } }); esta função retorna detalhes completos do produto para um item ela verifica se um productid válido é passado e garante que o solicitante esteja logado consultando produtos do vendedor esta função permite que um vendedor recupere todos os seus próprios produtos para implementar isso no seu código em nuvem, adicione o bloco de código abaixo ao seu products js arquivo parse cloud define("getsellerproducts", async (request) => { const currentuser = request user; // ensure the user is logged in if (!currentuser) { throw new error("you must be logged in to fetch seller products "); } // if your schema depends on verifying the user is truly a seller, you can check usertype const usertype = currentuser get("usertype"); if (usertype !== "seller") { throw new error("only sellers can view their own products "); } // if you want to retrieve products for the currently logged in seller // fetch the seller record that points to currentuser const seller = parse object extend("seller"); const sellerquery = new parse query(seller); sellerquery equalto("user", currentuser); const sellerrecord = await sellerquery first({ usemasterkey true }); if (!sellerrecord) { throw new error("no matching seller record found for the current user "); } // finally, fetch all products pointing to this seller const product = parse object extend("product"); const productquery = new parse query(product); productquery equalto("seller", sellerrecord); productquery limit(1000); // adjust or paginate as needed try { const products = await productquery find({ usemasterkey true }); // return a more friendly json structure return products map((prod) => ({ objectid prod id, name prod get("name"), description prod get("description"), price prod get("price"), quantityavailable prod get("quantityavailable"), isactive prod get("isactive"), createdat prod createdat, updatedat prod updatedat, })); } catch (error) { throw new error(`error fetching seller products ${error message}`); } }); esta função confirma que o usuário é um vendedor, localiza o seller associado e consulta a product classe usando um ponteiro para o vendedor os vendedores usam isso para buscar todos os seus próprios produtos excluindo um produto esta função garante que apenas o vendedor que criou um produto pode excluí lo para implementar isso no seu código em nuvem, adicione o bloco de código abaixo ao seu products js arquivo parse cloud define("deleteproduct", async (request) => { const { productid } = request params; const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to delete a product "); } const usertype = currentuser get("usertype"); if (usertype !== "seller") { throw new error("only sellers can delete products "); } if (!productid) { throw new error("missing required parameter productid "); } // 1 find the seller record for the current user const seller = parse object extend("seller"); const sellerquery = new parse query(seller); sellerquery equalto("user", currentuser); const sellerrecord = await sellerquery first({ usemasterkey true }); if (!sellerrecord) { throw new error("no matching seller record found for the current user "); } // 2 fetch the product with a query that ensures the user owns it const product = parse object extend("product"); const productquery = new parse query(product); productquery equalto("objectid", productid); productquery equalto("seller", sellerrecord); // must match the correct seller const product = await productquery first({ usemasterkey true }); if (!product) { throw new error("product not found or you do not have permission to delete it "); } // 3 destroy the product try { await product destroy({ usemasterkey true }); return { message "product deleted successfully ", productid }; } catch (error) { throw new error(`error deleting product ${error message}`); } }); esta função confirma a propriedade do usuário e, em seguida, remove o produto do banco de dados atualizando um produto permitir que os vendedores modifiquem os detalhes de um produto usando esta função para implementar isso no seu código em nuvem, adicione o bloco de código abaixo ao seu products js arquivo parse cloud define("updateproduct", async (request) => { const { productid, name, description, price, quantityavailable, isactive } = request params; const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to update a product "); } const usertype = currentuser get("usertype"); if (usertype !== "seller") { throw new error("only sellers can update products "); } if (!productid) { throw new error("missing required parameter productid "); } // 1 find the seller record for the current user const seller = parse object extend("seller"); const sellerquery = new parse query(seller); sellerquery equalto("user", currentuser); const sellerrecord = await sellerquery first({ usemasterkey true }); if (!sellerrecord) { throw new error("no matching seller record found for the current user "); } // 2 fetch the product const product = parse object extend("product"); const query = new parse query(product); query equalto("objectid", productid); query equalto("seller", sellerrecord); // must match the seller to ensure ownership const product = await query first({ usemasterkey true }); if (!product) { throw new error("product not found or you do not have permission to modify it "); } // 3 update product fields if (name !== undefined) product set("name", name); if (description !== undefined) product set("description", description); if (price !== undefined) product set("price", price); if (quantityavailable !== undefined) product set("quantityavailable", quantityavailable); if (isactive !== undefined) product set("isactive", isactive); // 4 save changes try { const updatedproduct = await product save(null, { usemasterkey true }); return { objectid updatedproduct id, name updatedproduct get("name"), description updatedproduct get("description"), price updatedproduct get("price"), quantityavailable updatedproduct get("quantityavailable"), isactive updatedproduct get("isactive"), }; } catch (error) { throw new error(`error updating product ${error message}`); } }); isso garante que o usuário seja um vendedor, confirma a propriedade do produto e atualiza apenas os campos que são fornecidos na solicitação carrinho as carrinho funções permitem que os compradores gerenciem os itens que pretendem comprar essas funções incluem adicionar ao carrinho, atualizar quantidades, visualizar conteúdos e remover itens adicionando ao carrinho esta função adiciona um produto ao carrinho do comprador ou atualiza a quantidade se já existir para implementar isso, crie um cart js arquivo e adicione o bloco de código abaixo a ele parse cloud define("addtocart", async (request) => { const { productid, quantity } = request params; // ensure there is a currently logged in user const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to modify the cart "); } if (!productid || !quantity) { throw new error("missing required parameters productid and quantity "); } // 1 fetch or create the user's cart const cart = parse object extend("cart"); const cartquery = new parse query(cart); cartquery equalto("user", currentuser); let cart = await cartquery first({ usemasterkey true }); if (!cart) { cart = new cart(); cart set("user", currentuser); cart set("items", \[]); // initialize empty array cart set("totalprice", 0); // initialize price } // 2 fetch the product for price details (or any other attributes you need) const product = parse object extend("product"); const productquery = new parse query(product); productquery equalto("objectid", productid); const product = await productquery first({ usemasterkey true }); if (!product) { throw new error("product not found "); } const productprice = product get("price") || 0; // 3 insert or update the item in the cart const cartitems = cart get("items") || \[]; // check if this product is already in the cart const existingitemindex = cartitems findindex( (item) => item product objectid === productid ); if (existingitemindex >= 0) { // if product is already in cart, update the quantity cartitems\[existingitemindex] quantity += quantity; } else { // otherwise, add a new entry cartitems push({ product { type "pointer", classname "product", objectid productid, }, quantity quantity }); } // 4 recalculate total price // e g , summation of productprice quantity for each cart item let total = 0; for (const item of cartitems) { if (item product objectid === productid) { // use productprice from the newly fetched product total += productprice item quantity; } else { // this is a simplified approach ideally, you'd also store a price attribute on each item // or re fetch each product's price // for demonstration, we'll just skip them } } cart set("items", cartitems); cart set("totalprice", total); // 5 save the cart object try { const savedcart = await cart save(null, { usemasterkey true }); return { message "cart updated successfully", cartid savedcart id, items savedcart get("items"), totalprice savedcart get("totalprice"), }; } catch (error) { throw new error(`error saving cart ${error message}`); } }); ele garante que o usuário esteja autenticado, valida o produto, atualiza a lista de itens e recalcula o preço total do carrinho consultando o carrinho recupere o conteúdo do carrinho do usuário atual, incluindo detalhes do produto e subtotais para implementar isso, adicione o bloco de código abaixo ao seu cart js arquivo parse cloud define("getcart", async (request) => { if (!request user) throw "user must be logged in "; const user = request user; const cart = parse object extend("cart"); const cartquery = new parse query(cart); cartquery equalto("user", user); cartquery include("items product"); // deep include const cart = await cartquery first(); if (!cart) return { items \[], totalprice 0 }; const items = cart get("items") || \[]; const parseditems = \[]; for (const item of items) { const product = item product; parseditems push({ productid product id, name product get("name"), price product get("price"), image product get("image")? url() || null, quantity item quantity, subtotal product get("price") item quantity, }); } return { cartid cart id, items parseditems, totalprice cart get("totalprice") || 0, }; }); esta função usa include("items product") para buscar dados de produtos aninhados em uma única consulta editando o carrinho atualize a quantidade de um item no carrinho ou remova o completamente se a nova quantidade for zero para implementar isso, adicione o bloco de código abaixo ao seu cart js arquivo parse cloud define("updatecart", async (request) => { const { productid, newquantity } = request params; const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to update the cart "); } if (!productid || newquantity === undefined) { throw new error("missing required parameters productid and newquantity "); } // fetch or create the user's cart const cart = parse object extend("cart"); const cartquery = new parse query(cart); cartquery equalto("user", currentuser); let cart = await cartquery first({ usemasterkey true }); if (!cart) { // if there's no existing cart, create one cart = new cart(); cart set("user", currentuser); cart set("items", \[]); cart set("totalprice", 0); } let cartitems = cart get("items") || \[]; // find the item matching the productid const itemindex = cartitems findindex( (item) => item product id === productid ); if (itemindex === 1) { throw new error("product not found in cart please add it first "); } // if newquantity <= 0, remove the item from the cart if (newquantity <= 0) { cartitems splice(itemindex, 1); } else { // otherwise, update the quantity cartitems\[itemindex] quantity = newquantity; } // recalculate total by fetching current prices from each product let total = 0; if (cartitems length > 0) { const product = parse object extend("product"); // for each item in the cart, fetch the product to get its price for (const item of cartitems) { const productquery = new parse query(product); productquery equalto("objectid", item product objectid); const product = await productquery first({ usemasterkey true }); if (product) { const productprice = product get("price") || 0; total += productprice item quantity; } } } // update and save the cart cart set("items", cartitems); cart set("totalprice", total); try { const updatedcart = await cart save(null, { usemasterkey true }); return { message "cart updated successfully", cartid updatedcart id, items updatedcart get("items"), totalprice updatedcart get("totalprice"), }; } catch (error) { throw new error(`error updating cart ${error message}`); } }); ele revalida todos os preços dos produtos durante a atualização para garantir a precisão total excluindo do carrinho esta função remove um produto do carrinho do usuário para implementar isso, adicione o bloco de código abaixo ao seu cart js arquivo parse cloud define("removefromcart", async (request) => { const { productid } = request params; const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to remove items from the cart "); } if (!productid) { throw new error("missing required parameter productid "); } // fetch the user's cart const cart = parse object extend("cart"); const cartquery = new parse query(cart); cartquery equalto("user", currentuser); const cart = await cartquery first({ usemasterkey true }); if (!cart) { throw new error("no existing cart found for this user "); } let cartitems = cart get("items") || \[]; // filter out the item with the specified productid const filtereditems = cartitems filter( (item) => item product id !== productid ); // if nothing changed, the product wasn't in the cart if (filtereditems length === cartitems length) { throw new error("product not found in cart "); } // recalculate the cart total let total = 0; if (filtereditems length > 0) { const product = parse object extend("product"); for (const item of filtereditems) { const productquery = new parse query(product); productquery equalto("objectid", item product objectid); const product = await productquery first({ usemasterkey true }); if (product) { const productprice = product get("price") || 0; total += productprice item quantity; } } } // update and save the cart cart set("items", filtereditems); cart set("totalprice", total); try { const updatedcart = await cart save(null, { usemasterkey true }); return { message "item removed from cart", cartid updatedcart id, items updatedcart get("items"), totalprice updatedcart get("totalprice"), }; } catch (error) { throw new error(`error removing item from cart ${error message}`); } }); ele filtra o item do array do carrinho e recalcula o total antes de salvar pedido essas funções gerenciam o processo de pedido—desde a criação de pedidos até a recuperação do histórico de pedidos de um vendedor criando um pedido esta função converte o carrinho do comprador em um pedido oficial para implementar isso, crie um order js arquivo e adicione o bloco de código abaixo a ele parse cloud define("createorder", async (request) => { const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to place an order "); } // ensure the user is a buyer (assumes buyer class with user pointer) const buyer = parse object extend("buyer"); const buyerquery = new parse query(buyer); buyerquery equalto("user", currentuser); const buyer = await buyerquery first({ usemasterkey true }); if (!buyer) { throw new error("only buyers can place orders "); } // retrieve the cart for the user const cart = parse object extend("cart"); const cartquery = new parse query(cart); cartquery equalto("user", buyer get("user")); // assuming the user pointer is stored in buyer const cart = await cartquery first({ usemasterkey true }); if (!cart || !cart get("items") || cart get("items") length === 0) { throw new error("cart is empty"); } const items = cart get("items"); let totalamount = 0; // adjust stock and calculate total order price const orderdetails = \[]; for (const item of items) { const productid = item product id; const quantity = item quantity; const product = parse object extend("product"); const productquery = new parse query(product); productquery equalto("objectid", productid); const product = await productquery first({ usemasterkey true }); if (!product) { throw new error(`product with id ${productid} not found`); } const availablequantity = product get("quantityavailable"); if (availablequantity < quantity) { throw new error(`not enough stock for product ${product get("name")}`); } // reduce the product quantity product set("quantityavailable", availablequantity quantity); await product save(null, { usemasterkey true }); const unitprice = product get("price"); totalamount += unitprice quantity; // prepare order detail entry orderdetails push({ product, quantity, unitprice }); } // create the new order object const order = parse object extend("order"); const order = new order(); order set("buyer", buyer); // set the buyer pointer order set("total", totalamount); // set the total amount order set("orderstatus", "pending"); // set the order status order set("orderdate", new date()); // set the order date // save the order to the database try { const savedorder = await order save(null, { usemasterkey true }); // create orderdetails for each item const orderdetails = parse object extend("orderdetails"); for (const detail of orderdetails) { const orderdetail = new orderdetails(); orderdetail set("order", savedorder); orderdetail set("product", detail product); orderdetail set("quantity", detail quantity); orderdetail set("unitprice", detail unitprice); await orderdetail save(null, { usemasterkey true }); } // optionally, clear the cart after saving the order cart set("items", \[]); await cart save(null, { usemasterkey true }); return savedorder; } catch (error) { throw new error(`could not create order ${error message}`); } }); valida o comprador, verifica a disponibilidade de estoque, reduz o inventário de produtos, economiza tanto pedido quanto detalhesdopedido , e limpa o carrinho após um pedido bem sucedido obtendo pedidos do vendedor esta função recupera todos os pedidos que incluem produtos vendidos pelo vendedor atual para implementar isso, adicione o bloco de código abaixo ao seu order js arquivo parse cloud define("getsellerorders", async (request) => { const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to view your orders "); } if (currentuser get("usertype") !== "seller") { throw new error("only sellers can access this endpoint "); } try { const seller = parse object extend("seller"); const seller = await new parse query(seller) equalto("userid", currentuser) first({ usemasterkey true }); if (!seller) { throw new error("seller profile not found "); } // find products by this seller const product = parse object extend("product"); const productquery = new parse query(product); productquery equalto("seller", seller); const products = await productquery find({ usemasterkey true }); if (!products || products length === 0) { return \[]; } // get product ids const productids = products map(product => product id); // find order details containing these products const orderdetails = parse object extend("orderdetails"); const orderdetailsquery = new parse query(orderdetails); orderdetailsquery containedin("product", products); const orderdetails = await orderdetailsquery find({ usemasterkey true }); if (!orderdetails || orderdetails length === 0) { return \[]; } const orderids = \[ new set(orderdetails map(detail => detail get("order") id))]; // query orders for these ids const order = parse object extend("order"); const orderquery = new parse query(order); orderquery containedin("objectid", orderids); orderquery include("buyer"); const orders = await orderquery find({ usemasterkey true }); // return the orders return orders map(order => ({ id order id, total order get("total"), status order get("orderstatus"), date order get("orderdate"), buyer order get("buyer") })); } catch (error) { throw new error(`could not fetch orders ${error message}`); } }); ele localiza produtos pertencentes ao vendedor, consulta orderdetails para esses produtos, busca os pedidos correspondentes e retorna uma estrutura simplificada incluindo informações do comprador atualizando o status do pedido esta função alterna o status de um pedido entre “pendente” e “concluído ” para implementar isso, adicione o bloco de código abaixo ao seu order js arquivo parse cloud define("updateorder", async (request) => { const { orderid } = request params; const currentuser = request user; if (!currentuser) { throw new error("you must be logged in to view your orders "); } if (currentuser get("usertype") !== "seller") { throw new error("only sellers can access this endpoint "); } // validate the input parameter if (!orderid) { throw new error("missing required field orderid"); } try { // find the order with the specified orderid const order = parse object extend("order"); const query = new parse query(order); query equalto("objectid", orderid); const order = await query first({ usemasterkey true }); if (!order) { throw new error("order not found"); } // check current status // update the order status if (order get("orderstatus") === "completed") { order set("orderstatus", "pending"); } else { order set("orderstatus", "completed"); } // save the updated order await order save(null, { usemasterkey true }); return { success true, message "order status updated to completed" }; } catch (error) { throw new error(`could not update order status ${error message}`); } }); isso garante que apenas vendedores possam realizar essa ação e que o pedido exista antes de atualizar o status essas funções de backend dão ao seu aplicativo de e commerce a capacidade de gerenciar com segurança todas as operações principais—listagens de produtos, carrinhos de compradores, pedidos e inventário de vendedores—diretamente dentro do back4app usando cloud code para garantir que você possa acessar essas funções em nuvem externamente, você precisa registrar todos os seus arquivos de código em nuvem no seu main js arquivo, você pode fazer isso adicionando o bloco de código abaixo ao seu main js arquivo //main js require(" /auth js") require(" /cart js") require(" /order js") require(" /product js") require(" /seller js") criação de frontend para construir visualmente sua vitrine de e commerce, você usará v0 dev para fazer isso, comece visitando v0 dev http //v0 dev crie uma conta se você ainda não tiver uma assim que sua conta estiver configurada, você pode começar a criar seu frontend para criar seu frontend, insira o prompt abaixo create an e commerce web application with authentication features and a buyer and seller feature o prompt irá construir um aplicativo de ecommerce em next js com os recursos solicitados create ecommerce app usando o recurso de visualização, você pode navegar pelo aplicativo para confirmar se tudo funciona como esperado se houver algumas complicações ou se você quiser adicionar mais recursos, pode passar outro prompt e a versão 0 modificará o aplicativo por exemplo, passe o prompt the seller can create, add, delete and update products este prompt irá modificar o aplicativo, criando páginas onde o vendedor pode realizar operações crud modify ecommerce app finalmente, passe o prompt do not sort products by categories and remove the categories page and input fields, remove the second and third step from the process of becoming a seller and add a bio input field to the first step, users should only sign in with email, and enhance the seller functionality to fully support product management (crud operations) este prompt fará as edições finais no aplicativo para obter uma prévia do aplicativo modificado, clique no visualizar botão na seção destacada na imagem acima uma vez que você tenha certeza de que o aplicativo é o que você deseja, o próximo passo é levar o projeto para o seu dispositivo local para fazer isso, clique no botão de download que a v0 gera com a resposta do prompt botão de download clicar no botão revelará um menu suspenso com um link e um botão de download zip menu suspenso em seguida, clique no botão de download zip depois de terminar de baixar o zip, abra seu terminal e crie uma nova pasta chamada ecommerce app no diretório de sua preferência mkdir ecommerce app agora extraia o conteúdo da pasta zip para a pasta ecommerce app navegue até o diretório ecommerce app no seu terminal e instale as dependências necessárias para fazer isso, execute o seguinte comando cd ecommerce app npm install após instalar as dependências, execute o npm run dev comando no seu terminal para visualizar o projeto no seu servidor localhost integrando seu frontend com seu backend para conectar seu frontend com as funções do cloud code no seu backend back4app, você usará o sdk javascript do parse o sdk permite que você autentique usuários, chame funções de backend e interaja com os modelos de dados do seu aplicativo de forma segura e eficiente para configurar o sdk, execute o seguinte comando no diretório do seu projeto no terminal npm install parse em seguida, crie um lib/parse js arquivo para configurar a conexão neste arquivo, insira o bloco de código abaixo import parse from "parse/dist/parse min js"; parse initialize("your app id", "your javascript key"); parse serverurl = "https //parseapi back4app com"; export default parse; substitua your app id e your javascript key pelas credenciais encontradas no seu painel do back4app em configurações do app esta configuração básica garante que o sdk saiba como se conectar ao seu projeto específico agora que você conectou seu frontend ao seu backend, pode começar a escrever funções para chamar as funções de código em nuvem que você definiu em sua aplicação back4app autenticação no cliente esta seção mostra como lidar com o registro, login e logout de usuários no seu frontend usando o sdk parse cada função corresponde a uma função de código em nuvem ou método do sdk que você implementou no seu backend do back4app em sua aplicação, o app/auth/register diretório contém a lógica para registrar usuários no page tsx defina o estado formdata este estado conterá as credenciais necessárias para registrar um usuário o estado formdata deve ser assim const \[formdata, setformdata] = usestate({ name "", email "", password "", confirmpassword "", shippingaddress "", paymentinfo "", }); com as credenciais passadas para o formdata , você pode chamar a signupuser função em nuvem que você definiu em sua aplicação back4app certifique se de importar parse do lib/parse js import parse from "@/lib/parse"; const handlesubmit = async(e react formevent) => { e preventdefault(); try { const response = await parse cloud run("signupuser", { name formdata name, email formdata email, password formdata password, confirmpassword formdata confirmpassword, shippingaddress formdata shippingaddress, paymentinfo formdata paymentinfo, }); console log("signup successful ", response); } catch (error any) { console error("signup failed ", error); } } esta função será executada quando você enviar o formulário de cadastro ela chama a signupuser função em nuvem definida no cloud code a função passa as credenciais do usuário e dados específicos do comprador (como informações de envio e pagamento) finalmente, ela registra a resposta se a operação for bem sucedida ou imprime um erro se falhar autenticando usuários para fazer login de um usuário, use a loginuser função de código em nuvem no seu backend navegue até o app/auth/login diretório na sua aplicação dentro do page tsx arquivo, v0 terá criado o estado contendo as credenciais do usuário que você precisa para fazer o login, tudo o que você precisa fazer é passar essas credenciais para a loginuser função por exemplo import parse from "@/lib/parse"; const handlesubmit = async (e react formevent) => { e preventdefault(); setisloading(true); try { const result = await parse cloud run("loginuser", { email, password }); // log in using returned session token await parse user become(result sessiontoken); console log("user logged in with session ", result sessiontoken); setisloading(false); router push("/"); // proceed to app } catch (error) { console error("login failed ", error); } }; esta função invoca a função em nuvem loginuser , enviando as credenciais de login do usuário para o servidor após receber um token de sessão válido em resposta, ele usa parse user become para autenticar o cliente e estabelecer a sessão como pertencente ao usuário logado desconectando usuários para desconectar um usuário de forma segura, você chamará tanto parse user logout() quanto sua função personalizada logoutuser do cloud code isso garante que o token de sessão seja limpo tanto no cliente quanto invalidado no servidor você encontrará o botão de logout no seu componente de cabeçalho este componente estará na sua components pasta no diretório raiz no componente, defina esta função const handlelogout = async () => { const sessiontoken = parse user current()? get("sessiontoken"); if (sessiontoken) { await parse user become(sessiontoken); // ensures proper context await parse cloud run("logoutuser"); // delete the session on server } await parse user logout(); // clear the local session }; esta função desconectará um usuário e limpará a sessão tanto no cliente quanto no servidor na parte jsx do componente, vincule a função ao botão de logout usando o onclick evento por exemplo \<dropdownmenuitem onclick={handlelogout}> logout \</dropdownmenuitem> integração de vendedores esta seção mostra uma função para permitir que os compradores atualizem sua conta e se registrem como vendedores no seu aplicativo, navegue até o app/seller/register diretório neste diretório, você encontrará seu page tsx arquivo onde você definirá a função que chama a createseller função do cloud esta função é responsável por criar um perfil de vendedor para o usuário atual no page tsx arquivo, modifique o estado formdata para ficar assim const \[formdata, setformdata] = usestate({ phone "", bio "", businessname "", }); substitua a lógica na handlesubmit função criada pelo v0 com a lógica abaixo const handlesubmit = async (e react formevent) => { e preventdefault(); try { const result = await parse cloud run("createseller", { businessname formdata businessname, bio formdata bio, phone formdata phone, }); console log("seller created ", result sellerid); } catch (error) { console error("error creating seller ", error); } }; chame esta função ao enviar o formulário para criar um perfil de vendedor para seus usuários gerenciamento de produtos use essas chamadas de função em seu frontend para gerenciar operações de produtos como vendedor criando um produto para chamar a função de código em nuvem que adiciona um produto ao banco de dados, localize o app/seller/products/new diretório dentro deste diretório está o seu page tsx arquivo, neste arquivo há um formulário este formulário coleta as informações do produto, incluindo imagens modifique o product estado para ficar assim const \[product, setproduct] = usestate({ name "", price "", description "", stock "", status "active", }); também crie um estado para armazenar suas imagens const \[images, setimages] = usestate\<file\[]>(\[]); agora, escreva uma função para lidar com a adição das imagens ao banco de dados esta função deve ser assim const handleimageupload = async (event) => { event preventdefault(); try { let name = "image jpg"; const file = new parse file(name, event target files\[0]); const photo = await file save(); setimages((prev) => \[ prev, photo]); console log("file saved ", file); alert(`image uploaded successfully`); } catch (error) { console error("error saving file ", error); } }; agora, escreva uma função para lidar com a adição das imagens ao banco de dados esta função deve ser assim vincule esta função à entrada responsável pelo upload de arquivos usando o onchange evento em seguida, defina a função handlesubmit esta função chama o addproduct código em nuvem enquanto passa as informações necessárias assim const handlesubmit = async (e react formevent) => { e preventdefault(); try { interface addproductparams { name string; description string; price number; quantityavailable number; isactive boolean; } interface addproductresponse { id string; } parse cloud run\<addproductresponse, addproductparams>("addproduct", { name product name, description product description, price product price, quantityavailable product stock, isactive product status === "active", imagefiles images, }) then((response) => { console log("product created ", response id); }); } catch (error) { console error("error creating product ", error); } }; esta chamada envia os dados do produto—incluindo imagens—para o backend para criar uma nova listagem buscar todos os produtos esta chamada recupera todo o catálogo para listagens de produtos públicas ou um feed da página inicial para criar a função que chama a fetchallproducts função em nuvem, navegue até o app/products diretório no arquivo page tsx , adicione este código interface product { id string; name string; description string; price number; image? string; } const \[products, setproducts] = usestate\<product\[]>(\[]); async function getallproducts() { try { const response = await parse cloud run("fetchallproducts"); console log("products fetched ", response); return response; } catch (error) { console error("error fetching products ", error); throw error; } } este bloco de código acima define uma interface para os produtos e um estado de products a função getallproducts chama a função em nuvem fetchallproducts para obter todos os produtos no banco de dados observe que você precisa chamar a função getallproducts acima dentro de um useeffect() hook para buscar e renderizar produtos ao carregar a página assim useeffect(() => { getallproducts() then((products) => { setproducts(products); }) catch((error) => { console error("error fetching products ", error); }); }, \[]); obter um produto único esta chamada recupera detalhes completos sobre um produto específico navegue até a \[id] pasta no seu app/products diretório esta pasta contém o page tsx arquivo que conterá a lógica para buscar os detalhes de um único produto no arquivo page tsx , escreva este código interface product { id string; name string; description string; price number; images? string\[]; quantityavailable number; } const \[product, setproduct] = usestate\<product>({ id "", name "", description "", price 0, images \[], quantityavailable 0, }); async function getsingleproduct() { try { const response = await parse cloud run("getsingleproduct", {productid params id}); console log("product fetched ", response); return response; } catch (error) { console error("error fetching products ", error); throw error; } } useeffect(() => { getsingleproduct() then((product) => { setproduct(product); }) catch((error) => { console error("error fetching products ", error); }); }, \[]); este bloco de código define a interface para o objeto produto, configura uma variável de estado product com valores padrão a função getsingleproduct chama sua função de código em nuvem getsingleproduct usando um productid dos parâmetros da rota este useeffect hook é executado uma vez quando o componente é montado atualizar um produto quando um vendedor edita um produto, chame esta função com os campos atualizados para atualizar produtos, você precisa de um formulário com campos de entrada coletando os novos dados, você pode encontrar este formulário no page tsx arquivo localizado no app/seller/products/\[id]/edit diretório antes de atualizar um produto, você precisa buscar o produto e para fazer isso adicione este código ao seu page tsx arquivo const \[product, setproduct] = usestate({ id "", name "", price "", description "", stock "", images \["", "", ""], status "active", }); useeffect(() => { async function fetchproduct() { try { const response = await parse cloud run("getsingleproduct", { productid params id, }); setproduct({ id response objectid, name response name || "", price string(response price ?? "0"), description response description || "", stock string(response quantityavailable ?? "0"), // fallback to placeholders if actual image data is not provided images \[ response image1 || `/placeholder svg?height=500\&width=500\&text=product`, response image2 || `/placeholder svg?height=500\&width=500\&text=productview+2`, response image3 || `/placeholder svg?height=500\&width=500\&text=productview+3`, ], status response isactive ? "active" "out of stock", }); } catch (error) { console error("error fetching product ", error); } } fetchproduct(); }, \[]); este código busca os detalhes de um único produto do seu backend do back4app com a função de código em nuvem getsingleproduct e armazena os detalhes no estado do componente product para exibir como o valor padrão em seu formulário antes de você modificá lo após buscar os detalhes do produto, você pode alterar os detalhes usando o formulário após preencher o formulário, enviar o formulário chamará uma handlesubmit função que conterá a lógica para atualizar seu produto sua handlesubmit função deve ser parecida com isto const handlesubmit = async (e react formevent) => { e preventdefault(); try { await parse cloud run("updateproduct", { productid product id, name product name, description product description, price parsefloat(product price), quantityavailable parseint(product stock, 10), isactive product status === "active", }); } catch (error) { console error("error updating product ", error); } }; esta função chama sua updateproduct função de cloud code e envia um objeto com os dados do produto atualizado excluir um produto use esta função para excluir um produto após a confirmação do vendedor para excluir um produto, você precisa adicionar uma handledelete função que contém a lógica necessária para excluir o produto você definirá a handledelete função no arquivo page tsx no diretório app/seller/products/\[id]/edit const handledelete = async () => { const confirmdelete = confirm( "are you sure you want to delete this product? this action cannot be undone " ); if (!confirmdelete) return; try { await parse cloud run("deleteproduct", { productid product id, }); } catch (error) { console error("error deleting product ", error); } }; a handledelete função primeiro confirma a intenção do usuário antes de chamar a deleteproduct função de código em nuvem definida no seu backend vincule a handledelete função ao botão de exclusão na parte jsx do componente por exemplo \<button type="button" variant="destructive" onclick={handledelete} \> \<trash2 classname="h 4 w 4 mr 2" /> delete product \</button> obter produtos do vendedor use isso para buscar todos os produtos pertencentes ao vendedor atualmente logado você definirá a função para lidar com a busca dos produtos do vendedor no arquivo page tsx no diretório app/seller/dashboard no arquivo, escreva este código const \[products, setproducts] = usestate< { objectid string; name string; price number; quantityavailable number; sales number; isactive boolean; }\[] \>(\[]); useeffect(() => { async function fetchproducts() { try { const result = await parse cloud run("getsellerproducts"); setproducts(result); } catch (error) { console error("error fetching products ", error); } }; fetchproducts(); }, \[]); este bloco de código define o products estado e usa o useeffect hook para chamar a fetchproducts função uma vez ao carregar a fetchproducts função chama a getsellerproducts função de código em nuvem e atualiza o products estado com o resultado da chamada gerenciamento de carrinho essas chamadas permitem que os compradores gerenciem seu carrinho de compras antes de fazer um pedido adicionar ao carrinho esta chamada adiciona um produto selecionado ao carrinho do usuário ou incrementa sua quantidade localize o page tsx arquivo no diretório app/products e adicione as seguintes linhas de código async function handleaddtocart(productid string, quantity number = 1) { try { const response = await parse cloud run("addtocart", { productid, quantity, }); console log("add to cart success ", response); } catch (error) { console error("failed to add to cart ", error); } } a função handleaddtocart aceita productid e quantidade opcional como argumentos e chama o addtocart código em nuvem no seu backend esta função deve ser executada quando seus usuários clicarem no botão "adicionar ao carrinho" no cartão do produto por exemplo \<button classname="w full" size="sm" onclick={() => handleaddtocart(product id)}> \<shoppingcart classname="h 4 w 4 mr 2" /> add to cart \</button> no arquivo, escreva este código ver carrinho use isso para buscar o conteúdo do carrinho e renderizar um resumo ao vivo do carrinho para fazer isso, navegue até o page tsx arquivo no app/cart diretório dentro deste arquivo, adicione o bloco de código abaixo interface cartitem { id string; // product's objectid name string; price number; quantity number; image string; } const \[cartitems, setcartitems] = usestate\<cartitem\[]>(\[]); useeffect(() => { async function fetchcart() { try { const response = await parse cloud run("getcart"); const parsed = response items map((item) => ({ id item productid, name item name, price item price, quantity item quantity, image item image, })); setcartitems(parsed); } catch (error) { console error("failed to fetch cart ", error); } } fetchcart(); }, \[]); o bloco de código acima define a estrutura dos dados do carrinho no frontend com a interface cartitem , define o estado cartitems que mantém os itens do carrinho ele também usa useeffect para acionar a função fetchcart uma vez ao carregar a página a função fetchcart chama a função de código em nuvem getcart e recupera o carrinho do seu backend ela usa o método map para converter o formato do backend para o formato do frontend antes de salvar os dados do carrinho processados no estado cartitems atualizar item do carrinho esta chamada altera a quantidade de um produto específico no carrinho dentro do page tsx arquivo no diretório app/cart , você encontrará uma updatequantity função substitua essa função pela abaixo const updatequantity = async (productid string, newquantity number) => { if (newquantity < 1) return; try { await parse cloud run("updatecart", { productid, newquantity, }); console log("updated the cart"); } catch (error) { console error("failed to update cart item ", error); } }; esta função recebe dois parâmetros, productid e a quantidade atualizada que o usuário deseja definir newquantity ela chama sua updatecart função em nuvem e envia tanto o productid quanto o newquantity como parâmetros você vincula essa função aos botões +/ usando o onclick evento assim \<div classname="flex items center gap 2"> \<button variant="outline" size="icon" classname="h 8 w 8" onclick={() => updatequantity(item id, item quantity 1)} \> \<minus classname="h 3 w 3" /> \<span classname="sr only">decrease quantity\</span> \</button> \<span classname="w 8 text center">{item quantity}\</span> \<button variant="outline" size="icon" classname="h 8 w 8" onclick={() => updatequantity(item id, item quantity + 1)} \> \<plus classname="h 3 w 3" /> \<span classname="sr only">increase quantity\</span> \</button> \</div> remover do carrinho remove um item completamente do carrinho para fazer isso, adicione o bloco de código abaixo ao page tsx arquivo no app/cart diretório dentro deste arquivo const removeitem = async (productid string) => { try { await parse cloud run("removefromcart", { productid, }); setcartitems((items) => items filter((item) => item id !== productid)); } catch (error) { console error("failed to remove item ", error); } }; esta função, removeitem , remove um produto específico do carrinho do usuário chamando a função em nuvem removefromcart no backend a função também atualiza o estado local do carrinho no frontend para refletir a mudança vincule esta função ao botão "remover item", assim \<button variant="ghost" size="icon" classname="h 8 w 8 text muted foreground" onclick={() => removeitem(item id)} \> \<trash2 classname="h 4 w 4" /> \<span classname="sr only">remove item\</span> \</button> gerenciamento de pedidos essas funções lidam com a criação e o rastreamento de pedidos para compradores e vendedores criar um pedido isso cria um pedido a partir do conteúdo atual do carrinho do usuário você também define essa função no page tsx arquivo no diretório app/cart a função que contém a lógica para criar o pedido deve ser assim const handleorder = async () => { try { const user = parse user current(); if (!user) { throw new error("you must be logged in to place an order "); } const result = await parse cloud run("createorder"); console log("order created successfully ", result); } catch (error any) { console error("failed to create order ", error); } }; esta função, handleorder , gerencia o processo de checkout ao fazer um pedido através do seu backend back4app ela verifica se um usuário está logado, então chama a createorder função em nuvem para converter o carrinho do usuário atual em um pedido oficial para chamar isso no checkout, vincule a função ao botão "checkout" usando o onclick evento por exemplo \<button classname="w full" onclick={handleorder}>proceed to checkout\</button> ver pedidos do vendedor os vendedores podem usar esta chamada para ver pedidos que incluem seus produtos defina esta função no arquivo page tsx no diretório app/seller/dashboard adicione as seguintes linhas de código ao arquivo page tsx const \[ordersdata, setordersdata] = usestate<{ id string; total number; buyer string; date date; status string; }\[] \>(\[]); async function fetchsellerorders() { try { const orders = await parse cloud run("getsellerorders"); console log("seller orders ", orders); setordersdata(orders); } catch (err) { console error("error fetching seller orders ", err); } }; este código recupera uma lista de pedidos que incluem os produtos do vendedor e os armazena no estado local ordersdata para exibição em um painel de controle do vendedor ou visualização de gerenciamento de pedidos certifique se de chamar a função em um useeffect hook para que a função seja executada uma vez ao carregar a página atualizar um pedido isso alterna o status de um pedido entre "pendente" e "concluído" defina esta função no arquivo page tsx no diretório app/seller/dashboard a função deve ser parecida com isto const handleupdate = async (id string) => { const confirmupdate = confirm( "are you sure you want to update this order?" ); if (!confirmupdate) return; try { await parse cloud run("completeorder", { orderid id, }); console log("updated order"); } catch (error) { console error("error updating order ", error); } }; esta função, handleupdate , atualiza o status de um pedido existente chamando a função em nuvem chamada completeorder no seu backend do back4app vincule esta função a um botão "editar" na parte jsx do componente assim \<button variant="ghost" size="icon" onclick={() => {handleupdate(order id)}}> \<pencil classname="h 4 w 4" /> \<span classname="sr only">view\</span> \</button> implantando o frontend em contêineres back4app os contêineres back4app oferecem uma maneira simplificada de empacotar e implantar sua aplicação frontend em vez de gerenciar serviços de hospedagem separados, você pode armazenar todas as dependências dentro de uma imagem docker, garantindo desempenho consistente e simplificando a manutenção essa abordagem baseada em contêineres é especialmente útil para aplicações next js, onde você pode otimizar as compilações para velocidade e confiabilidade para containerizar sua aplicação, crie um dockerfile para definir como sua aplicação é construída e servida abaixo está um exemplo de dockerfile para uma aplicação next js \# stage 1 build the next js app from node 20 alpine as builder workdir /app copy package json package lock json / run npm install copy run npm run build \# stage 2 run the next js app from node 20 alpine workdir /app copy from=builder /app / expose 3000 cmd \["npm", "start"] após criar seu dockerfile, crie um dockerignore e adicione estes comandos \# node modules (reinstalled in docker) node modules \# next js build output next out \# logs npm debug log yarn debug log yarn error log pnpm debug log \# env files (optional — only if you handle secrets another way) env env local env development env production env test \# os / ide / editor junk ds store thumbs db vscode idea \# git git gitignore agora você pode construir e testar sua aplicação localmente para fazer isso, execute o seguinte comando no seu terminal docker build t ecommerce app docker run p 3000 3000 ecommerce app abra http //localhost 3000 para garantir que seu site funcione corretamente depois de verificar que tudo está funcionando como esperado localmente, é hora de enviar seu código para o github e implantá lo através do back4app certifique se de que seu código está comprometido e enviado para um repositório do github isso permitirá que o back4app acesse seu projeto para implantação na sua conta do back4app, vá para o seu painel e clique no painel menu suspenso na parte superior da tela dashboard menu no menu suspenso, selecione plataforma de implantação web web deployment platform isso o levará à página de implantação da aplicação web deploy web application page clique no implantar um app web botão para iniciar o processo de implantação link github repo em seguida, clique em importar repositório do github e escolha o repositório que contém seu dockerfile atribua um nome ao seu projeto (por exemplo, ecommerce back4app) siga a configuração guiada para construir e implantar seu app uma vez que a implantação é concluída, o back4app exibirá uma página de confirmação como esta implantação bem sucedida a área destacada na imagem acima é a url onde sua aplicação está ao vivo você pode usá la para visualizar e testar seu aplicativo diretamente em um navegador da web uma vez implantado, use o painel do back4app para monitorar logs de construção, rastrear a saúde do contêiner e reverter para versões anteriores, se necessário o painel exibe atualizações em tempo real sobre o status do contêiner, facilitando a identificação de erros e a manutenção de um ambiente estável para seus usuários com contêineres, você ganha uma solução de frontend flexível e portátil que se integra perfeitamente ao seu backend do back4app, abrindo caminho para lançamentos consistentes e sem complicações você pode visitar o site de e commerce construído neste tutorial aqui https //ecommerceback4app mcphit37 b4a run/ conclusão parabéns—você agora montou cada camada de uma pilha de e commerce testada em batalha e pronta para produção configuração de back end desde a provisão da sua conta back4app até a modelagem de usuários, produtos e pedidos segurança e apis implementando autenticação robusta e expondo seus dados através de endpoints rest e graphql lógica de negócios e atualizações em tempo real automatizando fluxos de trabalho com cloud code e transmitindo alterações ao vivo através do livequery implantação de front end conectando o sdk javascript e enviando uma loja next js em contêineres back4app o que vem a seguir? mergulhe na documentação do back4app https //www back4app com/docs e no guia da parse platform https //docs parseplatform org para referência detalhada, ou junte se ao fórum da comunidade para obter dicas avançadas e aplicativos de exemplo de mantenedores e outros desenvolvedores esta fundação é apenas o começo—expanda a ainda mais integrando webhooks e trabalhos agendados, conectando gateways de pagamento ou construindo um aplicativo móvel complementar continue iterando, refatorando e evoluindo sua base de código—e veja sua loja crescer junto com suas ambições