From 7d16739a717e4a57ce371a31585e7c5a46d2a87c Mon Sep 17 00:00:00 2001 From: ShivaniYadav07 Date: Sun, 25 Aug 2024 00:30:34 +0530 Subject: [PATCH 1/9] update multple select and added subtopic in profile head --- src/actions/topicAction.js | 20 +++++--- src/components/EditModel.jsx | 85 +++++++++++++++++--------------- src/components/ProfileHead.jsx | 89 ++++++++++++++++++++++------------ 3 files changed, 118 insertions(+), 76 deletions(-) diff --git a/src/actions/topicAction.js b/src/actions/topicAction.js index 49e3410..06cc6f5 100644 --- a/src/actions/topicAction.js +++ b/src/actions/topicAction.js @@ -45,18 +45,26 @@ export const getTopics = (subjectName, standard, chapterNames) => async (dispatc try { dispatch({ type: GET_TOPICS_REQUEST }); - const { data } = await axios.get( - `${server}/api/get/topic?subjectName=${subjectName}&standard=${standard}&chapterName=${chapterNames}`, - { - withCredentials: true, - } - ); + // Ensure chapterNames is properly formatted as a comma-separated string + const chapters = Array.isArray(chapterNames) ? chapterNames.join(',') : chapterNames; + + // Make API call to get topics + const { data } = await axios.get(`${server}/api/get/topic`, { + params: { + subjectName, + standard, + chapterName: chapters, + }, + withCredentials: true, // Include credentials if needed + }); dispatch({ type: GET_TOPICS_SUCCESS, payload: data.topics, }); } catch (error) { + console.error('Error fetching topics:', error); // Log the error for debugging + dispatch({ type: GET_TOPICS_FAIL, payload: error.response?.data?.message || error.message, diff --git a/src/components/EditModel.jsx b/src/components/EditModel.jsx index 7043a07..49e78f8 100644 --- a/src/components/EditModel.jsx +++ b/src/components/EditModel.jsx @@ -1,6 +1,5 @@ -// EditQuestionModal.jsx -import { Select } from 'antd'; import React, { useEffect, useState } from 'react'; +import { Select } from 'antd'; import { getSubjects } from "../actions/subjectAction"; import { getChapters } from "../actions/chapterAction"; import { getTopics } from "../actions/topicAction"; @@ -18,12 +17,12 @@ const EditModel = ({ isOpen, onClose, selectedQuestion, onSave, setIsModalOpen } const { subtopics } = useSelector((state) => state.getSubtopic); const [standard, setStandard] = useState(selectedQuestion.standard || ''); const [subject, setSubject] = useState(selectedQuestion.subject || ''); - const [chapter, setChapter] = useState(selectedQuestion.chapter || ''); + const [chapter, setChapter] = useState(selectedQuestion.chapter || []); const [topic, setTopic] = useState(selectedQuestion.topics || []); const [subtopic, setSubtopic] = useState(selectedQuestion.subtopics || []); const dispatch = useDispatch(); const [error, setError] = useState(''); - if (!isOpen) return null; + useEffect(() => { if (standard) { dispatch(getSubjects(standard)); @@ -31,36 +30,39 @@ const EditModel = ({ isOpen, onClose, selectedQuestion, onSave, setIsModalOpen } if (subject && standard) { dispatch(getChapters(subject, standard)); } - + const fetchTopics = async () => { if (subject && standard && chapter.length > 0) { - setError(''); // Clear any error if chapters are selected - let allTopics = []; // To store all topics from selected chapters - for (const chap of chapter) { - const response = await dispatch(getTopics(subject, standard, chap)); - allTopics = [...allTopics, ...response.topics]; // Combine topics from all chapters + setError(''); + try { + // Fetch topics for all selected chapters in one go + const chapterNames = chapter.join(','); // Convert array to comma-separated string + const response = await dispatch(getTopics(subject, standard, chapterNames)); + + if (response && response.payload) { + setTopic(response.payload); + } + } catch (error) { + console.error('Error fetching topics:', error); } - setTopic(allTopics); // Set the combined topics if different from current state } else if (subject && standard && chapter.length === 0) { setError('Chapter selection is required.'); } }; - - fetchTopics(); // Call the function to fetch topics - - if (subject && standard && chapter.length > 0 && topic) { + + fetchTopics(); + + if (subject && standard && chapter.length > 0 && topic.length > 0) { dispatch(getSubtopics(subject, standard, chapter, topic)); } - }, [dispatch, standard, subject, chapter, topic, subtopic]); - + }, [dispatch, standard, subject, chapter, topic]); // Add `topic` to dependency array + const handleSaveChanges = async () => { - // Check if chapter is selected if (!chapter || chapter.length === 0) { setError('Chapter selection is required.'); - return; // Prevent form submission if chapter is not selected + return; } - - // Create the updated question object after validation passes + const updatedQuestion = { standard, subject, @@ -68,16 +70,15 @@ const EditModel = ({ isOpen, onClose, selectedQuestion, onSave, setIsModalOpen } topics: topic, subtopics: subtopic, }; - + try { - // Send the PUT request to update the question const response = await axios.put(`${server}/api/updatequestion/${selectedQuestion._id}`, updatedQuestion); const data = response.data; - + if (response.status === 200) { onSave(data.question); toast.success("Updated successfully"); - setIsModalOpen(false); // Close the modal after successful update + setIsModalOpen(false); } else { console.error('Failed to update question:', data.message); toast.error('Failed to update question: ' + data.message); @@ -87,8 +88,6 @@ const EditModel = ({ isOpen, onClose, selectedQuestion, onSave, setIsModalOpen } toast.error('Error updating question: ' + error.message); } }; - - const handleOverlayClick = (e) => { if (e.target === e.currentTarget) { @@ -104,10 +103,11 @@ const EditModel = ({ isOpen, onClose, selectedQuestion, onSave, setIsModalOpen } >
e.stopPropagation()} + onClick={(e) => e.stopPropagation()} >

Edit Details

+ {/* Standard Selector */}
{ setSubject(value); - setChapter(null); - setTopic(null); - setSubtopic(null) + setChapter([]); + setTopic([]); + setSubtopic([]); }} options={subjectList?.map((name) => ({ value: name, @@ -152,11 +153,12 @@ const EditModel = ({ isOpen, onClose, selectedQuestion, onSave, setIsModalOpen } Subject
+ + {/* Chapter Selector */}
{ setTopic(value); + setSubtopic([]); // Clear subtopics when topics change }} options={topicList?.map((el) => ({ value: el.name, @@ -202,6 +206,8 @@ const EditModel = ({ isOpen, onClose, selectedQuestion, onSave, setIsModalOpen } Topic
+ + {/* Subtopic Selector */}
{ - setSelectedChapter(value); - setSelectedTopic(""); - setSelectedQuestion(null); - setCurrentPage(1) - setMyCurrentPage(1) - }} - filterOption={(input, option) => - (option.label ?? "") - .toLowerCase() - .includes(input.toLowerCase()) - } - options={chapterList?.map((chapter) => ({ - value: chapter.name, - label: chapter.name, - }))} - /> -
+
+ Date: Mon, 26 Aug 2024 02:20:45 +0530 Subject: [PATCH 2/9] fixed render for profileHead --- src/components/ProfileHead.jsx | 901 ++++++++++++++++++--------------- src/pages/CreateQuestion.jsx | 42 +- 2 files changed, 529 insertions(+), 414 deletions(-) diff --git a/src/components/ProfileHead.jsx b/src/components/ProfileHead.jsx index 1fae352..829bc28 100644 --- a/src/components/ProfileHead.jsx +++ b/src/components/ProfileHead.jsx @@ -15,12 +15,11 @@ import { getTopics } from "../actions/topicAction"; import Loading from "../pages/Loading"; import ViewChapTop from "./ViewChapTop"; import { getSubtopics } from "../actions/subtopicAction"; - - +import _ from 'lodash'; function debounce(func, delay) { let timeoutId; - return function(...args) { + return function (...args) { if (timeoutId) { clearTimeout(timeoutId); } @@ -30,8 +29,6 @@ function debounce(func, delay) { }; } - - const ProfileHead = ({ setSelectedQuestion, toBottom }) => { const [questions, setQuestions] = useState([]); const [userTodayQuestions, setUserTodayQuestions] = useState(""); @@ -42,8 +39,8 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { const [myTodayQuestions, setTodayMyQuestions] = useState(""); const [selectedStandard, setSelectedStandard] = useState(""); const [selectedSubject, setSelectedSubject] = useState(""); - const [selectedChapter, setSelectedChapter] = useState(""); - const [selectedTopic, setSelectedTopic] = useState(""); + const [selectedChapter, setSelectedChapter] = useState([]); + const [selectedTopic, setSelectedTopic] = useState([]); // eslint-disable-next-line no-unused-vars const [subjects, setSubjects] = useState([]); // eslint-disable-next-line no-unused-vars @@ -73,10 +70,12 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { const [searchMyQuery, setSearchMyQuery] = useState(""); const questionsPerPage = 50; const [inputValue, setInputValue] = useState(''); - // eslint-disable-next-line no-unused-vars + const [selectedSubtopics, setSelectedSubtopics] = useState([]); + const [isSubtopicsLoading, setIsSubtopicsLoading] = useState(false); + // eslint-disable-next-line no-unused-vars const [myInputValue, setMyInputValue] = useState(''); - const inputRef = useRef(null); - const myInputRef = useRef(null); + const inputRef = useRef(null); + const myInputRef = useRef(null); const dispatch = useDispatch(); @@ -84,47 +83,79 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { const { subjectList } = useSelector((state) => state.getSubject); const { chapterList } = useSelector((state) => state.getChapter); const { topicList } = useSelector((state) => state.getTopic); + const { subtopics } = useSelector((state) => state.getSubtopic); + useEffect(() => { - // Fetch subjects when standard changes if (selectedStandard) { dispatch(getSubjects(selectedStandard)); } + }, [dispatch, selectedStandard]); - // Fetch chapters when both standard and subject are selected + useEffect(() => { if (selectedSubject && selectedStandard) { dispatch(getChapters(selectedSubject, selectedStandard)); } + }, [dispatch, selectedSubject, selectedStandard]); - // Function to fetch topics + useEffect(() => { const fetchTopics = async () => { if (selectedSubject && selectedStandard && selectedChapter.length > 0) { - setError(''); try { const chapterNames = selectedChapter.join(','); // Convert array to comma-separated string const response = await dispatch(getTopics(selectedSubject, selectedStandard, chapterNames)); if (response && response.payload) { - setTopics(response.payload); + setTopicList(response.payload); } } catch (error) { console.error('Error fetching topics:', error); - setError('Error fetching topics.'); } - } else if (selectedSubject && selectedStandard) { - setError('Chapter selection is required.'); } }; fetchTopics(); + }, [dispatch, selectedSubject, selectedStandard, selectedChapter]); - // Fetch subtopics if everything is selected - if (selectedSubject && selectedStandard && selectedChapter.length > 0 && selectedTopic.length > 0) { - dispatch(getSubtopics(selectedSubject, selectedStandard, selectedChapter, selectedTopic)); - } - - }, [dispatch, selectedStandard, selectedSubject, selectedChapter, selectedTopic]); - + useEffect(() => { + const fetchSubtopics = async () => { + if ( + selectedSubject && + selectedStandard && + selectedChapter.length > 0 && + selectedTopic.length > 0 + ) { + setIsSubtopicsLoading(true); + try { + // Fetch subtopics based on selected criteria + const response = await dispatch( + getSubtopics( + selectedSubject, + selectedStandard, + selectedChapter.join(","), // Convert chapter array to comma-separated string + selectedTopic.join(",") // Convert topic array to comma-separated string + ) + ); + + if (response && response.payload) { + setSelectedSubtopics(response.payload); // Update state with fetched subtopics + } else { + setSelectedSubtopics([]); // Reset subtopics if no data is received + } + } catch (error) { + console.error("Error fetching subtopics:", error); + setSelectedSubtopics([]); // Reset subtopics on error + } finally { + setIsSubtopicsLoading(false); + } + } else { + setSelectedSubtopics([]); // Reset subtopics if required fields are not selected + } + }; + + fetchSubtopics(); + }, [dispatch, selectedSubject, selectedStandard, selectedChapter, selectedTopic]); + const { user } = useSelector((state) => state.user); const isAdmin = user?.role === "admin"; @@ -136,6 +167,7 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { selectedSubject, selectedChapter, selectedTopic, + selectedSubtopics, selectedUser, searchKeyword, ); @@ -145,6 +177,7 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { selectedSubject, selectedChapter, selectedTopic, + selectedSubtopics, searchMyQuery ); } @@ -153,6 +186,7 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { selectedSubject, selectedChapter, selectedTopic, + selectedSubtopics, activeTabIndex, selectedUser, searchKeyword, @@ -164,47 +198,99 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { subject, chapter, topic, + subtopic, createdBy, - limit, - page + limit, + page ) => { setLoading(true); try { const response = await axios.get(`${server}/api/get/question`, { params: { - standard: selectedStandard, + standard, subject, chapter, topic, + subtopic, createdBy, - limit: questionsPerPage, + limit, page, - search: searchKeyword, + search: searchKeyword, }, withCredentials: true, }); - + if (response.data.success) { const questions = response.data.questions; - setQuestions(questions.reverse()); + setQuestions(questions.reverse()); setUserTodayQuestions(response.data?.todaysQuestionsCount); setUserRank(response.data?.userRank); setTopperUser(response.data?.topperUser); const totalQuestions = response.data.totalQuestions || 0; setTotalQuestions(totalQuestions); - setTotalPages(Math.ceil(totalQuestions / limit)); + setTotalPages(Math.ceil(totalQuestions / limit)); } else { setQuestions([]); } } catch (error) { - console.error(error); - toast.error(error.message); + console.error("Error fetching questions:", error); + toast.error("Failed to fetch questions. Please try again."); } finally { setLoading(false); } }; + + const fetchTotalQuestionsDebounced = useCallback( + _.debounce(async ( + standard, + subject, + chapter, + topic, + subtopic, + createdBy, + search, + mySearch + ) => { + try { + const response = await axios.get(`${server}/api/get/totalquestion`, { + params: { + standard, + subject, + chapter, + topic, + subtopic, + createdBy, + search, + mySearch, + }, + withCredentials: true, + }); + + if (response.data.success) { + const fixedMyTotalQuestions = response.data.totalMyQuestions || 0; + setFixedTotalMyQuestions(fixedMyTotalQuestions); + const fixedTotalQuestions = response.data.fixedTotalQuestions || 0; + setFixedTotalQuestions(fixedTotalQuestions); + setTotalQuestions(response.data.totalQuestions); + setQuestionsLength(response.data.questionsLength); + setTotalPages( + Math.ceil(response.data.totalQuestions / questionsPerPage) + ); + + setMyTotalPages( + Math.ceil(response.data.questionsLength / questionsPerPage) + ); + } + } catch (error) { + console.error(error); + toast.error("Failed to fetch total questions count"); + } + }, 500), + [] + ); + - const fetchUserQuestions = async (standard, subject, chapter, topic, limit, page) => { + const fetchUserQuestions = async (standard, subject, chapter, topicList, subtopic, limit, page) => { setLoading(true); try { const response = await axios.get(`${server}/api/get/myquestion`, { @@ -213,9 +299,10 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { subject, chapter, topicList, + subtopic, limit: questionsPerPage, page, - search: searchMyQuery, + search: searchMyQuery, }, withCredentials: true, }); @@ -256,52 +343,8 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { } }; - - const fetchTotalQuestions = async ( - standard, - subject, - chapter, - topic, - createdBy, - search, - mySearch - ) => { - try { - const response = await axios.get(`${server}/api/get/totalquestion`, { - params: { - standard, - subject, - chapter, - topic, - createdBy, - search, - mySearch, - }, - withCredentials: true, - }); - - if (response.data.success) { - const fixedMyTotalQuestions = response.data.totalMyQuestions || 0; - setFixedTotalMyQuestions(fixedMyTotalQuestions); - const fixedTotalQuestions = response.data.fixedTotalQuestions || 0; - setFixedTotalQuestions(fixedTotalQuestions); - setTotalQuestions(response.data.totalQuestions); - setQuestionsLength(response.data.questionsLength); - setTotalPages( - Math.ceil(response.data.totalQuestions / questionsPerPage) - ); - - setMyTotalPages( - Math.ceil(response.data.questionsLength / questionsPerPage) - ); - } - } catch (error) { - console.error(error); - toast.error("Failed to fetch total questions count"); - } - }; - + useEffect(() => { fetchUsers( @@ -346,33 +389,33 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { setMyCurrentPage(1) }; -const handleTabChange = (index) => { - setSelectedStandard("") - setSelectedQuestion(null); - setActiveTabIndex(index); - setCurrentPage(1); - setMyCurrentPage(1); - setSelectedSubject(""); - setSelectedChapter(""); - setSelectedTopic(""); - setSubjects([]); - setChapters([]); - setTopics([]); - setMySubjects([]); - setMyChapters([]); - setMyTopics([]); - setQuestions([]); - setSelectedUser(null); - setMyQuestions([]); - setMyRank(""); - setUserRank(""); - setUserTodayQuestions(""); - setTodayMyQuestions(""); - setSearchMyQuery(""); - setSearchKeyword(""); - setInputValue(""); - setMyInputValue("") -}; + const handleTabChange = (index) => { + setSelectedStandard("") + setSelectedQuestion(null); + setActiveTabIndex(index); + setCurrentPage(1); + setMyCurrentPage(1); + setSelectedSubject(""); + setSelectedChapter(""); + setSelectedTopic(""); + setSubjects([]); + setChapters([]); + setTopics([]); + setMySubjects([]); + setMyChapters([]); + setMyTopics([]); + setQuestions([]); + setSelectedUser(null); + setMyQuestions([]); + setMyRank(""); + setUserRank(""); + setUserTodayQuestions(""); + setTodayMyQuestions(""); + setSearchMyQuery(""); + setSearchKeyword(""); + setInputValue(""); + setMyInputValue("") + }; useEffect(() => { if (!isAdmin) { setActiveTabIndex(1); @@ -381,8 +424,9 @@ const handleTabChange = (index) => { useEffect(() => { setSelectedSubject(""); - setSelectedChapter(""); - setSelectedTopic(""); + setSelectedChapter([]); + setSelectedTopic([]); + setSelectedSubtopics([]) setSelectedUser(""); setSubjects([]); setChapters([]); @@ -415,16 +459,21 @@ const handleTabChange = (index) => { setSelectedUser(value); setUserRank(""); setUserTodayQuestions(""); - - }; - useEffect(() => { - fetchTotalQuestions(selectedStandard, selectedSubject, selectedChapter, selectedTopic, selectedUser, searchKeyword, searchMyQuery); + }; + useEffect(() => { + fetchTotalQuestionsDebounced( + selectedStandard, + selectedSubject, + selectedChapter, + selectedTopic, + selectedSubtopics, + selectedUser, + searchKeyword, + searchMyQuery + ); }); - - - const handleQuestionClick = (question) => { setSelectedQuestion(question); toBottom(); @@ -440,6 +489,7 @@ const handleTabChange = (index) => { selectedSubject, selectedChapter, selectedTopic, + selectedSubtopics, selectedUser, questionsPerPage, newPage @@ -454,6 +504,7 @@ const handleTabChange = (index) => { selectedSubject, selectedChapter, selectedTopic, + selectedSubtopics, questionsPerPage, newPage ); @@ -471,6 +522,7 @@ const handleTabChange = (index) => { selectedSubject, selectedChapter, selectedTopic, + selectedSubtopics, selectedUser, questionsPerPage, newPage @@ -485,84 +537,124 @@ const handleTabChange = (index) => { selectedSubject, selectedChapter, selectedTopic, + selectedSubtopics, questionsPerPage, newPage ); } } }; - + const handleSearch = useCallback( debounce((keyword) => { - setCurrentPage(1); + setCurrentPage(1); setSearchKeyword(keyword); if (inputRef.current) { - inputRef.current.focus(); + inputRef.current.focus(); } - fetchQuestions(keyword); - }, 300), + fetchQuestions(keyword); + }, 300), [] ); const handleSearchChange = (e) => { setCurrentPage(1); - const value = e.target.value; + const value = e.target.value; setInputValue(value); if (value === '') { resetSearchResults(); } else if (value.endsWith(' ') || value.endsWith('\n')) { - const trimmedValue = value.trim(); + const trimmedValue = value.trim(); handleSearch(trimmedValue); } }; const handleSearchClick = () => { handleSearch(inputValue.trim()); }; - const resetSearchResults = () => { + const resetSearchResults = () => { setSearchKeyword(''); setInputValue(''); - }; + }; - const handleMySearch = useCallback( + const handleMySearch = useCallback( debounce((keyword) => { setMyCurrentPage(1); setSearchMyQuery(keyword); if (myInputRef.current) { - myInputRef.current.focus(); + myInputRef.current.focus(); } - fetchUserQuestions(keyword); - }, 300), + fetchUserQuestions(keyword); + }, 300), [] ); const handleMySearcChange = (e) => { setMyCurrentPage(1); - const value = e.target.value; + const value = e.target.value; setMyInputValue(value); -// setSearchMyQuery(e.target.value) + // setSearchMyQuery(e.target.value) if (value === '') { - + resetMySearchResults(); } else if (value.endsWith(' ') || value.endsWith('\n')) { - const trimmedValue = value.trim(); + const trimmedValue = value.trim(); handleMySearch(trimmedValue); } } const resetMySearchResults = () => { setSearchMyQuery(''); - setMyInputValue(''); + setMyInputValue(''); }; const handleMySearchClick = () => { fetchUserQuestions(handleMySearch) } + const renderSubtopicSelectors = (subtopics, level) => { + if (!subtopics || subtopics.length === 0) { + return null; // Return early if there are no subtopics + } + + return ( + +
+
+ + {/* Topic Selection */} + {subtopics.length > 0 && ( + - (option.label ?? "").toLowerCase().includes(input.toLowerCase()) - } - onChange={(value) => { - setSelectedChapter(value); - setSelectedTopic(""); - setSelectedQuestion(null); - setCurrentPage(1) - setMyCurrentPage(1) - }} - options={chapterList?.map((chapter) => ({ - value: chapter.name, - label: chapter.name, - }))} - value={selectedChapter} - /> - -
-
-
-
- - + (option.label ?? "").toLowerCase().includes(input.toLowerCase()) + } + onChange={(value) => { + setSelectedChapter(value); + setSelectedTopic([]); + setSelectedSubtopics([]); + }} + options={chapterList?.map((chapter) => ({ + value: chapter.name, + label: chapter.name, + }))} + value={selectedChapter} + /> + +
+
+ +
+
+ + + - -
- )} - - {activeTabIndex === 1 && ( -
- - -
- )} -
- - {isAdmin && ( - + + + + {selectedUser && ( + + )} + {selectedUser && userRank && ( + + )} +
+ {activeTabIndex === 0 && ( +
+ + +
+ )} + + {activeTabIndex === 1 && ( +
+ + +
+ )} +
+ + {isAdmin && ( + +
+ {loading ? ( + + ) : ( + <> +

+ Total Questions: {totalQuestions} +

+ + {totalQuestions === 0 ? ( +
+ No questions found. +
+ ) : ( + filteredQuestions.map((question, index) => ( +
handleQuestionClick(question)} + className="cursor-pointer text-gray-900 p-2 " + > + + Q. + {(currentPage - 1) * questionsPerPage + index + 1} + + +
+ )) + )} + + )} +
+
+ +

+ + {totalQuestions === 0 ? "0 / " : `${currentPage} / `} + + + {totalQuestions === 0 ? "0" : totalPages} + +

+ + +
+
+ )} + + {activeTabIndex === 1 ? ( +
+ + +
+ ) : null} + +
{loading ? ( ) : ( <>

- Total Questions: {totalQuestions} + Total Questions: {questionsLength}

- {totalQuestions === 0 ? ( + {questionsLength === 0 ? (
No questions found.
) : ( - filteredQuestions.map((question, index) => ( + filteredMyQuestions.map((question, index) => (
handleQuestionClick(question)} - className="cursor-pointer text-gray-900 p-2 " + className="cursor-pointer text-gray-900 p-2" > - Q. - {(currentPage - 1) * questionsPerPage + index + 1} + Q.{" "} + {(myCurrentPage - 1) * questionsPerPage + index + 1} {

- {totalQuestions === 0 ? "0 / " : `${currentPage} / `} + {questionsLength === 0 ? "0 / " : `${myCurrentPage} / `} - {totalQuestions === 0 ? "0" : totalPages} + {questionsLength === 0 ? "0" : myTotalPages}

- )} - - {activeTabIndex === 1 ? ( -
- - -
- ) : null} - - -
- {loading ? ( - - ) : ( - <> -

- Total Questions: {questionsLength} -

- - {questionsLength === 0 ? ( -
- No questions found. -
- ) : ( - filteredMyQuestions.map((question, index) => ( -
handleQuestionClick(question)} - className="cursor-pointer text-gray-900 p-2" - > - - Q.{" "} - {(myCurrentPage - 1) * questionsPerPage + index + 1} - - -
- )) - )} - - )} -
-
- -

- - {questionsLength === 0 ? "0 / " : `${myCurrentPage} / `} - - - {questionsLength === 0 ? "0" : myTotalPages} - -

- - -
-
- - - ) : ( + + + ) : (
Loading...
)}
diff --git a/src/pages/CreateQuestion.jsx b/src/pages/CreateQuestion.jsx index 697b03a..c3ce349 100644 --- a/src/pages/CreateQuestion.jsx +++ b/src/pages/CreateQuestion.jsx @@ -189,39 +189,53 @@ const CreateQuestion = () => { ); - - useEffect(() => { + // Fetch subjects when the standard changes if (standard) { dispatch(getSubjects(standard)); } - if (subject && standard) { + + // Fetch chapters when both standard and subject are selected + if (standard && subject) { dispatch(getChapters(subject, standard)); } + + // Function to fetch topics for selected chapters const fetchTopics = async () => { - if (subject && standard && chapter) { - let allTopics = []; // To store all topics from selected chapters - for (const chap of chapter) { - const response = await dispatch(getTopics(subject, standard, chap)); - allTopics = [...allTopics, ...response.topic]; // Combine topics from all chapters + if (standard && subject && chapter && chapter.length > 0) { + const chapterNames = chapter.join(','); // Join chapter names with commas + + try { + const response = await dispatch(getTopics(subject, standard, chapterNames)); + if (response && response.payload && response.payload.success) { + // Assuming you have some logic to handle the fetched topics + // e.g., setting them in local state or using Redux state } - } - }; + } catch (error) { + console.error('Error fetching topics:', error); + } + } + }; - fetchTopics(); - if (subject && standard && chapter && topic) { + // Fetch topics based on the selected chapters + fetchTopics(); + + // Fetch subtopics only when all criteria are met + if (standard && subject && chapter && chapter.length > 0 && topic && topic.length > 0) { setIsSubtopicsLoading(true); dispatch(getSubtopics(subject, standard, chapter, topic)) - .then(() => { + .then((response) => { setIsSubtopicsLoading(false); }) - .catch(() => { + .catch((error) => { + console.error('Error fetching subtopics:', error); setIsSubtopicsLoading(false); }); } else { setIsSubtopicsLoading(false); } }, [dispatch, standard, subject, chapter, topic]); + const uploadImageToS3 = async (file, signedUrl) => { const response = await fetch(signedUrl, { From 9336f9a0475ddb00bc873f82e9efa7c81206ff53 Mon Sep 17 00:00:00 2001 From: ShivaniYadav07 Date: Wed, 28 Aug 2024 01:19:18 +0530 Subject: [PATCH 3/9] fixin frontend ... --- src/components/ProfileHead.jsx | 189 +++++++++++++++++++++------------ src/pages/Profile.jsx | 16 +-- 2 files changed, 129 insertions(+), 76 deletions(-) diff --git a/src/components/ProfileHead.jsx b/src/components/ProfileHead.jsx index 829bc28..b3718e0 100644 --- a/src/components/ProfileHead.jsx +++ b/src/components/ProfileHead.jsx @@ -5,7 +5,7 @@ import axios from "axios"; import classNames from "classnames"; import toast from "react-hot-toast"; import { useSelector, useDispatch } from "react-redux"; -import { Select } from "antd"; +import { Checkbox, Select } from "antd"; import { standards } from "../components/Options"; import { server } from "../main"; import "../styles/login.scss"; @@ -29,7 +29,7 @@ function debounce(func, delay) { }; } -const ProfileHead = ({ setSelectedQuestion, toBottom }) => { +const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { const [questions, setQuestions] = useState([]); const [userTodayQuestions, setUserTodayQuestions] = useState(""); const [userRank, setUserRank] = useState(""); @@ -62,7 +62,6 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { const [myCurrentPage, setMyCurrentPage] = useState(1); const [myTotalPages, setMyTotalPages] = useState(1); const [totalQuestions, setTotalQuestions] = useState(0); - // const [MyTotalQuestions, setMyTotalQuestions] = useState(0); const [questionsLength, setQuestionsLength] = useState(0); const [fixedTotalQuestions, setFixedTotalQuestions] = useState(0); const [fixedMyTotalQuestions, setFixedTotalMyQuestions] = useState(0); @@ -72,18 +71,18 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { const [inputValue, setInputValue] = useState(''); const [selectedSubtopics, setSelectedSubtopics] = useState([]); const [isSubtopicsLoading, setIsSubtopicsLoading] = useState(false); - // eslint-disable-next-line no-unused-vars const [myInputValue, setMyInputValue] = useState(''); const inputRef = useRef(null); const myInputRef = useRef(null); const dispatch = useDispatch(); - - - const { subjectList } = useSelector((state) => state.getSubject); const { chapterList } = useSelector((state) => state.getChapter); const { topicList } = useSelector((state) => state.getTopic); const { subtopics } = useSelector((state) => state.getSubtopic); + const [selectAll, setSelectAll] = useState(false); + const [selectedQuestions, setSelectedQuestions] = useState({}); + // State to track the currently expanded question + const [viewedQuestionId, setViewedQuestionId] = useState(null); useEffect(() => { @@ -649,6 +648,28 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { ); }; + const handleSelectAll = () => { + if (selectAll) { + setSelectedQuestions({}); // deselect all + } else { + const selectedQuestions = {}; + questions.forEach((question) => { + selectedQuestions[question._id] = true; + }); + setSelectedQuestions(selectedQuestions); + } + setSelectAll(!selectAll); + }; + + const handleSelectQuestion = (questionId) => { + const newSelectedQuestions = { ...selectedQuestions }; + if (newSelectedQuestions[questionId]) { + delete newSelectedQuestions[questionId]; + } else { + newSelectedQuestions[questionId] = true; + } + setSelectedQuestions(newSelectedQuestions); + }; @@ -959,72 +980,101 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => {
{isAdmin && ( - -
- {loading ? ( - - ) : ( - <> -

- Total Questions: {totalQuestions} -

+ +
+ {loading ? ( + + ) : ( + <> +

+ Total Questions: {totalQuestions} +

- {totalQuestions === 0 ? ( -
- No questions found. -
- ) : ( - filteredQuestions.map((question, index) => ( -
handleQuestionClick(question)} - className="cursor-pointer text-gray-900 p-2 " - > - - Q. - {(currentPage - 1) * questionsPerPage + index + 1} - - -
- )) - )} - - )} -
-
- -

- - {totalQuestions === 0 ? "0 / " : `${currentPage} / `} - - - {totalQuestions === 0 ? "0" : totalPages} - -

+ {/* Only show the question list if there are questions */} + {totalQuestions > 0 && filteredQuestions.length > 0 ? ( + <> + {(selectedTopic && selectedSubtopics.length === 0) || (selectedTopic && selectedSubtopics.length > 0) ? ( +
+ + Select All + +
+ ) : null} - + {/* Display the questions with checkboxes only if a topic is selected */} + {selectedTopic ? ( + filteredQuestions.map((question, index) => ( +
handleQuestionClick(question)} + className="cursor-pointer text-gray-900 p-2 flex items-start space-x-4" + > + {selectedTopic && selectedSubtopics.length > 0 && ( + handleSelectQuestion(question._id)} + onClick={(e) => { + e.stopPropagation(); + }} + /> + )} +
+ + Q. {(currentPage - 1) * questionsPerPage + index + 1} + + +
- + )) + ) : ( +
+ Please select a topic to view questions. +
)} + + ) : ( +
+ No questions available. +
+ )} + + )} +
+
+ +

+ + {totalQuestions === 0 ? "0 / " : `${currentPage} / `} + + + {totalQuestions === 0 ? "0" : totalPages} + +

+ +
+
+)} + + + + + {activeTabIndex === 1 ? (
@@ -1114,6 +1164,7 @@ const ProfileHead = ({ setSelectedQuestion, toBottom }) => { ProfileHead.propTypes = { setSelectedQuestion: PropTypes.func.isRequired, toBottom: PropTypes.func.isRequired, + selectedQuestion: PropTypes.func.isRequired }; export default ProfileHead; diff --git a/src/pages/Profile.jsx b/src/pages/Profile.jsx index 975b7ef..afc84bc 100644 --- a/src/pages/Profile.jsx +++ b/src/pages/Profile.jsx @@ -288,7 +288,7 @@ const Profile = () => { return (
- + {selectedQuestion ? (
@@ -358,18 +358,20 @@ const Profile = () => {

Class: {selectedQuestion.standard}

Subject: {selectedQuestion.subject}

-

Chapter: {selectedQuestion.chapter.join(", ")}

+

Chapter: {selectedQuestion?.chapter?.join(", ")}

Topics: {selectedQuestion && selectedQuestion.topics ? selectedQuestion.topics.join(", ") : "No topics available"}

Level: {selectedQuestion.level}

- Subtopics:{" "} - {selectedQuestion.subtopics.length > 0 - ? selectedQuestion.subtopics.join(", ") - : "N/A"} -

+ Subtopics:{" "} + {selectedQuestion && selectedQuestion.subtopics + ? selectedQuestion.subtopics.length > 0 + ? selectedQuestion.subtopics.join(", ") + : "No subtopics" + : "N/A"} +

Nested Subtopic: {selectedQuestion.nestedSubTopic || "N/A"}

From 3269e0d8293404dbc9ccbcbe7b0964d5e3c6f764 Mon Sep 17 00:00:00 2001 From: ShivaniYadav07 Date: Fri, 30 Aug 2024 01:25:15 +0530 Subject: [PATCH 4/9] update --- src/components/ProfileHead.jsx | 628 ++++++++++++++++++++++----------- 1 file changed, 425 insertions(+), 203 deletions(-) diff --git a/src/components/ProfileHead.jsx b/src/components/ProfileHead.jsx index b3718e0..9ccb7f6 100644 --- a/src/components/ProfileHead.jsx +++ b/src/components/ProfileHead.jsx @@ -5,7 +5,7 @@ import axios from "axios"; import classNames from "classnames"; import toast from "react-hot-toast"; import { useSelector, useDispatch } from "react-redux"; -import { Checkbox, Select } from "antd"; +import { Button, Checkbox, Modal, Select } from "antd"; import { standards } from "../components/Options"; import { server } from "../main"; import "../styles/login.scss"; @@ -51,6 +51,7 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { const [myChapters, setMyChapters] = useState([]); // eslint-disable-next-line no-unused-vars const [topics, setTopics] = useState([]); + const [subTopics, setSubtopics] = useState([]); // eslint-disable-next-line no-unused-vars const [myTopics, setMyTopics] = useState([]); const [activeTabIndex, setActiveTabIndex] = useState(0); @@ -81,10 +82,18 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { const { subtopics } = useSelector((state) => state.getSubtopic); const [selectAll, setSelectAll] = useState(false); const [selectedQuestions, setSelectedQuestions] = useState({}); - // State to track the currently expanded question - const [viewedQuestionId, setViewedQuestionId] = useState(null); + const [isModalOpen, setIsModalOpen] = useState(false); + const [areQuestionsSelected, setAreQuestionsSelected] = useState(false); + const [selectedTopic1, setSelectedTopic1] = useState([]); + const [selectedSubtopics1, setSelectedSubtopics1] = useState([]); + useEffect(() => { + // Check if any question is selected to update button state + const anySelected = Object.values(selectedQuestions).some(Boolean); + setAreQuestionsSelected(anySelected); + }, [selectedQuestions]); + useEffect(() => { if (selectedStandard) { dispatch(getSubjects(selectedStandard)); @@ -105,7 +114,9 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { const response = await dispatch(getTopics(selectedSubject, selectedStandard, chapterNames)); if (response && response.payload) { - setTopicList(response.payload); + setTopics(response.payload); + selectedTopic1(response.payload) + } } catch (error) { console.error('Error fetching topics:', error); @@ -122,39 +133,83 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { selectedSubject && selectedStandard && selectedChapter.length > 0 && - selectedTopic.length > 0 + (selectedTopic.length > 0) ) { setIsSubtopicsLoading(true); try { - // Fetch subtopics based on selected criteria + const response = await dispatch( getSubtopics( selectedSubject, selectedStandard, selectedChapter.join(","), // Convert chapter array to comma-separated string - selectedTopic.join(",") // Convert topic array to comma-separated string + selectedTopic.join(",") ) ); - + if (response && response.payload) { - setSelectedSubtopics(response.payload); // Update state with fetched subtopics + const fetchedSubtopics = response.payload; + setSubtopics(fetchedSubtopics); + setSelectedSubtopics1([]); // Clear previously selected subtopics } else { - setSelectedSubtopics([]); // Reset subtopics if no data is received + setSubtopics([]); + setSelectedSubtopics1([]); } } catch (error) { console.error("Error fetching subtopics:", error); - setSelectedSubtopics([]); // Reset subtopics on error + setSubtopics([]); + setSelectedSubtopics1([]); } finally { setIsSubtopicsLoading(false); } } else { - setSelectedSubtopics([]); // Reset subtopics if required fields are not selected + setSubtopics([]); + setSelectedSubtopics1([]); } }; - + fetchSubtopics(); - }, [dispatch, selectedSubject, selectedStandard, selectedChapter, selectedTopic]); - + }, [dispatch, selectedSubject, selectedStandard, selectedChapter, selectedTopic, selectedTopic1]); + + useEffect(() => { + const fetchSubtopicsForTopic1 = async () => { + if ( + selectedSubject && + selectedStandard && + selectedChapter.length > 0 && + selectedTopic1.length > 0 + ) { + setIsSubtopicsLoading(true); + try { + const response = await dispatch( + getSubtopics( + selectedSubject, + selectedStandard, + selectedChapter.join(","), + selectedTopic1.join(",") // Fetch subtopics based on selectedTopic1 + ) + ); + + if (response && response.payload) { + // Update or merge subtopics if needed + setSelectedSubtopics1(response.payload); + } else { + setSelectedSubtopics1([]); + } + } catch (error) { + console.error("Error fetching subtopics for topic1:", error); + setSelectedSubtopics1([]); + } finally { + setIsSubtopicsLoading(false); + } + } else { + setSelectedSubtopics1([]); + } + }; + + fetchSubtopicsForTopic1(); + }, [dispatch, selectedSubject, selectedStandard, selectedChapter, selectedTopic1]); + const { user } = useSelector((state) => state.user); const isAdmin = user?.role === "admin"; @@ -167,6 +222,8 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { selectedChapter, selectedTopic, selectedSubtopics, + selectedSubtopics1, + selectedTopic1, selectedUser, searchKeyword, ); @@ -186,6 +243,8 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { selectedChapter, selectedTopic, selectedSubtopics, + selectedSubtopics1, + selectedTopic1, activeTabIndex, selectedUser, searchKeyword, @@ -198,47 +257,60 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { chapter, topic, subtopic, - createdBy, - limit, - page + limit, + page ) => { setLoading(true); + try { + const params = { + standard, + subject, + chapter, + topic, + subtopic, + limit, + page, + search: searchKeyword, + }; + + + const response = await axios.get(`${server}/api/get/question`, { - params: { - standard, - subject, - chapter, - topic, - subtopic, - createdBy, - limit, - page, - search: searchKeyword, - }, + params, withCredentials: true, }); - + if (response.data.success) { const questions = response.data.questions; - setQuestions(questions.reverse()); + setQuestions(questions.reverse()); setUserTodayQuestions(response.data?.todaysQuestionsCount); setUserRank(response.data?.userRank); setTopperUser(response.data?.topperUser); + const totalQuestions = response.data.totalQuestions || 0; setTotalQuestions(totalQuestions); - setTotalPages(Math.ceil(totalQuestions / limit)); + setTotalPages(Math.ceil(totalQuestions / limit)); } else { setQuestions([]); } } catch (error) { console.error("Error fetching questions:", error); - toast.error("Failed to fetch questions. Please try again."); + + if (error.response && error.response.data && error.response.data.message) { + // Display specific error message from the response if available + toast.error(error.response.data.message); + } else { + // Fallback error message + toast.error("Failed to fetch questions. Please try again."); + } } finally { setLoading(false); } }; - + + + const fetchTotalQuestionsDebounced = useCallback( _.debounce(async ( standard, @@ -257,14 +329,14 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { subject, chapter, topic, - subtopic, + subtopic, createdBy, search, mySearch, }, withCredentials: true, }); - + if (response.data.success) { const fixedMyTotalQuestions = response.data.totalMyQuestions || 0; setFixedTotalMyQuestions(fixedMyTotalQuestions); @@ -275,7 +347,7 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { setTotalPages( Math.ceil(response.data.totalQuestions / questionsPerPage) ); - + setMyTotalPages( Math.ceil(response.data.questionsLength / questionsPerPage) ); @@ -287,7 +359,7 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { }, 500), [] ); - + const fetchUserQuestions = async (standard, subject, chapter, topicList, subtopic, limit, page) => { setLoading(true); @@ -385,7 +457,7 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { setInputValue(""); setMyInputValue("") setCurrentPage(1); - setMyCurrentPage(1) + setMyCurrentPage(1); }; const handleTabChange = (index) => { @@ -395,8 +467,8 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { setCurrentPage(1); setMyCurrentPage(1); setSelectedSubject(""); - setSelectedChapter(""); - setSelectedTopic(""); + setSelectedChapter([]); + setSelectedTopic([]); setSubjects([]); setChapters([]); setTopics([]); @@ -413,7 +485,9 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { setSearchMyQuery(""); setSearchKeyword(""); setInputValue(""); - setMyInputValue("") + setMyInputValue(""); + setSelectedTopic1([]); + setSelectedSubtopics1([]) }; useEffect(() => { if (!isAdmin) { @@ -441,6 +515,8 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { setSearchKeyword('') setCurrentPage(1); setMyCurrentPage(1) + setSelectedTopic1([]); + setSelectedSubtopics1([]); }, [user]); const filteredQuestions = questions.filter( @@ -458,6 +534,8 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { setSelectedUser(value); setUserRank(""); setUserTodayQuestions(""); + setSelectedTopic([]); + setSelectedSubtopics([]) }; useEffect(() => { @@ -472,7 +550,7 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { searchMyQuery ); }); - + const handleQuestionClick = (question) => { setSelectedQuestion(question); toBottom(); @@ -613,15 +691,15 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { if (!subtopics || subtopics.length === 0) { return null; // Return early if there are no subtopics } - + return ( - -
-
- - {/* Topic Selection */} - {subtopics.length > 0 && ( +
+
+ + + {/* Topic Selection */} + {subtopics.length > 0 && ( setSelectedSubtopics1(value)} + loading={isSubtopicsLoading} + options={subtopics.map((subtopic) => ({ + label: subtopic.name, + value: subtopic.name, + }))} + /> + + {/* Render recursive subtopics if they exist */} + {subtopics.map((subtopic) => ( +
+ {/* Recursive call to render further levels of subtopics */} + {renderSubtopicSelectors(subtopic.subtopics, level + 1)} +
+ ))} +
+
+ ); + }; return ( @@ -794,68 +950,68 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => {
-
-
- + (option.label ?? "").toLowerCase().includes(input.toLowerCase()) + } + onChange={(value) => { + setSelectedChapter(value); + setSelectedTopic([]); + setSelectedSubtopics([]); + }} + options={chapterList?.map((chapter) => ({ + value: chapter.name, + label: chapter.name, + }))} + value={selectedChapter} + /> + +
+
-
-
- - - + (option.label ?? "").toLowerCase().includes(input.toLowerCase()) + } + onChange={(value) => { + setSelectedTopic(value); + setSelectedSubtopics([]); + }} + options={topicList?.map((el) => ({ + value: el.name, + label: el.name, + }))} + />
+ {isSubtopicsLoading && ( +
+ +
+ )} +
+
+
+ {selectedTopic.length > 0 && !isSubtopicsLoading && ( + renderSubtopicSelectors(subtopics, 0) )} -
-
-
- {selectedTopic.length > 0 && !isSubtopicsLoading && ( - renderSubtopicSelectors(subtopics, 0) - )} -
+
{subjectList && chapterList && topicList ? ( @@ -980,101 +1136,104 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => {
{isAdmin && ( - -
- {loading ? ( - - ) : ( - <> -

- Total Questions: {totalQuestions} -

- - {/* Only show the question list if there are questions */} - {totalQuestions > 0 && filteredQuestions.length > 0 ? ( - <> - {(selectedTopic && selectedSubtopics.length === 0) || (selectedTopic && selectedSubtopics.length > 0) ? ( -
- - Select All - -
- ) : null} + +
+ {loading ? ( + + ) : ( + <> +

+ Total Questions: {totalQuestions} +

- {/* Display the questions with checkboxes only if a topic is selected */} - {selectedTopic ? ( - filteredQuestions.map((question, index) => ( -
handleQuestionClick(question)} - className="cursor-pointer text-gray-900 p-2 flex items-start space-x-4" - > - {selectedTopic && selectedSubtopics.length > 0 && ( - handleSelectQuestion(question._id)} - onClick={(e) => { - e.stopPropagation(); - }} - /> + {totalQuestions > 0 && filteredQuestions.length > 0 ? ( + <> + {selectedTopic.length > 0 && ( +
+ + Select All + + +
+ )} + + {selectedTopic ? ( + filteredQuestions.map((question, index) => ( +
handleQuestionClick(question)} + className="cursor-pointer text-gray-900 p-2 flex items-start space-x-4" + > + {selectedTopic.length > 0 && ( + handleSelectQuestion(question._id)} + onClick={(e) => { + e.stopPropagation(); + }} + /> + )} +
+ + Q. {(currentPage - 1) * questionsPerPage + index + 1} + + +
+
+ )) + ) : ( +
+ Please select a topic to view questions. +
+ )} + + ) : ( +
+ No questions available. +
+ )} + )} -
- - Q. {(currentPage - 1) * questionsPerPage + index + 1} - - -
- )) - ) : ( -
- Please select a topic to view questions. -
+
+ +

+ + {totalQuestions === 0 ? "0 / " : `${currentPage} / `} + + + {totalQuestions === 0 ? "0" : totalPages} + +

+ +
+ )} - - ) : ( -
- No questions available. -
- )} - - )} -
-
- -

- - {totalQuestions === 0 ? "0 / " : `${currentPage} / `} - - - {totalQuestions === 0 ? "0" : totalPages} - -

- -
-
-)} - - - - - {activeTabIndex === 1 ? (
@@ -1108,6 +1267,32 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => { onClick={() => handleQuestionClick(question)} className="cursor-pointer text-gray-900 p-2" > + {selectedTopic.length > 0 && ( +
+ + Select All + + +
+ )} + {selectedTopic.length > 0 && ( + handleSelectQuestion(question._id)} + onClick={(e) => { + e.stopPropagation(); + }} + /> + )} Q.{" "} {(myCurrentPage - 1) * questionsPerPage + index + 1} @@ -1157,6 +1342,43 @@ const ProfileHead = ({ selectedQuestion, setSelectedQuestion, toBottom }) => {
Loading...
)}
+ + +
+
+
+ + ({ - value: el.name, - label: el.name, - }))} - /> +