diff --git a/packages/twenty-front/src/modules/ai/components/AIChatApiKeyNotConfiguredMessage.tsx b/packages/twenty-front/src/modules/ai/components/AIChatApiKeyNotConfiguredMessage.tsx new file mode 100644 index 00000000000..df26fc79547 --- /dev/null +++ b/packages/twenty-front/src/modules/ai/components/AIChatApiKeyNotConfiguredMessage.tsx @@ -0,0 +1,22 @@ +import { AIChatBanner } from '@/ai/components/AIChatBanner'; +import { t } from '@lingui/core/macro'; +import { IconExternalLink } from 'twenty-ui/display'; + +const DOCS_URL = + 'https://twenty.com/developers/section/self-hosting/self-hosting-var#ai-features'; + +export const AIChatApiKeyNotConfiguredMessage = () => { + const handleDocsClick = () => { + window.open(DOCS_URL, '_blank', 'noopener,noreferrer'); + }; + + return ( + + ); +}; diff --git a/packages/twenty-front/src/modules/ai/components/AIChatBanner.tsx b/packages/twenty-front/src/modules/ai/components/AIChatBanner.tsx new file mode 100644 index 00000000000..dce8ea73e4f --- /dev/null +++ b/packages/twenty-front/src/modules/ai/components/AIChatBanner.tsx @@ -0,0 +1,106 @@ +import styled from '@emotion/styled'; +import { isDefined } from 'twenty-shared/utils'; +import { + AppTooltip, + type IconComponent, + IconAlertTriangle, + IconInfoCircle, +} from 'twenty-ui/display'; +import { Button } from 'twenty-ui/input'; + +type AIChatBannerVariant = 'default' | 'warning'; + +const StyledBanner = styled.div<{ variant: AIChatBannerVariant }>` + align-items: center; + background-color: ${({ theme, variant }) => + variant === 'warning' + ? theme.background.transparent.orange + : theme.accent.secondary}; + border-radius: ${({ theme }) => theme.border.radius.md}; + box-sizing: border-box; + display: flex; + gap: ${({ theme }) => theme.spacing(2)}; + padding: ${({ theme }) => theme.spacing(2)}; + width: 100%; +`; + +const StyledIconContainer = styled.div<{ variant: AIChatBannerVariant }>` + align-items: center; + color: ${({ theme, variant }) => + variant === 'warning' ? theme.color.orange : theme.color.blue}; + display: flex; + flex-shrink: 0; + height: 16px; + justify-content: center; + width: 16px; +`; + +const StyledMessage = styled.p<{ variant: AIChatBannerVariant }>` + color: ${({ theme, variant }) => + variant === 'warning' ? theme.color.orange : theme.color.blue}; + flex-grow: 1; + font-family: ${({ theme }) => theme.font.family}; + font-size: ${({ theme }) => theme.font.size.sm}; + font-style: normal; + font-weight: ${({ theme }) => theme.font.weight.medium}; + line-height: 1.4; + margin: 0; + min-width: 0; +`; + +export type AIChatBannerProps = { + message: string; + variant?: AIChatBannerVariant; + tooltipMessage?: string; + buttonTitle?: string; + buttonIcon?: IconComponent; + buttonOnClick?: () => void; + isButtonDisabled?: boolean; + isButtonLoading?: boolean; +}; + +export const AIChatBanner = ({ + message, + variant = 'default', + tooltipMessage, + buttonTitle, + buttonIcon, + buttonOnClick, + isButtonDisabled = false, + isButtonLoading = false, +}: AIChatBannerProps) => { + const tooltipId = 'ai-chat-banner-tooltip'; + + return ( + + + {variant === 'default' ? ( + + ) : ( + + )} + + {message} + {isDefined(buttonTitle) && isDefined(buttonOnClick) && ( +