Integrar o Firebase a um app Next.js

1. Antes de começar

Neste codelab, você aprenderá a integrar o Firebase a um app da Web Next.js chamado Friendly Eats, que é um site de avaliações de restaurantes.

App da Web Friendly Eats

O app da Web completo oferece recursos úteis que demonstram como o Firebase pode ajudar você a criar apps Next.js. Esses recursos incluem o seguinte:

  • Funcionalidade de login com o Google e logout: o app da Web completo permite que você faça login com o Google e saia. O login e a persistência do usuário são gerenciados inteiramente pelo Firebase Authentication.
  • Imagens: o app da Web concluído permite que os usuários que fizeram login façam upload de imagens de restaurantes. Os recursos de imagem são armazenados no Cloud Storage para Firebase. O SDK do Firebase para JavaScript fornece um URL público para as imagens enviadas. Esse URL público é armazenado no documento do restaurante relevante no Cloud Firestore.
  • Avaliações: o app da Web concluído permite que os usuários conectados postem avaliações de restaurantes com uma nota e uma mensagem de texto. As informações das avaliações são armazenadas no Cloud Firestore.
  • Filtros: o app da Web concluído permite que os usuários que fizeram login filtrem a lista de restaurantes por categoria, local e preço. Também é possível personalizar o método de classificação usado. Os dados são acessados do Cloud Firestore, e as consultas do Firestore são aplicadas com base nos filtros usados.

Pré-requisitos

  • Conhecimento de Next.js e JavaScript.

Neste curso, você vai aprender a:

  • Como usar o Firebase com o roteador de apps Next.js e a renderização do lado do servidor.
  • Como manter imagens no Cloud Storage para Firebase.
  • Como ler e gravar dados em um banco de dados do Cloud Firestore.
  • Como usar o login com o Google com o SDK do Firebase para JavaScript.

Pré-requisitos

  • Git
  • O Kit de desenvolvimento em Java
  • Uma versão estável recente do Node.js
  • Um navegador da sua escolha, como o Google Chrome
  • Ambiente de desenvolvimento com um editor de código e um terminal
  • Uma Conta do Google para a criação e o gerenciamento do seu projeto do Firebase
  • A capacidade de fazer upgrade do seu projeto do Firebase para o plano de preços Blaze

2. Configurar o ambiente de desenvolvimento

Este codelab fornece a base de código inicial do app e depende da CLI do Firebase.

Faça o download do repositório

  1. No seu terminal, clone o repositório do GitHub do codelab:
    git clone https://github.com/firebase/friendlyeats-web.git
    
  2. O repositório do GitHub contém projetos de exemplo para várias plataformas. No entanto, este codelab usa apenas o diretório nextjs-start. Anote os seguintes diretórios:
    • nextjs-start: contém o código inicial em que você vai criar.
    • nextjs-end: contém o código da solução do app da Web finalizado.
  3. No seu terminal, navegue até o diretório nextjs-start e instale as dependências necessárias:
    cd friendlyeats-web/nextjs-start
    npm install
    

Instalar ou atualizar a CLI do Firebase

Execute o seguinte comando para verificar se você tem a CLI do Firebase instalada e se ela é a v12.5.4 ou mais recente:

firebase --version
  • Se você tiver a CLI do Firebase instalada, mas ela não for v12.5.4 ou mais recente, atualize-a:
    npm update -g firebase-tools
    
  • Se você não tiver a CLI do Firebase, faça a instalação:
    npm install -g firebase-tools
    

Se não for possível instalar a CLI do Firebase devido a erros de permissão, consulte a documentação do npm ou use outra opção de instalação.

Fazer login no Firebase

  1. Execute o seguinte comando para fazer login na CLI do Firebase:
    firebase login
    
  2. Para que o Firebase colete dados, insira Y ou N.
  3. No navegador, selecione sua Conta do Google e clique em Permitir.

3. Configurar seu projeto do Firebase

Nesta seção, você vai configurar um projeto do Firebase e associar um app da Web do Firebase a ele. Você também vai configurar os serviços do Firebase usados pelo app da Web de exemplo.

