'use client' import React, { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' import useSWR from 'swr' import { useDebounceFn } from 'ahooks' import s from './style.module.css' import cn from '@/utils/classnames' import ExploreContext from '@/context/explore-context' import type { App } from '@/models/explore' import Category from '@/app/components/explore/category' import AppCard from '@/app/components/explore/app-card' import { fetchAppDetail, fetchAppList } from '@/service/explore' import { useTabSearchParams } from '@/hooks/use-tab-searchparams' import CreateAppModal from '@/app/components/explore/create-app-modal' import type { CreateAppModalProps } from '@/app/components/explore/create-app-modal' import Loading from '@/app/components/base/loading' import Input from '@/app/components/base/input' import { DSLImportMode, } from '@/models/app' import { useImportDSL } from '@/hooks/use-import-dsl' import DSLConfirmModal from '@/app/components/app/create-from-dsl-modal/dsl-confirm-modal' type AppsProps = { onSuccess?: () => void } export enum PageType { EXPLORE = 'explore', CREATE = 'create', } const Apps = ({ onSuccess, }: AppsProps) => { const { t } = useTranslation() const { hasEditPermission } = useContext(ExploreContext) const allCategoriesEn = t('explore.apps.allCategories', { lng: 'en' }) const [keywords, setKeywords] = useState('') const [searchKeywords, setSearchKeywords] = useState('') const { run: handleSearch } = useDebounceFn(() => { setSearchKeywords(keywords) }, { wait: 500 }) const handleKeywordsChange = (value: string) => { setKeywords(value) handleSearch() } const [currentType, setCurrentType] = useState('') const [currCategory, setCurrCategory] = useTabSearchParams({ defaultTab: allCategoriesEn, disableSearchParams: false, }) const { data: { categories, allList }, } = useSWR( ['/explore/apps'], () => fetchAppList().then(({ categories, recommended_apps }) => ({ categories, allList: recommended_apps.sort((a, b) => a.position - b.position), })), { fallbackData: { categories: [], allList: [], }, }, ) const filteredList = useMemo(() => { if (currCategory === allCategoriesEn) { if (!currentType) return allList else if (currentType === 'chatbot') return allList.filter(item => (item.app.mode === 'chat' || item.app.mode === 'advanced-chat')) else if (currentType === 'agent') return allList.filter(item => (item.app.mode === 'agent-chat')) else return allList.filter(item => (item.app.mode === 'workflow')) } else { if (!currentType) return allList.filter(item => item.category === currCategory) else if (currentType === 'chatbot') return allList.filter(item => (item.app.mode === 'chat' || item.app.mode === 'advanced-chat') && item.category === currCategory) else if (currentType === 'agent') return allList.filter(item => (item.app.mode === 'agent-chat') && item.category === currCategory) else return allList.filter(item => (item.app.mode === 'workflow') && item.category === currCategory) } }, [currentType, currCategory, allCategoriesEn, allList]) const searchFilteredList = useMemo(() => { if (!searchKeywords || !filteredList || filteredList.length === 0) return filteredList const lowerCaseSearchKeywords = searchKeywords.toLowerCase() return filteredList.filter(item => item.app && item.app.name && item.app.name.toLowerCase().includes(lowerCaseSearchKeywords), ) }, [searchKeywords, filteredList]) const [currApp, setCurrApp] = React.useState(null) const [isShowCreateModal, setIsShowCreateModal] = React.useState(false) const { handleImportDSL, handleImportDSLConfirm, versions, isFetching, } = useImportDSL() const [showDSLConfirmModal, setShowDSLConfirmModal] = useState(false) const onCreate: CreateAppModalProps['onConfirm'] = async ({ name, icon_type, icon, icon_background, description, }) => { const { export_data } = await fetchAppDetail( currApp?.app.id as string, ) const payload = { mode: DSLImportMode.YAML_CONTENT, yaml_content: export_data, name, icon_type, icon, icon_background, description, } await handleImportDSL(payload, { onSuccess: () => { setIsShowCreateModal(false) }, onPending: () => { setShowDSLConfirmModal(true) }, }) } const onConfirmDSL = useCallback(async () => { await handleImportDSLConfirm({ onSuccess, }) }, [handleImportDSLConfirm, onSuccess]) if (!categories || categories.length === 0) { return (
) } return (
{t('explore.apps.title')}
{t('explore.apps.description')}
<> handleKeywordsChange(e.target.value)} onClear={() => handleKeywordsChange('')} />
{isShowCreateModal && ( setIsShowCreateModal(false)} /> )} { showDSLConfirmModal && ( setShowDSLConfirmModal(false)} onConfirm={onConfirmDSL} confirmDisabled={isFetching} /> ) }
) } export default React.memo(Apps)