'use client' import type { FC } from 'react' import React, { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' import TemplateVarPanel, { PanelTitle, VarOpBtnGroup } from '../value-panel' import s from './style.module.css' import { AppInfo, ChatBtn, EditBtn, FootLogo, PromptTemplate } from './massive-component' import type { SiteInfo } from '@/models/share' import type { PromptConfig } from '@/models/debug' import { ToastContext } from '@/app/components/base/toast' import Select from '@/app/components/base/select' import { DEFAULT_VALUE_MAX_LEN } from '@/config' // regex to match the {{}} and replace it with a span const regex = /\{\{([^}]+)\}\}/g export type IWelcomeProps = { conversationName: string hasSetInputs: boolean isPublicVersion: boolean siteInfo: SiteInfo promptConfig: PromptConfig onStartChat: (inputs: Record) => void canEidtInpus: boolean savedInputs: Record onInputsChange: (inputs: Record) => void plan?: string } const Welcome: FC = ({ conversationName, hasSetInputs, isPublicVersion, siteInfo, plan, promptConfig, onStartChat, canEidtInpus, savedInputs, onInputsChange, }) => { const { t } = useTranslation() const hasVar = promptConfig.prompt_variables.length > 0 const [isFold, setIsFold] = useState(true) const [inputs, setInputs] = useState>((() => { if (hasSetInputs) return savedInputs const res: Record = {} if (promptConfig) { promptConfig.prompt_variables.forEach((item) => { res[item.key] = '' }) } // debugger return res })()) useEffect(() => { if (!savedInputs) { const res: Record = {} if (promptConfig) { promptConfig.prompt_variables.forEach((item) => { res[item.key] = '' }) } setInputs(res) } else { setInputs(savedInputs) } }, [savedInputs]) const highLightPromoptTemplate = (() => { if (!promptConfig) return '' const res = promptConfig.prompt_template.replace(regex, (match, p1) => { return `${inputs?.[p1] ? inputs?.[p1] : match}` }) return res })() const { notify } = useContext(ToastContext) const logError = (message: string) => { notify({ type: 'error', message, duration: 3000 }) } const renderHeader = () => { return (
{conversationName}
) } const renderInputs = () => { return (
{promptConfig.prompt_variables.map(item => (
{item.type === 'select' ? ( { setInputs({ ...inputs, [item.key]: e.target.value }) }} className={'w-full flex-grow py-2 pl-3 pr-3 box-border rounded-lg bg-gray-50'} maxLength={item.max_length || DEFAULT_VALUE_MAX_LEN} /> )}
))}
) } const canChat = () => { const prompt_variables = promptConfig?.prompt_variables if (!inputs || !prompt_variables || prompt_variables?.length === 0) return true let hasEmptyInput = '' const requiredVars = prompt_variables?.filter(({ key, name, required }) => { const res = (!key || !key.trim()) || (!name || !name.trim()) || (required || required === undefined || required === null) return res }) || [] // compatible with old version requiredVars.forEach(({ key, name }) => { if (hasEmptyInput) return if (!inputs?.[key]) hasEmptyInput = name }) if (hasEmptyInput) { logError(t('appDebug.errorMessage.valueOfVarRequired', { key: hasEmptyInput })) return false } return !hasEmptyInput } const handleChat = () => { if (!canChat()) return onStartChat(inputs) } const renderNoVarPanel = () => { if (isPublicVersion) { return (
} >
) } // private version return ( } > ) } const renderVarPanel = () => { return ( } > {renderInputs()} ) } const renderVarOpBtnGroup = () => { return ( { if (!canChat()) return onInputsChange(inputs) setIsFold(true) }} onCancel={() => { setInputs(savedInputs) setIsFold(true) }} /> ) } const renderHasSetInputsPublic = () => { if (!canEidtInpus) { return ( } /> ) } return ( {isFold && (
{t('share.chat.configStatusDes')} setIsFold(false)} />
)} } > {renderInputs()} {renderVarOpBtnGroup()}
) } const renderHasSetInputsPrivate = () => { if (!canEidtInpus || !hasVar) return null return ( {isFold && ( setIsFold(false)} /> )} } > {renderInputs()} {renderVarOpBtnGroup()} ) } const renderHasSetInputs = () => { if ((!isPublicVersion && !canEidtInpus) || !hasVar) return null return (
{isPublicVersion ? renderHasSetInputsPublic() : renderHasSetInputsPrivate()}
) } return (
{hasSetInputs && renderHeader()}
{/* Has't set inputs */} { !hasSetInputs && (
{hasVar ? ( renderVarPanel() ) : ( renderNoVarPanel() )}
) } {/* Has set inputs */} {hasSetInputs && renderHasSetInputs()} {/* foot */} {!hasSetInputs && (
{siteInfo.privacy_policy ?
{t('share.chat.privacyPolicyLeft')} {t('share.chat.privacyPolicyMiddle')} {t('share.chat.privacyPolicyRight')}
:
} {plan === 'basic' && {t('share.chat.powerBy')} }
)}
) } export default React.memo(Welcome)