app-tutor-ai-consumer 1.29.1 → 1.30.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.
- package/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/src/config/datahub/actions.ts +3 -2
- package/src/config/datahub/constants.ts +5 -1
- package/src/config/datahub/schemas/base-view-schema.ts +59 -0
- package/src/config/datahub/schemas/tutor/click-hotmart-tutor.ts +14 -6
- package/src/config/datahub/schemas/tutor/constants.ts +2 -1
- package/src/config/datahub/schemas/tutor/view-product-tutor.ts +42 -0
- package/src/config/datahub/types.ts +9 -1
- package/src/config/theme/init-theme.ts +1 -1
- package/src/modules/messages/components/message-actions/message-actions.tsx +18 -4
- package/src/modules/widget/components/chat-page/chat-page.tsx +3 -0
- package/src/modules/widget/hooks/index.ts +1 -0
- package/src/modules/widget/hooks/use-send-view-tutor-event/index.ts +1 -0
- package/src/modules/widget/hooks/use-send-view-tutor-event/use-send-view-tutor-event.spec.tsx +36 -0
- package/src/modules/widget/hooks/use-send-view-tutor-event/use-send-view-tutor-event.tsx +20 -0
- package/src/modules/widget/store/index.ts +1 -0
- package/src/modules/widget/store/widget-settings-config.atom.ts +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
# [1.30.0](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.29.2...v1.30.0) (2025-09-18)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- pr issues ([09ad360](https://github.com/Hotmart-Org/app-tutor-ai-consumer/commit/09ad360449e1f3b06e329f4594b00d9c245faaaa))
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- change datahub events to support product agent ([e6a91fb](https://github.com/Hotmart-Org/app-tutor-ai-consumer/commit/e6a91fbb7995e16d50909ab71018073f41901694))
|
|
10
|
+
|
|
11
|
+
## [1.29.2](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.29.1...v1.29.2) (2025-09-16)
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
- background color theme change ([8b401d4](https://github.com/Hotmart-Org/app-tutor-ai-consumer/commit/8b401d4ff7075052395c5229d744a75dd2a6ffb3))
|
|
16
|
+
|
|
1
17
|
## [1.29.1](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.29.0...v1.29.1) (2025-09-02)
|
|
2
18
|
|
|
3
19
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -19,5 +19,6 @@ export const ActionNames = {
|
|
|
19
19
|
CLICK_TUTOR_KNOW_MORE: `${DataHubActions.CLICK}_tutor_know_more`,
|
|
20
20
|
CLICK_TUTOR_ONBOARDING_START: `${DataHubActions.CLICK}_tutor_onboarding_start`,
|
|
21
21
|
CLICK_TUTOR_TEST_KNOWLEDGE: `${DataHubActions.CLICK}_tutor_test_knowledge`,
|
|
22
|
-
CLOSE_TUTOR_ONBOARDING: `${DataHubActions.CLOSE}_tutor_onboarding
|
|
23
|
-
}
|
|
22
|
+
CLOSE_TUTOR_ONBOARDING: `${DataHubActions.CLOSE}_tutor_onboarding`,
|
|
23
|
+
VIEW_PRODUCT_TUTOR: `${DataHubActions.VIEW}_product_tutor`
|
|
24
|
+
}
|
|
@@ -24,7 +24,9 @@ export const Result = {
|
|
|
24
24
|
export const ComponentNames = {
|
|
25
25
|
BUTTON_LIKE_ANSWER: 'BUTTON_LIKE_ANSWER',
|
|
26
26
|
BUTTON_DISLIKE_ANSWER: 'BUTTON_DISLIKE_ANSWER',
|
|
27
|
+
BUTTON_COPY_ANSWER: 'BUTTON_COPY_ANSWER',
|
|
27
28
|
BUTTON_CLOSE_TUTOR_CHAT: 'BUTTON_CLOSE_TUTOR_CHAT',
|
|
29
|
+
BUTTON_VIEW_AGENT: 'BUTTON_VIEW_AGENT',
|
|
28
30
|
PRODUCT_CONSUME_CLICK_TUTOR_BACK: 'product_consume_click_tutor_back',
|
|
29
31
|
PRODUCT_CONSUME_CLICK_TUTOR_HISTORY: 'product_consume_click_tutor_history',
|
|
30
32
|
PRODUCT_CONSUME_CLICK_TUTOR_INFO: 'product_consume_click_tutor_info',
|
|
@@ -35,7 +37,9 @@ export const ComponentNames = {
|
|
|
35
37
|
} as const
|
|
36
38
|
|
|
37
39
|
export const ComponentSource = {
|
|
38
|
-
ACTION_BAR_STATUS: 'ACTION_BAR_STATUS'
|
|
40
|
+
ACTION_BAR_STATUS: 'ACTION_BAR_STATUS',
|
|
41
|
+
HOTMART_TUTOR: 'HOTMART_TUTOR',
|
|
42
|
+
PRODUCT_AGENT: 'PRODUCT_AGENT'
|
|
39
43
|
} as const
|
|
40
44
|
|
|
41
45
|
export const ArrivedFrom = {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { DataHubEntities } from '../entities'
|
|
2
|
+
import type { ComponentNamesType, ComponentSourceType, DataHubEntityTypes } from '../types'
|
|
3
|
+
|
|
4
|
+
import BaseSchema from './base-schema'
|
|
5
|
+
import { ProductCategories } from './constants'
|
|
6
|
+
import type { ProductCategoriesType } from './types'
|
|
7
|
+
|
|
8
|
+
export type BaseViewSchemaConstructorArgs = {
|
|
9
|
+
componentName: ComponentNamesType
|
|
10
|
+
componentSource: ComponentSourceType
|
|
11
|
+
arrivedFrom?: string
|
|
12
|
+
entity?: DataHubEntityTypes
|
|
13
|
+
isLogged?: boolean
|
|
14
|
+
productType?: ProductCategoriesType
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
abstract class BaseViewSchema extends BaseSchema {
|
|
18
|
+
private arrivedFrom: string
|
|
19
|
+
private componentName: string
|
|
20
|
+
private componentSource: string
|
|
21
|
+
private productType: ProductCategoriesType
|
|
22
|
+
|
|
23
|
+
entity: DataHubEntityTypes
|
|
24
|
+
isLogged: boolean
|
|
25
|
+
|
|
26
|
+
constructor(args: BaseViewSchemaConstructorArgs) {
|
|
27
|
+
const {
|
|
28
|
+
componentName,
|
|
29
|
+
componentSource,
|
|
30
|
+
arrivedFrom = 'HOME_CLASS_CONSUMER',
|
|
31
|
+
entity = DataHubEntities.PRODUCT_CONSUME,
|
|
32
|
+
isLogged = true,
|
|
33
|
+
productType = ProductCategories.OnlineServices
|
|
34
|
+
} = args
|
|
35
|
+
|
|
36
|
+
super()
|
|
37
|
+
|
|
38
|
+
this.arrivedFrom = arrivedFrom
|
|
39
|
+
this.componentName = componentName
|
|
40
|
+
this.componentSource = componentSource
|
|
41
|
+
this.entity = entity
|
|
42
|
+
this.isLogged = isLogged
|
|
43
|
+
this.productType = productType
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
prepare(): Record<string, unknown> {
|
|
47
|
+
return {
|
|
48
|
+
...super.prepare(),
|
|
49
|
+
arrivedFrom: this.arrivedFrom,
|
|
50
|
+
componentName: this.componentName,
|
|
51
|
+
componentSource: this.componentSource,
|
|
52
|
+
entity: this.entity,
|
|
53
|
+
isLogged: this.isLogged,
|
|
54
|
+
productType: this.productType
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default BaseViewSchema
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ActionNames } from '../../actions'
|
|
2
|
-
import { ComponentNames, ScreenNames } from '../../constants'
|
|
2
|
+
import { ComponentNames, ComponentSource, ScreenNames } from '../../constants'
|
|
3
3
|
import { DataHubEntities } from '../../entities'
|
|
4
4
|
import type {
|
|
5
5
|
ActionNamesType,
|
|
6
6
|
ComponentNamesType,
|
|
7
|
+
ComponentSourceType,
|
|
7
8
|
DataHubEntityTypes,
|
|
8
9
|
ScreenNamesType
|
|
9
10
|
} from '../../types'
|
|
@@ -14,6 +15,7 @@ import type { ButtonReactionsType } from './types'
|
|
|
14
15
|
|
|
15
16
|
class ClickHotmartTutor extends BaseSchema {
|
|
16
17
|
private componentName: ComponentNamesType
|
|
18
|
+
private componentSource: ComponentSourceType
|
|
17
19
|
private screenName: ScreenNamesType
|
|
18
20
|
private messageId: string
|
|
19
21
|
private hasAccess: boolean
|
|
@@ -26,22 +28,27 @@ class ClickHotmartTutor extends BaseSchema {
|
|
|
26
28
|
reactionType,
|
|
27
29
|
messageId,
|
|
28
30
|
hasAccess = true,
|
|
29
|
-
isLogged = true
|
|
31
|
+
isLogged = true,
|
|
32
|
+
componentSource = ComponentSource.HOTMART_TUTOR
|
|
30
33
|
}: {
|
|
31
34
|
reactionType: ButtonReactionsType
|
|
32
35
|
messageId: string
|
|
33
36
|
hasAccess?: boolean
|
|
34
37
|
isLogged?: boolean
|
|
38
|
+
componentSource?: ComponentSourceType
|
|
35
39
|
}) {
|
|
36
40
|
super()
|
|
37
41
|
|
|
38
42
|
this.action = ActionNames.CLICK_HOTMART_TUTOR
|
|
39
43
|
this.entity = DataHubEntities.HOME
|
|
40
44
|
|
|
41
|
-
this.componentName =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
this.componentName = {
|
|
46
|
+
[ButtonReactions.LIKE]: ComponentNames.BUTTON_LIKE_ANSWER,
|
|
47
|
+
[ButtonReactions.DISLIKE]: ComponentNames.BUTTON_DISLIKE_ANSWER,
|
|
48
|
+
[ButtonReactions.COPY]: ComponentNames.BUTTON_COPY_ANSWER
|
|
49
|
+
}[reactionType]
|
|
50
|
+
|
|
51
|
+
this.componentSource = componentSource
|
|
45
52
|
this.screenName = ScreenNames.HOME_CONSUMER
|
|
46
53
|
this.messageId = messageId
|
|
47
54
|
this.hasAccess = hasAccess
|
|
@@ -52,6 +59,7 @@ class ClickHotmartTutor extends BaseSchema {
|
|
|
52
59
|
return {
|
|
53
60
|
...super.prepare(),
|
|
54
61
|
componentName: this.componentName,
|
|
62
|
+
componentSource: this.componentSource,
|
|
55
63
|
screenName: this.screenName,
|
|
56
64
|
messageId: this.messageId,
|
|
57
65
|
hasAccess: this.hasAccess
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ActionNames } from '../../actions'
|
|
2
|
+
import { ComponentNames, ComponentSource } from '../../constants'
|
|
3
|
+
import type { ActionNamesType, ComponentNamesType, ComponentSourceType } from '../../types'
|
|
4
|
+
import BaseViewSchema from '../base-view-schema'
|
|
5
|
+
import type { ProductCategoriesType } from '../types'
|
|
6
|
+
|
|
7
|
+
export type ViewProductTutorSchemaConstructorArgs = {
|
|
8
|
+
arrivedFrom?: string
|
|
9
|
+
componentName?: ComponentNamesType
|
|
10
|
+
componentSource?: ComponentSourceType
|
|
11
|
+
productType?: ProductCategoriesType
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class ViewProductTutorSchema extends BaseViewSchema {
|
|
15
|
+
action: ActionNamesType
|
|
16
|
+
|
|
17
|
+
constructor(args?: ViewProductTutorSchemaConstructorArgs) {
|
|
18
|
+
const {
|
|
19
|
+
arrivedFrom,
|
|
20
|
+
productType,
|
|
21
|
+
componentName = ComponentNames.BUTTON_VIEW_AGENT,
|
|
22
|
+
componentSource = ComponentSource.HOTMART_TUTOR
|
|
23
|
+
} = args ?? {}
|
|
24
|
+
|
|
25
|
+
super({
|
|
26
|
+
arrivedFrom,
|
|
27
|
+
productType,
|
|
28
|
+
componentName,
|
|
29
|
+
componentSource
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
this.action = ActionNames.VIEW_PRODUCT_TUTOR
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getDataHubEventData() {
|
|
36
|
+
return {
|
|
37
|
+
...super.prepare()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default ViewProductTutorSchema
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { ActionNames } from './actions'
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
ComponentNames,
|
|
4
|
+
ComponentSource,
|
|
5
|
+
Platform,
|
|
6
|
+
Result,
|
|
7
|
+
ScreenNames,
|
|
8
|
+
System
|
|
9
|
+
} from './constants'
|
|
3
10
|
import type { DataHubEntities } from './entities'
|
|
4
11
|
|
|
5
12
|
export type ActionNamesType = (typeof ActionNames)[keyof typeof ActionNames]
|
|
@@ -7,6 +14,7 @@ export type DataHubEntityTypes = (typeof DataHubEntities)[keyof typeof DataHubEn
|
|
|
7
14
|
export type PlatformType = (typeof Platform)[keyof typeof Platform]
|
|
8
15
|
export type SystemType = (typeof System)[keyof typeof System]
|
|
9
16
|
export type ComponentNamesType = (typeof ComponentNames)[keyof typeof ComponentNames]
|
|
17
|
+
export type ComponentSourceType = (typeof ComponentSource)[keyof typeof ComponentSource]
|
|
10
18
|
export type ScreenNamesType = (typeof ScreenNames)[keyof typeof ScreenNames]
|
|
11
19
|
export type ResultType = (typeof Result)[keyof typeof Result]
|
|
12
20
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { type CSSProperties, useState } from 'react'
|
|
1
|
+
import { type CSSProperties, useCallback, useState } from 'react'
|
|
2
2
|
import clsx from 'clsx'
|
|
3
3
|
import dayjs from 'dayjs'
|
|
4
4
|
import { useTranslation } from 'react-i18next'
|
|
5
5
|
|
|
6
|
-
import { DataHubService } from '@/src/config/datahub'
|
|
6
|
+
import { ComponentSource, DataHubService } from '@/src/config/datahub'
|
|
7
7
|
import type { ButtonReactionsType } from '@/src/config/datahub/schemas/tutor'
|
|
8
8
|
import { ButtonReactions, ClickHotmartTutor } from '@/src/config/datahub/schemas/tutor'
|
|
9
9
|
import { Button, Icon } from '@/src/lib/components'
|
|
10
10
|
import { ToastUtils } from '@/src/lib/utils'
|
|
11
|
+
import { useIsAgentParentAtomValue } from '@/src/modules/widget'
|
|
11
12
|
import type { ParsedMessage } from '../../types'
|
|
12
13
|
|
|
13
14
|
export type MessageActionsProps = {
|
|
@@ -21,6 +22,19 @@ function MessageActions({ message, className, showActions = false }: MessageActi
|
|
|
21
22
|
const [copying, setCopying] = useState(false)
|
|
22
23
|
const [copied, setCopied] = useState(false)
|
|
23
24
|
const [reaction, setReaction] = useState<ButtonReactionsType | null>(null)
|
|
25
|
+
const isAgentMode = useIsAgentParentAtomValue()
|
|
26
|
+
|
|
27
|
+
const sendEvent = useCallback(
|
|
28
|
+
({ reactionType }: { reactionType: ButtonReactionsType }) => {
|
|
29
|
+
const schema = new ClickHotmartTutor({
|
|
30
|
+
messageId: message.id,
|
|
31
|
+
reactionType,
|
|
32
|
+
componentSource: isAgentMode ? ComponentSource.PRODUCT_AGENT : undefined
|
|
33
|
+
})
|
|
34
|
+
DataHubService.sendEvent({ schema })
|
|
35
|
+
},
|
|
36
|
+
[isAgentMode, message.id]
|
|
37
|
+
)
|
|
24
38
|
|
|
25
39
|
const copyToClipboard = (): void => {
|
|
26
40
|
if (!message.text) return
|
|
@@ -32,6 +46,7 @@ function MessageActions({ message, className, showActions = false }: MessageActi
|
|
|
32
46
|
.then(() => {
|
|
33
47
|
setCopied(true)
|
|
34
48
|
ToastUtils.dispatch({ message: t('general.buttons.copied') })
|
|
49
|
+
sendEvent({ reactionType: ButtonReactions.COPY })
|
|
35
50
|
})
|
|
36
51
|
.catch((err) => {
|
|
37
52
|
const errorMessage = t('generic_error.title')
|
|
@@ -45,8 +60,7 @@ function MessageActions({ message, className, showActions = false }: MessageActi
|
|
|
45
60
|
}
|
|
46
61
|
|
|
47
62
|
const handleReaction = (reactionType: ButtonReactionsType = ButtonReactions.LIKE): void => {
|
|
48
|
-
|
|
49
|
-
DataHubService.sendEvent({ schema })
|
|
63
|
+
sendEvent({ reactionType })
|
|
50
64
|
setReaction(reactionType)
|
|
51
65
|
}
|
|
52
66
|
|
|
@@ -10,6 +10,7 @@ import { getAllMessagesQuery, useSendTextMessage } from '@/src/modules/messages/
|
|
|
10
10
|
import { useMessagesMaxCount } from '@/src/modules/messages/store'
|
|
11
11
|
import { useGetProfile } from '@/src/modules/profile'
|
|
12
12
|
import { TutorWidgetEvents } from '../../events'
|
|
13
|
+
import { useSendViewTutorEvent } from '../../hooks/use-send-view-tutor-event'
|
|
13
14
|
import {
|
|
14
15
|
useWidgetLoadingAtom,
|
|
15
16
|
useWidgetSettingsAtomValue,
|
|
@@ -47,6 +48,8 @@ function ChatPage() {
|
|
|
47
48
|
|
|
48
49
|
const messagesQuery = useInfiniteQuery(messagesQueryConfig)
|
|
49
50
|
|
|
51
|
+
useSendViewTutorEvent()
|
|
52
|
+
|
|
50
53
|
const handleSendMessage = () => {
|
|
51
54
|
const text = chatInputRef.current?.value ?? ''
|
|
52
55
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as useSendViewTutorEvent } from './use-send-view-tutor-event'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ComponentSource, DataHubService } from '@/src/config/datahub'
|
|
2
|
+
import ViewProductTutorSchema from '@/src/config/datahub/schemas/tutor/view-product-tutor'
|
|
3
|
+
import { renderHook } from '@/src/config/tests'
|
|
4
|
+
import { useIsAgentParentAtomValue } from '../../store'
|
|
5
|
+
|
|
6
|
+
import useSendViewTutorEvent from './use-send-view-tutor-event'
|
|
7
|
+
|
|
8
|
+
vi.mock('../../store', () => ({ useIsAgentParentAtomValue: vi.fn() }))
|
|
9
|
+
|
|
10
|
+
describe('useSendViewTutorEvent', () => {
|
|
11
|
+
const prepareHook = () => renderHook(useSendViewTutorEvent)
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
vi.mocked(useIsAgentParentAtomValue).mockReturnValue(true)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('should send datahub event when product is of type agent', () => {
|
|
18
|
+
const schema = new ViewProductTutorSchema({ componentSource: ComponentSource.PRODUCT_AGENT })
|
|
19
|
+
|
|
20
|
+
vi.spyOn(DataHubService, 'sendEvent')
|
|
21
|
+
|
|
22
|
+
prepareHook()
|
|
23
|
+
|
|
24
|
+
expect(DataHubService.sendEvent).toHaveBeenNthCalledWith(1, { schema })
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should not send datahub event when product is not of type agent', () => {
|
|
28
|
+
vi.mocked(useIsAgentParentAtomValue).mockReturnValue(false)
|
|
29
|
+
|
|
30
|
+
vi.spyOn(DataHubService, 'sendEvent')
|
|
31
|
+
|
|
32
|
+
prepareHook()
|
|
33
|
+
|
|
34
|
+
expect(DataHubService.sendEvent).not.toHaveBeenCalled()
|
|
35
|
+
})
|
|
36
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react'
|
|
2
|
+
|
|
3
|
+
import { ComponentSource, DataHubService } from '@/src/config/datahub'
|
|
4
|
+
import ViewProductTutorSchema from '@/src/config/datahub/schemas/tutor/view-product-tutor'
|
|
5
|
+
import { useIsAgentParentAtomValue } from '../../store'
|
|
6
|
+
|
|
7
|
+
function useSendViewTutorEvent() {
|
|
8
|
+
const isAgentMode = useIsAgentParentAtomValue()
|
|
9
|
+
const sent = useRef(false)
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (sent.current || !isAgentMode) return
|
|
13
|
+
|
|
14
|
+
const schema = new ViewProductTutorSchema({ componentSource: ComponentSource.PRODUCT_AGENT })
|
|
15
|
+
DataHubService.sendEvent({ schema })
|
|
16
|
+
sent.current = true
|
|
17
|
+
}, [isAgentMode])
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default useSendViewTutorEvent
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { atom, useAtomValue } from 'jotai'
|
|
2
|
+
|
|
3
|
+
import { widgetSettingsAtom } from './widget-settings.atom'
|
|
4
|
+
|
|
5
|
+
export const widgetSettingsConfigAgentParentAtom = atom((get) => {
|
|
6
|
+
const settings = get(widgetSettingsAtom)
|
|
7
|
+
return settings?.config?.metadata?.parent === 'AGENT'
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
export const useIsAgentParentAtomValue = () => useAtomValue(widgetSettingsConfigAgentParentAtom)
|