feat: enhance FlatList component to support localized empty states for templates

This commit is contained in:
yessenia 2026-02-14 03:27:43 +08:00
parent 0645eaeef9
commit efb35a97a1
3 changed files with 41 additions and 8 deletions

View File

@ -2,6 +2,7 @@
import type { Template } from '../types'
import type { Plugin } from '@/app/components/plugins/types'
import { useTranslation } from '#i18n'
import Empty from '../empty'
import CardWrapper from './card-wrapper'
import { GRID_CLASS } from './collection-constants'
@ -21,11 +22,17 @@ type TemplatesVariant = {
type FlatListProps = PluginsVariant | TemplatesVariant
const FlatList = (props: FlatListProps) => {
if (!props.items.length)
return <Empty />
const { items, variant } = props
const { t } = useTranslation()
if (props.variant === 'plugins') {
const { items, showInstallButton } = props
if (!items.length) {
if (variant === 'templates')
return <Empty text={t('marketplace.noTemplateFound', { ns: 'plugin' })} />
return <Empty />
}
if (variant === 'plugins') {
const { showInstallButton } = props
return (
<div className={GRID_CLASS}>
{items.map(plugin => (
@ -39,7 +46,6 @@ const FlatList = (props: FlatListProps) => {
)
}
const { items } = props
return (
<div className={GRID_CLASS}>
{items.map(template => (

View File

@ -21,6 +21,7 @@ vi.mock('#i18n', () => ({
'plugin.marketplace.viewMore': 'View More',
'plugin.marketplace.pluginsResult': `${options?.num || 0} plugins found`,
'plugin.marketplace.noPluginFound': 'No plugins found',
'plugin.marketplace.noTemplateFound': 'No template found',
'plugin.detailPanel.operation.install': 'Install',
'plugin.detailPanel.operation.detail': 'Detail',
}
@ -164,9 +165,9 @@ vi.mock('../sort-dropdown', () => ({
// Mock Empty component
vi.mock('../empty', () => ({
default: ({ className }: { className?: string }) => (
default: ({ className, text }: { className?: string, text?: string }) => (
<div data-testid="empty-component" className={className}>
No plugins found
{text || 'No plugins found'}
</div>
),
}))
@ -910,6 +911,32 @@ describe('ListWrapper', () => {
expect(screen.queryByTestId('loading-component')).not.toBeInTheDocument()
})
it('should render template empty state with flex content wrapper when templates are empty', () => {
delete (mockMarketplaceData as Record<string, unknown>).pluginCollections
delete (mockMarketplaceData as Record<string, unknown>).pluginCollectionPluginsMap
;(mockMarketplaceData as Record<string, unknown>).templateCollections = []
;(mockMarketplaceData as Record<string, unknown>).templateCollectionTemplatesMap = {}
;(mockMarketplaceData as Record<string, unknown>).templates = []
const { container } = render(<ListWrapper />)
expect(screen.getByTestId('empty-component')).toBeInTheDocument()
expect(screen.getByText('No template found')).toBeInTheDocument()
expect(container.querySelector('.relative.flex.grow.flex-col')).toBeInTheDocument()
})
it('should keep plugin empty text when plugins are empty', () => {
mockMarketplaceData.plugins = []
mockMarketplaceData.pluginsTotal = 0
mockMarketplaceData.pluginCollections = []
mockMarketplaceData.pluginCollectionPluginsMap = {}
render(<ListWrapper />)
expect(screen.getByTestId('empty-component')).toBeInTheDocument()
expect(screen.getByText('No plugins found')).toBeInTheDocument()
})
})
// ================================

View File

@ -56,7 +56,7 @@ const ListWrapper = ({ showInstallButton }: ListWrapperProps) => {
className="relative flex grow flex-col bg-background-default-subtle px-12 pt-2"
>
{isSearchMode && <ListTopInfo />}
<div className="relative grow">
<div className="relative flex grow flex-col">
{isLoading && page === 1 && (
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2">
<Loading />