From 6fdcd9cbce2eb64c77d51e8845d1b977411bee43 Mon Sep 17 00:00:00 2001 From: Arif Date: Thu, 29 Aug 2024 11:47:04 +0530 Subject: [PATCH] Issue #PS-1775 feat: Course planner API integration to View list of Topics and Sub-Topics --- .env | 2 +- src/pages/course-planner-detail.tsx | 377 ++++++++++++++++----------- src/services/CoursePlannerService.ts | 51 +++- src/utils/Interfaces.ts | 11 + 4 files changed, 279 insertions(+), 162 deletions(-) diff --git a/.env b/.env index 0d396ebc..ff6eea2b 100644 --- a/.env +++ b/.env @@ -6,4 +6,4 @@ NEXT_PUBLIC_TELEMETRY_URL=https://qa.prathamteacherapp.tekdinext.com NEXT_PUBLIC_MEASUREMENT_ID= G-GNMQZ8Z65Z NEXT_PUBLIC_TRACKING_API_URL=https://tracking-pratham.tekdinext.com NEXT_PUBLIC_SHIKSHALOKAM_API_URL=https://dev.elevate-apis.shikshalokam.org/project/v1 -NEXT_PUBLIC_SHIKSHALOKAM_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImlkIjoyNjIsIm5hbWUiOiJ0ZWtkaVRlc3RVc2VyIiwic2Vzc2lvbl9pZCI6NjExNiwib3JnYW5pemF0aW9uX2lkIjoxLCJyb2xlcyI6W3siaWQiOjEyLCJ0aXRsZSI6InByb2dyYW1fZGVzaWduZXIiLCJsYWJlbCI6IlByb2dyYW0gRGVzaWduZXIiLCJ1c2VyX3R5cGUiOjAsInN0YXR1cyI6IkFDVElWRSIsIm9yZ2FuaXphdGlvbl9pZCI6MSwidmlzaWJpbGl0eSI6IlBVQkxJQyJ9LHsiaWQiOjIxLCJ0aXRsZSI6ImRpc3RyaWN0X3Jlc291cmNlX3BlcnNvbiIsImxhYmVsIjoiRGlzdHJpY3QgUmVzb3VyY2UgUGVyc29uIiwidXNlcl90eXBlIjowLCJzdGF0dXMiOiJBQ1RJVkUiLCJvcmdhbml6YXRpb25faWQiOjI0LCJ2aXNpYmlsaXR5IjoiUFVCTElDIn1dfSwiaWF0IjoxNzI0ODI1MDM5LCJleHAiOjE3MjQ5MTE0Mzl9.HAK4_MAo-8tqxcVoLNDRuyNj_S_hqM8X5Pya1gKPXKg \ No newline at end of file +NEXT_PUBLIC_SHIKSHALOKAM_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImlkIjoxNjIsIm5hbWUiOiJQcml5YW5rYSIsInNlc3Npb25faWQiOjYxNTAsIm9yZ2FuaXphdGlvbl9pZCI6MjQsInJvbGVzIjpbeyJpZCI6MywidGl0bGUiOiJtZW50ZWUiLCJsYWJlbCI6Ik1lbnRlZSIsInVzZXJfdHlwZSI6MCwic3RhdHVzIjoiQUNUSVZFIiwib3JnYW5pemF0aW9uX2lkIjoxLCJ2aXNpYmlsaXR5IjoiUFVCTElDIn0seyJpZCI6NCwidGl0bGUiOiJhZG1pbiIsImxhYmVsIjoiQWRtaW4iLCJ1c2VyX3R5cGUiOjEsInN0YXR1cyI6IkFDVElWRSIsIm9yZ2FuaXphdGlvbl9pZCI6MSwidmlzaWJpbGl0eSI6IlBVQkxJQyJ9LHsiaWQiOjgsInRpdGxlIjoicHVibGljIiwibGFiZWwiOiJQdWJsaWMiLCJ1c2VyX3R5cGUiOjAsInN0YXR1cyI6IkFDVElWRSIsIm9yZ2FuaXphdGlvbl9pZCI6MSwidmlzaWJpbGl0eSI6IlBVQkxJQyJ9LHsiaWQiOjUsInRpdGxlIjoib3JnX2FkbWluIiwibGFiZWwiOiJPcmcgQWRtaW4iLCJ1c2VyX3R5cGUiOjEsInN0YXR1cyI6IkFDVElWRSIsIm9yZ2FuaXphdGlvbl9pZCI6MSwidmlzaWJpbGl0eSI6IlBVQkxJQyJ9LHsiaWQiOjEwLCJ0aXRsZSI6InJldmlld2VyIiwibGFiZWwiOiJSZXZpZXdlciIsInVzZXJfdHlwZSI6MCwic3RhdHVzIjoiQUNUSVZFIiwib3JnYW5pemF0aW9uX2lkIjoxLCJ2aXNpYmlsaXR5IjoiUFVCTElDIn0seyJpZCI6MjAsInRpdGxlIjoiZGlzdHJpY3RfZWR1Y2F0aW9uX29mZmljZXIiLCJsYWJlbCI6IkRpc3RyaWN0IEVkdWNhdGlvbiBPZmZpY2VyIiwidXNlcl90eXBlIjowLCJzdGF0dXMiOiJBQ1RJVkUiLCJvcmdhbml6YXRpb25faWQiOjI0LCJ2aXNpYmlsaXR5IjoiUFVCTElDIn1dfSwiaWF0IjoxNzI0ODM3NzEyLCJleHAiOjE3MjQ5MjQxMTJ9.5rBJlIC0wN-6zpISQfa-cNCLRvSSe6uI87W2JKBt4Yk \ No newline at end of file diff --git a/src/pages/course-planner-detail.tsx b/src/pages/course-planner-detail.tsx index 014f4ec6..cc43999f 100644 --- a/src/pages/course-planner-detail.tsx +++ b/src/pages/course-planner-detail.tsx @@ -21,9 +21,15 @@ import { useTranslation } from 'next-i18next'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import React, { useState, useEffect, useMemo, useCallback } from 'react'; import { buildStyles, CircularProgressbar } from 'react-circular-progressbar'; -import { getTargetedSolutions, getUserProjectDetails } from '@/services/CoursePlannerService'; +import { + getSolutionDetails, + getTargetedSolutions, + getUserProjectDetails, + getUserProjectTemplate, +} from '@/services/CoursePlannerService'; import useCourseStore from '@/store/coursePlannerStore'; import dayjs from 'dayjs'; +import { Role } from '@/utils/app.constant'; const CoursePlannerDetail = () => { const theme = useTheme(); @@ -32,14 +38,14 @@ const CoursePlannerDetail = () => { const setResources = useCourseStore((state) => state.setResources); const store = useCourseStore(); - // Initialize the panels' state, assuming you have a known set of panel IDs const [expandedPanels, setExpandedPanels] = useState<{ [key: string]: boolean; }>({ + 'panel0-header': true, 'panel1-header': true, - 'panel2-header': false, // || example for multiple accordions do this dynamically - // Add more panels if needed + 'panel2-header': true, + 'panel3-header': true, }); const [drawerState, setDrawerState] = React.useState({ bottom: false }); const [isDrawerOpen, setIsDrawerOpen] = useState(false); @@ -48,31 +54,80 @@ const CoursePlannerDetail = () => { const [courseDetails, setCourseDetails] = useState(null); const [userProjectDetails, setUserProjectDetails] = useState([]); - const fetchCourseDetails = useCallback(() => { - getTargetedSolutions({ - subject: "Marathi", - class: "10", - state: "Maharasthra", - board: "NIOS", - type: "foundationCourse", - role: "Teacher", - medium: "English" - }).then((response) => { - const courseId = response.result.data[0]._id; - setCourseDetails(response.result.data); - - return getUserProjectDetails({ id: '66cdb0c86a33880d1f4d60d7' }); - }).then((userProjectDetailsResponse) => { - setUserProjectDetails(userProjectDetailsResponse.result.tasks); - }).catch((error) => { - console.error('Error fetching course planner:', error); + const fetchCourseDetails = useCallback(async () => { + try { + const response = await getTargetedSolutions({ + subject: 'Marathi', + class: '10', + state: 'Assam', + board: 'ASEB', + type: 'mainCourse', + role: 'Teacher', + medium: 'Hindi', }); + + const courseData = response.result.data[0]; + let courseId = courseData._id; + + if (!courseId) { + courseId = await fetchCourseIdFromSolution(courseData.solutionId); + } + + await fetchAndSetUserProjectDetails(courseId); + + } catch (error) { + console.error('Error fetching course planner:', error); + } }, []); + const fetchCourseIdFromSolution = async (solutionId: string): Promise => { + try { + const solutionResponse = await getSolutionDetails({ + id: solutionId, + role: 'Teacher', + }); + + const externalId = solutionResponse?.result?.externalId; + + const templateResponse = await getUserProjectTemplate({ + templateId: externalId, + solutionId, + role: Role.TEACHER, + }); + + const updatedResponse = await getTargetedSolutions({ + subject: 'Marathi', + class: '10', + state: 'Kerala', + board: 'KSEB', + type: 'mainCourse', + role: 'Teacher', + medium: 'Hindi', + }); + + return updatedResponse.result.data[0]._id; + } catch (error) { + console.error('Error fetching solution details:', error); + throw error; + } + }; + + const fetchAndSetUserProjectDetails = async (courseId: string) => { + try { + const userProjectDetailsResponse = await getUserProjectDetails({ + id: courseId, + }); + setUserProjectDetails(userProjectDetailsResponse.result.tasks); + } catch (error) { + console.error('Error fetching user project details:', error); + } + }; + + + useEffect(() => { fetchCourseDetails(); }, [fetchCourseDetails]); - const handleBackEvent = () => { window.history.back(); @@ -115,8 +170,6 @@ const CoursePlannerDetail = () => { // setModalOpen(true); // }; - - const getAbbreviatedMonth = (dateString: string | number | Date) => { const date = new Date(dateString); const months = Array.from({ length: 12 }, (_, i) => @@ -234,169 +287,175 @@ const CoursePlannerDetail = () => { - {userProjectDetails.map((topic:any, index) => ( - - - setExpandedPanels((prev) => ({ - ...prev, - [`panel1-header`]: !prev[`panel1-header`], - })) - } - sx={{ - boxShadow: 'none', - background: '#F1E7D9', - border: 'none', - transition: '0.3s', - }} - > - - } - aria-controls={`panel${index}-content`} - id={`panel${index}-header`} - className="accordion-summary" - sx={{ - px: '16px', - m: 0, - '&.Mui-expanded': { - minHeight: '48px', - }, - }} - > - - - - - {`Topic ${index + 1} - ${topic.name}`} - - - - {getAbbreviatedMonth(topic?.metaInformation?.startDate)}, {getAbbreviatedMonth(topic?.metaInformation?.endDate)} - - - - - {topic.children.map((subTopic:any) => ( - ( + + + setExpandedPanels((prev) => ({ + ...prev, + [`panel${index}-header`]: !prev[`panel${index}-header`], + })) + } sx={{ - borderBottom: `1px solid ${theme.palette.warning['A100']}`, + boxShadow: 'none', + background: '#F1E7D9', + border: 'none', + transition: '0.3s', }} > - + } + aria-controls={`panel${index}-content`} + id={`panel${index}-header`} + className="accordion-summary" sx={{ - py: '10px', px: '16px', - background: theme.palette.warning['A400'], + m: 0, + '&.Mui-expanded': { + minHeight: '48px', + }, }} > { - setResources(subTopic); - router.push(`/topic-detail-view`); + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + gap: '5px', }} > - {subTopic.name} + + + {`Topic ${index + 1} - ${topic.name}`} + + + {getAbbreviatedMonth(topic?.metaInformation?.startDate)},{' '} + {getAbbreviatedMonth(topic?.metaInformation?.endDate)} + + + + + {topic.children.map((subTopic: any) => ( - {getAbbreviatedMonth(subTopic?.metaInformation?.startDate)} + + { + setResources(subTopic); + router.push(`/topic-detail-view`); + }} + > + {subTopic.name} + + + + {getAbbreviatedMonth( + subTopic?.metaInformation?.startDate + )} + + + + + { + router.push(`/topic-detail-view`); + }} + > + { + setResources(subTopic); + router.push(`/topic-detail-view`); + }} + > + {`${subTopic?.learningResources?.length} ${t('COURSE_PLANNER.RESOURCES')}`} + + + - - - - { - router.push(`/topic-detail-view`); - }} - > - { - setResources(subTopic); - router.push(`/topic-detail-view`); - }}> - {`${subTopic?.learningResources?.length} ${t('COURSE_PLANNER.RESOURCES')}`} - - - - - ))} - - - - ))} - + ))} + + + + ))} + { @@ -10,7 +10,7 @@ export const getCoursePlanner = (): CoursePlanner[] => { // { id: 3, subject: 'History', circular: 30 }, // { id: 4, subject: 'Geography', circular: 60 }, // { id: 5, subject: 'Marathi', circular: 90 }, - { id: 6, subject: 'Hindi', circular: 70 }, + { id: 6, subject: 'Marathi', circular: 0 }, // { id: 7, subject: 'Social Science', circular: 80 }, ]; @@ -76,4 +76,51 @@ export const getUserProjectDetails = async ({ id }: GetUserProjectDetailsParams) }; +export const getSolutionDetails = async ({ id, role }: GetSolutionDetailsParams): Promise => { + const apiUrl: string = `${process.env.NEXT_PUBLIC_SHIKSHALOKAM_API_URL}/solutions/details/${id}`; + + const headers = { + 'X-auth-token': process.env.NEXT_PUBLIC_SHIKSHALOKAM_TOKEN, + 'Content-Type': 'application/json', + }; + + const data = { + role, + }; + + try { + const response = await axios.post(apiUrl, data, { headers }); + return response?.data; + } catch (error) { + console.error('Error in getting Solution Details', error); + return error; + } +}; + +export const getUserProjectTemplate = async ({ + templateId, + solutionId, + role, +}: GetUserProjectTemplateParams): Promise => { + const apiUrl: string = `${process.env.NEXT_PUBLIC_SHIKSHALOKAM_API_URL}/userProjects/details?templateId=${templateId}&solutionId=${solutionId}`; + + const headers = { + 'X-auth-token': process.env.NEXT_PUBLIC_SHIKSHALOKAM_TOKEN, + 'Content-Type': 'application/json', + }; + + const data = { + role, + }; + + try { + const response = await axios.post(apiUrl, data, { headers }); + return response?.data; + } catch (error) { + console.error('Error in getting User Project Details', error); + throw error; + } +}; + + diff --git a/src/utils/Interfaces.ts b/src/utils/Interfaces.ts index 47f6f927..a74f16e6 100644 --- a/src/utils/Interfaces.ts +++ b/src/utils/Interfaces.ts @@ -632,3 +632,14 @@ export interface IQuestion { score: number; sectionId: string; } + +export interface GetSolutionDetailsParams { + id: string; + role: string; +} + +export interface GetUserProjectTemplateParams { + templateId: string; + solutionId: string; + role: string; +}