app-tutor-ai-consumer 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/.adr-dir +1 -0
  2. package/.github/CODEOWNERS +1 -0
  3. package/.github/pull_request_template.md +46 -0
  4. package/.github/workflows/jira.yaml +13 -0
  5. package/.github/workflows/merge-checker.yaml +14 -0
  6. package/.github/workflows/pr-agent.yaml +17 -0
  7. package/.github/workflows/production.yml +155 -0
  8. package/.github/workflows/quality.yml +63 -0
  9. package/.github/workflows/rollback.yml +133 -0
  10. package/.github/workflows/staging.yml +153 -0
  11. package/.husky/commit-msg +1 -0
  12. package/.husky/post-merge +1 -0
  13. package/.husky/pre-commit +1 -0
  14. package/.nvmrc +1 -0
  15. package/.prettierignore +8 -0
  16. package/.prettierrc +20 -0
  17. package/.releaserc.json +22 -0
  18. package/CHANGELOG.md +7 -0
  19. package/babel.config.js +3 -0
  20. package/catalog-info.yaml +21 -0
  21. package/commitlint.config.js +8 -0
  22. package/config/certs/.keep +0 -0
  23. package/config/certs/ssl-generate.sh +12 -0
  24. package/config/rspack/rspack.config.js +176 -0
  25. package/config/rspack/utils/alias.js +12 -0
  26. package/config/rspack/utils/devserver.config.js +34 -0
  27. package/config/rspack/utils/envs.js +39 -0
  28. package/config/rspack/utils/paths.js +29 -0
  29. package/config/rspack/utils/plugins.js +41 -0
  30. package/config/vitest/__mocks__/i18n.tsx +15 -0
  31. package/config/vitest/index.ts +1 -0
  32. package/config/vitest/polyfills/global.js +19 -0
  33. package/config/vitest/setupTests.ts +26 -0
  34. package/config/vitest/vitest.config.mts +47 -0
  35. package/docs/README.md +15 -0
  36. package/docs/architecture/decisions/index.md +0 -0
  37. package/docs/architecture/decisions/templates/template.md +82 -0
  38. package/docs/architecture/design/index.md +0 -0
  39. package/environments/.env.development +42 -0
  40. package/environments/.env.production +41 -0
  41. package/environments/.env.staging +40 -0
  42. package/environments/.env.test +41 -0
  43. package/eslint.config.mjs +87 -0
  44. package/mkdocs.yaml +11 -0
  45. package/package.json +130 -0
  46. package/postcss.config.js +3 -0
  47. package/public/favicon.ico +0 -0
  48. package/public/index.html +18 -0
  49. package/scripts/generate-icon-types.js +31 -0
  50. package/src/@types/declarations.d.ts +25 -0
  51. package/src/@types/env.d.ts +1 -0
  52. package/src/@types/global.types.ts +64 -0
  53. package/src/@types/index.d.ts +16 -0
  54. package/src/config/i18n/constants.ts +9 -0
  55. package/src/config/i18n/hooks/index.ts +1 -0
  56. package/src/config/i18n/hooks/use-app-lang/index.ts +1 -0
  57. package/src/config/i18n/hooks/use-app-lang/use-app-lang.tsx +22 -0
  58. package/src/config/i18n/index.ts +5 -0
  59. package/src/config/i18n/init.ts +44 -0
  60. package/src/config/i18n/types.ts +5 -0
  61. package/src/config/i18n/utils/get-lang.ts +10 -0
  62. package/src/config/styles/global.css +171 -0
  63. package/src/config/styles/index.css +5 -0
  64. package/src/config/styles/shared-styles.module.css +16 -0
  65. package/src/config/tests/abstract-mock-generator.ts +9 -0
  66. package/src/config/tests/customRenderHook.tsx +32 -0
  67. package/src/config/tests/handlers.ts +7 -0
  68. package/src/config/tests/index.ts +4 -0
  69. package/src/config/tests/mockRequest.tsx +36 -0
  70. package/src/config/tests/types.ts +10 -0
  71. package/src/config/tests/utils.tsx +38 -0
  72. package/src/config/tests/worker.ts +5 -0
  73. package/src/config/tests/wrappers.tsx +50 -0
  74. package/src/development-bootstrap.tsx +26 -0
  75. package/src/index.tsx +26 -0
  76. package/src/lib/components/icons/icon-names.d.ts +2 -0
  77. package/src/lib/components/icons/icon.tsx +41 -0
  78. package/src/lib/components/icons/index.ts +1 -0
  79. package/src/lib/components/icons/send.svg +3 -0
  80. package/src/lib/components/index.ts +1 -0
  81. package/src/lib/components/spinner/index.ts +2 -0
  82. package/src/lib/components/spinner/spinner.tsx +25 -0
  83. package/src/lib/components/spinner/styles.module.css +31 -0
  84. package/src/lib/components/spinner/types.ts +1 -0
  85. package/src/lib/hooks/index.ts +1 -0
  86. package/src/lib/hooks/use-default-id/index.ts +1 -0
  87. package/src/lib/hooks/use-default-id/use-default-id.tsx +13 -0
  88. package/src/lib/utils/constants.ts +2 -0
  89. package/src/lib/utils/http-codes.ts +13 -0
  90. package/src/lib/utils/index.ts +3 -0
  91. package/src/lib/utils/languages.ts +7 -0
  92. package/src/main/index.ts +1 -0
  93. package/src/main/main.spec.tsx +15 -0
  94. package/src/main/main.tsx +27 -0
  95. package/src/main/styles.module.css +15 -0
  96. package/src/modules/create-message/components/chat-input/chat-input.tsx +29 -0
  97. package/src/modules/create-message/components/chat-input/index.ts +2 -0
  98. package/src/modules/create-message/components/chat-input/types.ts +3 -0
  99. package/src/modules/create-message/components/index.ts +1 -0
  100. package/src/modules/widget/components/ai-avatar/ai-avatar.tsx +59 -0
  101. package/src/modules/widget/components/ai-avatar/index.ts +1 -0
  102. package/src/modules/widget/components/greetings-card/greetings-card.tsx +40 -0
  103. package/src/modules/widget/components/greetings-card/index.ts +1 -0
  104. package/src/modules/widget/components/greetings-card/styles.module.css +9 -0
  105. package/src/modules/widget/components/index.ts +1 -0
  106. package/src/modules/widget/events.ts +21 -0
  107. package/src/modules/widget/index.ts +2 -0
  108. package/src/modules/widget/types.ts +7 -0
  109. package/src/types.ts +23 -0
  110. package/tailwind.config.js +8 -0
  111. package/tsconfig.json +128 -0
