WEB3DEV

Cover image for Como Criar um Aplicativo de Lista de Participantes de Conferência Web3
Panegali
Panegali

Posted on

Como Criar um Aplicativo de Lista de Participantes de Conferência Web3

Usando Airstack, IA, POAP, Vite e React


Nos velhos tempos de participação em conferências, a lista de pessoas que compareceram ao evento muitas vezes era algo que você só conseguia obter se pagasse por patrocínio ou comprasse a lista posteriormente. No entanto, com o surgimento da Prova de Presença (Proof of Attendance), é possível não apenas comemorar os eventos que você participou de uma maneira fácil de visualizar, mas também obter listas de participantes depois do evento.

Hoje, vamos construir um aplicativo que permite que você insira um evento ao qual você compareceu e veja uma lista de participantes quase em tempo real. Mas antes de fazermos isso, vamos falar sobre o protocolo de prova de presença. O protocolo permite que as pessoas criem NFTs que representam sua presença em eventos específicos. O site do POAP diz o seguinte:

O Protocolo de Prova de Presença (POAP) transforma momentos preciosos em colecionáveis. Usando a tecnologia blockchain, o POAP tokeniza suas memórias, para que elas possam durar para sempre e serem verdadeiramente suas.

O protocolo torna fácil verificar de forma escalável e comprovável a presença em vários eventos. Isso traz benefícios pessoais, como a transformação de momentos em colecionáveis, como diz o POAP, transformando momentos em itens colecionáveis, e benefícios comerciais, pois você pode criar listas de clientes potenciais, fazer contatos e muito mais sabendo quem participou dos mesmos eventos que você.

Vamos mergulhar no tutorial!

Iniciando

Vamos usar as APIs gratuitas da Airstack para nos ajudar a construir nosso aplicativo de lista de participantes de conferência Web3. A Airstack é uma plataforma de desenvolvedor projetada para facilitar a consulta de dados Web3 e a construção de aplicativos em torno desses dados. Suas ferramentas são robustas e impressionantes. Vamos ver como podemos usar essas APIs para construir uma lista de participantes em um evento Web3 específico que emitiu POAPs.

Vamos usar o React para construir nosso aplicativo, então certifique-se de ter o seguinte:

Quando estiver pronto e tiver se cadastrado em sua conta na Airstack, vá em frente e pegue a chave da API em sua conta. Você pode fazer isso clicando em seu nome de usuário e selecionando "View API Keys" (Ver Chaves da API). Copie a chave e a salve em um local seguro. Vamos precisar dela em breve.

Agora, vamos construir a base para nosso aplicativo.

Configurando o Aplicativo React

No seu terminal/linha de comando (vou chamá-lo de terminal), certifique-se de navegar até o diretório onde você gerencia todos os seus incríveis projetos de desenvolvimento. Em seguida, execute o seguinte:

npm create vite@latest web3-conference-attendees -- --template react
Enter fullscreen mode Exit fullscreen mode

Se você estiver usando o NPM 6, atualize-o, se possível, ou execute este comando:

npm create vite@latest web3-conference-attendees --template react
Enter fullscreen mode Exit fullscreen mode

Quando isso for feito, você verá as etapas impressas no terminal que precisam ser seguidas.

Mude para o diretório de seu novo projeto:

cd web3-conference-attendees
Enter fullscreen mode Exit fullscreen mode

Em seguida, instale as dependências:

npm install
Enter fullscreen mode Exit fullscreen mode

E, finalmente, você pode executar o aplicativo inicial básico com:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Mas não queremos um aplicativo inicial, não é mesmo? Abra outra janela de terminal e vamos instalar outra dependência. Vamos instalar o Airstack React SDK. Execute o seguinte comando:

npm install @airstack/airstack-react
Enter fullscreen mode Exit fullscreen mode

Quando isso for feito, teremos o scaffolding para começar a criar nosso aplicativo. Vou manter as coisas simples e forçá-lo a escrever um pouco de CSS puro neste tutorial, mas sinta-se à vontade para usar qualquer estrutura CSS que desejar, se preferir. Vamos começar a criar a interface do usuário (UI).

Criando a interface do usuário

Antes de escrevermos qualquer código, vamos pensar no que estamos tentando realizar.

  • A pessoa que usa o aplicativo quer poder entrar em um evento de conferência que emite POAPs e ver uma lista de usuários (carteiras + metadados) que também participaram do evento.
  • Devemos facilitar a inserção das informações da conferência (usaremos a Airstack AI para nos ajudar aqui!).
  • A lista de participantes deve ser exibida em um formato de tabela com informações como endereço da carteira, contas sociais da Web3 e muito mais.

