'use client' import type { NavItem } from '../nav/nav-selector' import type { AppListQuery } from '@/contract/console/apps' import { RiRobot2Fill, RiRobot2Line, } from '@remixicon/react' import { keepPreviousData, useInfiniteQuery } from '@tanstack/react-query' import { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { useStore as useAppStore } from '@/app/components/app/store' import { useAppContext } from '@/context/app-context' import dynamic from '@/next/dynamic' import { useParams } from '@/next/navigation' import { consoleQuery } from '@/service/client' import { AppModeEnum } from '@/types/app' import Nav from '../nav' const CreateAppTemplateDialog = dynamic(() => import('@/app/components/app/create-app-dialog'), { ssr: false }) const CreateAppModal = dynamic(() => import('@/app/components/app/create-app-modal'), { ssr: false }) const CreateFromDSLModal = dynamic(() => import('@/app/components/app/create-from-dsl-modal'), { ssr: false }) const appNavListQuery = { page: 1, limit: 30, name: '', } satisfies AppListQuery const getAppLink = (isCurrentWorkspaceEditor: boolean, appId: string, appMode: AppModeEnum) => { if (!isCurrentWorkspaceEditor) return `/app/${appId}/overview` if (appMode === AppModeEnum.WORKFLOW || appMode === AppModeEnum.ADVANCED_CHAT) return `/app/${appId}/workflow` return `/app/${appId}/configuration` } const AppNav = () => { const { t } = useTranslation() const { appId } = useParams() const { isCurrentWorkspaceEditor } = useAppContext() const appDetail = useAppStore(state => state.appDetail) const [showNewAppDialog, setShowNewAppDialog] = useState(false) const [showNewAppTemplateDialog, setShowNewAppTemplateDialog] = useState(false) const [showCreateFromDSLModal, setShowCreateFromDSLModal] = useState(false) const { data: appsData, fetchNextPage, hasNextPage, isFetchingNextPage, refetch, } = useInfiniteQuery({ ...consoleQuery.apps.list.infiniteOptions({ input: pageParam => ({ query: { ...appNavListQuery, page: Number(pageParam), }, }), getNextPageParam: lastPage => lastPage.has_more ? lastPage.page + 1 : undefined, initialPageParam: 1, placeholderData: keepPreviousData, }), enabled: !!appId, }) const handleLoadMore = useCallback(() => { if (hasNextPage) fetchNextPage() }, [fetchNextPage, hasNextPage]) const openModal = (state: string) => { if (state === 'blank') setShowNewAppDialog(true) if (state === 'template') setShowNewAppTemplateDialog(true) if (state === 'dsl') setShowCreateFromDSLModal(true) } const navItems = useMemo(() => { const appItems = appsData?.pages.flatMap(appData => appData.data) ?? [] return appItems.map(app => ({ id: app.id, icon_type: app.icon_type, icon: app.icon, icon_background: app.icon_background, icon_url: app.icon_url, name: appDetail?.id === app.id ? appDetail.name : app.name, mode: app.mode, link: getAppLink(isCurrentWorkspaceEditor, app.id, app.mode), })) }, [appDetail?.id, appDetail?.name, appsData?.pages, isCurrentWorkspaceEditor]) return ( <>