Skip to content

Commit

Permalink
Merge pull request #3 from AqViolet/master
Browse files Browse the repository at this point in the history
Searchbar route setup
  • Loading branch information
NishantGupt786 authored Oct 5, 2024
2 parents 5a0eaf2 + ef091e8 commit 8a1e653
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 19 deletions.
6 changes: 3 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

102 changes: 102 additions & 0 deletions src/app/catalogue/page.tsx
Original file line number Diff line number Diff line change
@@ -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<Paper[]>([]);
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState<boolean>(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 (
<div className="min-h-screen bg-gray-50 p-8">

<button onClick={() => router.push('/')} className="mb-4 px-4 py-2 bg-blue-500 text-white rounded-md">
Back to Search
</button>

<h1 className="text-2xl font-bold mb-4">Papers for {subject}</h1>
{error && <p className="text-red-500">{error}</p>}

{loading ? (
<p>Loading papers...</p>
) : (
papers.length > 0 ? (
<div className="grid grid-cols-1 gap-4">

{papers.map((paper) => (
<div key={paper._id} className="border rounded-md p-4 shadow-md bg-white">

<h3 className="text-xl font-bold">Exam: {paper.exam}</h3>
<p>Slot: {paper.slot}</p>
<p>Subject: {paper.subject}</p>
<p>Year: {paper.year}</p>

<a href={paper.finalUrl} target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:underline">
View Paper
</a>

</div>
))}
</div>
) : (
<p>No papers available for this subject.</p>
)
)}
</div>
);
};

export default Catalogue;
77 changes: 61 additions & 16 deletions src/app/components/searchbar.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,79 @@
"use client";

import { useState } from "react";
import axios from "axios";
import { Search } from "lucide-react";
import Cryptr from "cryptr";
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<string[]>([]);
const [error, setError] = useState<string | null>(null);

const handleSearchChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const text = e.target.value;
setSearchText(text);

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);
// 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");
}
} else {
setSuggestions([]);
}
};

const handleSearch = (event: React.FormEvent) => {
event.preventDefault();
console.log("Searching for:", searchText);
const handleSelectSuggestion = async (suggestion: string) => {
setSearchText(suggestion);
setSuggestions([]);
router.push(`/catalogue?subject=${encodeURIComponent(suggestion)}`);
};

return (
<div className="flex min-h-screen items-center justify-center bg-gray-50">
<form onSubmit={handleSearch} className="w-full max-w-md">
<div className="flex min-h-screen items-center justify-center bg-gray-50 flex-col">
<form className="w-full max-w-md">
<div className="relative">
<input
type="text"
value={searchText}
onChange={(e) => 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"
/>
<button
type="submit"
className="absolute inset-y-0 right-0 flex items-center pr-3"
>

<input type="text" value={searchText} onChange={handleSearchChange}
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"/>

<button type="submit" className="absolute inset-y-0 right-0 flex items-center pr-3">
<Search className="h-5 w-5 text-gray-400" />
</button>

</div>
{suggestions.length > 0 && (
<ul className="absolute z-10 w-full bg-white border border-gray-300 rounded-md mt-2">
{suggestions.map((suggestion, index) => (

<li key={index} onClick={() => handleSelectSuggestion(suggestion)} className="cursor-pointer p-2 hover:bg-gray-100">
{suggestion}
</li>

))}
</ul>
)}
</form>

{error && <p className="mt-4 text-red">{error}</p>}
</div>
);
};
Expand Down

0 comments on commit 8a1e653

Please sign in to comment.