Skip to content

Commit

Permalink
Merge pull request #6 from mrswastik-robot/redux
Browse files Browse the repository at this point in the history
algoliasearch through Navbar using Redux
  • Loading branch information
mrswastik-robot authored Mar 6, 2024
2 parents a09926a + 4581469 commit f52058f
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 142 deletions.
23 changes: 13 additions & 10 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "./globals.css";
import { cn } from "@/lib/utils";
import Navbar from "@/components/Navbar";
import Providers from "@/components/ThemeProvider";
import { StoreProvider } from "@/store/StoreProvider";

const inter = Inter({ subsets: ["latin"] });

Expand All @@ -18,15 +19,17 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={cn(inter.className, "antialiased min-h-screen pt-12 bg-[#F1F2F2] dark:bg-[#181818]")}>
<Providers>
<Navbar />
<div className="container max-w-7xl mx-auto h-full pt-12 ">
{children}
</div>
</Providers>
</body>
</html>
<StoreProvider>
<html lang="en">
<body className={cn(inter.className, "antialiased min-h-screen pt-12 bg-[#F1F2F2] dark:bg-[#181818]")}>
<Providers>
<Navbar />
<div className="container max-w-7xl mx-auto h-full pt-12 ">
{children}
</div>
</Providers>
</body>
</html>
</StoreProvider>
);
}
29 changes: 23 additions & 6 deletions components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@ import { Button } from "./ui/button";
import { auth } from "@/utils/firebase";
import { useAuthState } from "react-firebase-hooks/auth";

// import { useSelector } from "react-redux";
// import { RootState } from "@/store/store";
import algoliasearch from "algoliasearch/lite";
// import { InstantSearch, SearchBox } from "react-instantsearch-core";
import { useMemo } from "react";
import { useDispatch , useSelector } from "react-redux";
import { setSearchText , triggerSearch } from "@/store/slice";
import { RootState } from "@/store/store";

type Props = {
// searchState: any;
Expand All @@ -40,6 +38,14 @@ const Navbar = ({}: Props) => {
// const searchClient = algoliasearch('8XQGGZTFH3', 'bd743f217017ce1ea457a8febb7404ef');
// const searchClient = useMemo(() => algoliasearch('8XQGGZTFH3', 'bd743f217017ce1ea457a8febb7404ef'), []);

const dispatch = useDispatch();
const searchText = useSelector((state: RootState) => state.search.searchText);

const handleSearchText = (e: React.ChangeEvent<HTMLInputElement>) => {
e.preventDefault();
dispatch(setSearchText(e.target.value));
}

const [clicked, setClicked] = useState("");

const [user, loading] = useAuthState(auth);
Expand Down Expand Up @@ -86,7 +92,18 @@ const Navbar = ({}: Props) => {

{/* search bar */}
<div className=" relative ">
<Input className=" pl-10 w-[40rem]" placeholder="Search" />
{/* <Input className=" pl-10 w-[40rem]" placeholder="Search" /> */}
<input type="text"
value={searchText}
onChange={handleSearchText}
placeholder="Search"
className="w-[40rem] border border-gray-300 rounded-lg p-2 pl-10"
onKeyDown={(e) => {
if (e.key === 'Enter') {
dispatch(triggerSearch());
}
}}
/>
<Search className=" absolute left-2 top-1/2 transform -translate-y-1/2 h-5 w-5 text-zinc-700" />
</div>

Expand Down
213 changes: 87 additions & 126 deletions components/PostFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
"use client";

import React, { ChangeEvent, useEffect, useState } from 'react'
import Post from './Post'
import { postData } from '@/lib/data'

import {db} from '@/utils/firebase'
import { collection, getDocs, onSnapshot, orderBy, query } from 'firebase/firestore'


import React, { ChangeEvent, useEffect, useState } from "react";
import Post from "./Post";
import { postData } from "@/lib/data";

import { db } from "@/utils/firebase";
import {
collection,
getDocs,
onSnapshot,
orderBy,
query,
} from "firebase/firestore";

import algoliasearch from "algoliasearch/lite";
// import algoliasearch from "algoliasearch";
import { InstantSearch , SearchBox , Hits, Highlight } from "react-instantsearch";
import { InstantSearch, SearchBox, Hits, Highlight } from "react-instantsearch";
import { Search } from "lucide-react";
import { set } from 'date-fns';
import { set } from "date-fns";

type Props = {}
import { useSelector, useDispatch } from "react-redux";
import { RootState } from "@/store/store";
import { triggerSearch } from "@/store/slice";

type Props = {};

type PostType = {
id: string;
Expand All @@ -32,84 +40,89 @@ type PostType = {
anonymity: boolean;
ansNumbers: number;
// Add any other fields as necessary
}
};

const PostFeed = (props: Props) => {

const [posts , setPosts] = useState<PostType[]>([]);
const [posts, setPosts] = useState<PostType[]>([]);

useEffect(() => {
const collectionRef = collection(db, "questions");
const q = query(collectionRef, orderBy("createdAt", "desc"));

const collectionRef = collection(db, 'questions');
const q = query(collectionRef, orderBy('createdAt', 'desc'));

const unsub = onSnapshot(q, async(snapshot) => {
const postsData =[];
const unsub = onSnapshot(q, async (snapshot) => {
const postsData = [];

for (const doc of snapshot.docs) {

// Fetch the 'answers' subcollection for each question
const answersCollectionRef = collection(doc.ref, 'answers');
const answersCollectionRef = collection(doc.ref, "answers");
const answersQuery = query(answersCollectionRef);

const answersSnapshot = await getDocs(answersQuery);
const numAnswers = answersSnapshot.size;

// Add the total number of answers to the question data
const questionData = { id: doc.id, comments: numAnswers, ...doc.data() } as PostType;

const questionData = {
id: doc.id,
comments: numAnswers,
...doc.data(),
} as PostType;

postsData.push(questionData);
}

setPosts(postsData);
})
});

return () => {
unsub()
}
}, [])

unsub();
};
}, []);

//algolia stuff

const [searchText, setSearchText] = useState<string>('');
const [searchResult , setSearchResult] = useState<any>(null);

// const [searchClient, setSearchClient] = useState<any>(null);
// useEffect(() => {
// setSearchClient(algoliasearch('8XQGGZTFH3', 'bd743f217017ce1ea457a8febb7404ef'))
// } , [])
// const [searchText, setSearchText] = useState<string>('');
const [searchResult, setSearchResult] = useState<any>(null);

const searchClient = algoliasearch('8XQGGZTFH3', 'bd743f217017ce1ea457a8febb7404ef')
const { searchText, searchTriggered } = useSelector(
(state: RootState) => state.search
);
const dispatch = useDispatch();


const searchIndex = searchClient.initIndex('search_questions');
const searchClient = algoliasearch(
"8XQGGZTFH3",
"bd743f217017ce1ea457a8febb7404ef"
);

const handleSearchText = (e: ChangeEvent<HTMLInputElement>) => {
e.preventDefault();
setSearchText(e.target.value);
}
const searchIndex = searchClient.initIndex("search_questions");

const handleSearch = async(queryText: string) => {
// const handleSearchText = (e: ChangeEvent<HTMLInputElement>) => {
// e.preventDefault();
// setSearchText(e.target.value);
// }

const handleSearch = async (queryText: string) => {
try {
const result = await searchIndex.search(queryText);
// console.log(result);
setSearchResult(result.hits);

} catch (error) {
console.log(error);
setSearchResult(null);
}
}
};

useEffect(() => {
if (searchText === '') {
if (searchText === "") {
setSearchResult(null);
}
}, [searchText])

}, [searchText]);

