diff --git a/frontend/src/pages/Home.jsx b/frontend/src/pages/Home.jsx index ff1a982..2b1c729 100644 --- a/frontend/src/pages/Home.jsx +++ b/frontend/src/pages/Home.jsx @@ -22,38 +22,18 @@ * - Call to action */ -import { Link } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import { useEffect, useState } from 'react'; -// TODO: Import API functions -import { getAllQuestions } from '../api/questionApi'; +import { getAllQuestions, searchQuestions } from '../api/questionApi'; import QuestionCard from '../components/QuestionCard'; import toast from 'react-hot-toast'; - -/** - * TODO: IMPLEMENT HOME PAGE - * - * Features: - * 1. Hero section with CTA - * 2. Fetch and display recent questions - * 3. Show statistics - * 4. Features grid - * 5. Responsive design - * - * EXAMPLE STRUCTURE: - *
- * - * - * - * - * - *
- */ +import { Search } from 'lucide-react'; const Home = () => { const [recentQuestions, setRecentQuestions] = useState([]); const [loading, setLoading] = useState(false); - - // TODO: Fetch recent questions on mount + const [searchQuery, setSearchQuery] = useState(''); + const navigate = useNavigate(); const fetchRecentQuestions = async () => { setLoading(true); @@ -77,6 +57,14 @@ const Home = () => { fetchRecentQuestions(); }, []); + const handleSearch = async (e) => { + e.preventDefault(); + if (searchQuery.trim()) { + // Navigate to questions page with search query + navigate(`/questions?search=${encodeURIComponent(searchQuery)}`); + } + }; + return (
{/* Hero Section */} @@ -87,6 +75,27 @@ const Home = () => { A community-sourced interview question bank where students share real questions from their internship and placement interviews.

+ + {/* Search Bar in Hero */} +
+
+ + setSearchQuery(e.target.value)} + /> + + +
+
Browse Questions @@ -103,7 +112,6 @@ const Home = () => {

Why Use InterviewPrep?

- {/* TODO: Add feature cards */}
📚

Vast Question Bank

@@ -147,44 +155,43 @@ const Home = () => {

Recent Questions

- {/* TODO: Display recent questions using QuestionCard */} - { - loading ? ( -
-
-

Loading questions...

-
- ) : recentQuestions.length > 0 ? ( + + {loading ? ( +
+
+

Loading questions...

+
+ ) : recentQuestions.length > 0 ? ( + <>
- {recentQuestions.map((question) => ( - - ))} -
- ) : ( -
-

No questions available yet

- - Be the first to submit a question! → - -
- ) - } -
- {/* Placeholder */} -
-

Questions will appear here once implemented

- - View All Questions → + {recentQuestions.map((question) => ( + + ))} +
+
+ + View All Questions → + +
+ + ) : ( +
+

No questions available yet

+ + Be the first to submit a question! →
-
+ )}
@@ -192,7 +199,6 @@ const Home = () => {
- {/* TODO: Fetch and display real statistics */}
500+
Questions
@@ -226,3 +232,232 @@ const Home = () => { }; export default Home; + +// /** +// * HOME PAGE - Landing page +// * +// * HACKTOBERFEST TODO: +// * This is the main landing page of the application. +// * +// * CONTRIBUTOR TASKS: +// * 1. Create hero section with: +// * - App title and tagline +// * - Brief description +// * - Call-to-action buttons +// * 2. Add features section highlighting key features +// * 3. Show recent/trending questions +// * 4. Add statistics (total questions, companies, topics) +// * 5. Make responsive and attractive +// * +// * SECTIONS: +// * - Hero section +// * - Features/Benefits +// * - Recent questions preview +// * - Statistics +// * - Call to action +// */ + +// import { Link } from 'react-router-dom'; +// import { useEffect, useState } from 'react'; +// // TODO: Import API functions +// import { getAllQuestions } from '../api/questionApi'; +// import QuestionCard from '../components/QuestionCard'; +// import toast from 'react-hot-toast'; + +// /** +// * TODO: IMPLEMENT HOME PAGE +// * +// * Features: +// * 1. Hero section with CTA +// * 2. Fetch and display recent questions +// * 3. Show statistics +// * 4. Features grid +// * 5. Responsive design +// * +// * EXAMPLE STRUCTURE: +// *
+// * +// * +// * +// * +// * +// *
+// */ + +// const Home = () => { +// const [recentQuestions, setRecentQuestions] = useState([]); +// const [loading, setLoading] = useState(false); + +// // TODO: Fetch recent questions on mount + +// const fetchRecentQuestions = async () => { +// setLoading(true); +// try { +// const response = await getAllQuestions({ +// sort: 'latest', +// limit: 6 +// }); + +// setRecentQuestions(response.questions || []); +// } catch (error) { +// console.error('Error fetching recent questions:', error); +// toast.error('Failed to load recent questions'); +// setRecentQuestions([]); +// } finally { +// setLoading(false); +// } +// }; + +// useEffect(() => { +// fetchRecentQuestions(); +// }, []); + +// return ( +//
+// {/* Hero Section */} +//
+//
+//

Welcome to InterviewPrep

+//

+// A community-sourced interview question bank where students share real questions from their internship and +// placement interviews. +//

+//
+// +// Browse Questions +// +// +// Submit Question +// +//
+//
+//
+ +// {/* Features Section */} +//
+//
+//

Why Use InterviewPrep?

+//
+// {/* TODO: Add feature cards */} +//
+//
📚
+//

Vast Question Bank

+//

+// Access thousands of real interview questions from top companies +//

+//
+//
+//
🏢
+//

Company-Specific

+//

+// Filter questions by company, role, and difficulty level +//

+//
+//
+//
🤝
+//

Community-Driven

+//

+// Built by students, for students. Everyone can contribute. +//

+//
+//
+//
🧠
+//

Topic-wise Practice

+//

+// Practice questions categorized by topic and difficulty to strengthen weak areas. +//

+//
+//
+//
🔖
+//

Bookmark Questions

+//

+// Save your favorite interview questions to revisit anytime. +//

+//
+//
+//
+//
+ +// {/* Recent Questions Preview */} +//
+//
+//

Recent Questions

+// {/* TODO: Display recent questions using QuestionCard */} +// { +// loading ? ( +//
+//
+//

Loading questions...

+//
+// ) : recentQuestions.length > 0 ? ( +//
+// {recentQuestions.map((question) => ( +// +// ))} +//
+// ) : ( +//
+//

No questions available yet

+// +// Be the first to submit a question! → +// +//
+// ) +// } +//
+// {/* Placeholder */} +//
+//

Questions will appear here once implemented

+// +// View All Questions → +// +//
+//
+//
+//
+ +// {/* Statistics Section */} +//
+//
+//
+// {/* TODO: Fetch and display real statistics */} +//
+//
500+
+//
Questions
+//
+//
+//
50+
+//
Companies
+//
+//
+//
20+
+//
Topics
+//
+//
+//
+//
+ +// {/* CTA Section */} +//
+//
+//

Ready to Start Preparing?

+//

+// Join our community and access thousands of interview questions +//

+// +// Get Started Free +// +//
+//
+//
+// ); +// }; + +// export default Home; diff --git a/frontend/src/pages/Questions.jsx b/frontend/src/pages/Questions.jsx index ca42148..80f70ad 100644 --- a/frontend/src/pages/Questions.jsx +++ b/frontend/src/pages/Questions.jsx @@ -1,68 +1,9 @@ /* eslint-disable no-unused-vars */ -/** - * QUESTIONS PAGE - Browse all questions with filters - * - * HACKTOBERFEST TODO: - * This page displays all questions with filtering and sorting options. - * - * CONTRIBUTOR TASKS: - * 1. Fetch all questions from API - * 2. Implement filter by: - * - Company - * - Topic - * - Role - * - Difficulty - * 3. Implement search functionality - * 4. Implement sorting (latest, oldest, most upvoted) - * 5. Implement pagination or infinite scroll - * 6. Display questions using QuestionCard component - * 7. Add loading and error states - * 8. Make responsive with sidebar filters - * - * FEATURES: - * - Search bar - * - Filter sidebar/dropdown - * - Sort options - * - Question grid/list - * - Pagination - */ - import { useState, useEffect, useCallback } from 'react'; +import { Search, X, Filter } from 'lucide-react'; // Import API functions import { getAllQuestions, getCategories, searchQuestions } from '../api/questionApi'; import QuestionCard from '../components/QuestionCard'; -// import Loading from '../components/Loading'; - -/** - * TODO: IMPLEMENT QUESTIONS PAGE - * - * State to manage: - * - questions: Array of questions - * - filters: { company, topic, role, difficulty, sort } - * - searchQuery: string - * - loading: boolean - * - error: string - * - pagination: { page, limit, total } - * - categories: { companies, topics, roles } - * - * Functions: - * 1. fetchQuestions() - Fetch questions with filters - * 2. fetchCategories() - Fetch filter options - * 3. handleFilterChange() - Update filters - * 4. handleSearch() - Search questions - * 5. handleSort() - Sort questions - * 6. handlePageChange() - Pagination - * - * LAYOUT: - *
- * - *
- * - * - *
- * - *
- */ const Questions = () => { const [questions, setQuestions] = useState([]); @@ -70,6 +11,7 @@ const Questions = () => { const [error, setError] = useState(''); const [categoriesLoading, setCategoriesLoading] = useState(false); const [categoriesError, setCategoriesError] = useState(''); + const [showFilters, setShowFilters] = useState(true); const [filters, setFilters] = useState({ company: '', @@ -93,26 +35,41 @@ const Questions = () => { })); }; -const fetchQuestions = useCallback(async () => { - setLoading(true); - setError(''); - try { - const queryParams = {}; - if (filters.company) queryParams.company = filters.company; - if (filters.topic) queryParams.topic = filters.topic; - if (filters.role) queryParams.role = filters.role; - if (filters.difficulty) queryParams.difficulty = filters.difficulty; - if (filters.sort) queryParams.sort = filters.sort; - - const questionData = await getAllQuestions(queryParams); - setQuestions(questionData.questions || questionData || []); - } catch (err) { - setError('Failed to load questions. Please try again later.'); - console.error('Error fetching questions:', err); - } finally { - setLoading(false); - } -}, [filters]); + const clearSearch = () => { + setSearchQuery(''); + }; + + const clearAllFilters = () => { + setFilters({ + company: '', + topic: '', + role: '', + difficulty: '', + sort: 'latest', + }); + setSearchQuery(''); + }; + + const fetchQuestions = useCallback(async () => { + setLoading(true); + setError(''); + try { + const queryParams = {}; + if (filters.company) queryParams.company = filters.company; + if (filters.topic) queryParams.topic = filters.topic; + if (filters.role) queryParams.role = filters.role; + if (filters.difficulty) queryParams.difficulty = filters.difficulty; + if (filters.sort) queryParams.sort = filters.sort; + + const questionData = await getAllQuestions(queryParams); + setQuestions(questionData.questions || questionData || []); + } catch (err) { + setError('Failed to load questions. Please try again later.'); + console.error('Error fetching questions:', err); + } finally { + setLoading(false); + } + }, [filters]); // Fetch questions on mount and when filters change useEffect(() => { @@ -175,6 +132,8 @@ const fetchQuestions = useCallback(async () => { fetchCategories(); }, []); + const activeFiltersCount = Object.values(filters).filter(v => v && v !== 'latest').length; + return (
{/* Page Header */} @@ -183,82 +142,130 @@ const fetchQuestions = useCallback(async () => {

Browse and search through community-sourced interview questions

- {/* Search Bar */} -
- {/* TODO: Implement search input */} + {/* Search Bar with Icon and Clear Button */} +
+ setSearchQuery(e.target.value)} /> + {searchQuery && ( + + )}
- {/* Filters and Sort */} -
- {/* TODO: Implement filter dropdowns */} - - - - - - - - - + + Filters + {activeFiltersCount > 0 && ( + + {activeFiltersCount} + + )} + + + {(activeFiltersCount > 0 || searchQuery) && ( + + )}
+ {/* Filters and Sort - Now Collapsible */} + {showFilters && ( +
+ + + + + + + + + +
+ )} + + {/* Active Search/Filter Indicator */} + {(searchQuery || activeFiltersCount > 0) && ( +
+ {searchQuery && ( + Searching for: "{searchQuery}" + )} + {searchQuery && activeFiltersCount > 0 && with } + {activeFiltersCount > 0 && ( + {activeFiltersCount} active filter{activeFiltersCount > 1 ? 's' : ''} + )} +
+ )} + {/* Error Message */} {error && (
@@ -276,6 +283,14 @@ const fetchQuestions = useCallback(async () => { ) : questions.length === 0 ? (

No questions found. Try adjusting your filters or search terms.

+ {(searchQuery || activeFiltersCount > 0) && ( + + )}
) : ( questions.map((question) => ( @@ -308,3 +323,316 @@ const fetchQuestions = useCallback(async () => { }; export default Questions; + + + +// /* eslint-disable no-unused-vars */ +// /** +// * QUESTIONS PAGE - Browse all questions with filters +// * +// * HACKTOBERFEST TODO: +// * This page displays all questions with filtering and sorting options. +// * +// * CONTRIBUTOR TASKS: +// * 1. Fetch all questions from API +// * 2. Implement filter by: +// * - Company +// * - Topic +// * - Role +// * - Difficulty +// * 3. Implement search functionality +// * 4. Implement sorting (latest, oldest, most upvoted) +// * 5. Implement pagination or infinite scroll +// * 6. Display questions using QuestionCard component +// * 7. Add loading and error states +// * 8. Make responsive with sidebar filters +// * +// * FEATURES: +// * - Search bar +// * - Filter sidebar/dropdown +// * - Sort options +// * - Question grid/list +// * - Pagination +// */ + +// import { useState, useEffect, useCallback } from 'react'; +// // Import API functions +// import { getAllQuestions, getCategories, searchQuestions } from '../api/questionApi'; +// import QuestionCard from '../components/QuestionCard'; +// // import Loading from '../components/Loading'; + +// /** +// * TODO: IMPLEMENT QUESTIONS PAGE +// * +// * State to manage: +// * - questions: Array of questions +// * - filters: { company, topic, role, difficulty, sort } +// * - searchQuery: string +// * - loading: boolean +// * - error: string +// * - pagination: { page, limit, total } +// * - categories: { companies, topics, roles } +// * +// * Functions: +// * 1. fetchQuestions() - Fetch questions with filters +// * 2. fetchCategories() - Fetch filter options +// * 3. handleFilterChange() - Update filters +// * 4. handleSearch() - Search questions +// * 5. handleSort() - Sort questions +// * 6. handlePageChange() - Pagination +// * +// * LAYOUT: +// *
+// * +// *
+// * +// * +// *
+// * +// *
+// */ + +// const Questions = () => { +// const [questions, setQuestions] = useState([]); +// const [loading, setLoading] = useState(true); +// const [error, setError] = useState(''); +// const [categoriesLoading, setCategoriesLoading] = useState(false); +// const [categoriesError, setCategoriesError] = useState(''); + +// const [filters, setFilters] = useState({ +// company: '', +// topic: '', +// role: '', +// difficulty: '', +// sort: 'latest', +// }); + +// const [searchQuery, setSearchQuery] = useState(''); +// const [categories, setCategories] = useState({ +// companies: [], +// topics: [], +// roles: [], +// }); + +// const handleFilterChange = (filterType, value) => { +// setFilters(prevFilters => ({ +// ...prevFilters, +// [filterType]: value +// })); +// }; + +// const fetchQuestions = useCallback(async () => { +// setLoading(true); +// setError(''); +// try { +// const queryParams = {}; +// if (filters.company) queryParams.company = filters.company; +// if (filters.topic) queryParams.topic = filters.topic; +// if (filters.role) queryParams.role = filters.role; +// if (filters.difficulty) queryParams.difficulty = filters.difficulty; +// if (filters.sort) queryParams.sort = filters.sort; + +// const questionData = await getAllQuestions(queryParams); +// setQuestions(questionData.questions || questionData || []); +// } catch (err) { +// setError('Failed to load questions. Please try again later.'); +// console.error('Error fetching questions:', err); +// } finally { +// setLoading(false); +// } +// }, [filters]); + +// // Fetch questions on mount and when filters change +// useEffect(() => { +// fetchQuestions(); +// }, [fetchQuestions]); + +// //Fetch categories function for filters +// const fetchCategories = async () => { +// setCategoriesLoading(true); +// setCategoriesError(''); +// try { +// const categoriesData = await getCategories(); + +// setCategories({ +// companies: categoriesData.companies || [], +// topics: categoriesData.topics || [], +// roles: categoriesData.roles || [], +// }) +// } +// catch (err) { +// setCategoriesError('Failed to load filter options. Please try again later.'); +// console.error('Error fetching categories:', err); +// } +// finally { +// setCategoriesLoading(false); // This ensures loading stops even if error occurs +// } +// } + +// // Handle search functionality +// const handleSearch = useCallback(async () => { +// if (searchQuery.trim()) { +// setLoading(true); +// setError(''); +// try { +// const response = await searchQuestions(searchQuery); +// setQuestions(response.questions || []); +// } catch (err) { +// setError('Failed to search questions. Please try again later.'); +// console.error('Error searching questions:', err); +// } finally { +// setLoading(false); +// } +// } else { +// // If search is empty, fetch all questions with current filters +// fetchQuestions(); +// } +// }, [searchQuery, fetchQuestions]); + +// // Debounce search queries +// useEffect(() => { +// const delayedSearch = setTimeout(() => { +// handleSearch(); +// }, 500); // Wait 500ms after user stops typing + +// return () => clearTimeout(delayedSearch); +// }, [searchQuery, handleSearch]); + +// // Fetch categories for filters +// useEffect(() => { +// fetchCategories(); +// }, []); + +// return ( +//
+// {/* Page Header */} +//
+//

Interview Questions

+//

Browse and search through community-sourced interview questions

+//
+ +// {/* Search Bar */} +//
+// {/* TODO: Implement search input */} +// setSearchQuery(e.target.value)} +// /> +//
+ +// {/* Filters and Sort */} +//
+// {/* TODO: Implement filter dropdowns */} +// + +// + +// + +// + +// +//
+ +// {/* Error Message */} +// {error && ( +//
+// {error} +//
+// )} + +// {/* Questions Grid */} +//
+// {loading ? ( +//
+//
+//

Loading questions...

+//
+// ) : questions.length === 0 ? ( +//
+//

No questions found. Try adjusting your filters or search terms.

+//
+// ) : ( +// questions.map((question) => ( +// { +// // TODO: Implement upvote functionality +// console.log('Upvote question:', questionId); +// }} +// showActions={true} +// /> +// )) +// )} +//
+ +// {/* Pagination */} +// {/* TODO: Implement pagination controls */} +//
+//
+// +// +// +// +// +//
+//
+//
+// ); +// }; + +// export default Questions;