mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-23 16:05:24 +00:00
Added search to feeds
This commit is contained in:
parent
185c96bf9b
commit
fd7b7567fe
src
@ -6,8 +6,9 @@ import { Button } from 'primereact/button';
|
||||
import { ProgressSpinner } from 'primereact/progressspinner';
|
||||
import { useDiscordQuery } from '@/hooks/communityQueries/useDiscordQuery';
|
||||
import { useRouter } from 'next/router';
|
||||
import { highlightText } from '@/utils/text';
|
||||
|
||||
const DiscordFeed = () => {
|
||||
const DiscordFeed = ({ searchQuery }) => {
|
||||
const router = useRouter();
|
||||
const { data, error, isLoading } = useDiscordQuery({page: router.query.page});
|
||||
|
||||
@ -54,18 +55,22 @@ const DiscordFeed = () => {
|
||||
</div>
|
||||
);
|
||||
|
||||
const filteredData = data.filter(message =>
|
||||
message.content.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="bg-gray-900 h-full w-full min-bottom-bar:w-[86vw]">
|
||||
<div className="mx-4 mt-4">
|
||||
{data && data.length > 0 ? (
|
||||
data.map(message => (
|
||||
{filteredData && filteredData.length > 0 ? (
|
||||
filteredData.map(message => (
|
||||
<Card
|
||||
key={message.id}
|
||||
header={() => header(message)}
|
||||
footer={() => footer(message)}
|
||||
className="w-full bg-gray-700 shadow-lg hover:shadow-xl transition-shadow duration-300 mb-4"
|
||||
>
|
||||
<p className="m-0 text-lg text-gray-200">{message.content}</p>
|
||||
<p className="m-0 text-lg text-gray-200">{highlightText(message.content, searchQuery)}</p>
|
||||
</Card>
|
||||
))
|
||||
) : (
|
||||
|
@ -14,6 +14,7 @@ import { findKind0Fields } from '@/utils/nostr';
|
||||
import NostrIcon from '../../../public/images/nostr.png';
|
||||
import Image from 'next/image';
|
||||
import { useImageProxy } from '@/hooks/useImageProxy';
|
||||
import { highlightText } from '@/utils/text';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
|
||||
const StackerNewsIconComponent = () => (
|
||||
@ -28,7 +29,7 @@ const fetchStackerNews = async () => {
|
||||
return response.data.data.items.items;
|
||||
};
|
||||
|
||||
const GlobalFeed = () => {
|
||||
const GlobalFeed = ({searchQuery}) => {
|
||||
const router = useRouter();
|
||||
const { data: discordData, error: discordError, isLoading: discordLoading } = useDiscordQuery({page: router.query.page});
|
||||
const { data: stackerNewsData, error: stackerNewsError, isLoading: stackerNewsLoading } = useQuery({queryKey: ['stackerNews'], queryFn: fetchStackerNews});
|
||||
@ -109,6 +110,14 @@ const GlobalFeed = () => {
|
||||
const dateA = a.type === 'nostr' ? a.created_at * 1000 : new Date(a.timestamp || a.createdAt);
|
||||
const dateB = b.type === 'nostr' ? b.created_at * 1000 : new Date(b.timestamp || b.createdAt);
|
||||
return dateB - dateA;
|
||||
}).filter(item => {
|
||||
const searchLower = searchQuery.toLowerCase();
|
||||
if (item.type === 'discord' || item.type === 'nostr') {
|
||||
return item.content.toLowerCase().includes(searchLower);
|
||||
} else if (item.type === 'stackernews') {
|
||||
return item.title.toLowerCase().includes(searchLower);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const header = (item) => (
|
||||
@ -192,10 +201,14 @@ const GlobalFeed = () => {
|
||||
className="w-full bg-gray-700 shadow-lg hover:shadow-xl transition-shadow duration-300 mb-4"
|
||||
>
|
||||
{item.type === 'discord' || item.type === 'nostr' ? (
|
||||
<p className="m-0 text-lg text-gray-200 overflow-hidden break-words">{item.content}</p>
|
||||
<p className="m-0 text-lg text-gray-200 overflow-hidden break-words">
|
||||
{highlightText(item.content, searchQuery)}
|
||||
</p>
|
||||
) : (
|
||||
<>
|
||||
<h3 className="m-0 text-lg text-gray-200">{item.title}</h3>
|
||||
<h3 className="m-0 text-lg text-gray-200">
|
||||
{highlightText(item.title, searchQuery)}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-400">
|
||||
Comments: {item.comments.length} | Sats: {item.sats}
|
||||
</p>
|
||||
@ -204,7 +217,9 @@ const GlobalFeed = () => {
|
||||
</Card>
|
||||
))
|
||||
) : (
|
||||
<div className="text-gray-400 text-center p-4">No items available.</div>
|
||||
<div className="text-gray-400 text-center p-4">
|
||||
{searchQuery ? "No matching items found." : "No items available."}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,9 +12,10 @@ import Image from 'next/image';
|
||||
import { useImageProxy } from '@/hooks/useImageProxy';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { useCommunityNotes } from '@/hooks/nostr/useCommunityNotes';
|
||||
import { highlightText } from '@/utils/text';
|
||||
import ZapThreadsWrapper from '@/components/ZapThreadsWrapper';
|
||||
|
||||
const NostrFeed = () => {
|
||||
const NostrFeed = ({ searchQuery }) => {
|
||||
const { communityNotes, isLoading, error } = useCommunityNotes();
|
||||
const { ndk } = useNDKContext();
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
@ -134,18 +135,24 @@ const NostrFeed = () => {
|
||||
return <div className="text-red-500 text-center p-4">Failed to load messages. Please try again later.</div>;
|
||||
}
|
||||
|
||||
const filteredNotes = communityNotes.filter(message =>
|
||||
message.content.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="bg-gray-900 h-full w-full min-bottom-bar:w-[86vw]">
|
||||
<div className="mx-4 mt-4">
|
||||
{communityNotes.length > 0 ? (
|
||||
communityNotes.map(message => (
|
||||
{filteredNotes.length > 0 ? (
|
||||
filteredNotes.map(message => (
|
||||
<Card
|
||||
key={message.id}
|
||||
header={renderHeader(message)}
|
||||
footer={() => footer(message)}
|
||||
className="w-full bg-gray-700 shadow-lg hover:shadow-xl transition-shadow duration-300 mb-4"
|
||||
>
|
||||
<p className="m-0 text-lg text-gray-200 overflow-hidden break-words">{message.content}</p>
|
||||
<p className="m-0 text-lg text-gray-200 overflow-hidden break-words">
|
||||
{highlightText(message.content, searchQuery)}
|
||||
</p>
|
||||
</Card>
|
||||
))
|
||||
) : (
|
||||
|
@ -5,6 +5,7 @@ import { Tag } from 'primereact/tag';
|
||||
import { Button } from 'primereact/button';
|
||||
import { ProgressSpinner } from 'primereact/progressspinner';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { highlightText } from '@/utils/text';
|
||||
import axios from 'axios';
|
||||
|
||||
const StackerNewsIconComponent = () => (
|
||||
@ -19,7 +20,7 @@ const fetchStackerNews = async () => {
|
||||
return response.data.data.items.items; // Note the change here
|
||||
};
|
||||
|
||||
const StackerNewsFeed = () => {
|
||||
const StackerNewsFeed = ({ searchQuery }) => {
|
||||
const { data: items, isLoading, error } = useQuery({queryKey: ['stackerNews'], queryFn: fetchStackerNews});
|
||||
|
||||
useEffect(() => {
|
||||
@ -71,18 +72,22 @@ const StackerNewsFeed = () => {
|
||||
</div>
|
||||
);
|
||||
|
||||
const filteredItems = items.filter(item =>
|
||||
item.title.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="bg-gray-900 h-full w-full min-bottom-bar:w-[86vw]">
|
||||
<div className="mx-4 mt-4">
|
||||
{items && items.length > 0 ? (
|
||||
items.map(item => (
|
||||
{filteredItems && filteredItems.length > 0 ? (
|
||||
filteredItems.map(item => (
|
||||
<Card
|
||||
key={item.id}
|
||||
header={() => header(item)}
|
||||
footer={() => footer(item)}
|
||||
className="w-full bg-gray-700 shadow-lg hover:shadow-xl transition-shadow duration-300 mb-4"
|
||||
>
|
||||
<h3 className="m-0 text-lg text-gray-200">{item.title}</h3>
|
||||
<h3 className="m-0 text-lg text-gray-200">{highlightText(item.title, searchQuery)}</h3>
|
||||
<p className="text-sm text-gray-400">
|
||||
Comments: {item.comments.length} | Sats: {item.sats}
|
||||
</p>
|
||||
|
@ -15,9 +15,9 @@ import { Divider } from 'primereact/divider';
|
||||
|
||||
const Feed = () => {
|
||||
const [selectedTopic, setSelectedTopic] = useState('global');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [title, setTitle] = useState('Community');
|
||||
const allTopics = ['global', 'nostr', 'discord', 'stackernews'];
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@ -96,16 +96,16 @@ const Feed = () => {
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
selectedTopic === 'global' && <GlobalFeed />
|
||||
selectedTopic === 'global' && <GlobalFeed searchQuery={searchQuery} />
|
||||
}
|
||||
{
|
||||
selectedTopic === 'nostr' && <NostrFeed />
|
||||
selectedTopic === 'nostr' && <NostrFeed searchQuery={searchQuery} />
|
||||
}
|
||||
{
|
||||
selectedTopic === 'discord' && <DiscordFeed />
|
||||
selectedTopic === 'discord' && <DiscordFeed searchQuery={searchQuery} />
|
||||
}
|
||||
{
|
||||
selectedTopic === 'stackernews' && <StackerNewsFeed />
|
||||
selectedTopic === 'stackernews' && <StackerNewsFeed searchQuery={searchQuery} />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
9
src/utils/text.js
Normal file
9
src/utils/text.js
Normal file
@ -0,0 +1,9 @@
|
||||
export const highlightText = (text, query) => {
|
||||
if (!query) return text;
|
||||
const parts = text.split(new RegExp(`(${query})`, 'gi'));
|
||||
return parts.map((part, index) =>
|
||||
part.toLowerCase() === query.toLowerCase()
|
||||
? <span key={index} className="bg-yellow-300 text-black">{part}</span>
|
||||
: part
|
||||
);
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user