From e2411ab4ee943f343f5f2397d12bf886afeade41 Mon Sep 17 00:00:00 2001 From: Joel Date: Sat, 9 May 2026 17:25:59 +0800 Subject: [PATCH] feat: continue work --- .../explore/app-list/__tests__/index.spec.tsx | 23 ++++++ web/app/components/explore/app-list/index.tsx | 2 + .../components/explore/continue-work/data.ts | 61 ++++++++++++++++ .../explore/continue-work/index.tsx | 71 +++++++++++++++++++ web/i18n/en-US/explore.json | 3 + web/i18n/zh-Hans/explore.json | 3 + 6 files changed, 163 insertions(+) create mode 100644 web/app/components/explore/continue-work/data.ts create mode 100644 web/app/components/explore/continue-work/index.tsx diff --git a/web/app/components/explore/app-list/__tests__/index.spec.tsx b/web/app/components/explore/app-list/__tests__/index.spec.tsx index 7b5c02be4c..47542c4e42 100644 --- a/web/app/components/explore/app-list/__tests__/index.spec.tsx +++ b/web/app/components/explore/app-list/__tests__/index.spec.tsx @@ -47,6 +47,13 @@ vi.mock('@/hooks/use-import-dsl', () => ({ isFetching: false, }), })) + +vi.mock('@/hooks/use-format-time-from-now', () => ({ + useFormatTimeFromNow: () => ({ + formatTimeFromNow: () => '3 minutes ago', + }), +})) + vi.mock('@/utils/create-app-tracking', () => ({ trackCreateApp: (...args: unknown[]) => mockTrackCreateApp(...args), })) @@ -193,6 +200,22 @@ describe('AppList', () => { expect(screen.getByText('Alpha')).toBeInTheDocument() expect(screen.getByText('Beta')).toBeInTheDocument() }) + + it('should render continue work placeholders', () => { + mockExploreData = { + categories: ['Writing'], + allList: [createApp()], + } + + renderAppList() + + expect(screen.getByRole('heading', { name: 'explore.continueWork.title' })).toBeInTheDocument() + expect(screen.getByText('Automated Email Reply')).toBeInTheDocument() + expect(screen.getByText('Customer Feedback Summary')).toBeInTheDocument() + expect(screen.getAllByText('Evan')).toHaveLength(5) + expect(screen.getAllByText('explore.continueWork.editedAt:{"time":"3 minutes ago"}')).toHaveLength(5) + expect(screen.getByRole('link', { name: 'explore.continueWork.exploreStudio' })).toHaveAttribute('href', '/apps') + }) }) describe('Props', () => { diff --git a/web/app/components/explore/app-list/index.tsx b/web/app/components/explore/app-list/index.tsx index 86a0bbc6c0..958c4459a1 100644 --- a/web/app/components/explore/app-list/index.tsx +++ b/web/app/components/explore/app-list/index.tsx @@ -17,6 +17,7 @@ import Loading from '@/app/components/base/loading' import AppCard from '@/app/components/explore/app-card' import Banner from '@/app/components/explore/banner/banner' import Category from '@/app/components/explore/category' +import ContinueWork from '@/app/components/explore/continue-work' import CreateAppModal from '@/app/components/explore/create-app-modal' import { useAppContext } from '@/context/app-context' import { useImportDSL } from '@/hooks/use-import-dsl' @@ -191,6 +192,7 @@ const Apps = ({ )} +
{ + const { t } = useTranslation() + const { formatTimeFromNow } = useFormatTimeFromNow() + + return ( +
+
+

+ {t('continueWork.title', { ns: 'explore' })} +

+ + {t('continueWork.exploreStudio', { ns: 'explore' })} + +
+
+ {continueWorkItems.map(item => ( +
+
+
+ {item.emoji} +
+ +
+
+

+ {item.title} +

+
+ {item.author} + · + {t('continueWork.editedAt', { ns: 'explore', time: formatTimeFromNow(item.updatedAt) })} +
+
+
+ ))} +
+
+ ) +} + +export default React.memo(ContinueWork) diff --git a/web/i18n/en-US/explore.json b/web/i18n/en-US/explore.json index 2293c8b8a7..3b17980a35 100644 --- a/web/i18n/en-US/explore.json +++ b/web/i18n/en-US/explore.json @@ -20,6 +20,9 @@ "category.Translate": "Translate", "category.Workflow": "Workflow", "category.Writing": "Writing", + "continueWork.editedAt": "Edited {{time}}", + "continueWork.exploreStudio": "Explore Studio →", + "continueWork.title": "Continue work with", "sidebar.action.delete": "Delete", "sidebar.action.pin": "Pin", "sidebar.action.rename": "Rename", diff --git a/web/i18n/zh-Hans/explore.json b/web/i18n/zh-Hans/explore.json index 3ef3bfa589..2e8aaf5d1c 100644 --- a/web/i18n/zh-Hans/explore.json +++ b/web/i18n/zh-Hans/explore.json @@ -20,6 +20,9 @@ "category.Translate": "翻译", "category.Workflow": "工作流", "category.Writing": "写作", + "continueWork.editedAt": "{{time}}编辑", + "continueWork.exploreStudio": "探索工作室 →", + "continueWork.title": "继续处理", "sidebar.action.delete": "删除", "sidebar.action.pin": "置顶", "sidebar.action.rename": "重命名",