criar um projeto do Firebase

  1. No console do Firebase, clique em Criar projeto.
  2. Na caixa de texto Digite o nome do projeto, digite FriendlyEats Codelab ou o nome do projeto que você quiser e clique em Continuar.
  3. Neste codelab, você não precisa do Google Analytics. Portanto, desative a opção Ativar o Google Analytics para este projeto.
  4. Clique em Criar projeto.
  5. Aguarde o provisionamento do projeto e clique em Continuar.
  6. No projeto do Firebase, acesse Configurações do projeto. Anote o ID do projeto, porque você vai precisar dele mais tarde. Esse identificador exclusivo é como seu projeto é identificado (por exemplo, na CLI do Firebase).

Adicionar um app da Web ao seu projeto do Firebase

  1. Navegue até a Visão geral do projeto no seu projeto do Firebase e clique em e41f2efdd9539c31.png Web.
  2. Na caixa de texto Apelido do app, digite um apelido fácil de lembrar, como My Next.js app.
  3. Marque a caixa de seleção Também configurar o Firebase Hosting para este app.
  4. Clique em Registrar app > Próxima > Próxima > Continuar para o console.

Fazer upgrade do plano de preços do Firebase

Para usar frameworks da Web, seu projeto do Firebase precisa estar no plano de preços Blaze, o que significa que ele está associado a uma conta do Cloud Billing.

  • Uma conta do Cloud Billing exige uma forma de pagamento, como cartão de crédito.
  • Se você ainda não conhece o Firebase e o Google Cloud, confira se tem qualificação para receber um crédito de US $300 e uma conta de teste gratuito do Cloud Billing.

No entanto, a conclusão deste codelab não gera cobranças.

Para fazer upgrade do seu projeto para o plano Blaze, siga estas etapas:

  1. No console do Firebase, selecione Fazer upgrade do seu plano.
  2. Na caixa de diálogo, selecione o plano Blaze e siga as instruções na tela para associar seu projeto a uma conta do Cloud Billing.
    Se precisar criar uma conta do Cloud Billing, talvez seja necessário voltar para o upgrade no console do Firebase para concluir o upgrade.

Configurar serviços do Firebase no console do Firebase

Configurar o Authentication

  1. No console do Firebase, navegue até Autenticação.
  2. Clique em Começar.
  3. Na coluna Outros provedores, clique em Google > Ativar.
  4. Na caixa de texto Nome voltado ao público do projeto, digite um nome fácil de lembrar, como My Next.js app.
  5. No menu suspenso E-mail de suporte do projeto, selecione seu endereço de e-mail.
  6. Clique em Salvar.

Configurar o Cloud Firestore

  1. No console do Firebase, navegue até o Firestore.
  2. Clique em Criar banco de dados > Iniciar no modo de teste > Próxima.
    Mais adiante neste codelab, você vai adicionar regras de segurança para proteger seus dados. Não distribua ou exponha um aplicativo publicamente sem adicionar regras de segurança ao seu banco de dados.
  3. Use o local padrão ou selecione um local de sua escolha.
    No caso de apps reais, escolha um local próximo aos usuários. Não é possível alterar o local depois. Ele também será automaticamente o local do seu bucket padrão do Cloud Storage (próxima etapa).
  4. Clique em Concluído.

Configurar o Cloud Storage para Firebase

  1. No console do Firebase, navegue até Armazenamento.
  2. Clique em Começar > Iniciar no modo de teste > Próxima.
    Mais adiante neste codelab, você vai adicionar regras de segurança para proteger seus dados. Não distribua ou exponha um aplicativo publicamente sem adicionar regras de segurança ao bucket do Storage.
  3. O local do seu bucket já deve estar selecionado (devido à configuração do Firestore na etapa anterior).
  4. Clique em Concluído.

4. Revisar a base de código inicial

Nesta seção, você vai revisar algumas áreas da base de código inicial do app às quais vai adicionar funcionalidades neste codelab.

Estrutura de pastas e arquivos

A tabela a seguir contém uma visão geral da estrutura de pastas e arquivos do app:

Pastas e arquivos

Descrição

src/components

Componentes do React para filtros, cabeçalhos, detalhes de restaurantes e avaliações

src/lib

Funções utilitárias que não estão necessariamente vinculadas ao React ou Next.js.

src/lib/firebase

Código específico e configuração do Firebase

public

Recursos estáticos no app da Web, como ícones

src/app

