From 6fd6880432decd911a2a976cab0bd90ed5118fe5 Mon Sep 17 00:00:00 2001 From: Aq Date: Thu, 3 Oct 2024 13:59:58 +0530 Subject: [PATCH 1/3] search route --- pnpm-lock.yaml | 6 +- src/app/components/searchbar.tsx | 99 +++++++++++++++++++++++++++----- 2 files changed, 88 insertions(+), 17 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1aa9c74..0dc78be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3385,7 +3385,7 @@ snapshots: '@babel/code-frame@7.24.7': dependencies: '@babel/highlight': 7.24.7 - picocolors: 1.0.1 + picocolors: 1.1.0 '@babel/compat-data@7.25.4': {} @@ -3470,7 +3470,7 @@ snapshots: '@babel/helper-validator-identifier': 7.24.7 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.1 + picocolors: 1.1.0 '@babel/parser@7.25.6': dependencies: @@ -6878,7 +6878,7 @@ snapshots: webpack@5.95.0: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 '@webassemblyjs/ast': 1.12.1 '@webassemblyjs/wasm-edit': 1.12.1 '@webassemblyjs/wasm-parser': 1.12.1 diff --git a/src/app/components/searchbar.tsx b/src/app/components/searchbar.tsx index cffc5f6..18c2035 100644 --- a/src/app/components/searchbar.tsx +++ b/src/app/components/searchbar.tsx @@ -1,34 +1,105 @@ "use client"; import { useState } from "react"; +import axios, { type AxiosError } from "axios"; import { Search } from "lucide-react"; +import Cryptr from "cryptr"; + +interface Paper { + _id: string; + exam: string; + finalUrl: string; + slot: string; + subject: string; + year: string; +} + +const cryptr = new Cryptr( + process.env.NEXT_PUBLIC_CRYPTO_SECRET ?? "default_crypto_secret" +); const SearchBar = () => { const [searchText, setSearchText] = useState(""); + const [papers, setPapers] = useState([]); + const [error, setError] = useState(null); - const handleSearch = (event: React.FormEvent) => { + const handleSearch = async (event: React.FormEvent) => { event.preventDefault(); - console.log("Searching for:", searchText); + setError(null); + + try { + const searchResponse = await axios.get("http://localhost:3000/api/search", { + params: { text: searchText }, + }); + + const { res: encryptedSearchResponse } = searchResponse.data; + const decryptedSearchResponse = cryptr.decrypt(encryptedSearchResponse); + const fetchedPapers: Paper[] = JSON.parse(decryptedSearchResponse); + + // console.log("Decrypted Search Response:", fetchedPapers); + setPapers(fetchedPapers); + const papersResponse = await axios.get("http://localhost:3000/api/papers", { + params: { subject: searchText }, + }); + + const { res: encryptedPapersResponse } = papersResponse.data; + const decryptedPapersResponse = cryptr.decrypt(encryptedPapersResponse); + const parsedResponse = JSON.parse(decryptedPapersResponse); + const papersData: Paper[] = parsedResponse.papers; + + // console.log("Decrypted Papers Response:", papersData); + setPapers(papersData); + } catch (error) { + if (axios.isAxiosError(error)) { + const axiosError = error as AxiosError; + const errorMessage = (axiosError.response?.data as { message: string }).message; + + setError(errorMessage ?? "Error fetching papers"); + } else { + setError("Error fetching papers"); + } + console.error("Error fetching papers:", error); + } }; return ( -
+
- setSearchText(e.target.value)} - placeholder="Search..." - className="w-full rounded-md border border-gray-300 px-4 py-2 pr-10 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500" - /> - +
+ + {papers.length > 0 && ( +
+

Papers:

+
+ + {papers.map((paper) => ( +
+

Exam: {paper.exam}

+ +

Slot: {paper.slot}

+

Subject: {paper.subject}

+

Year: {paper.year}

+ + + View Paper + + +
+ ))} +
+
+ )} + + {error &&

{error}

}
); }; From 952c4b87fae742b91b7fecf5e05fb2f9c6adef28 Mon Sep 17 00:00:00 2001 From: Aq Date: Thu, 3 Oct 2024 21:28:57 +0530 Subject: [PATCH 2/3] search update --- src/app/components/searchbar.tsx | 89 +++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 30 deletions(-) diff --git a/src/app/components/searchbar.tsx b/src/app/components/searchbar.tsx index 18c2035..bc76a5b 100644 --- a/src/app/components/searchbar.tsx +++ b/src/app/components/searchbar.tsx @@ -1,6 +1,7 @@ "use client"; + import { useState } from "react"; -import axios, { type AxiosError } from "axios"; +import axios, { AxiosError } from "axios"; import { Search } from "lucide-react"; import Cryptr from "cryptr"; @@ -19,41 +20,58 @@ const cryptr = new Cryptr( const SearchBar = () => { const [searchText, setSearchText] = useState(""); + const [suggestions, setSuggestions] = useState([]); const [papers, setPapers] = useState([]); const [error, setError] = useState(null); - const handleSearch = async (event: React.FormEvent) => { - event.preventDefault(); - setError(null); + const handleSearchChange = async (e: React.ChangeEvent) => { + const text = e.target.value; + setSearchText(text); - try { - const searchResponse = await axios.get("http://localhost:3000/api/search", { - params: { text: searchText }, - }); + if (text.length > 1) { + try { + const searchResponse = await axios.get("http://localhost:3000/api/search", { + params: { text }, + }); - const { res: encryptedSearchResponse } = searchResponse.data; - const decryptedSearchResponse = cryptr.decrypt(encryptedSearchResponse); - const fetchedPapers: Paper[] = JSON.parse(decryptedSearchResponse); + const { res: encryptedSearchResponse } = searchResponse.data; + const decryptedSearchResponse = cryptr.decrypt(encryptedSearchResponse); - // console.log("Decrypted Search Response:", fetchedPapers); - setPapers(fetchedPapers); + console.log("Decrypted Search Response:", decryptedSearchResponse); + + const { subjects } = JSON.parse(decryptedSearchResponse); + const suggestionList = subjects.map((subjectObj: { subject: string }) => subjectObj.subject); + setSuggestions(suggestionList); + } catch (error) { + setError("Error fetching suggestions"); + console.error("Error fetching suggestions:", error); + } + } else { + setSuggestions([]); + } + }; + + const handleSelectSuggestion = async (suggestion: string) => { + setSearchText(suggestion); + setSuggestions([]); + + try { const papersResponse = await axios.get("http://localhost:3000/api/papers", { - params: { subject: searchText }, + params: { subject: suggestion }, }); const { res: encryptedPapersResponse } = papersResponse.data; const decryptedPapersResponse = cryptr.decrypt(encryptedPapersResponse); - const parsedResponse = JSON.parse(decryptedPapersResponse); - const papersData: Paper[] = parsedResponse.papers; - // console.log("Decrypted Papers Response:", papersData); - setPapers(papersData); + console.log("Decrypted Papers Response:", decryptedPapersResponse); + + const papersData: Paper[] = JSON.parse(decryptedPapersResponse).papers; + setPapers(papersData); } catch (error) { if (axios.isAxiosError(error)) { - const axiosError = error as AxiosError; - const errorMessage = (axiosError.response?.data as { message: string }).message; - - setError(errorMessage ?? "Error fetching papers"); + const axiosError = error as AxiosError<{ message?: string }>; + const errorMessage = axiosError.response?.data?.message || "Error fetching papers"; + setError(errorMessage); } else { setError("Error fetching papers"); } @@ -63,28 +81,39 @@ const SearchBar = () => { return (
-
+
- setSearchText(e.target.value)} - placeholder="Search..." - className="w-full rounded-md border border-gray-300 px-4 py-2 pr-10 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500"/> - + +
+ + + {suggestions.length > 0 && ( +
    + {suggestions.map((suggestion, index) => ( + +
  • handleSelectSuggestion(suggestion)} className="cursor-pointer p-2 hover:bg-gray-100"> + {suggestion} +
  • + + ))} +
+ )}
{papers.length > 0 && (

Papers:

- {papers.map((paper) => (
-

Exam: {paper.exam}

+

Exam: {paper.exam}

Slot: {paper.slot}

Subject: {paper.subject}

Year: {paper.year}

@@ -92,7 +121,7 @@ const SearchBar = () => { View Paper - +
))}
From ef091e8ecc251d6e66332a9f70d5c71cbf789b19 Mon Sep 17 00:00:00 2001 From: Aq Date: Sat, 5 Oct 2024 18:27:12 +0530 Subject: [PATCH 3/3] download page setup --- src/app/catalogue/page.tsx | 102 +++++++++++++++++++++++++++++++ src/app/components/searchbar.tsx | 77 ++++------------------- 2 files changed, 113 insertions(+), 66 deletions(-) create mode 100644 src/app/catalogue/page.tsx diff --git a/src/app/catalogue/page.tsx b/src/app/catalogue/page.tsx new file mode 100644 index 0000000..665ebe5 --- /dev/null +++ b/src/app/catalogue/page.tsx @@ -0,0 +1,102 @@ +"use client"; + +import { useSearchParams, useRouter } from "next/navigation"; +import { useEffect, useState } from "react"; +import axios, { AxiosError } from "axios"; +import Cryptr from "cryptr"; + +interface Paper { + _id: string; + exam: string; + finalUrl: string; + slot: string; + subject: string; + year: string; +} + +const cryptr = new Cryptr(process.env.NEXT_PUBLIC_CRYPTO_SECRET ?? "default_crypto_secret"); + +const Catalogue = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + const subject = searchParams.get('subject'); + const [papers, setPapers] = useState([]); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + + useEffect(() => { + if (subject) { + const fetchPapers = async () => { + setLoading(true); + + try { + const papersResponse = await axios.get("http://localhost:3000/api/papers", { + params: { subject }, + }); + + const { res: encryptedPapersResponse } = papersResponse.data; + const decryptedPapersResponse = cryptr.decrypt(encryptedPapersResponse); + // console.log("Decrypted Papers Response:", decryptedPapersResponse); + + const papersData: Paper[] = JSON.parse(decryptedPapersResponse).papers; + setPapers(papersData); + } catch (error) { + + if (axios.isAxiosError(error)) { + const axiosError = error as AxiosError<{ message?: string }>; + const errorMessage = axiosError.response?.data?.message || "Error fetching papers"; + setError(errorMessage); + + } else { + setError("Error fetching papers"); + } + + } finally { + setLoading(false); + } + }; + + fetchPapers(); + } + }, [subject]); + + return ( +
+ + + +

Papers for {subject}

+ {error &&

{error}

} + + {loading ? ( +

Loading papers...

+ ) : ( + papers.length > 0 ? ( +
+ + {papers.map((paper) => ( +
+ +

Exam: {paper.exam}

+

Slot: {paper.slot}

+

Subject: {paper.subject}

+

Year: {paper.year}

+ + + View Paper + + +
+ ))} +
+ ) : ( +

No papers available for this subject.

+ ) + )} +
+ ); +}; + +export default Catalogue; diff --git a/src/app/components/searchbar.tsx b/src/app/components/searchbar.tsx index bc76a5b..aa1fcf2 100644 --- a/src/app/components/searchbar.tsx +++ b/src/app/components/searchbar.tsx @@ -1,27 +1,19 @@ "use client"; import { useState } from "react"; -import axios, { AxiosError } from "axios"; +import axios from "axios"; import { Search } from "lucide-react"; import Cryptr from "cryptr"; - -interface Paper { - _id: string; - exam: string; - finalUrl: string; - slot: string; - subject: string; - year: string; -} +import { useRouter } from "next/navigation"; const cryptr = new Cryptr( process.env.NEXT_PUBLIC_CRYPTO_SECRET ?? "default_crypto_secret" ); const SearchBar = () => { + const router = useRouter(); const [searchText, setSearchText] = useState(""); const [suggestions, setSuggestions] = useState([]); - const [papers, setPapers] = useState([]); const [error, setError] = useState(null); const handleSearchChange = async (e: React.ChangeEvent) => { @@ -36,53 +28,30 @@ const SearchBar = () => { const { res: encryptedSearchResponse } = searchResponse.data; const decryptedSearchResponse = cryptr.decrypt(encryptedSearchResponse); + // console.log("Decrypted Search Response:", decryptedSearchResponse); - console.log("Decrypted Search Response:", decryptedSearchResponse); - - const { subjects } = JSON.parse(decryptedSearchResponse); + const { subjects } = JSON.parse(decryptedSearchResponse); const suggestionList = subjects.map((subjectObj: { subject: string }) => subjectObj.subject); - setSuggestions(suggestionList); + setSuggestions(suggestionList); } catch (error) { setError("Error fetching suggestions"); - console.error("Error fetching suggestions:", error); } } else { - setSuggestions([]); + setSuggestions([]); } }; const handleSelectSuggestion = async (suggestion: string) => { - setSearchText(suggestion); - setSuggestions([]); - - try { - const papersResponse = await axios.get("http://localhost:3000/api/papers", { - params: { subject: suggestion }, - }); - - const { res: encryptedPapersResponse } = papersResponse.data; - const decryptedPapersResponse = cryptr.decrypt(encryptedPapersResponse); - - console.log("Decrypted Papers Response:", decryptedPapersResponse); - - const papersData: Paper[] = JSON.parse(decryptedPapersResponse).papers; - setPapers(papersData); - } catch (error) { - if (axios.isAxiosError(error)) { - const axiosError = error as AxiosError<{ message?: string }>; - const errorMessage = axiosError.response?.data?.message || "Error fetching papers"; - setError(errorMessage); - } else { - setError("Error fetching papers"); - } - console.error("Error fetching papers:", error); - } + setSearchText(suggestion); + setSuggestions([]); + router.push(`/catalogue?subject=${encodeURIComponent(suggestion)}`); }; return (
+ @@ -91,8 +60,6 @@ const SearchBar = () => {
- - {suggestions.length > 0 && (
    {suggestions.map((suggestion, index) => ( @@ -106,28 +73,6 @@ const SearchBar = () => { )} - {papers.length > 0 && ( -
    -

    Papers:

    -
    - {papers.map((paper) => ( -
    - -

    Exam: {paper.exam}

    -

    Slot: {paper.slot}

    -

    Subject: {paper.subject}

    -

    Year: {paper.year}

    - - - View Paper - - -
    - ))} -
    -
    - )} - {error &&

    {error}

    }
);