|
@@ -7,11 +7,11 @@ import { Trans, useTranslation } from 'react-i18next'
|
|
|
import s from './style.module.css'
|
|
|
import Modal from '@/app/components/base/modal'
|
|
|
import Button from '@/app/components/base/button'
|
|
|
-import Switch from '@/app/components/base/switch'
|
|
|
import AppIcon from '@/app/components/base/app-icon'
|
|
|
import { SimpleSelect } from '@/app/components/base/select'
|
|
|
import type { AppDetailResponse } from '@/models/app'
|
|
|
import type { Language } from '@/types/app'
|
|
|
+import EmojiPicker from '@/app/components/base/emoji-picker'
|
|
|
|
|
|
export type ISettingsModalProps = {
|
|
|
appInfo: AppDetailResponse
|
|
@@ -42,11 +42,14 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
|
|
onSave,
|
|
|
}) => {
|
|
|
const [isShowMore, setIsShowMore] = useState(false)
|
|
|
- const { title, description, copyright, privacy_policy, default_language } = appInfo.site
|
|
|
+ const { title, description, copyright, privacy_policy, default_language, icon, icon_background } = appInfo.site
|
|
|
const [inputInfo, setInputInfo] = useState({ title, desc: description, copyright, privacyPolicy: privacy_policy })
|
|
|
const [language, setLanguage] = useState(default_language)
|
|
|
const [saveLoading, setSaveLoading] = useState(false)
|
|
|
const { t } = useTranslation()
|
|
|
+ // Emoji Picker
|
|
|
+ const [showEmojiPicker, setShowEmojiPicker] = useState(false)
|
|
|
+ const [emoji, setEmoji] = useState({ icon, icon_background })
|
|
|
|
|
|
const onHide = () => {
|
|
|
onClose()
|
|
@@ -64,6 +67,8 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
|
|
prompt_public: false,
|
|
|
copyright: inputInfo.copyright,
|
|
|
privacy_policy: inputInfo.privacyPolicy,
|
|
|
+ icon: emoji.icon,
|
|
|
+ icon_background: emoji.icon_background,
|
|
|
}
|
|
|
await onSave(params)
|
|
|
setSaveLoading(false)
|
|
@@ -77,69 +82,88 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
|
|
}
|
|
|
|
|
|
return (
|
|
|
- <Modal
|
|
|
- title={t(`${prefixSettings}.title`)}
|
|
|
- isShow={isShow}
|
|
|
- onClose={onHide}
|
|
|
- className={`${s.settingsModal}`}
|
|
|
- >
|
|
|
- <div className={`mt-6 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.webName`)}</div>
|
|
|
- <div className='flex mt-2'>
|
|
|
- <AppIcon className='!mr-3 self-center' />
|
|
|
- <input className={`flex-grow rounded-lg h-10 box-border px-3 ${s.projectName} bg-gray-100`}
|
|
|
- value={inputInfo.title}
|
|
|
- onChange={onChange('title')} />
|
|
|
- </div>
|
|
|
- <div className={`mt-6 font-medium ${s.settingTitle} text-gray-900 `}>{t(`${prefixSettings}.webDesc`)}</div>
|
|
|
- <p className={`mt-1 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.webDescTip`)}</p>
|
|
|
- <textarea
|
|
|
- rows={3}
|
|
|
- className={`mt-2 pt-2 pb-2 px-3 rounded-lg bg-gray-100 w-full ${s.settingsTip} text-gray-900`}
|
|
|
- value={inputInfo.desc}
|
|
|
- onChange={onChange('desc')}
|
|
|
- placeholder={t(`${prefixSettings}.webDescPlaceholder`) as string}
|
|
|
- />
|
|
|
- <div className={`mt-6 mb-2 font-medium ${s.settingTitle} text-gray-900 `}>{t(`${prefixSettings}.language`)}</div>
|
|
|
- <SimpleSelect
|
|
|
- items={Object.keys(LANGUAGE_MAP).map(lang => ({ name: LANGUAGE_MAP[lang as Language], value: lang }))}
|
|
|
- defaultValue={language}
|
|
|
- onSelect={item => setLanguage(item.value as Language)}
|
|
|
- />
|
|
|
- {!isShowMore && <div className='w-full cursor-pointer mt-8' onClick={() => setIsShowMore(true)}>
|
|
|
- <div className='flex justify-between'>
|
|
|
- <div className={`font-medium ${s.settingTitle} flex-grow text-gray-900`}>{t(`${prefixSettings}.more.entry`)}</div>
|
|
|
- <div className='flex-shrink-0 w-4 h-4 text-gray-500'>
|
|
|
- <ChevronRightIcon />
|
|
|
- </div>
|
|
|
+ <>
|
|
|
+ {showEmojiPicker && <EmojiPicker
|
|
|
+ onSelect={(icon, icon_background) => {
|
|
|
+ console.log(icon, icon_background)
|
|
|
+ setEmoji({ icon, icon_background })
|
|
|
+ setShowEmojiPicker(false)
|
|
|
+ }}
|
|
|
+ onClose={() => {
|
|
|
+ setEmoji({ icon: '🤖', icon_background: '#FFEAD5' })
|
|
|
+ setShowEmojiPicker(false)
|
|
|
+ }}
|
|
|
+ />}
|
|
|
+ <Modal
|
|
|
+ title={t(`${prefixSettings}.title`)}
|
|
|
+ isShow={isShow}
|
|
|
+ onClose={onHide}
|
|
|
+ className={`${s.settingsModal}`}
|
|
|
+ >
|
|
|
+ <div className={`mt-6 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.webName`)}</div>
|
|
|
+ <div className='flex mt-2'>
|
|
|
+ <AppIcon size='large'
|
|
|
+ onClick={() => { setShowEmojiPicker(true) }}
|
|
|
+ className='cursor-pointer !mr-3 self-center'
|
|
|
+ icon={emoji.icon}
|
|
|
+ background={emoji.icon_background}
|
|
|
+ />
|
|
|
+ <input className={`flex-grow rounded-lg h-10 box-border px-3 ${s.projectName} bg-gray-100`}
|
|
|
+ value={inputInfo.title}
|
|
|
+ onChange={onChange('title')} />
|
|
|
</div>
|
|
|
- <p className={`mt-1 ${s.policy} text-gray-500`}>{t(`${prefixSettings}.more.copyright`)} & {t(`${prefixSettings}.more.privacyPolicy`)}</p>
|
|
|
- </div>}
|
|
|
- {isShowMore && <>
|
|
|
- <hr className='w-full mt-6' />
|
|
|
- <div className={`mt-6 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.copyright`)}</div>
|
|
|
- <input className={`w-full mt-2 rounded-lg h-10 box-border px-3 ${s.projectName} bg-gray-100`}
|
|
|
- value={inputInfo.copyright}
|
|
|
- onChange={onChange('copyright')}
|
|
|
- placeholder={t(`${prefixSettings}.more.copyRightPlaceholder`) as string}
|
|
|
+ <div className={`mt-6 font-medium ${s.settingTitle} text-gray-900 `}>{t(`${prefixSettings}.webDesc`)}</div>
|
|
|
+ <p className={`mt-1 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.webDescTip`)}</p>
|
|
|
+ <textarea
|
|
|
+ rows={3}
|
|
|
+ className={`mt-2 pt-2 pb-2 px-3 rounded-lg bg-gray-100 w-full ${s.settingsTip} text-gray-900`}
|
|
|
+ value={inputInfo.desc}
|
|
|
+ onChange={onChange('desc')}
|
|
|
+ placeholder={t(`${prefixSettings}.webDescPlaceholder`) as string}
|
|
|
/>
|
|
|
- <div className={`mt-8 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.privacyPolicy`)}</div>
|
|
|
- <p className={`mt-1 ${s.settingsTip} text-gray-500`}>
|
|
|
- <Trans
|
|
|
- i18nKey={`${prefixSettings}.more.privacyPolicyTip`}
|
|
|
- components={{ privacyPolicyLink: <Link href={'https://langgenius.ai/privacy-policy'} target='_blank' className='text-primary-600' /> }}
|
|
|
- />
|
|
|
- </p>
|
|
|
- <input className={`w-full mt-2 rounded-lg h-10 box-border px-3 ${s.projectName} bg-gray-100`}
|
|
|
- value={inputInfo.privacyPolicy}
|
|
|
- onChange={onChange('privacyPolicy')}
|
|
|
- placeholder={t(`${prefixSettings}.more.privacyPolicyPlaceholder`) as string}
|
|
|
+ <div className={`mt-6 mb-2 font-medium ${s.settingTitle} text-gray-900 `}>{t(`${prefixSettings}.language`)}</div>
|
|
|
+ <SimpleSelect
|
|
|
+ items={Object.keys(LANGUAGE_MAP).map(lang => ({ name: LANGUAGE_MAP[lang as Language], value: lang }))}
|
|
|
+ defaultValue={language}
|
|
|
+ onSelect={item => setLanguage(item.value as Language)}
|
|
|
/>
|
|
|
- </>}
|
|
|
- <div className='mt-10 flex justify-end'>
|
|
|
- <Button className='mr-2 flex-shrink-0' onClick={onHide}>{t('common.operation.cancel')}</Button>
|
|
|
- <Button type='primary' className='flex-shrink-0' onClick={onClickSave} loading={saveLoading}>{t('common.operation.save')}</Button>
|
|
|
- </div>
|
|
|
- </Modal >
|
|
|
+ {!isShowMore && <div className='w-full cursor-pointer mt-8' onClick={() => setIsShowMore(true)}>
|
|
|
+ <div className='flex justify-between'>
|
|
|
+ <div className={`font-medium ${s.settingTitle} flex-grow text-gray-900`}>{t(`${prefixSettings}.more.entry`)}</div>
|
|
|
+ <div className='flex-shrink-0 w-4 h-4 text-gray-500'>
|
|
|
+ <ChevronRightIcon />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <p className={`mt-1 ${s.policy} text-gray-500`}>{t(`${prefixSettings}.more.copyright`)} & {t(`${prefixSettings}.more.privacyPolicy`)}</p>
|
|
|
+ </div>}
|
|
|
+ {isShowMore && <>
|
|
|
+ <hr className='w-full mt-6' />
|
|
|
+ <div className={`mt-6 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.copyright`)}</div>
|
|
|
+ <input className={`w-full mt-2 rounded-lg h-10 box-border px-3 ${s.projectName} bg-gray-100`}
|
|
|
+ value={inputInfo.copyright}
|
|
|
+ onChange={onChange('copyright')}
|
|
|
+ placeholder={t(`${prefixSettings}.more.copyRightPlaceholder`) as string}
|
|
|
+ />
|
|
|
+ <div className={`mt-8 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.privacyPolicy`)}</div>
|
|
|
+ <p className={`mt-1 ${s.settingsTip} text-gray-500`}>
|
|
|
+ <Trans
|
|
|
+ i18nKey={`${prefixSettings}.more.privacyPolicyTip`}
|
|
|
+ components={{ privacyPolicyLink: <Link href={'https://langgenius.ai/privacy-policy'} target='_blank' className='text-primary-600' /> }}
|
|
|
+ />
|
|
|
+ </p>
|
|
|
+ <input className={`w-full mt-2 rounded-lg h-10 box-border px-3 ${s.projectName} bg-gray-100`}
|
|
|
+ value={inputInfo.privacyPolicy}
|
|
|
+ onChange={onChange('privacyPolicy')}
|
|
|
+ placeholder={t(`${prefixSettings}.more.privacyPolicyPlaceholder`) as string}
|
|
|
+ />
|
|
|
+ </>}
|
|
|
+ <div className='mt-10 flex justify-end'>
|
|
|
+ <Button className='mr-2 flex-shrink-0' onClick={onHide}>{t('common.operation.cancel')}</Button>
|
|
|
+ <Button type='primary' className='flex-shrink-0' onClick={onClickSave} loading={saveLoading}>{t('common.operation.save')}</Button>
|
|
|
+ </div>
|
|
|
+ </Modal >
|
|
|
+ </>
|
|
|
+
|
|
|
)
|
|
|
}
|
|
|
export default React.memo(SettingsModal)
|