Roteamento com o roteador de apps Next.js

src/app/restaurant

Um gerenciador de rotas de API

package.json e package-lock.json

Dependências do projeto com npm

next.config.js

Configuração específica do Next.js (as ações do servidor estão ativadas)

jsconfig.json

Configuração do serviço de linguagem JavaScript

Componentes do servidor e do cliente

O app é um app da Web Next.js que usa o Roteador de apps. A renderização do servidor é usada em todo o app. Por exemplo, o arquivo src/app/page.js é um componente do servidor responsável pela página principal. O arquivo src/components/RestaurantListings.jsx é um componente do cliente indicado pela diretiva "use client" no início do arquivo.

Declarações de importação

Você vai notar instruções de importação como estas:

import RatingPicker from "@/src/components/RatingPicker.jsx";

O app usa o símbolo @ para evitar caminhos de importação relativos pesados e é possível graças a aliases de caminho.

APIs específicas do Firebase

Todo o código da API do Firebase é encapsulado no diretório src/lib/firebase. Os componentes individuais do React importam as funções encapsuladas do diretório src/lib/firebase, em vez de importar as funções do Firebase diretamente.

Dados simulados

Os dados simulados de restaurantes e avaliações estão no arquivo src/lib/randomData.js. Os dados desse arquivo são reunidos no código do arquivo src/lib/fakeRestaurants.js.

5. Configurar a hospedagem local com o emulador do Firebase Hosting

Nesta seção, você vai usar o emulador do Firebase Hosting para executar o app da Web Next.js localmente.

Ao final desta seção, o emulador do Firebase Hosting executará o app Next.js para você. Assim, não será necessário executar o Next.js em um processo separado para os emuladores.

Fazer o download e usar uma conta de serviço do Firebase

O app da Web que você criará neste codelab usa a renderização do lado do servidor com o Next.js.

O SDK Admin do Firebase para Node.js é usado para garantir que as regras de segurança funcionem no código do lado do servidor. Para usar APIs no Admin Console do Firebase, você precisa fazer o download e usar uma conta de serviço do Firebase no console do Firebase.

  1. No console do Firebase, navegue até a página Contas de serviço nas Configurações do projeto.
  2. Clique em Gerar nova chave privada > Gerar chave.
  3. Após o download do arquivo no seu sistema de arquivos, confira o caminho completo para esse arquivo.
    Por exemplo, se você fez o download do arquivo para o diretório Downloads, o caminho completo pode ser assim: /Users/me/Downloads/my-project-id-firebase-adminsdk-123.json
  4. No seu terminal, defina a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS como o caminho da chave privada salva. Em um ambiente Unix, o comando pode ter esta aparência:
    export GOOGLE_APPLICATION_CREDENTIALS="/Users/me/Downloads/my-project-id-firebase-adminsdk-123.json"
    
  5. Mantenha esse terminal aberto e use-o no restante deste codelab, já que sua variável de ambiente poderá ser perdida se você iniciar uma nova sessão do terminal.
    Se você abrir uma nova sessão de terminal, será necessário executar novamente o comando anterior.

Adicionar a configuração do Firebase ao código do app da Web

  1. No console do Firebase, acesse as Configurações do projeto.
  2. No painel Configuração do SDK, encontre a variável firebaseConfig e copie as propriedades e os valores correspondentes.
  3. Abra o arquivo .env no editor de código e preencha os valores das variáveis de ambiente com os valores de configuração do console do Firebase.
  4. No arquivo, substitua as propriedades atuais pelas que você copiou.
  5. Salve o arquivo.

Inicializar o app da Web com seu projeto do Firebase

