Data

29 out, 2024

Como criar um painel de dados em tempo real

Publicidade

Neste tutorial, vamos guiá-lo na criação de um painel de dados em tempo real usando o SuperViz, um SDK poderoso para comunicação em tempo real e sincronização de dados. Painéis em tempo real são ferramentas essenciais para monitorar e analisar dados à medida que são gerados, permitindo que os usuários tomem decisões rápidas e informadas com base nas informações mais recentes.

Painel de dados em tempo real

Usaremos dados do mercado de ações do Yahoo Finance como nosso exemplo de fonte de dados. No entanto, os princípios e técnicas que você aprenderá podem ser aplicados a qualquer fonte de dados que você tenha acesso no servidor. Seja para dados financeiros, atualizações climáticas ou atividade de usuários, este tutorial lhe dará as habilidades para criar um painel dinâmico que atualiza em tempo real.

Ao final deste tutorial, você terá um painel totalmente funcional em tempo real que pode ser personalizado e expandido para atender às suas necessidades específicas. Vamos começar!

Pré-requisitos

Para seguir este tutorial, você precisará de uma conta SuperViz e de um token de desenvolvedor. Se já tiver uma conta e um token de desenvolvedor, pode passar para o próximo passo.

Criar uma conta

Para criar uma conta, acesse https://dashboard.superviz.com/register e crie uma conta usando o Google ou um e-mail/senha. É importante observar que, ao usar e-mail/senha, você receberá um link de confirmação que precisará clicar para verificar sua conta.

Obtendo um Token de Desenvolvedor

Para usar o SDK, você precisará fornecer um token de desenvolvedor, essencial para associar as solicitações do SDK à sua conta. Você pode obter tokens de desenvolvimento e de produção do SuperViz no painel de dados.

Copie e salve o token de desenvolvedor, pois você precisará dele nos próximos passos deste tutorial.

Passo 1: Configurando o Servidor com Express.js

O servidor é responsável por buscar dados de ações do Yahoo Finance e transmitir atualizações para o frontend usando o SuperViz.

1. Criar um Novo Projeto e Instalar Dependências

Primeiro, configure um novo projeto Node.js e instale os pacotes necessários para o servidor.

mkdir realtime-dashboard-server

cd realtime-dashboard-server

npm init -y

npm install express body-parser dotenv cors yahoo-finance2 node-fetch

Explicação:

  • express: Um framework de aplicação web para configurar o servidor.
  • body-parser: Middleware para analisar corpos de requisições JSON.
  • dotenv: Carrega variáveis de ambiente a partir de um arquivo .env.
  • cors: Middleware para habilitar o Compartilhamento de Recursos de Origem Cruzada.
  • yahoo-finance2: Biblioteca para buscar dados de ações do Yahoo Finance.
  • node-fetch: API Fetch para fazer requisições HTTP

2. Configurar o Servidor Express

Crie um arquivo chamado server.js e configure o servidor.

// server.js
import express from "express";
import bodyParser from "body-parser";
import cors from "cors";
import dotenv from "dotenv";
import yahooFinance from "yahoo-finance2";

dotenv.config();

const app = express();
app.use(bodyParser.json());
app.use(cors());

const subscriptions = [];

Explicação:

  • Express App: Crie uma aplicação Express para lidar com as requisições.
  • Middlewares: Use bodyParser para análise de JSON e cors para lidar com requisições de origem cruzada.
  • Assinaturas: Um array para armazenar assinaturas de ações ativas, identificadas por IDs de sala.

3. Inscrever-se em Atualizações de Ações

Defina um endpoint para se inscrever em atualizações de ações.

