@hed-hog/catalog 0.0.293 → 0.0.295
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 +391 -361
- package/dist/catalog-resource.config.d.ts.map +1 -1
- package/dist/catalog-resource.config.js +51 -24
- package/dist/catalog-resource.config.js.map +1 -1
- package/dist/catalog.controller.d.ts +420 -0
- package/dist/catalog.controller.d.ts.map +1 -1
- package/dist/catalog.controller.js +98 -0
- package/dist/catalog.controller.js.map +1 -1
- package/dist/catalog.module.d.ts.map +1 -1
- package/dist/catalog.module.js +5 -1
- package/dist/catalog.module.js.map +1 -1
- package/dist/catalog.service.d.ts +216 -1
- package/dist/catalog.service.d.ts.map +1 -1
- package/dist/catalog.service.js +1121 -7
- package/dist/catalog.service.js.map +1 -1
- package/hedhog/data/catalog_attribute.yaml +202 -0
- package/hedhog/data/catalog_attribute_option.yaml +109 -0
- package/hedhog/data/catalog_category.yaml +47 -0
- package/hedhog/data/catalog_category_attribute.yaml +209 -0
- package/hedhog/data/menu.yaml +46 -12
- package/hedhog/data/role.yaml +7 -7
- package/hedhog/data/route.yaml +64 -0
- package/hedhog/frontend/app/[resource]/page.tsx.ejs +358 -0
- package/hedhog/frontend/app/_components/catalog-ai-form-assist-dialog.tsx.ejs +340 -0
- package/hedhog/frontend/app/_components/catalog-resource-form-sheet.tsx.ejs +815 -0
- package/hedhog/frontend/app/_lib/catalog-resources.tsx.ejs +504 -736
- package/hedhog/frontend/app/dashboard/page.tsx.ejs +14 -83
- package/hedhog/frontend/messages/en.json +150 -60
- package/hedhog/frontend/messages/pt.json +185 -95
- package/hedhog/table/catalog_affiliate_program.yaml +41 -41
- package/hedhog/table/catalog_attribute.yaml +22 -7
- package/hedhog/table/catalog_attribute_group.yaml +18 -18
- package/hedhog/table/catalog_attribute_option.yaml +40 -0
- package/hedhog/table/catalog_brand.yaml +34 -34
- package/hedhog/table/catalog_category.yaml +40 -0
- package/hedhog/table/catalog_category_attribute.yaml +13 -7
- package/hedhog/table/catalog_click_event.yaml +50 -50
- package/hedhog/table/catalog_comparison.yaml +3 -6
- package/hedhog/table/catalog_comparison_highlight.yaml +39 -39
- package/hedhog/table/catalog_comparison_item.yaml +30 -30
- package/hedhog/table/catalog_content_relation.yaml +42 -42
- package/hedhog/table/catalog_import_run.yaml +33 -33
- package/hedhog/table/catalog_import_source.yaml +24 -24
- package/hedhog/table/catalog_merchant.yaml +29 -29
- package/hedhog/table/catalog_offer.yaml +83 -83
- package/hedhog/table/catalog_price_history.yaml +34 -34
- package/hedhog/table/catalog_product.yaml +5 -3
- package/hedhog/table/catalog_product_attribute_value.yaml +15 -2
- package/hedhog/table/catalog_product_category.yaml +3 -3
- package/hedhog/table/catalog_product_image.yaml +34 -34
- package/hedhog/table/catalog_product_score.yaml +38 -38
- package/hedhog/table/catalog_product_site.yaml +47 -47
- package/hedhog/table/catalog_product_tag.yaml +19 -19
- package/hedhog/table/catalog_score_criterion.yaml +25 -8
- package/hedhog/table/catalog_seo_page_rule.yaml +2 -2
- package/hedhog/table/catalog_similarity_rule.yaml +19 -6
- package/hedhog/table/catalog_site.yaml +8 -0
- package/hedhog/table/catalog_site_category.yaml +3 -3
- package/package.json +7 -7
- package/src/catalog-resource.config.ts +51 -24
- package/src/catalog.controller.ts +67 -0
- package/src/catalog.module.ts +5 -1
- package/src/catalog.service.ts +1531 -6
- package/src/index.ts +1 -1
- package/src/language/en.json +4 -4
- package/src/language/pt.json +4 -4
|
@@ -5,8 +5,10 @@ import {
|
|
|
5
5
|
Building2,
|
|
6
6
|
Eye,
|
|
7
7
|
Factory,
|
|
8
|
+
FolderTree,
|
|
8
9
|
Globe2,
|
|
9
10
|
Layers3,
|
|
11
|
+
List,
|
|
10
12
|
ListFilter,
|
|
11
13
|
PackagePlus,
|
|
12
14
|
PackageSearch,
|
|
@@ -34,33 +36,15 @@ type CatalogFormFieldType =
|
|
|
34
36
|
| 'date'
|
|
35
37
|
| 'datetime';
|
|
36
38
|
|
|
37
|
-
export type CatalogLocalizedText = {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export type CatalogFieldDefinition = {
|
|
43
|
-
key: string;
|
|
44
|
-
labelKey: string;
|
|
45
|
-
type?: CatalogFieldDisplayType;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export type CatalogFilterOptionDefinition = {
|
|
49
|
-
value: string;
|
|
50
|
-
labelKey: string;
|
|
51
|
-
};
|
|
52
|
-
|
|
39
|
+
export type CatalogLocalizedText = { pt: string; en: string };
|
|
40
|
+
export type CatalogFieldDefinition = { key: string; labelKey: string; type?: CatalogFieldDisplayType };
|
|
41
|
+
export type CatalogFilterOptionDefinition = { value: string; labelKey: string };
|
|
53
42
|
export type CatalogContextualKpiDefinition = {
|
|
54
43
|
translationKey: string;
|
|
55
44
|
icon: LucideIcon;
|
|
56
45
|
count: (records: Record<string, unknown>[]) => number;
|
|
57
46
|
};
|
|
58
|
-
|
|
59
|
-
export type CatalogFormOptionDefinition = {
|
|
60
|
-
value: string;
|
|
61
|
-
label: CatalogLocalizedText;
|
|
62
|
-
};
|
|
63
|
-
|
|
47
|
+
export type CatalogFormOptionDefinition = { value: string; label: CatalogLocalizedText };
|
|
64
48
|
export type CatalogRelationDefinition = {
|
|
65
49
|
endpoint: string;
|
|
66
50
|
resource?: string;
|
|
@@ -70,7 +54,6 @@ export type CatalogRelationDefinition = {
|
|
|
70
54
|
labelKeys: string[];
|
|
71
55
|
searchParam?: string;
|
|
72
56
|
};
|
|
73
|
-
|
|
74
57
|
export type CatalogFormFieldDefinition = {
|
|
75
58
|
key: string;
|
|
76
59
|
label: CatalogLocalizedText;
|
|
@@ -84,13 +67,11 @@ export type CatalogFormFieldDefinition = {
|
|
|
84
67
|
accept?: string;
|
|
85
68
|
uploadPreviewVariant?: 'default' | 'square';
|
|
86
69
|
};
|
|
87
|
-
|
|
88
70
|
export type CatalogFormSectionDefinition = {
|
|
89
71
|
title: CatalogLocalizedText;
|
|
90
72
|
description?: CatalogLocalizedText;
|
|
91
73
|
fields: CatalogFormFieldDefinition[];
|
|
92
74
|
};
|
|
93
|
-
|
|
94
75
|
export type CatalogResourceDefinition = {
|
|
95
76
|
resource: string;
|
|
96
77
|
translationKey: string;
|
|
@@ -117,167 +98,197 @@ export type CatalogResourceDefinition = {
|
|
|
117
98
|
};
|
|
118
99
|
|
|
119
100
|
const ptEn = (pt: string, en: string): CatalogLocalizedText => ({ pt, en });
|
|
101
|
+
const relation = (endpoint: string, labelKeys: string[], options?: Partial<CatalogRelationDefinition>): CatalogRelationDefinition => ({
|
|
102
|
+
endpoint,
|
|
103
|
+
labelKeys,
|
|
104
|
+
searchParam: 'search',
|
|
105
|
+
...options,
|
|
106
|
+
});
|
|
107
|
+
const fileField = (key: string, label: CatalogLocalizedText): CatalogFormFieldDefinition => ({
|
|
108
|
+
key,
|
|
109
|
+
label,
|
|
110
|
+
type: 'upload',
|
|
111
|
+
uploadDestination: `catalog/${key.replace(/_id$/, '')}`,
|
|
112
|
+
accept: 'image/*',
|
|
113
|
+
span: 2,
|
|
114
|
+
uploadPreviewVariant: 'square',
|
|
115
|
+
});
|
|
120
116
|
|
|
121
|
-
const activeInactiveStatusFilterOptions
|
|
117
|
+
const activeInactiveStatusFilterOptions = [
|
|
122
118
|
{ value: 'active', labelKey: 'active' },
|
|
123
119
|
{ value: 'inactive', labelKey: 'inactive' },
|
|
124
120
|
];
|
|
125
|
-
|
|
126
|
-
const publicationStatusFilterOptions: CatalogFilterOptionDefinition[] = [
|
|
121
|
+
const publicationStatusFilterOptions = [
|
|
127
122
|
{ value: 'draft', labelKey: 'draft' },
|
|
128
123
|
{ value: 'published', labelKey: 'published' },
|
|
129
124
|
{ value: 'archived', labelKey: 'archived' },
|
|
130
125
|
];
|
|
131
|
-
|
|
132
|
-
const availabilityFilterOptions: CatalogFilterOptionDefinition[] = [
|
|
126
|
+
const availabilityFilterOptions = [
|
|
133
127
|
{ value: 'in_stock', labelKey: 'inStock' },
|
|
134
128
|
{ value: 'out_of_stock', labelKey: 'outOfStock' },
|
|
135
|
-
{ value: '
|
|
129
|
+
{ value: 'pre_order', labelKey: 'preOrder' },
|
|
130
|
+
{ value: 'unknown', labelKey: 'unknown' },
|
|
136
131
|
];
|
|
137
|
-
|
|
138
|
-
const dataTypeFilterOptions: CatalogFilterOptionDefinition[] = [
|
|
132
|
+
const attributeTypeFilterOptions = [
|
|
139
133
|
{ value: 'text', labelKey: 'text' },
|
|
134
|
+
{ value: 'long_text', labelKey: 'longText' },
|
|
140
135
|
{ value: 'number', labelKey: 'number' },
|
|
141
136
|
{ value: 'boolean', labelKey: 'boolean' },
|
|
142
|
-
{ value: '
|
|
137
|
+
{ value: 'option', labelKey: 'option' },
|
|
143
138
|
];
|
|
144
|
-
|
|
145
|
-
const facetModeFilterOptions: CatalogFilterOptionDefinition[] = [
|
|
139
|
+
const facetModeFilterOptions = [
|
|
146
140
|
{ value: 'default', labelKey: 'default' },
|
|
147
141
|
{ value: 'range', labelKey: 'range' },
|
|
148
142
|
{ value: 'select', labelKey: 'select' },
|
|
143
|
+
{ value: 'hidden', labelKey: 'hidden' },
|
|
149
144
|
];
|
|
150
145
|
|
|
151
146
|
const activeInactiveStatusOptions = [
|
|
152
147
|
{ value: 'active', label: ptEn('Ativo', 'Active') },
|
|
153
148
|
{ value: 'inactive', label: ptEn('Inativo', 'Inactive') },
|
|
154
149
|
];
|
|
155
|
-
|
|
156
150
|
const publicationStatusOptions = [
|
|
157
151
|
{ value: 'draft', label: ptEn('Rascunho', 'Draft') },
|
|
158
152
|
{ value: 'published', label: ptEn('Publicado', 'Published') },
|
|
159
153
|
{ value: 'archived', label: ptEn('Arquivado', 'Archived') },
|
|
160
154
|
];
|
|
161
|
-
|
|
162
155
|
const comparisonStatusOptions = [
|
|
163
156
|
{ value: 'draft', label: ptEn('Rascunho', 'Draft') },
|
|
164
157
|
{ value: 'ready', label: ptEn('Pronto', 'Ready') },
|
|
165
158
|
{ value: 'disabled', label: ptEn('Desabilitado', 'Disabled') },
|
|
166
159
|
];
|
|
167
|
-
|
|
168
160
|
const siteTypeOptions = [
|
|
169
161
|
{ value: 'portal', label: ptEn('Portal', 'Portal') },
|
|
170
|
-
{ value: '
|
|
171
|
-
{ value: '
|
|
162
|
+
{ value: 'niche', label: ptEn('Nicho', 'Niche') },
|
|
163
|
+
{ value: 'tenant', label: ptEn('Tenant', 'Tenant') },
|
|
172
164
|
];
|
|
173
|
-
|
|
174
|
-
const dataTypeOptions = [
|
|
165
|
+
const attributeTypeOptions = [
|
|
175
166
|
{ value: 'text', label: ptEn('Texto', 'Text') },
|
|
167
|
+
{ value: 'long_text', label: ptEn('Texto longo', 'Long text') },
|
|
176
168
|
{ value: 'number', label: ptEn('Número', 'Number') },
|
|
177
169
|
{ value: 'boolean', label: ptEn('Booleano', 'Boolean') },
|
|
178
|
-
{ value: '
|
|
170
|
+
{ value: 'option', label: ptEn('Opção', 'Option') },
|
|
179
171
|
];
|
|
180
|
-
|
|
181
172
|
const comparisonModeOptions = [
|
|
182
173
|
{ value: 'neutral', label: ptEn('Neutro', 'Neutral') },
|
|
183
174
|
{ value: 'higher_better', label: ptEn('Maior é melhor', 'Higher is better') },
|
|
184
175
|
{ value: 'lower_better', label: ptEn('Menor é melhor', 'Lower is better') },
|
|
185
|
-
{ value: '
|
|
176
|
+
{ value: 'boolean_true_better', label: ptEn('Verdadeiro é melhor', 'True is better') },
|
|
177
|
+
{ value: 'exact_match', label: ptEn('Correspondência exata', 'Exact match') },
|
|
186
178
|
];
|
|
187
|
-
|
|
188
179
|
const facetModeOptions = [
|
|
189
180
|
{ value: 'default', label: ptEn('Padrão', 'Default') },
|
|
190
181
|
{ value: 'range', label: ptEn('Faixa', 'Range') },
|
|
191
182
|
{ value: 'select', label: ptEn('Seleção', 'Select') },
|
|
183
|
+
{ value: 'hidden', label: ptEn('Oculto', 'Hidden') },
|
|
192
184
|
];
|
|
193
|
-
|
|
194
185
|
const comparisonTypeOptions = [
|
|
195
186
|
{ value: 'manual', label: ptEn('Manual', 'Manual') },
|
|
196
|
-
{ value: '
|
|
187
|
+
{ value: 'automatic', label: ptEn('Automática', 'Automatic') },
|
|
188
|
+
{ value: 'similarity', label: ptEn('Similaridade', 'Similarity') },
|
|
189
|
+
{ value: 'compatibility', label: ptEn('Compatibilidade', 'Compatibility') },
|
|
197
190
|
];
|
|
198
|
-
|
|
199
191
|
const generationModeOptions = [
|
|
200
192
|
{ value: 'manual', label: ptEn('Manual', 'Manual') },
|
|
201
193
|
{ value: 'automatic', label: ptEn('Automática', 'Automatic') },
|
|
202
|
-
{ value: 'ai_assisted', label: ptEn('Assistida por IA', 'AI assisted') },
|
|
203
194
|
];
|
|
204
|
-
|
|
205
195
|
const availabilityOptions = [
|
|
206
196
|
{ value: 'in_stock', label: ptEn('Em estoque', 'In stock') },
|
|
207
197
|
{ value: 'out_of_stock', label: ptEn('Sem estoque', 'Out of stock') },
|
|
208
|
-
{ value: '
|
|
198
|
+
{ value: 'pre_order', label: ptEn('Pré-venda', 'Pre-order') },
|
|
199
|
+
{ value: 'unknown', label: ptEn('Desconhecido', 'Unknown') },
|
|
209
200
|
];
|
|
210
|
-
|
|
211
201
|
const merchantTypeOptions = [
|
|
212
202
|
{ value: 'retailer', label: ptEn('Varejista', 'Retailer') },
|
|
213
203
|
{ value: 'marketplace', label: ptEn('Marketplace', 'Marketplace') },
|
|
214
|
-
{ value: '
|
|
204
|
+
{ value: 'saas', label: ptEn('SaaS', 'SaaS') },
|
|
205
|
+
{ value: 'direct', label: ptEn('Direto', 'Direct') },
|
|
215
206
|
];
|
|
216
|
-
|
|
217
207
|
const networkTypeOptions = [
|
|
208
|
+
{ value: 'amazon', label: ptEn('Amazon', 'Amazon') },
|
|
209
|
+
{ value: 'mercado_livre', label: ptEn('Mercado Livre', 'Mercado Livre') },
|
|
210
|
+
{ value: 'aliexpress', label: ptEn('AliExpress', 'AliExpress') },
|
|
211
|
+
{ value: 'kabum', label: ptEn('KaBuM!', 'KaBuM!') },
|
|
218
212
|
{ value: 'direct', label: ptEn('Direto', 'Direct') },
|
|
219
213
|
{ value: 'network', label: ptEn('Rede', 'Network') },
|
|
220
|
-
{ value: 'api', label: ptEn('API', 'API') },
|
|
221
214
|
];
|
|
222
|
-
|
|
223
215
|
const commissionTypeOptions = [
|
|
224
216
|
{ value: 'percentage', label: ptEn('Percentual', 'Percentage') },
|
|
225
|
-
{ value: 'fixed', label: ptEn('Valor fixo', 'Fixed
|
|
226
|
-
{ value: 'cpa', label: ptEn('CPA', 'CPA') },
|
|
227
|
-
{ value: 'cpl', label: ptEn('CPL', 'CPL') },
|
|
217
|
+
{ value: 'fixed', label: ptEn('Valor fixo', 'Fixed') },
|
|
228
218
|
];
|
|
229
|
-
|
|
230
219
|
const pageTypeOptions = [
|
|
231
220
|
{ value: 'comparison', label: ptEn('Comparação', 'Comparison') },
|
|
232
|
-
{ value: '
|
|
233
|
-
{ value: '
|
|
221
|
+
{ value: 'best_of', label: ptEn('Melhores', 'Best of') },
|
|
222
|
+
{ value: 'cost_benefit', label: ptEn('Custo-benefício', 'Cost benefit') },
|
|
223
|
+
{ value: 'attribute', label: ptEn('Atributo', 'Attribute') },
|
|
224
|
+
{ value: 'price_range', label: ptEn('Faixa de preço', 'Price range') },
|
|
225
|
+
{ value: 'brand', label: ptEn('Marca', 'Brand') },
|
|
226
|
+
{ value: 'use_case', label: ptEn('Caso de uso', 'Use case') },
|
|
234
227
|
];
|
|
235
|
-
|
|
236
228
|
const canonicalStrategyOptions = [
|
|
237
|
-
{ value: 'self', label: ptEn('
|
|
238
|
-
{ value: 'parent', label: ptEn('Canônica
|
|
229
|
+
{ value: 'self', label: ptEn('Canônica própria', 'Self canonical') },
|
|
230
|
+
{ value: 'parent', label: ptEn('Canônica pai', 'Parent canonical') },
|
|
239
231
|
{ value: 'custom', label: ptEn('Canônica customizada', 'Custom canonical') },
|
|
240
232
|
];
|
|
241
|
-
|
|
242
233
|
const sourceTypeOptions = [
|
|
243
234
|
{ value: 'api', label: ptEn('API', 'API') },
|
|
244
235
|
{ value: 'feed', label: ptEn('Feed', 'Feed') },
|
|
245
|
-
{ value: '
|
|
246
|
-
{ value: '
|
|
236
|
+
{ value: 'file', label: ptEn('Arquivo', 'File') },
|
|
237
|
+
{ value: 'crawler', label: ptEn('Crawler', 'Crawler') },
|
|
247
238
|
];
|
|
248
|
-
|
|
249
239
|
const currencyOptions = [
|
|
250
240
|
{ value: 'BRL', label: ptEn('Real brasileiro (BRL)', 'Brazilian real (BRL)') },
|
|
251
241
|
{ value: 'USD', label: ptEn('Dólar americano (USD)', 'US dollar (USD)') },
|
|
252
242
|
{ value: 'EUR', label: ptEn('Euro (EUR)', 'Euro (EUR)') },
|
|
253
243
|
];
|
|
254
244
|
|
|
255
|
-
const
|
|
256
|
-
endpoint: string,
|
|
257
|
-
labelKeys: string[],
|
|
258
|
-
options?: Partial<CatalogRelationDefinition>
|
|
259
|
-
): CatalogRelationDefinition => ({
|
|
260
|
-
endpoint,
|
|
261
|
-
labelKeys,
|
|
262
|
-
searchParam: 'search',
|
|
263
|
-
...options,
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
const fileField = (
|
|
267
|
-
key: string,
|
|
268
|
-
label: CatalogLocalizedText
|
|
269
|
-
): CatalogFormFieldDefinition => ({
|
|
270
|
-
key,
|
|
271
|
-
label,
|
|
272
|
-
type: 'upload',
|
|
273
|
-
uploadDestination: `catalog/${key.replace(/_id$/, '')}`,
|
|
274
|
-
accept: 'image/*',
|
|
275
|
-
span: 2,
|
|
276
|
-
uploadPreviewVariant: 'square',
|
|
277
|
-
placeholder: ptEn('Envie uma imagem para representar este registro', 'Upload an image to represent this record'),
|
|
278
|
-
});
|
|
245
|
+
export const catalogResources: CatalogResourceDefinition[] = [];
|
|
279
246
|
|
|
280
|
-
|
|
247
|
+
catalogResources.push(
|
|
248
|
+
{
|
|
249
|
+
resource: 'categories',
|
|
250
|
+
translationKey: 'categories',
|
|
251
|
+
singularLabel: ptEn('Categoria', 'Category'),
|
|
252
|
+
createActionLabel: ptEn('Nova Categoria', 'New Category'),
|
|
253
|
+
editActionLabel: ptEn('Editar Categoria', 'Edit Category'),
|
|
254
|
+
icon: FolderTree,
|
|
255
|
+
href: '/catalog/categories',
|
|
256
|
+
colorClass: 'from-amber-500/20 via-orange-500/10 to-transparent',
|
|
257
|
+
glowClass: 'bg-amber-500/10 text-amber-700',
|
|
258
|
+
featured: true,
|
|
259
|
+
hasActiveStats: true,
|
|
260
|
+
listVariant: 'table',
|
|
261
|
+
primaryFilterField: 'status',
|
|
262
|
+
primaryFilterOptions: activeInactiveStatusFilterOptions,
|
|
263
|
+
titleFields: ['name', 'slug'],
|
|
264
|
+
descriptionFields: ['normalized_name', 'description'],
|
|
265
|
+
badgeFields: ['status'],
|
|
266
|
+
cardMetadata: [{ key: 'parent_category_id', labelKey: 'parentCategoryId' }, { key: 'comparison_enabled', labelKey: 'comparisonEnabled', type: 'boolean' }],
|
|
267
|
+
tableColumns: [
|
|
268
|
+
{ key: 'id', labelKey: 'id' },
|
|
269
|
+
{ key: 'name', labelKey: 'name' },
|
|
270
|
+
{ key: 'slug', labelKey: 'slug' },
|
|
271
|
+
{ key: 'parent_category_id', labelKey: 'parentCategoryId' },
|
|
272
|
+
{ key: 'comparison_enabled', labelKey: 'comparisonEnabled', type: 'boolean' },
|
|
273
|
+
{ key: 'sort_order', labelKey: 'sortOrder' },
|
|
274
|
+
{ key: 'status', labelKey: 'status' },
|
|
275
|
+
],
|
|
276
|
+
contextualKpi: { translationKey: 'visible', icon: Eye, count: (records) => records.length },
|
|
277
|
+
template: { parent_category_id: null, slug: '', name: '', normalized_name: '', description: '', comparison_enabled: true, status: 'active', sort_order: 0 },
|
|
278
|
+
formSections: [{
|
|
279
|
+
title: ptEn('Estrutura', 'Structure'),
|
|
280
|
+
fields: [
|
|
281
|
+
{ key: 'name', label: ptEn('Nome', 'Name'), type: 'text', required: true },
|
|
282
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
283
|
+
{ key: 'normalized_name', label: ptEn('Nome normalizado', 'Normalized name'), type: 'text' },
|
|
284
|
+
{ key: 'parent_category_id', label: ptEn('Categoria pai', 'Parent category'), type: 'relation', relation: relation('/catalog/categories', ['name', 'slug'], { resource: 'categories' }) },
|
|
285
|
+
{ key: 'comparison_enabled', label: ptEn('Permite comparação', 'Comparison enabled'), type: 'switch' },
|
|
286
|
+
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
287
|
+
{ key: 'sort_order', label: ptEn('Ordem', 'Sort order'), type: 'number' },
|
|
288
|
+
{ key: 'description', label: ptEn('Descrição', 'Description'), type: 'textarea', span: 2 },
|
|
289
|
+
],
|
|
290
|
+
}],
|
|
291
|
+
},
|
|
281
292
|
{
|
|
282
293
|
resource: 'brands',
|
|
283
294
|
translationKey: 'brands',
|
|
@@ -301,305 +312,19 @@ export const catalogResources: CatalogResourceDefinition[] = [
|
|
|
301
312
|
{ key: 'normalized_name', labelKey: 'normalizedName' },
|
|
302
313
|
{ key: 'website_url', labelKey: 'websiteUrl' },
|
|
303
314
|
],
|
|
304
|
-
contextualKpi: {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
},
|
|
317
|
-
formSections: [
|
|
318
|
-
{
|
|
319
|
-
title: ptEn('Identificação', 'Identity'),
|
|
320
|
-
fields: [
|
|
321
|
-
{ key: 'name', label: ptEn('Nome da marca', 'Brand name'), type: 'text', required: true, placeholder: ptEn('Ex.: Samsung', 'Ex.: Samsung') },
|
|
322
|
-
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true, placeholder: ptEn('Ex.: samsung', 'Ex.: samsung') },
|
|
323
|
-
{ key: 'normalized_name', label: ptEn('Nome normalizado', 'Normalized name'), type: 'text', placeholder: ptEn('Versão limpa para buscas e matching', 'Normalized value for search and matching') },
|
|
324
|
-
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
325
|
-
{ key: 'website_url', label: ptEn('Site oficial', 'Official website'), type: 'url', span: 2, placeholder: ptEn('https://www.sua-marca.com', 'https://www.your-brand.com') },
|
|
326
|
-
fileField('logo_file_id', ptEn('Logo', 'Logo')),
|
|
327
|
-
],
|
|
328
|
-
},
|
|
329
|
-
],
|
|
330
|
-
},
|
|
331
|
-
{
|
|
332
|
-
resource: 'category-attributes',
|
|
333
|
-
translationKey: 'categoryAttributes',
|
|
334
|
-
singularLabel: ptEn('Atributo por categoria', 'Category attribute'),
|
|
335
|
-
createActionLabel: ptEn('Novo Atributo por Categoria', 'New Category Attribute'),
|
|
336
|
-
editActionLabel: ptEn('Editar Atributo por Categoria', 'Edit Category Attribute'),
|
|
337
|
-
icon: BadgePercent,
|
|
338
|
-
href: '/catalog/category-attributes',
|
|
339
|
-
colorClass: 'from-pink-500/20 via-rose-500/10 to-transparent',
|
|
340
|
-
glowClass: 'bg-pink-500/10 text-pink-700',
|
|
341
|
-
listVariant: 'table',
|
|
342
|
-
primaryFilterField: 'facet_mode',
|
|
343
|
-
primaryFilterOptions: facetModeFilterOptions,
|
|
344
|
-
titleFields: ['attribute_id', 'category_id'],
|
|
345
|
-
descriptionFields: ['facet_mode'],
|
|
346
|
-
badgeFields: ['facet_mode', 'is_required', 'is_highlighted'],
|
|
347
|
-
cardMetadata: [
|
|
348
|
-
{ key: 'category_id', labelKey: 'categoryId' },
|
|
349
|
-
{ key: 'attribute_id', labelKey: 'attributeId' },
|
|
350
|
-
{ key: 'weight', labelKey: 'weight' },
|
|
351
|
-
],
|
|
352
|
-
tableColumns: [
|
|
353
|
-
{ key: 'id', labelKey: 'id' },
|
|
354
|
-
{ key: 'category_id', labelKey: 'categoryId' },
|
|
355
|
-
{ key: 'attribute_id', labelKey: 'attributeId' },
|
|
356
|
-
{ key: 'facet_mode', labelKey: 'facetMode' },
|
|
357
|
-
{ key: 'is_required', labelKey: 'isRequired', type: 'boolean' },
|
|
358
|
-
{ key: 'is_highlighted', labelKey: 'isHighlighted', type: 'boolean' },
|
|
359
|
-
],
|
|
360
|
-
contextualKpi: {
|
|
361
|
-
translationKey: 'requiredInSlice',
|
|
362
|
-
icon: BadgePercent,
|
|
363
|
-
count: (records) => records.filter((record) => record.is_required === true).length,
|
|
364
|
-
},
|
|
365
|
-
template: {
|
|
366
|
-
category_id: null,
|
|
367
|
-
attribute_id: null,
|
|
368
|
-
is_required: false,
|
|
369
|
-
is_highlighted: true,
|
|
370
|
-
display_order: 0,
|
|
371
|
-
weight: 1,
|
|
372
|
-
facet_mode: 'default',
|
|
373
|
-
},
|
|
374
|
-
formSections: [
|
|
375
|
-
{
|
|
376
|
-
title: ptEn('Relacionamentos', 'Relationships'),
|
|
377
|
-
fields: [
|
|
378
|
-
{
|
|
379
|
-
key: 'category_id',
|
|
380
|
-
label: ptEn('Categoria', 'Category'),
|
|
381
|
-
type: 'relation',
|
|
382
|
-
required: true,
|
|
383
|
-
relation: relation('/category', ['name', 'slug'], { valueKey: 'category_id' }),
|
|
384
|
-
},
|
|
385
|
-
{
|
|
386
|
-
key: 'attribute_id',
|
|
387
|
-
label: ptEn('Atributo', 'Attribute'),
|
|
388
|
-
type: 'relation',
|
|
389
|
-
required: true,
|
|
390
|
-
relation: relation('/catalog/attributes', ['label', 'slug'], {
|
|
391
|
-
resource: 'attributes',
|
|
392
|
-
createResource: 'attributes',
|
|
393
|
-
allowCreate: true,
|
|
394
|
-
}),
|
|
395
|
-
},
|
|
396
|
-
{ key: 'facet_mode', label: ptEn('Modo de faceta', 'Facet mode'), type: 'select', required: true, options: facetModeOptions },
|
|
397
|
-
{ key: 'display_order', label: ptEn('Ordem de exibição', 'Display order'), type: 'number' },
|
|
398
|
-
{ key: 'weight', label: ptEn('Peso', 'Weight'), type: 'number' },
|
|
399
|
-
{ key: 'is_required', label: ptEn('Obrigatório', 'Required'), type: 'switch' },
|
|
400
|
-
{ key: 'is_highlighted', label: ptEn('Destacado', 'Highlighted'), type: 'switch' },
|
|
401
|
-
],
|
|
402
|
-
},
|
|
403
|
-
],
|
|
404
|
-
},
|
|
405
|
-
{
|
|
406
|
-
resource: 'comparisons',
|
|
407
|
-
translationKey: 'comparisons',
|
|
408
|
-
singularLabel: ptEn('Comparação', 'Comparison'),
|
|
409
|
-
createActionLabel: ptEn('Nova Comparação', 'New Comparison'),
|
|
410
|
-
editActionLabel: ptEn('Editar Comparação', 'Edit Comparison'),
|
|
411
|
-
icon: Scale,
|
|
412
|
-
href: '/catalog/comparisons',
|
|
413
|
-
colorClass: 'from-amber-500/20 via-yellow-500/10 to-transparent',
|
|
414
|
-
glowClass: 'bg-amber-500/10 text-amber-700',
|
|
415
|
-
hasActiveStats: true,
|
|
416
|
-
listVariant: 'cards',
|
|
417
|
-
primaryFilterField: 'status',
|
|
418
|
-
primaryFilterOptions: publicationStatusFilterOptions,
|
|
419
|
-
titleFields: ['title', 'slug'],
|
|
420
|
-
descriptionFields: ['summary', 'slug'],
|
|
421
|
-
badgeFields: ['status', 'comparison_type', 'generation_mode'],
|
|
422
|
-
cardMetadata: [
|
|
423
|
-
{ key: 'slug', labelKey: 'slug' },
|
|
424
|
-
{ key: 'site_id', labelKey: 'siteId' },
|
|
425
|
-
{ key: 'category_id', labelKey: 'categoryId' },
|
|
426
|
-
],
|
|
427
|
-
contextualKpi: {
|
|
428
|
-
translationKey: 'publishedInSlice',
|
|
429
|
-
icon: Scale,
|
|
430
|
-
count: (records) =>
|
|
431
|
-
records.filter((record) =>
|
|
432
|
-
String(record.status ?? '') === 'published'
|
|
433
|
-
).length,
|
|
434
|
-
},
|
|
435
|
-
template: {
|
|
436
|
-
category_id: null,
|
|
437
|
-
site_id: null,
|
|
438
|
-
primary_content_id: null,
|
|
439
|
-
slug: '',
|
|
440
|
-
comparison_type: 'manual',
|
|
441
|
-
generation_mode: 'manual',
|
|
442
|
-
status: 'draft',
|
|
443
|
-
title: '',
|
|
444
|
-
summary: '',
|
|
445
|
-
intro: '',
|
|
446
|
-
verdict: '',
|
|
447
|
-
spec_snapshot_json: {},
|
|
448
|
-
eligibility_hash: '',
|
|
449
|
-
published_at: '',
|
|
450
|
-
},
|
|
451
|
-
formSections: [
|
|
452
|
-
{
|
|
453
|
-
title: ptEn('Base da comparação', 'Comparison basics'),
|
|
454
|
-
fields: [
|
|
455
|
-
{ key: 'title', label: ptEn('Título', 'Title'), type: 'text', required: true, placeholder: ptEn('Ex.: Melhor celular premium de 2026', 'Ex.: Best premium smartphone of 2026') },
|
|
456
|
-
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true, placeholder: ptEn('Ex.: melhor-celular-premium-2026', 'Ex.: best-premium-smartphone-2026') },
|
|
457
|
-
{
|
|
458
|
-
key: 'site_id',
|
|
459
|
-
label: ptEn('Site', 'Site'),
|
|
460
|
-
type: 'relation',
|
|
461
|
-
required: true,
|
|
462
|
-
relation: relation('/catalog/sites', ['name', 'domain', 'slug'], {
|
|
463
|
-
resource: 'sites',
|
|
464
|
-
createResource: 'sites',
|
|
465
|
-
allowCreate: true,
|
|
466
|
-
}),
|
|
467
|
-
},
|
|
468
|
-
{ key: 'category_id', label: ptEn('Categoria', 'Category'), type: 'relation', relation: relation('/category', ['name', 'slug'], { valueKey: 'category_id' }) },
|
|
469
|
-
{ key: 'primary_content_id', label: ptEn('Conteúdo principal', 'Primary content'), type: 'relation', relation: relation('/content', ['title', 'slug'], { valueKey: 'content_id' }) },
|
|
470
|
-
{ key: 'comparison_type', label: ptEn('Tipo de comparação', 'Comparison type'), type: 'select', required: true, options: comparisonTypeOptions },
|
|
471
|
-
{ key: 'generation_mode', label: ptEn('Modo de geração', 'Generation mode'), type: 'select', required: true, options: generationModeOptions },
|
|
472
|
-
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: publicationStatusOptions },
|
|
473
|
-
{ key: 'published_at', label: ptEn('Publicado em', 'Published at'), type: 'datetime' },
|
|
474
|
-
],
|
|
475
|
-
},
|
|
476
|
-
{
|
|
477
|
-
title: ptEn('Conteúdo editorial', 'Editorial content'),
|
|
478
|
-
fields: [
|
|
479
|
-
{ key: 'summary', label: ptEn('Resumo', 'Summary'), type: 'richtext', span: 2, placeholder: ptEn('Resumo editorial da comparação', 'Editorial summary of the comparison') },
|
|
480
|
-
{ key: 'intro', label: ptEn('Introdução', 'Introduction'), type: 'richtext', span: 2, placeholder: ptEn('Contextualize o comparativo para o leitor', 'Add reader-facing context for the comparison') },
|
|
481
|
-
{ key: 'verdict', label: ptEn('Veredito', 'Verdict'), type: 'richtext', span: 2, placeholder: ptEn('Conclusão e recomendação final', 'Final conclusion and recommendation') },
|
|
482
|
-
{ key: 'eligibility_hash', label: ptEn('Hash de elegibilidade', 'Eligibility hash'), type: 'text', span: 2, placeholder: ptEn('Chave técnica para rastrear o conjunto elegível', 'Technical key to track the eligible set') },
|
|
483
|
-
{ key: 'spec_snapshot_json', label: ptEn('Snapshot de regras', 'Rule snapshot'), type: 'json', span: 2 },
|
|
484
|
-
],
|
|
485
|
-
},
|
|
486
|
-
],
|
|
487
|
-
},
|
|
488
|
-
{
|
|
489
|
-
resource: 'offers',
|
|
490
|
-
translationKey: 'offers',
|
|
491
|
-
singularLabel: ptEn('Oferta', 'Offer'),
|
|
492
|
-
createActionLabel: ptEn('Nova Oferta', 'New Offer'),
|
|
493
|
-
editActionLabel: ptEn('Editar Oferta', 'Edit Offer'),
|
|
494
|
-
icon: ShoppingCart,
|
|
495
|
-
href: '/catalog/offers',
|
|
496
|
-
colorClass: 'from-red-500/20 via-orange-500/10 to-transparent',
|
|
497
|
-
glowClass: 'bg-red-500/10 text-red-700',
|
|
498
|
-
featured: true,
|
|
499
|
-
listVariant: 'cards',
|
|
500
|
-
primaryFilterField: 'availability_status',
|
|
501
|
-
primaryFilterOptions: availabilityFilterOptions,
|
|
502
|
-
titleFields: ['title', 'external_offer_id'],
|
|
503
|
-
descriptionFields: ['external_offer_id', 'affiliate_url'],
|
|
504
|
-
badgeFields: ['availability_status', 'is_featured'],
|
|
505
|
-
cardMetadata: [
|
|
506
|
-
{ key: 'price_amount', labelKey: 'priceAmount', type: 'currency' },
|
|
507
|
-
{ key: 'merchant_id', labelKey: 'merchantId' },
|
|
508
|
-
{ key: 'product_id', labelKey: 'productId' },
|
|
509
|
-
],
|
|
510
|
-
contextualKpi: {
|
|
511
|
-
translationKey: 'inStockInSlice',
|
|
512
|
-
icon: ShoppingCart,
|
|
513
|
-
count: (records) => records.filter((record) => record.availability_status === 'in_stock').length,
|
|
514
|
-
},
|
|
515
|
-
template: {
|
|
516
|
-
product_id: null,
|
|
517
|
-
merchant_id: null,
|
|
518
|
-
affiliate_program_id: null,
|
|
519
|
-
site_id: null,
|
|
520
|
-
external_offer_id: '',
|
|
521
|
-
title: '',
|
|
522
|
-
price_amount: 0,
|
|
523
|
-
price_currency: 'BRL',
|
|
524
|
-
original_price_amount: 0,
|
|
525
|
-
installment_json: {},
|
|
526
|
-
availability_status: 'in_stock',
|
|
527
|
-
affiliate_url: '',
|
|
528
|
-
deep_link_url: '',
|
|
529
|
-
priority_score: 0,
|
|
530
|
-
is_featured: false,
|
|
531
|
-
valid_from: '',
|
|
532
|
-
valid_until: '',
|
|
533
|
-
last_seen_at: '',
|
|
534
|
-
},
|
|
535
|
-
formSections: [
|
|
536
|
-
{
|
|
537
|
-
title: ptEn('Oferta comercial', 'Commercial offer'),
|
|
538
|
-
fields: [
|
|
539
|
-
{ key: 'title', label: ptEn('Título da oferta', 'Offer title'), type: 'text', required: true, span: 2, placeholder: ptEn('Ex.: Galaxy S25 Ultra 256GB por R$ 6.999', 'Ex.: Galaxy S25 Ultra 256GB for $1,299') },
|
|
540
|
-
{
|
|
541
|
-
key: 'product_id',
|
|
542
|
-
label: ptEn('Produto', 'Product'),
|
|
543
|
-
type: 'relation',
|
|
544
|
-
required: true,
|
|
545
|
-
relation: relation('/catalog/products', ['name', 'model_name', 'slug'], {
|
|
546
|
-
resource: 'products',
|
|
547
|
-
createResource: 'products',
|
|
548
|
-
allowCreate: true,
|
|
549
|
-
}),
|
|
550
|
-
},
|
|
551
|
-
{
|
|
552
|
-
key: 'merchant_id',
|
|
553
|
-
label: ptEn('Lojista', 'Merchant'),
|
|
554
|
-
type: 'relation',
|
|
555
|
-
required: true,
|
|
556
|
-
relation: relation('/catalog/merchants', ['name', 'slug'], {
|
|
557
|
-
resource: 'merchants',
|
|
558
|
-
createResource: 'merchants',
|
|
559
|
-
allowCreate: true,
|
|
560
|
-
}),
|
|
561
|
-
},
|
|
562
|
-
{
|
|
563
|
-
key: 'affiliate_program_id',
|
|
564
|
-
label: ptEn('Programa de afiliação', 'Affiliate program'),
|
|
565
|
-
type: 'relation',
|
|
566
|
-
relation: relation('/catalog/affiliate-programs', ['name', 'slug'], {
|
|
567
|
-
resource: 'affiliate-programs',
|
|
568
|
-
createResource: 'affiliate-programs',
|
|
569
|
-
allowCreate: true,
|
|
570
|
-
}),
|
|
571
|
-
},
|
|
572
|
-
{
|
|
573
|
-
key: 'site_id',
|
|
574
|
-
label: ptEn('Site', 'Site'),
|
|
575
|
-
type: 'relation',
|
|
576
|
-
relation: relation('/catalog/sites', ['name', 'domain', 'slug'], {
|
|
577
|
-
resource: 'sites',
|
|
578
|
-
createResource: 'sites',
|
|
579
|
-
allowCreate: true,
|
|
580
|
-
}),
|
|
581
|
-
},
|
|
582
|
-
{ key: 'external_offer_id', label: ptEn('ID externo', 'External ID'), type: 'text', placeholder: ptEn('ID da oferta no feed/API do parceiro', 'Offer id from partner feed/API') },
|
|
583
|
-
{ key: 'availability_status', label: ptEn('Disponibilidade', 'Availability'), type: 'select', required: true, options: availabilityOptions },
|
|
584
|
-
{ key: 'price_amount', label: ptEn('Preço', 'Price'), type: 'currency', required: true },
|
|
585
|
-
{ key: 'original_price_amount', label: ptEn('Preço original', 'Original price'), type: 'currency' },
|
|
586
|
-
{ key: 'price_currency', label: ptEn('Moeda', 'Currency'), type: 'select', required: true, options: currencyOptions },
|
|
587
|
-
{ key: 'priority_score', label: ptEn('Prioridade', 'Priority'), type: 'number' },
|
|
588
|
-
{ key: 'is_featured', label: ptEn('Oferta destacada', 'Featured offer'), type: 'switch' },
|
|
589
|
-
],
|
|
590
|
-
},
|
|
591
|
-
{
|
|
592
|
-
title: ptEn('Links e vigência', 'Links and schedule'),
|
|
593
|
-
fields: [
|
|
594
|
-
{ key: 'affiliate_url', label: ptEn('URL de afiliação', 'Affiliate URL'), type: 'url', span: 2, placeholder: ptEn('https://parceiro.com/r/abc123', 'https://partner.com/r/abc123') },
|
|
595
|
-
{ key: 'deep_link_url', label: ptEn('Deep link', 'Deep link'), type: 'url', span: 2, placeholder: ptEn('https://loja.com/produto/oferta', 'https://store.com/product/offer') },
|
|
596
|
-
{ key: 'valid_from', label: ptEn('Válida a partir de', 'Valid from'), type: 'datetime' },
|
|
597
|
-
{ key: 'valid_until', label: ptEn('Válida até', 'Valid until'), type: 'datetime' },
|
|
598
|
-
{ key: 'last_seen_at', label: ptEn('Última captura', 'Last seen at'), type: 'datetime' },
|
|
599
|
-
{ key: 'installment_json', label: ptEn('Parcelamento', 'Installments'), type: 'json', span: 2 },
|
|
600
|
-
],
|
|
601
|
-
},
|
|
602
|
-
],
|
|
315
|
+
contextualKpi: { translationKey: 'visible', icon: Eye, count: (records) => records.length },
|
|
316
|
+
template: { slug: '', name: '', normalized_name: '', logo_file_id: null, status: 'active', website_url: '' },
|
|
317
|
+
formSections: [{
|
|
318
|
+
title: ptEn('Identificação', 'Identity'),
|
|
319
|
+
fields: [
|
|
320
|
+
{ key: 'name', label: ptEn('Nome da marca', 'Brand name'), type: 'text', required: true },
|
|
321
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
322
|
+
{ key: 'normalized_name', label: ptEn('Nome normalizado', 'Normalized name'), type: 'text' },
|
|
323
|
+
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
324
|
+
{ key: 'website_url', label: ptEn('Site oficial', 'Official website'), type: 'url', span: 2 },
|
|
325
|
+
fileField('logo_file_id', ptEn('Logo', 'Logo')),
|
|
326
|
+
],
|
|
327
|
+
}],
|
|
603
328
|
},
|
|
604
329
|
{
|
|
605
330
|
resource: 'sites',
|
|
@@ -611,6 +336,7 @@ export const catalogResources: CatalogResourceDefinition[] = [
|
|
|
611
336
|
href: '/catalog/sites',
|
|
612
337
|
colorClass: 'from-sky-500/20 via-cyan-500/10 to-transparent',
|
|
613
338
|
glowClass: 'bg-sky-500/10 text-sky-700',
|
|
339
|
+
featured: true,
|
|
614
340
|
hasActiveStats: true,
|
|
615
341
|
listVariant: 'cards',
|
|
616
342
|
primaryFilterField: 'status',
|
|
@@ -623,36 +349,19 @@ export const catalogResources: CatalogResourceDefinition[] = [
|
|
|
623
349
|
{ key: 'domain', labelKey: 'domain' },
|
|
624
350
|
{ key: 'default_locale_id', labelKey: 'defaultLocaleId' },
|
|
625
351
|
],
|
|
626
|
-
contextualKpi: {
|
|
627
|
-
|
|
628
|
-
icon: Eye,
|
|
629
|
-
count: (records) => records.length,
|
|
630
|
-
},
|
|
631
|
-
template: {
|
|
632
|
-
slug: '',
|
|
633
|
-
name: '',
|
|
634
|
-
domain: '',
|
|
635
|
-
status: 'active',
|
|
636
|
-
site_type: 'portal',
|
|
637
|
-
default_locale_id: null,
|
|
638
|
-
theme_settings_json: {},
|
|
639
|
-
seo_defaults_json: {},
|
|
640
|
-
},
|
|
352
|
+
contextualKpi: { translationKey: 'visible', icon: Eye, count: (records) => records.length },
|
|
353
|
+
template: { slug: '', name: '', domain: '', status: 'active', site_type: 'portal', default_locale_id: null, logo_file_id: null, theme_settings_json: {}, seo_defaults_json: {} },
|
|
641
354
|
formSections: [
|
|
642
355
|
{
|
|
643
356
|
title: ptEn('Dados principais', 'Main details'),
|
|
644
357
|
fields: [
|
|
645
|
-
{ key: 'name', label: ptEn('Nome do site', 'Site name'), type: 'text', required: true
|
|
646
|
-
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true
|
|
647
|
-
{ key: 'domain', label: ptEn('Domínio', 'Domain'), type: 'url', required: true
|
|
358
|
+
{ key: 'name', label: ptEn('Nome do site', 'Site name'), type: 'text', required: true },
|
|
359
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
360
|
+
{ key: 'domain', label: ptEn('Domínio', 'Domain'), type: 'url', required: true },
|
|
648
361
|
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
649
362
|
{ key: 'site_type', label: ptEn('Tipo de site', 'Site type'), type: 'select', required: true, options: siteTypeOptions },
|
|
650
|
-
{
|
|
651
|
-
|
|
652
|
-
label: ptEn('Locale padrão', 'Default locale'),
|
|
653
|
-
type: 'relation',
|
|
654
|
-
relation: relation('/locale', ['name', 'code'], { valueKey: 'id' }),
|
|
655
|
-
},
|
|
363
|
+
{ key: 'default_locale_id', label: ptEn('Locale padrão', 'Default locale'), type: 'relation', required: true, relation: relation('/locale', ['name', 'code']) },
|
|
364
|
+
fileField('logo_file_id', ptEn('Logo', 'Logo')),
|
|
656
365
|
],
|
|
657
366
|
},
|
|
658
367
|
{
|
|
@@ -676,7 +385,7 @@ export const catalogResources: CatalogResourceDefinition[] = [
|
|
|
676
385
|
glowClass: 'bg-emerald-500/10 text-emerald-700',
|
|
677
386
|
featured: true,
|
|
678
387
|
hasActiveStats: true,
|
|
679
|
-
listVariant: '
|
|
388
|
+
listVariant: 'table',
|
|
680
389
|
primaryFilterField: 'status',
|
|
681
390
|
primaryFilterOptions: publicationStatusFilterOptions,
|
|
682
391
|
titleFields: ['name', 'model_name', 'slug'],
|
|
@@ -685,69 +394,30 @@ export const catalogResources: CatalogResourceDefinition[] = [
|
|
|
685
394
|
cardMetadata: [
|
|
686
395
|
{ key: 'slug', labelKey: 'slug' },
|
|
687
396
|
{ key: 'sku', labelKey: 'sku' },
|
|
688
|
-
{ key: '
|
|
689
|
-
{ key: '
|
|
397
|
+
{ key: 'brand_name', labelKey: 'brandId' },
|
|
398
|
+
{ key: 'category_name', labelKey: 'catalogCategoryId' },
|
|
690
399
|
],
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
slug: '',
|
|
701
|
-
name: '',
|
|
702
|
-
short_description: '',
|
|
703
|
-
description: '',
|
|
704
|
-
model_name: '',
|
|
705
|
-
sku: '',
|
|
706
|
-
gtin: '',
|
|
707
|
-
status: 'draft',
|
|
708
|
-
comparison_status: 'draft',
|
|
709
|
-
release_date: '',
|
|
710
|
-
spec_snapshot_json: {},
|
|
711
|
-
comparison_snapshot_json: {},
|
|
712
|
-
is_active: true,
|
|
713
|
-
},
|
|
400
|
+
tableColumns: [
|
|
401
|
+
{ key: 'name', labelKey: 'name' },
|
|
402
|
+
{ key: 'brand_name', labelKey: 'brandId' },
|
|
403
|
+
{ key: 'category_name', labelKey: 'catalogCategoryId' },
|
|
404
|
+
{ key: 'status', labelKey: 'status' },
|
|
405
|
+
{ key: 'is_active', labelKey: 'isActive', type: 'boolean' },
|
|
406
|
+
],
|
|
407
|
+
contextualKpi: { translationKey: 'activeInSlice', icon: PackageSearch, count: (records) => records.filter((record) => record.is_active === true).length },
|
|
408
|
+
template: { brand_id: null, catalog_category_id: null, primary_content_id: null, slug: '', name: '', short_description: '', description: '', model_name: '', sku: '', gtin: '', status: 'draft', comparison_status: 'draft', release_date: '', spec_snapshot_json: {}, comparison_snapshot_json: {}, is_active: true },
|
|
714
409
|
formSections: [
|
|
715
410
|
{
|
|
716
411
|
title: ptEn('Base do produto', 'Product basics'),
|
|
717
412
|
fields: [
|
|
718
|
-
{ key: 'name', label: ptEn('Nome do produto', 'Product name'), type: 'text', required: true
|
|
719
|
-
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true
|
|
720
|
-
{
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
resource: 'brands',
|
|
727
|
-
createResource: 'brands',
|
|
728
|
-
allowCreate: true,
|
|
729
|
-
}),
|
|
730
|
-
},
|
|
731
|
-
{
|
|
732
|
-
key: 'category_id',
|
|
733
|
-
label: ptEn('Categoria', 'Category'),
|
|
734
|
-
type: 'relation',
|
|
735
|
-
required: true,
|
|
736
|
-
relation: relation('/category', ['name', 'slug'], {
|
|
737
|
-
valueKey: 'category_id',
|
|
738
|
-
}),
|
|
739
|
-
},
|
|
740
|
-
{
|
|
741
|
-
key: 'primary_content_id',
|
|
742
|
-
label: ptEn('Conteúdo principal', 'Primary content'),
|
|
743
|
-
type: 'relation',
|
|
744
|
-
relation: relation('/content', ['title', 'slug'], {
|
|
745
|
-
valueKey: 'content_id',
|
|
746
|
-
}),
|
|
747
|
-
},
|
|
748
|
-
{ key: 'model_name', label: ptEn('Modelo', 'Model'), type: 'text', placeholder: ptEn('Nome técnico ou comercial do modelo', 'Technical or commercial model name') },
|
|
749
|
-
{ key: 'sku', label: ptEn('SKU', 'SKU'), type: 'text', placeholder: ptEn('Código interno de estoque', 'Internal stock code') },
|
|
750
|
-
{ key: 'gtin', label: ptEn('GTIN', 'GTIN'), type: 'text', placeholder: ptEn('Código de barras/GTIN', 'Barcode / GTIN') },
|
|
413
|
+
{ key: 'name', label: ptEn('Nome do produto', 'Product name'), type: 'text', required: true },
|
|
414
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
415
|
+
{ key: 'brand_id', label: ptEn('Marca', 'Brand'), type: 'relation', required: true, relation: relation('/catalog/brands', ['name', 'slug'], { resource: 'brands', createResource: 'brands', allowCreate: true }) },
|
|
416
|
+
{ key: 'catalog_category_id', label: ptEn('Categoria', 'Category'), type: 'relation', required: true, relation: relation('/catalog/categories', ['name', 'slug'], { resource: 'categories', createResource: 'categories', allowCreate: true }) },
|
|
417
|
+
{ key: 'primary_content_id', label: ptEn('Conteúdo principal', 'Primary content'), type: 'relation', relation: relation('/content', ['title', 'slug']) },
|
|
418
|
+
{ key: 'model_name', label: ptEn('Modelo', 'Model'), type: 'text' },
|
|
419
|
+
{ key: 'sku', label: ptEn('SKU', 'SKU'), type: 'text' },
|
|
420
|
+
{ key: 'gtin', label: ptEn('GTIN', 'GTIN'), type: 'text' },
|
|
751
421
|
{ key: 'release_date', label: ptEn('Data de lançamento', 'Release date'), type: 'date' },
|
|
752
422
|
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: publicationStatusOptions },
|
|
753
423
|
{ key: 'comparison_status', label: ptEn('Status de comparação', 'Comparison status'), type: 'select', required: true, options: comparisonStatusOptions },
|
|
@@ -757,136 +427,116 @@ export const catalogResources: CatalogResourceDefinition[] = [
|
|
|
757
427
|
{
|
|
758
428
|
title: ptEn('Conteúdo', 'Content'),
|
|
759
429
|
fields: [
|
|
760
|
-
{ key: 'short_description', label: ptEn('Resumo curto', 'Short description'), type: 'richtext', span: 2
|
|
761
|
-
{ key: 'description', label: ptEn('Descrição completa', 'Full description'), type: 'richtext', span: 2
|
|
430
|
+
{ key: 'short_description', label: ptEn('Resumo curto', 'Short description'), type: 'richtext', span: 2 },
|
|
431
|
+
{ key: 'description', label: ptEn('Descrição completa', 'Full description'), type: 'richtext', span: 2 },
|
|
432
|
+
],
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
title: ptEn('Snapshots', 'Snapshots'),
|
|
436
|
+
description: ptEn('Campos secundários para cache, leitura legada e payloads desnormalizados.', 'Secondary fields for cache, legacy reads, and denormalized payloads.'),
|
|
437
|
+
fields: [
|
|
762
438
|
{ key: 'spec_snapshot_json', label: ptEn('Snapshot de especificações', 'Specification snapshot'), type: 'json', span: 2 },
|
|
763
439
|
{ key: 'comparison_snapshot_json', label: ptEn('Snapshot de comparação', 'Comparison snapshot'), type: 'json', span: 2 },
|
|
764
440
|
],
|
|
765
441
|
},
|
|
766
442
|
],
|
|
767
|
-
}
|
|
443
|
+
}
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
catalogResources.push(
|
|
768
447
|
{
|
|
769
|
-
resource: '
|
|
770
|
-
translationKey: '
|
|
771
|
-
singularLabel: ptEn('
|
|
772
|
-
createActionLabel: ptEn('
|
|
773
|
-
editActionLabel: ptEn('Editar
|
|
774
|
-
icon:
|
|
775
|
-
href: '/catalog/
|
|
776
|
-
colorClass: 'from-
|
|
777
|
-
glowClass: 'bg-
|
|
448
|
+
resource: 'comparisons',
|
|
449
|
+
translationKey: 'comparisons',
|
|
450
|
+
singularLabel: ptEn('Comparação', 'Comparison'),
|
|
451
|
+
createActionLabel: ptEn('Nova Comparação', 'New Comparison'),
|
|
452
|
+
editActionLabel: ptEn('Editar Comparação', 'Edit Comparison'),
|
|
453
|
+
icon: Scale,
|
|
454
|
+
href: '/catalog/comparisons',
|
|
455
|
+
colorClass: 'from-amber-500/20 via-yellow-500/10 to-transparent',
|
|
456
|
+
glowClass: 'bg-amber-500/10 text-amber-700',
|
|
778
457
|
hasActiveStats: true,
|
|
779
|
-
listVariant: '
|
|
458
|
+
listVariant: 'cards',
|
|
780
459
|
primaryFilterField: 'status',
|
|
781
|
-
primaryFilterOptions:
|
|
782
|
-
titleFields: ['
|
|
783
|
-
descriptionFields: ['slug'],
|
|
784
|
-
badgeFields: ['status'],
|
|
785
|
-
cardMetadata: [
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
],
|
|
789
|
-
tableColumns: [
|
|
790
|
-
{ key: 'id', labelKey: 'id' },
|
|
791
|
-
{ key: 'name', labelKey: 'name' },
|
|
792
|
-
{ key: 'slug', labelKey: 'slug' },
|
|
793
|
-
{ key: 'status', labelKey: 'status' },
|
|
794
|
-
],
|
|
795
|
-
contextualKpi: {
|
|
796
|
-
translationKey: 'visible',
|
|
797
|
-
icon: Eye,
|
|
798
|
-
count: (records) => records.length,
|
|
799
|
-
},
|
|
800
|
-
template: { slug: '', name: '', status: 'active' },
|
|
460
|
+
primaryFilterOptions: publicationStatusFilterOptions,
|
|
461
|
+
titleFields: ['title', 'slug'],
|
|
462
|
+
descriptionFields: ['summary', 'slug'],
|
|
463
|
+
badgeFields: ['status', 'comparison_type', 'generation_mode'],
|
|
464
|
+
cardMetadata: [{ key: 'slug', labelKey: 'slug' }, { key: 'site_id', labelKey: 'siteId' }, { key: 'catalog_category_id', labelKey: 'catalogCategoryId' }],
|
|
465
|
+
contextualKpi: { translationKey: 'publishedInSlice', icon: Scale, count: (records) => records.filter((record) => String(record.status ?? '') === 'published').length },
|
|
466
|
+
template: { catalog_category_id: null, site_id: null, primary_content_id: null, slug: '', comparison_type: 'manual', generation_mode: 'manual', status: 'draft', title: '', summary: '', intro: '', verdict: '', eligibility_hash: '', published_at: '' },
|
|
801
467
|
formSections: [
|
|
802
468
|
{
|
|
803
|
-
title: ptEn('
|
|
469
|
+
title: ptEn('Base da comparação', 'Comparison basics'),
|
|
804
470
|
fields: [
|
|
805
|
-
{ key: '
|
|
806
|
-
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true
|
|
807
|
-
{ key: '
|
|
471
|
+
{ key: 'title', label: ptEn('Título', 'Title'), type: 'text', required: true },
|
|
472
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
473
|
+
{ key: 'site_id', label: ptEn('Site', 'Site'), type: 'relation', required: true, relation: relation('/catalog/sites', ['name', 'domain', 'slug'], { resource: 'sites', createResource: 'sites', allowCreate: true }) },
|
|
474
|
+
{ key: 'catalog_category_id', label: ptEn('Categoria', 'Category'), type: 'relation', required: true, relation: relation('/catalog/categories', ['name', 'slug'], { resource: 'categories' }) },
|
|
475
|
+
{ key: 'primary_content_id', label: ptEn('Conteúdo principal', 'Primary content'), type: 'relation', relation: relation('/content', ['title', 'slug']) },
|
|
476
|
+
{ key: 'comparison_type', label: ptEn('Tipo de comparação', 'Comparison type'), type: 'select', required: true, options: comparisonTypeOptions },
|
|
477
|
+
{ key: 'generation_mode', label: ptEn('Modo de geração', 'Generation mode'), type: 'select', required: true, options: generationModeOptions },
|
|
478
|
+
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: publicationStatusOptions },
|
|
479
|
+
{ key: 'published_at', label: ptEn('Publicado em', 'Published at'), type: 'datetime' },
|
|
480
|
+
],
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
title: ptEn('Conteúdo editorial', 'Editorial content'),
|
|
484
|
+
fields: [
|
|
485
|
+
{ key: 'summary', label: ptEn('Resumo', 'Summary'), type: 'richtext', span: 2 },
|
|
486
|
+
{ key: 'intro', label: ptEn('Introdução', 'Introduction'), type: 'richtext', span: 2 },
|
|
487
|
+
{ key: 'verdict', label: ptEn('Veredito', 'Verdict'), type: 'richtext', span: 2 },
|
|
488
|
+
{ key: 'eligibility_hash', label: ptEn('Hash de elegibilidade', 'Eligibility hash'), type: 'text', span: 2 },
|
|
808
489
|
],
|
|
809
490
|
},
|
|
810
491
|
],
|
|
811
492
|
},
|
|
812
493
|
{
|
|
813
|
-
resource: '
|
|
814
|
-
translationKey: '
|
|
815
|
-
singularLabel: ptEn('
|
|
816
|
-
createActionLabel: ptEn('
|
|
817
|
-
editActionLabel: ptEn('Editar
|
|
818
|
-
icon:
|
|
819
|
-
href: '/catalog/
|
|
820
|
-
colorClass: 'from-
|
|
821
|
-
glowClass: 'bg-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
],
|
|
833
|
-
tableColumns: [
|
|
834
|
-
{ key: 'id', labelKey: 'id' },
|
|
835
|
-
{ key: 'label', labelKey: 'label' },
|
|
836
|
-
{ key: 'slug', labelKey: 'slug' },
|
|
837
|
-
{ key: 'data_type', labelKey: 'dataType' },
|
|
838
|
-
{ key: 'comparison_mode', labelKey: 'comparisonMode' },
|
|
839
|
-
],
|
|
840
|
-
contextualKpi: {
|
|
841
|
-
translationKey: 'filterableInSlice',
|
|
842
|
-
icon: ListFilter,
|
|
843
|
-
count: (records) => records.filter((record) => record.is_filterable === true).length,
|
|
844
|
-
},
|
|
845
|
-
template: {
|
|
846
|
-
group_id: null,
|
|
847
|
-
slug: '',
|
|
848
|
-
label: '',
|
|
849
|
-
description: '',
|
|
850
|
-
data_type: 'text',
|
|
851
|
-
unit: '',
|
|
852
|
-
comparison_mode: 'neutral',
|
|
853
|
-
is_filterable: true,
|
|
854
|
-
is_sortable: false,
|
|
855
|
-
is_required_for_comparison: false,
|
|
856
|
-
normalization_rule_json: {},
|
|
857
|
-
display_order: 0,
|
|
858
|
-
},
|
|
494
|
+
resource: 'offers',
|
|
495
|
+
translationKey: 'offers',
|
|
496
|
+
singularLabel: ptEn('Oferta', 'Offer'),
|
|
497
|
+
createActionLabel: ptEn('Nova Oferta', 'New Offer'),
|
|
498
|
+
editActionLabel: ptEn('Editar Oferta', 'Edit Offer'),
|
|
499
|
+
icon: ShoppingCart,
|
|
500
|
+
href: '/catalog/offers',
|
|
501
|
+
colorClass: 'from-red-500/20 via-orange-500/10 to-transparent',
|
|
502
|
+
glowClass: 'bg-red-500/10 text-red-700',
|
|
503
|
+
featured: true,
|
|
504
|
+
listVariant: 'cards',
|
|
505
|
+
primaryFilterField: 'availability_status',
|
|
506
|
+
primaryFilterOptions: availabilityFilterOptions,
|
|
507
|
+
titleFields: ['title', 'external_offer_id'],
|
|
508
|
+
descriptionFields: ['external_offer_id', 'affiliate_url'],
|
|
509
|
+
badgeFields: ['availability_status', 'is_featured'],
|
|
510
|
+
cardMetadata: [{ key: 'price_amount', labelKey: 'priceAmount', type: 'currency' }, { key: 'merchant_id', labelKey: 'merchantId' }, { key: 'product_id', labelKey: 'productId' }],
|
|
511
|
+
contextualKpi: { translationKey: 'inStockInSlice', icon: ShoppingCart, count: (records) => records.filter((record) => record.availability_status === 'in_stock').length },
|
|
512
|
+
template: { product_id: null, merchant_id: null, affiliate_program_id: null, site_id: null, external_offer_id: '', title: '', price_amount: 0, price_currency: 'BRL', original_price_amount: null, installment_json: {}, availability_status: 'in_stock', affiliate_url: '', deep_link_url: '', priority_score: 0, is_featured: false, valid_from: '', valid_until: '', last_seen_at: '' },
|
|
859
513
|
formSections: [
|
|
860
514
|
{
|
|
861
|
-
title: ptEn('
|
|
515
|
+
title: ptEn('Oferta comercial', 'Commercial offer'),
|
|
862
516
|
fields: [
|
|
863
|
-
{ key: '
|
|
864
|
-
{ key: '
|
|
865
|
-
{
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
},
|
|
876
|
-
{ key: 'data_type', label: ptEn('Tipo de dado', 'Data type'), type: 'select', required: true, options: dataTypeOptions },
|
|
877
|
-
{ key: 'unit', label: ptEn('Unidade', 'Unit'), type: 'text', placeholder: ptEn('Ex.: polegadas, GB, kg', 'Ex.: inches, GB, kg') },
|
|
878
|
-
{ key: 'comparison_mode', label: ptEn('Modo de comparação', 'Comparison mode'), type: 'select', required: true, options: comparisonModeOptions },
|
|
879
|
-
{ key: 'display_order', label: ptEn('Ordem de exibição', 'Display order'), type: 'number' },
|
|
880
|
-
{ key: 'description', label: ptEn('Descrição', 'Description'), type: 'richtext', span: 2, placeholder: ptEn('Explique como o atributo deve ser usado e exibido', 'Explain how the attribute should be used and displayed') },
|
|
517
|
+
{ key: 'title', label: ptEn('Título da oferta', 'Offer title'), type: 'text', required: true, span: 2 },
|
|
518
|
+
{ key: 'product_id', label: ptEn('Produto', 'Product'), type: 'relation', required: true, relation: relation('/catalog/products', ['name', 'model_name', 'slug'], { resource: 'products' }) },
|
|
519
|
+
{ key: 'merchant_id', label: ptEn('Lojista', 'Merchant'), type: 'relation', required: true, relation: relation('/catalog/merchants', ['name', 'slug'], { resource: 'merchants', createResource: 'merchants', allowCreate: true }) },
|
|
520
|
+
{ key: 'affiliate_program_id', label: ptEn('Programa de afiliação', 'Affiliate program'), type: 'relation', relation: relation('/catalog/affiliate-programs', ['name', 'slug'], { resource: 'affiliate-programs', createResource: 'affiliate-programs', allowCreate: true }) },
|
|
521
|
+
{ key: 'site_id', label: ptEn('Site', 'Site'), type: 'relation', relation: relation('/catalog/sites', ['name', 'domain', 'slug'], { resource: 'sites' }) },
|
|
522
|
+
{ key: 'external_offer_id', label: ptEn('ID externo', 'External ID'), type: 'text' },
|
|
523
|
+
{ key: 'availability_status', label: ptEn('Disponibilidade', 'Availability'), type: 'select', required: true, options: availabilityOptions },
|
|
524
|
+
{ key: 'price_amount', label: ptEn('Preço', 'Price'), type: 'currency', required: true },
|
|
525
|
+
{ key: 'original_price_amount', label: ptEn('Preço original', 'Original price'), type: 'currency' },
|
|
526
|
+
{ key: 'price_currency', label: ptEn('Moeda', 'Currency'), type: 'select', required: true, options: currencyOptions },
|
|
527
|
+
{ key: 'priority_score', label: ptEn('Prioridade', 'Priority'), type: 'number' },
|
|
528
|
+
{ key: 'is_featured', label: ptEn('Oferta destacada', 'Featured offer'), type: 'switch' },
|
|
881
529
|
],
|
|
882
530
|
},
|
|
883
531
|
{
|
|
884
|
-
title: ptEn('
|
|
532
|
+
title: ptEn('Links e vigência', 'Links and schedule'),
|
|
885
533
|
fields: [
|
|
886
|
-
{ key: '
|
|
887
|
-
{ key: '
|
|
888
|
-
{ key: '
|
|
889
|
-
{ key: '
|
|
534
|
+
{ key: 'affiliate_url', label: ptEn('URL de afiliação', 'Affiliate URL'), type: 'url', span: 2 },
|
|
535
|
+
{ key: 'deep_link_url', label: ptEn('Deep link', 'Deep link'), type: 'url', span: 2 },
|
|
536
|
+
{ key: 'valid_from', label: ptEn('Válida a partir de', 'Valid from'), type: 'datetime' },
|
|
537
|
+
{ key: 'valid_until', label: ptEn('Válida até', 'Valid until'), type: 'datetime' },
|
|
538
|
+
{ key: 'last_seen_at', label: ptEn('Última captura', 'Last seen at'), type: 'datetime' },
|
|
539
|
+
{ key: 'installment_json', label: ptEn('Parcelamento', 'Installments'), type: 'json', span: 2 },
|
|
890
540
|
],
|
|
891
541
|
},
|
|
892
542
|
],
|
|
@@ -909,35 +559,19 @@ export const catalogResources: CatalogResourceDefinition[] = [
|
|
|
909
559
|
titleFields: ['name', 'slug'],
|
|
910
560
|
descriptionFields: ['slug'],
|
|
911
561
|
badgeFields: ['status', 'merchant_type'],
|
|
912
|
-
cardMetadata: [
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
status: 'active',
|
|
926
|
-
merchant_type: 'retailer',
|
|
927
|
-
logo_file_id: null,
|
|
928
|
-
},
|
|
929
|
-
formSections: [
|
|
930
|
-
{
|
|
931
|
-
title: ptEn('Perfil do lojista', 'Merchant profile'),
|
|
932
|
-
fields: [
|
|
933
|
-
{ key: 'name', label: ptEn('Nome do lojista', 'Merchant name'), type: 'text', required: true, placeholder: ptEn('Ex.: Magazine Luiza', 'Ex.: Best Buy') },
|
|
934
|
-
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true, placeholder: ptEn('Ex.: magazine-luiza', 'Ex.: best-buy') },
|
|
935
|
-
{ key: 'merchant_type', label: ptEn('Tipo de lojista', 'Merchant type'), type: 'select', required: true, options: merchantTypeOptions },
|
|
936
|
-
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
937
|
-
fileField('logo_file_id', ptEn('Logo', 'Logo')),
|
|
938
|
-
],
|
|
939
|
-
},
|
|
940
|
-
],
|
|
562
|
+
cardMetadata: [{ key: 'slug', labelKey: 'slug' }, { key: 'merchant_type', labelKey: 'merchantType' }, { key: 'logo_file_id', labelKey: 'logoFileId' }],
|
|
563
|
+
contextualKpi: { translationKey: 'visible', icon: Eye, count: (records) => records.length },
|
|
564
|
+
template: { slug: '', name: '', status: 'active', merchant_type: 'retailer', logo_file_id: null },
|
|
565
|
+
formSections: [{
|
|
566
|
+
title: ptEn('Perfil do lojista', 'Merchant profile'),
|
|
567
|
+
fields: [
|
|
568
|
+
{ key: 'name', label: ptEn('Nome do lojista', 'Merchant name'), type: 'text', required: true },
|
|
569
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
570
|
+
{ key: 'merchant_type', label: ptEn('Tipo de lojista', 'Merchant type'), type: 'select', required: true, options: merchantTypeOptions },
|
|
571
|
+
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
572
|
+
fileField('logo_file_id', ptEn('Logo', 'Logo')),
|
|
573
|
+
],
|
|
574
|
+
}],
|
|
941
575
|
},
|
|
942
576
|
{
|
|
943
577
|
resource: 'affiliate-programs',
|
|
@@ -956,51 +590,22 @@ export const catalogResources: CatalogResourceDefinition[] = [
|
|
|
956
590
|
titleFields: ['name', 'slug'],
|
|
957
591
|
descriptionFields: ['slug', 'network_type'],
|
|
958
592
|
badgeFields: ['status', 'network_type', 'commission_type'],
|
|
959
|
-
cardMetadata: [
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
commission_type: 'percentage',
|
|
976
|
-
default_commission_value: 0,
|
|
977
|
-
status: 'active',
|
|
978
|
-
},
|
|
979
|
-
formSections: [
|
|
980
|
-
{
|
|
981
|
-
title: ptEn('Programa', 'Program'),
|
|
982
|
-
fields: [
|
|
983
|
-
{ key: 'name', label: ptEn('Nome do programa', 'Program name'), type: 'text', required: true, placeholder: ptEn('Ex.: Programa Magalu Ads', 'Ex.: Best Buy Affiliate Program') },
|
|
984
|
-
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true, placeholder: ptEn('Ex.: magalu-ads', 'Ex.: best-buy-affiliate') },
|
|
985
|
-
{
|
|
986
|
-
key: 'merchant_id',
|
|
987
|
-
label: ptEn('Lojista', 'Merchant'),
|
|
988
|
-
type: 'relation',
|
|
989
|
-
required: true,
|
|
990
|
-
relation: relation('/catalog/merchants', ['name', 'slug'], {
|
|
991
|
-
resource: 'merchants',
|
|
992
|
-
createResource: 'merchants',
|
|
993
|
-
allowCreate: true,
|
|
994
|
-
}),
|
|
995
|
-
},
|
|
996
|
-
{ key: 'network_type', label: ptEn('Rede', 'Network'), type: 'select', required: true, options: networkTypeOptions },
|
|
997
|
-
{ key: 'commission_type', label: ptEn('Tipo de comissão', 'Commission type'), type: 'select', required: true, options: commissionTypeOptions },
|
|
998
|
-
{ key: 'default_commission_value', label: ptEn('Comissão padrão', 'Default commission'), type: 'currency' },
|
|
999
|
-
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
1000
|
-
{ key: 'tracking_template', label: ptEn('Template de tracking', 'Tracking template'), type: 'textarea', span: 2, placeholder: ptEn('Template com macros e parâmetros de tracking', 'Template with tracking macros and parameters') },
|
|
1001
|
-
],
|
|
1002
|
-
},
|
|
1003
|
-
],
|
|
593
|
+
cardMetadata: [{ key: 'merchant_id', labelKey: 'merchantId' }, { key: 'commission_type', labelKey: 'commissionType' }, { key: 'default_commission_value', labelKey: 'defaultCommissionValue', type: 'currency' }],
|
|
594
|
+
contextualKpi: { translationKey: 'visible', icon: Eye, count: (records) => records.length },
|
|
595
|
+
template: { merchant_id: null, slug: '', name: '', network_type: 'direct', tracking_template: '', commission_type: 'percentage', default_commission_value: 0, status: 'active' },
|
|
596
|
+
formSections: [{
|
|
597
|
+
title: ptEn('Programa', 'Program'),
|
|
598
|
+
fields: [
|
|
599
|
+
{ key: 'name', label: ptEn('Nome do programa', 'Program name'), type: 'text', required: true },
|
|
600
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
601
|
+
{ key: 'merchant_id', label: ptEn('Lojista', 'Merchant'), type: 'relation', required: true, relation: relation('/catalog/merchants', ['name', 'slug'], { resource: 'merchants', createResource: 'merchants', allowCreate: true }) },
|
|
602
|
+
{ key: 'network_type', label: ptEn('Rede', 'Network'), type: 'select', required: true, options: networkTypeOptions },
|
|
603
|
+
{ key: 'commission_type', label: ptEn('Tipo de comissão', 'Commission type'), type: 'select', required: true, options: commissionTypeOptions },
|
|
604
|
+
{ key: 'default_commission_value', label: ptEn('Comissão padrão', 'Default commission'), type: 'currency' },
|
|
605
|
+
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
606
|
+
{ key: 'tracking_template', label: ptEn('Template de tracking', 'Tracking template'), type: 'textarea', span: 2 },
|
|
607
|
+
],
|
|
608
|
+
}],
|
|
1004
609
|
},
|
|
1005
610
|
{
|
|
1006
611
|
resource: 'seo-rules',
|
|
@@ -1020,47 +625,17 @@ export const catalogResources: CatalogResourceDefinition[] = [
|
|
|
1020
625
|
titleFields: ['rule_slug', 'page_type'],
|
|
1021
626
|
descriptionFields: ['page_type', 'canonical_strategy'],
|
|
1022
627
|
badgeFields: ['status', 'page_type', 'canonical_strategy'],
|
|
1023
|
-
cardMetadata: [
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
{ key: 'priority', labelKey: 'priority' },
|
|
1027
|
-
],
|
|
1028
|
-
contextualKpi: {
|
|
1029
|
-
translationKey: 'visible',
|
|
1030
|
-
icon: Eye,
|
|
1031
|
-
count: (records) => records.length,
|
|
1032
|
-
},
|
|
1033
|
-
template: {
|
|
1034
|
-
site_id: null,
|
|
1035
|
-
category_id: null,
|
|
1036
|
-
page_type: 'comparison',
|
|
1037
|
-
rule_slug: '',
|
|
1038
|
-
status: 'active',
|
|
1039
|
-
generation_query_json: {},
|
|
1040
|
-
min_product_count: 2,
|
|
1041
|
-
min_attribute_coverage: 1,
|
|
1042
|
-
canonical_strategy: 'self',
|
|
1043
|
-
priority: 0,
|
|
1044
|
-
template_json: {},
|
|
1045
|
-
},
|
|
628
|
+
cardMetadata: [{ key: 'site_id', labelKey: 'siteId' }, { key: 'catalog_category_id', labelKey: 'catalogCategoryId' }, { key: 'priority', labelKey: 'priority' }],
|
|
629
|
+
contextualKpi: { translationKey: 'visible', icon: Eye, count: (records) => records.length },
|
|
630
|
+
template: { site_id: null, catalog_category_id: null, page_type: 'comparison', rule_slug: '', status: 'active', generation_query_json: {}, min_product_count: 2, min_attribute_coverage: 1, canonical_strategy: 'self', priority: 0, template_json: {} },
|
|
1046
631
|
formSections: [
|
|
1047
632
|
{
|
|
1048
633
|
title: ptEn('Escopo da regra', 'Rule scope'),
|
|
1049
634
|
fields: [
|
|
1050
|
-
{
|
|
1051
|
-
|
|
1052
|
-
label: ptEn('Site', 'Site'),
|
|
1053
|
-
type: 'relation',
|
|
1054
|
-
required: true,
|
|
1055
|
-
relation: relation('/catalog/sites', ['name', 'domain', 'slug'], {
|
|
1056
|
-
resource: 'sites',
|
|
1057
|
-
createResource: 'sites',
|
|
1058
|
-
allowCreate: true,
|
|
1059
|
-
}),
|
|
1060
|
-
},
|
|
1061
|
-
{ key: 'category_id', label: ptEn('Categoria', 'Category'), type: 'relation', relation: relation('/category', ['name', 'slug'], { valueKey: 'category_id' }) },
|
|
635
|
+
{ key: 'site_id', label: ptEn('Site', 'Site'), type: 'relation', required: true, relation: relation('/catalog/sites', ['name', 'domain', 'slug'], { resource: 'sites' }) },
|
|
636
|
+
{ key: 'catalog_category_id', label: ptEn('Categoria', 'Category'), type: 'relation', relation: relation('/catalog/categories', ['name', 'slug'], { resource: 'categories' }) },
|
|
1062
637
|
{ key: 'page_type', label: ptEn('Tipo de página', 'Page type'), type: 'select', required: true, options: pageTypeOptions },
|
|
1063
|
-
{ key: 'rule_slug', label: ptEn('Slug da regra', 'Rule slug'), type: 'text', required: true
|
|
638
|
+
{ key: 'rule_slug', label: ptEn('Slug da regra', 'Rule slug'), type: 'text', required: true },
|
|
1064
639
|
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
1065
640
|
{ key: 'canonical_strategy', label: ptEn('Estratégia canônica', 'Canonical strategy'), type: 'select', required: true, options: canonicalStrategyOptions },
|
|
1066
641
|
{ key: 'priority', label: ptEn('Prioridade', 'Priority'), type: 'number' },
|
|
@@ -1095,66 +670,259 @@ export const catalogResources: CatalogResourceDefinition[] = [
|
|
|
1095
670
|
titleFields: ['name', 'slug'],
|
|
1096
671
|
descriptionFields: ['slug', 'source_type'],
|
|
1097
672
|
badgeFields: ['status', 'source_type'],
|
|
673
|
+
cardMetadata: [{ key: 'slug', labelKey: 'slug' }, { key: 'source_type', labelKey: 'sourceType' }, { key: 'status', labelKey: 'status' }],
|
|
674
|
+
contextualKpi: { translationKey: 'visible', icon: Eye, count: (records) => records.length },
|
|
675
|
+
template: { slug: '', name: '', source_type: 'api', config_json: {}, status: 'active' },
|
|
676
|
+
formSections: [{
|
|
677
|
+
title: ptEn('Origem dos dados', 'Data source'),
|
|
678
|
+
fields: [
|
|
679
|
+
{ key: 'name', label: ptEn('Nome da fonte', 'Source name'), type: 'text', required: true },
|
|
680
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
681
|
+
{ key: 'source_type', label: ptEn('Tipo de fonte', 'Source type'), type: 'select', required: true, options: sourceTypeOptions },
|
|
682
|
+
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
683
|
+
{ key: 'config_json', label: ptEn('Configuração', 'Configuration'), type: 'json', span: 2 },
|
|
684
|
+
],
|
|
685
|
+
}],
|
|
686
|
+
}
|
|
687
|
+
);
|
|
688
|
+
|
|
689
|
+
catalogResources.push(
|
|
690
|
+
{
|
|
691
|
+
resource: 'attribute-groups',
|
|
692
|
+
translationKey: 'attributeGroups',
|
|
693
|
+
singularLabel: ptEn('Grupo de atributos', 'Attribute group'),
|
|
694
|
+
createActionLabel: ptEn('Novo Grupo de Atributos', 'New Attribute Group'),
|
|
695
|
+
editActionLabel: ptEn('Editar Grupo de Atributos', 'Edit Attribute Group'),
|
|
696
|
+
icon: Layers3,
|
|
697
|
+
href: '/catalog/attribute-groups',
|
|
698
|
+
colorClass: 'from-violet-500/20 via-fuchsia-500/10 to-transparent',
|
|
699
|
+
glowClass: 'bg-violet-500/10 text-violet-700',
|
|
700
|
+
hasActiveStats: true,
|
|
701
|
+
listVariant: 'table',
|
|
702
|
+
primaryFilterField: 'status',
|
|
703
|
+
primaryFilterOptions: activeInactiveStatusFilterOptions,
|
|
704
|
+
titleFields: ['name', 'slug'],
|
|
705
|
+
descriptionFields: ['slug'],
|
|
706
|
+
badgeFields: ['status'],
|
|
707
|
+
cardMetadata: [{ key: 'slug', labelKey: 'slug' }, { key: 'status', labelKey: 'status' }],
|
|
708
|
+
tableColumns: [
|
|
709
|
+
{ key: 'id', labelKey: 'id' },
|
|
710
|
+
{ key: 'name', labelKey: 'name' },
|
|
711
|
+
{ key: 'slug', labelKey: 'slug' },
|
|
712
|
+
{ key: 'status', labelKey: 'status' },
|
|
713
|
+
],
|
|
714
|
+
contextualKpi: { translationKey: 'visible', icon: Eye, count: (records) => records.length },
|
|
715
|
+
template: { slug: '', name: '', status: 'active' },
|
|
716
|
+
formSections: [{
|
|
717
|
+
title: ptEn('Grupo', 'Group'),
|
|
718
|
+
fields: [
|
|
719
|
+
{ key: 'name', label: ptEn('Nome do grupo', 'Group name'), type: 'text', required: true },
|
|
720
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
721
|
+
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
722
|
+
],
|
|
723
|
+
}],
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
resource: 'attributes',
|
|
727
|
+
translationKey: 'attributes',
|
|
728
|
+
singularLabel: ptEn('Atributo', 'Attribute'),
|
|
729
|
+
createActionLabel: ptEn('Novo Atributo', 'New Attribute'),
|
|
730
|
+
editActionLabel: ptEn('Editar Atributo', 'Edit Attribute'),
|
|
731
|
+
icon: Tags,
|
|
732
|
+
href: '/catalog/attributes',
|
|
733
|
+
colorClass: 'from-indigo-500/20 via-blue-500/10 to-transparent',
|
|
734
|
+
glowClass: 'bg-indigo-500/10 text-indigo-700',
|
|
735
|
+
listVariant: 'table',
|
|
736
|
+
primaryFilterField: 'data_type',
|
|
737
|
+
primaryFilterOptions: attributeTypeFilterOptions,
|
|
738
|
+
titleFields: ['name', 'code', 'slug'],
|
|
739
|
+
descriptionFields: ['description', 'slug'],
|
|
740
|
+
badgeFields: ['data_type', 'comparison_mode', 'status'],
|
|
1098
741
|
cardMetadata: [
|
|
742
|
+
{ key: 'group_id', labelKey: 'groupId' },
|
|
743
|
+
{ key: 'group_name', labelKey: 'groupName' },
|
|
744
|
+
{ key: 'is_filterable', labelKey: 'isFilterable', type: 'boolean' },
|
|
745
|
+
{ key: 'is_comparable', labelKey: 'isComparable', type: 'boolean' },
|
|
746
|
+
],
|
|
747
|
+
tableColumns: [
|
|
748
|
+
{ key: 'id', labelKey: 'id' },
|
|
749
|
+
{ key: 'name', labelKey: 'name' },
|
|
750
|
+
{ key: 'code', labelKey: 'code' },
|
|
1099
751
|
{ key: 'slug', labelKey: 'slug' },
|
|
1100
|
-
{ key: '
|
|
752
|
+
{ key: 'data_type', labelKey: 'dataType' },
|
|
1101
753
|
{ key: 'status', labelKey: 'status' },
|
|
1102
754
|
],
|
|
1103
|
-
contextualKpi: {
|
|
1104
|
-
|
|
1105
|
-
icon: Eye,
|
|
1106
|
-
count: (records) => records.length,
|
|
1107
|
-
},
|
|
1108
|
-
template: {
|
|
1109
|
-
slug: '',
|
|
1110
|
-
name: '',
|
|
1111
|
-
source_type: 'api',
|
|
1112
|
-
config_json: {},
|
|
1113
|
-
status: 'active',
|
|
1114
|
-
},
|
|
755
|
+
contextualKpi: { translationKey: 'filterableInSlice', icon: ListFilter, count: (records) => records.filter((record) => record.is_filterable === true).length },
|
|
756
|
+
template: { code: '', group_id: null, group_name: '', slug: '', name: '', description: '', data_type: 'text', unit: '', comparison_mode: 'neutral', is_filterable: true, is_sortable: false, is_comparable: true, is_required_default: false, status: 'active', display_order: 0 },
|
|
1115
757
|
formSections: [
|
|
1116
758
|
{
|
|
1117
|
-
title: ptEn('
|
|
759
|
+
title: ptEn('Configuração do atributo', 'Attribute setup'),
|
|
1118
760
|
fields: [
|
|
1119
|
-
{ key: 'name', label: ptEn('Nome
|
|
1120
|
-
{ key: '
|
|
1121
|
-
{ key: '
|
|
761
|
+
{ key: 'name', label: ptEn('Nome', 'Name'), type: 'text', required: true },
|
|
762
|
+
{ key: 'code', label: ptEn('Código', 'Code'), type: 'text', required: true },
|
|
763
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
764
|
+
{ key: 'group_id', label: ptEn('Grupo', 'Group'), type: 'relation', relation: relation('/catalog/attribute-groups', ['name', 'slug'], { resource: 'attribute-groups', createResource: 'attribute-groups', allowCreate: true }) },
|
|
765
|
+
{ key: 'group_name', label: ptEn('Grupo textual', 'Group name'), type: 'text' },
|
|
766
|
+
{ key: 'data_type', label: ptEn('Tipo de dado', 'Data type'), type: 'select', required: true, options: attributeTypeOptions },
|
|
767
|
+
{ key: 'unit', label: ptEn('Unidade', 'Unit'), type: 'text' },
|
|
1122
768
|
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
1123
|
-
{ key: '
|
|
769
|
+
{ key: 'comparison_mode', label: ptEn('Modo de comparação', 'Comparison mode'), type: 'select', required: true, options: comparisonModeOptions },
|
|
770
|
+
{ key: 'display_order', label: ptEn('Ordem de exibição', 'Display order'), type: 'number' },
|
|
771
|
+
{ key: 'description', label: ptEn('Descrição', 'Description'), type: 'richtext', span: 2 },
|
|
772
|
+
],
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
title: ptEn('Regras', 'Rules'),
|
|
776
|
+
fields: [
|
|
777
|
+
{ key: 'is_filterable', label: ptEn('Filtrável', 'Filterable'), type: 'switch' },
|
|
778
|
+
{ key: 'is_sortable', label: ptEn('Ordenável', 'Sortable'), type: 'switch' },
|
|
779
|
+
{ key: 'is_comparable', label: ptEn('Comparável', 'Comparable'), type: 'switch' },
|
|
780
|
+
{ key: 'is_required_default', label: ptEn('Obrigatório por padrão', 'Required by default'), type: 'switch' },
|
|
1124
781
|
],
|
|
1125
782
|
},
|
|
1126
783
|
],
|
|
1127
784
|
},
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
785
|
+
{
|
|
786
|
+
resource: 'attribute-options',
|
|
787
|
+
translationKey: 'attributeOptions',
|
|
788
|
+
singularLabel: ptEn('Opção de atributo', 'Attribute option'),
|
|
789
|
+
createActionLabel: ptEn('Nova Opção', 'New Option'),
|
|
790
|
+
editActionLabel: ptEn('Editar Opção', 'Edit Option'),
|
|
791
|
+
icon: List,
|
|
792
|
+
href: '/catalog/attribute-options',
|
|
793
|
+
colorClass: 'from-slate-500/20 via-zinc-500/10 to-transparent',
|
|
794
|
+
glowClass: 'bg-slate-500/10 text-slate-700',
|
|
795
|
+
hasActiveStats: true,
|
|
796
|
+
listVariant: 'table',
|
|
797
|
+
primaryFilterField: 'status',
|
|
798
|
+
primaryFilterOptions: activeInactiveStatusFilterOptions,
|
|
799
|
+
titleFields: ['label', 'option_value', 'slug'],
|
|
800
|
+
descriptionFields: ['option_value', 'normalized_value'],
|
|
801
|
+
badgeFields: ['status', 'is_default'],
|
|
802
|
+
cardMetadata: [{ key: 'attribute_id', labelKey: 'attributeId' }, { key: 'sort_order', labelKey: 'sortOrder' }],
|
|
803
|
+
tableColumns: [
|
|
804
|
+
{ key: 'id', labelKey: 'id' },
|
|
805
|
+
{ key: 'label', labelKey: 'label' },
|
|
806
|
+
{ key: 'slug', labelKey: 'slug' },
|
|
807
|
+
{ key: 'option_value', labelKey: 'optionValue' },
|
|
808
|
+
{ key: 'status', labelKey: 'status' },
|
|
809
|
+
{ key: 'is_default', labelKey: 'isDefault', type: 'boolean' },
|
|
810
|
+
],
|
|
811
|
+
contextualKpi: { translationKey: 'visible', icon: Eye, count: (records) => records.length },
|
|
812
|
+
template: { attribute_id: null, slug: '', label: '', option_value: '', normalized_value: '', sort_order: 0, status: 'active', is_default: false },
|
|
813
|
+
formSections: [{
|
|
814
|
+
title: ptEn('Opção', 'Option'),
|
|
815
|
+
fields: [
|
|
816
|
+
{ key: 'attribute_id', label: ptEn('Atributo', 'Attribute'), type: 'relation', required: true, relation: relation('/catalog/attributes', ['name', 'code', 'slug'], { resource: 'attributes', createResource: 'attributes', allowCreate: true }) },
|
|
817
|
+
{ key: 'label', label: ptEn('Rótulo', 'Label'), type: 'text', required: true },
|
|
818
|
+
{ key: 'slug', label: ptEn('Slug', 'Slug'), type: 'text', required: true },
|
|
819
|
+
{ key: 'option_value', label: ptEn('Valor', 'Value'), type: 'text', required: true },
|
|
820
|
+
{ key: 'normalized_value', label: ptEn('Valor normalizado', 'Normalized value'), type: 'text' },
|
|
821
|
+
{ key: 'sort_order', label: ptEn('Ordem', 'Sort order'), type: 'number' },
|
|
822
|
+
{ key: 'status', label: ptEn('Status', 'Status'), type: 'select', required: true, options: activeInactiveStatusOptions },
|
|
823
|
+
{ key: 'is_default', label: ptEn('Padrão', 'Default'), type: 'switch' },
|
|
824
|
+
],
|
|
825
|
+
}],
|
|
826
|
+
},
|
|
827
|
+
{
|
|
828
|
+
resource: 'category-attributes',
|
|
829
|
+
translationKey: 'categoryAttributes',
|
|
830
|
+
singularLabel: ptEn('Atributo por categoria', 'Category attribute'),
|
|
831
|
+
createActionLabel: ptEn('Novo Atributo por Categoria', 'New Category Attribute'),
|
|
832
|
+
editActionLabel: ptEn('Editar Atributo por Categoria', 'Edit Category Attribute'),
|
|
833
|
+
icon: BadgePercent,
|
|
834
|
+
href: '/catalog/category-attributes',
|
|
835
|
+
colorClass: 'from-pink-500/20 via-rose-500/10 to-transparent',
|
|
836
|
+
glowClass: 'bg-pink-500/10 text-pink-700',
|
|
837
|
+
listVariant: 'table',
|
|
838
|
+
primaryFilterField: 'facet_mode',
|
|
839
|
+
primaryFilterOptions: facetModeFilterOptions,
|
|
840
|
+
titleFields: ['attribute_id', 'catalog_category_id'],
|
|
841
|
+
descriptionFields: ['facet_mode'],
|
|
842
|
+
badgeFields: ['facet_mode', 'is_required', 'is_highlight'],
|
|
843
|
+
cardMetadata: [{ key: 'catalog_category_id', labelKey: 'catalogCategoryId' }, { key: 'attribute_id', labelKey: 'attributeId' }, { key: 'weight', labelKey: 'weight' }],
|
|
844
|
+
tableColumns: [
|
|
845
|
+
{ key: 'id', labelKey: 'id' },
|
|
846
|
+
{ key: 'catalog_category_id', labelKey: 'catalogCategoryId' },
|
|
847
|
+
{ key: 'attribute_id', labelKey: 'attributeId' },
|
|
848
|
+
{ key: 'facet_mode', labelKey: 'facetMode' },
|
|
849
|
+
{ key: 'is_required', labelKey: 'isRequired', type: 'boolean' },
|
|
850
|
+
{ key: 'is_highlight', labelKey: 'isHighlight', type: 'boolean' },
|
|
851
|
+
],
|
|
852
|
+
contextualKpi: { translationKey: 'requiredInSlice', icon: BadgePercent, count: (records) => records.filter((record) => record.is_required === true).length },
|
|
853
|
+
template: { catalog_category_id: null, attribute_id: null, is_required: false, is_highlight: true, is_filter_visible: true, is_comparison_visible: true, sort_order: 0, weight: 1, facet_mode: 'default' },
|
|
854
|
+
formSections: [{
|
|
855
|
+
title: ptEn('Relacionamentos', 'Relationships'),
|
|
856
|
+
fields: [
|
|
857
|
+
{ key: 'catalog_category_id', label: ptEn('Categoria', 'Category'), type: 'relation', required: true, relation: relation('/catalog/categories', ['name', 'slug'], { resource: 'categories', createResource: 'categories', allowCreate: true }) },
|
|
858
|
+
{ key: 'attribute_id', label: ptEn('Atributo', 'Attribute'), type: 'relation', required: true, relation: relation('/catalog/attributes', ['name', 'code', 'slug'], { resource: 'attributes', createResource: 'attributes', allowCreate: true }) },
|
|
859
|
+
{ key: 'facet_mode', label: ptEn('Modo de faceta', 'Facet mode'), type: 'select', required: true, options: facetModeOptions },
|
|
860
|
+
{ key: 'sort_order', label: ptEn('Ordem de exibição', 'Display order'), type: 'number' },
|
|
861
|
+
{ key: 'weight', label: ptEn('Peso', 'Weight'), type: 'number' },
|
|
862
|
+
{ key: 'is_required', label: ptEn('Obrigatório', 'Required'), type: 'switch' },
|
|
863
|
+
{ key: 'is_highlight', label: ptEn('Destacado', 'Highlighted'), type: 'switch' },
|
|
864
|
+
{ key: 'is_filter_visible', label: ptEn('Visível no filtro', 'Visible in filters'), type: 'switch' },
|
|
865
|
+
{ key: 'is_comparison_visible', label: ptEn('Visível na comparação', 'Visible in comparison'), type: 'switch' },
|
|
866
|
+
],
|
|
867
|
+
}],
|
|
868
|
+
},
|
|
869
|
+
{
|
|
870
|
+
resource: 'product-attributes',
|
|
871
|
+
translationKey: 'productAttributes',
|
|
872
|
+
singularLabel: ptEn('Atributo de produto', 'Product attribute'),
|
|
873
|
+
createActionLabel: ptEn('Novo Valor de Atributo', 'New Attribute Value'),
|
|
874
|
+
editActionLabel: ptEn('Editar Valor de Atributo', 'Edit Attribute Value'),
|
|
875
|
+
icon: ListFilter,
|
|
876
|
+
href: '/catalog/product-attributes',
|
|
877
|
+
colorClass: 'from-teal-500/20 via-emerald-500/10 to-transparent',
|
|
878
|
+
glowClass: 'bg-teal-500/10 text-teal-700',
|
|
879
|
+
listVariant: 'table',
|
|
880
|
+
primaryFilterField: 'is_verified',
|
|
881
|
+
primaryFilterOptions: [{ value: 'true', labelKey: 'verified' }, { value: 'false', labelKey: 'unverified' }],
|
|
882
|
+
titleFields: ['raw_value', 'value_text', 'attribute_id'],
|
|
883
|
+
descriptionFields: ['normalized_value', 'source_type'],
|
|
884
|
+
badgeFields: ['is_verified', 'source_type'],
|
|
885
|
+
cardMetadata: [{ key: 'product_id', labelKey: 'productId' }, { key: 'attribute_id', labelKey: 'attributeId' }, { key: 'attribute_option_id', labelKey: 'attributeOptionId' }],
|
|
886
|
+
tableColumns: [
|
|
887
|
+
{ key: 'id', labelKey: 'id' },
|
|
888
|
+
{ key: 'product_id', labelKey: 'productId' },
|
|
889
|
+
{ key: 'attribute_id', labelKey: 'attributeId' },
|
|
890
|
+
{ key: 'attribute_option_id', labelKey: 'attributeOptionId' },
|
|
891
|
+
{ key: 'raw_value', labelKey: 'rawValue' },
|
|
892
|
+
{ key: 'value_text', labelKey: 'valueText' },
|
|
893
|
+
{ key: 'is_verified', labelKey: 'isVerified', type: 'boolean' },
|
|
894
|
+
],
|
|
895
|
+
contextualKpi: { translationKey: 'verifiedInSlice', icon: BadgePercent, count: (records) => records.filter((record) => record.is_verified === true).length },
|
|
896
|
+
template: { product_id: null, attribute_id: null, attribute_option_id: null, value_text: '', value_number: null, value_boolean: null, raw_value: '', value_unit: '', normalized_value: '', normalized_text: '', normalized_number: null, source_type: 'manual', confidence_score: null, is_verified: false },
|
|
897
|
+
formSections: [{
|
|
898
|
+
title: ptEn('Valor', 'Value'),
|
|
899
|
+
fields: [
|
|
900
|
+
{ key: 'product_id', label: ptEn('Produto', 'Product'), type: 'relation', required: true, relation: relation('/catalog/products', ['name', 'model_name', 'slug'], { resource: 'products' }) },
|
|
901
|
+
{ key: 'attribute_id', label: ptEn('Atributo', 'Attribute'), type: 'relation', required: true, relation: relation('/catalog/attributes', ['name', 'code', 'slug'], { resource: 'attributes' }) },
|
|
902
|
+
{ key: 'attribute_option_id', label: ptEn('Opção', 'Option'), type: 'relation', relation: relation('/catalog/attribute-options', ['label', 'option_value'], { resource: 'attribute-options' }) },
|
|
903
|
+
{ key: 'raw_value', label: ptEn('Valor bruto', 'Raw value'), type: 'textarea', span: 2 },
|
|
904
|
+
{ key: 'value_text', label: ptEn('Texto', 'Text'), type: 'text' },
|
|
905
|
+
{ key: 'value_number', label: ptEn('Número', 'Number'), type: 'number' },
|
|
906
|
+
{ key: 'value_unit', label: ptEn('Unidade', 'Unit'), type: 'text' },
|
|
907
|
+
{ key: 'normalized_value', label: ptEn('Valor normalizado', 'Normalized value'), type: 'text' },
|
|
908
|
+
{ key: 'source_type', label: ptEn('Origem', 'Source'), type: 'select', options: [{ value: 'manual', label: ptEn('Manual', 'Manual') }, { value: 'import', label: ptEn('Importação', 'Import') }, { value: 'computed', label: ptEn('Calculado', 'Computed') }] },
|
|
909
|
+
{ key: 'confidence_score', label: ptEn('Confiança', 'Confidence'), type: 'number' },
|
|
910
|
+
{ key: 'is_verified', label: ptEn('Verificado', 'Verified'), type: 'switch' },
|
|
911
|
+
],
|
|
912
|
+
}],
|
|
913
|
+
}
|
|
1132
914
|
);
|
|
1133
915
|
|
|
916
|
+
export const catalogResourceMap = new Map(catalogResources.map((resource) => [resource.resource, resource]));
|
|
1134
917
|
export const catalogDashboardHref = '/catalog/dashboard';
|
|
1135
|
-
|
|
1136
|
-
export const
|
|
1137
|
-
(resource) => resource.featured
|
|
1138
|
-
);
|
|
1139
|
-
|
|
1140
|
-
export const catalogKpiResources = ['products', 'brands', 'offers', 'merchants'];
|
|
918
|
+
export const catalogQuickActionResources = catalogResources.filter((resource) => resource.featured);
|
|
919
|
+
export const catalogKpiResources = ['categories', 'products', 'brands', 'offers'];
|
|
1141
920
|
|
|
1142
921
|
export function getCatalogRecordLabel(record: Record<string, unknown>) {
|
|
1143
|
-
return
|
|
1144
|
-
record.name ||
|
|
1145
|
-
record.title ||
|
|
1146
|
-
record.label ||
|
|
1147
|
-
record.slug ||
|
|
1148
|
-
record.rule_slug ||
|
|
1149
|
-
record.external_offer_id ||
|
|
1150
|
-
`#${record.id}`
|
|
1151
|
-
);
|
|
922
|
+
return record.name || record.title || record.label || record.code || record.slug || record.rule_slug || record.option_value || record.external_offer_id || `#${record.id}`;
|
|
1152
923
|
}
|
|
1153
924
|
|
|
1154
|
-
export function getCatalogLocalizedText(
|
|
1155
|
-
value: CatalogLocalizedText,
|
|
1156
|
-
localeCode?: string | null
|
|
1157
|
-
) {
|
|
925
|
+
export function getCatalogLocalizedText(value: CatalogLocalizedText, localeCode?: string | null) {
|
|
1158
926
|
return localeCode?.toLowerCase().startsWith('pt') ? value.pt : value.en;
|
|
1159
927
|
}
|
|
1160
928
|
|