@motor-cms/ui-admin 1.16.2 → 2.0.0

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.
@@ -0,0 +1,252 @@
1
+ import { z } from 'zod'
2
+ import type { FormFieldConfig, FormGroupConfig } from '@motor-cms/ui-core/app/types/form'
3
+
4
+ // ============================================
5
+ // FrontendConfig Interface (full JSON column)
6
+ // ============================================
7
+
8
+ export interface FrontendConfig {
9
+ brand: {
10
+ name: string
11
+ logoAlt: string
12
+ }
13
+ colorScheme: string
14
+ logoSlug: string
15
+ contact: {
16
+ contactUrl: string
17
+ email: string
18
+ whatsappUrl: string | null
19
+ }
20
+ features: {
21
+ orderLine: boolean
22
+ appointments: boolean
23
+ clickpath: boolean
24
+ footerMenu: boolean
25
+ }
26
+ social: {
27
+ instagram: string | null
28
+ facebook: string | null
29
+ }
30
+ seo: {
31
+ siteName: string
32
+ }
33
+ globalComponents?: {
34
+ footer?: Record<string, string> // language_id -> builder_page_uuid
35
+ }
36
+ }
37
+
38
+ // ============================================
39
+ // Zod Schema (editable fields only, no globalComponents)
40
+ // ============================================
41
+
42
+ const optionalUrlSchema = z.string().refine(
43
+ (val) => val === '' || val === null || (() => { try { new URL(val); return true } catch { return false } })(),
44
+ { message: 'Must be a valid URL or empty' }
45
+ )
46
+
47
+ export const frontendConfigSchema = z.object({
48
+ brand: z.object({
49
+ name: z.string().min(1, { message: 'Required' }),
50
+ logoAlt: z.string().min(1, { message: 'Required' })
51
+ }),
52
+ colorScheme: z.string().min(1, { message: 'Required' }),
53
+ logoSlug: z.string().min(1, { message: 'Required' }),
54
+ contact: z.object({
55
+ contactUrl: z.string().url({ message: 'Must be a valid URL' }),
56
+ email: z.string().email({ message: 'Must be a valid email' }),
57
+ whatsappUrl: optionalUrlSchema.nullable().optional().transform((v) => v ?? null)
58
+ }),
59
+ features: z.object({
60
+ orderLine: z.boolean().default(false),
61
+ appointments: z.boolean().default(false),
62
+ clickpath: z.boolean().default(false),
63
+ footerMenu: z.boolean().default(false)
64
+ }),
65
+ social: z.object({
66
+ instagram: optionalUrlSchema.nullable().optional().transform((v) => v ?? null),
67
+ facebook: optionalUrlSchema.nullable().optional().transform((v) => v ?? null)
68
+ }),
69
+ seo: z.object({
70
+ siteName: z.string().min(1, { message: 'Required' })
71
+ })
72
+ })
73
+
74
+ export type FrontendConfigFormState = z.infer<typeof frontendConfigSchema>
75
+
76
+ // ============================================
77
+ // Form Field Definitions
78
+ // ============================================
79
+
80
+ export function frontendConfigFields(t: (key: string) => string): FormFieldConfig[] {
81
+ return [
82
+ // Brand group
83
+ {
84
+ key: 'brand.name',
85
+ label: t('motor-admin.clients.frontend_config.brand_name'),
86
+ input: 'text',
87
+ required: true,
88
+ group: 'fc_brand'
89
+ },
90
+ {
91
+ key: 'brand.logoAlt',
92
+ label: t('motor-admin.clients.frontend_config.brand_logo_alt'),
93
+ input: 'text',
94
+ required: true,
95
+ group: 'fc_brand'
96
+ },
97
+ {
98
+ key: 'colorScheme',
99
+ label: t('motor-admin.clients.frontend_config.color_scheme'),
100
+ input: 'select',
101
+ required: true,
102
+ group: 'fc_brand'
103
+ },
104
+ {
105
+ key: 'logoSlug',
106
+ label: t('motor-admin.clients.frontend_config.logo_slug'),
107
+ input: 'select',
108
+ required: true,
109
+ group: 'fc_brand'
110
+ },
111
+
112
+ // Contact group
113
+ {
114
+ key: 'contact.contactUrl',
115
+ label: t('motor-admin.clients.frontend_config.contact_url'),
116
+ input: 'url',
117
+ required: true,
118
+ group: 'fc_contact'
119
+ },
120
+ {
121
+ key: 'contact.email',
122
+ label: t('motor-admin.clients.frontend_config.contact_email'),
123
+ input: 'email',
124
+ required: true,
125
+ group: 'fc_contact'
126
+ },
127
+ {
128
+ key: 'contact.whatsappUrl',
129
+ label: t('motor-admin.clients.frontend_config.contact_whatsapp_url'),
130
+ input: 'url',
131
+ required: false,
132
+ group: 'fc_contact'
133
+ },
134
+
135
+ // Features group
136
+ {
137
+ key: 'features.orderLine',
138
+ label: t('motor-admin.clients.frontend_config.features_order_line'),
139
+ input: 'toggle',
140
+ required: false,
141
+ group: 'fc_features'
142
+ },
143
+ {
144
+ key: 'features.appointments',
145
+ label: t('motor-admin.clients.frontend_config.features_appointments'),
146
+ input: 'toggle',
147
+ required: false,
148
+ group: 'fc_features'
149
+ },
150
+ {
151
+ key: 'features.clickpath',
152
+ label: t('motor-admin.clients.frontend_config.features_clickpath'),
153
+ input: 'toggle',
154
+ required: false,
155
+ group: 'fc_features'
156
+ },
157
+ {
158
+ key: 'features.footerMenu',
159
+ label: t('motor-admin.clients.frontend_config.features_footer_menu'),
160
+ input: 'toggle',
161
+ required: false,
162
+ group: 'fc_features'
163
+ },
164
+
165
+ // Social group
166
+ {
167
+ key: 'social.instagram',
168
+ label: t('motor-admin.clients.frontend_config.social_instagram'),
169
+ input: 'url',
170
+ required: false,
171
+ group: 'fc_social'
172
+ },
173
+ {
174
+ key: 'social.facebook',
175
+ label: t('motor-admin.clients.frontend_config.social_facebook'),
176
+ input: 'url',
177
+ required: false,
178
+ group: 'fc_social'
179
+ },
180
+
181
+ // SEO group
182
+ {
183
+ key: 'seo.siteName',
184
+ label: t('motor-admin.clients.frontend_config.seo_site_name'),
185
+ input: 'text',
186
+ required: true,
187
+ group: 'fc_seo'
188
+ }
189
+ ]
190
+ }
191
+
192
+ // ============================================
193
+ // Form Group Definitions
194
+ // ============================================
195
+
196
+ export function frontendConfigGroups(t: (key: string) => string): FormGroupConfig[] {
197
+ return [
198
+ {
199
+ key: 'fc_brand',
200
+ label: t('motor-admin.clients.frontend_config.group_brand')
201
+ },
202
+ {
203
+ key: 'fc_contact',
204
+ label: t('motor-admin.clients.frontend_config.group_contact')
205
+ },
206
+ {
207
+ key: 'fc_features',
208
+ label: t('motor-admin.clients.frontend_config.group_features')
209
+ },
210
+ {
211
+ key: 'fc_social',
212
+ label: t('motor-admin.clients.frontend_config.group_social')
213
+ },
214
+ {
215
+ key: 'fc_seo',
216
+ label: t('motor-admin.clients.frontend_config.group_seo')
217
+ }
218
+ ]
219
+ }
220
+
221
+ // ============================================
222
+ // Default Empty State
223
+ // ============================================
224
+
225
+ export function emptyFrontendConfig(): FrontendConfigFormState {
226
+ return {
227
+ brand: {
228
+ name: '',
229
+ logoAlt: ''
230
+ },
231
+ colorScheme: '',
232
+ logoSlug: '',
233
+ contact: {
234
+ contactUrl: '',
235
+ email: '',
236
+ whatsappUrl: null
237
+ },
238
+ features: {
239
+ orderLine: false,
240
+ appointments: false,
241
+ clickpath: false,
242
+ footerMenu: false
243
+ },
244
+ social: {
245
+ instagram: null,
246
+ facebook: null
247
+ },
248
+ seo: {
249
+ siteName: ''
250
+ }
251
+ }
252
+ }
package/nuxt.config.ts CHANGED
@@ -6,4 +6,10 @@ const __layerDir = dirname(fileURLToPath(import.meta.url))
6
6
  export default defineNuxtConfig({
7
7
  modules: ['v-onboarding/nuxt'],
8
8
  css: [resolve(__layerDir, 'app/assets/css/v-onboarding.css')],
9
+ runtimeConfig: {
10
+ public: {
11
+ featureClientFrontendConfig:
12
+ process.env.NUXT_PUBLIC_FEATURE_CLIENT_FRONTEND_CONFIG === 'true'
13
+ }
14
+ }
9
15
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motor-cms/ui-admin",
3
- "version": "1.16.2",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "main": "./nuxt.config.ts",
6
6
  "files": [
@@ -20,7 +20,7 @@
20
20
  "zod": "^4.0.0"
21
21
  },
22
22
  "peerDependencies": {
23
- "@motor-cms/ui-core": ">=1.16.2",
23
+ "@motor-cms/ui-core": ">=2.0.0",
24
24
  "nuxt": "^4.0.0",
25
25
  "vue": "^3.5.0"
26
26
  }