---
name: perfex-menus
description: Criação de menus para módulos Perfex CRM — sidebar, menus de cliente, add_sidebar_menu_item(), posições e ícones. Baseado apenas na documentação oficial.
---

# /perfex-menus - Menus Perfex CRM

Criação de menus para módulos. **Zero assumptions, zero hallucinations** - apenas documentação oficial.

---

## Documentação Base

- [Create Menu Items](https://help.perfexcrm.com/create-menu-items/)

---

## Menu Admin (Sidebar)

### Adicionar Item Simples

```php
// No init file do módulo
hooks()->add_action('admin_init', 'meu_modulo_init_menu');

function meu_modulo_init_menu()
{
    $CI = &get_instance();

    $CI->app_menu->add_sidebar_menu_item('meu-modulo-menu', [
        'name'     => _l('meu_modulo_title'),
        'href'     => admin_url('meu_modulo'),
        'position' => 25,
        'icon'     => 'fa fa-cube',
    ]);
}
```

### Parâmetros

| Parâmetro | Tipo | Descrição |
|-----------|------|-----------|
| `name` | string | Texto do menu (usar _l() para tradução) |
| `href` | string | URL destino |
| `position` | int | Posição no menu (menor = mais acima) |
| `icon` | string | Classe Font Awesome |
| `collapse` | bool | Se tem sub-items (default: false) |
| `badge` | array | Badge com contagem |

---

## Menu com Sub-Items (Collapsible)

```php
hooks()->add_action('admin_init', 'meu_modulo_init_menu');

function meu_modulo_init_menu()
{
    $CI = &get_instance();

    // Menu pai (collapsible)
    $CI->app_menu->add_sidebar_menu_item('meu-modulo-menu', [
        'name'     => _l('meu_modulo_title'),
        'collapse' => true,
        'position' => 25,
        'icon'     => 'fa fa-cube',
    ]);

    // Sub-item 1
    $CI->app_menu->add_sidebar_children_item('meu-modulo-menu', [
        'slug'     => 'meu-modulo-lista',
        'name'     => _l('list'),
        'href'     => admin_url('meu_modulo'),
        'position' => 1,
        'icon'     => 'fa fa-list',
    ]);

    // Sub-item 2
    $CI->app_menu->add_sidebar_children_item('meu-modulo-menu', [
        'slug'     => 'meu-modulo-criar',
        'name'     => _l('create'),
        'href'     => admin_url('meu_modulo/create'),
        'position' => 2,
        'icon'     => 'fa fa-plus',
    ]);

    // Sub-item 3
    $CI->app_menu->add_sidebar_children_item('meu-modulo-menu', [
        'slug'     => 'meu-modulo-settings',
        'name'     => _l('settings'),
        'href'     => admin_url('meu_modulo/settings'),
        'position' => 3,
        'icon'     => 'fa fa-cog',
    ]);
}
```

---

## Posições Padrão Admin

| Posição | Menu Item |
|---------|-----------|
| 1 | Dashboard |
| 5 | Customers |
| 10 | Sales |
| 15 | Subscriptions |
| 20 | Expenses |
| 25 | Contracts |
| 30 | Projects |
| 35 | Tasks |
| 40 | Tickets |
| 45 | Leads |
| 50 | Knowledge Base |
| 55 | Utilities |
| 60 | Reports |

**Dica:** Usar posições intermédias (ex: 27, 32) para inserir entre items existentes.

---

## Badge (Contador)

```php
$CI->app_menu->add_sidebar_menu_item('meu-modulo-menu', [
    'name'     => _l('meu_modulo_title'),
    'href'     => admin_url('meu_modulo'),
    'position' => 25,
    'icon'     => 'fa fa-cube',
    'badge'    => [
        'value'      => meu_modulo_count_pending(),
        'type'       => 'danger',    // primary, success, warning, danger, info
        'show_on_sidebar' => true,
    ],
]);

// Função de contagem
function meu_modulo_count_pending()
{
    $CI = &get_instance();
    $CI->db->where('status', 'pending');
    return $CI->db->count_all_results(db_prefix() . 'meu_modulo');
}
```

---

## Menu Condicional (Permissões)

```php
function meu_modulo_init_menu()
{
    // Só mostrar se staff tem permissão
    if (!staff_can('view', 'meu_modulo')) {
        return;
    }

    $CI = &get_instance();

    $CI->app_menu->add_sidebar_menu_item('meu-modulo-menu', [
        'name'     => _l('meu_modulo_title'),
        'href'     => admin_url('meu_modulo'),
        'position' => 25,
        'icon'     => 'fa fa-cube',
    ]);
}
```

---

## Menu Cliente (Área Cliente)

### Adicionar Item

```php
hooks()->add_action('clients_init', 'meu_modulo_client_menu');

function meu_modulo_client_menu()
{
    // Só mostrar se cliente logado
    if (!is_client_logged_in()) {
        return;
    }

    add_theme_menu_item('meu-modulo', [
        'name'     => _l('meu_modulo_title'),
        'href'     => site_url('meu_modulo'),
        'position' => 35,
        'icon'     => 'fa fa-cube',
    ]);
}
```

### Posições Padrão Cliente

| Posição | Menu Item |
|---------|-----------|
| 5 | Knowledge Base |
| 10 | Projects |
| 15 | Invoices |
| 20 | Contracts |
| 25 | Estimates |
| 30 | Proposals |
| 40 | Subscriptions |
| 45 | Support |
| 99 | Registration |
| 100 | Login |

---

## Menu no Setup (Administração)

Para adicionar configurações ao menu Setup:

```php
hooks()->add_action('admin_init', 'meu_modulo_setup_menu');

function meu_modulo_setup_menu()
{
    $CI = &get_instance();

    // Adicionar ao sub-menu de Setup
    $CI->app_menu->add_setup_menu_item('meu-modulo-settings', [
        'name'     => _l('meu_modulo_settings'),
        'href'     => admin_url('meu_modulo/settings'),
        'position' => 50,
        'icon'     => 'fa fa-cog',
    ]);
}
```

---

## Ícones Font Awesome 4

### Mais Usados

| Ícone | Classe |
|-------|--------|
| Lista | `fa fa-list` |
| Adicionar | `fa fa-plus` |
| Editar | `fa fa-edit` / `fa fa-pencil` |
| Apagar | `fa fa-trash` |
| Configurações | `fa fa-cog` / `fa fa-cogs` |
| Utilizador | `fa fa-user` |
| Utilizadores | `fa fa-users` |
| Ficheiro | `fa fa-file` / `fa fa-file-o` |
| Pasta | `fa fa-folder` / `fa fa-folder-o` |
| Email | `fa fa-envelope` / `fa fa-envelope-o` |
| Calendário | `fa fa-calendar` |
| Gráfico | `fa fa-bar-chart` / `fa fa-line-chart` |
| Dinheiro | `fa fa-money` |
| Cubo | `fa fa-cube` |
| Sino | `fa fa-bell` |
| Check | `fa fa-check` |
| Warning | `fa fa-exclamation-triangle` |
| Info | `fa fa-info-circle` |

### Referência Completa

[Font Awesome 4.7 Icons](https://fontawesome.com/v4/icons/)

---

## Exemplos Completos

### Módulo com Menu Completo

```php
// modules/meu_modulo/meu_modulo.php

hooks()->add_action('admin_init', 'meu_modulo_init_menus');
hooks()->add_action('clients_init', 'meu_modulo_client_menu');

/**
 * Menus Admin
 */
function meu_modulo_init_menus()
{
    if (!staff_can('view', 'meu_modulo')) {
        return;
    }

    $CI = &get_instance();

    // Menu principal com sub-items
    $CI->app_menu->add_sidebar_menu_item('meu-modulo', [
        'name'     => _l('meu_modulo'),
        'collapse' => true,
        'position' => 27,
        'icon'     => 'fa fa-cube',
        'badge'    => [
            'value' => meu_modulo_count_pending(),
            'type'  => 'warning',
            'show_on_sidebar' => true,
        ],
    ]);

    // Sub-items
    $CI->app_menu->add_sidebar_children_item('meu-modulo', [
        'slug'     => 'meu-modulo-dashboard',
        'name'     => _l('dashboard'),
        'href'     => admin_url('meu_modulo'),
        'position' => 1,
        'icon'     => 'fa fa-tachometer',
    ]);

    $CI->app_menu->add_sidebar_children_item('meu-modulo', [
        'slug'     => 'meu-modulo-items',
        'name'     => _l('items'),
        'href'     => admin_url('meu_modulo/items'),
        'position' => 2,
        'icon'     => 'fa fa-list',
    ]);

    if (staff_can('create', 'meu_modulo')) {
        $CI->app_menu->add_sidebar_children_item('meu-modulo', [
            'slug'     => 'meu-modulo-create',
            'name'     => _l('create'),
            'href'     => admin_url('meu_modulo/create'),
            'position' => 3,
            'icon'     => 'fa fa-plus',
        ]);
    }

    // Settings no Setup
    if (is_admin()) {
        $CI->app_menu->add_setup_menu_item('meu-modulo-settings', [
            'name'     => _l('meu_modulo_settings'),
            'href'     => admin_url('meu_modulo/settings'),
            'position' => 80,
            'icon'     => 'fa fa-cog',
        ]);
    }
}

/**
 * Menu Cliente
 */
function meu_modulo_client_menu()
{
    if (!is_client_logged_in()) {
        return;
    }

    add_theme_menu_item('meu-modulo', [
        'name'     => _l('meu_modulo'),
        'href'     => site_url('meu_modulo'),
        'position' => 32,
        'icon'     => 'fa fa-cube',
    ]);
}

/**
 * Contador para badge
 */
function meu_modulo_count_pending()
{
    $CI = &get_instance();
    $CI->db->where('status', 'pending');
    return $CI->db->count_all_results(db_prefix() . 'meu_modulo');
}
```

---

## Anti-Patterns (NUNCA FAZER)

| Anti-Pattern | Risco | Alternativa |
|--------------|-------|-------------|
| Menu sem verificar permissões | Acesso não autorizado | `staff_can()` |
| Posição fixa sem considerar conflitos | Sobreposição | Posições intermédias |
| Hardcode nome do menu | Não traduzível | Usar `_l()` |
| ID duplicado | Menu não aparece | IDs únicos com prefixo |
| Badge com query pesada | Performance | Cache ou contagem eficiente |

---

## Checklist Menu

```
1. [ ] Hook correcto (admin_init / clients_init)
2. [ ] ID único com prefixo do módulo
3. [ ] Permissões verificadas
4. [ ] _l() para nome do menu
5. [ ] Posição apropriada (não conflitar)
6. [ ] Ícone Font Awesome 4 válido
7. [ ] Badge eficiente (se usado)
8. [ ] Sub-items com slugs únicos
```

---

**Versão:** 1.0.0 | **Autor:** Descomplicar®
**Fonte:** help.perfexcrm.com/create-menu-items

---

## Healing Log

Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.

```jsonl
{"date":"","issue":"","fix":"","source":"user|auto"}
```

*Adicionar nova linha após cada erro corrigido.*