@@ -0,0 +1,40 @@
1
+ # APP
2
+ ENVIRONMENT=staging
3
+ APP_HOST=local.buildstaging.com
4
+ APP_PORT=4223
5
+ APP_NAME=app-tutor-ai-consumer
6
+
7
+ # CAS Hotmart
8
+ CAS_CLIENT_ID=b432cdd3-eb60-46bd-892b-5b450a65153e
9
+ IS_CAS=false
10
+
11
+ APP_HOST_MF=
12
+
13
+ # API
14
+ API_CONTENT_PLATFORM_SPACE=https://api-content-platform-space-gateway.buildstaging.com
15
+ API_HOTMART_TUTOR=https://api-smart-search-content.buildstaging.com
16
+
17
+ # OPTIMIZELY
18
+
19
+ OPTIMIZELY_SDK_KEY=B9rwquwdhY7XfEzaqZH94
20
+
21
+ # FIREBASE
22
+ FIREBASE_API_KEY=AIzaSyAq3KtkkTsJC5maHM_A9YJ-roI2IbvI5fM
23
+ FIREBASE_AUTH_DOMAIN=omnichat-cad8c.firebaseapp.com
24
+ FIREBASE_DATABASE_URL=https://omnichat-cad8c.firebaseio.com
25
+ FIREBASE_MESSAGING_SENDER_ID=78513709264
26
+ FIREBASE_PROJECT_ID=omnichat-cad8c
27
+ FIREBASE_STORAGE_BUCKET=omnichat-cad8c.appspot.com
28
+
29
+ # C3PO
30
+ API_CONVERSATION_URL=https://c3po-api-conversations.buildstaging.com
31
+ API_AUTH_URL=https://c3po-api-auth.buildstaging.com/v1
32
+
33
+ # VLC
34
+ USER_VLC=
35
+ VLC_PASSWORD=
36
+ SECURITY_BASE_URL=
37
+ AUTH_CLIENT_SECRET=
38
+
39
+ # BUNDLE
40
+ BUNDLE_PATH=https://app-club-microfrontends.buildstaging.com
@@ -0,0 +1,41 @@
1
+ # APP
2
+ ENVIRONMENT=test
3
+ APP_HOST=local.buildstaging.com
4
+ APP_PORT=4223
5
+ APP_NAME=app-tutor-ai-consumer
6
+
7
+ # CAS Hotmart
8
+ CAS_CLIENT_ID=
9
+ IS_CAS=
10
+
11
+ # IT SHOULD ONLY BE FILLED IN the .env.local file
12
+ MEMBERSHIP_SLUG=
13
+
14
+ # API
15
+ API_CONTENT_PLATFORM_SPACE=
16
+ API_HOTMART_TUTOR=
17
+
18
+ # OPTIMIZELY
19
+
20
+ OPTIMIZELY_SDK_KEY=B9rwquwdhY7XfEzaqZH94
21
+
22
+ # FIREBASE
23
+ FIREBASE_API_KEY=AIzaSyAq3KtkkTsJC5maHM_A9YJ-roI2IbvI5fM
24
+ FIREBASE_AUTH_DOMAIN=omnichat-cad8c.firebaseapp.com
25
+ FIREBASE_DATABASE_URL=https://omnichat-cad8c.firebaseio.com
26
+ FIREBASE_MESSAGING_SENDER_ID=78513709264
27
+ FIREBASE_PROJECT_ID=omnichat-cad8c
28
+ FIREBASE_STORAGE_BUCKET=omnichat-cad8c.appspot.com
29
+
30
+ # C3PO
31
+ API_CONVERSATION_URL=
32
+ API_AUTH_URL=
33
+
34
+ # VLC
35
+ USER_VLC=
36
+ VLC_PASSWORD=
37
+ SECURITY_BASE_URL=
38
+ AUTH_CLIENT_SECRET=
39
+
40
+ # BUNDLE
41
+ BUNDLE_PATH=
@@ -0,0 +1,87 @@
1
+ // @ts-nocheck
2
+
3
+ import eslint from '@eslint/js'
4
+ import tseslint from 'typescript-eslint'
5
+ import reactPlugin from 'eslint-plugin-react'
6
+ import reactHooks from 'eslint-plugin-react-hooks'
7
+ import globals from 'globals'
8
+ import simpleImportSort from 'eslint-plugin-simple-import-sort'
9
+ import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
10
+
11
+ export default tseslint.config(
12
+ {
13
+ ignores: [
14
+ '**/node_modules/',
15
+ '**/dist/',
16
+ 'config/rspack/',
17
+ '**/tailwind.config.*',
18
+ '**/postcss.config.*',
19
+ 'eslint.config.mjs',
20
+ 'commitlint.config.js',
21
+ 'babel.config.js',
22
+ '**/*.d.ts',
23
+ ],
24
+ },
25
+ eslintPluginPrettierRecommended,
26
+ eslint.configs.recommended,
27
+ tseslint.configs.recommendedTypeChecked,
28
+ { languageOptions: { globals: globals.browser } },
29
+ {
30
+ languageOptions: {
31
+ parserOptions: {
32
+ projectService: true,
33
+ tsconfigRootDir: import.meta.dirname,
34
+ },
35
+ },
36
+ },
37
+ reactPlugin.configs.flat.recommended,
38
+ reactPlugin.configs.flat['jsx-runtime'],
39
+ {
40
+ settings: {
41
+ react: {
42
+ version: 'detect',
43
+ },
44
+ },
45
+ plugins: {
46
+ 'react-hooks': reactHooks,
47
+ 'simple-import-sort': simpleImportSort,
48
+ },
49
+ rules: {
50
+ ...reactHooks.configs.recommended.rules,
51
+ 'prettier/prettier': [
52
+ 'error',
53
+ {
54
+ usePrettierrc: true,
55
+ },
56
+ ],
57
+ 'simple-import-sort/imports': [
58
+ 'error',
59
+ {
60
+ groups: [
61
+ // 1. Side effect imports at the start. For me this is important because I want to import reset.css and global styles at the top of my main file.
62
+ ['^\\u0000'],
63
+ // 2. `react` and packages: Things that start with a letter (or digit or underscore), or `@` followed by a letter.
64
+ ['^react$', '^@?\\w'],
65
+ // 3. Absolute imports and other imports such as Vue-style `@/foo`.
66
+ // Anything not matched in another group. (also relative imports starting with "../")
67
+ ['^@', '^'],
68
+ // 4. relative imports from same folder "./" (I like to have them grouped together)
69
+ ['^\\./'],
70
+ // 5. style module imports always come last, this helps to avoid CSS order issues
71
+ ['^.+\\.(module.css|module.scss)$'],
72
+ // 6. media imports
73
+ ['^.+\\.(gif|png|svg|jpg)$'],
74
+ ],
75
+ },
76
+ ],
77
+ 'simple-import-sort/exports': 'error',
78
+ '@typescript-eslint/consistent-type-imports': [
79
+ 'error',
80
+ {
81
+ fixStyle: 'separate-type-imports',
82
+ },
83
+ ],
84
+ '@typescript-eslint/no-explicit-any': 'off',
85
+ },
86
+ },
87
+ )
package/mkdocs.yaml ADDED
@@ -0,0 +1,11 @@
1
+ site_name: app-tutor-ai-consumer
2
+ repo_url: https://github.com/Hotmart-Org/app-tutor-ai-consumer
3
+
4
+ plugins:
5
+ - techdocs-core
6
+
7
+ nav:
8
+ - Summary: 'index.md'
9
+ - ADR: 'architecture/decisions/index.md'
10
+ - Design Docs: 'architecture/design/index.md'
11
+ - Quick Guide: 'README.md'
package/package.json ADDED
@@ -0,0 +1,130 @@
1
+ {
2
+ "name": "app-tutor-ai-consumer",
3
+ "version": "1.0.1",
4
+ "main": "index.js",
5
+ "scripts": {
6
+ "dev": "rspack serve --env=development --config config/rspack/rspack.config.js",
7
+ "dev:local": "rspack serve --env=local --config config/rspack/rspack.config.js",
8
+ "generate-icon-types": "ts-node scripts/generate-icon-types.js",
9
+ "postgenerate-icon-types": "npm run format",
10
+ "prebuild": "npm run generate-icon-types",
11
+ "build": "rspack build --mode=production --env=production --config config/rspack/rspack.config.js",
12
+ "prebuild:staging": "npm run generate-icon-types",
13
+ "build:staging": "rspack build --mode=production --env=staging --config config/rspack/rspack.config.js",
14
+ "prebuild:start": "npm run build",
15
+ "build:start": "NODE_ENV=production rspack preview --config config/rspack/rspack.config.js --port 4200",
16
+ "test": "vitest --config config/vitest/vitest.config.mts",
17
+ "test:ci": "npm run test -- --run --coverage --silent --bail 1",
18
+ "type-check": "bash -c tsc --project ./tsconfig.json --noEmit",
19
+ "lint": "eslint --ext js,ts,tsx ./src --no-warn-ignored --max-warnings=0",
20
+ "lint:fix": "npm run lint -- --fix",
21
+ "prelint": "npm run format",
22
+ "format": "prettier --ignore-path .prettierignore --write \"**/*.+(js|jsx|ts|tsx|json)\"",
23
+ "fetch-langs": "PROJECT=app-tutor-ai-consumer PATH_LANGUAGES=public/locales api-languages-cli",
24
+ "fetch-langs:local": "PROJECT=app-tutor-ai-consumer PATH_LANGUAGES=public/locales LANG_ENV=local api-languages-cli",
25
+ "semantic-release": "semantic-release",
26
+ "prepare": "husky || true"
27
+ },
28
+ "keywords": [],
29
+ "author": "",
30
+ "license": "ISC",
31
+ "description": "",
32
+ "devDependencies": {
33
+ "@babel/preset-typescript": "~7.27.1",
34
+ "@commitlint/cli": "~19.8.1",
35
+ "@commitlint/config-conventional": "~19.8.1",
36
+ "@eslint/compat": "~1.2.9",
37
+ "@eslint/js": "~9.28.0",
38
+ "@hotmart/api-languages-cli": "~2.0.5",
39
+ "@rsbuild/plugin-svgr": "~1.2.0",
40
+ "@rspack/cli": "~1.3.15",
41
+ "@rspack/core": "~1.3.15",
42
+ "@rspack/plugin-react-refresh": "~1.4.3",
43
+ "@semantic-release/changelog": "~6.0.3",
44
+ "@semantic-release/commit-analyzer": "~13.0.1",
45
+ "@semantic-release/git": "~10.0.1",
46
+ "@semantic-release/npm": "~12.0.1",
47
+ "@semantic-release/release-notes-generator": "~14.0.3",
48
+ "@stylistic/eslint-plugin-js": "~4.4.1",
49
+ "@svgr/webpack": "~8.1.0",
50
+ "@tanstack/react-query-devtools": "~5.80.6",
51
+ "@testing-library/jest-dom": "~6.6.3",
52
+ "@testing-library/react": "~16.3.0",
53
+ "@testing-library/user-event": "~14.6.1",
54
+ "@types/axios": "~0.9.36",
55
+ "@types/chance": "~1.1.6",
56
+ "@types/node": "~24.0.0",
57
+ "@types/react": "~19.1.7",
58
+ "@types/react-dom": "~19.1.6",
59
+ "@types/react-router-dom": "~5.3.3",
60
+ "@types/ua-parser-js": "~0.7.39",
61
+ "@vitejs/plugin-react": "~4.5.2",
62
+ "@vitest/coverage-istanbul": "~3.2.3",
63
+ "@vitest/coverage-v8": "~3.2.3",
64
+ "autoprefixer": "~10.4.21",
65
+ "chance": "~1.1.13",
66
+ "compression-webpack-plugin": "~11.1.0",
67
+ "css-loader": "~7.1.2",
68
+ "dotenv": "~16.5.0",
69
+ "eslint": "~9.28.0",
70
+ "eslint-config-prettier": "~10.1.5",
71
+ "eslint-plugin-prettier": "~5.4.1",
72
+ "eslint-plugin-react": "~7.37.5",
73
+ "eslint-plugin-react-hooks": "~5.2.0",
74
+ "eslint-plugin-simple-import-sort": "~12.1.1",
75
+ "file-loader": "~6.2.0",
76
+ "globals": "~16.2.0",
77
+ "husky": "~9.1.7",
78
+ "jsdom": "~26.1.0",
79
+ "lint-staged": "~16.1.0",
80
+ "loader": "~2.1.1",
81
+ "msw": "~2.10.2",
82
+ "postcss": "~8.5.4",
83
+ "postcss-import": "~16.1.0",
84
+ "postcss-loader": "~8.1.1",
85
+ "prettier": "~3.5.3",
86
+ "prettier-plugin-tailwindcss": "~0.6.12",
87
+ "process": "~0.11.10",
88
+ "react-refresh": "~0.17.0",
89
+ "semantic-release": "~24.2.5",
90
+ "style-loader": "~4.0.0",
91
+ "tailwindcss": "~3.4.17",
92
+ "ts-checker-rspack-plugin": "~1.1.4",
93
+ "ts-node": "~10.9.2",
94
+ "typescript": "~5.8.3",
95
+ "typescript-eslint": "~8.34.0",
96
+ "ua-parser-js": "~2.0.3",
97
+ "undici": "~7.10.0",
98
+ "vite-tsconfig-paths": "~5.1.4",
99
+ "vitest": "~3.2.3"
100
+ },
101
+ "dependencies": {
102
+ "@tanstack/react-query": "~5.80.6",
103
+ "clsx": "~2.1.1",
104
+ "i18next": "~25.2.1",
105
+ "i18next-resources-to-backend": "~1.2.1",
106
+ "react": "~19.1.0",
107
+ "react-dom": "~19.1.0",
108
+ "react-i18next": "~15.5.2"
109
+ },
110
+ "optionalDependencies": {
111
+ "@rollup/rollup-linux-x64-gnu": "4.6.1",
112
+ "@rspack/binding-linux-x64-gnu": "1.3.10"
113
+ },
114
+ "browserslist": [
115
+ ">0.2%",
116
+ "not dead",
117
+ "not ie <= 11",
118
+ "not op_mini all"
119
+ ],
120
+ "lint-staged": {
121
+ "*.{js,ts,jsx,tsx}": [
122
+ "npm run type-check",
123
+ "npm run lint:fix",
124
+ "vitest --config config/vitest/vitest.config.mts related --run --bail 1"
125
+ ],
126
+ "*.{json,js,jsx,ts,tsx,css,md,html}": [
127
+ "prettier --write"
128
+ ]
129
+ }
130
+ }
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ plugins: [require('postcss-import'), require('tailwindcss'), require('autoprefixer')]
3
+ }
Binary file
@@ -0,0 +1,18 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
7
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
8
+ <link
9
+ href="https://fonts.googleapis.com/css?family=Nunito:400,700"
10
+ rel="stylesheet"
11
+ />
12
+ <title>App Tutor AI Consumer</title>
13
+ </head>
14
+
15
+ <body>
16
+ <div id="root"></div>
17
+ </body>
18
+ </html>
@@ -0,0 +1,31 @@
1
+ /* eslint-disable no-undef */
2
+ /* eslint-disable @typescript-eslint/no-require-imports */
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+
6
+ const ICONS_DIR = path.join(process.cwd(), 'src/lib/components/icons')
7
+
8
+ const generateIconTypes = () => {
9
+ try {
10
+ const files = fs.readdirSync(ICONS_DIR)
11
+ const svgNames = files
12
+ .filter((file) => file.endsWith('.svg'))
13
+ .map((file) => file.replace(/\.svg$/, ''))
14
+
15
+ const typeContent = `// Auto-generated file - DO NOT EDIT
16
+ export type ValidIconNames = ${svgNames.map((name) => `'${name}'`).join(' | ')};
17
+ `
18
+
19
+ fs.writeFileSync(
20
+ path.join(process.cwd(), 'src/lib/components/icons/icon-names.d.ts'),
21
+ typeContent
22
+ )
23
+
24
+ console.log('✅ Icon types generated successfully')
25
+ } catch (error) {
26
+ console.error('Error generating icon types:', error)
27
+ process.exit(1)
28
+ }
29
+ }
30
+
31
+ generateIconTypes()
@@ -0,0 +1,25 @@
1
+ declare module '*.module.css' {
2
+ const classes: { readonly [key: string]: string }
3
+ export default classes
4
+ }
5
+
6
+ declare module '*.css'
7
+
8
+ declare module '*.css?inline'
9
+
10
+ declare module '*.png'
11
+
12
+ declare module '*.jpg'
13
+
14
+ declare module '*.gif'
15
+
16
+ declare module '*?url'
17
+
18
+ declare module '*.svg?url'
19
+
20
+ declare module '*.svg' {
21
+ const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>
22
+ const content: string
23
+ export { ReactComponent }
24
+ export default content
25
+ }
@@ -0,0 +1 @@
1
+ declare module 'HotmartTutorAIConsumer/*'
@@ -0,0 +1,64 @@
1
+ import type { PropsWithChildren } from 'react'
2
+
3
+ export type Logos = {
4
+ type: 'light' | 'dark'
5
+ imageUrl: string
6
+ }
7
+
8
+ export type Banners = {
9
+ imageUrlWeb: string
10
+ imageUrlMobile: string
11
+ url: string
12
+ altText: string
13
+ }
14
+
15
+ export type Settings = {
16
+ primaryColor: string
17
+ logoAltText: string
18
+ logos: Logos[]
19
+ banners: Banners[]
20
+ orientation: { global: 'HORIZONTAL' | 'VERTICAL' }
21
+ }
22
+
23
+ export type Membership = {
24
+ id: string
25
+ name: string
26
+ ownerId?: number
27
+ ownerUcode: string
28
+ settings: Settings
29
+ roles: string[]
30
+ }
31
+
32
+ export enum Roles {
33
+ OWNER = 'OWNER',
34
+ VIEWER = 'VIEWER'
35
+ }
36
+
37
+ export type UserInfo = {
38
+ id: string
39
+ name: string
40
+ email: string
41
+ role: Roles
42
+ isMembership: boolean
43
+ isAttendant: boolean
44
+ ucode?: string
45
+ permission: {
46
+ addProduct: boolean
47
+ deleteProduct: boolean
48
+ }
49
+ avatar: string
50
+ }
51
+
52
+ export type MicrofrontEndProps = {
53
+ locale: string
54
+ membership: Membership
55
+ slug: string
56
+ token: string
57
+ user: UserInfo
58
+ isOwner: boolean
59
+ baseUrl: string
60
+ }
61
+
62
+ export type IMicrofrontEndProps = Partial<PropsWithChildren<MicrofrontEndProps>>
63
+
64
+ export type IQueryDataUpdater<T = unknown> = T | ((args: T) => T)
@@ -0,0 +1,16 @@
1
+ import type { StartTutorWidgetProps } from '@/src/types'
2
+
3
+ export {}
4
+
5
+ declare global {
6
+ interface WindowEventMap {}
7
+
8
+ type OptionalSpread<T> = T extends undefined ? [] : [T]
9
+
10
+ interface Window {
11
+ __INJECT_CSS_MODULE__?: (cssText: string, id: string) => void
12
+ startTutorWidget: (props: StartTutorWidgetProps) => Promise<void>
13
+ closeTutorWidget: () => void
14
+ TOKEN: string
15
+ }
16
+ }
@@ -0,0 +1,9 @@
1
+ export const LANGUAGES = {
2
+ EN: 'en',
3
+ ES: 'es',
4
+ PT_BR: 'pt_BR'
5
+ } as const
6
+
7
+ export const DEFAULT_LANGUAGE = LANGUAGES.EN
8
+
9
+ export const LANG_RESOURCES = new Set(Object.values(LANGUAGES))
@@ -0,0 +1 @@
1
+ export * from './use-app-lang'
@@ -0,0 +1 @@
1
+ export { default as useAppLang } from './use-app-lang'
@@ -0,0 +1,22 @@
1
+ import { useEffect } from 'react'
2
+
3
+ import { productionMode } from '@/src/lib/utils'
4
+ import i18n from '../../init'
5
+ import type { ILanguages } from '../../types'
6
+ import { getLang } from '../../utils/get-lang'
7
+
8
+ const useAppLang = (lng?: ILanguages) => {
9
+ const language = getLang(lng)
10
+
11
+ useEffect(() => {
12
+ if (i18n?.language && i18n.language === language) return
13
+
14
+ void i18n.changeLanguage(language, (err) => {
15
+ if (!err) return
16
+
17
+ console[productionMode ? 'warn' : 'error']('user: ', err)
18
+ })
19
+ }, [language])
20
+ }
21
+
22
+ export default useAppLang
@@ -0,0 +1,5 @@
1
+ export * from './constants'
2
+ export * from './hooks'
3
+ export { default } from './init'
4
+ export * from './init'
5
+ export * from './types'
@@ -0,0 +1,44 @@
1
+ import i18n from 'i18next'
2
+ import resourcesToBackend from 'i18next-resources-to-backend'
3
+ import { initReactI18next } from 'react-i18next'
4
+
5
+ import { devMode } from '@/src/lib/utils'
6
+
7
+ import { DEFAULT_LANGUAGE, LANG_RESOURCES, LANGUAGES } from './constants'
8
+ import type { ILangs } from './types'
9
+
10
+ let i18nInitialized = false
11
+
12
+ export const initLanguage = async (language: string) => {
13
+ if (i18nInitialized) return
14
+
15
+ const lang = language?.toUpperCase() as keyof ILangs
16
+ let lng = language.match(/^pt/gi) ? LANGUAGES.PT_BR : LANGUAGES[lang]
17
+
18
+ if (!LANG_RESOURCES.has(lng)) lng = DEFAULT_LANGUAGE
19
+
20
+ await i18n
21
+ .use(initReactI18next)
22
+ .use(
23
+ resourcesToBackend(() => {
24
+ return import(`@/public/locales/${lng}.json`)
25
+ })
26
+ )
27
+ .init({
28
+ debug: devMode,
29
+ fallbackLng: [DEFAULT_LANGUAGE, LANGUAGES.PT_BR],
30
+ preload: [DEFAULT_LANGUAGE, LANGUAGES.PT_BR],
31
+ load: 'currentOnly',
32
+ lng: lng || DEFAULT_LANGUAGE,
33
+ interpolation: {
34
+ escapeValue: false
35
+ },
36
+ returnEmptyString: false
37
+ })
38
+
39
+ i18nInitialized = true
40
+ }
41
+
42
+ export const t = i18n.t.bind(i18n)
43
+
44
+ export default i18n
@@ -0,0 +1,5 @@
1
+ import type { LANGUAGES } from './constants'
2
+
3
+ export type ILangs = typeof LANGUAGES
4
+
5
+ export type ILanguages = ILangs[keyof ILangs]
@@ -0,0 +1,10 @@
1
+ import { DEFAULT_LANGUAGE, LANGUAGES } from '../constants'
2
+ import type { ILanguages } from '../types'
3
+
4
+ export const getLang = (lng?: string) => {
5
+ if (lng && lng.match(/^pt/gi)) return LANGUAGES.PT_BR
6
+
7
+ if (lng && Object.values(LANGUAGES).includes(lng as ILanguages)) return lng as ILanguages
8
+
9
+ return DEFAULT_LANGUAGE
10
+ }