useEffect(() => {
if (searchTriggered) {
handleSearch(searchText);
dispatch(triggerSearch());
}
}, [searchTriggered]);

function transformHitToPost(hit: any) {
return {
Expand All @@ -130,81 +143,29 @@ const PostFeed = (props: Props) => {
};
}

const searchClasses = {
root: 'flex flex-col space-y-2 ',
form: 'flex flex-col space-y-2 ',
input: 'w-full border border-gray-300 rounded-lg p-2 pl-10',
// submit: 'bg-emerald-500 text-white rounded-lg p-2',
submit: 'hidden',
reset: 'hidden',
// loadingIndicator: 'text-red-500',
// submitIcon: 'h-5 w-5',
// resetIcon: 'h-5 w-5',
// loadingIcon: 'h-5 w-5',
};

return (
<div className=' w-[100%]'>
{/* <ul className=' flex flex-col col-span-2 space-y-4'>
{posts.map((post, index) => (
<li key={index}>
<Post post={post} />
</li>
))}
</ul> */}
{/* {
searchClient && (
<InstantSearch searchClient={searchClient} indexName="search_questions">
<div className="relative">
<SearchBox classNames={searchClasses} searchAsYouType={true} placeholder="Search ..." />
<Search className="absolute left-2 top-1/2 transform -translate-y-1/2 h-5 w-5 text-zinc-700" />
</div>
<Hits hitComponent={({hit}) => <Post post={transformHitToPost(hit)} />} />
</InstantSearch>
)
} */}
<div className="relative">

<input type="text"
value={searchText}
onChange={handleSearchText}
placeholder="Search"
className="w-full border border-gray-300 rounded-lg p-2 pl-10"
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleSearch(searchText);
}
}}
/>

{
searchResult && searchResult.length > 0 ? (
<ul className="flex flex-col space-y-1">
{searchResult.map((hit: any) => (
<li key={hit.objectID}>
<Post post={transformHitToPost(hit)} />
</li>
))}
</ul>
) : (
<ul className=' flex flex-col col-span-2 space-y-1'>
{posts.map((post, index) => (
<li key={index}>
<Post post={post} />
</li>
))}
</ul>

)
}
</div>
<div className=" w-[100%]">
<div className="relative">
{searchResult && searchResult.length > 0 ? (
<ul className="flex flex-col space-y-1">
{searchResult.map((hit: any) => (
<li key={hit.objectID}>
<Post post={transformHitToPost(hit)} />
</li>
))}
</ul>
) : (
<ul className=" flex flex-col col-span-2 space-y-1">
{posts.map((post, index) => (
<li key={index}>
<Post post={post} />
</li>
))}
</ul>
)}
</div>
</div>
)
}
);
};

export default PostFeed
export default PostFeed;
Loading

0 comments on commit f52058f

Please sign in to comment.