app-tutor-ai-consumer 1.33.0 → 1.33.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 (46) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/config/vitest/__mocks__/sparkie.tsx +1 -1
  3. package/package.json +2 -2
  4. package/src/@types/index.d.ts +2 -3
  5. package/src/config/tanstack/query-provider.tsx +3 -7
  6. package/src/index.tsx +11 -64
  7. package/src/lib/components/icons/icon-names.d.ts +1 -0
  8. package/src/lib/components/icons/tutor-logo.svg +9 -0
  9. package/src/modules/global-providers/global-providers.tsx +6 -1
  10. package/src/modules/messages/__tests__/imessage-with-sender-data.builder.ts +1 -1
  11. package/src/modules/messages/components/chat-input/chat-input.tsx +1 -1
  12. package/src/modules/messages/components/message-item/message-item.tsx +1 -2
  13. package/src/modules/messages/hooks/use-subscribe-message-received-event/use-subscribe-message-received-event.tsx +54 -119
  14. package/src/modules/messages/service.direct.ts +1 -1
  15. package/src/modules/messages/service.ts +2 -3
  16. package/src/modules/messages/types.ts +1 -1
  17. package/src/modules/messages/utils/set-messages-cache/utils.ts +1 -1
  18. package/src/modules/sparkie/hooks/use-init-sparkie/use-init-sparkie.tsx +6 -20
  19. package/src/modules/sparkie/service.ts +3 -2
  20. package/src/modules/widget/components/ai-disclaimer/ai-disclaimer.tsx +19 -0
  21. package/src/modules/widget/components/ai-disclaimer/index.ts +1 -0
  22. package/src/modules/widget/components/chat-page/chat-page.tsx +30 -71
  23. package/src/modules/widget/components/constants.tsx +1 -3
  24. package/src/modules/widget/components/container/container.tsx +14 -0
  25. package/src/modules/widget/components/greetings-card/greetings-card.tsx +9 -2
  26. package/src/modules/widget/components/starter-page/starter-page.tsx +63 -34
  27. package/src/modules/widget/store/widget-tabs.atom.ts +1 -31
  28. package/src/types.ts +0 -9
  29. package/src/index.backup.tsx +0 -61
  30. package/src/lib/hooks/use-response-timeout/index.ts +0 -1
  31. package/src/lib/hooks/use-response-timeout/use-response-timeout.tsx +0 -42
  32. package/src/modules/sparkie/store/index.ts +0 -1
  33. package/src/modules/sparkie/store/sparkie-state.atom.ts +0 -13
  34. package/src/modules/widget/components/error-page/error-page.spec.tsx +0 -17
  35. package/src/modules/widget/components/error-page/error-page.tsx +0 -10
  36. package/src/modules/widget/components/error-page/index.ts +0 -1
  37. package/src/modules/widget/components/starter-page/starter-page-actions/index.ts +0 -1
  38. package/src/modules/widget/components/starter-page/starter-page-actions/starter-page-actions.spec.tsx +0 -68
  39. package/src/modules/widget/components/starter-page/starter-page-actions/starter-page-actions.tsx +0 -33
  40. package/src/modules/widget/components/starter-page/starter-page-content/index.ts +0 -1
  41. package/src/modules/widget/components/starter-page/starter-page-content/starter-page-content.spec.tsx +0 -62
  42. package/src/modules/widget/components/starter-page/starter-page-content/starter-page-content.tsx +0 -57
  43. package/src/modules/widget/components/starter-page/starter-page-header/index.ts +0 -1
  44. package/src/modules/widget/components/starter-page/starter-page-header/starter-page-header.spec.tsx +0 -41
  45. package/src/modules/widget/components/starter-page/starter-page-header/starter-page-header.tsx +0 -34
  46. package/src/wrapper.tsx +0 -32
