@hedhog/admin 0.51.16 → 0.51.21

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.
Files changed (61) hide show
  1. package/dist/admin.module.d.ts.map +1 -1
  2. package/dist/admin.module.js +5 -0
  3. package/dist/admin.module.js.map +1 -1
  4. package/dist/auth/auth.controller.d.ts +12 -6
  5. package/dist/auth/auth.controller.d.ts.map +1 -1
  6. package/dist/auth/auth.controller.js +57 -24
  7. package/dist/auth/auth.controller.js.map +1 -1
  8. package/dist/auth/auth.module.d.ts.map +1 -1
  9. package/dist/auth/auth.module.js +4 -0
  10. package/dist/auth/auth.module.js.map +1 -1
  11. package/dist/auth/auth.service.d.ts +19 -10
  12. package/dist/auth/auth.service.d.ts.map +1 -1
  13. package/dist/auth/auth.service.js +104 -45
  14. package/dist/auth/auth.service.js.map +1 -1
  15. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +11 -11
  16. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +11 -11
  17. package/dist/dashboard/dashboard-user/dashboard-user.controller.d.ts +3 -3
  18. package/dist/dashboard/dashboard-user/dashboard-user.service.d.ts +3 -3
  19. package/dist/menu/menu.controller.d.ts +3 -3
  20. package/dist/menu/menu.service.d.ts +3 -3
  21. package/dist/setting/setting.service.d.ts.map +1 -1
  22. package/dist/setting/setting.service.js +17 -11
  23. package/dist/setting/setting.service.js.map +1 -1
  24. package/frontend/dashboard/components/create-panel.tsx.ejs +63 -63
  25. package/frontend/dashboard/components/dashboard.screen.tsx.ejs +116 -116
  26. package/frontend/dashboard/components/update-panel.tsx.ejs +80 -80
  27. package/frontend/dashboard/locales/en/dashboard.dashboard.json +11 -11
  28. package/frontend/dashboard/locales/pt/dashboard.dashboard.json +11 -11
  29. package/frontend/dashboard/react-query/handlers.ts.ejs +28 -28
  30. package/frontend/dashboard/react-query/requests.ts.ejs +56 -56
  31. package/frontend/dashboard-component/components/create-panel.tsx.ejs +130 -130
  32. package/frontend/dashboard-component/components/update-panel.tsx.ejs +164 -164
  33. package/frontend/dashboard-component/locales/en/dashboard.dashboard-component.json +11 -11
  34. package/frontend/dashboard-component/locales/pt/dashboard.dashboard-component.json +11 -11
  35. package/frontend/dashboard-component/react-query/handlers.ts.ejs +28 -28
  36. package/frontend/dashboard-component/react-query/requests.ts.ejs +61 -61
  37. package/frontend/dashboard-item/components/create-panel.tsx.ejs +108 -108
  38. package/frontend/dashboard-item/components/update-panel.tsx.ejs +141 -141
  39. package/frontend/dashboard-item/locales/en/dashboard.dashboard-item.json +11 -11
  40. package/frontend/dashboard-item/locales/pt/dashboard.dashboard-item.json +11 -11
  41. package/frontend/dashboard-item/react-query/handlers.ts.ejs +28 -28
  42. package/frontend/dashboard-item/react-query/requests.ts.ejs +58 -58
  43. package/frontend/dashboard-user/components/create-panel.tsx.ejs +108 -108
  44. package/frontend/dashboard-user/components/update-panel.tsx.ejs +137 -137
  45. package/frontend/dashboard-user/locales/en/dashboard.dashboard-user.json +11 -11
  46. package/frontend/dashboard-user/locales/pt/dashboard.dashboard-user.json +11 -11
  47. package/frontend/dashboard-user/react-query/handlers.ts.ejs +28 -28
  48. package/frontend/dashboard-user/react-query/requests.ts.ejs +58 -58
  49. package/hedhog.yaml +2 -2
  50. package/package.json +7 -6
  51. package/src/admin.module.ts +5 -0
  52. package/src/auth/auth.controller.ts +37 -11
  53. package/src/auth/auth.module.ts +4 -0
  54. package/src/auth/auth.service.ts +154 -63
  55. package/src/dashboard/dashboard-component/dashboard-component.controller.ts +55 -55
  56. package/src/dashboard/dashboard-component/dto/create.dto.ts +36 -36
  57. package/src/dashboard/dashboard-component/dto/update.dto.ts +4 -4
  58. package/src/dashboard/dashboard-item/dto/update.dto.ts +4 -4
  59. package/src/dashboard/dashboard-user/dto/update.dto.ts +4 -4
  60. package/src/dashboard/index.ts +1 -1
  61. package/src/setting/setting.service.ts +16 -11