app.get('/subscribe', async (req, res) => {
  console.log(req.query)

  if(!req.query.symbol) {
    return res.status(400).json({ error: 'Missing symbol' })
  }

  try {
    const response = await yahooFinance.quote(req.query.symbol)

    if(!response) {
      return res.status(404).json({ error: 'Symbol not found' })
    }

    subscriptions.push({
      roomId: req.query.roomId,
      symbol: req.query.symbol
    })

    return res.json({
      symbol: response.symbol,
      name: response.shortName,
      price: response.regularMarketPrice,
      change: response.regularMarketChange,
      changePercent: response.regularMarketChangePercent,
      high: response.regularMarketDayHigh,
      low: response.regularMarketDayLow,
      updatedAt: new Date().toISOString(),
    })
  } catch (error) {
    return res.status(500).json({ error: error.toString() })
  }
})

Explicação:

  • Endpoint de Inscrição: Um endpoint /subscribe permite que os clientes se inscrevam em atualizações de ações fornecendo um symbol e roomId.
  • API Yahoo Finance: O método yahooFinance.quote busca os dados da ação usando o símbolo fornecido.
  • Response Data: Se a ação for encontrada, adiciona uma assinatura e retorna dados detalhados da ação.

4. Cancelar Inscrição em Atualizações de Ações

Forneça uma maneira de cancelar a inscrição em atualizações de ações.

app.get('/unsubscribe', (req, res) => {
  if(!req.query.roomId) {
    return res.status(400).json({ error: 'Missing roomId' })
  }

  if(!req.query.symbol) {
    return res.status(400).json({ error: 'Missing symbol' })
  }

  const index = subscriptions.findIndex(subscription => subscription.roomId === req.query.roomId && subscription.symbol === req.query.symbol)
  if(index === -1) {
    return res.status(404).json({ error: 'Subscription not found' })
  }

  subscriptions.splice(index, 1)
  return res.json({ message: 'Subscription removed' })
})

Explicação:

  • Endpoint de Cancelamento: Um endpoint /unsubscribe permite que os clientes removam assinaturas pelo roomId.
  • Encontrar Assinatura: Localiza a assinatura usando o roomId e a remove se encontrada.

5. Enviar Atualizações de Ações para o SuperViz

Use um intervalo de tempo para buscar atualizações de ações e transmiti-las usando a API do SuperViz.

const interval = setInterval(async () => {
  for(const subscription of subscriptions) {
    try {
      const stock = await yahooFinance.quote(subscription.symbol)

      if(!stock) return

      const data = {
        symbol: stock.symbol,
        name: stock.shortName,
        price: stock.regularMarketPrice,
        change: stock.regularMarketChange,
        changePercent: stock.regularMarketChangePercent,
        high: stock.regularMarketDayHigh,
        low: stock.regularMarketDayLow,
        updatedAt: new Date().toISOString(),
      }
      const channelId = 'stock-price'

      const response = await fetch(`https://api.superviz.com/realtime/${channelId}/publish`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          secret: process.env.VITE_SUPERVIZ_SECRET_KEY,
          client_id: process.env.VITE_SUPERVIZ_CLIENT_ID,
        },
        body: JSON.stringify({
          name: 'stock-update',
          data,
        })
      })

      console.log(`Sending data to ${channelId}, stock: ${stock.symbol}`, response.status)
    } catch (error) {
      console.error(error)
    }
  }
}, 2000)

 

Explicação:

  • Intervalo: A cada 2 segundos, busca atualizações de ações para todas as assinaturas.
  • API SuperViz: Envia dados de ações para a API em tempo real do SuperViz, usando roomId e channelId para direcionar clientes específicos.

6. Iniciar o Servidor

Inicie o servidor para escutar requisições.

app.listen(3000, () => {
  console.log("Server is running on <http://localhost:3000>");
});

Explicação:

  • Server Listening: O servidor escuta na porta 3000 e registra uma mensagem de confirmação quando está em execução.

Passo 2: Configurando o Frontend com React

O frontend usa React para exibir atualizações de ações em tempo real conectando-se ao SuperViz Real-time.

1. Criar um Novo Projeto React

Inicialize uma nova aplicação React usando o Create React App com TypeScript.

npm create vite@latest
cd realtime-dashboard-frontend

2. Instalar o SDK do SuperViz