Em um aplicativo de produção, provavelmente gostaríamos de permitir que o usuário insira um endereço de carteira ou conecte o seu próprio endereço para que possamos criar relacionamentos e conexões automatizadas, mas vamos ignorar isso neste tutorial. Em vez disso, criaremos uma interface que não exija autenticação. Em breve, conectaremos a interface do usuário à API da Airstack.

Abra seu projeto React em seu editor de código. Exclua imediatamente o arquivo App.css. Você também precisará remover sua referência do arquivo App.js. Usaremos o arquivo index.css para todo o nosso CSS.

Agora, crie uma pasta chamada components dentro do diretório src. Dentro desta pasta, vamos criar alguns arquivos que sabemos que precisaremos. Dê uma olhada nos requisitos do nosso projeto e nos esboços. Precisaremos de, no mínimo:

  • NavBar
  • EventSelector
  • TableView

Crie um arquivo para cada um desses componentes dentro da sua pasta components. O componente NavBar seria chamado de NavBar.jsx e o EventSelector seria chamado de EventSelector.jsx, e assim por diante.

Vamos construir cada componente um de cada vez, começando pelo NavBar, portanto, abra esse arquivo no seu editor de código. Adicione o seguinte a esse arquivo:

import React from 'react'

const NavBar = () => {
 return (
   <div className="navbar">
     <h3>POAPify</h3>     
   </div>
 )
}
export default NavBar
Enter fullscreen mode Exit fullscreen mode

Este é um arquivo muito simples que cria a nossa barra de navegação superior. É extensível para que, se você quiser adicionar uma conexão de carteira, você possa exibir o perfil e os detalhes de saída aqui neste NavBar. Para nós, ele apenas mostrará o nome do aplicativo.

Ainda não há muito aqui, mas lembre-se de adicionar isso ao nosso arquivo App.jsx para que possamos renderizar a barra de navegação. Abra esse arquivo e substitua tudo por isso:

import NavBar from './components/NavBar'

function App() {
  return (
    <>
    <NavBar />
    </>
  )
}
export default App
Enter fullscreen mode Exit fullscreen mode

Abra seu aplicativo no seu navegador Web e você não verá muito, apenas a palavra "POAPify". Vamos precisar de algum estilo. Vamos trabalhar nisso agora. Abra seu arquivo index.css e substitua tudo por isso:

body {
  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
  min-height: 100vh;
  background: #213547;
  color: #fff;
}

.navbar {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}
Enter fullscreen mode Exit fullscreen mode

Agora, se você der uma olhada no aplicativo na janela do navegador, verá que ele ainda parece ruim, mas está um pouco melhor!

Vamos começar a construir o restante do aplicativo. Voltaremos para conectar funções e fazer chamadas de API em breve. No arquivo App.jsx, vamos adicionar uma visualização que contenha nosso estado vazio e a visualização de tabela. Abaixo da NavBar, adicione o seguinte:

<div className="main-view">
 <div className="event-input">
   <EventSelector />
 </div>
 <div>
   <TableView />
 </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Agora adicionamos os componentes que criamos anteriormente. Eventualmente, vamos passar props (propriedades*/atributos*) **para esses componentes, mas por enquanto, vamos apenas começar a construí-los para ver como eles ficam.

Vamos começar com o componente EventSelector.jsx. Abra esse arquivo e adicione o seguinte:

import React from "react";
const EventSelector = (props) => {
 return (
   <div className="event-search">
     <h3>Search for an event</h3>
     <input
       type="text"
       value={props.eventId}
       onChange={(e) => props.setEventId({ eventId: e.target.value })}
       placeholder="Insira o ID do evento para pesquisar"
     />
   </div>
 );
};

export default CommunitySelector;
Enter fullscreen mode Exit fullscreen mode

Ele recebe dois valores de props e exibe o ID do evento que você deseja buscar. Lembre-se de que obteremos o ID do evento graças à magia da IA e da Airstack. Também usaremos a IA para criar nossa consulta a Airstack, mas isso virá mais tarde.

Ainda temos mais um componente para construir antes de começarmos a conectar tudo às APIs da Airstack. Vamos construir nosso componente de tabela. Abra o arquivo TableView.jsx e adicione o seguinte:

import React from 'react'
import graph from "../assets/graph.png";

const TableView = (props) => {
 const renderPopulated = () => {
   return (
     <div>
     </div>
   )
 }
 const renderEmpty = () => {
   return (
     <div className="empty-state">
       <img src={graph} alt="Graph of knowledge" />
       <h1>Enter an Event ID and see attendees now</h1>
       <button disabled={!props.selectionsMade} onClick={props.searchAttendees}>
         View now
       </button>
     </div>
   );
 };
 return (
   <div className="table">
     {
       props.results.length ?
       <>{renderPopulated()}</> :
       <>{renderEmpty()}</>
     }
   </div>
 )
}
export default TableView
Enter fullscreen mode Exit fullscreen mode

Como você pode ver, ainda não criamos a exibição preenchida. Começaremos com o estado vazio, nos conectaremos à API e, quando tivermos dados, poderemos criar nossa exibição preenchida.

Esse componente está renderizando um bom estado vazio que tem uma imagem que gerei com o Midjourney. Você pode usar a minha imagem ou qualquer outra que desejar. Aqui está a imagem:

Certifique-se de que a sua imagem tenha o mesmo nome que a minha e seja adicionada à pasta assets no diretório src do projeto.

Estamos passando duas props para esse componente. Estamos enviando os resultados de nossa pesquisa e a função para executar a pesquisa. Simples, certo?

Temos duas coisas que precisamos fazer antes de podermos ver como tudo isso se parece. Vamos adicionar um pouco de CSS. Atualize seu arquivo CSS para incluir o seguinte:

body {
 font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
 min-height: 100vh;
 background: #213547;
 color: #fff;
}

.navbar {
 display: flex;
 flex-direction: row;
 justify-content: space-between;
}

.event-input {
 display: flex;
 flex-direction: row;
 justify-content: space-between;
 margin: auto;
}

.table {
 width: 100%;
 margin: auto;
 min-height: 400px;
 margin-top: 20px;
 background: #dadada;
 border-radius: 10px;
}
.empty-state {
 width: 100%;
 height: 100%;
 display: flex;
 flex-direction: column;
 justify-content: center;
 align-items: center;
 padding-bottom: 50px;
 color: #213547;
}
.empty-state img {
 max-width: 25%;
 border-radius: 50px;
 margin-top: 50px;
}
Enter fullscreen mode Exit fullscreen mode

Vá até o arquivo App.jsx e atualize todo o arquivo para que fique assim:

import { useState } from "react";
import NavBar from './components/NavBar'
import EventSelector from "./components/EventSelector";
import TableView from "./components/TableView";

function App() {
 const [variables, setVariables] = useState({
   eventId: ""
 })

 return (
   <>
    <NavBar walletAddress={walletAddress} disconnect={disconnect} />
    <div className="main-view">
       <div className="event-input">        
         <EventSelector eventId={variables.eventId} setEventId={setVariables} />
       </div>
       <div>
         <TableView eventId={variables.eventId} results={null} searchAttendees={() => console.log("Real function soon!")} />
       </div>
     </div>
   </>
 )
}
export default App
Enter fullscreen mode Exit fullscreen mode

Adicionamos espaços reservados para todos as props e funções que estamos passando para nossos componentes. Nossa variável de estado é chamada de variables e é formatada como um objeto porque a passaremos para nossa consulta GraphQL quando trabalharmos com o SDK Airstack.

Com isso, você deverá conseguir ver o que construímos até agora!

Agora parece um aplicativo de verdade! Só precisamos nos conectar à API Airstack e renderizar nossa tabela com a lista de participantes de qualquer evento que procurarmos.

Conectando-se a Airstack

Antes de escrevermos qualquer código, devemos fazer algo semelhante ao que fizemos com a interface do usuário. Devemos pensar em nossos objetivos e planejar nosso curso de ação.

Sabemos que queremos receber entradas e solicitar uma lista de pessoas que correspondam aos critérios que inserirmos. A entrada neste caso é o ID do evento.

Felizmente, a Airstack possui uma API GraphQL robusta para dar suporte à nossa consulta e muitas outras. Sua documentação é fantástica. Melhor ainda, eles têm um assistente de IA para nos ajudar a construir a consulta que podemos então adicionar ao nosso aplicativo.

Construir de forma mais inteligente

