Extrator de Dados - Fetch API Pontomais

by Daniel Gualberto

HTML

<script src="https://code.jquery.com/jquery-3.4.1.slim.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@latest/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@latest/dist/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<div class="container mt-4">
  <div class="row">
    <div class="col-12">
      <h2 class="mb-4">
        <i class="fas fa-code"></i> Extrator de Dados - Fetch API Pontomais
      </h2>

      <div class="card shadow">
        <div class="card-header bg-primary text-white">
          <div class="d-flex justify-content-between align-items-center">
            <h5 class="mb-0">
              <i class="fas fa-paste"></i> Cole seu código fetch abaixo
            </h5>
            <button
              id="pasteBtn"
              class="btn btn-sm btn-light"
              title="Colar da área de transferência"
            >
              <i class="fas fa-paste"></i>
            </button>
          </div>
        </div>
        <div class="card-body">
          <div class="form-group">
            <textarea
              id="fetchInput"
              class="form-control font-monospace"
              rows="10"
              placeholder="Cole aqui o código fetch(...)"
            ></textarea>
          </div>
          <button id="extractBtn" class="btn btn-primary btn-lg mt-3">
            <i class="fas fa-search"></i> Extrair Dados
          </button>
        </div>
      </div>

      <div id="resultContainer" class="mt-4" style="display: none">
        <div class="card shadow">
          <div class="card-header bg-success text-white">
            <h5 class="mb-0">
              <i class="fas fa-circle-check"></i> Dados Extraídos
            </h5>
          </div>
          <div class="card-body">
            <div class="alert alert-info">
          ...

CSS

body {
  background-color: #f8f9fa;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.card {
  border: none;
  border-radius: 10px;
  transition: transform 0.2s;
}

.card:hover {
  transform: translateY(-2px);
}

#fetchInput {
  font-size: 0.85rem;
  border: 2px solid #e9ecef;
  transition: border-color 0.3s;
}

#fetchInput:focus {
  border-color: #0d6efd;
  box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
}

#resultCode {
  font-size: 0.9rem;
  line-height: 1.6;
  overflow-x: auto;
}

.json-value {
  cursor: pointer;
  color: #a8ff60;
  position: relative;
  padding: 2px 4px;
  border-radius: 3px;
  transition: all 0.2s;
}

.json-value:hover {
  background-color: rgba(168, 255, 96, 0.2);
  box-shadow: 0 0 0 2px rgba(168, 255, 96, 0.3);
}

.json-value:active {
  transform: scale(0.95);
}

.json-key {
  color: #f92672;
  font-weight: bold;
}

.json-string {
  color: #66d9ef;
}

.btn-primary {
  background-color: #0d6efd;
  border: none;
  padding: 10px 30px;
  font-weight: 500;
  transition: all 0.3s;
}

.btn-primary:hover {
  background-color: #0b5ed7;
  transform: translateY(-2px);
  box-shadow: 0 4px 10px rgba(13, 110, 253, 0.3);
}

#pasteBtn {
  padding: 5px 12px;
  transition: all 0.2s;
}

#pasteBtn:hover {
  transform: scale(1.1);
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}

#pasteBtn:active {
  transform: scale(0.95);
}

.toast {
  min-width: 350px;
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

#resultContainer.show {
  animation: fadeInUp 0.5s ease-out;
}

JavaScript

// Função para extrair dados do fetch
function extractData() {
  const fetchCode = document.getElementById("fetchInput").value.trim()

  if (!fetchCode) {
    alert("Por favor, cole o código fetch no campo de texto.")
    return
  }

  try {
    // Extrair o objeto de configuração do fetch
    const fetchMatch = fetchCode.match(
      /fetch\s*\(\s*["']([^"']+)["']\s*,\s*(\{[\s\S]*\})\s*\)/,
    )

    if (!fetchMatch) {
      throw new Error("Formato de fetch não reconhecido")
    }

    // Avaliar o objeto de configuração
    const configStr = fetchMatch[2]
    const config = eval("(" + configStr + ")")

    // Extrair dados do headers
    const headers = config.headers || {}

    // Converter o body string em objeto
    const bodyData = config.body ? JSON.parse(config.body) : {}

    // Criar objeto com os dados extraídos
    const extractedData = {
      uid: headers["uid"] || "Não encontrado",
      uuid: headers["uuid"] || "Não encontrado",
      address: bodyData.time_card?.address || "Não encontrado",
      clientId: headers["client"] || "Não encontrado",
      latitude: bodyData.time_card?.latitude || "Não encontrado",
      longitude: bodyData.time_card?.longitude || "Não encontrado",
      employeeId: bodyData.employee?.id || "Não encontrado",
      accessToken: headers["access-token"] || "Não encontrado",
      referenceId: bodyData.time_card?.reference_id || "Não encontrado",
    }

    // Exibir resultados
    displayResults(extractedData)
  } catch (error) {
    console.error("Erro ao processar:", error)
    alert(
      "Erro ao processar o código fetch. Verifique se o formato está correto.",
    )
  }
}

// Função para exibir os resultados formatados
function displayResults(data) {
  const resultContainer = document.getElementById("resultContainer")
  const resultCode = document.getElementById("resultCode")

  // Formatar JSON com HTML para permitir cliques
  let formattedJson = "{\n"
 ...