Adicione o SuperViz e outros pacotes necessários.

npm install @superviz/realtime luxon uuid

Explicação:

  • @superviz/realtime: Biblioteca SuperViz Real-Time para integrar sincronização em tempo real em sua aplicação.
  • luxon: Biblioteca DateTime para formatação de datas.
  • uuid: Biblioteca para gerar identificadores únicos.

3. Configurar o Tailwind

Neste tutorial, usaremos o framework Tailwind CSS. Primeiro, instale o pacote do Tailwind.

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Em seguida, precisamos configurar o caminho do template. Abra tailwind.config.js na raiz do projeto e insira o seguinte código:

/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Depois, precisamos adicionar as diretivas do Tailwind ao arquivo CSS global. (src/index.css)

@tailwind base;
@tailwind components;
@tailwind utilities;

4. Configurar Variáveis de Ambiente

Crie um arquivo .env no diretório frontend e adicione a chave da API do SuperViz.

VITE_SUPERVIZ_API_KEY=YOUR_SUPERVIZ_API_KEY
VITE_SUPERVIZ_CLIENT_ID=YOUR_SUPERVIZ_CLIENT_ID
VITE_SUPERVIZ_SECRET_KEY=YOUR_SUPERVIZ_SECRET_KEY

Explicação:

  • Variáveis de Ambiente: Armazena a chave da API de forma segura usando .env e a acessa através de import.meta.env.

5. Definir Tipos Comuns

Crie um diretório src/common e adicione um arquivo types.ts para definir os tipos usados em toda a aplicação.

// src/common/types.ts
export type Stock = {
  symbol: string;
  name: string;
  price: number;
  change: number;
  changePercent: number;
  high: number;
  low: number;
  updatedAt: string;
};

Explicação:

  • Tipo Stock: Define a estrutura para dados de ações, garantindo uso consistente em toda a aplicação.

6. Implementar o Componente Principal da Aplicação

Abra src/App.tsx e configure o componente principal para lidar com interações do usuário e exibir dados de ações.

import { v4 as generateId } from "uuid";
import { useCallback, useEffect, useState } from "react";
import { Realtime } from "@superviz/realtime/client";
import { Stock } from "./common/types";
import { StockPrice } from "./components/stock-price";

const apiKey = import.meta.env.VITE_SUPERVIZ_API_KEY as string;

export default function App() {
  const [stock, setStock] = useState('AAPL')
  const [stockList, setStockList] = useState<Stock[]>([])

  const subscribeToStock = useCallback(async () => {
    const params = {
      roomId: ROOM_ID,
      symbol: stock,
    }

    const url = new URL('http://localhost:3000/subscribe')
    url.search = new URLSearchParams(params).toString()

    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      }
    })

    const data = await response.json()

    if(!data || stockList.includes(data.symbol)) return

    setStockList((prev) => [...prev, data])
  }, [stock, stockList])
}

Explicação:

  • Gerenciamento de Estado: stock contém o símbolo de entrada, enquanto stockList mantém a lista de ações assinadas.
  • Função de Inscrição: Constrói uma URL com parâmetros de consulta e busca dados de ações do servidor. Atualiza o estado se a ação não estiver já inscrita.

7. Inicializar o SuperViz para Sincronização de Dados em Tempo Real

Adicione a lógica de inicialização para conectar-se ao SuperViz.

const initialize = useCallback(async () => {
  const realtime = new Realtime(apiKey, {
    participant: {
      id: generateId(),
      name: "participant-name",
    },
  });

  const channel = await realtime.connect("stock-price");
  channel.subscribe("stock-update", (data) => {
    console.log("New channel event", data);

    if (typeof data === "string") return;

    setStockList((prev) => {
      return prev.map((stock) => {
        const newStock = data.data as Stock;

        if (stock.symbol === newStock?.symbol) {
          return newStock;
        }

        return stock;
      });
    });
  });
}, []);