Poderíamos ler a documentação e aprender a escrever nossas consultas (e você deve fazer isso!), mas também podemos usar a IA para escrever a consulta para nós. Se você fizer login em sua conta Airstack, notará a opção "AI Assistant" \
(Assistente de IA) na parte superior. Vamos ver se podemos fazer com que ele construa uma consulta que corresponda a algo que poderíamos usar.

É incrível como isso funciona bem. O resultado daquela solicitação em linguagem natural foi esta consulta GraphQL:

query POAPEventAttendeesAndSocialProfiles {
 Poaps(input: {filter: {eventId: {_eq: "65602"}}, blockchain: ALL, limit: 200}) {
   Poap {
     owner {
       identity
       socials {
         profileName
         userHomeURL
         profileTokenUri
       }
     }
   }
 }
}
Enter fullscreen mode Exit fullscreen mode

Isso inicializa nossas chamadas de API e acelera muito o desenvolvimento. Brinque um pouco com o assistente de IA. Ele será muito útil à medida que você construir mais coisas com a Airstack.

Usaremos a consulta gerada pelo assistente de IA, mas teremos que definir dinamicamente o ID do evento com base na entrada. Provavelmente, devemos incluir um link para o construtor de consulta de IA da Airstack para ajudar as pessoas a procurar os IDs de eventos. Atualize o arquivo EventSelector.jsx para incluir um link para o explorador da Airstack da seguinte forma:

import React from "react";

const EventSelector = (props) => {
 return (
   <div className="event-search">
     <h3>Search for an event</h3>
     <p><a style={{color: "#fff", textDecoration: "underline"}} href="https://app.airstack.xyz/explorer" target="_blank" rel="noopener noreferrer">Use Airstack AI to look up event IDs</a></p>
     <input
       type="text"
       value={props.eventId}
       onChange={(e) => props.setEventId({eventId: e.target.value})}
       placeholder="Enter event ID to search"
     />
   </div>
 );
};

export default EventSelector;
Enter fullscreen mode Exit fullscreen mode

Agora, vamos começar a criar nossas chamadas de API. No topo do seu arquivo App.jsx, importe o SDK Airstack desta forma:

import { init, useLazyQueryWithPagination } from "@airstack/airstack-react";
init("SUA CHAVE DE API AIRSTACK");
Enter fullscreen mode Exit fullscreen mode

A função init permite fazer a solicitação com sua chave de API para aumentar o limite de solicitações por minuto.

Vamos usar a consulta preguiçosa com paginação porque precisamos acionar a consulta manualmente e não sabemos quantos resultados podemos obter.

Agora, em seu componente de função principal, adicione o seguinte:

const [fetch, { data, loading, pagination, error }] = useLazyQueryWithPagination(query, variables, {});
const { hasNextPage, hasPrevPage, getNextPage, getPrevPage } = pagination;
Enter fullscreen mode Exit fullscreen mode

Adicionei isso abaixo dos meus ganchos useState.

