forlogic-core 2.3.2 → 2.3.4
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/dist/action-plans/auth/services/AuthService.d.ts +19 -0
- package/dist/action-plans/exports/ui.d.ts +2 -0
- package/dist/action-plans/i18n/LanguageBootstrap.d.ts +14 -0
- package/dist/action-plans/i18n/index.d.ts +1 -0
- package/dist/action-plans/index.d.ts +14 -103
- package/dist/action-plans/index.esm.js +1 -1
- package/dist/action-plans/index.js +1 -1
- package/dist/action-plans/types.d.ts +361 -551
- package/dist/audit-trail/auth/services/AuthService.d.ts +19 -0
- package/dist/audit-trail/exports/ui.d.ts +2 -0
- package/dist/audit-trail/i18n/LanguageBootstrap.d.ts +14 -0
- package/dist/audit-trail/i18n/index.d.ts +1 -0
- package/dist/audit-trail/index.d.ts +8 -103
- package/dist/audit-trail/types.d.ts +173 -567
- package/dist/auth/services/AuthService.d.ts +19 -0
- package/dist/auth/services/TokenService.d.ts +1 -0
- package/dist/auth/utils/authDebug.d.ts +18 -0
- package/dist/components/ui/combobox.d.ts +2 -1
- package/dist/exports/ui.d.ts +2 -0
- package/dist/i18n/LanguageBootstrap.d.ts +14 -0
- package/dist/i18n/index.d.ts +1 -0
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/dist/leadership/auth/services/AuthService.d.ts +19 -0
- package/dist/leadership/exports/ui.d.ts +2 -0
- package/dist/leadership/i18n/LanguageBootstrap.d.ts +14 -0
- package/dist/leadership/i18n/index.d.ts +1 -0
- package/dist/leadership/index.d.ts +12 -103
- package/dist/leadership/types.d.ts +13 -593
- package/dist/places/auth/services/AuthService.d.ts +19 -0
- package/dist/places/exports/ui.d.ts +2 -0
- package/dist/places/i18n/LanguageBootstrap.d.ts +14 -0
- package/dist/places/i18n/index.d.ts +1 -0
- package/dist/places/index.d.ts +8 -104
- package/dist/places/types.d.ts +6 -599
- package/dist/qualiex/hooks/useQualiexReady.d.ts +15 -0
- package/dist/qualiex/services/qualiexApiService.d.ts +18 -0
- package/dist/sign/auth/services/AuthService.d.ts +19 -0
- package/dist/sign/exports/ui.d.ts +2 -0
- package/dist/sign/i18n/LanguageBootstrap.d.ts +14 -0
- package/dist/sign/i18n/index.d.ts +1 -0
- package/dist/sign/index.d.ts +8 -104
- package/dist/sign/index.esm.js +1 -1
- package/dist/sign/index.js +1 -1
- package/dist/sign/types.d.ts +46 -596
- package/dist/updates/components/UpdatesBar.d.ts +10 -0
- package/dist/updates/components/UpdatesDialog.d.ts +10 -0
- package/dist/updates/components/UserUpdatesViewer.d.ts +5 -0
- package/dist/updates/hooks/useUserUpdates.d.ts +5 -0
- package/dist/updates/index.d.ts +9 -0
- package/dist/updates/services/userUpdatesApi.d.ts +3 -0
- package/dist/updates/types.d.ts +24 -0
- package/dist/updates/utils/dismissedStore.d.ts +4 -0
- package/package.json +2 -2
package/dist/places/types.d.ts
CHANGED
|
@@ -1,603 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
export type LoadingState = 'idle' | 'loading' | 'success' | 'error';
|
|
3
|
-
export type ViewMode = 'table';
|
|
4
|
-
export type SortDirection = 'asc' | 'desc';
|
|
5
|
-
export type ActionType = 'create' | 'update' | 'delete' | 'fetch' | 'export';
|
|
6
|
-
/**
|
|
7
|
-
* Interface mínima que **toda** entidade da plataforma deve estender.
|
|
8
|
-
*
|
|
9
|
-
* Reflete os campos obrigatórios de qualquer tabela multi-tenant: `id`, `alias` (tenant),
|
|
10
|
-
* timestamps e flags de soft delete (`is_removed`) e ativação (`is_actived`).
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* // Estendendo para uma entidade de domínio
|
|
14
|
-
* interface ActionPlan extends BaseEntity {
|
|
15
|
-
* title: string;
|
|
16
|
-
* description: string | null;
|
|
17
|
-
* status: 'pending' | 'in_progress' | 'completed';
|
|
18
|
-
* id_user: string;
|
|
19
|
-
* }
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* // Uso genérico em hooks/serviços CRUD
|
|
23
|
-
* function useEntities<T extends BaseEntity>(table: string) {
|
|
24
|
-
* return useQuery<T[]>(['entities', table], () => fetchAll(table));
|
|
25
|
-
* }
|
|
26
|
-
*/
|
|
27
|
-
export interface BaseEntity {
|
|
1
|
+
export interface Place {
|
|
28
2
|
id: string;
|
|
29
|
-
alias: string;
|
|
30
|
-
created_at: string;
|
|
31
|
-
updated_at: string;
|
|
32
|
-
is_removed: boolean;
|
|
33
|
-
is_actived: boolean;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* BaseEntityPayload - Payload básico para criação de entidades
|
|
37
|
-
* IMPORTANTE: Customize conforme as propriedades da sua entidade específica
|
|
38
|
-
*/
|
|
39
|
-
export interface BaseEntityPayload {
|
|
40
|
-
alias: string;
|
|
41
|
-
}
|
|
42
|
-
export interface QueryParams {
|
|
43
|
-
page?: number;
|
|
44
|
-
limit?: number;
|
|
45
|
-
search?: string;
|
|
46
|
-
sortField?: string;
|
|
47
|
-
sortDirection?: SortDirection;
|
|
48
|
-
}
|
|
49
|
-
export interface PaginatedResponse<T = unknown> {
|
|
50
|
-
data: T[];
|
|
51
|
-
currentPage: number;
|
|
52
|
-
totalPages: number;
|
|
53
|
-
totalItems: number;
|
|
54
|
-
itemsPerPage: number;
|
|
55
|
-
hasNextPage: boolean;
|
|
56
|
-
hasPreviousPage: boolean;
|
|
57
|
-
}
|
|
58
|
-
export interface SortState {
|
|
59
|
-
field: string;
|
|
60
|
-
direction: SortDirection;
|
|
61
|
-
}
|
|
62
|
-
export interface CrudManager<T extends BaseEntity> {
|
|
63
|
-
entities: T[];
|
|
64
|
-
pagination: PaginatedResponse<T>;
|
|
65
|
-
isLoading: boolean;
|
|
66
|
-
isDeleting: boolean;
|
|
67
|
-
searchTerm: string;
|
|
68
|
-
sortField: string;
|
|
69
|
-
sortDirection: SortDirection;
|
|
70
|
-
currentPage: number;
|
|
71
|
-
itemsPerPage: number;
|
|
72
|
-
handleSearch: (search: string) => void;
|
|
73
|
-
handleSort: (field: string) => void;
|
|
74
|
-
handlePageChange: (page: number) => void;
|
|
75
|
-
handleItemsPerPageChange: (limit: number) => void;
|
|
76
|
-
clearFilters: () => void;
|
|
77
|
-
deleteEntity: (id: string) => void;
|
|
78
|
-
refetch: () => void;
|
|
79
|
-
selectedIds: string[];
|
|
80
|
-
selectItem: (id: string) => void;
|
|
81
|
-
selectAll: () => void;
|
|
82
|
-
clearSelection: () => void;
|
|
83
|
-
isAllSelected: boolean;
|
|
84
|
-
bulkDelete?: (ids: string[]) => Promise<void>;
|
|
85
|
-
isBulkDeleting?: boolean;
|
|
86
|
-
}
|
|
87
|
-
export interface CrudEntity extends BaseEntity {
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Definição de coluna usada por {@link CrudTable} e `createCrudPage`.
|
|
91
|
-
*
|
|
92
|
-
* Suporta tipagem semântica (`type`), ordenação (default `true`), filtros, busca textual,
|
|
93
|
-
* renderização customizada e larguras controladas.
|
|
94
|
-
*
|
|
95
|
-
* @example
|
|
96
|
-
* const columns: CrudColumn<ActionPlan>[] = [
|
|
97
|
-
* { key: 'title', header: 'Título', type: 'text', searchable: true, weight: 3 },
|
|
98
|
-
* {
|
|
99
|
-
* key: 'status',
|
|
100
|
-
* header: 'Status',
|
|
101
|
-
* type: 'select',
|
|
102
|
-
* options: [
|
|
103
|
-
* { label: 'Pendente', value: 'pending' },
|
|
104
|
-
* { label: 'Concluído', value: 'completed' },
|
|
105
|
-
* ],
|
|
106
|
-
* filterable: true,
|
|
107
|
-
* render: (row) => <StatusBadge status={row.status} />,
|
|
108
|
-
* },
|
|
109
|
-
* {
|
|
110
|
-
* key: 'created_at',
|
|
111
|
-
* header: 'Criado em',
|
|
112
|
-
* type: 'date',
|
|
113
|
-
* sortable: true,
|
|
114
|
-
* render: (row) => formatDatetime(row.created_at),
|
|
115
|
-
* },
|
|
116
|
-
* { key: 'id_user', header: 'Responsável', minWidth: 180 },
|
|
117
|
-
* ];
|
|
118
|
-
*/
|
|
119
|
-
export interface CrudColumn<T = any> {
|
|
120
|
-
key: keyof T;
|
|
121
|
-
header: string;
|
|
122
|
-
label?: string;
|
|
123
|
-
type?: 'text' | 'number' | 'date' | 'boolean' | 'select' | 'textarea' | 'email' | 'tel';
|
|
124
|
-
required?: boolean;
|
|
125
|
-
/** Coluna é ordenável. Default: true. Use `false` para desabilitar. */
|
|
126
|
-
sortable?: boolean;
|
|
127
|
-
filterable?: boolean;
|
|
128
|
-
searchable?: boolean;
|
|
129
|
-
options?: Array<{
|
|
130
|
-
label: string;
|
|
131
|
-
value: any;
|
|
132
|
-
}>;
|
|
133
|
-
render?: (item: T) => React.ReactNode;
|
|
134
|
-
validation?: (value: any) => string | undefined;
|
|
135
|
-
className?: string;
|
|
136
|
-
/** Minimum width in pixels (only applied in desktop view) */
|
|
137
|
-
minWidth?: number;
|
|
138
|
-
/** Maximum width in pixels for column resize */
|
|
139
|
-
maxWidth?: number;
|
|
140
|
-
/** Flex weight for distributing remaining space (only applied in desktop view) */
|
|
141
|
-
weight?: number;
|
|
142
|
-
/** Fixed width (overrides minWidth and weight) */
|
|
143
|
-
width?: number;
|
|
144
|
-
/** Whether the column can be resized (default: true when enableColumnResize is enabled) */
|
|
145
|
-
resizable?: boolean;
|
|
146
|
-
/** Whether the column can be hidden via column manager (default: true) */
|
|
147
|
-
hideable?: boolean;
|
|
148
|
-
/** Whether the column can be used for grouping (default: false) */
|
|
149
|
-
groupable?: boolean;
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Filtro customizado para páginas CRUD
|
|
153
|
-
*
|
|
154
|
-
* Permite adicionar filtros personalizados (busca, selects, checkboxes, etc)
|
|
155
|
-
* nas páginas CRUD geradas automaticamente.
|
|
156
|
-
*
|
|
157
|
-
* **Tipos de filtro:**
|
|
158
|
-
* - `'search'`: Campo de busca padrão (integrado com `manager.searchTerm`)
|
|
159
|
-
* - `'select'`: Select nativo com opções predefinidas
|
|
160
|
-
* - `'custom'`: Componente React customizado (Select, Checkbox, etc)
|
|
161
|
-
*
|
|
162
|
-
* **Posicionamento:**
|
|
163
|
-
* - Desktop: Filtros aparecem inline na Action Bar (ao lado do botão "Novo")
|
|
164
|
-
* - Mobile: Filtros empilhados verticalmente abaixo do botão "Novo"
|
|
165
|
-
*
|
|
166
|
-
* @example
|
|
167
|
-
* ```typescript
|
|
168
|
-
* // Filtro de busca padrão
|
|
169
|
-
* const filters: CrudFilter[] = [
|
|
170
|
-
* { type: 'search' }
|
|
171
|
-
* ];
|
|
172
|
-
*
|
|
173
|
-
* // Filtro select nativo
|
|
174
|
-
* const filters: CrudFilter[] = [
|
|
175
|
-
* {
|
|
176
|
-
* type: 'select',
|
|
177
|
-
* placeholder: 'Filtrar por status',
|
|
178
|
-
* options: [
|
|
179
|
-
* { label: 'Todos', value: 'all' },
|
|
180
|
-
* { label: 'Ativos', value: 'active' },
|
|
181
|
-
* { label: 'Inativos', value: 'inactive' }
|
|
182
|
-
* ],
|
|
183
|
-
* value: statusFilter,
|
|
184
|
-
* onChange: setStatusFilter
|
|
185
|
-
* }
|
|
186
|
-
* ];
|
|
187
|
-
*
|
|
188
|
-
* // Filtro customizado com Select
|
|
189
|
-
* import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from 'forlogic-core';
|
|
190
|
-
*
|
|
191
|
-
* const filters: CrudFilter[] = [
|
|
192
|
-
* {
|
|
193
|
-
* type: 'custom',
|
|
194
|
-
* component: ({ value, onChange }) => (
|
|
195
|
-
* <Select value={value} onValueChange={onChange}>
|
|
196
|
-
* <SelectTrigger className="w-[180px]">
|
|
197
|
-
* <SelectValue placeholder="Status" />
|
|
198
|
-
* </SelectTrigger>
|
|
199
|
-
* <SelectContent>
|
|
200
|
-
* <SelectItem value="all">Todos</SelectItem>
|
|
201
|
-
* <SelectItem value="active">Ativos</SelectItem>
|
|
202
|
-
* <SelectItem value="inactive">Inativos</SelectItem>
|
|
203
|
-
* </SelectContent>
|
|
204
|
-
* </Select>
|
|
205
|
-
* ),
|
|
206
|
-
* props: { value: statusFilter, onChange: setStatusFilter }
|
|
207
|
-
* }
|
|
208
|
-
* ];
|
|
209
|
-
* ```
|
|
210
|
-
*
|
|
211
|
-
* @example
|
|
212
|
-
* ```typescript
|
|
213
|
-
* // Múltiplos filtros customizados
|
|
214
|
-
* function ProcessesPage() {
|
|
215
|
-
* const [statusFilter, setStatusFilter] = useState('all');
|
|
216
|
-
* const [typeFilter, setTypeFilter] = useState('all');
|
|
217
|
-
*
|
|
218
|
-
* const filters: CrudFilter[] = [
|
|
219
|
-
* { type: 'search' },
|
|
220
|
-
* {
|
|
221
|
-
* type: 'select',
|
|
222
|
-
* placeholder: 'Status',
|
|
223
|
-
* options: [
|
|
224
|
-
* { label: 'Todos', value: 'all' },
|
|
225
|
-
* { label: 'Ativos', value: 'active' },
|
|
226
|
-
* { label: 'Inativos', value: 'inactive' }
|
|
227
|
-
* ],
|
|
228
|
-
* value: statusFilter,
|
|
229
|
-
* onChange: setStatusFilter
|
|
230
|
-
* },
|
|
231
|
-
* {
|
|
232
|
-
* type: 'custom',
|
|
233
|
-
* component: TypeSelect,
|
|
234
|
-
* props: { value: typeFilter, onChange: setTypeFilter }
|
|
235
|
-
* }
|
|
236
|
-
* ];
|
|
237
|
-
*
|
|
238
|
-
* // Filtrar dados baseado nos filtros customizados
|
|
239
|
-
* const filteredData = useMemo(() => {
|
|
240
|
-
* let data = manager.entities;
|
|
241
|
-
* if (statusFilter !== 'all') {
|
|
242
|
-
* data = data.filter(item => item.status === statusFilter);
|
|
243
|
-
* }
|
|
244
|
-
* if (typeFilter !== 'all') {
|
|
245
|
-
* data = data.filter(item => item.type === typeFilter);
|
|
246
|
-
* }
|
|
247
|
-
* return data;
|
|
248
|
-
* }, [manager.entities, statusFilter, typeFilter]);
|
|
249
|
-
*
|
|
250
|
-
* return <CrudPage manager={{ ...manager, entities: filteredData }} />;
|
|
251
|
-
* }
|
|
252
|
-
* ```
|
|
253
|
-
*
|
|
254
|
-
* @see {@link FilterBar} - Componente que renderiza os filtros
|
|
255
|
-
*/
|
|
256
|
-
export interface CrudFilter {
|
|
257
|
-
/** Tipo do filtro: 'search' para busca padrão, 'select' para select nativo, 'custom' para componente personalizado */
|
|
258
|
-
type: 'search' | 'select' | 'custom';
|
|
259
|
-
/** Placeholder para select (quando type='select') */
|
|
260
|
-
placeholder?: string;
|
|
261
|
-
/** Opções para select (quando type='select') */
|
|
262
|
-
options?: Array<{
|
|
263
|
-
label: string;
|
|
264
|
-
value: string;
|
|
265
|
-
}>;
|
|
266
|
-
/** Valor atual do filtro (quando type='select') */
|
|
267
|
-
value?: string;
|
|
268
|
-
/** Callback quando o valor muda (quando type='select') */
|
|
269
|
-
onChange?: (value: string) => void;
|
|
270
|
-
/** Componente React customizado (obrigatório quando type='custom') */
|
|
271
|
-
component?: React.ComponentType<any>;
|
|
272
|
-
/** Props passadas para o componente customizado (value, onChange, etc) */
|
|
273
|
-
props?: Record<string, any>;
|
|
274
|
-
/** Função para controlar visibilidade do filtro baseado no estado do manager */
|
|
275
|
-
show?: (manager: CrudManager<any>) => boolean;
|
|
276
|
-
}
|
|
277
|
-
export interface BulkAction<T extends BaseEntity> {
|
|
278
|
-
label: string;
|
|
279
|
-
icon?: React.ComponentType<{
|
|
280
|
-
size?: number;
|
|
281
|
-
className?: string;
|
|
282
|
-
}>;
|
|
283
|
-
variant?: 'default' | 'destructive' | 'outline';
|
|
284
|
-
action: (items: T[]) => void | Promise<void>;
|
|
285
|
-
confirmMessage?: string;
|
|
286
|
-
/** Se a ação está desabilitada */
|
|
287
|
-
disabled?: boolean;
|
|
288
|
-
/** Motivo do bloqueio (exibido em tooltip quando disabled=true) */
|
|
289
|
-
disabledReason?: string;
|
|
290
|
-
}
|
|
291
|
-
export interface CrudPageConfig<T extends CrudEntity> {
|
|
292
|
-
entityName: string;
|
|
293
|
-
entityNamePlural: string;
|
|
294
|
-
filters?: CrudFilter[];
|
|
295
|
-
columns: CrudColumn<T>[];
|
|
296
|
-
cardFields?: Array<{
|
|
297
|
-
key: keyof T;
|
|
298
|
-
label: string;
|
|
299
|
-
render?: (value: any, item: T) => React.ReactNode;
|
|
300
|
-
}>;
|
|
301
|
-
onNew?: () => void;
|
|
302
|
-
onEdit?: (entity: T) => void;
|
|
303
|
-
useCustomRouting?: boolean;
|
|
304
|
-
/** @deprecated Use showNewButton={false} instead */
|
|
305
|
-
hideNewButton?: boolean;
|
|
306
|
-
/** Exibir botão "Novo" (default: true) */
|
|
307
|
-
showNewButton?: boolean;
|
|
308
|
-
/** Texto customizado para o botão "Novo" */
|
|
309
|
-
newButtonLabel?: string;
|
|
310
|
-
newButtonText?: string;
|
|
311
|
-
title?: string;
|
|
312
|
-
searchPlaceholder?: string;
|
|
313
|
-
/** Exibir busca integrada na Action Bar (default: false - usa busca global) */
|
|
314
|
-
showSearch?: boolean;
|
|
315
|
-
/** Exibir Action Bar (default: true) */
|
|
316
|
-
showActionBar?: boolean;
|
|
317
|
-
enableBulkActions?: boolean;
|
|
318
|
-
bulkActions?: BulkAction<T>[];
|
|
319
|
-
customActions?: Array<{
|
|
320
|
-
label: string;
|
|
321
|
-
icon?: React.ComponentType<{
|
|
322
|
-
size?: number;
|
|
323
|
-
className?: string;
|
|
324
|
-
}>;
|
|
325
|
-
variant?: 'default' | 'destructive' | 'outline' | 'ghost';
|
|
326
|
-
action: () => void;
|
|
327
|
-
/** Se a ação está desabilitada */
|
|
328
|
-
disabled?: boolean;
|
|
329
|
-
/** Motivo do bloqueio (exibido em tooltip quando disabled=true) */
|
|
330
|
-
disabledReason?: string;
|
|
331
|
-
}>;
|
|
332
|
-
customRowActions?: (item: T) => Array<{
|
|
333
|
-
icon: any;
|
|
334
|
-
label: string;
|
|
335
|
-
onClick: () => void;
|
|
336
|
-
}>;
|
|
337
|
-
customListView?: (items: T[], manager?: CrudManager<T>) => React.ReactNode;
|
|
338
|
-
/** Colunas ocultas por padrão (antes de qualquer interação do usuário). */
|
|
339
|
-
defaultHiddenColumns?: string[];
|
|
340
|
-
}
|
|
341
|
-
export interface EntityWithId {
|
|
342
|
-
id: string | number;
|
|
343
|
-
}
|
|
344
|
-
export type CreateEntityInput<T extends EntityWithId> = Omit<T, 'id' | 'created_at' | 'updated_at'>;
|
|
345
|
-
export type UpdateEntityInput<T extends EntityWithId> = Partial<CreateEntityInput<T>>;
|
|
346
|
-
export interface GeneratedCrudConfig<T extends EntityWithId> {
|
|
347
|
-
title: string;
|
|
348
|
-
columns: CrudColumn<T>[];
|
|
349
|
-
searchPlaceholder?: string;
|
|
350
|
-
itemsPerPage?: number;
|
|
351
|
-
enableCreate?: boolean;
|
|
352
|
-
enableEdit?: boolean;
|
|
353
|
-
enableDelete?: boolean;
|
|
354
|
-
enableSearch?: boolean;
|
|
355
|
-
enableFilters?: boolean;
|
|
356
|
-
customActions?: Array<{
|
|
357
|
-
label: string;
|
|
358
|
-
icon?: React.ComponentType;
|
|
359
|
-
onClick: (item: T) => void;
|
|
360
|
-
variant?: 'default' | 'destructive' | 'outline';
|
|
361
|
-
}>;
|
|
362
|
-
}
|
|
363
|
-
export interface FormField {
|
|
364
|
-
name: string;
|
|
365
|
-
label: string;
|
|
366
|
-
type: 'text' | 'textarea' | 'select' | 'multiselect' | 'date' | 'datetime-local' | 'number' | 'user-select' | 'group' | 'checkbox' | 'switch' | 'email' | 'password' | 'color' | 'color-picker' | 'icon-picker' | 'custom';
|
|
367
|
-
required?: boolean;
|
|
368
|
-
disabled?: boolean;
|
|
369
|
-
options?: {
|
|
370
|
-
label: string;
|
|
371
|
-
value: string | number;
|
|
372
|
-
}[];
|
|
373
|
-
placeholder?: string;
|
|
374
|
-
component?: React.ComponentType<any>;
|
|
375
|
-
componentProps?: Record<string, any>;
|
|
376
|
-
value?: any;
|
|
377
|
-
defaultValue?: any;
|
|
378
|
-
dependsOn?: string;
|
|
379
|
-
computedValue?: (formData: any) => any;
|
|
380
|
-
validation?: {
|
|
381
|
-
custom?: (value: any, formData?: any) => string | undefined;
|
|
382
|
-
} | ((value: any, formData?: any) => string | undefined);
|
|
383
|
-
layout?: 'horizontal' | 'vertical';
|
|
384
|
-
className?: string;
|
|
385
|
-
fields?: FormField[];
|
|
386
|
-
onValueChange?: (value: any) => void;
|
|
387
|
-
step?: number;
|
|
388
|
-
rows?: number;
|
|
389
|
-
mode?: 'single' | 'multiple';
|
|
390
|
-
columns?: number;
|
|
391
|
-
render?: (props: {
|
|
392
|
-
value: any;
|
|
393
|
-
onChange: (value: any) => void;
|
|
394
|
-
error?: string;
|
|
395
|
-
disabled?: boolean;
|
|
396
|
-
}) => React.ReactNode;
|
|
397
|
-
}
|
|
398
|
-
export interface FormSection {
|
|
399
|
-
id: string;
|
|
400
|
-
title: string;
|
|
401
|
-
label?: string;
|
|
402
|
-
fields: FormField[];
|
|
403
|
-
component?: React.ComponentType<any>;
|
|
404
|
-
disabled?: boolean;
|
|
405
|
-
condition?: (formData: any) => boolean;
|
|
406
|
-
}
|
|
407
|
-
export interface BaseFormConfig<T> {
|
|
408
|
-
title: string;
|
|
409
|
-
sections: FormSection[];
|
|
410
|
-
initialData?: Partial<T>;
|
|
411
|
-
onSubmit: (data: T) => void;
|
|
412
|
-
onCancel: () => void;
|
|
413
|
-
submitButtonText?: string;
|
|
414
|
-
isMobile?: boolean;
|
|
415
|
-
}
|
|
416
|
-
export interface BaseFormProps<T> extends BaseFormConfig<T> {
|
|
417
|
-
open: boolean;
|
|
418
|
-
}
|
|
419
|
-
export interface GenericQueryConfig<TData, TParams> {
|
|
420
|
-
queryKey: string[];
|
|
421
|
-
queryFn: (params: TParams) => Promise<TData>;
|
|
422
|
-
params: TParams;
|
|
423
|
-
hookName: string;
|
|
424
|
-
enabled?: boolean;
|
|
425
|
-
defaultPagination?: {
|
|
426
|
-
currentPage: number;
|
|
427
|
-
totalPages: number;
|
|
428
|
-
totalItems: number;
|
|
429
|
-
itemsPerPage: number;
|
|
430
|
-
hasNextPage: boolean;
|
|
431
|
-
hasPreviousPage: boolean;
|
|
432
|
-
};
|
|
433
|
-
dataMapper?: (data: TData) => unknown;
|
|
434
|
-
dataExtractor?: (response: TData) => unknown;
|
|
435
|
-
paginationExtractor?: (response: TData) => unknown;
|
|
436
|
-
}
|
|
437
|
-
export interface GenericDataQueryResult<TItem> {
|
|
438
|
-
data: TItem[];
|
|
439
|
-
pagination: unknown;
|
|
440
|
-
isLoading: boolean;
|
|
441
|
-
error: unknown;
|
|
442
|
-
refetch: () => void;
|
|
443
|
-
}
|
|
444
|
-
export interface AuthTokens {
|
|
445
|
-
accessToken: string;
|
|
446
|
-
idToken: string;
|
|
447
|
-
supabaseToken?: string;
|
|
448
|
-
}
|
|
449
|
-
export interface UserInfo {
|
|
450
|
-
id: string;
|
|
451
|
-
email: string;
|
|
452
3
|
name: string;
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
isSysAdmin: boolean;
|
|
456
|
-
}
|
|
457
|
-
export interface Company {
|
|
458
|
-
id: string;
|
|
459
|
-
alias: string;
|
|
460
|
-
name: string;
|
|
461
|
-
}
|
|
462
|
-
export interface SelectedUnit {
|
|
463
|
-
id: string;
|
|
464
|
-
name: string;
|
|
465
|
-
alias: string;
|
|
466
|
-
}
|
|
467
|
-
export interface CompanyTokenData {
|
|
468
|
-
id: string;
|
|
469
|
-
alias: string;
|
|
470
|
-
name: string;
|
|
471
|
-
payload: any;
|
|
472
|
-
}
|
|
473
|
-
export interface AuthState {
|
|
474
|
-
isAuthenticated: boolean;
|
|
475
|
-
isLoading: boolean;
|
|
476
|
-
user: UserInfo | null;
|
|
477
|
-
alias: string | null;
|
|
478
|
-
companies: Company[];
|
|
479
|
-
selectedUnit: SelectedUnit | null;
|
|
480
|
-
userId: string | null;
|
|
481
|
-
userAlias: string | null;
|
|
482
|
-
placeId: string | null;
|
|
483
|
-
placeName: string | null;
|
|
484
|
-
activePlaceId?: string | null;
|
|
485
|
-
activePlaceName?: string | null;
|
|
486
|
-
}
|
|
487
|
-
export interface IdTokenPayload {
|
|
488
|
-
subNewId: string;
|
|
489
|
-
email: string;
|
|
490
|
-
name: string;
|
|
491
|
-
identifier: string;
|
|
492
|
-
default?: string;
|
|
493
|
-
[key: string]: any;
|
|
494
|
-
}
|
|
495
|
-
export interface AccessTokenPayload {
|
|
496
|
-
default?: string;
|
|
497
|
-
[key: string]: any;
|
|
498
|
-
}
|
|
499
|
-
export interface QualiexUser {
|
|
500
|
-
id?: string;
|
|
501
|
-
userId?: string;
|
|
502
|
-
userName?: string;
|
|
503
|
-
userEmail?: string;
|
|
504
|
-
placeId?: string | null;
|
|
505
|
-
placeName?: string | null;
|
|
506
|
-
roleId?: string;
|
|
507
|
-
roleName?: string;
|
|
508
|
-
companyId?: string;
|
|
509
|
-
companyName?: string;
|
|
510
|
-
/** Indica se o usuário está ativo no Qualiex. Default `true` quando ausente. */
|
|
4
|
+
usersCount?: number;
|
|
5
|
+
hasChild?: boolean;
|
|
511
6
|
isActive?: boolean;
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
idField: string;
|
|
516
|
-
/** Nome do campo de saída para o nome (ex: "target_user_name"). Default: idField + "_name" */
|
|
517
|
-
nameField?: string;
|
|
518
|
-
/** Nome do campo de saída para o email (ex: "target_user_email"). Default: idField + "_email" */
|
|
519
|
-
emailField?: string;
|
|
520
|
-
/** Nome do campo de saída para o username (ex: "target_user_username"). Default: idField + "_username" */
|
|
521
|
-
usernameField?: string;
|
|
522
|
-
}
|
|
523
|
-
export interface QualiexEnrichmentConfig {
|
|
524
|
-
/** Sufixo padrão para campos de nome (default: "_name") */
|
|
525
|
-
userNameFieldSuffix?: string;
|
|
526
|
-
/** Sufixo padrão para campos de email (default: "_email") */
|
|
527
|
-
userEmailFieldSuffix?: string;
|
|
528
|
-
/** Sufixo padrão para campos de username (default: "_username") */
|
|
529
|
-
userUsernameFieldSuffix?: string;
|
|
530
|
-
}
|
|
531
|
-
/**
|
|
532
|
-
* Representa um módulo/software disponível na plataforma Qualiex.
|
|
533
|
-
* Retornado pela API GET /api/common/v1/softwares
|
|
534
|
-
*/
|
|
535
|
-
export interface Software {
|
|
536
|
-
id: number;
|
|
537
|
-
alias: string;
|
|
538
|
-
color: string;
|
|
539
|
-
colorLight: string;
|
|
540
|
-
namePtBr: string;
|
|
541
|
-
nameUs: string;
|
|
542
|
-
nameEs: string;
|
|
543
|
-
}
|
|
544
|
-
/**
|
|
545
|
-
* Representa uma associação do usuário com uma empresa/unidade.
|
|
546
|
-
* Retornado pela API GET /api/common/v1/Users/{userId}/associations
|
|
547
|
-
*
|
|
548
|
-
* O array `softwares` contém os IDs dos módulos aos quais o usuário tem acesso.
|
|
549
|
-
* O `roleId` e `roleName` representam o papel do usuário naquela associação.
|
|
550
|
-
*/
|
|
551
|
-
export interface UserAssociation {
|
|
552
|
-
associationId: string;
|
|
553
|
-
userId: string;
|
|
554
|
-
userName: string;
|
|
555
|
-
companyId: string;
|
|
556
|
-
companyName: string;
|
|
557
|
-
companyAlias: string;
|
|
558
|
-
companyPhotoDate?: string;
|
|
559
|
-
language?: string;
|
|
560
|
-
roleId: string;
|
|
561
|
-
roleName: string;
|
|
562
|
-
placeId?: string;
|
|
563
|
-
placeName?: string;
|
|
564
|
-
softwares: number[];
|
|
565
|
-
functionalities: string[];
|
|
566
|
-
isQualitfy?: boolean;
|
|
567
|
-
isMetroex?: boolean;
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* Resultado do hook useModuleAccess
|
|
571
|
-
*/
|
|
572
|
-
export interface ModuleAccessResult {
|
|
573
|
-
/** Se o usuário tem acesso ao módulo configurado/especificado */
|
|
574
|
-
hasAccess: boolean;
|
|
575
|
-
/** Se os dados ainda estão carregando */
|
|
576
|
-
isLoading: boolean;
|
|
577
|
-
/** Role do usuário na associação atual */
|
|
578
|
-
role: {
|
|
579
|
-
id: string;
|
|
580
|
-
name: string;
|
|
581
|
-
} | null;
|
|
582
|
-
/** Associação completa do usuário para a unidade atual */
|
|
583
|
-
association: UserAssociation | null;
|
|
584
|
-
/** Função para verificar acesso a outro(s) módulo(s) */
|
|
585
|
-
hasAccessTo: (alias: string | string[]) => boolean;
|
|
586
|
-
}
|
|
587
|
-
export interface ApiResponse<T = unknown> {
|
|
588
|
-
data: T;
|
|
589
|
-
success: boolean;
|
|
590
|
-
message?: string;
|
|
591
|
-
error?: string;
|
|
592
|
-
}
|
|
593
|
-
export interface ValidationResult {
|
|
594
|
-
isValid: boolean;
|
|
595
|
-
errors: string[];
|
|
596
|
-
warnings?: string[];
|
|
597
|
-
}
|
|
598
|
-
export interface NotificationConfig {
|
|
599
|
-
title: string;
|
|
600
|
-
description?: string;
|
|
601
|
-
type: 'success' | 'error' | 'warning' | 'info';
|
|
602
|
-
duration?: number;
|
|
7
|
+
parentId?: string;
|
|
8
|
+
parentName?: string;
|
|
9
|
+
subPlaces?: Place[];
|
|
603
10
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook que sinaliza quando o app está pronto para falar com a API Qualiex:
|
|
3
|
+
* autenticado, com alias, com token de acesso e (opcionalmente) com companyId resolvido.
|
|
4
|
+
*/
|
|
5
|
+
export declare function useQualiexReady(): {
|
|
6
|
+
alias: string;
|
|
7
|
+
companyId: string;
|
|
8
|
+
hasAccessToken: boolean;
|
|
9
|
+
isAuthLoading: boolean;
|
|
10
|
+
isAuthenticated: boolean;
|
|
11
|
+
isReadyForQualiex: boolean;
|
|
12
|
+
isReadyForQualiexWithCompany: boolean;
|
|
13
|
+
isWaitingCompanyId: boolean;
|
|
14
|
+
waitingReason: string;
|
|
15
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base URL da API common-v4 do Qualiex.
|
|
3
|
+
* Usa `getQualiexApiUrl()` (VITE_QUALIEX_API_URL) com fallback para produção.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getCommonBaseUrl(): string;
|
|
6
|
+
/**
|
|
7
|
+
* URL base do ident-api (serviço de identidade), derivada da common-v4 (espelha sufixos `-dev`, etc).
|
|
8
|
+
*/
|
|
9
|
+
export declare function getIdentBaseUrl(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Monta os headers padrão exigidos pelas APIs Qualiex (Authorization + un-alias).
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildQualiexHeaders(alias: string): Record<string, string>;
|
|
14
|
+
/**
|
|
15
|
+
* Fetch padronizado para a API Qualiex: injeta headers, valida resposta e
|
|
16
|
+
* faz retry automático via `QualiexErrorInterceptor` quando há 401.
|
|
17
|
+
*/
|
|
18
|
+
export declare function qualiexFetch(url: string, alias: string, options?: RequestInit): Promise<Response>;
|
|
@@ -42,4 +42,23 @@ export declare class AuthService {
|
|
|
42
42
|
* Extrai alias do access token (campo default)
|
|
43
43
|
*/
|
|
44
44
|
private static extractAliasFromAccessToken;
|
|
45
|
+
/**
|
|
46
|
+
* Detecta o alias a partir do subdomínio da URL atual.
|
|
47
|
+
*
|
|
48
|
+
* Padrões reconhecidos:
|
|
49
|
+
* - `educacao.sabergestao.com.br` → "sabergestao"
|
|
50
|
+
* - `<modulo>.<alias>.<tld>` → alias
|
|
51
|
+
* - `<alias>.qualiex.com` → alias
|
|
52
|
+
* - localhost / *.lovable.app / *.lovable.dev → null
|
|
53
|
+
*/
|
|
54
|
+
private static getSubdomainAlias;
|
|
55
|
+
/**
|
|
56
|
+
* Resolve o alias ativo seguindo prioridade:
|
|
57
|
+
* 1. Subdomínio da URL (se válido contra companies)
|
|
58
|
+
* 2. Alias do Supabase token (se válido)
|
|
59
|
+
* 3. Alias armazenado (se válido)
|
|
60
|
+
* 4. `default` do access token (se válido)
|
|
61
|
+
* 5. Primeira company
|
|
62
|
+
*/
|
|
63
|
+
private static resolveAliasFromContext;
|
|
45
64
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Componente interno (renderiza `null`) que aplica automaticamente o idioma
|
|
3
|
+
* do usuário ao i18next assim que `useModuleAccess` resolver a associação atual.
|
|
4
|
+
*
|
|
5
|
+
* - Fonte de verdade: `association.language` (vindo de `/users/{userId}/associations`).
|
|
6
|
+
* - Não persiste em `localStorage` — o React-Query já cacheia o resultado e o
|
|
7
|
+
* próximo boot refaz a chamada para revalidar.
|
|
8
|
+
* - Reage a `switchUnit`: ao trocar de unidade, useModuleAccess refaz a query
|
|
9
|
+
* e o efeito reaplica o idioma da nova associação.
|
|
10
|
+
*
|
|
11
|
+
* Para que funcione, deve ser montado dentro do `AuthProvider`, `LocaleProvider`
|
|
12
|
+
* e `ModuleProvider`. `CoreProviders` já cuida disso.
|
|
13
|
+
*/
|
|
14
|
+
export declare function LanguageBootstrap(): any;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Import this instead of importing directly from react-i18next.
|
|
6
6
|
*/
|
|
7
7
|
export { default as i18n, addAppTranslations } from './config';
|
|
8
|
+
export { LanguageBootstrap } from './LanguageBootstrap';
|
|
8
9
|
export { useTranslation } from 'react-i18next';
|
|
9
10
|
export { I18nextProvider } from 'react-i18next';
|
|
10
11
|
export { mergeTranslationFiles } from './utils';
|