@@ -1,33 +0,0 @@
1
- import { useMemo } from 'react'
2
- import { useDecision } from '@optimizely/react-sdk'
3
-
4
- import { useInitSparkie } from '@/src/modules/sparkie/hooks'
5
- import { useIsAgentParentAtomValue, useWidgetSettingsAtomValue } from '../../../store'
6
- import { QuickActionButtons } from '../../quick-action-buttons'
7
-
8
- function WidgetStarterPageActions({ send }: { send: (textContent?: string | null) => void }) {
9
- const [tutorQuickActionsFF] = useDecision('lex_tutor_quick_actions')
10
- const settings = useWidgetSettingsAtomValue()
11
- const isAgentMode = useIsAgentParentAtomValue()
12
- const isSparkieReady = useInitSparkie()
13
-
14
- const isDarkTheme = useMemo(() => settings?.config?.theme === 'dark', [settings?.config?.theme])
15
-
16
- const shouldNotRender = useMemo(
17
- () => [isAgentMode, !tutorQuickActionsFF?.enabled].some(Boolean),
18
- [isAgentMode, tutorQuickActionsFF?.enabled]
19
- )
20
-
21
- if (shouldNotRender) return null
22
-
23
- return (
24
- <QuickActionButtons
25
- className='grid-area-[b] my-4 flex flex-shrink-0 snap-x snap-mandatory gap-2 overflow-x-auto whitespace-nowrap [scrollbar-width:none] [&::-webkit-scrollbar]:hidden'
26
- isDarkTheme={isDarkTheme}
27
- send={send}
28
- loading={!isSparkieReady}
29
- />
30
- )
31
- }
32
-
33
- export default WidgetStarterPageActions
@@ -1 +0,0 @@
1
- export { default as WidgetStarterPageContent } from './starter-page-content'
@@ -1,62 +0,0 @@
1
- import { render, screen } from '@/src/config/tests'
2
- import { useSparkieStateAtomValue } from '@/src/modules/sparkie/store'
3
- import {
4
- useIsAgentParentAtomValue,
5
- useWidgetLoadingAtomValue,
6
- useWidgetTabsAtom
7
- } from '../../../store'
8
-
9
- import WidgetStarterPageContent from './starter-page-content'
10
-
11
- vi.mock('../../../store', async (importActual) => ({
12
- ...(await importActual()),
13
- useIsAgentParentAtomValue: vi.fn(),
14
- useWidgetLoadingAtomValue: vi.fn(),
15
- useWidgetTabsAtom: vi.fn()
16
- }))
17
-
18
- vi.mock('@/src/modules/sparkie/store', () => ({
19
- useSparkieStateAtomValue: vi.fn()
20
- }))
21
-
22
- describe('<WidgetStarterPageContent />', () => {
23
- const widgetTabsMock = ['starter', vi.fn()]
24
-
25
- const renderComponent = () => render(<WidgetStarterPageContent />)
26
-
27
- beforeEach(() => {
28
- vi.mocked(useIsAgentParentAtomValue).mockReturnValue(false)
29
- vi.mocked(useWidgetLoadingAtomValue).mockReturnValue(false)
30
- vi.mocked(useSparkieStateAtomValue).mockReturnValue('idle')
31
- vi.mocked(useWidgetTabsAtom).mockReturnValue(widgetTabsMock as never)
32
- })
33
-
34
- it('should render greetings card when not in agent mode', () => {
35
- renderComponent()
36
-
37
- expect(screen.getByText(/sparkle-tutor-light/i)).toBeInTheDocument()
38
- expect(screen.getByText(/general.greetings.hello/i)).toBeInTheDocument()
39
- expect(screen.getByText(/general.greetings.firstMessage/i)).toBeInTheDocument()
40
- expect(screen.getByText(/general.greetings.description/i)).toBeInTheDocument()
41
- })
42
-
43
- it('should render the skeleton when in agent mode and is loading state', () => {
44
- vi.mocked(useIsAgentParentAtomValue).mockReturnValueOnce(true)
45
- vi.mocked(useWidgetLoadingAtomValue).mockReturnValueOnce(true)
46
-
47
- renderComponent()
48
-
49
- expect(screen.getByTestId('avatar-animation-icon')).toBeInTheDocument()
50
- })
51
-
52
- it('should redirect to chat page when in agent mode, widget is not loading and sparkie is initialized', () => {
53
- vi.mocked(useSparkieStateAtomValue).mockReturnValue('initialized')
54
- vi.mocked(useIsAgentParentAtomValue).mockReturnValueOnce(true)
55
-
56
- const { container } = renderComponent()
57
-
58
- expect(container).toBeEmptyDOMElement()
59
- expect(widgetTabsMock[1]).toHaveBeenCalledOnce()
60
- expect(widgetTabsMock[1]).toHaveBeenNthCalledWith(1, 'chat')
61
- })
62
- })
@@ -1,57 +0,0 @@
1
- import { useMemo } from 'react'
2
- import { useTranslation } from 'react-i18next'
3
-
4
- import { MessageSkeleton } from '@/src/modules/messages/components'
5
- import { useSparkieStateAtomValue } from '@/src/modules/sparkie/store'
6
- import {
7
- useIsAgentParentAtomValue,
8
- useWidgetLoadingAtomValue,
9
- useWidgetSettingsAtomValue,
10
- useWidgetTabsAtom
11
- } from '../../../store'
12
- import { GreetingsCard } from '../../greetings-card'
13
-
14
- function WidgetStarterPageContent() {
15
- const { t } = useTranslation()
16
- const settings = useWidgetSettingsAtomValue()
17
- const isAgentMode = useIsAgentParentAtomValue()
18
- const widgetLoading = useWidgetLoadingAtomValue()
19
- const [, setWidgetTabs] = useWidgetTabsAtom()
20
- const sparkieState = useSparkieStateAtomValue()
21
-
22
- const authorName = useMemo(() => {
23
- const username = typeof settings?.user?.name === 'string' ? settings?.user?.name : ''
24
-
25
- return username?.split?.(' ')?.[0] || ''
26
- }, [settings?.user?.name])
27
-
28
- const isDarkTheme = useMemo(() => settings?.config?.theme === 'dark', [settings?.config?.theme])
29
-
30
- const name = useMemo(() => settings?.tutorName ?? t('general.name'), [settings?.tutorName, t])
31
-
32
- const shouldGoToChat = useMemo(
33
- () => [isAgentMode, !widgetLoading, sparkieState === 'initialized'].every(Boolean),
34
- [isAgentMode, sparkieState, widgetLoading]
35
- )
36
-
37
- if (shouldGoToChat) {
38
- setWidgetTabs('chat')
39
- return null
40
- }
41
-
42
- if (isAgentMode && (widgetLoading || sparkieState !== 'initialized')) {
43
- return (
44
- <div className='mt-auto'>
45
- <MessageSkeleton />
46
- </div>
47
- )
48
- }
49
-
50
- return (
51
- <div className='my-auto'>
52
- <GreetingsCard author={authorName} tutorName={name} isDarkTheme={isDarkTheme} />
53
- </div>
54
- )
55
- }
56
-
57
- export default WidgetStarterPageContent
@@ -1 +0,0 @@
1
- export { default as WidgetStarterPageHeader } from './starter-page-header'
@@ -1,41 +0,0 @@
1
- import { render, screen } from '@/src/config/tests'
2
- import { useInitSparkie } from '@/src/modules/sparkie/hooks/use-init-sparkie'
3
- import { useIsAgentParentAtomValue } from '../../../store/widget-settings-config.atom'
4
-
5
- import WidgetStarterPageHeader from './starter-page-header'
6
-
7
- vi.mock('../../../store/widget-settings-config.atom')
8
- vi.mock('@/src/modules/sparkie/hooks/use-init-sparkie', () => ({ useInitSparkie: vi.fn() }))
9
-
10
- describe('<WidgetStarterPageHeader />', () => {
11
- const renderComponent = () => render(<WidgetStarterPageHeader />)
12
-
13
- beforeEach(() => {
14
- vi.mocked(useIsAgentParentAtomValue).mockReturnValue(true)
15
- vi.mocked(useInitSparkie).mockReturnValue(false)
16
- })
17
-
18
- it('should return null when rendered as agent mode', () => {
19
- const { container } = renderComponent()
20
-
21
- expect(container).toBeEmptyDOMElement()
22
- })
23
-
24
- it('should render without errors when is not rendered as agent', () => {
25
- vi.mocked(useIsAgentParentAtomValue).mockReturnValue(false)
26
- renderComponent()
27
-
28
- expect(screen.getByRole('button', { name: /general.buttons.info Icon/i })).toBeInTheDocument()
29
- expect(screen.getByRole('button', { name: /Close Icon/i })).toBeInTheDocument()
30
- })
31
-
32
- it('should render the archive button when isSparkieReady is true', () => {
33
- vi.mocked(useIsAgentParentAtomValue).mockReturnValue(false)
34
- vi.mocked(useInitSparkie).mockReturnValue(true)
35
- renderComponent()
36
-
37
- expect(
38
- screen.getByRole('button', { name: /general.buttons.archive Icon/i })
39
- ).toBeInTheDocument()
40
- })
41
- })
@@ -1,34 +0,0 @@
1
- import { useMemo } from 'react'
2
- import { useTranslation } from 'react-i18next'
3
-
4
- import type { ValidIconNames } from '@/src/lib/components/icons/icon-names'
5
- import { useMediaQuery } from '@/src/lib/hooks'
6
- import { useInitSparkie } from '@/src/modules/sparkie/hooks'
7
- import { useIsAgentParentAtomValue, useWidgetSettingsAtomValue } from '../../../store'
8
- import { WidgetHeader } from '../../header'
9
-
10
- function WidgetStarterPageHeader() {
11
- const { t } = useTranslation()
12
- const settings = useWidgetSettingsAtomValue()
13
- const isAgentMode = useIsAgentParentAtomValue()
14
- const isSparkieReady = useInitSparkie()
15
- const isMobile = useMediaQuery({ maxSize: 'md' })
16
-
17
- const enabledButtons = useMemo(() => {
18
- const btns = ['close', 'info'] as ValidIconNames[]
19
-
20
- if (isSparkieReady) {
21
- btns.push('archive')
22
- }
23
-
24
- return btns
25
- }, [isSparkieReady])
26
-
27
- const name = useMemo(() => settings?.tutorName ?? t('general.name'), [settings?.tutorName, t])
28
-
29
- if (isAgentMode) return null
30
-
31
- return <WidgetHeader enabledButtons={enabledButtons} tutorName={name} showContent={isMobile} />
32
- }
33
-
34
- export default WidgetStarterPageHeader
package/src/wrapper.tsx DELETED
@@ -1,32 +0,0 @@
1
- import { useEffect } from 'react'
2
-
3
- import { Main } from './main'
4
- import { SparkieService } from './modules/sparkie'
5
- import { useSparkieStateAtom } from './modules/sparkie/store'
6
- import type { WidgetSettingProps } from './types'
7
-
8
- export type WrapperProps = {
9
- settings: WidgetSettingProps
10
- }
11
-
12
- function Wrapper({ settings }: WrapperProps) {
13
- const [, setSparkieState] = useSparkieStateAtom()
14
-
15
- useEffect(() => {
16
- SparkieService.initSparkie({
17
- token: settings?.hotmartToken,
18
- skipPresenceSetup: true,
19
- retryOptions: {
20
- maxRetries: 5,
21
- retryDelay: 2000,
22
- backoffMultiplier: 1.5
23
- }
24
- })
25
- .then((result) => setSparkieState(result ? 'initialized' : 'failed'))
26
- .catch(() => setSparkieState('failed'))
27
- }, [setSparkieState, settings?.hotmartToken])
28
-
29
- return <Main settings={settings} />
30
- }
31
-
32
- export default Wrapper