Explicação:

  • Inicialização do SuperViz: Conecta-se à sala do SuperViz usando uma chave API e detalhes da sala. Adiciona o componente Realtime para lidar com eventos em tempo real.
  • Assinatura em Tempo Real: Assina stock-update de ações, atualizando a lista de ações com novos dados.

8. Renderizar os Componentes da UI

Finalize o componente App renderizando a interface do usuário.

return (
  <div className="w-full h-full bg-gray-200 flex items-center justify-center flex-col">
    <header className="w-full p-5 bg-purple-400 flex items-center justify-between">
      <div>
        <h1 className="text-white text-2xl font-bold">
          Realtime Data Dashboard
        </h1>
      </div>
      <div>
        <input
          type="text"
          value={stock}
          onChange={(e) => setStock(e.target.value)}
          className="p-2 border border-gray-400 rounded-md focus:outline-none focus:border-purple-400"
        />
        <button
          onClick={subscribeToStock}
          className="p-2 bg-purple-500 text-white rounded-md ml-2 focus:outline-none"
        >
          Subscribe
        </button>
      </div>
    </header>
    <main className="flex-1 p-20 flex w-full gap-2">
      {stockList.map((stock) => (
        <StockPrice key={stock.symbol} stock={stock} />
      ))}
    </main>
  </div>
);

Explicação:

  • Estrutura da UI: A UI contém um campo de entrada para símbolos de ações e um botão de inscrição. O componente StockPrice é usado para exibir os detalhes de cada ação.
  • Atualizações de Estado: O evento onChange atualiza a entrada de ações, enquanto clicar no botão aciona a lógica de inscrição.

9. Implementar o Componente StockPrice

Crie um diretório src/components e adicione um arquivo stock-price.tsx para definir como cada ação é exibida.

// src/components/stock-price.tsx
import { Stock } from "../common/types";
import { DateTime } from "luxon";

type Props = {
  stock: Stock;
};

export function StockPrice({ stock }: Props) {
  const formatPrice = (price: number) => {
    return new Intl.NumberFormat("en-US", {
      style: "currency",
      currency: "USD",
    }).format(price);
  };

  const formatDateTime = (date: string) => {
    return DateTime.fromISO(date).toFormat("DD HH:mm:ss");
  };

  return (
    <div className="p-6 border border-solid border-gray-300 bg-white min-w-40 rounded-xl h-fit shadow-md">
      <h1>{stock.name}</h1>
      <p>{stock.symbol}</p>
      <p>Current Price: {formatPrice(stock.price)}</p>
      <p>Lower Price: {formatPrice(stock.low)}</p>
      <p>Higher Price: {formatPrice(stock.high)}</p>
      <p>Updated At: {formatDateTime(stock.updatedAt)}</p>
    </div>
  );
}

Explicação:

  • Componente StockPrice: Exibe informações detalhadas da ação, incluindo o nome, símbolo, preço atual, preços mínimo/máximo e timestamp de atualização.
  • Funções de Formatação: formatPrice e formatDateTime garantem que os preços e datas sejam exibidos de maneira amigável ao usuário.

Passo 3: Executando a Aplicação

Para iniciar a aplicação, execute este comando no terminal:

npm run dev

Esse comando iniciará tanto o servidor quanto a aplicação frontend.

Você pode acessar a aplicação frontend em http://localhost:5173 e o servidor em http://localhost:3000.

Resumo

Neste tutorial, construímos um painel de ações em tempo real usando SuperViz, Express.js e React. O servidor busca dados de ações da Yahoo Finance e envia atualizações para clientes inscritos usando a API em tempo real do SuperViz. O frontend se inscreve para receber atualizações de ações, exibindo-as em uma interface de usuário responsiva. Seguindo esses passos, você pode personalizar o painel de dados para acompanhar diferentes ações, adicionar mais recursos e implantá-lo em um ambiente de produção.

Sinta-se à vontade para consultar o código completo no repositório do GitHub para mais detalhes.

e assista ao vídeo a seguir: