From b659e2a6e151b925e1f545d5d2a9c8df77d18572 Mon Sep 17 00:00:00 2001 From: zhaoying Date: Fri, 17 Apr 2026 13:36:19 +0800 Subject: [PATCH] feat(web): package tabs --- web/src/views/Package/index.tsx | 67 ++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/web/src/views/Package/index.tsx b/web/src/views/Package/index.tsx index b8e30593..b3aed9d5 100644 --- a/web/src/views/Package/index.tsx +++ b/web/src/views/Package/index.tsx @@ -105,39 +105,54 @@ const Package: FC = () => { }, []) const [activeTab, setActiveTab] = useState('saas_personal'); + + const categories = useMemo(() => { + const cats = [...new Set(data.map(p => p.category))] + return cats + }, [data]) + const formatTabItems = useMemo(() => { - return ['saas_personal', 'commercial_deployment'].map(value => ({ - value, - label: `${t(`package.${value}`)}`, - })) - }, [t, activeTab]) + return (['saas_personal', 'commercial_deployment'] as const) + .filter(v => categories.includes(v)) + .map(value => ({ value, label: t(`package.${value}`) })) + }, [t, categories]) + + const showTabs = categories.length > 1 const handleChangeTab = (value: SegmentedProps['value']) => { setActiveTab(value as string); } + const getList = () => { - getPackageList({ category: activeTab as Package['category'] }) - .then(res => { - setData(res as Package[] || []) - }) + getPackageList({ status: true }).then(res => { + setData(res as Package[] || []) + }) } useEffect(() => { getList() - }, [activeTab]) + }, []) + + useEffect(() => { + if (categories.length > 0 && !categories.includes(activeTab as Package['category'])) { + setActiveTab(categories[0]) + } + }, [categories]) const getKeyWithLanguage = (key: string) => { return (language === 'en' ? `${key}_en` : key) as keyof Package } + const filteredData = useMemo(() => data.filter(p => p.category === activeTab), [data, activeTab]) + const [currentPage, setCurrentPage] = useState(0) - const totalPages = visibleCount > 0 ? Math.ceil(data.length / visibleCount) : 1 + const totalPages = visibleCount > 0 ? Math.ceil(filteredData.length / visibleCount) : 1 const showArrows = totalPages > 1 - const pageData = data.slice(currentPage * visibleCount, (currentPage + 1) * visibleCount) + const pageData = filteredData.slice(currentPage * visibleCount, (currentPage + 1) * visibleCount) useEffect(() => { setCurrentPage(0) - }, [activeTab, visibleCount]) + }, [activeTab, visibleCount, filteredData]) const handleChoosePlan = () => { window.open(`https://docs.redbearai.com/s/${language || 'en'}-memorybear`, '_blank') @@ -145,14 +160,16 @@ const Package: FC = () => { return ( <> - - - - + {showTabs && ( + + + + )} +
{showArrows && ( { {/* Features */} - + {billingUnits.map(({ key, unit, icon }) => { const value = pkg?.quotas?.[key as keyof Package['quotas']]; if (value === undefined || value === null) return null; return (