forlogic-core 1.5.5 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # 🧱 Projeto atual
2
2
 
3
- **Schema padrão:** `central`
3
+ **Schema padrão:** `processes`
4
4
 
5
- > **Nota sobre schemas:** O schema padrão é `central`, mas módulos podem usar schemas diferentes quando necessário para organização ou isolamento de dados. Por exemplo, o módulo de treinamentos usa o schema `trainings`. Você pode especificar o schema no service usando `schemaName: 'nome_do_schema'`.
5
+ > **Nota sobre schemas:** Temos o schema padrão, mas módulos podem usar schemas diferentes quando necessário para organização ou isolamento de dados. Por exemplo, o módulo de treinamentos usa o schema `trainings`. Você pode especificar o schema no service usando `schemaName: 'nome_do_schema'`.
6
6
 
7
7
  ---
8
8
 
@@ -40,10 +40,412 @@ CREATE INDEX idx_table_user ON schema.table(id_user);
40
40
 
41
41
  ---
42
42
 
43
+ ## 📝 CONVENÇÕES DE NOMENCLATURA
44
+
45
+ ### ⚠️ PADRÕES OBRIGATÓRIOS
46
+
47
+ **Foreign Keys (Chaves Estrangeiras):**
48
+ ```typescript
49
+ // ❌ ERRADO
50
+ process_id: string
51
+ user_id: string
52
+
53
+ // ✅ CORRETO - Sempre prefixo id_
54
+ id_process: string
55
+ id_user: string
56
+ ```
57
+
58
+ **Booleans:**
59
+ ```typescript
60
+ // ❌ ERRADO
61
+ active: boolean
62
+ removed: boolean
63
+
64
+ // ✅ CORRETO - Sempre prefixo is_
65
+ is_active: boolean
66
+ is_removed: boolean
67
+ ```
68
+
69
+ **Timestamps:**
70
+ ```typescript
71
+ // ❌ ERRADO
72
+ creation_date: string
73
+ update_time: string
74
+
75
+ // ✅ CORRETO - Sempre sufixo _at
76
+ created_at: string
77
+ updated_at: string
78
+ deleted_at: string
79
+ ```
80
+
81
+ ---
82
+
83
+ ## 🚫 ÍNDICES: ABSOLUTAMENTE PROIBIDO CRIAR AUTOMATICAMENTE
84
+
85
+ ### ⚠️ REGRA DE OURO
86
+ **NUNCA, EM HIPÓTESE ALGUMA, criar índices automaticamente em migrations!**
87
+
88
+ ### 🤔 Por Quê?
89
+ 1. **Custo**: Índices ocupam espaço em disco e custam dinheiro
90
+ 2. **Performance de Escrita**: Cada índice adiciona overhead em INSERTs/UPDATEs
91
+ 3. **Otimização Prematura**: 99% dos índices criados "por precaução" nunca são usados
92
+ 4. **Manutenção**: Índices desnecessários dificultam manutenção e análise de queries
93
+
94
+ ### ❌ Casos PROIBIDOS (mesmo que pareçam "boas práticas")
95
+ ```sql
96
+ -- ❌ PROIBIDO: Índice em FK "porque é boa prática"
97
+ CREATE INDEX idx_subprocess_process ON subprocesses(id_process);
98
+
99
+ -- ❌ PROIBIDO: Índice em campo de busca "porque pode ser útil"
100
+ CREATE INDEX idx_process_title ON processes(title);
101
+
102
+ -- ❌ PROIBIDO: Índice composto "por precaução"
103
+ CREATE INDEX idx_deliverable_status ON deliverables(id_subprocess, is_completed);
104
+ ```
105
+
106
+ ### ✅ Quando Criar Índices?
107
+
108
+ **APENAS** quando:
109
+ 1. ✅ **Solicitado explicitamente** pelo usuário
110
+ 2. ✅ **Análise de performance** comprovou necessidade (EXPLAIN ANALYZE)
111
+ 3. ✅ **Aprovação prévia** do usuário para incluir na migration
112
+
113
+ ### 📋 Checklist OBRIGATÓRIO Antes de Qualquer Migration
114
+ ```markdown
115
+ - [ ] A migration NÃO contém NENHUM `CREATE INDEX`?
116
+ - [ ] Se contém, o usuário solicitou EXPLICITAMENTE?
117
+ - [ ] Se contém, foi feita análise de performance (EXPLAIN ANALYZE)?
118
+ - [ ] Se contém, o usuário APROVOU adicionar à migration?
119
+ ```
120
+
121
+ ### 🔧 Processo Correto Para Criar Índices
122
+ 1. **Usuário solicita** OU problemas de performance são detectados
123
+ 2. **Rodar EXPLAIN ANALYZE** para confirmar necessidade
124
+ 3. **Perguntar ao usuário**: "Posso criar o índice X na coluna Y? Isso vai melhorar a query Z mas adiciona overhead."
125
+ 4. **Aguardar aprovação** do usuário
126
+ 5. **Criar migration separada** apenas com os índices aprovados
127
+
128
+ ### 📝 Template de Migration de Índices (quando aprovado)
129
+ ```sql
130
+ -- Migration: [TIMESTAMP]_add_performance_indexes.sql
131
+ -- Aprovado em: [DATA]
132
+ -- Justificativa: [RAZÃO ESPECÍFICA]
133
+
134
+ CREATE INDEX idx_processes_title ON processes.processes(title);
135
+ -- Melhora busca por título em 80% (EXPLAIN ANALYZE anexo)
136
+ ```
137
+
138
+ ---
139
+
140
+ ## 🚫 USAR forlogic-core - NÃO DUPLICAR CÓDIGO
141
+
142
+ ### ⚠️ ARQUIVOS PROIBIDOS DE CRIAR LOCALMENTE
143
+
144
+ **NUNCA crie estes arquivos localmente:**
145
+ ```typescript
146
+ // ❌ PROIBIDO - Usar da lib
147
+ src/lib/utils.ts // cn() já existe no forlogic-core
148
+ src/components/ui/dialog.tsx
149
+ src/components/ui/button.tsx
150
+ src/components/ui/card.tsx
151
+ src/components/ui/input.tsx
152
+ // ... e TODOS os outros componentes UI
153
+ ```
154
+
155
+ ### ✅ Imports Corretos
156
+
157
+ **Utils (cn):**
158
+ ```typescript
159
+ // ❌ ERRADO
160
+ import { cn } from '@/lib/utils'
161
+
162
+ // ✅ CORRETO
163
+ import { cn } from 'forlogic-core'
164
+ ```
165
+
166
+ **Componentes UI:**
167
+ ```typescript
168
+ // ❌ ERRADO
169
+ import { Dialog } from '@/components/ui/dialog'
170
+ import { Button } from '@/components/ui/button'
171
+
172
+ // ✅ CORRETO
173
+ import { Dialog, DialogContent, DialogTitle, DialogHeader } from 'forlogic-core'
174
+ import { Button } from 'forlogic-core'
175
+ ```
176
+
177
+ ### 📋 Checklist Antes de Criar Novo Arquivo
178
+ ```markdown
179
+ - [ ] Este componente/util JÁ existe no forlogic-core?
180
+ - [ ] Verifiquei a lista de exports disponíveis abaixo?
181
+ - [ ] Se existe, estou usando o import correto da lib?
182
+ ```
183
+
184
+ ### 📦 Componentes e Utils Disponíveis no forlogic-core
185
+
186
+ **🎨 Componentes UI:**
187
+ ```typescript
188
+ // Formulários
189
+ Button, Input, Textarea, Label, Select, SelectContent,
190
+ SelectItem, SelectTrigger, SelectValue, Checkbox, RadioGroup,
191
+ RadioGroupItem, Switch
192
+
193
+ // Layout
194
+ Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle
195
+ Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader,
196
+ DialogTitle, DialogTrigger
197
+ Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle
198
+ Separator, ScrollArea
199
+
200
+ // Navegação
201
+ Tabs, TabsContent, TabsList, TabsTrigger
202
+ Accordion, AccordionContent, AccordionItem, AccordionTrigger
203
+ DropdownMenu, DropdownMenuContent, DropdownMenuItem
204
+
205
+ // Feedback
206
+ Alert, AlertDescription, AlertTitle
207
+ Toast, useToast
208
+ Progress
209
+ Badge
210
+ Tooltip, TooltipContent, TooltipProvider, TooltipTrigger
211
+
212
+ // Tabelas
213
+ Table, TableBody, TableCell, TableHead, TableHeader, TableRow
214
+ ```
215
+
216
+ **🛠️ Utils e Hooks:**
217
+ ```typescript
218
+ // Utils
219
+ cn // Merge classes Tailwind
220
+ formatDate, formatDatetime // Formatação de datas
221
+
222
+ // Auth
223
+ useAuth // Hook de autenticação
224
+ ProtectedRoute // Componente de rota protegida
225
+
226
+ // Qualiex
227
+ useQualiexUsers // Hook de usuários
228
+ QualiexUserField // Campo de seleção de usuário
229
+
230
+ // Supabase
231
+ getSupabaseClient // Cliente Supabase configurado
232
+ TokenManager // Gerenciamento de tokens
233
+
234
+ // Services
235
+ createSimpleService // Criar service CRUD
236
+ createCrudPage // Criar página CRUD
237
+ generateCrudConfig // Gerar config CRUD
238
+ createSimpleSaveHandler // Handler de save
239
+
240
+ // Errors
241
+ errorService // Service de erros
242
+ ```
243
+
244
+ ### 🔍 Como Verificar Exports Disponíveis
245
+
246
+ Se não tiver certeza se algo existe no forlogic-core:
247
+ 1. Abra `node_modules/forlogic-core/package.json`
248
+ 2. Verifique os exports disponíveis
249
+ 3. Em caso de dúvida, pergunte ao usuário antes de criar localmente
250
+
251
+ ---
252
+
253
+ ### 🔽 COMPONENTES AVANÇADOS
254
+
255
+ #### EntitySelect - Dropdown Genérico com Busca
256
+
257
+ **Quando usar?**
258
+
259
+ Use o `EntitySelect` para criar dropdowns com busca e ordenação para qualquer entidade do sistema:
260
+ - ✅ Seleção de processos, departamentos, categorias, etc
261
+ - ✅ Busca em tempo real
262
+ - ✅ Ordenação alfabética automática
263
+ - ✅ Estados de loading e erro inclusos
264
+
265
+ **Uso Básico:**
266
+
267
+ ```typescript
268
+ import { EntitySelect } from 'forlogic-core';
269
+ import { useProcesses } from './processService';
270
+
271
+ function MyForm() {
272
+ const { data: processes = [], isLoading, error } = useProcesses();
273
+ const [selectedId, setSelectedId] = useState('');
274
+
275
+ return (
276
+ <EntitySelect
277
+ value={selectedId}
278
+ onChange={setSelectedId}
279
+ items={processes}
280
+ isLoading={isLoading}
281
+ error={error}
282
+ getItemValue={(process) => process.id}
283
+ getItemLabel={(process) => process.title}
284
+ placeholder="Selecionar processo"
285
+ searchPlaceholder="Buscar processo..."
286
+ />
287
+ );
288
+ }
289
+ ```
290
+
291
+ **Props do EntitySelect:**
292
+
293
+ | Prop | Tipo | Obrigatório | Descrição |
294
+ |------|------|-------------|-----------|
295
+ | `items` | `T[]` | ✅ | Array de itens para seleção |
296
+ | `getItemValue` | `(item: T) => string` | ✅ | Função que retorna o valor único do item (ex: `id`) |
297
+ | `getItemLabel` | `(item: T) => string` | ✅ | Função que retorna o texto exibido |
298
+ | `value` | `string` | ❌ | Valor selecionado |
299
+ | `onChange` | `(value: string) => void` | ❌ | Callback quando valor muda |
300
+ | `isLoading` | `boolean` | ❌ | Mostra skeleton durante carregamento |
301
+ | `error` | `Error \| null` | ❌ | Mostra mensagem de erro |
302
+ | `placeholder` | `string` | ❌ | Placeholder do select (padrão: "Selecionar...") |
303
+ | `searchPlaceholder` | `string` | ❌ | Placeholder da busca (padrão: "Buscar...") |
304
+ | `emptyMessage` | `string` | ❌ | Mensagem quando não há itens |
305
+ | `noResultsMessage` | `string` | ❌ | Mensagem quando busca não encontra resultados |
306
+ | `sortItems` | `(a: T, b: T) => number` | ❌ | Função customizada de ordenação (padrão: alfabético) |
307
+ | `disabled` | `boolean` | ❌ | Desabilita o select |
308
+ | `className` | `string` | ❌ | Classes CSS adicionais |
309
+
310
+ **Ordenação Customizada:**
311
+
312
+ Por padrão, itens são ordenados alfabeticamente pelo `label`. Para customizar:
313
+
314
+ ```typescript
315
+ <EntitySelect
316
+ items={employees}
317
+ getItemValue={(e) => e.id}
318
+ getItemLabel={(e) => `${e.name} - ${e.department}`}
319
+ sortItems={(a, b) => {
320
+ // Ordenar por departamento, depois por nome
321
+ if (a.department !== b.department) {
322
+ return a.department.localeCompare(b.department);
323
+ }
324
+ return a.name.localeCompare(b.name);
325
+ }}
326
+ />
327
+ ```
328
+
329
+ **Integração com React Hook Form:**
330
+
331
+ ```typescript
332
+ import { useForm } from 'react-hook-form';
333
+ import { EntitySelect } from 'forlogic-core';
334
+
335
+ function MyForm() {
336
+ const { control } = useForm();
337
+ const { data: categories = [] } = useCategories();
338
+
339
+ return (
340
+ <FormField
341
+ control={control}
342
+ name="category_id"
343
+ render={({ field }) => (
344
+ <FormItem>
345
+ <FormLabel>Categoria</FormLabel>
346
+ <FormControl>
347
+ <EntitySelect
348
+ value={field.value}
349
+ onChange={field.onChange}
350
+ items={categories}
351
+ getItemValue={(c) => c.id}
352
+ getItemLabel={(c) => c.name}
353
+ placeholder="Selecionar categoria"
354
+ />
355
+ </FormControl>
356
+ <FormMessage />
357
+ </FormItem>
358
+ )}
359
+ />
360
+ );
361
+ }
362
+ ```
363
+
364
+ **Usando em Formulários CRUD:**
365
+
366
+ Para usar o `EntitySelect` em formulários CRUD gerados automaticamente, você precisa criar um componente wrapper e registrá-lo no `BaseForm.tsx`:
367
+
368
+ ```typescript
369
+ // 1. Criar wrapper do EntitySelect
370
+ // src/components/ProcessSelect.tsx
371
+ import { EntitySelect } from 'forlogic-core';
372
+ import { useProcesses } from '@/processes/processService';
373
+
374
+ export function ProcessSelect({ value, onChange, disabled }: any) {
375
+ const { data: processes = [], isLoading, error } = useProcesses();
376
+
377
+ return (
378
+ <EntitySelect
379
+ value={value}
380
+ onChange={onChange}
381
+ items={processes}
382
+ isLoading={isLoading}
383
+ error={error}
384
+ getItemValue={(p) => p.id}
385
+ getItemLabel={(p) => p.title}
386
+ disabled={disabled}
387
+ placeholder="Selecionar processo"
388
+ />
389
+ );
390
+ }
391
+
392
+ // 2. Registrar no BaseForm.tsx (lib/crud/components/BaseForm.tsx)
393
+ // Adicionar no switch case do renderField:
394
+ case 'process-select':
395
+ return <ProcessSelect {...commonFieldProps} />;
396
+
397
+ // 3. Usar na configuração do formulário
398
+ {
399
+ name: 'id_process',
400
+ label: 'Processo',
401
+ type: 'process-select' as const,
402
+ required: true
403
+ }
404
+ ```
405
+
406
+ **Exemplo Completo:**
407
+
408
+ ```typescript
409
+ // src/departments/DepartmentSelect.tsx
410
+ import { EntitySelect } from 'forlogic-core';
411
+ import { useDepartments } from './departmentService';
412
+
413
+ interface DepartmentSelectProps {
414
+ value?: string;
415
+ onChange?: (value: string) => void;
416
+ disabled?: boolean;
417
+ className?: string;
418
+ }
419
+
420
+ export function DepartmentSelect(props: DepartmentSelectProps) {
421
+ const { data: departments = [], isLoading, error } = useDepartments();
422
+
423
+ return (
424
+ <EntitySelect
425
+ {...props}
426
+ items={departments}
427
+ isLoading={isLoading}
428
+ error={error}
429
+ getItemValue={(dept) => dept.id}
430
+ getItemLabel={(dept) => dept.name}
431
+ placeholder="Selecionar departamento"
432
+ searchPlaceholder="Buscar departamento..."
433
+ emptyMessage="Nenhum departamento cadastrado"
434
+ noResultsMessage="Nenhum departamento encontrado com esse nome"
435
+ />
436
+ );
437
+ }
438
+ ```
439
+
440
+ ---
441
+
43
442
  ### ✅ CHECKLIST (antes de implementar)
44
443
 
45
444
  - [ ] Schema `schema` especificado em queries e service?
46
445
  - [ ] RLS usando `alias` (nunca `id_user`)?
446
+ - [ ] **Nomenclatura correta**: `id_<entity>`, `is_<bool>`, `<action>_at`?
447
+ - [ ] **Migration SEM índices** (ou aprovados pelo usuário)?
448
+ - [ ] **Imports do forlogic-core** (não criar utils.ts ou ui/* localmente)?
47
449
  - [ ] Preservar `item.id` no update?
48
450
  - [ ] Config gerado com `useMemo()`?
49
451
  - [ ] `<Outlet />` no componente pai?