Para conectar o app da Web ao seu projeto do Firebase, siga estas etapas:

  1. No seu terminal, verifique se os frameworks da Web estão ativados no Firebase:
    firebase experiments:enable webframeworks
    
  2. Inicializar o Firebase:
    firebase init
    
  3. Selecione as seguintes opções:
    • Firestore: configure regras de segurança e arquivos de índices para o Firestore
    • Hosting: configure arquivos para o Firebase Hosting e implantações do GitHub Action (opcional)
    • Storage: configure um arquivo de regras de segurança para o Cloud Storage
    • Emuladores: configure emuladores locais para produtos do Firebase
  4. Selecione Usar um projeto existente e insira o ID do projeto que você anotou anteriormente.
  5. Selecione os valores padrão para todas as perguntas subsequentes até chegar à pergunta Em qual região você gostaria de hospedar conteúdo do lado do servidor, se aplicável?. O terminal mostra uma mensagem informando que há uma base de código do Next.js no diretório atual.
  6. Para a pergunta Em qual região você gostaria de hospedar conteúdo do lado do servidor, se aplicável?, selecione o local selecionado anteriormente para o Firestore e o Cloud Storage.
  7. Selecione os valores padrão para todas as perguntas subsequentes até chegar à pergunta Quais emuladores do Firebase você quer configurar?. Para esta pergunta, selecione Emulador do Functions e Emulador do Hosting.
  8. Selecione os valores padrão para todas as outras perguntas.

Implantar regras de segurança

O código já tem conjuntos de regras de segurança para o Firestore e o Cloud Storage para Firebase. Após a implantação das regras de segurança, os dados no banco de dados e no bucket ficam mais bem protegidos contra uso indevido.

  1. Para implantar essas regras de segurança, execute este comando no seu terminal:
    firebase deploy --only firestore:rules,storage
    
  2. Se aparecer a pergunta "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?", selecione Sim.

Iniciar o emulador do Hosting

  1. No seu terminal, inicie o emulador do Hosting:
    firebase emulators:start --only hosting
    
    Seu terminal responde com a porta em que você encontra o emulador do Hosting, por exemplo, http://localhost:5000/.

Terminal mostrando que o emulador do Hosting está pronto

  1. No seu navegador, acesse o URL com o emulador do Firebase Hosting.
  2. Se aparecer o erro na página da Web que começa assim: "Error: Firebase session cookie has incorrect...", você precisa excluir todos os cookies do seu ambiente localhost. Para fazer isso, siga as instruções em excluir cookies | Documentação do DevTools.

Erro na sessão de cookies

Excluir cookies no DevTools

Agora você pode conferir o app da Web inicial. Mesmo que você esteja visualizando o app da Web em um URL do localhost, ele usa serviços reais do Firebase configurados no console.

6. Adicionar autenticação ao app da Web

Nesta seção, você vai adicionar uma autenticação ao app da Web para fazer login nele.

Implementar as funções de login e logout

  1. No arquivo src/lib/firebase/auth.js, substitua as funções onAuthStateChanged, signInWithGoogle e signOut pelo seguinte código:
export function onAuthStateChanged(cb) {
        return _onAuthStateChanged(auth, cb);
}

export async function signInWithGoogle() {
        const provider = new GoogleAuthProvider();

        try {
                await signInWithPopup(auth, provider);
        } catch (error) {
                console.error("Error signing in with Google", error);
        }
}

export async function signOut() {
        try {
                return auth.signOut();
        } catch (error) {
                console.error("Error signing out with Google", error);
        }
}

Esse código usa as seguintes APIs do Firebase:

API Firebase

Descrição

GoogleAuthProvider

Cria uma instância do provedor de autenticação do Google.

signInWithPopup

Inicia um fluxo de autenticação baseado em caixa de diálogo.

auth.signOut

Desconecta o usuário.

No arquivo src/components/Header.jsx, o código já invoca as funções signInWithGoogle e signOut.

  1. No app da Web, atualize a página e clique em Fazer login com o Google. O app da Web não é atualizado, então não está claro se o login foi bem-sucedido.

Receber notificações sobre mudanças na autenticação

Para receber as mudanças na autenticação, siga estas etapas:

  1. Navegue até o arquivo src/components/Header.jsx.
  2. Substitua a função useUserSession por este código:
function useUserSession(initialUser) {
        // The initialUser comes from the server through a server component
        const [user, setUser] = useState(initialUser);
        const router = useRouter();

        useEffect(() => {
                const unsubscribe = onAuthStateChanged(authUser => {
                        setUser(authUser);
                });
                return () => {
                        unsubscribe();
                };
        }, []);

        useEffect(() => {
                onAuthStateChanged(authUser => {
                        if (user === undefined) return;
                        if (user?.email !== authUser?.email) {
                                router.refresh();
                        }
                });
        }, [user]);

        return user;
}

Esse código usa um hook de estado do React para atualizar o usuário quando a função onAuthStateChanged especifica que há uma mudança no estado de autenticação.

