mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
feat(boards list): add filter by tag
This commit is contained in:
@@ -136,6 +136,7 @@ const App = () => {
|
|||||||
<Routes>
|
<Routes>
|
||||||
<Route element={<GlobalLayout />}>
|
<Route element={<GlobalLayout />}>
|
||||||
<Route path='/' element={<Home />} />
|
<Route path='/' element={<Home />} />
|
||||||
|
<Route path='/:tag' element={<Home />} />
|
||||||
<Route path='/faq' element={<FAQ />} />
|
<Route path='/faq' element={<FAQ />} />
|
||||||
<Route path='*' element={<NotFound />} />
|
<Route path='*' element={<NotFound />} />
|
||||||
<Route element={<ValidateRouteParams />}>
|
<Route element={<ValidateRouteParams />}>
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ const SearchBar = ({ setShowSearchBar }: { setShowSearchBar: (show: boolean) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderBoardsList = (subplebbits: any, isInCatalogView: boolean, subscriptions: string[]) =>
|
const renderBoardsList = (subplebbits: any, isInCatalogView: boolean, subscriptions: string[]) =>
|
||||||
subplebbits.length > 0 && (
|
subplebbits?.length > 0 && (
|
||||||
<>
|
<>
|
||||||
[
|
[
|
||||||
{subplebbits.map((sub: any, index: any) => (
|
{subplebbits.map((sub: any, index: any) => (
|
||||||
@@ -77,11 +77,11 @@ const renderBoardsList = (subplebbits: any, isInCatalogView: boolean, subscripti
|
|||||||
<Link to={`/p/${sub.address}${isInCatalogView ? '/catalog' : ''}`}>
|
<Link to={`/p/${sub.address}${isInCatalogView ? '/catalog' : ''}`}>
|
||||||
{sub.address.endsWith('.eth') || sub.address.endsWith('.sol') ? sub.address : sub.address.slice(0, 10).concat('...')}
|
{sub.address.endsWith('.eth') || sub.address.endsWith('.sol') ? sub.address : sub.address.slice(0, 10).concat('...')}
|
||||||
</Link>
|
</Link>
|
||||||
{index !== subplebbits?.length - 1 ? ' /' : null}
|
{index !== subplebbits.length - 1 ? ' /' : null}
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
]{' '}
|
]{' '}
|
||||||
{subscriptions.length > 0 && (
|
{subscriptions?.length > 0 && (
|
||||||
<>
|
<>
|
||||||
[
|
[
|
||||||
{subscriptions.map((address: any, index: any) => (
|
{subscriptions.map((address: any, index: any) => (
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
// Add this helper function to collect unique tags from subplebbits
|
||||||
|
const getUniqueTags = (multisub: any) => {
|
||||||
|
const allTags = new Set<string>();
|
||||||
|
Object.values(multisub).forEach((sub: any) => {
|
||||||
|
if (sub?.tags?.length) {
|
||||||
|
sub.tags.forEach((tag: string) => allTags.add(tag));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Array.from(allTags).sort();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Export tags as a derived value where it's needed
|
||||||
|
export const useDefaultSubplebbitTags = (subplebbits: any) => {
|
||||||
|
return useMemo(() => getUniqueTags(subplebbits), [subplebbits]);
|
||||||
|
};
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
||||||
import { Subplebbit } from '@plebbit/plebbit-react-hooks';
|
import { Subplebbit } from '@plebbit/plebbit-react-hooks';
|
||||||
|
import { useDefaultSubplebbitTags } from '../../../hooks/use-default-subplebbits-tags';
|
||||||
import useIsSubplebbitOffline from '../../../hooks/use-is-subplebbit-offline';
|
import useIsSubplebbitOffline from '../../../hooks/use-is-subplebbit-offline';
|
||||||
import styles from '../home.module.css';
|
import styles from '../home.module.css';
|
||||||
import { nsfwTags } from '../home';
|
import { nsfwTags } from '../home';
|
||||||
import { useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
const Board = ({ subplebbit, subplebbits }: { subplebbit: Subplebbit; subplebbits: any; useCatalog?: boolean }) => {
|
const Board = ({ subplebbit }: { subplebbit: Subplebbit; useCatalog?: boolean }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { address, title, tags } = subplebbit || {};
|
const { address, title, tags } = subplebbit || {};
|
||||||
const nsfwTag = tags.find((tag: string) => nsfwTags.includes(tag));
|
const nsfwTag = tags?.find((tag: string) => nsfwTags.includes(tag));
|
||||||
|
|
||||||
const subplebbitData = subplebbits && subplebbits.find((sub: Subplebbit) => sub?.address === address);
|
const { isOffline, isOnlineStatusLoading, offlineIconClass, offlineTitle } = useIsSubplebbitOffline(subplebbit);
|
||||||
const { isOffline, isOnlineStatusLoading, offlineIconClass, offlineTitle } = useIsSubplebbitOffline(subplebbitData);
|
|
||||||
|
|
||||||
const displayAddress = address === 'all' ? 'all' : Plebbit.getShortAddress(address);
|
const displayAddress = address === 'all' ? 'all' : Plebbit.getShortAddress(address);
|
||||||
const showOfflineIcon = address !== 'all' && (isOffline || isOnlineStatusLoading);
|
const showOfflineIcon = address !== 'all' && (isOffline || isOnlineStatusLoading);
|
||||||
@@ -31,28 +31,41 @@ const Board = ({ subplebbit, subplebbits }: { subplebbit: Subplebbit; subplebbit
|
|||||||
<p className={styles.boardCell}>{title || displayAddress}</p>
|
<p className={styles.boardCell}>{title || displayAddress}</p>
|
||||||
</td>
|
</td>
|
||||||
<td className={styles.boardTags}>
|
<td className={styles.boardTags}>
|
||||||
<p className={styles.boardCell}>{tags.join(', ')}</p>
|
<p className={styles.boardCell}>
|
||||||
|
{tags.map((tag: string, index: number) => (
|
||||||
|
<>
|
||||||
|
{tag === 'multiboard' ? <span>{tag}</span> : <Link to={`/${tag}`}>{tag}</Link>}
|
||||||
|
{index < tags.length - 1 && ', '}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const BoardsList = ({ multisub, subplebbits }: { multisub: Subplebbit[]; subplebbits: any }) => {
|
const BoardsList = ({ multisub }: { multisub: Subplebbit[] }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const location = useLocation();
|
||||||
const [displayCount, setDisplayCount] = useState(15);
|
const [displayCount, setDisplayCount] = useState(15);
|
||||||
|
|
||||||
const handleLoadMore = () => {
|
const currentTag = location.pathname.split('/').filter(Boolean)[0];
|
||||||
setDisplayCount((prevCount) => prevCount + 15);
|
const tags = useDefaultSubplebbitTags(multisub);
|
||||||
};
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDisplayCount(15);
|
||||||
|
}, [currentTag]);
|
||||||
|
|
||||||
|
// First filter by tag, then limit by displayCount
|
||||||
|
const filteredBoards = (currentTag && tags.includes(currentTag) ? multisub.filter((sub) => sub?.tags?.includes(currentTag)) : multisub).slice(0, displayCount);
|
||||||
|
|
||||||
const visibleBoards = multisub.slice(0, displayCount);
|
|
||||||
const hasMoreBoards = displayCount < multisub.length;
|
const hasMoreBoards = displayCount < multisub.length;
|
||||||
|
|
||||||
const defaultBoard = {
|
const defaultBoard = {
|
||||||
address: 'all',
|
address: 'all',
|
||||||
title: 'Temporary Default Subplebbits',
|
title: 'Temporary Default Subplebbits',
|
||||||
tags: ['multiboard'],
|
tags: ['multiboard'],
|
||||||
};
|
} as Subplebbit;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.boardsBox}>
|
<div className={styles.boardsBox}>
|
||||||
@@ -69,15 +82,19 @@ const BoardsList = ({ multisub, subplebbits }: { multisub: Subplebbit[]; subpleb
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<Board key='all' subplebbit={defaultBoard} subplebbits={subplebbits} />
|
{!currentTag && <Board key='all' subplebbit={defaultBoard} />}
|
||||||
{visibleBoards.map((sub) => (
|
{filteredBoards.map((sub) => (
|
||||||
<Board key={sub.address} subplebbit={sub} subplebbits={subplebbits} />
|
<Board key={sub.address} subplebbit={sub} />
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<div className={styles.displayCount}>
|
||||||
|
displaying {filteredBoards.length} of {multisub.length} boards
|
||||||
|
{currentTag && tags.includes(currentTag) && ` tagged "${currentTag}"`}
|
||||||
|
</div>
|
||||||
{hasMoreBoards && (
|
{hasMoreBoards && (
|
||||||
<div className={styles.loadMoreButton}>
|
<div className={styles.loadMoreButton}>
|
||||||
[<span onClick={handleLoadMore}>{t('load_more')}</span>]
|
[<span onClick={() => setDisplayCount((prevCount) => prevCount + 15)}>{t('load_more')}</span>]
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -95,6 +95,12 @@
|
|||||||
color: var(--topbar-separator-color);
|
color: var(--topbar-separator-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.displayCount {
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.loadMoreButton span {
|
.loadMoreButton span {
|
||||||
color: var(--topbar-desktop-link-text-color);
|
color: var(--topbar-desktop-link-text-color);
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
@@ -122,7 +128,7 @@
|
|||||||
color: var(--homepage-box-bar-text-color);
|
color: var(--homepage-box-bar-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.boxBar h2, .infoboxBar h2{
|
.boxBar h2, .infoboxBar h2 {
|
||||||
font-size: 131%;
|
font-size: 131%;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ const Home = () => {
|
|||||||
<HomeLogo />
|
<HomeLogo />
|
||||||
<SearchBar />
|
<SearchBar />
|
||||||
<InfoBox />
|
<InfoBox />
|
||||||
<BoardsList multisub={defaultSubplebbits} subplebbits={subplebbits} />
|
<BoardsList multisub={defaultSubplebbits} />
|
||||||
<PopularThreadsBox multisub={defaultSubplebbits} subplebbits={subplebbits} />
|
<PopularThreadsBox multisub={defaultSubplebbits} subplebbits={subplebbits} />
|
||||||
<Stats subplebbitAddresses={subplebbitAddresses} />
|
<Stats subplebbitAddresses={subplebbitAddresses} />
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export { HomeLogo, Footer, default } from './home';
|
export { HomeLogo, Footer, nsfwTags, default } from './home';
|
||||||
|
|||||||
Reference in New Issue
Block a user