# 📦 @jackiemacklein/nettz-utils

Biblioteca com serviços utilitários para aplicações Node.js/TypeScript, incluindo:

- 📸 Processamento de Imagens com [sharp](https://www.npmjs.com/package/sharp) _(Backend)_
- 📧 Envio de E-mails via SMTP com [nodemailer](https://www.npmjs.com/package/nodemailer) _(Backend)_
- 🏷️ Análise de Códigos de Barras (Boletos e Tributos) _(Web + Backend)_
- 🔢 Utilitários Numéricos (Conversão de valores monetários) _(Web + Backend)_
- 🎨 **ImageUtils** - Análise de brilho de imagens _(Web)_
- 📊 **OnTable** - Componente de tabela avançada com React _(Web)_
- 🛠️ **Utils** - Utilitários para banco de dados _(Backend)_

---

## 📦 Instalação

```bash
npm install @jackiemacklein/nettz-utils
# ou
yarn add @jackiemacklein/nettz-utils
```

---

## 🌐 Compatibilidade

### 🔧 Backend (Node.js)

```ts
// Importação completa (Node.js)
import nettzUtils from "@jackiemacklein/nettz-utils";

// Ou importação específica para backend
import {
  Image,
  Mail,
  Number,
  Utils,
} from "@jackiemacklein/nettz-utils/backend";

// Utilitários de banco de dados
import { buildWhereConditions } from "@jackiemacklein/nettz-utils/Utils";
```

### 🌍 Web (Browser + Node.js)

```ts
// Importação específica para web
import {
  Barcode,
  Number,
  OnTable,
  ImageUtils,
} from "@jackiemacklein/nettz-utils/web";

// Componente OnTable
import OnTable from "@jackiemacklein/nettz-utils/OnTable";

// Ou importação individual
import { analyzeBarcode } from "@jackiemacklein/nettz-utils/web";
import { toInteger, fromInteger } from "@jackiemacklein/nettz-utils/web";
import { detectImageBrightness } from "@jackiemacklein/nettz-utils/web";
```

> 📖 **Para mais detalhes sobre compatibilidade, consulte [COMPATIBILITY.md](./COMPATIBILITY.md)**

---

## 📊 OnTable _(Web)_

Componente React avançado para exibição de tabelas com funcionalidades completas de seleção, ordenação, filtragem, paginação e personalização.

### ✨ Exemplos de uso

```tsx
import OnTable from "@jackiemacklein/nettz-utils/OnTable";

const columns = [
  { key: "id", label: "ID", type: "number", align: "center", sortable: true },
  {
    key: "name",
    label: "Nome",
    type: "string",
    align: "left",
    filterable: true,
  },
  { key: "email", label: "E-mail", type: "string", align: "left" },
  { key: "status", label: "Status", type: "string", align: "center" },
  { key: "createdAt", label: "Data", type: "date", align: "center" },
];

const data = [
  {
    id: 1,
    name: "João Silva",
    email: "joao@exemplo.com",
    status: "Ativo",
    createdAt: "2024-01-15",
  },
  {
    id: 2,
    name: "Maria Santos",
    email: "maria@exemplo.com",
    status: "Inativo",
    createdAt: "2024-01-10",
  },
];

function MyTable() {
  return (
    <OnTable
      data={data}
      columns={columns}
      selectable={true}
      onSelectionChange={(selected) => console.log(selected)}
      onSort={(sortConfig) => console.log(sortConfig)}
      onFilter={(filters) => console.log(filters)}
      currentPage={1}
      totalPages={5}
      onPageChange={(page) => console.log(page)}
    />
  );
}
```

### 🔧 Funcionalidades disponíveis

| Funcionalidade  | Descrição                               |
| --------------- | --------------------------------------- |
| **Seleção**     | Seleção individual e múltipla de linhas |
| **Ordenação**   | Ordenação por múltiplas colunas         |
| **Filtragem**   | Filtros avançados por coluna            |
| **Paginação**   | Paginação com navegação intuitiva       |
| **Colunas**     | Mostrar/ocultar colunas dinamicamente   |
| **Drag & Drop** | Reordenação de colunas por arraste      |
| **Responsivo**  | Design adaptável para mobile            |
| **Loading**     | Estado de carregamento                  |
| **Ações**       | Ações personalizadas por linha/célula   |

### 📋 Propriedades principais

```tsx
interface TableProps<T> {
  data: T[]; // Dados da tabela
  columns: Column<T>[]; // Configuração das colunas
  selectable?: boolean; // Habilita seleção
  onSelectionChange?: (items: T[]) => void;
  onSort?: (config: SortConfig[]) => void;
  onFilter?: (filters: Record<string, string>) => void;
  currentPage?: number; // Página atual
  totalPages?: number; // Total de páginas
  onPageChange?: (page: number) => void;
  loading?: boolean; // Estado de carregamento
  customButtons?: React.ReactNode; // Botões personalizados
}
```

### 🎨 Componentes incluídos

- **Button**: Botões com variantes e tamanhos
- **Modal**: Modal responsivo para filtros
- **Form**: Formulários com validação
- **Pagination**: Paginação avançada
- **Popover**: Popover para seleção de colunas

---

## 🛠️ Utils _(Backend)_

Utilitários para construção de consultas SQL e filtros de banco de dados.

### ✨ Exemplos de uso

```ts
import { buildWhereConditions } from "@jackiemacklein/nettz-utils/Utils";

// Filtros simples
const filters = {
  name: "João Silva",
  age: { value: 18, operator: ">" },
  status: { value: ["ACTIVE", "PENDING"], operator: "in" },
};

const whereConditions = buildWhereConditions(filters, {
  mainTable: "users",
  useUnaccent: true,
});

console.log(whereConditions);
// [
//   "unaccent(users.name) ilike unaccent('%João Silva%')",
//   "users.age > 18",
//   "users.status = ANY(ARRAY[ACTIVE,PENDING])"
// ]
```

### 🔧 Operadores suportados

| Operador  | Descrição                 | Exemplo                                     |
| --------- | ------------------------- | ------------------------------------------- |
| `=`       | Igual                     | `{ value: "ativo", operator: "=" }`         |
| `!=`      | Diferente                 | `{ value: "inativo", operator: "!=" }`      |
| `>`       | Maior que                 | `{ value: 18, operator: ">" }`              |
| `>=`      | Maior ou igual            | `{ value: 18, operator: ">=" }`             |
| `<`       | Menor que                 | `{ value: 65, operator: "<" }`              |
| `<=`      | Menor ou igual            | `{ value: 65, operator: "<=" }`             |
| `like`    | Contém (case sensitive)   | `{ value: "silva", operator: "like" }`      |
| `ilike`   | Contém (case insensitive) | `{ value: "silva", operator: "ilike" }`     |
| `in`      | Está em lista             | `{ value: ["A", "B"], operator: "in" }`     |
| `not in`  | Não está em lista         | `{ value: ["X", "Y"], operator: "not in" }` |
| `between` | Entre valores             | `{ value: [10, 20], operator: "between" }`  |

### 📋 Opções de configuração

```ts
interface WhereBuilderOptions {
  mainTable?: string; // Tabela principal
  useUnaccent?: boolean; // Usar função unaccent
  customConditions?: string[]; // Condições customizadas
}
```

---

## 📸 ImageService _(Backend)_

Classe utilitária para manipulação de imagens usando `sharp`.

### ✨ Exemplos de uso

```ts
import ImageService from "@jackiemacklein/nettz-utils/backend";
import fs from "fs";

const imageService = new ImageService();
const buffer = fs.readFileSync("input.jpg");

(async () => {
  const resized = await imageService.resize(buffer, 800, 600);
  fs.writeFileSync("resized.jpg", resized);

  const base64 = await imageService.toBase64(resized, "jpeg");
  console.log(base64);
})();
```

### 🔧 Métodos disponíveis

| Método                   | Descrição                                |
| ------------------------ | ---------------------------------------- |
| `resize`                 | Redimensiona mantendo proporção          |
| `crop`                   | Recorta com dimensões fixas              |
| `compress`               | Comprime imagem com qualidade ajustável  |
| `convert`                | Converte formato (`jpeg`, `png`, `webp`) |
| `addWatermark`           | Adiciona uma marca d'água                |
| `toBase64`               | Converte `Buffer` para base64 com header |
| `fromBase64`             | Converte base64 para `Buffer`            |
| `processAndReturnBase64` | Redimensiona, converte e retorna base64  |

---

## 📧 EmailService _(Backend)_

Classe Singleton para envio de e-mails usando SMTP.

### ⚙️ Configuração

Você precisa informar os parâmetros SMTP dinamicamente com `setParameters()`:

```ts
import { EmailService } from "@jackiemacklein/nettz-utils/backend";

EmailService.setParameters({
  SMTP_INTEGRATION: "true",
  SMTP_PROVIDER: "Outlook", // "Gmail", "Outros", "Brevo"
  SMTP_HOST: "smtp.office365.com",
  SMTP_PORT: "587",
  SMTP_SECURITY: "STARTTLS",
  SMTP_USERNAME: "email@dominio.com",
  SMTP_PASSWORD: "senha",
  SMTP_FROM_NAME: "Minha App",
  SMTP_FROM_EMAIL: "email@dominio.com",
});
```

### ✉️ Enviando um e-mail simples

```ts
await EmailService.sendSimpleEmail(
  "destinatario@exemplo.com",
  "Assunto do e-mail",
  "Mensagem em texto ou HTML",
  true // define se é HTML
);
```

### 📑 Enviando com opções avançadas

```ts
await EmailService.sendEmail({
  to: ["user@exemplo.com"],
  subject: "Assunto",
  html: "<h1>Olá</h1>",
  attachments: [
    {
      filename: "file.pdf",
      content: fs.readFileSync("file.pdf"),
    },
  ],
});
```

---

## 🏷️ BarcodeService _(Web + Backend)_

Módulo para análise e validação de códigos de barras brasileiros, incluindo boletos bancários e tributos.

### ✨ Exemplos de uso

```ts
import {
  analyzeBarcode,
  convertLineToBarcode,
} from "@jackiemacklein/nettz-utils/web";

// Analisando um código de barras
const barcode = "23793381286000000063305974530006339000063300";
const result = analyzeBarcode(barcode);

console.log(result);
// {
//   isValid: true,
//   type: "boleto_bancario",
//   value: "633.90",
//   dueDate: "15/12/2023"
// }

// Convertendo linha digitável para código de barras
const linhaDigitavel = "23793.38128 60000.000633 05974.530006 3 39000063300";
const codigoBarras = convertLineToBarcode(linhaDigitavel);
console.log(codigoBarras); // "23793381286000000063305974530006339000063300"
```

### 🔧 Métodos disponíveis

| Método                 | Descrição                                      |
| ---------------------- | ---------------------------------------------- |
| `analyzeBarcode`       | Analisa e valida códigos de barras             |
| `convertLineToBarcode` | Converte linha digitável para código de barras |
| `validateDVModulo11`   | Valida dígito verificador (módulo 11)          |
| `checkBarcodeType`     | Identifica o tipo de código de barras          |

### 📋 Tipos de Códigos Suportados

- **Boleto Bancário**: Códigos de 44 ou 47 dígitos (linha digitável)
- **Tributo**: Códigos de 44, 47 ou 48 dígitos que começam com "8"

### 📊 Estrutura de Retorno

```ts
interface BarcodeResult {
  isValid: boolean; // Se o código é válido
  type: BarcodeType; // Tipo do código (boleto_bancario, tributo, formato_invalido)
  value: string; // Valor em reais (formato "0.00")
  dueDate: string | null; // Data de vencimento (apenas para boletos)
}

interface BarcodeResultError {
  isValid: boolean; // Sempre false
  type: BarcodeType; // Tipo do erro
  value?: string; // Valor (se disponível)
  message: string; // Mensagem de erro
}
```

---

## 🔢 NumberService _(Web + Backend)_

Utilitários para conversão segura de valores numéricos, especialmente para valores monetários. Salva tudo como inteiro (centavos, gramas, etc.) evitando problemas de ponto flutuante.

### ✨ Exemplos de uso

```ts
import { toInteger, fromInteger } from "@jackiemacklein/nettz-utils/web";

// Convertendo string para inteiro (centavos)
const valor = toInteger("1.100.098,90"); // 110009890
const valorNegativo = toInteger("(934,33)"); // -93433

// Convertendo de volta para string formatada
const formatado = fromInteger(110009890, 2, "pt-BR", "BRL"); // "R$ 1.100.098,90"
const negativo = fromInteger(-93433, 2, "pt-BR", "BRL"); // "-R$ 934,33"

// Outros formatos
const dolares = fromInteger(100000, 2, "en-US", "USD"); // "$1,000.00"
const gramas = fromInteger(1500, 3, "pt-BR"); // "1,500"
```

### 🔧 Métodos disponíveis

| Método        | Descrição                                       |
| ------------- | ----------------------------------------------- |
| `toInteger`   | Converte string/numero para inteiro (centavos)  |
| `fromInteger` | Converte inteiro de volta para string formatada |

### 📋 Formatos Aceitos

**Entrada (`toInteger`):**

- ✅ Vírgula ou ponto como separador decimal: `"1.234,56"` ou `"1,234.56"`
- ✅ Separadores de milhar: `"1.100.098,90"`
- ✅ Negativos com `-` ou parênteses: `"-123,45"` ou `"(123,45)"`
- ✅ Números já numéricos: `1234.56`

**Saída (`fromInteger`):**

- ✅ Formato monetário: `"R$ 1.234,56"`
- ✅ Formato numérico: `"1.234,56"`
- ✅ Locale configurável: `"pt-BR"`, `"en-US"`, etc.
- ✅ Moeda configurável: `"BRL"`, `"USD"`, `"EUR"`, etc.

### ⚙️ Parâmetros

**`toInteger(value, scale = 2)`**

- `value`: Valor a ser convertido (string, number, etc.)
- `scale`: Casas decimais (2 = centavos, 3 = milésimos, etc.)

**`fromInteger(value, scale = 2, locale = "pt-BR", currency?)`**

- `value`: Inteiro salvo (ex.: centavos)
- `scale`: Casas decimais que o inteiro representa
- `locale`: Locale para formatação
- `currency`: Moeda opcional (`"BRL"`, `"USD"`, etc.)

### 💡 Casos de Uso

```ts
// E-commerce - Preços
const preco = toInteger("R$ 1.299,99"); // 129999
const precoFormatado = fromInteger(129999, 2, "pt-BR", "BRL"); // "R$ 1.299,99"

// Contabilidade - Valores negativos
const despesa = toInteger("(2.450,67)"); // -245067
const despesaFormatada = fromInteger(-245067, 2, "pt-BR", "BRL"); // "-R$ 2.450,67"

// Medidas - Gramas/Miligramas
const peso = toInteger("1.500,250", 3); // 1500250 (miligramas)
const pesoFormatado = fromInteger(1500250, 3, "pt-BR"); // "1.500,250"
```

---

## 🧪 Teste de Conexão SMTP

```ts
const result = await EmailService.testConnection();
console.log(result);
```

---

## ✅ Tipagem incluída

Essa biblioteca é escrita em TypeScript e inclui tipagens automáticas ao instalar.

---

## 📄 Licença

Todos os direitos reservados © [Jackiê Macklein](mailto:jackiemacklein@gmail.com) • Onside Tecnologia / Nettz

---

## 💬 Contato

Tem dúvidas ou sugestões? Entre em contato:

- 📧 jackiemacklein@gmail.com
- 🌐 [onsidetecnologia.com.br](https://onsidetecnologia.com.br)