@@ -1,5 +1,6 @@
1
- import { MailService } from '@hedhog/mail';
1
+ import { MailService as MailManagerService } from '@hedhog/mail-manager';
2
2
  import { PrismaService } from '@hedhog/prisma';
3
+ import { HttpService } from '@nestjs/axios';
3
4
  import {
4
5
  BadRequestException,
5
6
  ConflictException,
@@ -13,14 +14,8 @@ import { ConfigService } from '@nestjs/config';
13
14
  import { JwtService } from '@nestjs/jwt';
14
15
  import { compare, genSalt, hash } from 'bcrypt';
15
16
  import * as qrcode from 'qrcode';
17
+ import { lastValueFrom } from 'rxjs';
16
18
  import * as speakeasy from 'speakeasy';
17
- import {
18
- getChangeEmailEmail,
19
- getChangePasswordEmail,
20
- getCreateUserEmail,
21
- getForgetPasswordEmail,
22
- getResetPasswordEmail,
23
- } from '../emails';
24
19
  import { SettingService } from '../setting/setting.service';
25
20
  import { ChangeDTO } from './dto/change.dto';
26
21
  import { CreateUserDTO } from './dto/create-user.dto';
@@ -34,16 +29,17 @@ import { MultifactorType } from './enums/multifactor-type.enum';
34
29
 
35
30
  @Injectable()
36
31
  export class AuthService implements OnModuleInit {
37
- private settings: Record<string, any> = {};
32
+ public settings: Record<string, any> = {};
38
33
 
39
34
  constructor(
35
+ private readonly httpService: HttpService,
40
36
  private readonly configService: ConfigService,
41
37
  @Inject(forwardRef(() => PrismaService))
42
38
  private readonly prisma: PrismaService,
43
39
  @Inject(forwardRef(() => JwtService))
44
40
  private readonly jwt: JwtService,
45
- @Inject(forwardRef(() => MailService))
46
- private readonly mail: MailService,
41
+ @Inject(forwardRef(() => MailManagerService))
42
+ private readonly mail: MailManagerService,
47
43
  @Inject(forwardRef(() => SettingService))
48
44
  private readonly setting: SettingService,
49
45
  ) {}
@@ -54,6 +50,10 @@ export class AuthService implements OnModuleInit {
54
50
  'mfa-window',
55
51
  'mfa-setp',
56
52
  'system-name',
53
+ 'google_client_id',
54
+ 'google_client_secret',
55
+ 'google_scopes',
56
+ 'url',
57
57
  ]);
58
58
  }
59
59
 
@@ -109,17 +109,20 @@ export class AuthService implements OnModuleInit {
109
109
  return this.getToken(newUser);
110
110
  }
111
111
 
