@orbe-agro/client-core 5.6.260 → 5.6.261

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 (94) hide show
  1. package/dist/@ecme/assets/styles/app.css +23 -3
  2. package/dist/@ecme/assets/styles/tailwind/index.css +25 -3
  3. package/dist/@ecme/components/template/Footer.js +1 -1
  4. package/dist/@ecme/components/template/OrbeAiWidget/OrbeAiChatDrawer.js +121 -0
  5. package/dist/@ecme/components/template/OrbeAiWidget/OrbeAiChatDrawer.js.map +1 -0
  6. package/dist/@ecme/components/template/OrbeAiWidget/OrbeAiWidget.js +47 -18
  7. package/dist/@ecme/components/template/OrbeAiWidget/OrbeAiWidget.js.map +1 -1
  8. package/dist/@ecme/components/template/OrbeAiWidget/useResizablePanel.js +45 -31
  9. package/dist/@ecme/components/template/OrbeAiWidget/useResizablePanel.js.map +1 -1
  10. package/dist/@ecme/components/ui/Dropdown/DropdownMenu.js +5 -1
  11. package/dist/@ecme/components/ui/Dropdown/DropdownMenu.js.map +1 -1
  12. package/dist/@ecme/index.js +4 -1
  13. package/dist/@ecme/services/AiService.js +22 -0
  14. package/dist/@ecme/services/AiService.js.map +1 -1
  15. package/dist/@ecme/services/index.js +4 -1
  16. package/dist/@ecme/views/concepts/ai/Chat/components/ChatHistory.js +9 -23
  17. package/dist/@ecme/views/concepts/ai/Chat/components/ChatHistory.js.map +1 -1
  18. package/dist/@ecme/views/concepts/ai/Chat/components/ChatHistoryItem.js +6 -16
  19. package/dist/@ecme/views/concepts/ai/Chat/components/ChatHistoryItem.js.map +1 -1
  20. package/dist/@ecme/views/concepts/ai/Chat/components/ChatHistoryRenameDialog.js +10 -7
  21. package/dist/@ecme/views/concepts/ai/Chat/components/ChatHistoryRenameDialog.js.map +1 -1
  22. package/dist/@ecme/views/concepts/ai/Chat/components/ChatView.js +6 -4
  23. package/dist/@ecme/views/concepts/ai/Chat/components/ChatView.js.map +1 -1
  24. package/dist/@ecme/views/concepts/ai/Chat/hooks/useChatConversations.js +83 -0
  25. package/dist/@ecme/views/concepts/ai/Chat/hooks/useChatConversations.js.map +1 -0
  26. package/dist/@ecme/views/concepts/ai/Chat/hooks/useChatSend.js +3 -2
  27. package/dist/@ecme/views/concepts/ai/Chat/hooks/useChatSend.js.map +1 -1
  28. package/dist/@ecme/views/concepts/ai/Chat/hooks/useConversationMessages.js +37 -0
  29. package/dist/@ecme/views/concepts/ai/Chat/hooks/useConversationMessages.js.map +1 -0
  30. package/dist/@ecme/views/concepts/ai/Chat/store/generativeChatStore.js +25 -1
  31. package/dist/@ecme/views/concepts/ai/Chat/store/generativeChatStore.js.map +1 -1
  32. package/dist/@ecme/views/concepts/ai/Chat/utils.js +16 -1
  33. package/dist/@ecme/views/concepts/ai/Chat/utils.js.map +1 -1
  34. package/dist/@types/@ecme/components/template/OrbeAiWidget/OrbeAiChatDrawer.d.ts +14 -0
  35. package/dist/@types/@ecme/components/template/OrbeAiWidget/OrbeAiChatDrawer.d.ts.map +1 -0
  36. package/dist/@types/@ecme/components/template/OrbeAiWidget/OrbeAiWidget.d.ts.map +1 -1
  37. package/dist/@types/@ecme/components/template/OrbeAiWidget/useResizablePanel.d.ts +12 -5
  38. package/dist/@types/@ecme/components/template/OrbeAiWidget/useResizablePanel.d.ts.map +1 -1
  39. package/dist/@types/@ecme/components/ui/Dropdown/DropdownMenu.d.ts +2 -0
  40. package/dist/@types/@ecme/components/ui/Dropdown/DropdownMenu.d.ts.map +1 -1
  41. package/dist/@types/@ecme/services/AiService.d.ts +5 -0
  42. package/dist/@types/@ecme/services/AiService.d.ts.map +1 -1
  43. package/dist/@types/@ecme/views/concepts/ai/Chat/components/ChatHistory.d.ts +3 -1
  44. package/dist/@types/@ecme/views/concepts/ai/Chat/components/ChatHistory.d.ts.map +1 -1
  45. package/dist/@types/@ecme/views/concepts/ai/Chat/components/ChatHistoryItem.d.ts +1 -1
  46. package/dist/@types/@ecme/views/concepts/ai/Chat/components/ChatHistoryItem.d.ts.map +1 -1
  47. package/dist/@types/@ecme/views/concepts/ai/Chat/components/ChatHistoryRenameDialog.d.ts +5 -1
  48. package/dist/@types/@ecme/views/concepts/ai/Chat/components/ChatHistoryRenameDialog.d.ts.map +1 -1
  49. package/dist/@types/@ecme/views/concepts/ai/Chat/components/ChatView.d.ts +8 -1
  50. package/dist/@types/@ecme/views/concepts/ai/Chat/components/ChatView.d.ts.map +1 -1
  51. package/dist/@types/@ecme/views/concepts/ai/Chat/hooks/useChatConversations.d.ts +12 -0
  52. package/dist/@types/@ecme/views/concepts/ai/Chat/hooks/useChatConversations.d.ts.map +1 -0
  53. package/dist/@types/@ecme/views/concepts/ai/Chat/hooks/useChatSend.d.ts.map +1 -1
  54. package/dist/@types/@ecme/views/concepts/ai/Chat/hooks/useConversationMessages.d.ts +12 -0
  55. package/dist/@types/@ecme/views/concepts/ai/Chat/hooks/useConversationMessages.d.ts.map +1 -0
  56. package/dist/@types/@ecme/views/concepts/ai/Chat/store/generativeChatStore.d.ts +4 -0
  57. package/dist/@types/@ecme/views/concepts/ai/Chat/store/generativeChatStore.d.ts.map +1 -1
  58. package/dist/@types/@ecme/views/concepts/ai/Chat/types.d.ts +24 -0
  59. package/dist/@types/@ecme/views/concepts/ai/Chat/types.d.ts.map +1 -1
  60. package/dist/@types/@ecme/views/concepts/ai/Chat/utils.d.ts +13 -0
  61. package/dist/@types/@ecme/views/concepts/ai/Chat/utils.d.ts.map +1 -1
  62. package/dist/@types/base/configs/endpoints.config/endpoints.navigation.d.ts +8 -0
  63. package/dist/@types/base/configs/endpoints.config/endpoints.navigation.d.ts.map +1 -1
  64. package/dist/@types/base/configs/endpoints.config/transportadora/contratoFrete.d.ts +8 -0
  65. package/dist/@types/base/configs/endpoints.config/transportadora/contratoFrete.d.ts.map +1 -1
  66. package/dist/@types/base/services/modules/transportadora/ContratoFrete/ContratoFreteService.d.ts +2 -0
  67. package/dist/@types/base/services/modules/transportadora/ContratoFrete/ContratoFreteService.d.ts.map +1 -1
  68. package/dist/base/assets/styles/init.css +23 -4
  69. package/dist/base/configs/endpoints.config/transportadora/contratoFrete.js +3 -1
  70. package/dist/base/configs/endpoints.config/transportadora/contratoFrete.js.map +1 -1
  71. package/dist/base/index.js +3 -1
  72. package/dist/base/services/index.js +3 -1
  73. package/dist/base/services/modules/index.js +3 -1
  74. package/dist/base/services/modules/transportadora/ContratoFrete/ContratoFreteService.js +14 -0
  75. package/dist/base/services/modules/transportadora/ContratoFrete/ContratoFreteService.js.map +1 -1
  76. package/dist/base/services/modules/transportadora/index.js +3 -1
  77. package/lib/@ecme/components/template/OrbeAiWidget/OrbeAiChatDrawer.tsx +140 -0
  78. package/lib/@ecme/components/template/OrbeAiWidget/OrbeAiWidget.tsx +48 -16
  79. package/lib/@ecme/components/template/OrbeAiWidget/useResizablePanel.ts +72 -37
  80. package/lib/@ecme/components/ui/Dropdown/DropdownMenu.tsx +7 -1
  81. package/lib/@ecme/services/AiService.ts +24 -0
  82. package/lib/@ecme/views/concepts/ai/Chat/components/ChatHistory.tsx +11 -27
  83. package/lib/@ecme/views/concepts/ai/Chat/components/ChatHistoryItem.tsx +7 -13
  84. package/lib/@ecme/views/concepts/ai/Chat/components/ChatHistoryRenameDialog.tsx +17 -8
  85. package/lib/@ecme/views/concepts/ai/Chat/components/ChatView.tsx +17 -4
  86. package/lib/@ecme/views/concepts/ai/Chat/hooks/useChatConversations.tsx +128 -0
  87. package/lib/@ecme/views/concepts/ai/Chat/hooks/useChatSend.ts +3 -2
  88. package/lib/@ecme/views/concepts/ai/Chat/hooks/useConversationMessages.ts +68 -0
  89. package/lib/@ecme/views/concepts/ai/Chat/store/generativeChatStore.ts +44 -1
  90. package/lib/@ecme/views/concepts/ai/Chat/types.ts +28 -0
  91. package/lib/@ecme/views/concepts/ai/Chat/utils.ts +33 -0
  92. package/lib/base/configs/endpoints.config/transportadora/contratoFrete.ts +2 -0
  93. package/lib/base/services/modules/transportadora/ContratoFrete/ContratoFreteService.ts +14 -0
  94. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.js","sources":["../../../../../lib/@ecme/components/ui/Dropdown/DropdownMenu.tsx"],"sourcesContent":["import {\n useState,\n useRef,\n useContext,\n useEffect,\n useImperativeHandle,\n} from 'react'\nimport DropdownToggle from './DropdownToggle'\nimport DropdownSubItem from './DropdownSubItem'\nimport MenuContext from './context/menuContext'\nimport classNames from '../utils/classNames'\nimport { useConfig } from '../ConfigProvider'\nimport {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingList,\n FloatingNode,\n FloatingPortal,\n safePolygon,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListItem,\n useListNavigation,\n useMergeRefs,\n useRole,\n useTypeahead,\n useTransitionStyles,\n} from '@floating-ui/react'\nimport type { CommonProps } from '../@types/common'\nimport type { DropdownToggleSharedProps } from './DropdownToggle'\nimport type { DropdownSubItemSharedProps } from './DropdownSubItem'\nimport type { Placement } from '@floating-ui/react'\nimport type { HTMLProps, FocusEvent, MouseEvent, ReactNode, Ref } from 'react'\n\nexport interface DropdownMenuProps\n extends CommonProps,\n DropdownToggleSharedProps,\n DropdownSubItemSharedProps {\n activeKey?: string\n title?: string | ReactNode\n menuClass?: string\n trigger?: 'click' | 'hover' | 'context'\n placement?: Placement\n onOpen?: (bool: boolean) => void\n ref?: Ref<HTMLElement | DropdownMenuRef>\n}\n\nexport type DropdownMenuRef = {\n handleDropdownOpen: () => void\n handleDropdownClose: () => void\n}\n\nconst DropdownMenu = (props: DropdownMenuProps & HTMLProps<HTMLElement>) => {\n const {\n children,\n title,\n renderTitle,\n disabled,\n toggleClassName,\n menuClass,\n placement,\n trigger = 'click',\n onOpen,\n ref,\n ...rest\n } = props\n\n const [isOpen, setIsOpen] = useState(false)\n const [hasFocusInside, setHasFocusInside] = useState(false)\n const [activeIndex, setActiveIndex] = useState<number | null>(null)\n\n const elementsRef = useRef<Array<HTMLElement | null>>([])\n const labelsRef = useRef<Array<string | null>>([])\n\n const { direction } = useConfig()\n\n const parent = useContext(MenuContext)\n\n const tree = useFloatingTree()\n const nodeId = useFloatingNodeId()\n const parentId = useFloatingParentNodeId()\n const item = useListItem()\n\n const isNested = parentId != null\n\n const handleOpen = (open: boolean) => {\n if (disabled) {\n return\n }\n setIsOpen(open)\n onOpen?.(open)\n }\n\n const getDefaultPlacement = () => {\n return direction === 'ltr' ? 'bottom-start' : 'bottom-end'\n }\n\n const getNestedDefaultPlacement = () => {\n return direction === 'ltr' ? 'right-start' : 'left-start'\n }\n\n const { floatingStyles, refs, context } = useFloating<HTMLElement>({\n nodeId,\n open: isOpen,\n onOpenChange: (open) => {\n handleOpen(open)\n },\n placement:\n placement ||\n (isNested ? getNestedDefaultPlacement() : getDefaultPlacement()),\n middleware: [flip(), shift()],\n whileElementsMounted: autoUpdate,\n })\n\n const { isMounted, styles } = useTransitionStyles(context, {\n common: ({ side }) => ({\n transformOrigin: {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n }[side],\n }),\n initial: {\n transform: 'translateY(-5%)',\n opacity: 0,\n },\n duration: 200,\n open: {\n opacity: 1,\n transform: 'translateY(0%)',\n },\n close: {\n opacity: 0,\n transform: 'translateY(-5%)',\n },\n })\n\n const hover = useHover(context, {\n enabled: isNested || trigger === 'hover',\n delay: { open: 75 },\n handleClose: safePolygon({ blockPointerEvents: true }),\n })\n\n const click = useClick(context, {\n event: 'mousedown',\n toggle: !isNested,\n ignoreMouse: isNested,\n })\n\n const role = useRole(context, { role: 'menu' })\n\n const dismiss = useDismiss(context, { bubbles: true })\n\n const listNavigation = useListNavigation(context, {\n listRef: elementsRef,\n activeIndex,\n nested: isNested,\n onNavigate: setActiveIndex,\n })\n const typeahead = useTypeahead(context, {\n listRef: labelsRef,\n onMatch: isOpen ? setActiveIndex : undefined,\n activeIndex,\n })\n\n const { getReferenceProps, getFloatingProps, getItemProps } =\n useInteractions([\n hover,\n role,\n dismiss,\n listNavigation,\n typeahead,\n ...(trigger === 'click' ? [click] : []),\n ])\n\n useEffect(() => {\n if (!tree) return\n\n function handleTreeClick() {\n setIsOpen(false)\n onOpen?.(false)\n }\n\n function onSubMenuOpen(event: { nodeId: string; parentId: string }) {\n if (event.nodeId !== nodeId && event.parentId === parentId) {\n setIsOpen(false)\n onOpen?.(false)\n }\n }\n\n tree.events.on('click', handleTreeClick)\n tree.events.on('menuopen', onSubMenuOpen)\n\n return () => {\n tree.events.off('click', handleTreeClick)\n tree.events.off('menuopen', onSubMenuOpen)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tree, nodeId, parentId])\n\n useEffect(() => {\n if (isOpen && tree) {\n tree.events.emit('menuopen', { parentId, nodeId })\n }\n }, [tree, isOpen, nodeId, parentId])\n\n const toggleRef = useMergeRefs([refs.setReference, item.ref, ref])\n\n useImperativeHandle(ref, () => {\n return {\n handleDropdownOpen: () => {\n setIsOpen(true)\n onOpen?.(true)\n },\n handleDropdownClose: () => {\n setIsOpen(false)\n onOpen?.(false)\n },\n }\n }, [onOpen])\n\n const toggleProps = {\n ...getReferenceProps(\n parent.getItemProps({\n ...rest,\n onFocus(event: FocusEvent<HTMLElement>) {\n rest.onFocus?.(event)\n setHasFocusInside(false)\n parent.setHasFocusInside(true)\n },\n }),\n ),\n ...(trigger === 'context'\n ? {\n onContextMenu: (e: MouseEvent<HTMLElement>) => {\n e.preventDefault()\n handleOpen(true)\n },\n }\n : {}),\n }\n\n return (\n <FloatingNode id={nodeId}>\n {!isNested ? (\n <DropdownToggle\n ref={toggleRef}\n role={'menuitem'}\n data-open={isOpen ? '' : undefined}\n data-focus-inside={hasFocusInside ? '' : undefined}\n className={classNames(toggleClassName)}\n disabled={disabled}\n placement={placement}\n renderTitle={renderTitle}\n {...toggleProps}\n >\n {title}\n </DropdownToggle>\n ) : (\n <li\n ref={toggleRef}\n tabIndex={parent.activeIndex === item.index ? 0 : -1}\n data-open={isOpen ? '' : undefined}\n data-nested={''}\n data-focus-inside={hasFocusInside ? '' : undefined}\n className={classNames(toggleClassName, 'outline-none')}\n {...toggleProps}\n >\n <DropdownSubItem>\n {renderTitle ? renderTitle : title}\n </DropdownSubItem>\n </li>\n )}\n <MenuContext.Provider\n value={{\n activeIndex,\n setActiveIndex,\n getItemProps,\n setHasFocusInside,\n isOpen,\n }}\n >\n <FloatingList elementsRef={elementsRef} labelsRef={labelsRef}>\n {isMounted && (\n <FloatingPortal>\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={isNested ? -1 : 0}\n returnFocus={!isNested}\n >\n <div\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n className=\"outline-none z-30\"\n >\n <ul\n className={classNames(\n 'dropdown-menu min-w-[160px]',\n menuClass,\n )}\n style={styles}\n >\n {children}\n </ul>\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </FloatingList>\n </MenuContext.Provider>\n </FloatingNode>\n )\n}\n\nexport default DropdownMenu\n"],"names":["DropdownSubItem"],"mappings":"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"}
1
+ {"version":3,"file":"DropdownMenu.js","sources":["../../../../../lib/@ecme/components/ui/Dropdown/DropdownMenu.tsx"],"sourcesContent":["import {\n useState,\n useRef,\n useContext,\n useEffect,\n useImperativeHandle,\n} from 'react'\nimport DropdownToggle from './DropdownToggle'\nimport DropdownSubItem from './DropdownSubItem'\nimport MenuContext from './context/menuContext'\nimport classNames from '../utils/classNames'\nimport { useConfig } from '../ConfigProvider'\nimport {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingList,\n FloatingNode,\n FloatingPortal,\n safePolygon,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListItem,\n useListNavigation,\n useMergeRefs,\n useRole,\n useTypeahead,\n useTransitionStyles,\n} from '@floating-ui/react'\nimport type { CommonProps } from '../@types/common'\nimport type { DropdownToggleSharedProps } from './DropdownToggle'\nimport type { DropdownSubItemSharedProps } from './DropdownSubItem'\nimport type { Placement } from '@floating-ui/react'\nimport type { HTMLProps, FocusEvent, MouseEvent, ReactNode, Ref } from 'react'\n\nexport interface DropdownMenuProps\n extends CommonProps,\n DropdownToggleSharedProps,\n DropdownSubItemSharedProps {\n activeKey?: string\n title?: string | ReactNode\n menuClass?: string\n /** Classes do wrapper flutuante (portal). Útil para subir o z-index acima de painéis fixos. */\n floatingClass?: string\n trigger?: 'click' | 'hover' | 'context'\n placement?: Placement\n onOpen?: (bool: boolean) => void\n ref?: Ref<HTMLElement | DropdownMenuRef>\n}\n\nexport type DropdownMenuRef = {\n handleDropdownOpen: () => void\n handleDropdownClose: () => void\n}\n\nconst DropdownMenu = (props: DropdownMenuProps & HTMLProps<HTMLElement>) => {\n const {\n children,\n title,\n renderTitle,\n disabled,\n toggleClassName,\n menuClass,\n floatingClass,\n placement,\n trigger = 'click',\n onOpen,\n ref,\n ...rest\n } = props\n\n const [isOpen, setIsOpen] = useState(false)\n const [hasFocusInside, setHasFocusInside] = useState(false)\n const [activeIndex, setActiveIndex] = useState<number | null>(null)\n\n const elementsRef = useRef<Array<HTMLElement | null>>([])\n const labelsRef = useRef<Array<string | null>>([])\n\n const { direction } = useConfig()\n\n const parent = useContext(MenuContext)\n\n const tree = useFloatingTree()\n const nodeId = useFloatingNodeId()\n const parentId = useFloatingParentNodeId()\n const item = useListItem()\n\n const isNested = parentId != null\n\n const handleOpen = (open: boolean) => {\n if (disabled) {\n return\n }\n setIsOpen(open)\n onOpen?.(open)\n }\n\n const getDefaultPlacement = () => {\n return direction === 'ltr' ? 'bottom-start' : 'bottom-end'\n }\n\n const getNestedDefaultPlacement = () => {\n return direction === 'ltr' ? 'right-start' : 'left-start'\n }\n\n const { floatingStyles, refs, context } = useFloating<HTMLElement>({\n nodeId,\n open: isOpen,\n onOpenChange: (open) => {\n handleOpen(open)\n },\n placement:\n placement ||\n (isNested ? getNestedDefaultPlacement() : getDefaultPlacement()),\n middleware: [flip(), shift()],\n whileElementsMounted: autoUpdate,\n })\n\n const { isMounted, styles } = useTransitionStyles(context, {\n common: ({ side }) => ({\n transformOrigin: {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n }[side],\n }),\n initial: {\n transform: 'translateY(-5%)',\n opacity: 0,\n },\n duration: 200,\n open: {\n opacity: 1,\n transform: 'translateY(0%)',\n },\n close: {\n opacity: 0,\n transform: 'translateY(-5%)',\n },\n })\n\n const hover = useHover(context, {\n enabled: isNested || trigger === 'hover',\n delay: { open: 75 },\n handleClose: safePolygon({ blockPointerEvents: true }),\n })\n\n const click = useClick(context, {\n event: 'mousedown',\n toggle: !isNested,\n ignoreMouse: isNested,\n })\n\n const role = useRole(context, { role: 'menu' })\n\n const dismiss = useDismiss(context, { bubbles: true })\n\n const listNavigation = useListNavigation(context, {\n listRef: elementsRef,\n activeIndex,\n nested: isNested,\n onNavigate: setActiveIndex,\n })\n const typeahead = useTypeahead(context, {\n listRef: labelsRef,\n onMatch: isOpen ? setActiveIndex : undefined,\n activeIndex,\n })\n\n const { getReferenceProps, getFloatingProps, getItemProps } =\n useInteractions([\n hover,\n role,\n dismiss,\n listNavigation,\n typeahead,\n ...(trigger === 'click' ? [click] : []),\n ])\n\n useEffect(() => {\n if (!tree) return\n\n function handleTreeClick() {\n setIsOpen(false)\n onOpen?.(false)\n }\n\n function onSubMenuOpen(event: { nodeId: string; parentId: string }) {\n if (event.nodeId !== nodeId && event.parentId === parentId) {\n setIsOpen(false)\n onOpen?.(false)\n }\n }\n\n tree.events.on('click', handleTreeClick)\n tree.events.on('menuopen', onSubMenuOpen)\n\n return () => {\n tree.events.off('click', handleTreeClick)\n tree.events.off('menuopen', onSubMenuOpen)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tree, nodeId, parentId])\n\n useEffect(() => {\n if (isOpen && tree) {\n tree.events.emit('menuopen', { parentId, nodeId })\n }\n }, [tree, isOpen, nodeId, parentId])\n\n const toggleRef = useMergeRefs([refs.setReference, item.ref, ref])\n\n useImperativeHandle(ref, () => {\n return {\n handleDropdownOpen: () => {\n setIsOpen(true)\n onOpen?.(true)\n },\n handleDropdownClose: () => {\n setIsOpen(false)\n onOpen?.(false)\n },\n }\n }, [onOpen])\n\n const toggleProps = {\n ...getReferenceProps(\n parent.getItemProps({\n ...rest,\n onFocus(event: FocusEvent<HTMLElement>) {\n rest.onFocus?.(event)\n setHasFocusInside(false)\n parent.setHasFocusInside(true)\n },\n }),\n ),\n ...(trigger === 'context'\n ? {\n onContextMenu: (e: MouseEvent<HTMLElement>) => {\n e.preventDefault()\n handleOpen(true)\n },\n }\n : {}),\n }\n\n return (\n <FloatingNode id={nodeId}>\n {!isNested ? (\n <DropdownToggle\n ref={toggleRef}\n role={'menuitem'}\n data-open={isOpen ? '' : undefined}\n data-focus-inside={hasFocusInside ? '' : undefined}\n className={classNames(toggleClassName)}\n disabled={disabled}\n placement={placement}\n renderTitle={renderTitle}\n {...toggleProps}\n >\n {title}\n </DropdownToggle>\n ) : (\n <li\n ref={toggleRef}\n tabIndex={parent.activeIndex === item.index ? 0 : -1}\n data-open={isOpen ? '' : undefined}\n data-nested={''}\n data-focus-inside={hasFocusInside ? '' : undefined}\n className={classNames(toggleClassName, 'outline-none')}\n {...toggleProps}\n >\n <DropdownSubItem>\n {renderTitle ? renderTitle : title}\n </DropdownSubItem>\n </li>\n )}\n <MenuContext.Provider\n value={{\n activeIndex,\n setActiveIndex,\n getItemProps,\n setHasFocusInside,\n isOpen,\n }}\n >\n <FloatingList elementsRef={elementsRef} labelsRef={labelsRef}>\n {isMounted && (\n <FloatingPortal>\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={isNested ? -1 : 0}\n returnFocus={!isNested}\n >\n <div\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n className={classNames(\n 'outline-none z-30',\n floatingClass,\n )}\n >\n <ul\n className={classNames(\n 'dropdown-menu min-w-[160px]',\n menuClass,\n )}\n style={styles}\n >\n {children}\n </ul>\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </FloatingList>\n </MenuContext.Provider>\n </FloatingNode>\n )\n}\n\nexport default DropdownMenu\n"],"names":["DropdownSubItem"],"mappings":"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"}
@@ -10,7 +10,7 @@ import "./auth/index.js";
10
10
  import "./assets/index.js";
11
11
  import "./locales/index.js";
12
12
  import { ADMIN, USER } from "./constants/roles.constant.js";
13
- import { AI_API_URL, apiGetChatHistory, apiGetImages, apiPostImages, resumeChat, streamChat } from "./services/AiService.js";
13
+ import { AI_API_URL, apiDeleteConversation, apiGetChatHistory, apiGetConversations, apiGetImages, apiPostImages, apiRenameConversation, resumeChat, streamChat } from "./services/AiService.js";
14
14
  import { APP_NAME, REDIRECT_URL_KEY } from "./constants/app.constant.js";
15
15
  import { AUTH_PREFIX_PATH, CONCEPTS_PREFIX_PATH, DASHBOARDS_PREFIX_PATH, GUIDE_PREFIX_PATH, PAGES_PREFIX_PATH, ROOT, UI_COMPONENTS_PREFIX_PATH } from "./constants/route.constant.js";
16
16
  import { default as default2 } from "./components/shared/AbbreviateNumber.js";
@@ -374,6 +374,7 @@ export {
374
374
  default102 as UsersAvatarGroup,
375
375
  default103 as Views,
376
376
  default104 as acronym,
377
+ apiDeleteConversation,
377
378
  apiForgotPassword,
378
379
  apiGetAnalyticDashboard,
379
380
  apiGetArticleList,
@@ -383,6 +384,7 @@ export {
383
384
  apiGetContactDetails,
384
385
  apiGetContacts,
385
386
  apiGetConversation,
387
+ apiGetConversations,
386
388
  apiGetCustomer,
387
389
  apiGetCustomerLog,
388
390
  apiGetCustomersList,
@@ -421,6 +423,7 @@ export {
421
423
  apiGoogleOauthSignIn,
422
424
  apiPostImages,
423
425
  apiPostProject,
426
+ apiRenameConversation,
424
427
  apiResetPassword,
425
428
  apiSignIn,
426
429
  apiSignOut,
@@ -23,6 +23,25 @@ async function apiGetChatHistory(conversationId) {
23
23
  params: conversationId ? { conversation_id: conversationId } : void 0
24
24
  });
25
25
  }
26
+ async function apiGetConversations() {
27
+ return aiRequest({
28
+ url: "/ai/chat/conversations",
29
+ method: "get"
30
+ });
31
+ }
32
+ async function apiRenameConversation(conversationId, title) {
33
+ return aiRequest({
34
+ url: `/ai/chat/conversations/${encodeURIComponent(conversationId)}`,
35
+ method: "patch",
36
+ data: { title }
37
+ });
38
+ }
39
+ async function apiDeleteConversation(conversationId) {
40
+ return aiRequest({
41
+ url: `/ai/chat/conversations/${encodeURIComponent(conversationId)}`,
42
+ method: "delete"
43
+ });
44
+ }
26
45
  async function streamChat({
27
46
  prompt,
28
47
  conversationId,
@@ -87,9 +106,12 @@ async function apiPostImages(data) {
87
106
  }
88
107
  export {
89
108
  AI_API_URL,
109
+ apiDeleteConversation,
90
110
  apiGetChatHistory,
111
+ apiGetConversations,
91
112
  apiGetImages,
92
113
  apiPostImages,
114
+ apiRenameConversation,
93
115
  resumeChat,
94
116
  streamChat
95
117
  };
@@ -1 +1 @@
1
- {"version":3,"file":"AiService.js","sources":["../../../lib/@ecme/services/AiService.ts"],"sourcesContent":["import { authHeaders } from './aiAuthHeaders'\nimport ApiService from './ApiService'\nimport { readSse } from './sseParser'\nimport type { ChatEvent } from '@/views/concepts/ai/Chat/types'\nimport type { AxiosRequestConfig } from 'axios'\n\nconst AI_DEV_URL = 'http://localhost:8000'\nconst AI_BUILD_URL = 'https://orbe-ai.apps.qas.orbeagro.com.br'\n\n/**\n * Host da API de IA.\n *\n * O /ai/* nao vive no gateway do resto da aplicacao, entao nao pode usar o\n * baseURL do AxiosBase (API_URL). A resolucao e por origin em runtime, e nao\n * por import.meta.env.MODE, porque o MODE e congelado na build da lib como\n * \"production\" e nao reflete o dev do MFE consumidor.\n */\nfunction getAiApiUrl() {\n const origin = globalThis?.location?.origin ?? ''\n\n if (origin.includes('localhost') || origin.includes('127.0.0.1')) {\n return AI_DEV_URL\n }\n\n // QAS e PRD compartilham a mesma URL por enquanto. Quando houver uma URL\n // de PRD, o split entra aqui: if (origin.includes('.prd.')) return AI_PRD_URL\n return AI_BUILD_URL\n}\n\nexport const AI_API_URL = getAiApiUrl()\n\n/**\n * Toda chamada de IA sai pelo AI_API_URL (o baseURL por requisicao vence o da\n * instancia do AxiosBase) e fica fora do loading global — o chat mostra o\n * proprio balaozinho de \"digitando\".\n */\nconst aiRequest = <T>(config: AxiosRequestConfig) =>\n ApiService.fetchDataWithAxios<T>({\n ...config,\n baseURL: AI_API_URL,\n skipGlobalLoading: true,\n })\n\nexport async function apiGetChatHistory<T>(conversationId?: string) {\n return aiRequest<T>({\n url: '/ai/chat/history',\n method: 'get',\n params: conversationId ? { conversation_id: conversationId } : undefined,\n })\n}\n\nexport type StreamChatParams = {\n prompt: string\n /** Identifica a conversa; o backend usa como thread da memoria. */\n conversationId?: string\n signal?: AbortSignal\n onEvent: (evento: ChatEvent) => void\n}\n\n/**\n * Resposta a pausa atual do agente. Ha duas, e um endpoint so:\n * - `approved` responde ao `approval_required` (true aprova, false nega).\n * - `dados` responde ao `input_required`; `null` = o usuario fechou o\n * formulario sem preencher.\n */\nexport type ResumeChatParams = {\n approved?: boolean\n dados?: Record<string, unknown> | null\n conversationId?: string\n signal?: AbortSignal\n onEvent: (evento: ChatEvent) => void\n}\n\n/**\n * Envia a mensagem e consome a resposta em streaming (SSE).\n *\n * Usa `fetch`, e nao o Axios, porque o Axios no browser so resolve a Promise\n * com a resposta inteira — nao ha como ler o corpo enquanto ele chega.\n */\nexport async function streamChat({\n prompt,\n conversationId,\n signal,\n onEvent,\n}: StreamChatParams): Promise<void> {\n await postarEConsumir(\n '/ai/chat/stream',\n { prompt, conversation_id: conversationId },\n onEvent,\n signal,\n )\n}\n\n/**\n * Retoma uma conversa parada numa pausa (aprovacao ou coleta de dados).\n *\n * Devolve o mesmo tipo de stream do `streamChat`, e a resposta continua na\n * MESMA mensagem do chat — o backend so volta do ponto onde parou.\n *\n * O `JSON.stringify` descarta chaves `undefined`, entao o backend recebe apenas\n * o campo da pausa que esta sendo respondida.\n */\nexport async function resumeChat({\n approved,\n dados,\n conversationId,\n signal,\n onEvent,\n}: ResumeChatParams): Promise<void> {\n await postarEConsumir(\n '/ai/chat/resume',\n { approved, dados, conversation_id: conversationId },\n onEvent,\n signal,\n )\n}\n\n/** POST + leitura do SSE, comum ao envio e a retomada. */\nasync function postarEConsumir(\n caminho: string,\n corpo: Record<string, unknown>,\n onEvent: (evento: ChatEvent) => void,\n signal?: AbortSignal,\n): Promise<void> {\n const resposta = await fetch(`${AI_API_URL}${caminho}`, {\n method: 'POST',\n headers: {\n ...authHeaders(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(corpo),\n signal,\n })\n\n if (!resposta.ok || !resposta.body) {\n throw new Error(`Falha ao falar com a IA (HTTP ${resposta.status})`)\n }\n\n await readSse(resposta.body, ({ event, data }) => {\n try {\n onEvent({ type: event, data: JSON.parse(data) } as ChatEvent)\n } catch (error) {\n // Evento malformado nao pode derrubar o stream inteiro.\n console.debug('Evento SSE ignorado:', event, error)\n }\n })\n}\n\nexport async function apiGetImages<T, U extends Record<string, unknown>>(\n params: U,\n) {\n return aiRequest<T>({\n url: '/ai/images',\n method: 'get',\n params,\n })\n}\n\nexport async function apiPostImages<T, U extends Record<string, unknown>>(\n data: U,\n) {\n return aiRequest<T>({\n url: '/ai/images',\n method: 'post',\n data,\n })\n}\n"],"names":[],"mappings":";;;AAMA,MAAM,aAAa;AACnB,MAAM,eAAe;AAUrB,SAAS,cAAc;AACnB,QAAM,SAAS,YAAY,UAAU,UAAU;AAE/C,MAAI,OAAO,SAAS,WAAW,KAAK,OAAO,SAAS,WAAW,GAAG;AAC9D,WAAO;AAAA,EACX;AAIA,SAAO;AACX;AAEO,MAAM,aAAa,YAAA;AAO1B,MAAM,YAAY,CAAI,WAClB,WAAW,mBAAsB;AAAA,EAC7B,GAAG;AAAA,EACH,SAAS;AAAA,EACT,mBAAmB;AACvB,CAAC;AAEL,eAAsB,kBAAqB,gBAAyB;AAChE,SAAO,UAAa;AAAA,IAChB,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ,iBAAiB,EAAE,iBAAiB,mBAAmB;AAAA,EAAA,CAClE;AACL;AA8BA,eAAsB,WAAW;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAAoC;AAChC,QAAM;AAAA,IACF;AAAA,IACA,EAAE,QAAQ,iBAAiB,eAAA;AAAA,IAC3B;AAAA,IACA;AAAA,EAAA;AAER;AAWA,eAAsB,WAAW;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAAoC;AAChC,QAAM;AAAA,IACF;AAAA,IACA,EAAE,UAAU,OAAO,iBAAiB,eAAA;AAAA,IACpC;AAAA,IACA;AAAA,EAAA;AAER;AAGA,eAAe,gBACX,SACA,OACA,SACA,QACa;AACb,QAAM,WAAW,MAAM,MAAM,GAAG,UAAU,GAAG,OAAO,IAAI;AAAA,IACpD,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,GAAG,YAAA;AAAA,MACH,gBAAgB;AAAA,IAAA;AAAA,IAEpB,MAAM,KAAK,UAAU,KAAK;AAAA,IAC1B;AAAA,EAAA,CACH;AAED,MAAI,CAAC,SAAS,MAAM,CAAC,SAAS,MAAM;AAChC,UAAM,IAAI,MAAM,iCAAiC,SAAS,MAAM,GAAG;AAAA,EACvE;AAEA,QAAM,QAAQ,SAAS,MAAM,CAAC,EAAE,OAAO,WAAW;AAC9C,QAAI;AACA,cAAQ,EAAE,MAAM,OAAO,MAAM,KAAK,MAAM,IAAI,GAAgB;AAAA,IAChE,SAAS,OAAO;AAEZ,cAAQ,MAAM,wBAAwB,OAAO,KAAK;AAAA,IACtD;AAAA,EACJ,CAAC;AACL;AAEA,eAAsB,aAClB,QACF;AACE,SAAO,UAAa;AAAA,IAChB,KAAK;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,EAAA,CACH;AACL;AAEA,eAAsB,cAClB,MACF;AACE,SAAO,UAAa;AAAA,IAChB,KAAK;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,EAAA,CACH;AACL;"}
1
+ {"version":3,"file":"AiService.js","sources":["../../../lib/@ecme/services/AiService.ts"],"sourcesContent":["import { authHeaders } from './aiAuthHeaders'\nimport ApiService from './ApiService'\nimport { readSse } from './sseParser'\nimport type { ChatEvent } from '@/views/concepts/ai/Chat/types'\nimport type { AxiosRequestConfig } from 'axios'\n\nconst AI_DEV_URL = 'http://localhost:8000'\nconst AI_BUILD_URL = 'https://orbe-ai.apps.qas.orbeagro.com.br'\n\n/**\n * Host da API de IA.\n *\n * O /ai/* nao vive no gateway do resto da aplicacao, entao nao pode usar o\n * baseURL do AxiosBase (API_URL). A resolucao e por origin em runtime, e nao\n * por import.meta.env.MODE, porque o MODE e congelado na build da lib como\n * \"production\" e nao reflete o dev do MFE consumidor.\n */\nfunction getAiApiUrl() {\n const origin = globalThis?.location?.origin ?? ''\n\n if (origin.includes('localhost') || origin.includes('127.0.0.1')) {\n return AI_DEV_URL\n }\n\n // QAS e PRD compartilham a mesma URL por enquanto. Quando houver uma URL\n // de PRD, o split entra aqui: if (origin.includes('.prd.')) return AI_PRD_URL\n return AI_BUILD_URL\n}\n\nexport const AI_API_URL = getAiApiUrl()\n\n/**\n * Toda chamada de IA sai pelo AI_API_URL (o baseURL por requisicao vence o da\n * instancia do AxiosBase) e fica fora do loading global — o chat mostra o\n * proprio balaozinho de \"digitando\".\n */\nconst aiRequest = <T>(config: AxiosRequestConfig) =>\n ApiService.fetchDataWithAxios<T>({\n ...config,\n baseURL: AI_API_URL,\n skipGlobalLoading: true,\n })\n\nexport async function apiGetChatHistory<T>(conversationId?: string) {\n return aiRequest<T>({\n url: '/ai/chat/history',\n method: 'get',\n params: conversationId ? { conversation_id: conversationId } : undefined,\n })\n}\n\n/** Conversas do usuário (só o resumo), a mais recente primeiro. */\nexport async function apiGetConversations<T>() {\n return aiRequest<T>({\n url: '/ai/chat/conversations',\n method: 'get',\n })\n}\n\nexport async function apiRenameConversation(conversationId: string, title: string) {\n return aiRequest<void>({\n url: `/ai/chat/conversations/${encodeURIComponent(conversationId)}`,\n method: 'patch',\n data: { title },\n })\n}\n\n/** Apaga a conversa e toda a memória dela no backend. */\nexport async function apiDeleteConversation(conversationId: string) {\n return aiRequest<void>({\n url: `/ai/chat/conversations/${encodeURIComponent(conversationId)}`,\n method: 'delete',\n })\n}\n\nexport type StreamChatParams = {\n prompt: string\n /** Identifica a conversa; o backend usa como thread da memoria. */\n conversationId?: string\n signal?: AbortSignal\n onEvent: (evento: ChatEvent) => void\n}\n\n/**\n * Resposta a pausa atual do agente. Ha duas, e um endpoint so:\n * - `approved` responde ao `approval_required` (true aprova, false nega).\n * - `dados` responde ao `input_required`; `null` = o usuario fechou o\n * formulario sem preencher.\n */\nexport type ResumeChatParams = {\n approved?: boolean\n dados?: Record<string, unknown> | null\n conversationId?: string\n signal?: AbortSignal\n onEvent: (evento: ChatEvent) => void\n}\n\n/**\n * Envia a mensagem e consome a resposta em streaming (SSE).\n *\n * Usa `fetch`, e nao o Axios, porque o Axios no browser so resolve a Promise\n * com a resposta inteira — nao ha como ler o corpo enquanto ele chega.\n */\nexport async function streamChat({\n prompt,\n conversationId,\n signal,\n onEvent,\n}: StreamChatParams): Promise<void> {\n await postarEConsumir(\n '/ai/chat/stream',\n { prompt, conversation_id: conversationId },\n onEvent,\n signal,\n )\n}\n\n/**\n * Retoma uma conversa parada numa pausa (aprovacao ou coleta de dados).\n *\n * Devolve o mesmo tipo de stream do `streamChat`, e a resposta continua na\n * MESMA mensagem do chat — o backend so volta do ponto onde parou.\n *\n * O `JSON.stringify` descarta chaves `undefined`, entao o backend recebe apenas\n * o campo da pausa que esta sendo respondida.\n */\nexport async function resumeChat({\n approved,\n dados,\n conversationId,\n signal,\n onEvent,\n}: ResumeChatParams): Promise<void> {\n await postarEConsumir(\n '/ai/chat/resume',\n { approved, dados, conversation_id: conversationId },\n onEvent,\n signal,\n )\n}\n\n/** POST + leitura do SSE, comum ao envio e a retomada. */\nasync function postarEConsumir(\n caminho: string,\n corpo: Record<string, unknown>,\n onEvent: (evento: ChatEvent) => void,\n signal?: AbortSignal,\n): Promise<void> {\n const resposta = await fetch(`${AI_API_URL}${caminho}`, {\n method: 'POST',\n headers: {\n ...authHeaders(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(corpo),\n signal,\n })\n\n if (!resposta.ok || !resposta.body) {\n throw new Error(`Falha ao falar com a IA (HTTP ${resposta.status})`)\n }\n\n await readSse(resposta.body, ({ event, data }) => {\n try {\n onEvent({ type: event, data: JSON.parse(data) } as ChatEvent)\n } catch (error) {\n // Evento malformado nao pode derrubar o stream inteiro.\n console.debug('Evento SSE ignorado:', event, error)\n }\n })\n}\n\nexport async function apiGetImages<T, U extends Record<string, unknown>>(\n params: U,\n) {\n return aiRequest<T>({\n url: '/ai/images',\n method: 'get',\n params,\n })\n}\n\nexport async function apiPostImages<T, U extends Record<string, unknown>>(\n data: U,\n) {\n return aiRequest<T>({\n url: '/ai/images',\n method: 'post',\n data,\n })\n}\n"],"names":[],"mappings":";;;AAMA,MAAM,aAAa;AACnB,MAAM,eAAe;AAUrB,SAAS,cAAc;AACnB,QAAM,SAAS,YAAY,UAAU,UAAU;AAE/C,MAAI,OAAO,SAAS,WAAW,KAAK,OAAO,SAAS,WAAW,GAAG;AAC9D,WAAO;AAAA,EACX;AAIA,SAAO;AACX;AAEO,MAAM,aAAa,YAAA;AAO1B,MAAM,YAAY,CAAI,WAClB,WAAW,mBAAsB;AAAA,EAC7B,GAAG;AAAA,EACH,SAAS;AAAA,EACT,mBAAmB;AACvB,CAAC;AAEL,eAAsB,kBAAqB,gBAAyB;AAChE,SAAO,UAAa;AAAA,IAChB,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ,iBAAiB,EAAE,iBAAiB,mBAAmB;AAAA,EAAA,CAClE;AACL;AAGA,eAAsB,sBAAyB;AAC3C,SAAO,UAAa;AAAA,IAChB,KAAK;AAAA,IACL,QAAQ;AAAA,EAAA,CACX;AACL;AAEA,eAAsB,sBAAsB,gBAAwB,OAAe;AAC/E,SAAO,UAAgB;AAAA,IACnB,KAAK,0BAA0B,mBAAmB,cAAc,CAAC;AAAA,IACjE,QAAQ;AAAA,IACR,MAAM,EAAE,MAAA;AAAA,EAAM,CACjB;AACL;AAGA,eAAsB,sBAAsB,gBAAwB;AAChE,SAAO,UAAgB;AAAA,IACnB,KAAK,0BAA0B,mBAAmB,cAAc,CAAC;AAAA,IACjE,QAAQ;AAAA,EAAA,CACX;AACL;AA8BA,eAAsB,WAAW;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAAoC;AAChC,QAAM;AAAA,IACF;AAAA,IACA,EAAE,QAAQ,iBAAiB,eAAA;AAAA,IAC3B;AAAA,IACA;AAAA,EAAA;AAER;AAWA,eAAsB,WAAW;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAAoC;AAChC,QAAM;AAAA,IACF;AAAA,IACA,EAAE,UAAU,OAAO,iBAAiB,eAAA;AAAA,IACpC;AAAA,IACA;AAAA,EAAA;AAER;AAGA,eAAe,gBACX,SACA,OACA,SACA,QACa;AACb,QAAM,WAAW,MAAM,MAAM,GAAG,UAAU,GAAG,OAAO,IAAI;AAAA,IACpD,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,GAAG,YAAA;AAAA,MACH,gBAAgB;AAAA,IAAA;AAAA,IAEpB,MAAM,KAAK,UAAU,KAAK;AAAA,IAC1B;AAAA,EAAA,CACH;AAED,MAAI,CAAC,SAAS,MAAM,CAAC,SAAS,MAAM;AAChC,UAAM,IAAI,MAAM,iCAAiC,SAAS,MAAM,GAAG;AAAA,EACvE;AAEA,QAAM,QAAQ,SAAS,MAAM,CAAC,EAAE,OAAO,WAAW;AAC9C,QAAI;AACA,cAAQ,EAAE,MAAM,OAAO,MAAM,KAAK,MAAM,IAAI,GAAgB;AAAA,IAChE,SAAS,OAAO;AAEZ,cAAQ,MAAM,wBAAwB,OAAO,KAAK;AAAA,IACtD;AAAA,EACJ,CAAC;AACL;AAEA,eAAsB,aAClB,QACF;AACE,SAAO,UAAa;AAAA,IAChB,KAAK;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,EAAA,CACH;AACL;AAEA,eAAsB,cAClB,MACF;AACE,SAAO,UAAa;AAAA,IAChB,KAAK;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,EAAA,CACH;AACL;"}
@@ -1,6 +1,6 @@
1
1
  import { default as default2 } from "./ApiService.js";
2
2
  import { apiGetPricingPlans, apiGetRolesPermissionsRoles, apiGetRolesPermissionsUsers, apiGetSettingsBilling, apiGetSettingsIntergration, apiGetSettingsNotification, apiGetSettingsProfile } from "./AccontsService.js";
3
- import { AI_API_URL, apiGetChatHistory, apiGetImages, apiPostImages, resumeChat, streamChat } from "./AiService.js";
3
+ import { AI_API_URL, apiDeleteConversation, apiGetChatHistory, apiGetConversations, apiGetImages, apiPostImages, apiRenameConversation, resumeChat, streamChat } from "./AiService.js";
4
4
  import { apiForgotPassword, apiResetPassword, apiSignIn, apiSignOut, apiSignUp } from "./AuthService.js";
5
5
  import { apiGetCalendar } from "./CalendarService.js";
6
6
  import { apiGetChats, apiGetContactDetails, apiGetContacts, apiGetConversation } from "./ChatService.js";
@@ -18,6 +18,7 @@ import { apiGetProject, apiGetProjectMembers, apiGetProjectTask, apiGetProjectTa
18
18
  export {
19
19
  AI_API_URL,
20
20
  default2 as ApiService,
21
+ apiDeleteConversation,
21
22
  apiForgotPassword,
22
23
  apiGetAnalyticDashboard,
23
24
  apiGetArticleList,
@@ -27,6 +28,7 @@ export {
27
28
  apiGetContactDetails,
28
29
  apiGetContacts,
29
30
  apiGetConversation,
31
+ apiGetConversations,
30
32
  apiGetCustomer,
31
33
  apiGetCustomerLog,
32
34
  apiGetCustomersList,
@@ -65,6 +67,7 @@ export {
65
67
  apiGoogleOauthSignIn,
66
68
  apiPostImages,
67
69
  apiPostProject,
70
+ apiRenameConversation,
68
71
  apiResetPassword,
69
72
  apiSignIn,
70
73
  apiSignOut,
@@ -3,36 +3,22 @@ import { Fragment } from "react";
3
3
  import "../../../../../components/ui/ScrollBar/index.js";
4
4
  import ChatHistoryItem from "./ChatHistoryItem.js";
5
5
  import { usGenerativeChatStore } from "../store/generativeChatStore.js";
6
- import { apiGetChatHistory } from "../../../../../services/AiService.js";
7
- import useSWR from "swr";
6
+ import useChatConversations from "../hooks/useChatConversations.js";
8
7
  import ScrollBar from "../../../../../components/ui/ScrollBar/ScrollBar.js";
9
- const ChatHistory = ({ queryText = "", onClick }) => {
8
+ const ChatHistory = ({
9
+ queryText = "",
10
+ onClick,
11
+ dropdownFloatingClass
12
+ }) => {
10
13
  const {
11
14
  chatHistory,
12
- setChatHistory,
13
15
  setRenameDialog,
14
16
  setSelectedConversation,
15
17
  selectedConversation
16
18
  } = usGenerativeChatStore();
17
- useSWR(
18
- ["/api/ai/chat/history"],
19
- () => apiGetChatHistory(),
20
- {
21
- revalidateOnFocus: false,
22
- revalidateIfStale: false,
23
- revalidateOnReconnect: false,
24
- onSuccess: (data) => {
25
- setChatHistory(data);
26
- }
27
- }
28
- );
19
+ const { remover } = useChatConversations();
29
20
  const handleDelete = (id) => {
30
- setChatHistory(chatHistory.filter((item) => item.id !== id));
31
- setSelectedConversation("");
32
- };
33
- const handleArchive = (id) => {
34
- setChatHistory(chatHistory.filter((item) => item.id !== id));
35
- setSelectedConversation("");
21
+ remover(id);
36
22
  };
37
23
  const handleRename = (id, title) => {
38
24
  setRenameDialog({
@@ -58,8 +44,8 @@ const ChatHistory = ({ queryText = "", onClick }) => {
58
44
  title: item.title,
59
45
  conversation: item.lastConversation,
60
46
  active: selectedConversation === item.id,
47
+ dropdownFloatingClass,
61
48
  onDelete: () => handleDelete(item.id),
62
- onArchive: () => handleArchive(item.id),
63
49
  onRename: () => handleRename(item.id, item.title),
64
50
  onClick: () => handleClick(item.id)
65
51
  },
@@ -1 +1 @@
1
- {"version":3,"file":"ChatHistory.js","sources":["../../../../../../../lib/@ecme/views/concepts/ai/Chat/components/ChatHistory.tsx"],"sourcesContent":["import { Fragment } from 'react'\nimport ScrollBar from '@/components/ui/ScrollBar'\nimport ChatHistoryItem from './ChatHistoryItem'\nimport { usGenerativeChatStore } from '../store/generativeChatStore'\nimport { apiGetChatHistory } from '@/services/AiService'\n\nimport useSWR from 'swr'\nimport type { GetChatHistoryResponse } from '../types'\n\ntype ChatHistoryProps = {\n queryText?: string\n onClick?: () => void\n}\n\nconst ChatHistory = ({ queryText = '', onClick }: ChatHistoryProps) => {\n const {\n chatHistory,\n setChatHistory,\n setRenameDialog,\n setSelectedConversation,\n selectedConversation,\n } = usGenerativeChatStore()\n\n useSWR(\n ['/api/ai/chat/history'],\n () => apiGetChatHistory<GetChatHistoryResponse>(),\n {\n revalidateOnFocus: false,\n revalidateIfStale: false,\n revalidateOnReconnect: false,\n onSuccess: (data) => {\n setChatHistory(data)\n },\n },\n )\n\n const handleDelete = (id: string) => {\n setChatHistory(chatHistory.filter((item) => item.id !== id))\n setSelectedConversation('')\n }\n\n const handleArchive = (id: string) => {\n setChatHistory(chatHistory.filter((item) => item.id !== id))\n setSelectedConversation('')\n }\n\n const handleRename = (id: string, title: string) => {\n setRenameDialog({\n id,\n title,\n open: true,\n })\n }\n\n const handleClick = (id: string) => {\n setSelectedConversation(id)\n onClick?.()\n }\n\n return (\n <ScrollBar className=\"h-full\">\n <div className=\"flex flex-col gap-2 py-2 px-3\">\n {chatHistory\n .filter((item) =>\n item.title\n .toLowerCase()\n .includes(queryText.toLowerCase()),\n )\n .map((item) => {\n if (!item.enable) {\n return <Fragment key={item.id} />\n }\n return (\n <ChatHistoryItem\n key={item.id}\n data-testid={item.id}\n title={item.title}\n conversation={item.lastConversation}\n active={selectedConversation === item.id}\n onDelete={() => handleDelete(item.id)}\n onArchive={() => handleArchive(item.id)}\n onRename={() =>\n handleRename(item.id, item.title)\n }\n onClick={() => handleClick(item.id)}\n />\n )\n })}\n </div>\n </ScrollBar>\n )\n}\n\nexport default ChatHistory\n"],"names":[],"mappings":";;;;;;;;AAcA,MAAM,cAAc,CAAC,EAAE,YAAY,IAAI,cAAgC;AACnE,QAAM;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACA,sBAAA;AAEJ;AAAA,IACI,CAAC,sBAAsB;AAAA,IACvB,MAAM,kBAAA;AAAA,IACN;AAAA,MACI,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,MACnB,uBAAuB;AAAA,MACvB,WAAW,CAAC,SAAS;AACjB,uBAAe,IAAI;AAAA,MACvB;AAAA,IAAA;AAAA,EACJ;AAGJ,QAAM,eAAe,CAAC,OAAe;AACjC,mBAAe,YAAY,OAAO,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;AAC3D,4BAAwB,EAAE;AAAA,EAC9B;AAEA,QAAM,gBAAgB,CAAC,OAAe;AAClC,mBAAe,YAAY,OAAO,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;AAC3D,4BAAwB,EAAE;AAAA,EAC9B;AAEA,QAAM,eAAe,CAAC,IAAY,UAAkB;AAChD,oBAAgB;AAAA,MACZ;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IAAA,CACT;AAAA,EACL;AAEA,QAAM,cAAc,CAAC,OAAe;AAChC,4BAAwB,EAAE;AAC1B,cAAA;AAAA,EACJ;AAEA,SACI,oBAAC,aAAU,WAAU,UACjB,8BAAC,OAAA,EAAI,WAAU,iCACV,UAAA,YACI;AAAA,IAAO,CAAC,SACL,KAAK,MACA,cACA,SAAS,UAAU,YAAA,CAAa;AAAA,EAAA,EAExC,IAAI,CAAC,SAAS;AACX,QAAI,CAAC,KAAK,QAAQ;AACd,aAAO,oBAAC,UAAA,IAAc,KAAK,EAAI;AAAA,IACnC;AACA,WACI;AAAA,MAAC;AAAA,MAAA;AAAA,QAEG,eAAa,KAAK;AAAA,QAClB,OAAO,KAAK;AAAA,QACZ,cAAc,KAAK;AAAA,QACnB,QAAQ,yBAAyB,KAAK;AAAA,QACtC,UAAU,MAAM,aAAa,KAAK,EAAE;AAAA,QACpC,WAAW,MAAM,cAAc,KAAK,EAAE;AAAA,QACtC,UAAU,MACN,aAAa,KAAK,IAAI,KAAK,KAAK;AAAA,QAEpC,SAAS,MAAM,YAAY,KAAK,EAAE;AAAA,MAAA;AAAA,MAV7B,KAAK;AAAA,IAAA;AAAA,EAatB,CAAC,GACT,GACJ;AAER;"}
1
+ {"version":3,"file":"ChatHistory.js","sources":["../../../../../../../lib/@ecme/views/concepts/ai/Chat/components/ChatHistory.tsx"],"sourcesContent":["import { Fragment } from 'react'\nimport ScrollBar from '@/components/ui/ScrollBar'\nimport ChatHistoryItem from './ChatHistoryItem'\nimport { usGenerativeChatStore } from '../store/generativeChatStore'\nimport useChatConversations from '../hooks/useChatConversations'\n\ntype ChatHistoryProps = {\n queryText?: string\n onClick?: () => void\n /** Repassado ao menu de cada item (ex.: subir o z-index dentro do widget). */\n dropdownFloatingClass?: string\n}\n\nconst ChatHistory = ({\n queryText = '',\n onClick,\n dropdownFloatingClass,\n}: ChatHistoryProps) => {\n const {\n chatHistory,\n setRenameDialog,\n setSelectedConversation,\n selectedConversation,\n } = usGenerativeChatStore()\n const { remover } = useChatConversations()\n\n const handleDelete = (id: string) => {\n remover(id)\n }\n\n const handleRename = (id: string, title: string) => {\n setRenameDialog({\n id,\n title,\n open: true,\n })\n }\n\n const handleClick = (id: string) => {\n setSelectedConversation(id)\n onClick?.()\n }\n\n return (\n <ScrollBar className=\"h-full\">\n <div className=\"flex flex-col gap-2 py-2 px-3\">\n {chatHistory\n .filter((item) =>\n item.title\n .toLowerCase()\n .includes(queryText.toLowerCase()),\n )\n .map((item) => {\n if (!item.enable) {\n return <Fragment key={item.id} />\n }\n return (\n <ChatHistoryItem\n key={item.id}\n data-testid={item.id}\n title={item.title}\n conversation={item.lastConversation}\n active={selectedConversation === item.id}\n dropdownFloatingClass={dropdownFloatingClass}\n onDelete={() => handleDelete(item.id)}\n onRename={() =>\n handleRename(item.id, item.title)\n }\n onClick={() => handleClick(item.id)}\n />\n )\n })}\n </div>\n </ScrollBar>\n )\n}\n\nexport default ChatHistory\n"],"names":[],"mappings":";;;;;;;AAaA,MAAM,cAAc,CAAC;AAAA,EACjB,YAAY;AAAA,EACZ;AAAA,EACA;AACJ,MAAwB;AACpB,QAAM;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACA,sBAAA;AACJ,QAAM,EAAE,QAAA,IAAY,qBAAA;AAEpB,QAAM,eAAe,CAAC,OAAe;AACjC,YAAQ,EAAE;AAAA,EACd;AAEA,QAAM,eAAe,CAAC,IAAY,UAAkB;AAChD,oBAAgB;AAAA,MACZ;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IAAA,CACT;AAAA,EACL;AAEA,QAAM,cAAc,CAAC,OAAe;AAChC,4BAAwB,EAAE;AAC1B,cAAA;AAAA,EACJ;AAEA,SACI,oBAAC,aAAU,WAAU,UACjB,8BAAC,OAAA,EAAI,WAAU,iCACV,UAAA,YACI;AAAA,IAAO,CAAC,SACL,KAAK,MACA,cACA,SAAS,UAAU,YAAA,CAAa;AAAA,EAAA,EAExC,IAAI,CAAC,SAAS;AACX,QAAI,CAAC,KAAK,QAAQ;AACd,aAAO,oBAAC,UAAA,IAAc,KAAK,EAAI;AAAA,IACnC;AACA,WACI;AAAA,MAAC;AAAA,MAAA;AAAA,QAEG,eAAa,KAAK;AAAA,QAClB,OAAO,KAAK;AAAA,QACZ,cAAc,KAAK;AAAA,QACnB,QAAQ,yBAAyB,KAAK;AAAA,QACtC;AAAA,QACA,UAAU,MAAM,aAAa,KAAK,EAAE;AAAA,QACpC,UAAU,MACN,aAAa,KAAK,IAAI,KAAK,KAAK;AAAA,QAEpC,SAAS,MAAM,YAAY,KAAK,EAAE;AAAA,MAAA;AAAA,MAV7B,KAAK;AAAA,IAAA;AAAA,EAatB,CAAC,GACT,GACJ;AAER;"}
@@ -2,7 +2,7 @@ import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { useState, useRef } from "react";
3
3
  import { Dropdown } from "../../../../../components/ui/Dropdown/index.js";
4
4
  import classNames from "classnames";
5
- import { TbPencil, TbArchive, TbTrash, TbDots } from "react-icons/tb";
5
+ import { TbPencil, TbTrash, TbDots } from "react-icons/tb";
6
6
  const ChatHistoryItem = (props) => {
7
7
  const [dropdownOpen, setDropdownOpen] = useState(false);
8
8
  const dropdownRef = useRef(null);
@@ -11,9 +11,9 @@ const ChatHistoryItem = (props) => {
11
11
  conversation,
12
12
  active,
13
13
  onRename,
14
- onArchive,
15
14
  onDelete,
16
15
  onClick,
16
+ dropdownFloatingClass,
17
17
  ...rest
18
18
  } = props;
19
19
  const handleCallback = (e, callback) => {
@@ -50,6 +50,7 @@ const ChatHistoryItem = (props) => {
50
50
  {
51
51
  ref: dropdownRef,
52
52
  placement: "bottom-end",
53
+ floatingClass: dropdownFloatingClass,
53
54
  renderTitle: /* @__PURE__ */ jsx(
54
55
  "div",
55
56
  {
@@ -75,18 +76,7 @@ const ChatHistoryItem = (props) => {
75
76
  onClick: (e) => handleCallback(e, onRename),
76
77
  children: [
77
78
  /* @__PURE__ */ jsx(TbPencil, { className: "text-xl" }),
78
- /* @__PURE__ */ jsx("span", { children: "Rename" })
79
- ]
80
- }
81
- ),
82
- /* @__PURE__ */ jsxs(
83
- Dropdown.Item,
84
- {
85
- eventKey: "rename",
86
- onClick: (e) => handleCallback(e, onArchive),
87
- children: [
88
- /* @__PURE__ */ jsx(TbArchive, { className: "text-xl" }),
89
- /* @__PURE__ */ jsx("span", { children: "Archive" })
79
+ /* @__PURE__ */ jsx("span", { children: "Renomear" })
90
80
  ]
91
81
  }
92
82
  ),
@@ -94,11 +84,11 @@ const ChatHistoryItem = (props) => {
94
84
  Dropdown.Item,
95
85
  {
96
86
  className: "text-error",
97
- eventKey: "rename",
87
+ eventKey: "delete",
98
88
  onClick: (e) => handleCallback(e, onDelete),
99
89
  children: [
100
90
  /* @__PURE__ */ jsx(TbTrash, { className: "text-xl text-error" }),
101
- /* @__PURE__ */ jsx("span", { className: "text-error", children: "Deleted" })
91
+ /* @__PURE__ */ jsx("span", { className: "text-error", children: "Excluir" })
102
92
  ]
103
93
  }
104
94
  )
@@ -1 +1 @@
1
- {"version":3,"file":"ChatHistoryItem.js","sources":["../../../../../../../lib/@ecme/views/concepts/ai/Chat/components/ChatHistoryItem.tsx"],"sourcesContent":["import { useState, useRef } from 'react'\nimport Dropdown from '@/components/ui/Dropdown'\nimport classNames from 'classnames'\nimport { TbDots, TbArchive, TbPencil, TbTrash } from 'react-icons/tb'\nimport type { DropdownRef } from '@/components/ui/Dropdown'\n\nimport type { MouseEvent, SyntheticEvent } from 'react'\n\ntype ChatHistoryItemProps = {\n title: string\n conversation: string\n active?: boolean\n onDelete?: () => void\n onArchive?: () => void\n onRename?: () => void\n onClick?: () => void\n}\n\nconst ChatHistoryItem = (props: ChatHistoryItemProps) => {\n const [dropdownOpen, setDropdownOpen] = useState(false)\n\n const dropdownRef = useRef<DropdownRef>(null)\n\n const {\n title,\n conversation,\n active,\n onRename,\n onArchive,\n onDelete,\n onClick,\n ...rest\n } = props\n\n const handleCallback = (\n e: SyntheticEvent<Element, Event>,\n callback?: () => void,\n ) => {\n e.stopPropagation()\n callback?.()\n }\n\n const handleDropdownToggleClick = (e: MouseEvent) => {\n e.stopPropagation()\n dropdownRef.current?.handleDropdownOpen()\n }\n\n return (\n <div\n className={classNames(\n 'rounded-xl p-3 px-5 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer group relative',\n (dropdownOpen || active) && 'bg-gray-100 dark:bg-gray-700',\n )}\n onClick={onClick}\n {...rest}\n >\n <div>\n <div className=\"heading-text font-bold truncate\">{title}</div>\n <div className=\"truncate\">{conversation}</div>\n </div>\n <div\n className={classNames(\n 'rounded-xl absolute bottom-0 top-0 to-transparent ltr:right-0 ltr:bg-gradient-to-l rtl:left-0 rtl:bg-gradient-to-r group-hover:from-gray-100 dark:group-hover:from-gray-700 w-8 from-0% group-hover:w-20 group-hover:from-60% flex items-center justify-end',\n dropdownOpen &&\n 'from-gray-100 dark:from-gray-700 w-20 from-60%',\n )}\n >\n <Dropdown\n ref={dropdownRef}\n placement=\"bottom-end\"\n renderTitle={\n <div\n className={classNames(\n 'p-2 opacity-0 group-hover:opacity-100',\n dropdownOpen && 'opacity-100',\n )}\n >\n <TbDots\n className=\"text-xl\"\n onClick={handleDropdownToggleClick}\n />\n </div>\n }\n onOpen={(bool) => setDropdownOpen(bool)}\n >\n <Dropdown.Item\n eventKey=\"rename\"\n onClick={(e) => handleCallback(e, onRename)}\n >\n <TbPencil className=\"text-xl\" />\n <span>Rename</span>\n </Dropdown.Item>\n <Dropdown.Item\n eventKey=\"rename\"\n onClick={(e) => handleCallback(e, onArchive)}\n >\n <TbArchive className=\"text-xl\" />\n <span>Archive</span>\n </Dropdown.Item>\n <Dropdown.Item\n className=\"text-error\"\n eventKey=\"rename\"\n onClick={(e) => handleCallback(e, onDelete)}\n >\n <TbTrash className=\"text-xl text-error\" />\n <span className=\"text-error\">Deleted</span>\n </Dropdown.Item>\n </Dropdown>\n </div>\n </div>\n )\n}\n\nexport default ChatHistoryItem\n"],"names":[],"mappings":";;;;;AAkBA,MAAM,kBAAkB,CAAC,UAAgC;AACrD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AAEtD,QAAM,cAAc,OAAoB,IAAI;AAE5C,QAAM;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,IACH;AAEJ,QAAM,iBAAiB,CACnB,GACA,aACC;AACD,MAAE,gBAAA;AACF,eAAA;AAAA,EACJ;AAEA,QAAM,4BAA4B,CAAC,MAAkB;AACjD,MAAE,gBAAA;AACF,gBAAY,SAAS,mBAAA;AAAA,EACzB;AAEA,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,WAAW;AAAA,QACP;AAAA,SACC,gBAAgB,WAAW;AAAA,MAAA;AAAA,MAEhC;AAAA,MACC,GAAG;AAAA,MAEJ,UAAA;AAAA,QAAA,qBAAC,OAAA,EACG,UAAA;AAAA,UAAA,oBAAC,OAAA,EAAI,WAAU,mCAAmC,UAAA,OAAM;AAAA,UACxD,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,aAAA,CAAa;AAAA,QAAA,GAC5C;AAAA,QACA;AAAA,UAAC;AAAA,UAAA;AAAA,YACG,WAAW;AAAA,cACP;AAAA,cACA,gBACI;AAAA,YAAA;AAAA,YAGR,UAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACG,KAAK;AAAA,gBACL,WAAU;AAAA,gBACV,aACI;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACG,WAAW;AAAA,sBACP;AAAA,sBACA,gBAAgB;AAAA,oBAAA;AAAA,oBAGpB,UAAA;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACG,WAAU;AAAA,wBACV,SAAS;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACb;AAAA,gBAAA;AAAA,gBAGR,QAAQ,CAAC,SAAS,gBAAgB,IAAI;AAAA,gBAEtC,UAAA;AAAA,kBAAA;AAAA,oBAAC,SAAS;AAAA,oBAAT;AAAA,sBACG,UAAS;AAAA,sBACT,SAAS,CAAC,MAAM,eAAe,GAAG,QAAQ;AAAA,sBAE1C,UAAA;AAAA,wBAAA,oBAAC,UAAA,EAAS,WAAU,UAAA,CAAU;AAAA,wBAC9B,oBAAC,UAAK,UAAA,SAAA,CAAM;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAEhB;AAAA,oBAAC,SAAS;AAAA,oBAAT;AAAA,sBACG,UAAS;AAAA,sBACT,SAAS,CAAC,MAAM,eAAe,GAAG,SAAS;AAAA,sBAE3C,UAAA;AAAA,wBAAA,oBAAC,WAAA,EAAU,WAAU,UAAA,CAAU;AAAA,wBAC/B,oBAAC,UAAK,UAAA,UAAA,CAAO;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAEjB;AAAA,oBAAC,SAAS;AAAA,oBAAT;AAAA,sBACG,WAAU;AAAA,sBACV,UAAS;AAAA,sBACT,SAAS,CAAC,MAAM,eAAe,GAAG,QAAQ;AAAA,sBAE1C,UAAA;AAAA,wBAAA,oBAAC,SAAA,EAAQ,WAAU,qBAAA,CAAqB;AAAA,wBACxC,oBAAC,QAAA,EAAK,WAAU,cAAa,UAAA,UAAA,CAAO;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACxC;AAAA,cAAA;AAAA,YAAA;AAAA,UACJ;AAAA,QAAA;AAAA,MACJ;AAAA,IAAA;AAAA,EAAA;AAGZ;"}
1
+ {"version":3,"file":"ChatHistoryItem.js","sources":["../../../../../../../lib/@ecme/views/concepts/ai/Chat/components/ChatHistoryItem.tsx"],"sourcesContent":["import { useState, useRef } from 'react'\nimport Dropdown from '@/components/ui/Dropdown'\nimport classNames from 'classnames'\nimport { TbDots, TbPencil, TbTrash } from 'react-icons/tb'\nimport type { DropdownRef } from '@/components/ui/Dropdown'\n\nimport type { MouseEvent, SyntheticEvent } from 'react'\n\ntype ChatHistoryItemProps = {\n title: string\n conversation: string\n active?: boolean\n onDelete?: () => void\n onRename?: () => void\n onClick?: () => void\n dropdownFloatingClass?: string\n}\n\nconst ChatHistoryItem = (props: ChatHistoryItemProps) => {\n const [dropdownOpen, setDropdownOpen] = useState(false)\n\n const dropdownRef = useRef<DropdownRef>(null)\n\n const {\n title,\n conversation,\n active,\n onRename,\n onDelete,\n onClick,\n dropdownFloatingClass,\n ...rest\n } = props\n\n const handleCallback = (\n e: SyntheticEvent<Element, Event>,\n callback?: () => void,\n ) => {\n e.stopPropagation()\n callback?.()\n }\n\n const handleDropdownToggleClick = (e: MouseEvent) => {\n e.stopPropagation()\n dropdownRef.current?.handleDropdownOpen()\n }\n\n return (\n <div\n className={classNames(\n 'rounded-xl p-3 px-5 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer group relative',\n (dropdownOpen || active) && 'bg-gray-100 dark:bg-gray-700',\n )}\n onClick={onClick}\n {...rest}\n >\n <div>\n <div className=\"heading-text font-bold truncate\">{title}</div>\n <div className=\"truncate\">{conversation}</div>\n </div>\n <div\n className={classNames(\n 'rounded-xl absolute bottom-0 top-0 to-transparent ltr:right-0 ltr:bg-gradient-to-l rtl:left-0 rtl:bg-gradient-to-r group-hover:from-gray-100 dark:group-hover:from-gray-700 w-8 from-0% group-hover:w-20 group-hover:from-60% flex items-center justify-end',\n dropdownOpen &&\n 'from-gray-100 dark:from-gray-700 w-20 from-60%',\n )}\n >\n <Dropdown\n ref={dropdownRef}\n placement=\"bottom-end\"\n floatingClass={dropdownFloatingClass}\n renderTitle={\n <div\n className={classNames(\n 'p-2 opacity-0 group-hover:opacity-100',\n dropdownOpen && 'opacity-100',\n )}\n >\n <TbDots\n className=\"text-xl\"\n onClick={handleDropdownToggleClick}\n />\n </div>\n }\n onOpen={(bool) => setDropdownOpen(bool)}\n >\n <Dropdown.Item\n eventKey=\"rename\"\n onClick={(e) => handleCallback(e, onRename)}\n >\n <TbPencil className=\"text-xl\" />\n <span>Renomear</span>\n </Dropdown.Item>\n <Dropdown.Item\n className=\"text-error\"\n eventKey=\"delete\"\n onClick={(e) => handleCallback(e, onDelete)}\n >\n <TbTrash className=\"text-xl text-error\" />\n <span className=\"text-error\">Excluir</span>\n </Dropdown.Item>\n </Dropdown>\n </div>\n </div>\n )\n}\n\nexport default ChatHistoryItem\n"],"names":[],"mappings":";;;;;AAkBA,MAAM,kBAAkB,CAAC,UAAgC;AACrD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AAEtD,QAAM,cAAc,OAAoB,IAAI;AAE5C,QAAM;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,IACH;AAEJ,QAAM,iBAAiB,CACnB,GACA,aACC;AACD,MAAE,gBAAA;AACF,eAAA;AAAA,EACJ;AAEA,QAAM,4BAA4B,CAAC,MAAkB;AACjD,MAAE,gBAAA;AACF,gBAAY,SAAS,mBAAA;AAAA,EACzB;AAEA,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,WAAW;AAAA,QACP;AAAA,SACC,gBAAgB,WAAW;AAAA,MAAA;AAAA,MAEhC;AAAA,MACC,GAAG;AAAA,MAEJ,UAAA;AAAA,QAAA,qBAAC,OAAA,EACG,UAAA;AAAA,UAAA,oBAAC,OAAA,EAAI,WAAU,mCAAmC,UAAA,OAAM;AAAA,UACxD,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,aAAA,CAAa;AAAA,QAAA,GAC5C;AAAA,QACA;AAAA,UAAC;AAAA,UAAA;AAAA,YACG,WAAW;AAAA,cACP;AAAA,cACA,gBACI;AAAA,YAAA;AAAA,YAGR,UAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACG,KAAK;AAAA,gBACL,WAAU;AAAA,gBACV,eAAe;AAAA,gBACf,aACI;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACG,WAAW;AAAA,sBACP;AAAA,sBACA,gBAAgB;AAAA,oBAAA;AAAA,oBAGpB,UAAA;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACG,WAAU;AAAA,wBACV,SAAS;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACb;AAAA,gBAAA;AAAA,gBAGR,QAAQ,CAAC,SAAS,gBAAgB,IAAI;AAAA,gBAEtC,UAAA;AAAA,kBAAA;AAAA,oBAAC,SAAS;AAAA,oBAAT;AAAA,sBACG,UAAS;AAAA,sBACT,SAAS,CAAC,MAAM,eAAe,GAAG,QAAQ;AAAA,sBAE1C,UAAA;AAAA,wBAAA,oBAAC,UAAA,EAAS,WAAU,UAAA,CAAU;AAAA,wBAC9B,oBAAC,UAAK,UAAA,WAAA,CAAQ;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAElB;AAAA,oBAAC,SAAS;AAAA,oBAAT;AAAA,sBACG,WAAU;AAAA,sBACV,UAAS;AAAA,sBACT,SAAS,CAAC,MAAM,eAAe,GAAG,QAAQ;AAAA,sBAE1C,UAAA;AAAA,wBAAA,oBAAC,SAAA,EAAQ,WAAU,qBAAA,CAAqB;AAAA,wBACxC,oBAAC,QAAA,EAAK,WAAU,cAAa,UAAA,UAAA,CAAO;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACxC;AAAA,cAAA;AAAA,YAAA;AAAA,UACJ;AAAA,QAAA;AAAA,MACJ;AAAA,IAAA;AAAA,EAAA;AAGZ;"}
@@ -5,6 +5,7 @@ import "../../../../../components/ui/Form/index.js";
5
5
  import "../../../../../components/ui/Input/index.js";
6
6
  import "../../../../../components/ui/Button/index.js";
7
7
  import { usGenerativeChatStore } from "../store/generativeChatStore.js";
8
+ import useChatConversations from "../hooks/useChatConversations.js";
8
9
  import { useForm, Controller } from "react-hook-form";
9
10
  import { zodResolver } from "@hookform/resolvers/zod";
10
11
  import { z } from "zod";
@@ -14,10 +15,13 @@ import FormItem from "../../../../../components/ui/Form/FormItem.js";
14
15
  import Input from "../../../../../components/ui/Input/Input.js";
15
16
  import Button from "../../../../../components/ui/Button/Button.js";
16
17
  const validationSchema = z.object({
17
- title: z.string().min(1, "Please do not leave chat title blank!")
18
+ title: z.string().trim().min(1, "Informe um título para a conversa.")
18
19
  });
19
- const ChatHistoryRenameDialog = () => {
20
- const { renameDialog, setRenameDialog, setChatHistoryName } = usGenerativeChatStore();
20
+ const ChatHistoryRenameDialog = ({
21
+ overlayClassName
22
+ }) => {
23
+ const { renameDialog, setRenameDialog } = usGenerativeChatStore();
24
+ const { renomear } = useChatConversations();
21
25
  const {
22
26
  control,
23
27
  formState: { errors },
@@ -44,16 +48,15 @@ const ChatHistoryRenameDialog = () => {
44
48
  });
45
49
  };
46
50
  const onFormSubmit = async ({ title }) => {
47
- setChatHistoryName({
48
- id: renameDialog.id,
49
- title
50
- });
51
+ const { id } = renameDialog;
51
52
  handleDialogClose();
53
+ await renomear(id, title.trim());
52
54
  };
53
55
  return /* @__PURE__ */ jsxs(
54
56
  Dialog,
55
57
  {
56
58
  isOpen: renameDialog.open,
59
+ overlayClassName,
57
60
  onClose: handleDialogClose,
58
61
  onRequestClose: handleDialogClose,
59
62
  children: [
@@ -1 +1 @@
1
- {"version":3,"file":"ChatHistoryRenameDialog.js","sources":["../../../../../../../lib/@ecme/views/concepts/ai/Chat/components/ChatHistoryRenameDialog.tsx"],"sourcesContent":["import { useEffect } from 'react'\nimport Dialog from '@/components/ui/Dialog'\nimport { Form, FormItem } from '@/components/ui/Form'\nimport Input from '@/components/ui/Input'\nimport Button from '@/components/ui/Button'\nimport { usGenerativeChatStore } from '../store/generativeChatStore'\nimport { useForm, Controller } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { z } from 'zod'\nimport type { ZodType } from 'zod'\n\ntype FormSchema = {\n title: string\n}\n\nconst validationSchema: ZodType<FormSchema> = z.object({\n title: z.string().min(1, 'Please do not leave chat title blank!'),\n})\n\nconst ChatHistoryRenameDialog = () => {\n const { renameDialog, setRenameDialog, setChatHistoryName } =\n usGenerativeChatStore()\n\n const {\n control,\n formState: { errors },\n handleSubmit,\n reset,\n } = useForm<FormSchema>({\n defaultValues: {\n title: renameDialog.title,\n },\n resolver: zodResolver(validationSchema),\n })\n\n useEffect(() => {\n if (renameDialog.open) {\n reset({\n title: renameDialog.title,\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [renameDialog.title, renameDialog.open])\n\n const handleDialogClose = () => {\n setRenameDialog({\n id: '',\n title: '',\n open: false,\n })\n }\n\n const onFormSubmit = async ({ title }: FormSchema) => {\n setChatHistoryName({\n id: renameDialog.id,\n title,\n })\n handleDialogClose()\n }\n\n return (\n <Dialog\n isOpen={renameDialog.open}\n onClose={handleDialogClose}\n onRequestClose={handleDialogClose}\n >\n <h5>Rename chat</h5>\n <div className=\"mt-8\">\n <Form onSubmit={handleSubmit(onFormSubmit)}>\n <FormItem\n label=\"Chat title\"\n invalid={Boolean(errors.title)}\n errorMessage={errors.title?.message}\n >\n <Controller\n name=\"title\"\n control={control}\n rules={{ required: true }}\n render={({ field }) => (\n <Input\n placeholder=\"Rename chat\"\n type=\"text\"\n autoComplete=\"off\"\n {...field}\n />\n )}\n />\n </FormItem>\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" onClick={handleDialogClose}>\n Cancel\n </Button>\n <Button variant=\"solid\" type=\"submit\">\n Rename\n </Button>\n </div>\n </Form>\n </div>\n </Dialog>\n )\n}\n\nexport default ChatHistoryRenameDialog\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAeA,MAAM,mBAAwC,EAAE,OAAO;AAAA,EACnD,OAAO,EAAE,OAAA,EAAS,IAAI,GAAG,uCAAuC;AACpE,CAAC;AAED,MAAM,0BAA0B,MAAM;AAClC,QAAM,EAAE,cAAc,iBAAiB,mBAAA,IACnC,sBAAA;AAEJ,QAAM;AAAA,IACF;AAAA,IACA,WAAW,EAAE,OAAA;AAAA,IACb;AAAA,IACA;AAAA,EAAA,IACA,QAAoB;AAAA,IACpB,eAAe;AAAA,MACX,OAAO,aAAa;AAAA,IAAA;AAAA,IAExB,UAAU,YAAY,gBAAgB;AAAA,EAAA,CACzC;AAED,YAAU,MAAM;AACZ,QAAI,aAAa,MAAM;AACnB,YAAM;AAAA,QACF,OAAO,aAAa;AAAA,MAAA,CACvB;AAAA,IACL;AAAA,EAEJ,GAAG,CAAC,aAAa,OAAO,aAAa,IAAI,CAAC;AAE1C,QAAM,oBAAoB,MAAM;AAC5B,oBAAgB;AAAA,MACZ,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,IAAA,CACT;AAAA,EACL;AAEA,QAAM,eAAe,OAAO,EAAE,YAAwB;AAClD,uBAAmB;AAAA,MACf,IAAI,aAAa;AAAA,MACjB;AAAA,IAAA,CACH;AACD,sBAAA;AAAA,EACJ;AAEA,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,QAAQ,aAAa;AAAA,MACrB,SAAS;AAAA,MACT,gBAAgB;AAAA,MAEhB,UAAA;AAAA,QAAA,oBAAC,QAAG,UAAA,cAAA,CAAW;AAAA,QACf,oBAAC,SAAI,WAAU,QACX,+BAAC,MAAA,EAAK,UAAU,aAAa,YAAY,GACrC,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,OAAM;AAAA,cACN,SAAS,QAAQ,OAAO,KAAK;AAAA,cAC7B,cAAc,OAAO,OAAO;AAAA,cAE5B,UAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACG,MAAK;AAAA,kBACL;AAAA,kBACA,OAAO,EAAE,UAAU,KAAA;AAAA,kBACnB,QAAQ,CAAC,EAAE,MAAA,MACP;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACG,aAAY;AAAA,sBACZ,MAAK;AAAA,sBACL,cAAa;AAAA,sBACZ,GAAG;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACR;AAAA,cAAA;AAAA,YAER;AAAA,UAAA;AAAA,UAEJ,qBAAC,OAAA,EAAI,WAAU,0BACX,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAO,MAAK,UAAS,SAAS,mBAAmB,UAAA,UAElD;AAAA,gCACC,QAAA,EAAO,SAAQ,SAAQ,MAAK,UAAS,UAAA,SAAA,CAEtC;AAAA,UAAA,EAAA,CACJ;AAAA,QAAA,EAAA,CACJ,EAAA,CACJ;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGZ;"}
1
+ {"version":3,"file":"ChatHistoryRenameDialog.js","sources":["../../../../../../../lib/@ecme/views/concepts/ai/Chat/components/ChatHistoryRenameDialog.tsx"],"sourcesContent":["import { useEffect } from 'react'\nimport Dialog from '@/components/ui/Dialog'\nimport { Form, FormItem } from '@/components/ui/Form'\nimport Input from '@/components/ui/Input'\nimport Button from '@/components/ui/Button'\nimport { usGenerativeChatStore } from '../store/generativeChatStore'\nimport useChatConversations from '../hooks/useChatConversations'\nimport { useForm, Controller } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { z } from 'zod'\nimport type { ZodType } from 'zod'\n\ntype FormSchema = {\n title: string\n}\n\nconst validationSchema: ZodType<FormSchema> = z.object({\n title: z.string().trim().min(1, 'Informe um título para a conversa.'),\n})\n\ntype ChatHistoryRenameDialogProps = {\n /** Classes do overlay (ex.: subir o z-index acima do widget flutuante). */\n overlayClassName?: string\n}\n\nconst ChatHistoryRenameDialog = ({\n overlayClassName,\n}: ChatHistoryRenameDialogProps) => {\n const { renameDialog, setRenameDialog } = usGenerativeChatStore()\n const { renomear } = useChatConversations()\n\n const {\n control,\n formState: { errors },\n handleSubmit,\n reset,\n } = useForm<FormSchema>({\n defaultValues: {\n title: renameDialog.title,\n },\n resolver: zodResolver(validationSchema),\n })\n\n useEffect(() => {\n if (renameDialog.open) {\n reset({\n title: renameDialog.title,\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [renameDialog.title, renameDialog.open])\n\n const handleDialogClose = () => {\n setRenameDialog({\n id: '',\n title: '',\n open: false,\n })\n }\n\n const onFormSubmit = async ({ title }: FormSchema) => {\n // Fecha antes da resposta: o rename é otimista e desfaz sozinho se o\n // backend recusar.\n const { id } = renameDialog\n handleDialogClose()\n await renomear(id, title.trim())\n }\n\n return (\n <Dialog\n isOpen={renameDialog.open}\n overlayClassName={overlayClassName}\n onClose={handleDialogClose}\n onRequestClose={handleDialogClose}\n >\n <h5>Rename chat</h5>\n <div className=\"mt-8\">\n <Form onSubmit={handleSubmit(onFormSubmit)}>\n <FormItem\n label=\"Chat title\"\n invalid={Boolean(errors.title)}\n errorMessage={errors.title?.message}\n >\n <Controller\n name=\"title\"\n control={control}\n rules={{ required: true }}\n render={({ field }) => (\n <Input\n placeholder=\"Rename chat\"\n type=\"text\"\n autoComplete=\"off\"\n {...field}\n />\n )}\n />\n </FormItem>\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" onClick={handleDialogClose}>\n Cancel\n </Button>\n <Button variant=\"solid\" type=\"submit\">\n Rename\n </Button>\n </div>\n </Form>\n </div>\n </Dialog>\n )\n}\n\nexport default ChatHistoryRenameDialog\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAM,mBAAwC,EAAE,OAAO;AAAA,EACnD,OAAO,EAAE,OAAA,EAAS,OAAO,IAAI,GAAG,oCAAoC;AACxE,CAAC;AAOD,MAAM,0BAA0B,CAAC;AAAA,EAC7B;AACJ,MAAoC;AAChC,QAAM,EAAE,cAAc,gBAAA,IAAoB,sBAAA;AAC1C,QAAM,EAAE,SAAA,IAAa,qBAAA;AAErB,QAAM;AAAA,IACF;AAAA,IACA,WAAW,EAAE,OAAA;AAAA,IACb;AAAA,IACA;AAAA,EAAA,IACA,QAAoB;AAAA,IACpB,eAAe;AAAA,MACX,OAAO,aAAa;AAAA,IAAA;AAAA,IAExB,UAAU,YAAY,gBAAgB;AAAA,EAAA,CACzC;AAED,YAAU,MAAM;AACZ,QAAI,aAAa,MAAM;AACnB,YAAM;AAAA,QACF,OAAO,aAAa;AAAA,MAAA,CACvB;AAAA,IACL;AAAA,EAEJ,GAAG,CAAC,aAAa,OAAO,aAAa,IAAI,CAAC;AAE1C,QAAM,oBAAoB,MAAM;AAC5B,oBAAgB;AAAA,MACZ,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,IAAA,CACT;AAAA,EACL;AAEA,QAAM,eAAe,OAAO,EAAE,YAAwB;AAGlD,UAAM,EAAE,OAAO;AACf,sBAAA;AACA,UAAM,SAAS,IAAI,MAAM,KAAA,CAAM;AAAA,EACnC;AAEA,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,QAAQ,aAAa;AAAA,MACrB;AAAA,MACA,SAAS;AAAA,MACT,gBAAgB;AAAA,MAEhB,UAAA;AAAA,QAAA,oBAAC,QAAG,UAAA,cAAA,CAAW;AAAA,QACf,oBAAC,SAAI,WAAU,QACX,+BAAC,MAAA,EAAK,UAAU,aAAa,YAAY,GACrC,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,OAAM;AAAA,cACN,SAAS,QAAQ,OAAO,KAAK;AAAA,cAC7B,cAAc,OAAO,OAAO;AAAA,cAE5B,UAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACG,MAAK;AAAA,kBACL;AAAA,kBACA,OAAO,EAAE,UAAU,KAAA;AAAA,kBACnB,QAAQ,CAAC,EAAE,MAAA,MACP;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACG,aAAY;AAAA,sBACZ,MAAK;AAAA,sBACL,cAAa;AAAA,sBACZ,GAAG;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACR;AAAA,cAAA;AAAA,YAER;AAAA,UAAA;AAAA,UAEJ,qBAAC,OAAA,EAAI,WAAU,0BACX,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAO,MAAK,UAAS,SAAS,mBAAmB,UAAA,UAElD;AAAA,gCACC,QAAA,EAAO,SAAQ,SAAQ,MAAK,UAAS,UAAA,SAAA,CAEtC;AAAA,UAAA,EAAA,CACJ;AAAA,QAAA,EAAA,CACJ,EAAA,CACJ;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGZ;"}
@@ -13,13 +13,15 @@ import ApprovalCard from "./ApprovalCard.js";
13
13
  import DataRequestCard from "./DataRequestCard.js";
14
14
  import { usGenerativeChatStore } from "../store/generativeChatStore.js";
15
15
  import useChatSend from "../hooks/useChatSend.js";
16
+ import useConversationMessages from "../hooks/useConversationMessages.js";
16
17
  import Card from "../../../../../components/ui/Card/Card.js";
17
18
  import ChatBox from "../../../../../components/view/ChatBox/ChatBox.js";
18
19
  const BALAO_AGENTE = "prose rounded-xl bg-gray-100 px-5 py-2.5 text-sm text-gray-900 dark:bg-gray-700 dark:text-gray-100";
19
- const ChatView = () => {
20
+ const ChatView = ({ showMobileNav = true }) => {
20
21
  const scrollRef = useRef(null);
21
22
  const { selectedConversation, chatHistory, isTyping, disabledChatFresh } = usGenerativeChatStore();
22
23
  const { handleSend, handleApproval, handleDataSubmit } = useChatSend();
24
+ const { carregando } = useConversationMessages();
23
25
  const scrollToBottom = () => {
24
26
  if (scrollRef.current?.getScrollElement) {
25
27
  const scrollElement = scrollRef.current.getScrollElement();
@@ -47,7 +49,7 @@ const ChatView = () => {
47
49
  scrollToBottom();
48
50
  };
49
51
  return /* @__PURE__ */ jsxs(Card, { className: "flex-1 h-full", bodyClass: "h-full", children: [
50
- /* @__PURE__ */ jsx(ChatMobileNav, {}),
52
+ showMobileNav && /* @__PURE__ */ jsx(ChatMobileNav, {}),
51
53
  /* @__PURE__ */ jsx(
52
54
  ChatBox,
53
55
  {
@@ -61,9 +63,9 @@ const ChatView = () => {
61
63
  botBubbleClass: "bg-transparent dark:bg-transparent p-0 rounded-none",
62
64
  errorBubbleClass: "bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/20",
63
65
  renderTyping: () => /* @__PURE__ */ jsx("div", { className: BALAO_AGENTE, children: /* @__PURE__ */ jsx(AiThinkingIndicator, {}) }),
64
- containerClass: "h-[calc(100%-30px)] xl:h-full",
66
+ containerClass: showMobileNav ? "h-[calc(100%-30px)] xl:h-full" : "h-full",
65
67
  messageListClass: "h-[calc(100%-100px)] xl:h-[calc(100%-70px)]",
66
- typing: isTyping ? {
68
+ typing: isTyping || carregando ? {
67
69
  id: "ai",
68
70
  name: "Chat AI",
69
71
  avatarImageUrl: "/img/thumbs/ai.jpg"
@@ -1 +1 @@
1
- {"version":3,"file":"ChatView.js","sources":["../../../../../../../lib/@ecme/views/concepts/ai/Chat/components/ChatView.tsx"],"sourcesContent":["import { useRef, useEffect, useMemo } from 'react'\nimport Card from '@/components/ui/Card'\nimport ChatBox from '@/components/view/ChatBox'\nimport ChatLandingView from './ChatLandingView'\nimport ChatMobileNav from './ChatMobileNav'\nimport ChatCustomContent from './ChatCustomContent'\nimport ChatCustomAction from './ChatCustomAction'\nimport AiThinkingIndicator from './AiThinkingIndicator'\nimport AiErrorMessage from './AiErrorMessage'\nimport ToolCallChip from './ToolCallChip'\nimport ApprovalCard from './ApprovalCard'\nimport DataRequestCard from './DataRequestCard'\nimport { usGenerativeChatStore } from '../store/generativeChatStore'\nimport useChatSend from '../hooks/useChatSend'\nimport type { Conversation } from '../types'\nimport type { ScrollBarRef } from '@/components/ui/ScrollBar'\n\n/**\n * O balao de fala do agente, desenhado aqui em vez de vir do ChatBox.\n *\n * O `botBubbleClass` abaixo zera o balao que o Message desenharia, para os chips\n * de ferramenta e o card de aprovacao ficarem FORA dele — antes tudo dividia a\n * mesma caixa cinza e as ferramentas eram lidas como uma segunda mensagem.\n * Usado tambem pelo indicador de \"pensando\", que passa pelo mesmo balao zerado.\n *\n * Repete `prose text-sm` do balao original de proposito: o reset de margem do\n * @tailwindcss/typography e `.prose > :first-child`, filho DIRETO. Sem o `prose`\n * aqui, o markdown ficaria um nivel abaixo do container e o primeiro paragrafo\n * voltaria a ter margem, inflando todos os baloes.\n */\nconst BALAO_AGENTE =\n 'prose rounded-xl bg-gray-100 px-5 py-2.5 text-sm text-gray-900 dark:bg-gray-700 dark:text-gray-100'\n\nconst ChatView = () => {\n const scrollRef = useRef<ScrollBarRef>(null)\n const { selectedConversation, chatHistory, isTyping, disabledChatFresh } =\n usGenerativeChatStore()\n const { handleSend, handleApproval, handleDataSubmit } = useChatSend()\n\n const scrollToBottom = () => {\n if (scrollRef.current?.getScrollElement) {\n const scrollElement = scrollRef.current.getScrollElement()\n if (scrollElement) {\n scrollElement.scrollTop = scrollElement.scrollHeight\n }\n }\n }\n\n useEffect(() => {\n scrollToBottom()\n }, [selectedConversation, chatHistory])\n\n const messageList = useMemo(() => {\n const chat = chatHistory.find(\n (chat) => chat.id === selectedConversation,\n )\n return chat?.conversation || []\n }, [selectedConversation, chatHistory])\n\n const handleInputChange = async ({\n value,\n }: {\n value: string\n attachments?: File[]\n }) => {\n await handleSend(value)\n }\n\n const handleFinish = (id: string) => {\n disabledChatFresh(id)\n scrollToBottom()\n }\n\n return (\n <Card className=\"flex-1 h-full\" bodyClass=\"h-full\">\n <ChatMobileNav />\n <ChatBox\n ref={scrollRef}\n messageList={messageList}\n placeholder=\"Pergunte algo sobre o Orbe Agro…\"\n showMessageList={Boolean(selectedConversation)}\n showAvatar={false}\n avatarGap={false}\n myBubbleClass=\"bg-primary text-white\"\n botBubbleClass=\"bg-transparent dark:bg-transparent p-0 rounded-none\"\n errorBubbleClass=\"bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/20\"\n renderTyping={() => (\n <div className={BALAO_AGENTE}>\n <AiThinkingIndicator />\n </div>\n )}\n containerClass=\"h-[calc(100%-30px)] xl:h-full\"\n messageListClass=\"h-[calc(100%-100px)] xl:h-[calc(100%-70px)]\"\n typing={\n isTyping\n ? {\n id: 'ai',\n name: 'Chat AI',\n avatarImageUrl: '/img/thumbs/ai.jpg',\n }\n : false\n }\n customRenderer={(message) => {\n if (message.isError) {\n return <AiErrorMessage />\n }\n\n if (message.sender.id === 'ai') {\n // As ferramentas e as pausas chegam pelo streaming e\n // vivem no Conversation; o tipo do ChatBox nao os conhece.\n const { tools, pendingApproval, pendingInput } =\n message as Conversation\n // Enquanto as ferramentas rodam o conteudo ainda e '':\n // sem esta guarda sobraria um balao cinza vazio.\n const temTexto = Boolean(\n (message.content as string)?.trim(),\n )\n\n return (\n <div className=\"flex flex-col items-start gap-1.5\">\n {tools?.map((tool) => (\n <ToolCallChip key={tool.id} tool={tool} />\n ))}\n {temTexto && (\n <div className={BALAO_AGENTE}>\n <ChatCustomContent\n content={message.content as string}\n triggerTyping={\n message.fresh\n ? message.fresh\n : false\n }\n onFinish={() =>\n handleFinish(message.id)\n }\n />\n </div>\n )}\n {pendingInput && (\n <DataRequestCard\n input={pendingInput}\n onSubmit={(dados) =>\n handleDataSubmit(\n selectedConversation,\n message.id,\n dados,\n )\n }\n />\n )}\n {pendingApproval && (\n <ApprovalCard\n approval={pendingApproval}\n onDecide={(aprovado) =>\n handleApproval(\n selectedConversation,\n message.id,\n aprovado,\n )\n }\n />\n )}\n </div>\n )\n }\n\n return message.content\n }}\n customAction={(message) => {\n if (message.sender.id === 'ai' && !message.isError) {\n return (\n <ChatCustomAction\n content={message.content as string}\n />\n )\n }\n\n return null\n }}\n onInputChange={handleInputChange}\n >\n {!selectedConversation && (\n <div className=\"flex-1 min-h-0 overflow-y-auto\">\n <ChatLandingView />\n </div>\n )}\n </ChatBox>\n </Card>\n )\n}\n\nexport default ChatView\n"],"names":["chat"],"mappings":"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"}
1
+ {"version":3,"file":"ChatView.js","sources":["../../../../../../../lib/@ecme/views/concepts/ai/Chat/components/ChatView.tsx"],"sourcesContent":["import { useRef, useEffect, useMemo } from 'react'\nimport Card from '@/components/ui/Card'\nimport ChatBox from '@/components/view/ChatBox'\nimport ChatLandingView from './ChatLandingView'\nimport ChatMobileNav from './ChatMobileNav'\nimport ChatCustomContent from './ChatCustomContent'\nimport ChatCustomAction from './ChatCustomAction'\nimport AiThinkingIndicator from './AiThinkingIndicator'\nimport AiErrorMessage from './AiErrorMessage'\nimport ToolCallChip from './ToolCallChip'\nimport ApprovalCard from './ApprovalCard'\nimport DataRequestCard from './DataRequestCard'\nimport { usGenerativeChatStore } from '../store/generativeChatStore'\nimport useChatSend from '../hooks/useChatSend'\nimport useConversationMessages from '../hooks/useConversationMessages'\nimport type { Conversation } from '../types'\nimport type { ScrollBarRef } from '@/components/ui/ScrollBar'\n\n/**\n * O balao de fala do agente, desenhado aqui em vez de vir do ChatBox.\n *\n * O `botBubbleClass` abaixo zera o balao que o Message desenharia, para os chips\n * de ferramenta e o card de aprovacao ficarem FORA dele — antes tudo dividia a\n * mesma caixa cinza e as ferramentas eram lidas como uma segunda mensagem.\n * Usado tambem pelo indicador de \"pensando\", que passa pelo mesmo balao zerado.\n *\n * Repete `prose text-sm` do balao original de proposito: o reset de margem do\n * @tailwindcss/typography e `.prose > :first-child`, filho DIRETO. Sem o `prose`\n * aqui, o markdown ficaria um nivel abaixo do container e o primeiro paragrafo\n * voltaria a ter margem, inflando todos os baloes.\n */\nconst BALAO_AGENTE =\n 'prose rounded-xl bg-gray-100 px-5 py-2.5 text-sm text-gray-900 dark:bg-gray-700 dark:text-gray-100'\n\ntype ChatViewProps = {\n /**\n * Mostra o drawer de histórico do ChatMobileNav abaixo de xl. O widget\n * flutuante desliga, porque tem o próprio drawer dentro do painel.\n */\n showMobileNav?: boolean\n}\n\nconst ChatView = ({ showMobileNav = true }: ChatViewProps) => {\n const scrollRef = useRef<ScrollBarRef>(null)\n const { selectedConversation, chatHistory, isTyping, disabledChatFresh } =\n usGenerativeChatStore()\n const { handleSend, handleApproval, handleDataSubmit } = useChatSend()\n // Conversa aberta da lista: as mensagens vêm do backend na primeira vez.\n const { carregando } = useConversationMessages()\n\n const scrollToBottom = () => {\n if (scrollRef.current?.getScrollElement) {\n const scrollElement = scrollRef.current.getScrollElement()\n if (scrollElement) {\n scrollElement.scrollTop = scrollElement.scrollHeight\n }\n }\n }\n\n useEffect(() => {\n scrollToBottom()\n }, [selectedConversation, chatHistory])\n\n const messageList = useMemo(() => {\n const chat = chatHistory.find(\n (chat) => chat.id === selectedConversation,\n )\n return chat?.conversation || []\n }, [selectedConversation, chatHistory])\n\n const handleInputChange = async ({\n value,\n }: {\n value: string\n attachments?: File[]\n }) => {\n await handleSend(value)\n }\n\n const handleFinish = (id: string) => {\n disabledChatFresh(id)\n scrollToBottom()\n }\n\n return (\n <Card className=\"flex-1 h-full\" bodyClass=\"h-full\">\n {showMobileNav && <ChatMobileNav />}\n <ChatBox\n ref={scrollRef}\n messageList={messageList}\n placeholder=\"Pergunte algo sobre o Orbe Agro…\"\n showMessageList={Boolean(selectedConversation)}\n showAvatar={false}\n avatarGap={false}\n myBubbleClass=\"bg-primary text-white\"\n botBubbleClass=\"bg-transparent dark:bg-transparent p-0 rounded-none\"\n errorBubbleClass=\"bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/20\"\n renderTyping={() => (\n <div className={BALAO_AGENTE}>\n <AiThinkingIndicator />\n </div>\n )}\n containerClass={\n showMobileNav ? 'h-[calc(100%-30px)] xl:h-full' : 'h-full'\n }\n messageListClass=\"h-[calc(100%-100px)] xl:h-[calc(100%-70px)]\"\n typing={\n isTyping || carregando\n ? {\n id: 'ai',\n name: 'Chat AI',\n avatarImageUrl: '/img/thumbs/ai.jpg',\n }\n : false\n }\n customRenderer={(message) => {\n if (message.isError) {\n return <AiErrorMessage />\n }\n\n if (message.sender.id === 'ai') {\n // As ferramentas e as pausas chegam pelo streaming e\n // vivem no Conversation; o tipo do ChatBox nao os conhece.\n const { tools, pendingApproval, pendingInput } =\n message as Conversation\n // Enquanto as ferramentas rodam o conteudo ainda e '':\n // sem esta guarda sobraria um balao cinza vazio.\n const temTexto = Boolean(\n (message.content as string)?.trim(),\n )\n\n return (\n <div className=\"flex flex-col items-start gap-1.5\">\n {tools?.map((tool) => (\n <ToolCallChip key={tool.id} tool={tool} />\n ))}\n {temTexto && (\n <div className={BALAO_AGENTE}>\n <ChatCustomContent\n content={message.content as string}\n triggerTyping={\n message.fresh\n ? message.fresh\n : false\n }\n onFinish={() =>\n handleFinish(message.id)\n }\n />\n </div>\n )}\n {pendingInput && (\n <DataRequestCard\n input={pendingInput}\n onSubmit={(dados) =>\n handleDataSubmit(\n selectedConversation,\n message.id,\n dados,\n )\n }\n />\n )}\n {pendingApproval && (\n <ApprovalCard\n approval={pendingApproval}\n onDecide={(aprovado) =>\n handleApproval(\n selectedConversation,\n message.id,\n aprovado,\n )\n }\n />\n )}\n </div>\n )\n }\n\n return message.content\n }}\n customAction={(message) => {\n if (message.sender.id === 'ai' && !message.isError) {\n return (\n <ChatCustomAction\n content={message.content as string}\n />\n )\n }\n\n return null\n }}\n onInputChange={handleInputChange}\n >\n {!selectedConversation && (\n <div className=\"flex-1 min-h-0 overflow-y-auto\">\n <ChatLandingView />\n </div>\n )}\n </ChatBox>\n </Card>\n )\n}\n\nexport default ChatView\n"],"names":["chat"],"mappings":"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"}