feat: marketplace list more link

This commit is contained in:
zxhlyh 2024-12-16 17:38:40 +08:00
parent 4f8cdabef0
commit 672843dcab
6 changed files with 59 additions and 9 deletions

View File

@ -24,6 +24,7 @@ import type {
MarketplaceCollection, MarketplaceCollection,
PluginsSort, PluginsSort,
SearchParams, SearchParams,
SearchParamsFromCollection,
} from './types' } from './types'
import { DEFAULT_SORT } from './constants' import { DEFAULT_SORT } from './constants'
import { import {
@ -49,10 +50,12 @@ export type MarketplaceContextValue = {
page: number page: number
handlePageChange: (page: number) => void handlePageChange: (page: number) => void
plugins?: Plugin[] plugins?: Plugin[]
pluginsTotal?: number
resetPlugins: () => void resetPlugins: () => void
sort: PluginsSort sort: PluginsSort
handleSortChange: (sort: PluginsSort) => void handleSortChange: (sort: PluginsSort) => void
handleQueryPlugins: () => void handleQueryPlugins: () => void
handleMoreClick: (searchParams: SearchParamsFromCollection) => void
marketplaceCollectionsFromClient?: MarketplaceCollection[] marketplaceCollectionsFromClient?: MarketplaceCollection[]
setMarketplaceCollectionsFromClient: (collections: MarketplaceCollection[]) => void setMarketplaceCollectionsFromClient: (collections: MarketplaceCollection[]) => void
marketplaceCollectionPluginsMapFromClient?: Record<string, Plugin[]> marketplaceCollectionPluginsMapFromClient?: Record<string, Plugin[]>
@ -73,10 +76,12 @@ export const MarketplaceContext = createContext<MarketplaceContextValue>({
page: 1, page: 1,
handlePageChange: () => {}, handlePageChange: () => {},
plugins: undefined, plugins: undefined,
pluginsTotal: 0,
resetPlugins: () => {}, resetPlugins: () => {},
sort: DEFAULT_SORT, sort: DEFAULT_SORT,
handleSortChange: () => {}, handleSortChange: () => {},
handleQueryPlugins: () => {}, handleQueryPlugins: () => {},
handleMoreClick: () => {},
marketplaceCollectionsFromClient: [], marketplaceCollectionsFromClient: [],
setMarketplaceCollectionsFromClient: () => {}, setMarketplaceCollectionsFromClient: () => {},
marketplaceCollectionPluginsMapFromClient: {}, marketplaceCollectionPluginsMapFromClient: {},
@ -248,7 +253,7 @@ export const MarketplaceContextProvider = ({
}, [handleQueryPlugins]) }, [handleQueryPlugins])
const handlePageChange = useCallback(() => { const handlePageChange = useCallback(() => {
if (pluginsTotal && plugins && pluginsTotal > plugins.length && (!!searchPluginTextRef.current || !!filterPluginTagsRef.current.length)) { if (pluginsTotal && plugins && pluginsTotal > plugins.length) {
setPage(pageRef.current + 1) setPage(pageRef.current + 1)
pageRef.current++ pageRef.current++
@ -256,6 +261,23 @@ export const MarketplaceContextProvider = ({
} }
}, [handleQueryPlugins, plugins, pluginsTotal]) }, [handleQueryPlugins, plugins, pluginsTotal])
const handleMoreClick = useCallback((searchParams: SearchParamsFromCollection) => {
setSearchPluginText(searchParams?.query || '')
searchPluginTextRef.current = searchParams?.query || ''
setSort({
sortBy: searchParams?.sort_by || DEFAULT_SORT.sortBy,
sortOrder: searchParams?.sort_order || DEFAULT_SORT.sortOrder,
})
sortRef.current = {
sortBy: searchParams?.sort_by || DEFAULT_SORT.sortBy,
sortOrder: searchParams?.sort_order || DEFAULT_SORT.sortOrder,
}
setPage(1)
pageRef.current = 1
handleQueryPlugins()
}, [handleQueryPlugins])
useMarketplaceContainerScroll(handlePageChange, scrollContainerId) useMarketplaceContainerScroll(handlePageChange, scrollContainerId)
return ( return (
@ -272,10 +294,12 @@ export const MarketplaceContextProvider = ({
page, page,
handlePageChange, handlePageChange,
plugins, plugins,
pluginsTotal,
resetPlugins, resetPlugins,
sort, sort,
handleSortChange, handleSortChange,
handleQueryPlugins, handleQueryPlugins,
handleMoreClick,
marketplaceCollectionsFromClient, marketplaceCollectionsFromClient,
setMarketplaceCollectionsFromClient, setMarketplaceCollectionsFromClient,
marketplaceCollectionPluginsMapFromClient, marketplaceCollectionPluginsMapFromClient,

View File

@ -1,9 +1,13 @@
'use client' 'use client'
import { useTranslation } from 'react-i18next'
import { RiArrowRightSLine } from '@remixicon/react'
import type { MarketplaceCollection } from '../types' import type { MarketplaceCollection } from '../types'
import CardWrapper from './card-wrapper' import CardWrapper from './card-wrapper'
import type { Plugin } from '@/app/components/plugins/types' import type { Plugin } from '@/app/components/plugins/types'
import { getLanguage } from '@/i18n/language' import { getLanguage } from '@/i18n/language'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import type { SearchParamsFromCollection } from '@/app/components/plugins/marketplace/types'
type ListWithCollectionProps = { type ListWithCollectionProps = {
marketplaceCollections: MarketplaceCollection[] marketplaceCollections: MarketplaceCollection[]
@ -12,7 +16,7 @@ type ListWithCollectionProps = {
locale: string locale: string
cardContainerClassName?: string cardContainerClassName?: string
cardRender?: (plugin: Plugin) => JSX.Element | null cardRender?: (plugin: Plugin) => JSX.Element | null
onMoreClick?: () => void onMoreClick?: (searchParams?: SearchParamsFromCollection) => void
} }
const ListWithCollection = ({ const ListWithCollection = ({
marketplaceCollections, marketplaceCollections,
@ -21,8 +25,10 @@ const ListWithCollection = ({
locale, locale,
cardContainerClassName, cardContainerClassName,
cardRender, cardRender,
// onMoreClick, onMoreClick,
}: ListWithCollectionProps) => { }: ListWithCollectionProps) => {
const { t } = useTranslation()
return ( return (
<> <>
{ {
@ -31,15 +37,22 @@ const ListWithCollection = ({
key={collection.name} key={collection.name}
className='py-3' className='py-3'
> >
<div className='flex justify-between'> <div className='flex justify-between items-end'>
<div> <div>
<div className='title-xl-semi-bold text-text-primary'>{collection.label[getLanguage(locale)]}</div> <div className='title-xl-semi-bold text-text-primary'>{collection.label[getLanguage(locale)]}</div>
<div className='system-xs-regular text-text-tertiary'>{collection.description[getLanguage(locale)]}</div> <div className='system-xs-regular text-text-tertiary'>{collection.description[getLanguage(locale)]}</div>
</div> </div>
{/* <div {
className='system-xs-regular text-text-tertiary cursor-pointer hover:underline' collection.searchable && onMoreClick && (
onClick={() => onMoreClick?.()} <div
>more</div> */} className='flex items-center system-xs-medium text-text-accent cursor-pointer '
onClick={() => onMoreClick?.(collection.search_params)}
>
{t('plugin.marketplace.viewMore')}
<RiArrowRightSLine className='w-4 h-4' />
</div>
)
}
</div> </div>
<div className={cn( <div className={cn(
'grid grid-cols-4 gap-3 mt-2', 'grid grid-cols-4 gap-3 mt-2',

View File

@ -22,12 +22,14 @@ const ListWrapper = ({
}: ListWrapperProps) => { }: ListWrapperProps) => {
const { t } = useTranslation() const { t } = useTranslation()
const plugins = useMarketplaceContext(v => v.plugins) const plugins = useMarketplaceContext(v => v.plugins)
const pluginsTotal = useMarketplaceContext(v => v.pluginsTotal)
const marketplaceCollectionsFromClient = useMarketplaceContext(v => v.marketplaceCollectionsFromClient) const marketplaceCollectionsFromClient = useMarketplaceContext(v => v.marketplaceCollectionsFromClient)
const marketplaceCollectionPluginsMapFromClient = useMarketplaceContext(v => v.marketplaceCollectionPluginsMapFromClient) const marketplaceCollectionPluginsMapFromClient = useMarketplaceContext(v => v.marketplaceCollectionPluginsMapFromClient)
const isLoading = useMarketplaceContext(v => v.isLoading) const isLoading = useMarketplaceContext(v => v.isLoading)
const isSuccessCollections = useMarketplaceContext(v => v.isSuccessCollections) const isSuccessCollections = useMarketplaceContext(v => v.isSuccessCollections)
const handleQueryPlugins = useMarketplaceContext(v => v.handleQueryPlugins) const handleQueryPlugins = useMarketplaceContext(v => v.handleQueryPlugins)
const page = useMarketplaceContext(v => v.page) const page = useMarketplaceContext(v => v.page)
const handleMoreClick = useMarketplaceContext(v => v.handleMoreClick)
useEffect(() => { useEffect(() => {
if (!marketplaceCollectionsFromClient?.length && isSuccessCollections) if (!marketplaceCollectionsFromClient?.length && isSuccessCollections)
@ -39,7 +41,7 @@ const ListWrapper = ({
{ {
plugins && ( plugins && (
<div className='top-5 flex items-center mb-4 pt-3'> <div className='top-5 flex items-center mb-4 pt-3'>
<div className='title-xl-semi-bold text-text-primary'>{t('plugin.marketplace.pluginsResult', { num: plugins.length })}</div> <div className='title-xl-semi-bold text-text-primary'>{t('plugin.marketplace.pluginsResult', { num: pluginsTotal })}</div>
<div className='mx-3 w-[1px] h-3.5 bg-divider-regular'></div> <div className='mx-3 w-[1px] h-3.5 bg-divider-regular'></div>
<SortDropdown /> <SortDropdown />
</div> </div>
@ -60,6 +62,7 @@ const ListWrapper = ({
plugins={plugins} plugins={plugins}
showInstallButton={showInstallButton} showInstallButton={showInstallButton}
locale={locale} locale={locale}
onMoreClick={handleMoreClick}
/> />
) )
} }

View File

@ -1,5 +1,11 @@
import type { Plugin } from '../types' import type { Plugin } from '../types'
export type SearchParamsFromCollection = {
query?: string
sort_by?: string
sort_order?: string
}
export type MarketplaceCollection = { export type MarketplaceCollection = {
name: string name: string
label: Record<string, string> label: Record<string, string>
@ -7,6 +13,8 @@ export type MarketplaceCollection = {
rule: string rule: string
created_at: string created_at: string
updated_at: string updated_at: string
searchable?: boolean
search_params?: SearchParamsFromCollection
} }
export type MarketplaceCollectionsResponse = { export type MarketplaceCollectionsResponse = {

View File

@ -161,6 +161,7 @@ const translation = {
newlyReleased: 'Newly Released', newlyReleased: 'Newly Released',
firstReleased: 'First Released', firstReleased: 'First Released',
}, },
viewMore: 'View more',
}, },
task: { task: {
installing: 'Installing {{installingLength}} plugins, 0 done.', installing: 'Installing {{installingLength}} plugins, 0 done.',

View File

@ -161,6 +161,7 @@ const translation = {
newlyReleased: '最新发布', newlyReleased: '最新发布',
firstReleased: '首次发布', firstReleased: '首次发布',
}, },
viewMore: '查看更多',
}, },
task: { task: {
installing: '{{installingLength}} 个插件安装中0 已完成', installing: '{{installingLength}} 个插件安装中0 已完成',