112
- async createUser({
113
- code,
114
- password,
115
- street,
116
- number,
117
- complement,
118
- district,
119
- city,
120
- state,
121
- postal_code,
122
- }: CreateUserDTO) {
112
+ async createUser(
113
+ locale: string,
114
+ {
115
+ code,
116
+ password,
117
+ street,
118
+ number,
119
+ complement,
120
+ district,
121
+ city,
122
+ state,
123
+ postal_code,
124
+ }: CreateUserDTO,
125
+ ) {
123
126
  try {
124
127
  const user = await this.createUserCheck(code);
125
128
  const salt = await genSalt();
@@ -184,12 +187,10 @@ export class AuthService implements OnModuleInit {
184
187
  });
185
188
  }
186
189
 
187
- await this.mail.send({
188
- to: user.email,
189
- subject: 'Conta criada',
190
- body: getCreateUserEmail({
191
- name: user.name,
192
- }),
190
+ await this.mail.sendTemplatedMail(locale, {
191
+ email: user.email,
192
+ slug: 'create-user',
193
+ variables: {},
193
194
  });
194
195
 
195
196
  return this.getToken(user);
@@ -221,7 +222,11 @@ export class AuthService implements OnModuleInit {
221
222
  return Math.floor(Math.random() * (max - min + 1)) + min;
222
223
  }
223
224
 
224
- async loginWithEmailAndPassword(email: string, password: string) {
225
+ async loginWithEmailAndPassword(
226
+ locale: string,
227
+ email: string,
228
+ password: string,
229
+ ) {
225
230
  const user = await this.prisma.user.findFirst({
226
231
  where: {
227
232
  email,
@@ -237,8 +242,6 @@ export class AuthService implements OnModuleInit {
237
242
  throw new BadRequestException('Acesso negado');
238
243
  }
239
244
 
240
- console.log('loginWithEmailAndPassword', { user });
241
-
242
245
  if (!user.multifactor_id) {
243
246
  return this.getToken(user);
244
247
  } else {
@@ -255,10 +258,10 @@ export class AuthService implements OnModuleInit {
255
258
  },
256
259
  });
257
260
 
258
- await this.mail.send({
259
- to: user.email,
260
- subject: 'Código de Login',
261
- body: `Seu código de login é ${code}`,
261
+ await this.mail.sendTemplatedMail(locale, {
262
+ email: user.email,
263
+ slug: 'login',
264
+ variables: { code: String(code) },
262
265
  });
263
266
 
264
267
  return {
@@ -290,7 +293,7 @@ export class AuthService implements OnModuleInit {
290
293
  };
291
294
  }
292
295
 
293
- async forget({ email }: ForgetDTO) {
296
+ async forget(locale: string, { email }: ForgetDTO) {
294
297
  const appUrl =
295
298
  process.env.APP_URL ?? this.configService.get<string>('APP_URL');
296
299
 
@@ -319,10 +322,13 @@ export class AuthService implements OnModuleInit {
319
322
  },
320
323
  });
321
324
 
322
- await this.mail.send({
323
- to: email,
324
- subject: `Recuperação de Senha`,
325
- body: getForgetPasswordEmail(`${appUrl}/home?reset&code=${code}`),
325
+ await this.mail.sendTemplatedMail(locale, {
326
+ email,
327
+ slug: 'forget',
328
+ variables: {
329
+ appUrl,
330
+ code,
331
+ },
326
332
  });
327
333
  }
328
334
 
@@ -332,12 +338,10 @@ export class AuthService implements OnModuleInit {
332
338
  };
333
339
  }
334
340
 
335
- async changePassword({
336
- email,
337
- currentPassword,
338
- newPassword,
339
- confirmNewPassword,
340
- }: ChangeDTO) {
341
+ async changePassword(
342
+ locale: string,
343
+ { email, currentPassword, newPassword, confirmNewPassword }: ChangeDTO,
344
+ ) {
341
345
  if (newPassword !== confirmNewPassword) {
342
346
  throw new BadRequestException('Senhas não conferem');
343
347
  }
@@ -362,16 +366,19 @@ export class AuthService implements OnModuleInit {
362
366
  },
363
367
  });
364
368
 
365
- await this.mail.send({
366
- to: email,
367
- subject: `Senha alterada`,
368
- body: getChangePasswordEmail(),
369
+ await this.mail.sendTemplatedMail(locale, {
370
+ email,
371
+ slug: 'change-password',
372
+ variables: {},
369
373
  });
370
374
 
371
375
  return this.getToken(newUser);
372
376
  }
373
377
 
374
- async changeEmail({ currentEmail, password, newEmail }: EmailDTO) {
378
+ async changeEmail(
379
+ locale: string,
380
+ { currentEmail, password, newEmail }: EmailDTO,
381
+ ) {
375
382
  const user = await this.prisma.user.findFirst({
376
383
  where: { email: currentEmail },
377
384
  });
@@ -419,16 +426,19 @@ export class AuthService implements OnModuleInit {
419
426
  data: { value: newEmail },
420
427
  });
421
428
 
422
- await this.mail.send({
423
- to: newEmail,
424
- subject: `Email alterado`,
425
- body: getChangeEmailEmail(),
429
+ await this.mail.sendTemplatedMail(locale, {
430
+ email: newEmail,
431
+ slug: 'change-email',
432
+ variables: {},
426
433
  });
427
434
 
428
435
  return this.getToken(newUser);
429
436
  }
430
437
 
431
- async resetPassword({ code, newPassword, confirmNewPassword }: ResetDTO) {
438
+ async resetPassword(
439
+ locale: string,
440
+ { code, newPassword, confirmNewPassword }: ResetDTO,
441
+ ) {
432
442
  if (newPassword !== confirmNewPassword) {
433
443
  throw new BadRequestException('Senhas não conferem');
434
444
  }
@@ -459,10 +469,10 @@ export class AuthService implements OnModuleInit {
459
469
  },
460
470
  });
461
471
 
462
- await this.mail.send({
463
- to: user.email,
464
- subject: `Senha recuperada`,
465
- body: getResetPasswordEmail(),
472
+ await this.mail.sendTemplatedMail(locale, {
473
+ email: user.email,
474
+ slug: 'reset-password',
475
+ variables: {},
466
476
  });
467
477
 
468
478
  return this.getToken(user);
@@ -513,7 +523,6 @@ export class AuthService implements OnModuleInit {
513
523
 
514
524
  switch (data.mfa) {
515
525
  case MultifactorType.EMAIL:
516
- //TO DO
517
526
  case MultifactorType.APP:
518
527
  const codes = await this.prisma.user_code_recovery.findMany({
519
528
  where: {
@@ -602,8 +611,8 @@ export class AuthService implements OnModuleInit {
602
611
  }
603
612
  }
604
613
 
605
- async login({ email, password }: LoginDTO) {
606
- return this.loginWithEmailAndPassword(email, password);
614
+ async login(locale: string, { email, password }: LoginDTO) {
615
+ return this.loginWithEmailAndPassword(locale, email, password);
607
616
  }
608
617
 
609
618
  async verify(id: number) {
@@ -764,4 +773,86 @@ export class AuthService implements OnModuleInit {
764
773
 
765
774
  return { ...this.getToken(user), codes };
766
775
  }
776
+
777
+ async loginGoogle(res: any) {
778
+ const redirectURI = new URL(
779
+ '/auth/google/callback',
780
+ this.settings['url'],
781
+ ).toString();
782
+
783
+ const params = new URLSearchParams({
784
+ client_id: this.settings['google_client_id'],
785
+ redirect_uri: redirectURI,
786
+ response_type: 'code',
787
+ scope: this.settings['google_scopes'].join(' '),
788
+ });
789
+
790
+ const url = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
791
+
792
+ return res.redirect(url);
793
+ }
794
+
795
+ async callbackGoogle(code: string) {
796
+ const tokenUrl = 'https://oauth2.googleapis.com/token';
797
+ const profileUrl = 'https://www.googleapis.com/oauth2/v2/userinfo';
798
+
799
+ const tokenResponse = await this.fetchGoogleToken(code, tokenUrl);
800
+ const profile = await this.fetchGoogleProfile(
801
+ tokenResponse.access_token,
802
+ profileUrl,
803
+ );
804
+
805
+ let user = await this.findOrCreateUser(profile);
806
+
807
+ return this.getToken(user);
808
+ }
809
+
810
+ private async fetchGoogleToken(code: string, url: string) {
811
+ const response = await lastValueFrom(
812
+ this.httpService.post(
813
+ url,
814
+ {
815
+ client_id: this.settings['google_client_id'],
816
+ client_secret: this.settings['google_client_secret'],
817
+ redirect_uri: `${this.settings['url']}/auth/google/callback`,
818
+ grant_type: 'authorization_code',
819
+ code,
820
+ },
821
+ {
822
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
823
+ },
824
+ ),
825
+ );
826
+
827
+ return response.data;
828
+ }
829
+
830
+ private async fetchGoogleProfile(accessToken: string, url: string) {
831
+ const response = await lastValueFrom(
832
+ this.httpService.get(url, {
833
+ headers: { Authorization: `Bearer ${accessToken}` },
834
+ }),
835
+ );
836
+
837
+ return response.data;
838
+ }
839
+
840
+ private async findOrCreateUser(profile: any) {
841
+ let user = await this.prisma.user.findFirst({
842
+ where: { email: profile.email },
843
+ });
844
+
845
+ if (!user) {
846
+ user = await this.prisma.user.create({
847
+ data: {
848
+ email: profile.email,
849
+ name: profile.name,
850
+ password: '',
851
+ code: profile.id,
852
+ },
853
+ });
854
+ }
855
+
856
+ return user;
857
+ }
767
858
  }
@@ -1,55 +1,55 @@
1
- import { Pagination } from '@hedhog/pagination';
2
- import { Locale } from '@hedhog/locale';
3
- import {
4
- Body,
5
- Controller,
6
- Delete,
7
- Get,
8
- Inject,
9
- Param,
10
- ParseIntPipe,
11
- Patch,
12
- Post,
13
- forwardRef
14
- } from '@nestjs/common';
15
- import { CreateDTO } from './dto/create.dto';
16
- import { UpdateDTO } from './dto/update.dto';
17
- import { DashboardComponentService } from './dashboard-component.service';
18
- import { Role, DeleteDTO } from '@hedhog/core';
19
-
20
- @Role()
21
- @Controller('dashboard-component')
22
- export class DashboardComponentController {
23
- constructor(
24
- @Inject(forwardRef(() => DashboardComponentService))
25
- private readonly dashboardComponentService: DashboardComponentService
26
- ) {}
27
-
28
- @Get()
29
- async list(@Locale() locale, @Pagination() paginationParams) {
30
- return this.dashboardComponentService.list(locale, paginationParams);
31
- }
32
-
33
- @Get(':id')
34
- async get(@Param('id', ParseIntPipe) id: number) {
35
- return this.dashboardComponentService.get(id);
36
- }
37
-
38
- @Post()
39
- async create(@Body() data: CreateDTO) {
40
- return this.dashboardComponentService.create(data);
41
- }
42
-
43
- @Patch(':id')
44
- async update(@Param('id', ParseIntPipe) id: number, @Body() data: UpdateDTO) {
45
- return this.dashboardComponentService.update({
46
- id,
47
- data
48
- });
49
- }
50
-
51
- @Delete()
52
- async delete(@Body() data: DeleteDTO) {
53
- return this.dashboardComponentService.delete(data);
54
- }
55
- }
1
+ import { Pagination } from '@hedhog/pagination';
2
+ import { Locale } from '@hedhog/locale';
3
+ import {
4
+ Body,
5
+ Controller,
6
+ Delete,
7
+ Get,
8
+ Inject,
9
+ Param,
10
+ ParseIntPipe,
11
+ Patch,
12
+ Post,
13
+ forwardRef
14
+ } from '@nestjs/common';
15
+ import { CreateDTO } from './dto/create.dto';
16
+ import { UpdateDTO } from './dto/update.dto';
17
+ import { DashboardComponentService } from './dashboard-component.service';
18
+ import { Role, DeleteDTO } from '@hedhog/core';
19
+
20
+ @Role()
21
+ @Controller('dashboard-component')
22
+ export class DashboardComponentController {
23
+ constructor(
24
+ @Inject(forwardRef(() => DashboardComponentService))
25
+ private readonly dashboardComponentService: DashboardComponentService
26
+ ) {}
27
+
28
+ @Get()
29
+ async list(@Locale() locale, @Pagination() paginationParams) {
30
+ return this.dashboardComponentService.list(locale, paginationParams);
31
+ }
32
+
33
+ @Get(':id')
34
+ async get(@Param('id', ParseIntPipe) id: number) {
35
+ return this.dashboardComponentService.get(id);
36
+ }
37
+
38
+ @Post()
39
+ async create(@Body() data: CreateDTO) {
40
+ return this.dashboardComponentService.create(data);
41
+ }
42
+
43
+ @Patch(':id')
44
+ async update(@Param('id', ParseIntPipe) id: number, @Body() data: UpdateDTO) {
45
+ return this.dashboardComponentService.update({
46
+ id,
47
+ data
48
+ });
49
+ }
50
+
51
+ @Delete()
52
+ async delete(@Body() data: DeleteDTO) {
53
+ return this.dashboardComponentService.delete(data);
54
+ }
55
+ }
@@ -1,36 +1,36 @@
1
- import { IsString, IsNumber, IsBoolean, IsOptional } from 'class-validator';
2
- import { WithLocaleDTO } from '@hedhog/locale';
3
-
4
- export class CreateDTO extends WithLocaleDTO {
5
- @IsString()
6
- slug: string;
7
-
8
- @IsString()
9
- path: string;
10
-
11
- @IsOptional()
12
- @IsNumber()
13
- min_width?: number;
14
-
15
- @IsOptional()
16
- @IsNumber()
17
- max_width?: number;
18
-
19
- @IsOptional()
20
- @IsNumber()
21
- min_height?: number;
22
-
23
- @IsOptional()
24
- @IsNumber()
25
- max_height?: number;
26
-
27
- @IsNumber()
28
- width: number;
29
-
30
- @IsNumber()
31
- height: number;
32
-
33
- @IsOptional()
34
- @IsBoolean()
35
- is_resizable?: boolean;
36
- }
1
+ import { IsString, IsNumber, IsBoolean, IsOptional } from 'class-validator';
2
+ import { WithLocaleDTO } from '@hedhog/locale';
3
+
4
+ export class CreateDTO extends WithLocaleDTO {
5
+ @IsString()
6
+ slug: string;
7
+
8
+ @IsString()
9
+ path: string;
10
+
11
+ @IsOptional()
12
+ @IsNumber()
13
+ min_width?: number;
14
+
15
+ @IsOptional()
16
+ @IsNumber()
17
+ max_width?: number;
18
+
19
+ @IsOptional()
20
+ @IsNumber()
21
+ min_height?: number;
22
+
23
+ @IsOptional()
24
+ @IsNumber()
25
+ max_height?: number;
26
+
27
+ @IsNumber()
28
+ width: number;
29
+
30
+ @IsNumber()
31
+ height: number;
32
+
33
+ @IsOptional()
34
+ @IsBoolean()
35
+ is_resizable?: boolean;
36
+ }
@@ -1,4 +1,4 @@
1
- import { PartialType } from '@nestjs/mapped-types';
2
- import { CreateDTO } from './create.dto';
3
-
4
- export class UpdateDTO extends PartialType(CreateDTO) {}
1
+ import { PartialType } from '@nestjs/mapped-types';
2
+ import { CreateDTO } from './create.dto';
3
+
4
+ export class UpdateDTO extends PartialType(CreateDTO) {}
@@ -1,4 +1,4 @@
1
- import { PartialType } from '@nestjs/mapped-types';
2
- import { CreateDTO } from './create.dto';
3
-
4
- export class UpdateDTO extends PartialType(CreateDTO) {}
1
+ import { PartialType } from '@nestjs/mapped-types';
2
+ import { CreateDTO } from './create.dto';
3
+
4
+ export class UpdateDTO extends PartialType(CreateDTO) {}
@@ -1,4 +1,4 @@
1
- import { PartialType } from '@nestjs/mapped-types';
2
- import { CreateDTO } from './create.dto';
3
-
4
- export class UpdateDTO extends PartialType(CreateDTO) {}
1
+ import { PartialType } from '@nestjs/mapped-types';
2
+ import { CreateDTO } from './create.dto';
3
+
4
+ export class UpdateDTO extends PartialType(CreateDTO) {}
@@ -1 +1 @@
1
- export * from './dashboard.module';
1
+ export * from './dashboard.module';
@@ -344,7 +344,7 @@ export class SettingService {
344
344
  },
345
345
  });
346
346
 
347
- const slugUserOverride = setting.filter((setting) => setting.user_override);
347
+ const slugUserOverride = setting.filter((s) => s.user_override);
348
348
 
349
349
  const settingUser = await this.prismaService.setting_user.findMany({
350
350
  where: {
@@ -360,26 +360,31 @@ export class SettingService {
360
360
 
361
361
  const data: Record<string, any> = {};
362
362
 
363
- setting.forEach((setting) => {
364
- switch (setting.type) {
363
+ for (const s of setting) {
364
+ switch (s.type) {
365
365
  case 'boolean':
366
- data[setting.slug] = setting.value === 'true';
366
+ data[s.slug] = s.value === 'true';
367
367
  break;
368
368
  case 'number':
369
- data[setting.slug] = Number(setting.value);
369
+ data[s.slug] = Number(s.value);
370
370
  break;
371
371
  case 'array':
372
372
  case 'json':
373
- data[setting.slug] = JSON.parse(setting.value);
373
+ try {
374
+ data[s.slug] = JSON.parse(s.value);
375
+ } catch (err) {
376
+ console.error('Error parsing JSON', s.value, err);
377
+ data[s.slug] = s.value;
378
+ }
374
379
  break;
375
380
  default:
376
- data[setting.slug] = setting.value;
381
+ data[s.slug] = s.value;
377
382
  }
378
- });
383
+ }
379
384
 
380
- settingUser.forEach((setting) => {
381
- data[slugUserOverride.find((s) => s.id === setting.setting_id).slug] =
382
- setting.value;
385
+ settingUser.forEach((ss) => {
386
+ data[slugUserOverride.find((s) => s.id === ss.setting_id).slug] =
387
+ ss.value;
383
388
  });
384
389
 
385
390
  return data;