Agora, precisamos criar nossa consulta para podermos acionar a solicitação à API quando alguém clicar no botão de pesquisa. Certifique-se de que isso está acima do novo gancho useLazyQueryWithPagination:

 const query = `
 query POAPEventAttendeesAndSocialProfiles($eventId: String!) {
   Poaps(input: {filter: {eventId: {_eq: $eventId}}, blockchain: ALL, limit: 200}) {
     Poap {
       owner {
         identity
         socials {
           profileName
           userHomeURL
           profileTokenUri
         }
       }
     }
   }
 }
Enter fullscreen mode Exit fullscreen mode

Estamos aproveitando o valor do estado variables que está sendo passado para nossa função fetch, e esta consulta será atualizada automaticamente para passar o eventId quando a solicitação de rede for feita.

Agora, só precisamos acionar a chamada fetch e retornar os resultados. Os resultados estão contidos na variável data do nosso gancho Airstack.

Vamos atualizar o componente TableView em nosso arquivo App.jsx para passar a variável fetch para o componente.

TableView eventId={variables.eventId} results={data?.Poaps?.Poap || []} searchAttendees={() => fetch()} />
Enter fullscreen mode Exit fullscreen mode

Observe que com a propriedade results, estamos passando o array de resultados que está aninhado na resposta da API. Você pode ver o formato na documentação da Airstack.

E é isso! Na verdade, temos tudo o que precisamos para buscar nossos dados. Vamos tentar. Abra a guia de rede nas ferramentas de desenvolvimento do seu navegador, em seguida, insira um ID de evento. Clique no botão "Build Now" (Construir agora) e verifique o resultado da chamada de rede.

Se preferir, você pode adicionar um console.log no arquivo App.jsx em qualquer lugar, como este:

console.log(data)
Enter fullscreen mode Exit fullscreen mode

De qualquer maneira, você verá que agora estamos buscando dados. Vamos renderizá-los na tela!

Abra novamente o arquivo TableView.jsx e vamos criar uma tabela. Na função renderPopulated, adicione o seguinte:

const renderPopulated = () => {
 return (
   <div>
     <button  style={{marginBottom: 12, marginLeft: 10}} onClick={props.searchAttendees} className="btn">Reload table</button>
     <table>         
       <thead>
         <tr>
           <th scope="col">User address</th>
           <th scope="col" rowspan="2">
             Social Usernames
           </th>
         </tr>
       </thead>
       <tbody>
         {props.results.map((r) => {
           return (
             <tr key={r.owner.indentity}>
               <td>
                 {r.owner.identity}
               </td>
               <td>{r.owner.socials && r.owner.socials.map(s => {
                 return (
                   <><span title={s.profileName}>{s.profileName.split(0, 20)}</span><br/></>)
               })}</td>                 
             </tr>
           );
         })}
       </tbody>
     </table>
   </div>
 );
};
Enter fullscreen mode Exit fullscreen mode

Aqui estamos mapeando os resultados de nossa lista de participantes e exibindo o endereço da carteira e quaisquer perfis sociais que eles possam ter.

Vamos ver como isso fica quando tudo estiver pronto. Mas primeiro, vamos adicionar um pouco de CSS. Abra o seu arquivo index.css e adicione o seguinte:

table {
 border-collapse:collapse;
 border:.5px solid #E8F1F2;
 text-align:left;
 margin: 0 auto;
}

table > caption {
 text-transform:uppercase;
 font-weight:bolder;
}
th {
 background-color: #172A3A;
 color:#fff;
 padding:8px;
 text-align:center;
}
tr:nth-child(even){
 background-color:#E5EFF0;
}
td[data-style="bold"]{
 font-weight:bold;
 color:#11202C;
 border-right:1px solid #C5C7D3;
}
td {
 padding: 12px;
 text-align:center;
 color:#11202C;
 border-bottom: 1px solid #C5C7D3;
}
tfoot {
 background-color:#172A3A;
 text-align:center;
 color:#A4C8CB;
}
tbody > tr:hover {
 background-color:#8DE2E2;
}
Enter fullscreen mode Exit fullscreen mode

Isso deve ser suficiente. Acredito que temos material para a grande revelação!

O Aplicativo em Ação

Recarregue seu aplicativo e insira um ID de evento, e você verá algo parecido com isto:

Isso é bastante poderoso quando você pensa nas implicações. Você pode usar esses resultados para seguir esses participantes nas plataformas sociais Web3 das quais eles fazem parte. Você pode enviar coisas para eles. Você pode iniciar seus próprios eventos. Você pode fazer tantas coisas com um aplicativo tão simples.

Com a API da Airstack, você pode ir muito mais longe. Imagens de perfil, imagens de POAP, links para outros tokens NFT que essas pessoas possuem e muito mais.

Conclusão

Os POAPs têm sido uma ótima ferramenta para comemorar eventos que as pessoas participaram. Mas há muito mais oportunidades para networking e prospecção. Usando o assistente de IA da Airstack e sua API, podemos construir uma ferramenta que ajuda você a ver e se conectar com participantes de qualquer evento, simplesmente verificando quem possui os POAPs do evento.

Se você está pronto para criar ferramentas de prospecção de eventos mais poderosas e aproveitar os POAPs de uma maneira totalmente nova, espero que este tutorial tenha sido útil. Se você criar algo depois de ler isso, não deixe de compartilhá-lo.

Como você pode levar este aplicativo adiante? Existem várias coisas que você pode fazer, incluindo, mas não se limitando a:

  • Adicionar paginação (lembre-se, já temos suporte para isso com o gancho useLazyQueryWithPagination que usamos).
  • Adicionar uma opção de conexão de carteira e encontrar automaticamente conexões entre o endereço autenticado e os POAPs na carteira conectada.
  • Mostrar imagens de perfil e POAPs.
  • Adicionar uma opção de exportação em CSV.
  • E muito mais!

Se você estiver interessado no código completo deste projeto, ele pode ser encontrado aqui.


Artigo escrito por Justin Hunter. Traduzido por Marcelo Panegali.

Top comments (0)