forlogic-core 1.15.8 → 1.16.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/.note/memory/components/action-button-for-tables.md +23 -0
- package/.note/memory/components/alertdialog-permanent-deletion.md +47 -0
- package/.note/memory/components/baseform-custom-fields.md +60 -0
- package/.note/memory/components/baseform-usage.md +43 -0
- package/.note/memory/components/delete-confirmation-dialog.md +48 -0
- package/.note/memory/components/dialog-sizes-and-structure.md +31 -0
- package/.note/memory/components/dialog-variants.md +44 -0
- package/.note/memory/components/pagination-usage.md +28 -0
- package/.note/memory/documentation/consolidated-components-registry.md +18 -0
- package/.note/memory/features/crud-standardized-config-props.md +3 -0
- package/.note/memory/features/import/attachment-strategy.md +18 -0
- package/.note/memory/patterns/body-content-scroll-usage.md +59 -0
- package/.note/memory/patterns/crud-action-bar-3-zone-layout.md +3 -0
- package/.note/memory/patterns/crud-bulk-actions-dropdown-standard.md +3 -0
- package/.note/memory/patterns/crud-toolbar-layout.md +26 -0
- package/.note/memory/patterns/dialog-body-scroll-pattern.md +27 -0
- package/.note/memory/patterns/single-scroll-pattern.md +22 -0
- package/.note/memory/patterns/spa-navigation-pattern.md +19 -0
- package/.note/memory/rules/no-auto-index-rule.md +20 -0
- package/.note/memory/rules/no-delete-policy-rule.md +23 -0
- package/.note/memory/rules/no-env-modification-rule.md +19 -0
- package/.note/memory/rules/supabase-schema-rule.md +19 -0
- package/README.md +8 -4
- package/dist/README.md +7 -4
- package/dist/assets/AccordionDoc-BnfxyOi9.js +31 -0
- package/dist/assets/ActionButtonDoc-b4F_J8gn.js +47 -0
- package/dist/assets/AlertDoc-PkiHguSJ.js +37 -0
- package/dist/assets/AppHeaderDoc-CsFMZGV0.js +67 -0
- package/dist/assets/AppSidebarDoc-Bg71N-zq.js +196 -0
- package/dist/assets/AuthDoc-DDm57y_J.js +192 -0
- package/dist/assets/AvatarDoc-C6wiZIZR.js +11 -0
- package/dist/assets/BadgeDoc-Bsg7cfm0.js +36 -0
- package/dist/assets/BaseFormDoc-DeIlV273.js +169 -0
- package/dist/assets/BodyContentDoc-Q3DGvyN9.js +83 -0
- package/dist/assets/BreadcrumbDoc-ChsVFjMF.js +75 -0
- package/dist/assets/ButtonDoc-C7Q31Bh3.js +41 -0
- package/dist/assets/ButtonGroupDoc-Bn5vhjBq.js +7 -0
- package/dist/assets/CalendarDoc-iVjNyxyr.js +81 -0
- package/dist/assets/CardDoc-D511dll7.js +49 -0
- package/dist/assets/ChartDoc-CQyYOEHL.js +111 -0
- package/dist/assets/CheckboxDoc-Cjsy4XAq.js +55 -0
- package/dist/assets/ColorPickerDoc-hnYJUWpF.js +10 -0
- package/dist/assets/ColorsFoundationDoc-B8Z4tAyZ.js +13 -0
- package/dist/assets/ComboTreeDoc-ChEbW4a3.js +21 -0
- package/dist/assets/ComboboxDoc-CHWeGE_F.js +134 -0
- package/dist/assets/ComponentDocTemplate-BtOCnlM2.js +1 -0
- package/dist/assets/ContextMenuDoc-C3mFO_Yx.js +182 -0
- package/dist/assets/ContextsDoc-ChEbQxom.js +184 -0
- package/dist/assets/CreateCrudPageDoc-C9tXisCF.js +106 -0
- package/dist/assets/CrudActionBarDoc-Cp1L4gpO.js +112 -0
- package/dist/assets/CrudGridDoc-D-kSFBAQ.js +85 -0
- package/dist/assets/CrudOverviewDoc-CeLBwg-B.js +14 -0
- package/dist/assets/CrudPrimitivesDoc-B2u1vZog.js +164 -0
- package/dist/assets/CrudTableDoc-CvV-II_X.js +95 -0
- package/dist/assets/DataListDoc-BLRii0jB.js +13 -0
- package/dist/assets/DesignSystemHome-TE0Ubaup.js +1 -0
- package/dist/assets/DialogDoc--LC5Jvat.js +981 -0
- package/dist/assets/DropdownMenuDoc-oPlEriRY.js +175 -0
- package/dist/assets/EmptyStateDoc-rNqfWKok.js +35 -0
- package/dist/assets/EnvironmentsDoc-CT7l5s2u.js +96 -0
- package/dist/assets/ErrorBoundaryDoc-rPHOUygA.js +111 -0
- package/dist/assets/ExampleCard-DfuMYM6E.js +1 -0
- package/dist/assets/FormDoc-B0L_QaCT.js +81 -0
- package/dist/assets/FoundationOverview-Dbb8rBsU.js +1 -0
- package/dist/assets/GridDoc-ifcGA2Yw.js +28 -0
- package/dist/assets/HooksDoc-CUOT_3Du.js +665 -0
- package/dist/assets/HoverCardDoc-CdTU2QkI.js +31 -0
- package/dist/assets/I18nDoc-CMEvFqsz.js +232 -0
- package/dist/assets/IconPickerDoc-DF9hEwnJ.js +10 -0
- package/dist/assets/IconsFoundationDoc-D4Y0wKbm.js +33 -0
- package/dist/assets/InputDoc-d_IL4dsq.js +211 -0
- package/dist/assets/LabelDoc-Dr64ISiJ.js +42 -0
- package/dist/assets/LeadershipDoc-BnrTuaeV.js +416 -0
- package/dist/assets/MediaDoc-CLuVprAr.js +459 -0
- package/dist/assets/MenubarDoc-CW7L4QJ4.js +165 -0
- package/dist/assets/ModulesDialogDoc-CUb_g4X-.js +71 -0
- package/dist/assets/NavigationMenuDoc-Csc0U6bV.js +116 -0
- package/dist/assets/OnboardingDialogDoc-3RtjNH1O.js +55 -0
- package/dist/assets/PaginationDoc-BGurD4xQ.js +27 -0
- package/dist/assets/PaginationDoc-DqFyou6O.js +98 -0
- package/dist/assets/PlacesDoc-Dyx8gsqb.js +226 -0
- package/dist/assets/PopoverDoc-DHF-ItUX.js +64 -0
- package/dist/assets/ProgressDoc-DXKV-fkI.js +29 -0
- package/dist/assets/QualiexUserFieldDoc-BbP7w-Pu.js +149 -0
- package/dist/assets/RadioGroupDoc-D845uweM.js +57 -0
- package/dist/assets/RadiusDoc-vN4tTsay.js +7 -0
- package/dist/assets/RequiredFieldsCounterDoc-TzR9r-U9.js +58 -0
- package/dist/assets/ResizableDoc-Bkfz_25O.js +104 -0
- package/dist/assets/RichTextEditorDoc-BUQrg7M8.js +24 -0
- package/dist/assets/ScrollAreaDoc-B6ODYHMX.js +28 -0
- package/dist/assets/SecurityDoc-Chbt6w1s.js +204 -0
- package/dist/assets/SelectDoc-BhcpBIAO.js +80 -0
- package/dist/assets/SeparatorDoc-C3fhatb0.js +4 -0
- package/dist/assets/ServicesDoc-_uao-HA_.js +308 -0
- package/dist/assets/ShadowsDoc-DpkO_TZQ.js +9 -0
- package/dist/assets/SignDoc-BJtnoT6I.js +66 -0
- package/dist/assets/SkeletonDoc-BZS07PJh.js +54 -0
- package/dist/assets/SliderDoc-D2ApV3XT.js +41 -0
- package/dist/assets/SpacingDoc-PNrU24B2.js +12 -0
- package/dist/assets/SplitButtonDoc-D5tUF2Ja.js +53 -0
- package/dist/assets/StepSelectorDoc-Cj0ALYar.js +41 -0
- package/dist/assets/SwitchDoc-DtsT8oh_.js +56 -0
- package/dist/assets/TableDoc-BC-jQnXu.js +128 -0
- package/dist/assets/TableOfContents-DBMJMbI4.js +1 -0
- package/dist/assets/TabsDoc-DtXJ0xY5.js +42 -0
- package/dist/assets/TextareaDoc-nuW5tqBQ.js +46 -0
- package/dist/assets/ToastDoc-D1aX5zda.js +157 -0
- package/dist/assets/ToggleDoc-ILass4CS.js +51 -0
- package/dist/assets/TooltipDoc-lPbdWe_9.js +58 -0
- package/dist/assets/TruncatedCellDoc-DOAzbF2F.js +12 -0
- package/dist/assets/TypographyFoundationDoc-3ZD-rQZw.js +7 -0
- package/dist/assets/UtilitiesDoc-D7lkYhuz.js +145 -0
- package/dist/assets/blocks-Jy49RoqJ.js +1 -0
- package/dist/assets/calendar-days-Cvf2zLJl.js +1 -0
- package/dist/assets/circle-plus-MnG9kjyq.js +1 -0
- package/dist/assets/circle-x-B9ouupla.js +1 -0
- package/dist/assets/crown-BweN5jpI.js +1 -0
- package/dist/assets/date-picker-ttyYeYvC.js +1 -0
- package/dist/assets/disabled-menu-item-WlpPOqxg.js +1 -0
- package/dist/assets/drawer-DvU6_eK5.js +3 -0
- package/dist/assets/file-pen-line-C0VV-QjF.js +1 -0
- package/dist/assets/git-branch-DCjGGwvF.js +1 -0
- package/dist/assets/globe-BdFDFP_k.js +1 -0
- package/dist/assets/grip-vertical-CgXp0oI-.js +1 -0
- package/dist/assets/hash-BAYi_wfk.js +1 -0
- package/dist/assets/index-BtX5DZqb.js +310 -0
- package/dist/assets/index-C1So5Sai.css +1 -0
- package/dist/assets/life-buoy-BydIgTyJ.js +1 -0
- package/dist/assets/lucide-react-ZIMhRYmb.js +1 -0
- package/dist/assets/monitor-B6txWJPg.js +1 -0
- package/dist/assets/package-DNe3FsCh.js +1 -0
- package/dist/assets/pen-CzTmQ16z.js +1 -0
- package/dist/assets/pin-CJJgLEBz.js +1 -0
- package/dist/assets/radio-group-Btv_BY60.js +1 -0
- package/dist/assets/server-XQDXtrjm.js +1 -0
- package/dist/assets/share-2-Dz_89MJb.js +1 -0
- package/dist/assets/step-selector-D0_Y1dow.js +1 -0
- package/dist/assets/text-align-start-WsHo7CNJ.js +1 -0
- package/dist/assets/trash-CeK-mWnM.js +1 -0
- package/dist/assets/useMockCrud-RV9z9n5x.js +1 -0
- package/dist/assets/user-check-CrbWcnPN.js +1 -0
- package/dist/assets/user-plus-Dce9DbqQ.js +1 -0
- package/dist/auth/services/TokenManager.d.ts +5 -0
- package/dist/auth/services/TokenRegenerationService.d.ts +5 -3
- package/dist/auth/services/TokenService.d.ts +0 -4
- package/dist/bin/pull-docs.js +87 -64
- package/dist/components/modules/ModuleAccessGuard.d.ts +16 -0
- package/dist/components/modules/index.d.ts +2 -0
- package/dist/components/ui/chart.d.ts +1 -1
- package/dist/components/ui/color-picker.d.ts +4 -0
- package/dist/components/ui/combo-tree.d.ts +70 -0
- package/dist/components/ui/combobox.d.ts +1 -0
- package/dist/components/ui/dialog.d.ts +8 -0
- package/dist/components/ui/icon-picker.d.ts +2 -0
- package/dist/components/ui/input-group.d.ts +1 -1
- package/dist/components/ui/resizable.d.ts +1 -1
- package/dist/config/environments.d.ts +12 -0
- package/dist/config/index.d.ts +23 -9
- package/dist/contexts/ModuleContext.d.ts +34 -0
- package/dist/crud/components/SelectionCheckbox.d.ts +9 -0
- package/dist/crud/generateCrudConfig.d.ts +2 -2
- package/dist/docs/KNOWLEDGE.md +206 -0
- package/dist/exports/ui.d.ts +1 -0
- package/dist/hooks/useMediaQuery.d.ts +14 -0
- package/dist/hooks/useModuleAccess.d.ts +60 -0
- package/dist/hooks/usePageTitle.d.ts +7 -1
- package/dist/index.css +2 -2
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.html +16 -11
- package/dist/index.js +1 -1
- package/dist/leadership/hooks/useLeadershipMutations.d.ts +0 -1
- package/dist/media/hooks/useMediaUpload.d.ts +0 -1
- package/dist/media/utils/imageHelpers.d.ts +1 -1
- package/dist/places/services/PlaceService.d.ts +1 -1
- package/dist/providers/CoreProviders.d.ts +20 -4
- package/dist/qualiex/services/qualiexApi.d.ts +22 -4
- package/dist/services/QualiexEnrichmentService.d.ts +0 -12
- package/dist/setup.d.ts +2 -0
- package/dist/sign/services/signService.d.ts +0 -6
- package/dist/types.d.ts +59 -10
- package/dist/utils/index.d.ts +2 -2
- package/docs/DESIGN_SYSTEM.md +12181 -0
- package/docs/KNOWLEDGE.md +206 -0
- package/docs/PUBLISH.md +168 -0
- package/package.json +16 -18
- package/dist/assets/index-D0RTIFH3.css +0 -1
- package/dist/assets/index-YMQXWoDk.js +0 -9868
- package/dist/auth/utils/AuthUtils.d.ts +0 -4
- package/dist/i18n/DatabaseBackend.d.ts +0 -9
- package/dist/i18n/components/TranslationLoader.d.ts +0 -10
- package/dist/services/TranslationService.d.ts +0 -20
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Memory: components/action-button-for-tables
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
Uso de `ActionButton` é **OBRIGATÓRIO** para menus de ação em linhas de tabela.
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
// ❌ PROIBIDO - botão genérico com ícone manual
|
|
8
|
+
<Button variant="ghost" size="icon">
|
|
9
|
+
<MoreHorizontal className="h-4 w-4" />
|
|
10
|
+
</Button>
|
|
11
|
+
|
|
12
|
+
// ✅ CORRETO - ActionButton padronizado
|
|
13
|
+
import { ActionButton } from 'forlogic-core';
|
|
14
|
+
|
|
15
|
+
<ActionButton
|
|
16
|
+
items={[
|
|
17
|
+
{ label: 'Editar', icon: Edit, onClick: handleEdit },
|
|
18
|
+
{ label: 'Excluir', icon: Trash, onClick: handleDelete, variant: 'destructive' }
|
|
19
|
+
]}
|
|
20
|
+
/>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Motivo**: Garante mesma estética e comportamento em todas as tabelas do sistema.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Memory: components/alertdialog-permanent-deletion
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
AlertDialog é usado **apenas** para exclusões permanentes que requerem digitação de confirmação:
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
<AlertDialog open={open} onOpenChange={setOpen}>
|
|
8
|
+
<AlertDialogContent>
|
|
9
|
+
<AlertDialogHeader className="border-b pb-4">
|
|
10
|
+
<AlertDialogTitle className="text-center">
|
|
11
|
+
Exclusão Permanente
|
|
12
|
+
</AlertDialogTitle>
|
|
13
|
+
</AlertDialogHeader>
|
|
14
|
+
|
|
15
|
+
<div className="py-4 space-y-4">
|
|
16
|
+
<div className="flex justify-center">
|
|
17
|
+
<AlertTriangle className="h-12 w-12 text-destructive" />
|
|
18
|
+
</div>
|
|
19
|
+
<AlertDialogDescription className="text-center">
|
|
20
|
+
Esta ação é irreversível. Digite <strong>EXCLUIR</strong> para confirmar.
|
|
21
|
+
</AlertDialogDescription>
|
|
22
|
+
<Input
|
|
23
|
+
value={confirmation}
|
|
24
|
+
onChange={(e) => setConfirmation(e.target.value)}
|
|
25
|
+
placeholder="Digite EXCLUIR"
|
|
26
|
+
className="text-center"
|
|
27
|
+
/>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<AlertDialogFooter>
|
|
31
|
+
<AlertDialogCancel>Cancelar</AlertDialogCancel>
|
|
32
|
+
<AlertDialogAction
|
|
33
|
+
disabled={confirmation !== 'EXCLUIR'}
|
|
34
|
+
onClick={handlePermanentDelete}
|
|
35
|
+
className="bg-destructive hover:bg-destructive/90"
|
|
36
|
+
>
|
|
37
|
+
Excluir Permanentemente
|
|
38
|
+
</AlertDialogAction>
|
|
39
|
+
</AlertDialogFooter>
|
|
40
|
+
</AlertDialogContent>
|
|
41
|
+
</AlertDialog>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Quando usar:**
|
|
45
|
+
- ✅ Exclusão de dados sem possibilidade de recuperação
|
|
46
|
+
- ✅ Ações destrutivas em massa críticas
|
|
47
|
+
- ❌ NÃO usar para soft deletes (usar Dialog padrão)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Memory: components/baseform-custom-fields
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
Campos customizados no BaseForm usam `type: 'custom'` com `component` ou `render`:
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
// Opção 1: Componente externo
|
|
8
|
+
{
|
|
9
|
+
name: 'module_id',
|
|
10
|
+
label: 'Módulo',
|
|
11
|
+
type: 'custom',
|
|
12
|
+
required: true,
|
|
13
|
+
component: ModuleCombobox,
|
|
14
|
+
componentProps: {
|
|
15
|
+
placeholder: 'Selecione...',
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Opção 2: Props dinâmicas baseadas em formData
|
|
20
|
+
{
|
|
21
|
+
name: 'file',
|
|
22
|
+
label: 'Arquivo',
|
|
23
|
+
type: 'custom',
|
|
24
|
+
component: FileUpload,
|
|
25
|
+
componentProps: (formData) => ({
|
|
26
|
+
required: !formData?.id, // Obrigatório só no cadastro
|
|
27
|
+
accept: '.pdf,.doc',
|
|
28
|
+
}),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Opção 3: Render function inline
|
|
32
|
+
{
|
|
33
|
+
name: 'priority',
|
|
34
|
+
label: 'Prioridade',
|
|
35
|
+
type: 'custom',
|
|
36
|
+
render: ({ value, onChange, error }) => (
|
|
37
|
+
<div className="flex gap-2">
|
|
38
|
+
{['low', 'medium', 'high'].map(p => (
|
|
39
|
+
<Button
|
|
40
|
+
key={p}
|
|
41
|
+
variant={value === p ? 'default' : 'outline'}
|
|
42
|
+
onClick={() => onChange(p)}
|
|
43
|
+
>
|
|
44
|
+
{p}
|
|
45
|
+
</Button>
|
|
46
|
+
))}
|
|
47
|
+
</div>
|
|
48
|
+
),
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Interface do componente customizado:**
|
|
53
|
+
```tsx
|
|
54
|
+
interface CustomFieldProps {
|
|
55
|
+
value: any;
|
|
56
|
+
onChange: (value: any) => void;
|
|
57
|
+
error?: string;
|
|
58
|
+
disabled?: boolean;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Memory: components/baseform-usage
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
BaseForm é o formulário dinâmico do sistema CRUD, configurado via `sections` e `fields`.
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
import BaseForm from 'forlogic-core/crud/components/BaseForm';
|
|
8
|
+
|
|
9
|
+
const sections: FormSection[] = [
|
|
10
|
+
{
|
|
11
|
+
id: 'basic',
|
|
12
|
+
title: 'Informações Básicas',
|
|
13
|
+
fields: [
|
|
14
|
+
{ name: 'title', label: 'Título', type: 'text', required: true },
|
|
15
|
+
{ name: 'email', label: 'E-mail', type: 'email' },
|
|
16
|
+
{ name: 'is_active', label: 'Ativo', type: 'switch' },
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
<BaseForm
|
|
22
|
+
title="Novo Item"
|
|
23
|
+
sections={sections}
|
|
24
|
+
initialData={data}
|
|
25
|
+
open={isOpen}
|
|
26
|
+
onSubmit={handleSubmit}
|
|
27
|
+
onCancel={() => setIsOpen(false)}
|
|
28
|
+
/>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Tipos de campo suportados:**
|
|
32
|
+
`text`, `email`, `password`, `number`, `textarea`, `select`, `multiselect`, `date`, `datetime-local`, `switch`, `checkbox`, `color`, `color-picker`, `icon-picker`, `user-select`, `custom`
|
|
33
|
+
|
|
34
|
+
**Grupos de campos:**
|
|
35
|
+
```tsx
|
|
36
|
+
{
|
|
37
|
+
name: 'row1',
|
|
38
|
+
type: 'group',
|
|
39
|
+
layout: 'horizontal', // ou 'vertical'
|
|
40
|
+
wrapperClassName: 'col-span-full',
|
|
41
|
+
fields: [...]
|
|
42
|
+
}
|
|
43
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Memory: components/delete-confirmation-dialog
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
Dialog de exclusão segue padrão visual específico (NÃO usar AlertDialog para deleções simples):
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
<Dialog open={open} onOpenChange={setOpen}>
|
|
8
|
+
<DialogContent size="sm" className="bg-white">
|
|
9
|
+
<DialogHeader showSeparator>
|
|
10
|
+
<DialogTitle className="sr-only">Confirmação</DialogTitle>
|
|
11
|
+
</DialogHeader>
|
|
12
|
+
|
|
13
|
+
{/* Conteúdo centralizado */}
|
|
14
|
+
<div className="flex flex-col items-center text-center space-y-3 py-4">
|
|
15
|
+
{/* Ícone de alerta */}
|
|
16
|
+
<div className="w-12 h-12 rounded-full bg-destructive/10 flex items-center justify-center">
|
|
17
|
+
<AlertTriangle className="h-6 w-6 text-destructive" />
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
{/* Título */}
|
|
21
|
+
<h3 className="text-lg font-semibold">Tem certeza?</h3>
|
|
22
|
+
|
|
23
|
+
{/* Mensagem em duas linhas */}
|
|
24
|
+
<p className="text-sm text-muted-foreground">
|
|
25
|
+
Você está prestes a excluir este registro.<br />
|
|
26
|
+
Esta ação não pode ser desfeita.
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
{/* Botões centralizados */}
|
|
31
|
+
<DialogFooter className="justify-center gap-2 mt-6">
|
|
32
|
+
<Button variant="outline" onClick={() => setOpen(false)}>
|
|
33
|
+
Cancelar
|
|
34
|
+
</Button>
|
|
35
|
+
<Button variant="destructive" onClick={handleDelete}>
|
|
36
|
+
Sim, excluir
|
|
37
|
+
</Button>
|
|
38
|
+
</DialogFooter>
|
|
39
|
+
</DialogContent>
|
|
40
|
+
</Dialog>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Regras:**
|
|
44
|
+
- Usar `size="sm"` (~420px quadrado)
|
|
45
|
+
- Background branco (`bg-white`)
|
|
46
|
+
- Ícone AlertTriangle com `bg-destructive/10`
|
|
47
|
+
- Botões lado a lado, centralizados
|
|
48
|
+
- Texto fixo em português
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Memory: components/dialog-sizes-and-structure
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
Dialog possui 3 tamanhos opcionais (sem default) e estrutura obrigatória:
|
|
5
|
+
|
|
6
|
+
| Size | Width | MaxHeight | Uso |
|
|
7
|
+
|------|-------|-----------|-----|
|
|
8
|
+
| (nenhum) | Auto (className controla) | Auto | Quando classes Tailwind definem o tamanho |
|
|
9
|
+
| `sm` | 30vw (320-480px) | 320px | Confirmações rápidas |
|
|
10
|
+
| `md` | 50vw (480-720px) | 70vh | Formulários padrão |
|
|
11
|
+
| `lg` | 85vw (720-1440px) | 900px | Tabelas, conteúdo extenso |
|
|
12
|
+
|
|
13
|
+
**Regra de prioridade:** Quando `size` é informado, inline styles são aplicados e vencem sobre className. Sem `size`, className controla livremente.
|
|
14
|
+
|
|
15
|
+
**Estrutura obrigatória:**
|
|
16
|
+
```tsx
|
|
17
|
+
<DialogContent size="md">
|
|
18
|
+
<DialogHeader showSeparator>
|
|
19
|
+
<DialogTitle>Título</DialogTitle>
|
|
20
|
+
</DialogHeader>
|
|
21
|
+
<DialogBody>
|
|
22
|
+
{/* Conteúdo aqui */}
|
|
23
|
+
</DialogBody>
|
|
24
|
+
<DialogFooter>...</DialogFooter>
|
|
25
|
+
</DialogContent>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Regras:**
|
|
29
|
+
- `showSeparator` no DialogHeader para linha divisória
|
|
30
|
+
- DialogBody é obrigatório para scroll interno
|
|
31
|
+
- `size` é opcional — sem ele, classes Tailwind no className controlam o tamanho
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Memory: components/dialog-variants
|
|
2
|
+
Updated: 2026-02-26
|
|
3
|
+
|
|
4
|
+
## Variantes Semânticas do Dialog
|
|
5
|
+
|
|
6
|
+
O `DialogContent` possui uma prop `variant` que controla o comportamento de fechamento:
|
|
7
|
+
|
|
8
|
+
### Variantes
|
|
9
|
+
|
|
10
|
+
| Variante | Clique externo | ESC | Botão X | Uso |
|
|
11
|
+
|----------|---------------|-----|---------|-----|
|
|
12
|
+
| `informative` (padrão) | Fecha | Fecha | Fecha | Avisos, leitura |
|
|
13
|
+
| `form` | Bloqueado | Fecha* | Fecha* | Formulários, edições |
|
|
14
|
+
| `destructive` | Bloqueado | Bloqueado | Oculto | Exclusões, ações irreversíveis |
|
|
15
|
+
|
|
16
|
+
\* Com `isDirty={true}`, exibe `window.confirm` antes de fechar.
|
|
17
|
+
|
|
18
|
+
### Props
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
interface DialogContentProps {
|
|
22
|
+
variant?: 'informative' | 'form' | 'destructive'; // default: 'informative'
|
|
23
|
+
isDirty?: boolean; // para variant='form', confirmação antes de fechar
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Padrão de uso
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
// Formulários
|
|
31
|
+
<DialogContent variant="form" isDirty={form.formState.isDirty}>
|
|
32
|
+
|
|
33
|
+
// Exclusões
|
|
34
|
+
<DialogContent variant="destructive" size="sm">
|
|
35
|
+
|
|
36
|
+
// Informativos (comportamento padrão, pode omitir variant)
|
|
37
|
+
<DialogContent variant="informative">
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Regras
|
|
41
|
+
- Default é `'informative'` para compatibilidade com dialogs existentes
|
|
42
|
+
- `destructive` oculta o botão X — fechamento apenas por botões no DialogFooter
|
|
43
|
+
- `form` com `isDirty` usa `window.confirm` nativo para confirmação
|
|
44
|
+
- Tipos exportados: `DialogVariant`, `DialogSize`, `DialogContentProps`
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Memory: components/pagination-usage
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
**SEMPRE** usar `Pagination` ou `CrudPrimitivePagination` da lib. NUNCA implementar manualmente.
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
// ❌ PROIBIDO - paginação manual
|
|
8
|
+
<div className="flex gap-2">
|
|
9
|
+
<Button onClick={() => setPage(p => p - 1)}>Anterior</Button>
|
|
10
|
+
<span>Página {page}</span>
|
|
11
|
+
<Button onClick={() => setPage(p => p + 1)}>Próxima</Button>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
// ✅ CORRETO - componente padronizado
|
|
15
|
+
import { CrudPrimitivePagination } from 'forlogic-core';
|
|
16
|
+
|
|
17
|
+
<CrudPrimitivePagination
|
|
18
|
+
currentPage={page}
|
|
19
|
+
totalPages={totalPages}
|
|
20
|
+
pageSize={pageSize}
|
|
21
|
+
totalItems={total}
|
|
22
|
+
onPageChange={setPage}
|
|
23
|
+
onPageSizeChange={setPageSize}
|
|
24
|
+
variant="full"
|
|
25
|
+
/>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Obrigatório**: `variant="full"` inclui seletor de itens por página e "X-Y de Z itens".
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Memory: documentation/consolidated-components-registry
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
Design System maintains a Consolidated Components Registry tracking components documented together under single documentation entries for reusability reference:
|
|
5
|
+
|
|
6
|
+
- **Breadcrumb** (documents Breadcrumb and PageBreadcrumb)
|
|
7
|
+
- **Calendar & Date Picker** (documents Calendar and DatePicker)
|
|
8
|
+
- **Combobox** (documents Combobox with Command used internally)
|
|
9
|
+
- **Toggle & Group** (documents Toggle and ToggleGroup)
|
|
10
|
+
- **Skeleton** (documents base Skeleton and all skeleton variants)
|
|
11
|
+
- **AppSidebar** (documents AppSidebar, Sidebar base component, SidebarProvider, SidebarMenu*, Collapsible integration)
|
|
12
|
+
- **Accordion** (documents Accordion and Collapsible)
|
|
13
|
+
- **Input** (documents Input, InputGroup, InputGroupAddon, InputGroupButton)
|
|
14
|
+
- **Grid & Stack** (documents Grid and Stack layout components)
|
|
15
|
+
- **Dialog** (documents Dialog, AlertDialog, Sheet positional variants, Drawer)
|
|
16
|
+
- **Tabs** (documents Tabs and TabPageLayout)
|
|
17
|
+
|
|
18
|
+
This registry must be checked before creating new documentation to avoid duplicates. The Sidebar base component from Shadcn is documented as a subsection within AppSidebarDoc for users who need to create custom sidebars outside the AppLayout context.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Memory: features/crud-standardized-config-props
|
|
2
|
+
|
|
3
|
+
A interface CrudPageConfig foi estendida para padronizar a experiência do usuário (UX) em todos os CRUDs (createCrudPage, CrudTable, CrudGrid). As novas propriedades incluem: showNewButton (default: true), showSearch (default: true), showBulkActions (alias para enableBulkActions), showActionBar (default: true, substituindo hideActionBar), newButtonLabel (para customizar o texto do botão de criação) e searchPlaceholder. Esta padronização garante que todos os CRUDs ofereçam as mesmas capacidades de busca, criação e ações em lote de forma consistente.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Memory: features/import/attachment-strategy
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
O sistema de anexos usa upload direto ao Azure Blob Storage (sem staging). O .zip contém pastas nomeadas pelo código do registro (ex: `OC-001/foto.pdf`). Cada arquivo recebe um `id_file_revision` de 8 caracteres alfanuméricos (`crypto.randomUUID().slice(0,8)`) gerado no front-end. O arquivo é enviado ao container `un{id_company_padded_5}` com nome `{id_file_revision}.{ext}`. Esse mesmo ID é incluído no CSV como coluna `id_file_revision` para que a API grave no banco com a mesma referência. Metadados (nome, extensão, tamanho, usuário, revision) são injetados automaticamente nas linhas do CSV via campos `data_type: 'file'` e `'file_metadata'`. A Edge Function `azure-blob-upload` aceita campo `container` opcional no FormData.
|
|
5
|
+
|
|
6
|
+
## Templates de anexo (attachment-only)
|
|
7
|
+
|
|
8
|
+
Quando todos os campos ativos do template são `data_type: 'file'` ou `'file_metadata'`, o sistema detecta automaticamente como "template de anexo". Nesse modo:
|
|
9
|
+
- O .zip **não precisa conter xlsx** — apenas pastas com arquivos
|
|
10
|
+
- O código do registro é extraído do **diretório pai imediato** do arquivo (último nível): `dir1/dir2/file.txt → "dir2"`
|
|
11
|
+
- As linhas do CSV são geradas automaticamente a partir dos metadados dos arquivos
|
|
12
|
+
- O botão "Baixar template" é substituído por "Gerenciar template"
|
|
13
|
+
- O dropzone aceita apenas `.zip`
|
|
14
|
+
- Não há fetch de lookups nem validação de colunas
|
|
15
|
+
- Função `executeAttachmentOnlyImport` no `importHelpers.ts` orquestra o fluxo completo
|
|
16
|
+
- Função `buildRowsFromAttachments` no `attachmentUploadService.ts` gera as linhas
|
|
17
|
+
- Função `extractZipAttachmentsOnly` no `zipExtractorService.ts` extrai sem exigir xlsx
|
|
18
|
+
- Detecção via `isAttachmentOnlyTemplate` no `attachmentUploadService.ts`
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Memory: patterns/body-content-scroll-usage
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
## Quando Usar Cada Abordagem
|
|
5
|
+
|
|
6
|
+
| Cenário | Componente | Classes |
|
|
7
|
+
|---------|------------|---------|
|
|
8
|
+
| **Página nova (Design System)** | `BodyContent` + `ContentContainer` | Padrão, sem classes extras |
|
|
9
|
+
| **Página legada (design próprio)** | `BodyContent` | `className="bg-transparent p-0"` |
|
|
10
|
+
| **Módulo customizado** | `div` simples | `className="h-full overflow-y-auto"` |
|
|
11
|
+
|
|
12
|
+
## Exemplos
|
|
13
|
+
|
|
14
|
+
### ✅ Página Nova (Design System Completo)
|
|
15
|
+
```tsx
|
|
16
|
+
import { BodyContent, ContentContainer } from 'forlogic-core';
|
|
17
|
+
|
|
18
|
+
<BodyContent breadcrumbs={[{ label: 'Home', href: '/' }, { label: 'Página' }]}>
|
|
19
|
+
<ContentContainer title="Título" subtitle="Descrição">
|
|
20
|
+
{/* Conteúdo */}
|
|
21
|
+
</ContentContainer>
|
|
22
|
+
</BodyContent>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### ✅ Página Legada (Preservar Design Original)
|
|
26
|
+
```tsx
|
|
27
|
+
import { BodyContent } from 'forlogic-core';
|
|
28
|
+
|
|
29
|
+
<BodyContent className="bg-transparent p-0">
|
|
30
|
+
{/* Conteúdo original mantido sem alterações */}
|
|
31
|
+
<div className="p-6">
|
|
32
|
+
<h1>Título Original</h1>
|
|
33
|
+
{/* ... */}
|
|
34
|
+
</div>
|
|
35
|
+
</BodyContent>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### ✅ Container Mínimo (Sem BodyContent)
|
|
39
|
+
```tsx
|
|
40
|
+
// Apenas scroll, sem dependência do forlogic-core
|
|
41
|
+
<div className="h-full overflow-y-auto">
|
|
42
|
+
{/* Conteúdo original */}
|
|
43
|
+
</div>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## ❌ Erro Comum
|
|
47
|
+
```tsx
|
|
48
|
+
// ERRADO: ContentContainer em página com design próprio
|
|
49
|
+
<BodyContent>
|
|
50
|
+
<ContentContainer>
|
|
51
|
+
{/* Resultado: fundo branco, bordas, padding extra indesejados */}
|
|
52
|
+
</ContentContainer>
|
|
53
|
+
</BodyContent>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Regra de Ouro
|
|
57
|
+
- `ContentContainer` adiciona: fundo branco, borda, sombra, padding
|
|
58
|
+
- Use apenas quando o design da página DEVE seguir esse padrão
|
|
59
|
+
- Para páginas legadas: `BodyContent className="bg-transparent p-0"`
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Memory: patterns/crud-action-bar-3-zone-layout
|
|
2
|
+
|
|
3
|
+
O CrudActionBar (lib/crud/components/CrudActionBar.tsx) é o componente compartilhado que unifica a barra de ações de todos os CRUDs do sistema. Ele implementa um layout rígido de 3 zonas: ESQUERDA (Botão Novo + Dropdown de Ações em Lote), CENTRO (Barra de busca centralizada) e DIREITA (Filtros customizados + Toggle de visualização). Este componente substitui as implementações locais de barra de ferramentas no CrudTable, CrudGrid e createCrudPage, garantindo que a barra superior tenha sempre o mesmo visual (bg-muted/50), comportamento e espaçamento, independentemente do componente de visualização de dados utilizado.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Memory: patterns/crud-bulk-actions-dropdown-standard
|
|
2
|
+
|
|
3
|
+
As ações em lote foram unificadas em um dropdown 'Ações em lote' no CrudActionBar. Este menu permanece visível se habilitado, exibindo um badge com a contagem de itens selecionados. As opções internas são desabilitadas se a seleção for zero. O componente BulkActionBar foi removido para evitar barras duplicadas e 'layout shifts'. Na CrudTable, a coluna de ações de linha não deve ter label no cabeçalho (usar apenas ícone ⋮ ou tooltip) para evitar confusão com o menu de ações em lote da toolbar.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Memory: patterns/crud-toolbar-layout
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
Toolbar CRUD segue layout obrigatório de 3 zonas:
|
|
5
|
+
|
|
6
|
+
| Zona | Posição | Conteúdo |
|
|
7
|
+
|------|---------|----------|
|
|
8
|
+
| Esquerda | `justify-start` | Botão "Novo" (ação principal) |
|
|
9
|
+
| Centro | `flex-1 max-w-md` | Campo de busca (FilterBar/Input) |
|
|
10
|
+
| Direita | `justify-end` | Botões Filtro/Ações |
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
// ✅ CORRETO
|
|
14
|
+
<div className="flex items-center gap-4">
|
|
15
|
+
<Button>Novo Item</Button>
|
|
16
|
+
<div className="flex-1 max-w-md">
|
|
17
|
+
<Input placeholder="Buscar..." />
|
|
18
|
+
</div>
|
|
19
|
+
<div className="flex gap-2">
|
|
20
|
+
<Button variant="outline">Filtrar</Button>
|
|
21
|
+
<ActionButton items={actions} />
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Regra**: Botão de criação NUNCA deve ficar isolado no cabeçalho do Card.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Memory: patterns/dialog-body-scroll-pattern
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
Conteúdo de Dialog/Sheet com scroll interno **DEVE** usar o padrão responsivo:
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
// ✅ CORRETO - padrão obrigatório
|
|
8
|
+
<div className="flex-1 min-h-0 overflow-auto py-4 px-1 -mx-1">
|
|
9
|
+
{/* Conteúdo scrollável */}
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
// ❌ ERRADO - overflow escondido, sem scroll
|
|
13
|
+
<div className="p-4">
|
|
14
|
+
{/* Conteúdo pode ser cortado */}
|
|
15
|
+
</div>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Breakdown das classes:**
|
|
19
|
+
| Classe | Função |
|
|
20
|
+
|--------|--------|
|
|
21
|
+
| `flex-1` | Expande para preencher espaço disponível |
|
|
22
|
+
| `min-h-0` | Permite shrink em flex container |
|
|
23
|
+
| `overflow-auto` | Habilita scroll quando necessário |
|
|
24
|
+
| `py-4` | Padding vertical padrão (16px) |
|
|
25
|
+
| `px-1 -mx-1` | Previne corte de focus rings |
|
|
26
|
+
|
|
27
|
+
**Aplica-se a:** Dialog, Sheet, Drawer, AlertDialog
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Memory: patterns/single-scroll-pattern
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
O padrão de Scroll Único evita barras de rolagem duplicadas na aplicação.
|
|
5
|
+
|
|
6
|
+
| Componente | Responsabilidade |
|
|
7
|
+
|------------|------------------|
|
|
8
|
+
| `AppLayout` | `overflow-hidden` - delega scroll para filhos |
|
|
9
|
+
| `BodyContent` | `h-full overflow-y-auto` - gerencia scroll da página |
|
|
10
|
+
| Custom | `h-full` + `ScrollArea` interno quando necessário |
|
|
11
|
+
|
|
12
|
+
**Regra**: Apenas UM nível da hierarquia deve ter scroll ativo.
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
// ❌ ERRADO - h-screen causa scroll duplicado
|
|
16
|
+
<div className="h-screen overflow-auto">
|
|
17
|
+
|
|
18
|
+
// ✅ CORRETO - h-full respeita container pai
|
|
19
|
+
<BodyContent>
|
|
20
|
+
<ContentContainer>...</ContentContainer>
|
|
21
|
+
</BodyContent>
|
|
22
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Memory: patterns/spa-navigation-pattern
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
Navegação SPA deve usar componentes do React Router, nunca `<a href>` ou `window.location`.
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
// ❌ ERRADO - recarrega página inteira
|
|
8
|
+
<a href="/dashboard">Dashboard</a>
|
|
9
|
+
window.location.href = '/page';
|
|
10
|
+
|
|
11
|
+
// ✅ CORRETO - navegação SPA sem reload
|
|
12
|
+
import { Link, useNavigate } from 'react-router-dom';
|
|
13
|
+
|
|
14
|
+
<Link to="/dashboard">Dashboard</Link>
|
|
15
|
+
const navigate = useNavigate();
|
|
16
|
+
navigate('/page');
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Exceção**: Links externos devem usar `<a>` com `target="_blank"` e `rel="noopener noreferrer"`.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Memory: rules/no-auto-index-rule
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
**NUNCA** criar índices automaticamente em migrations.
|
|
5
|
+
|
|
6
|
+
```sql
|
|
7
|
+
-- ❌ PROIBIDO - índice "por precaução"
|
|
8
|
+
CREATE INDEX idx_subprocess_process ON subprocesses(id_process);
|
|
9
|
+
CREATE INDEX idx_process_title ON processes(title);
|
|
10
|
+
|
|
11
|
+
-- ✅ CORRETO - criar tabela SEM índices
|
|
12
|
+
CREATE TABLE common.processes (...);
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Quando criar índices?** APENAS quando:
|
|
16
|
+
1. Solicitado explicitamente pelo usuário
|
|
17
|
+
2. Análise de performance comprovou necessidade (EXPLAIN ANALYZE)
|
|
18
|
+
3. Aprovação prévia do usuário
|
|
19
|
+
|
|
20
|
+
**Motivo**: Índices custam espaço, impactam escrita e 99% dos "preventivos" nunca são usados.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Memory: rules/no-delete-policy-rule
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
**NUNCA** criar política RLS de DELETE. Usar soft delete com UPDATE.
|
|
5
|
+
|
|
6
|
+
```sql
|
|
7
|
+
-- ❌ PROIBIDO
|
|
8
|
+
CREATE POLICY "table_delete" ON common.table
|
|
9
|
+
FOR DELETE USING (...);
|
|
10
|
+
|
|
11
|
+
-- ✅ CORRETO - adicionar coluna deleted_at
|
|
12
|
+
ALTER TABLE common.table ADD COLUMN deleted_at TIMESTAMP WITH TIME ZONE;
|
|
13
|
+
|
|
14
|
+
CREATE POLICY "table_update" ON common.table
|
|
15
|
+
FOR UPDATE USING (...) WITH CHECK (...);
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Motivo**: Soft delete preserva histórico e evita problemas de integridade referencial.
|
|
19
|
+
|
|
20
|
+
**Sintaxe RLS**:
|
|
21
|
+
- `SELECT` → usa `USING`
|
|
22
|
+
- `INSERT` → usa `WITH CHECK`
|
|
23
|
+
- `UPDATE` → usa `USING` E `WITH CHECK`
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Memory: rules/no-env-modification-rule
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
**NUNCA** modificar o arquivo `.env` sem autorização EXPLÍCITA do usuário.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
# ❌ PROIBIDO sem autorização
|
|
8
|
+
VITE_SUPABASE_URL="..."
|
|
9
|
+
VITE_QUALIEX_API_URL="..."
|
|
10
|
+
|
|
11
|
+
# ✅ CORRETO - perguntar antes
|
|
12
|
+
"Posso modificar o .env para alterar X?"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Quando modificar?** APENAS quando:
|
|
16
|
+
1. Solicitado explicitamente pelo usuário
|
|
17
|
+
2. Usuário aprovou a mudança de ambiente (dev/prod)
|
|
18
|
+
|
|
19
|
+
**Motivo**: O .env controla ambiente (dev/prod) e contém credenciais sensíveis.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Memory: rules/supabase-schema-rule
|
|
2
|
+
Updated: now
|
|
3
|
+
|
|
4
|
+
**SEMPRE** especifique o schema `common` em TODA query Supabase:
|
|
5
|
+
|
|
6
|
+
```typescript
|
|
7
|
+
// ✅ CORRETO
|
|
8
|
+
const { data } = await supabase
|
|
9
|
+
.schema('common')
|
|
10
|
+
.from('tabela')
|
|
11
|
+
.select('*');
|
|
12
|
+
|
|
13
|
+
// ❌ ERRADO - vai falhar em produção
|
|
14
|
+
const { data } = await supabase
|
|
15
|
+
.from('tabela')
|
|
16
|
+
.select('*');
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Motivo**: O projeto usa schema customizado `common`, não o `public` padrão do Supabase.
|