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.
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:
- Build e implantação automáticos:este codelab usa o Firebase App Hosting para criar e implantar automaticamente seu código Next.js sempre que você envia para uma ramificação configurada.
- Login e logout:o app da Web concluído 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
- Uma conta no GitHub
- 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
- 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 e o repositório do GitHub
Este codelab fornece a base de código inicial do app e depende da CLI do Firebase.
Crie um repositório do GitHub
O código-fonte do codelab está disponível em https://github.com/firebase/friendlyeats-web. O repositório 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`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.
Copie a pasta nextjs-start
para seu próprio repositório:
- Usando um terminal, crie uma pasta no computador e mude para o novo diretório:
mkdir codelab-friendlyeats-web cd codelab-friendlyeats-web
- Use o pacote npm giget para buscar apenas a pasta
nextjs-start
:npx giget@latest gh:firebase/friendlyeats-web/nextjs-start#master . --install
- Rastreie as mudanças localmente com o git:
git init git add . git commit -m "codelab starting point" git branch -M main
- Crie um repositório do GitHub: https://github.com/new. Dê o nome que quiser.
- Copie o novo URL criado pelo GitHub. Ela vai aparecer assim:
https://github.com/<USER_NAME>/<REPOSITORY_NAME>.git
ougit@github.com:<USER_NAME>/<REPOSITORY_NAME>.git
- Envie as mudanças locais para o novo repositório do GitHub executando o seguinte comando. Substitua o URL real do repositório pelo marcador de posição
<REPOSITORY_URL>
.git remote add origin <REPOSITORY_URL> git push -u origin main
- Agora você vai ver o código inicial no repositório do GitHub.
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 v14.1.0 ou mais recente:
firebase --version
Se você vir uma versão mais antiga ou não tiver a CLI do Firebase instalada, execute o comando de instalação:
npm install -g firebase-tools@latest
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
- Execute o seguinte comando para fazer login na CLI do Firebase:
firebase login
- Para que o Firebase colete dados, insira
Y
ouN
. - 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
- Faça login no console do Firebase usando a mesma Conta do Google da etapa anterior.
- Clique no botão para criar um projeto e insira um nome (por exemplo,
FriendlyEats Codelab
).
- Clique em Continuar.
- Se solicitado, leia e aceite os Termos do Firebase e clique em Continuar.
- (Opcional) Ative a assistência de IA no console do Firebase (chamada de "Gemini no Firebase").
- Neste codelab, você não precisa do Google Analytics. Portanto, desative a opção do Google Analytics.
- Clique em Criar projeto, aguarde o provisionamento e clique em Continuar.
Fazer upgrade do plano de preços do Firebase
Para usar o Firebase App Hosting e o Cloud Storage para Firebase, seu projeto do Firebase precisa estar no plano de preços Blaze de pagamento por uso, o que significa que ele está vinculado 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 sem custos financeiros do Cloud Billing.
- Se você estiver fazendo este codelab como parte de um evento, pergunte ao organizador se há créditos do Cloud disponíveis.
Para fazer upgrade do seu projeto para o plano Blaze, siga estas etapas:
- No console do Firebase, selecione Fazer upgrade do seu plano.
- Selecione o plano Blaze. Siga as instruções na tela para vincular uma conta do Cloud Billing ao seu projeto.
Se você precisou criar uma conta do Cloud Billing como parte desse upgrade, talvez seja necessário voltar para o fluxo de upgrade no console do Firebase para concluir o processo.
Adicionar um app da Web ao seu projeto do Firebase
- Navegue até a Visão geral do projeto no seu projeto do Firebase e clique em
Web.
Se você já tiver apps registrados no projeto, clique em Adicionar app para ver o ícone da Web. - Na caixa de texto Apelido do app, digite um apelido fácil de lembrar, como
My Next.js app
. - Deixe a caixa de seleção Também configurar o Firebase Hosting para este app desmarcada.
- Clique em Registrar app > Continuar para o console.
Configurar serviços do Firebase no console do Firebase
Configurar o Authentication
- No console do Firebase, navegue até Autenticação.
- Clique em Começar.
- Na coluna Outros provedores, clique em Google > Ativar.
- Na caixa de texto Nome voltado ao público do projeto, digite um nome fácil de lembrar, como
My Next.js app
. - No menu suspenso E-mail de suporte do projeto, selecione seu endereço de e-mail.
- Clique em Salvar.
Configurar o Cloud Firestore
- No painel à esquerda do console do Firebase, expanda Build e selecione Banco de dados do Firestore.
- Clique em Criar banco de dados.
- Deixe o ID do banco de dados definido como
(default)
. - Selecione um local para o banco de dados e clique em Próxima.
No caso de apps reais, escolha um local próximo aos usuários. - Clique em Iniciar no modo de teste. Leia o aviso sobre as regras de segurança.
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. - Clique em Criar.
Configurar o Cloud Storage para Firebase
- No painel à esquerda do console do Firebase, expanda Build e selecione Storage.
- Clique em Começar.
- Selecione um local para seu bucket de armazenamento padrão.
Os buckets emUS-WEST1
,US-CENTRAL1
eUS-EAST1
podem aproveitar o nível"Sempre sem custo financeiro" do Google Cloud Storage. Os buckets em todos os outros locais seguem os preços e usos do Google Cloud Storage. - Clique em Iniciar no modo de teste. Leia o aviso sobre as regras de segurança.
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. - Clique em Criar.
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.
- No terminal, configure a CLI para usar o projeto do Firebase que você criou antes:
Quando um alias for solicitado, digitefirebase use --add
friendlyeats-codelab
. - Para implantar essas regras de segurança (e os índices que serão necessários mais tarde), execute este comando no terminal:
firebase deploy --only firestore,storage
- Se aparecer a pergunta
"Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?"
, pressioneEnter
para selecionar Sim.
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 |
| Componentes do React para filtros, cabeçalhos, detalhes de restaurantes e avaliações |
| Funções utilitárias que não estão necessariamente vinculadas ao React ou Next.js. |
| Código específico e configuração do Firebase |
| Recursos estáticos no app da Web, como ícones |
| Roteamento com o roteador de apps Next.js |
| Dependências do projeto com npm |
| Configuração específica do Next.js (as ações do servidor estão ativadas) |
| 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. Criar um back-end do App Hosting
Nesta seção, você vai configurar um back-end do App Hosting para monitorar uma ramificação no seu repositório git.
Ao final desta seção, você terá um back-end do App Hosting conectado ao seu repositório no GitHub, que vai recriar e lançar automaticamente uma nova versão do app sempre que você enviar um novo commit para a ramificação main
.
Criar um back-end
- Acesse a página App Hosting no console do Firebase:
- Clique em "Começar" para iniciar o fluxo de criação do back-end. Configure o back-end da seguinte maneira:
- Escolha uma região. Para um app real, escolha a região mais próxima dos usuários.
- Siga as instruções na etapa "Importar um repositório do GitHub" para conectar o repositório do GitHub que você criou anteriormente.
- Defina as configurações de implantação:
- Mantenha o diretório raiz como
/
- Defina a ramificação ativa como
main
- Ativar os lançamentos automáticos
- Mantenha o diretório raiz como
- Nomeie seu back-end como
friendlyeats-codelab
. - Em "Associar um app da Web do Firebase", clique em "Criar um app da Web do Firebase".
- Clique em "Concluir e implantar". Depois de um momento, você vai acessar uma nova página em que poderá conferir o status do novo back-end do App Hosting.
- Quando a implantação for concluída, clique no seu domínio sem custo financeiro em "Domínios". Isso pode levar alguns minutos para começar a funcionar devido à propagação do DNS.
- Ops. Ao carregar a página, você vai encontrar uma mensagem de erro que diz "Erro de aplicativo: ocorreu uma exceção do lado do servidor. Consulte os registros do servidor para mais informações".
- No console do Firebase, verifique a guia "Registros" do back-end do App Hosting. Você vai encontrar um registro "Erro: não implementado". Isso será corrigido na próxima etapa, quando adicionarmos a autenticação.
Você implantou o app da Web inicial. Sempre que você enviar uma nova confirmação para a ramificação main
do seu repositório do GitHub, um novo build e lançamento vão começar no console do Firebase, e seu site será atualizado automaticamente quando o lançamento for concluído.
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.
Adicione um domínio autorizado
O Firebase Authentication só aceita solicitações de login de domínios permitidos. Aqui, vamos adicionar o domínio do back-end do App Hosting à lista de domínios aprovados no seu projeto.
- Copie o domínio do back-end do App Hosting na página "Visão geral" do App Hosting.
- Acesse a guia Configurações de autenticação e escolha Domínios autorizados.
- Clique no botão Adicionar domínio.
- Insira o domínio do back-end do App Hosting.
- Clique em Adicionar.
Implementar as funções de login e logout
- No arquivo
src/lib/firebase/auth.js
, substitua as funçõesonAuthStateChanged
,onIdTokenChanged
,signInWithGoogle
esignOut
pelo seguinte código:
export function onAuthStateChanged(cb) {
return _onAuthStateChanged(auth, cb);
}
export function onIdTokenChanged(cb) {
return _onIdTokenChanged(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 |
Adiciona um observador para mudanças no estado de login do usuário. | |
Adiciona um observador para mudanças no token de ID do usuário. | |
Cria uma instância do provedor de autenticação do Google. | |
Inicia um fluxo de autenticação baseado em caixa de diálogo. | |
Desconecta o usuário. |
No arquivo src/components/Header.jsx
, o código já invoca as funções signInWithGoogle
e signOut
.
Enviar o estado de autenticação para o servidor
Para transmitir o estado de autenticação ao servidor, vamos usar cookies. Sempre que o estado de autenticação mudar no cliente, vamos atualizar o cookie __session
.
Em src/components/Header.jsx
, substitua a função useUserSession
pelo seguinte código:
function useUserSession(initialUser) {
useEffect(() => {
return onIdTokenChanged(async (user) => {
if (user) {
const idToken = await user.getIdToken();
await setCookie("__session", idToken);
} else {
await deleteCookie("__session");
}
if (initialUser?.uid === user?.uid) {
return;
}
window.location.reload();
});
}, [initialUser]);
return initialUser;
}
Ler o estado de autenticação no servidor
Vamos usar o FirebaseServerApp para espelhar o estado de autenticação do cliente no servidor.
Abra src/lib/firebase/serverApp.js
e substitua a função getAuthenticatedAppForUser
:
export async function getAuthenticatedAppForUser() {
const authIdToken = (await cookies()).get("__session")?.value;
// Firebase Server App is a new feature in the JS SDK that allows you to
// instantiate the SDK with credentials retrieved from the client & has
// other affordances for use in server environments.
const firebaseServerApp = initializeServerApp(
// https://github.com/firebase/firebase-js-sdk/issues/8863#issuecomment-2751401913
initializeApp(),
{
authIdToken,
}
);
const auth = getAuth(firebaseServerApp);
await auth.authStateReady();
return { firebaseServerApp, currentUser: auth.currentUser };
}
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 lançar um novo build e verificar o que você criou.
- Crie uma confirmação com a mensagem "Add authentication" e envie para o repositório do GitHub.
- Abra a página do App Hosting no console do Firebase e aguarde a conclusão do novo lançamento.
- Verifique o novo comportamento de autenticação:
- No navegador, atualize o app da Web. Seu nome de exibição aparece no cabeçalho.
- Saia e faça login novamente. Repita essa etapa com diferentes usuários.
- 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:
- Faça login no web app, caso ainda não tenha feito isso. Em seguida, selecione
> Adicionar restaurantes de exemplo.
- 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.
- 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:
- No arquivo
src/app/page.js
, encontre o componente de servidor<Home />
e revise a chamada para a funçãogetRestaurants
, que recupera uma lista de restaurantes no ambiente de execução do servidor. Implemente a funçãogetRestaurants
nas etapas a seguir. - No arquivo
src/lib/firebase/firestore.js
, substitua as funçõesapplyQueryFilters
egetRestaurants
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(db = db, 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(),
};
});
}
- Crie um commit com a mensagem "Read the list of restaurants from Firestore" e envie para o repositório do GitHub.
- Abra a página do App Hosting no console do Firebase e aguarde a conclusão do novo lançamento.
- No app da Web, atualize a página. 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:
- No app da Web, abra o DevTools e desative o JavaScript.
- 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.
- 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:
- No arquivo
src/components/RestaurantListings.jsx
, observe o seguinte código, que já está escrito para você:
useEffect(() => {
return getRestaurantsSnapshot((data) => {
setRestaurants(data);
}, filters);
}, [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.
- No arquivo
src/lib/firebase/firestore.js
, substitua a funçãogetRestaurantsSnapshot()
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);
return 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);
});
}
As alterações feitas na página do banco de dados do Firestore agora são refletidas no app da Web em tempo real.
- Crie um commit com a mensagem "Listen for realtime restaurant updates" e envie para seu repositório do GitHub.
- Abra a página do App Hosting no console do Firebase e aguarde a conclusão do novo lançamento.
- No app da Web, selecione
> 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 avaliações enviadas pelo usuário no app da Web
- No arquivo
src/lib/firebase/firestore.js
, substitua a funçãoupdateWithRating()
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.
- Substitua a função
addReviewToRestaurant()
por este código:
export async function addReviewToRestaurant(db, restaurantId, review) {
if (!restaurantId) {
throw new Error("No restaurant ID has been 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`)
);
// corrected line
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:
- No arquivo
src/components/ReviewDialog.jsx
, encontre o atributoaction
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.
- No arquivo
src/app/actions.js
, substitua a funçãohandleReviewFormSubmission()
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:
- Crie um commit com a mensagem "Allow users to submit restaurant reviews" e envie para seu repositório do GitHub.
- Abra a página do App Hosting no console do Firebase e aguarde a conclusão do novo lançamento.
- Atualize o app da Web e selecione um restaurante na página inicial.
- Na página do restaurante, clique em
.
- Selecione uma nota.
- Escreva uma avaliação.
- Clique em Enviar. Sua avaliação vai aparecer no topo da lista.
- No Cloud Firestore, pesquise o documento do restaurante que você avaliou no painel Adicionar documento e selecione-o.
- No painel Iniciar coleção, selecione classificações.
- No painel Adicionar documento, encontre o documento da sua avaliação para verificar se ele foi inserido conforme o esperado.
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:
- 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);
setRestaurantDetails({ ...restaurantDetails, photo: imageURL });
}
Nenhuma mudança é necessária nessa função, mas você vai implementar o comportamento da função updateRestaurantImage()
nas etapas a seguir.
- No arquivo
src/lib/firebase/storage.js
, substitua as funçõesupdateRestaurantImage()
euploadImage()
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:
- Crie um commit com a mensagem "Permitir que os usuários mudem a foto de cada restaurante" e envie para seu repositório do GitHub.
- Abra a página do App Hosting no console do Firebase e aguarde a conclusão do novo lançamento.
- No app da Web, verifique se você fez login e selecione um restaurante.
- Clique em
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.
- Acesse o Cloud Storage para Firebase.
- Navegue até a pasta que representa o restaurante. A imagem que você enviou existe na pasta.
10. Resumir avaliações de restaurantes com a IA generativa
Nesta seção, você vai adicionar um recurso de resumo de avaliações para que um usuário entenda rapidamente o que todos pensam de um restaurante sem precisar ler todas as avaliações.
Armazenar uma chave de API do Gemini no Cloud Secret Manager
- Para usar a API Gemini, você precisará de uma chave de API. Acesse o Google AI Studio e clique em "Criar chave de API".
- Na entrada "Pesquisar projetos do Google Cloud", escolha seu projeto do Firebase. Cada projeto do Firebase é apoiado por um projeto do Google Cloud.
- O App Hosting se integra ao Cloud Secret Manager para permitir que você armazene valores sensíveis, como chaves de API, com segurança:
- Em um terminal, execute o comando para criar um novo secret:
firebase apphosting:secrets:set GEMINI_API_KEY
- Quando o valor secreto for solicitado, copie e cole sua chave da API Gemini do Google AI Studio.
- Quando perguntado se o novo secret é para produção ou teste local, escolha "Produção".
- Quando perguntado se você quer conceder acesso para que a conta de serviço do back-end possa acessar o secret, selecione "Sim".
- Quando for perguntado se o novo secret deve ser adicionado a
apphosting.yaml
, digiteY
para aceitar.
Sua chave de API do Gemini agora está armazenada com segurança no Cloud Secret Manager e pode ser acessada pelo back-end do App Hosting.
Implementar o componente de resumo da avaliação
- Em
src/components/Reviews/ReviewSummary.jsx
, substitua a funçãoGeminiSummary
pelo seguinte código:export async function GeminiSummary({ restaurantId }) { const { firebaseServerApp } = await getAuthenticatedAppForUser(); const reviews = await getReviewsByRestaurantId( getFirestore(firebaseServerApp), restaurantId ); const reviewSeparator = "@"; const prompt = ` Based on the following restaurant reviews, where each review is separated by a '${reviewSeparator}' character, create a one-sentence summary of what people think of the restaurant. Here are the reviews: ${reviews.map((review) => review.text).join(reviewSeparator)} `; try { if (!process.env.GEMINI_API_KEY) { // Make sure GEMINI_API_KEY environment variable is set: // https://firebase.google.com/docs/genkit/get-started throw new Error( 'GEMINI_API_KEY not set. Set it with "firebase apphosting:secrets:set GEMINI_API_KEY"' ); } // Configure a Genkit instance. const ai = genkit({ plugins: [googleAI()], model: gemini20Flash, // set default model }); const { text } = await ai.generate(prompt); return ( <div className="restaurant__review_summary"> <p>{text}</p> <p>✨ Summarized with Gemini</p> </div> ); } catch (e) { console.error(e); return <p>Error summarizing reviews.</p>; } }
- Crie um commit com a mensagem "Use AI to summarize reviews" e envie para seu repositório do GitHub.
- Abra a página do App Hosting no console do Firebase e aguarde a conclusão do novo lançamento.
- Abra a página de um restaurante. Na parte de cima, você vai encontrar um resumo de uma frase com todas as avaliações na página.
- Adicione uma nova avaliação e atualize a página. O resumo vai mudar.
11. 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:
- Firebase App Hosting para criar e implantar automaticamente seu código Next.js sempre que você enviar para uma ramificação configurada.
- Firebase Authentication para ativar a funcionalidade de login e logout.
- Cloud Firestore para dados de restaurantes e dados de avaliações de restaurantes.
- Cloud Storage para Firebase, para imagens de restaurantes.