Verificar mudanças

O layout raiz no arquivo src/app/layout.js renderiza o cabeçalho e transmite o usuário, se disponível, como uma propriedade.

<Header initialUser={currentUser?.toJSON()} />

Isso significa que o componente <Header> renderiza dados do usuário, se disponíveis, durante o ambiente de execução do servidor. Se houver alguma atualização de autenticação durante o ciclo de vida da página após o carregamento inicial da página, ela será processada pelo gerenciador onAuthStateChanged.

Agora é hora de testar o app da Web e verificar o que você criou.

Para verificar o novo comportamento de autenticação, siga estas etapas:

  1. No navegador, atualize o app da Web. Seu nome de exibição aparece no cabeçalho.
  2. Saia e faça login novamente. A página é atualizada em tempo real sem ser atualizada. Repita essa etapa com diferentes usuários.
  3. Opcional: clique com o botão direito do mouse no app da Web, selecione Conferir código-fonte da página e pesquise o nome de exibição. Ele aparece no código-fonte HTML bruto retornado do servidor.

7. Acessar informações do restaurante

O app da Web inclui dados simulados de restaurantes e avaliações.

Adicionar um ou mais restaurantes

Para inserir dados simulados de restaurantes no seu banco de dados local do Cloud Firestore, siga estas etapas:

  1. No app da Web, selecione 2cf67d488d8e6332.png > Adicionar restaurantes de exemplo.
  2. No console do Firebase, na página Banco de dados do Firestore, selecione restaurantes. Você encontrará os documentos de nível superior na coleção do restaurante. Cada um deles representa um restaurante.
  3. Clique em alguns documentos para explorar as propriedades de um documento de restaurante.

Mostrar a lista de restaurantes

Seu banco de dados do Cloud Firestore agora tem restaurantes que o app da Web Next.js pode exibir.

Para definir o código de busca de dados, siga estas etapas:

  1. No arquivo src/app/page.js, encontre o componente de servidor <Home /> e revise a chamada para a função getRestaurants, que recupera uma lista de restaurantes no ambiente de execução do servidor. Implemente a função getRestaurants nas etapas a seguir.
  2. No arquivo src/lib/firebase/firestore.js, substitua as funções applyQueryFilters e getRestaurants pelo seguinte código:
function applyQueryFilters(q, { category, city, price, sort }) {
        if (category) {
                q = query(q, where("category", "==", category));
        }
        if (city) {
                q = query(q, where("city", "==", city));
        }
        if (price) {
                q = query(q, where("price", "==", price.length));
        }
        if (sort === "Rating" || !sort) {
                q = query(q, orderBy("avgRating", "desc"));
        } else if (sort === "Review") {
                q = query(q, orderBy("numRatings", "desc"));
        }
        return q;
}

export async function getRestaurants(filters = {}) {
        let q = query(collection(db, "restaurants"));

        q = applyQueryFilters(q, filters);
        const results = await getDocs(q);
        return results.docs.map(doc => {
                return {
                        id: doc.id,
                        ...doc.data(),
                        // Only plain objects can be passed to Client Components from Server Components
                        timestamp: doc.data().timestamp.toDate(),
                };
        });
}
  1. Atualize o app da Web. As imagens do restaurante aparecem como blocos na página.

Verificar se as listas do restaurante são carregadas no ambiente de execução do servidor

Usando o framework Next.js, pode não ser óbvio quando os dados são carregados no ambiente de execução do servidor ou do lado do cliente.

Para verificar se as fichas de restaurantes são carregadas no ambiente de execução do servidor, siga estas etapas:

  1. No app da Web, abra o DevTools e desative o JavaScript.

Desativar o JavaScipt no DevTools

  1. Atualize o app da Web. As listas dos restaurantes ainda são carregadas. As informações do restaurante são retornadas na resposta do servidor. Quando o JavaScript está ativado, as informações do restaurante são hidratadas com o código JavaScript do lado do cliente.
  2. No DevTools, reative o JavaScript.

Detectar atualizações de restaurantes com listeners de snapshots do Cloud Firestore

Na seção anterior, você soube como o conjunto inicial de restaurantes foi carregado do arquivo src/app/page.js. O arquivo src/app/page.js é um componente do servidor e é renderizado no servidor, incluindo o código de busca de dados do Firebase.

O arquivo src/components/RestaurantListings.jsx é um componente do cliente e pode ser configurado para hidratar a marcação renderizada pelo servidor.

Se quiser configurar o arquivo src/components/RestaurantListings.jsx para hidratar a marcação renderizada pelo servidor, siga estas etapas:

  1. No arquivo src/components/RestaurantListings.jsx, observe o seguinte código, que já está escrito para você:
useEffect(() => {
        const unsubscribe = getRestaurantsSnapshot(data => {
                setRestaurants(data);
        }, filters);

        return () => {
                unsubscribe();
        };
}, [filters]);

Esse código invoca a função getRestaurantsSnapshot(), que é semelhante à função getRestaurants() implementada em uma etapa anterior. No entanto, essa função de snapshot fornece um mecanismo de callback para que o callback seja invocado sempre que uma mudança for feita na coleção do restaurante.

  1. No arquivo src/lib/firebase/firestore.js, substitua a função getRestaurantsSnapshot() pelo seguinte código:
export function getRestaurantsSnapshot(cb, filters = {}) {
        if (typeof cb !== "function") {
                console.log("Error: The callback parameter is not a function");
                return;
        }

        let q = query(collection(db, "restaurants"));
        q = applyQueryFilters(q, filters);

        const unsubscribe = onSnapshot(q, querySnapshot => {
                const results = querySnapshot.docs.map(doc => {
                        return {
                                id: doc.id,
                                ...doc.data(),
                                // Only plain objects can be passed to Client Components from Server Components
                                timestamp: doc.data().timestamp.toDate(),
                        };
                });

                cb(results);
        });

        return unsubscribe;
}

As alterações feitas na página do banco de dados do Firestore agora são refletidas no app da Web em tempo real.

  1. No app da Web, selecione 27ca5d1e8ed8adfe.png > Adicionar restaurantes de exemplo. Se a função de snapshot for implementada corretamente, os restaurantes vão aparecer em tempo real, sem precisar atualizar a página.

8. Salvar dados do usuário no app da Web

  1. No arquivo src/lib/firebase/firestore.js, substitua a função updateWithRating() pelo seguinte código:
const updateWithRating = async (
        transaction,
        docRef,
        newRatingDocument,
        review
) => {
        const restaurant = await transaction.get(docRef);
        const data = restaurant.data();
        const newNumRatings = data?.numRatings ? data.numRatings + 1 : 1;
        const newSumRating = (data?.sumRating || 0) + Number(review.rating);
        const newAverage = newSumRating / newNumRatings;

        transaction.update(docRef, {
                numRatings: newNumRatings,
                sumRating: newSumRating,
                avgRating: newAverage,
        });

        transaction.set(newRatingDocument, {
                ...review,
                timestamp: Timestamp.fromDate(new Date()),
        });
};

Esse código insere um novo documento do Firestore que representa a nova avaliação. O código também atualiza o documento atual do Firestore que representa o restaurante com números atualizados para o número de avaliações e a classificação média calculada.

  1. Substitua a função addReviewToRestaurant() por este código:
export async function addReviewToRestaurant(db, restaurantId, review) {
        if (!restaurantId) {
                throw new Error("No restaurant ID was provided.");
        }

        if (!review) {
                throw new Error("A valid review has not been provided.");
        }

        try {
                const docRef = doc(collection(db, "restaurants"), restaurantId);
                const newRatingDocument = doc(
                        collection(db, `restaurants/${restaurantId}/ratings`)
                );

                await runTransaction(db, transaction =>
                        updateWithRating(transaction, docRef, newRatingDocument, review)
                );
        } catch (error) {
                console.error(
                        "There was an error adding the rating to the restaurant.",
                        error
                );
                throw error;
        }
}

Implementar uma ação do servidor Next.js

Uma ação do servidor Next.js oferece uma API conveniente para acessar dados de formulário, como data.get("text"), para acessar o valor de texto do payload de envio de formulário.

Se quiser usar uma ação do servidor do Next.js para processar o envio do formulário de avaliação, siga estas etapas:

  1. No arquivo src/components/ReviewDialog.jsx, encontre o atributo action no elemento <form>.
<form action={handleReviewFormSubmission}>

O valor do atributo action se refere a uma função que você vai implementar na próxima etapa.

  1. No arquivo src/app/actions.js, substitua a função handleReviewFormSubmission() pelo seguinte código:
// This is a next.js server action, which is an alpha feature, so
// use with caution.
// https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions
export async function handleReviewFormSubmission(data) {
        const { app } = await getAuthenticatedAppForUser();
        const db = getFirestore(app);

        await addReviewToRestaurant(db, data.get("restaurantId"), {
                text: data.get("text"),
                rating: data.get("rating"),

                // This came from a hidden form field.
                userId: data.get("userId"),
        });
}

Adicionar avaliações de um restaurante

Você implementou a compatibilidade com envios de avaliação, então agora pode verificar se as avaliações foram inseridas corretamente no Cloud Firestore.

Para adicionar uma avaliação e verificar se ela está inserida no Cloud Firestore, siga estas etapas:

  1. No app da Web, selecione um restaurante na página inicial.
  2. Na página do restaurante, clique em 3e19beef78bb0d0e.png.
  3. Selecione uma nota.
  4. Escreva uma avaliação.
  5. Clique em Enviar. Sua avaliação vai aparecer no topo da lista.
  6. No Cloud Firestore, pesquise o documento do restaurante que você avaliou no painel Adicionar documento e selecione-o.
  7. No painel Iniciar coleção, selecione classificações.
  8. No painel Adicionar documento, encontre o documento da sua avaliação para verificar se ele foi inserido conforme o esperado.

Documentos no emulador do Firestore

9. Salvar arquivos enviados pelo usuário no app da Web

Nesta seção, você vai adicionar uma funcionalidade para substituir a imagem associada a um restaurante quando estiver conectado. Você faz upload da imagem para o Firebase Storage e atualiza o URL da imagem no documento do Cloud Firestore que representa o restaurante.

Para salvar arquivos enviados por usuários no app da Web, siga estas etapas:

  1. No arquivo src/components/Restaurant.jsx, observe o código executado quando o usuário faz upload de um arquivo:
async function handleRestaurantImage(target) {
        const image = target.files ? target.files[0] : null;
        if (!image) {
                return;
        }

        const imageURL = await updateRestaurantImage(id, image);
        setRestaurant({ ...restaurant, photo: imageURL });
}

Nenhuma mudança é necessária, mas você vai implementar o comportamento da função updateRestaurantImage() nas etapas a seguir.

  1. No arquivo src/lib/firebase/storage.js, substitua as funções updateRestaurantImage() e uploadImage() pelo seguinte código:
export async function updateRestaurantImage(restaurantId, image) {
        try {
                if (!restaurantId)
                        throw new Error("No restaurant ID has been provided.");

                if (!image || !image.name)
                        throw new Error("A valid image has not been provided.");

                const publicImageUrl = await uploadImage(restaurantId, image);
                await updateRestaurantImageReference(restaurantId, publicImageUrl);

                return publicImageUrl;
        } catch (error) {
                console.error("Error processing request:", error);
        }
}

async function uploadImage(restaurantId, image) {
        const filePath = `images/${restaurantId}/${image.name}`;
        const newImageRef = ref(storage, filePath);
        await uploadBytesResumable(newImageRef, image);

        return await getDownloadURL(newImageRef);
}

A função updateRestaurantImageReference() já foi implementada para você. Essa função atualiza um documento de restaurante no Cloud Firestore com um URL de imagem atualizado.

Verificar a funcionalidade de upload de imagem

Para verificar se o upload da imagem é o esperado, siga estas etapas:

  1. No app da Web, verifique se você fez login e selecione um restaurante.
  2. Clique em 7067eb41fea41ff0.png e faça upload de uma imagem do seu sistema de arquivos. A imagem sai do ambiente local e é carregada no Cloud Storage. A imagem aparece imediatamente após o upload.
  3. Acesse o Cloud Storage para Firebase.
  4. Navegue até a pasta que representa o restaurante. A imagem que você enviou existe na pasta.

6cf3f9e2303c931c.png

10. Conclusão

Parabéns! Você aprendeu a usar o Firebase para adicionar recursos e funcionalidades a um app Next.js. Especificamente, você usou o seguinte:

Saiba mais