Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
# wms
WMS for small business

## Extensão Edge (MVP) - Autofill por PDF

Foi adicionada uma extensão em `edge-extension/` para Microsoft Edge que:

1. Permite subir um PDF.
2. Tenta extrair os campos de **Dados do Transporte** via regex.
3. Preenche automaticamente o formulário na aba ativa.

### Campos mapeados
- Transportadora
- Nome do Motorista
- Placa
- Placa 2
- Placa 3
- Tipo de Veículo (select)
- Telefone
- Nº da CNH
- CPF

### Como instalar no Edge
1. Abra `edge://extensions`.
2. Ative **Modo de desenvolvedor**.
3. Clique em **Carregar sem compactação**.
4. Selecione a pasta `edge-extension` deste repositório.

### Como usar
1. Abra a página com o formulário de transporte.
2. Clique no ícone da extensão.
3. Selecione o PDF e clique em **Extrair e preencher**.
4. Revise os campos antes de salvar.

### Observações importantes
- Este MVP funciona melhor com PDF baseado em texto (não escaneado).
- A extração usa heurística; dependendo do layout do PDF, regex podem precisar de ajuste.
- Para maior precisão em produção, o ideal é usar `pdfjs-dist` para extração de texto por página.
12 changes: 12 additions & 0 deletions edge-extension/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"manifest_version": 3,
"name": "WMS PDF Autofill",
"description": "Extrai dados de transporte de um PDF e preenche automaticamente o formulário no site WMS.",
"version": "0.1.0",
"permissions": ["activeTab", "scripting"],
"action": {
"default_title": "WMS PDF Autofill",
"default_popup": "popup.html"
},
"host_permissions": ["<all_urls>"]
}
21 changes: 21 additions & 0 deletions edge-extension/popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!doctype html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<title>WMS PDF Autofill</title>
<style>
body { font-family: Arial, sans-serif; margin: 12px; width: 320px; }
h1 { font-size: 16px; margin: 0 0 10px; }
input, button { width: 100%; margin: 8px 0; }
.status { font-size: 12px; color: #333; white-space: pre-line; }
button { padding: 8px; border: 0; background: #1976d2; color: white; border-radius: 6px; cursor: pointer; }
</style>
</head>
<body>
<h1>Dados do Transporte via PDF</h1>
<input id="pdfInput" type="file" accept="application/pdf" />
<button id="processBtn">Extrair e preencher</button>
<div id="status" class="status">Selecione um PDF para começar.</div>
<script src="popup.js"></script>
</body>
</html>
109 changes: 109 additions & 0 deletions edge-extension/popup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
const statusEl = document.getElementById('status');
const fileInput = document.getElementById('pdfInput');

document.getElementById('processBtn').addEventListener('click', async () => {
const file = fileInput.files?.[0];
if (!file) {
statusEl.textContent = 'Selecione um arquivo PDF.';
return;
}

statusEl.textContent = 'Lendo PDF...';
const buffer = await file.arrayBuffer();

// MVP: extração simples para PDFs baseados em texto.
const rawText = new TextDecoder('latin1').decode(buffer);
const data = extractTransportData(rawText);

statusEl.textContent = 'Preenchendo formulário na aba ativa...';

const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab?.id) {
statusEl.textContent = 'Não foi possível detectar aba ativa.';
return;
}

await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: fillFormFields,
args: [data]
});

statusEl.textContent = 'Concluído. Revise os campos preenchidos.';
});

function extractByRegex(text, regex) {
const match = text.match(regex);
return match?.[1]?.trim() || '';
}

function extractTransportData(text) {
return {
transportadora: extractByRegex(text, /Transportadora\s*:?\s*([^\n\r]+)/i),
motorista: extractByRegex(text, /Nome\s+do\s+Motorista\s*:?\s*([^\n\r]+)/i),
placa: extractByRegex(text, /Placa\s*:?\s*([A-Z0-9-]{7,10})/i),
placa2: extractByRegex(text, /Placa\s*2\s*:?\s*([A-Z0-9-]{7,10})/i),
placa3: extractByRegex(text, /Placa\s*3\s*:?\s*([A-Z0-9-]{7,10})/i),
tipoVeiculo: extractByRegex(text, /Tipo\s+de\s+Ve[ií]culo\s*:?\s*([^\n\r]+)/i),
telefone: extractByRegex(text, /Telefone\s*:?\s*([^\n\r]+)/i),
cnh: extractByRegex(text, /N[º°o]?\s*da\s*CNH\s*:?\s*([^\n\r]+)/i),
cpf: extractByRegex(text, /CPF\s*:?\s*([0-9.\/-]+)/i)
};
}

function fillFormFields(data) {
const mapping = [
{ keys: ['transportadora'], labels: ['Transportadora'] },
{ keys: ['motorista'], labels: ['Nome do Motorista'] },
{ keys: ['placa'], labels: ['Placa'] },
{ keys: ['placa2'], labels: ['Placa 2'] },
{ keys: ['placa3'], labels: ['Placa 3'] },
{ keys: ['telefone'], labels: ['Telefone'] },
{ keys: ['cnh'], labels: ['CNH'] },
{ keys: ['cpf'], labels: ['CPF'] }
];

function findInputByLabel(labelText) {
const labels = Array.from(document.querySelectorAll('label'));
const label = labels.find((l) => l.textContent?.trim().toLowerCase().includes(labelText.toLowerCase()));
if (label?.htmlFor) {
return document.getElementById(label.htmlFor);
}
return label?.querySelector('input,select,textarea') || null;
}

mapping.forEach(({ keys, labels }) => {
const value = data[keys[0]];
if (!value) return;

for (const labelName of labels) {
const el = findInputByLabel(labelName);
if (el) {
el.value = value;
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
break;
}
}
});

// Tipo de veículo (select)
if (data.tipoVeiculo) {
const selects = Array.from(document.querySelectorAll('select'));
const select = selects.find((s) => {
const idMatch = (s.id || '').toLowerCase().includes('veiculo');
const nameMatch = (s.name || '').toLowerCase().includes('veiculo');
return idMatch || nameMatch;
});

if (select) {
const option = Array.from(select.options).find((opt) =>
opt.textContent.toLowerCase().includes(data.tipoVeiculo.toLowerCase())
);
if (option) {
select.value = option.value;
select.dispatchEvent(new Event('change', { bubbles: true }));
}
}
}
}