diff --git a/public/locales/en/common.json b/public/locales/en/common.json index dc76bb71..5a016d6e 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -115,7 +115,7 @@ "REASSIGN_CENTERS": "Re-assign Center", "REASSIGN_BLOCKS": "Re-assign Blocks", "REASSIGN": "Reassign", - "COHORT_ID_NOT_FOUND": "Could not found cohort Id for {{block}} ", + "COHORT_ID_NOT_FOUND": "Could not found center Id for {{block}} ", "CENTERS_REASSIGN_SUCCESSFULLY": "Center reassign successfully", "BLOCKS_REASSIGN_SUCCESSFULLY": "Block reassign successfully", "CENTERS_REASSIGN_FAILED": "Center Reassignment fails", @@ -137,7 +137,7 @@ "ASSIGNED_TEAM_LEADERS": "{{assignedTeamLeaderNames}} and more..", "CONTINUE": "Continue", "DESCRIPTION": "Description", - "ALREADY_EXIST": "Cohort name already exist.Please provide another name", + "ALREADY_EXIST": "Center name already exist.Please provide another name", "PAGE_NOT_FOUND": "Page not found", "ACCESS_DENIED": "Access Denied", "YOU_DONT_HAVE_PERMISSION_TO_ACCESS_THIS_PAGE": "You don't have access to this page", diff --git a/src/components/AddNewCenters.tsx b/src/components/AddNewCenters.tsx index da5e891c..6a6fd6c1 100644 --- a/src/components/AddNewCenters.tsx +++ b/src/components/AddNewCenters.tsx @@ -168,7 +168,7 @@ const AddNewCenters: React.FC = ({ if (selectedBlockCohortId) { const parentId = selectedBlockCohortId; const cohortDetails: CohortDetails = { - name: formData.name, + name: (formData.name).toLowerCase(), type: CohortTypes.COHORT, parentId: parentId, customFields: [ @@ -258,6 +258,8 @@ const AddNewCenters: React.FC = ({ } else { showToastMessage(t("CENTER.NOT_ABLE_CREATE_CENTER"), "error"); } + onClose(); + }; const handleChangeForm = (event: IChangeEvent) => { diff --git a/src/components/ResourceCard.tsx b/src/components/ResourceCard.tsx index 0ad54d1b..a1f73d47 100644 --- a/src/components/ResourceCard.tsx +++ b/src/components/ResourceCard.tsx @@ -3,56 +3,46 @@ import { Card, CardContent, Typography, Box } from "@mui/material"; import Image, { StaticImageData } from "next/image"; import placeholderImage from "../../public/placeholderImage.png"; import router from "next/router"; -import { getYouTubeThumbnail } from "@/utils/Helper"; import { fetchContent } from "@/services/PlayerService"; interface ResourceCardProps { title: string; - type: string; - resource: string; + // type: string; + // resource: string; identifier: string; + appIcon?: string; } const ResourceCard: React.FC = ({ title, - type, - resource, + // type, + // resource, identifier, + appIcon }) => { - const [thumbnailUrl, setThumbnailUrl] = useState(placeholderImage); + // const [thumbnailUrl, setThumbnailUrl] = useState(placeholderImage); + const thumbnailUrl = appIcon || placeholderImage; - useEffect(() => { - const loadContent = async () => { - try { - if (identifier) { - if (type === 'self') { - const data = await fetchContent(identifier); - if (data?.appIcon) { - setThumbnailUrl(data.appIcon); - } - console.log("vivek", data); - } else if (type.toLowerCase() === 'youtube') { - const img = getYouTubeThumbnail(identifier); - if (img) { - setThumbnailUrl(img); - } - } - } - } catch (error) { - console.error("Unable to fetch content", error); - } - } - loadContent(); + // useEffect(() => { + // const loadContent = async () => { + // try { + // if (identifier) { + // const data = await fetchContent(identifier); + // if (data?.appIcon) { + // setThumbnailUrl(data.appIcon); + // } + // } + // } catch (error) { + // console.error("Unable to fetch content", error); + // } + // } + // loadContent(); - }, [identifier, type]) + // }, [identifier]) const openPlayers = () => { sessionStorage.setItem("previousPage", window.location.href); - if (type === 'self') { - router.push(`/play/content/${identifier}`); - } else if (type.toLowerCase() === 'youtube') { - window.open(identifier); - } + router.push(`/play/content/${identifier}`); }; return ( @@ -81,7 +71,7 @@ const ResourceCard: React.FC = ({ {title} - {type} + {/* {type} */} diff --git a/src/pages/centers.tsx b/src/pages/centers.tsx index 986f8df8..3cea5360 100644 --- a/src/pages/centers.tsx +++ b/src/pages/centers.tsx @@ -51,6 +51,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useRouter } from "next/router"; import { telemetryFactory } from "@/utils/telemetry"; import useStore from "@/store/store"; +import axios from 'axios'; type cohortFilterDetails = { type?: string; status?: any; @@ -962,7 +963,7 @@ const response= await fetchCohortMemberList(data); return; } let cohortDetails = { - name: formData?.name, + name: (formData?.name).toLowerCase(), updatedBy:localStorage.getItem('userId'), customFields: customFields, }; @@ -994,7 +995,13 @@ const response= await fetchCohortMemberList(data); } } catch (error) { console.error("Error updating cohort:", error); - showToastMessage(t("CENTERS.CENTER_UPDATE_FAILED"), "error"); + if (axios.isAxiosError(error) && error.response) { + if (error.response.status === 409) { + showToastMessage(t("COMMON.ALREADY_EXIST"), "error"); + } + } + else + showToastMessage(t("CENTERS.CENTER_UPDATE_FAILED"), "error"); } finally { setLoading(false); setConfirmButtonDisable(false); diff --git a/src/pages/index.tsx b/src/pages/index.tsx index f4b43804..432df698 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,6 +2,7 @@ import React, { useEffect } from "react"; import { useRouter } from "next/router"; import { useTranslation } from "next-i18next"; import { serverSideTranslations } from "next-i18next/serverSideTranslations"; +import { Role } from "@/utils/app.constant"; // const Login = dynamic(() => import('./Login'), { ssr: false }); // const Dashboard = dynamic(() => import('./Dashboard'), { ssr: false }); @@ -17,6 +18,13 @@ const Home: React.FC = () => { const token = localStorage.getItem("token"); setLoading(false); if (token) { + const storedUserData = JSON.parse( + localStorage.getItem("adminInfo") || "{}" + ); + if(storedUserData?.role === Role.SCTA || storedUserData?.role === Role.CCTA){ + window.location.href = "/course-planner"; + } + else push("/centers"); } else { push("/login", undefined, { locale: "en" }); diff --git a/src/pages/resourceList.tsx b/src/pages/resourceList.tsx index 90a6c2d3..63386e92 100644 --- a/src/pages/resourceList.tsx +++ b/src/pages/resourceList.tsx @@ -7,6 +7,7 @@ import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import { ResourceType } from "@/utils/app.constant"; import { useTranslation } from "next-i18next"; import router from "next/router"; +import { fetchBulkContents } from "@/services/PlayerService"; const ResourceList = () => { const [learnersPreReq, setLearnersPreReq] = useState([]); @@ -20,19 +21,37 @@ const ResourceList = () => { const fetchData = async () => { const resources = tstore.resources; const fetchedLearningResources = resources.learningResources || []; - const preReqs = fetchedLearningResources.filter( - (item: any) => item.type === ResourceType.PREREQUISITE - ); - const postReqs = fetchedLearningResources.filter( - (item: any) => item.type === ResourceType.POSTREQUISITE - ); - const facilitatorsReqs = fetchedLearningResources.filter( - (item: any) => !item.type - ); - setLearnersPreReq(preReqs); - setLearnersPostReq(postReqs); - setFacilitatorsPreReq(facilitatorsReqs); + + if (fetchedLearningResources?.length) { + let contents = await fetchBulkContents(fetchedLearningResources.map((item: any) => item.id)); + + contents = contents.map((item: any) => { + const contentType = fetchedLearningResources.find( + (resource: any) => resource.id === item.identifier + ).type; + + return { + ...item, + type: contentType + } + }) + console.log("contents", contents); + + const preRequisite = contents.filter( + (item: any) => item.type === ResourceType.LEARNER_PRE_REQUISITE + ); + const postRequisite = contents.filter( + (item: any) => item.type === ResourceType.LEARNER_POST_REQUISITE + ); + const facilitatorsRequisite = contents.filter( + (item: any) => item.type === ResourceType.FACILITATOR_REQUISITE + ); + + setLearnersPreReq(preRequisite); + setLearnersPostReq(postRequisite); + setFacilitatorsPreReq(facilitatorsRequisite); + } }; fetchData(); @@ -68,9 +87,10 @@ const ResourceList = () => { ))} @@ -90,9 +110,10 @@ const ResourceList = () => { ))} @@ -112,9 +133,10 @@ const ResourceList = () => { ))} diff --git a/src/pages/subjectDetails.tsx b/src/pages/subjectDetails.tsx index cdd034cc..c8199003 100644 --- a/src/pages/subjectDetails.tsx +++ b/src/pages/subjectDetails.tsx @@ -163,6 +163,122 @@ const SubjectDetails = () => { fetchFrameworkDetails(); }, [boardName]); + useEffect(() => { + const savedMedium = localStorage.getItem("selectedMedium") || ""; + const savedGrade = localStorage.getItem("selectedGrade") || ""; + const savedType = localStorage.getItem("selectedType") || ""; + + setSelectedmedium(savedMedium); + setSelectedgrade(savedGrade); + setSelectedtype(savedType); + }, []); + + const fetchAndSetGradeData = (medium: any) => { + const getGrades = getOptionsByCategory(store?.framedata, "gradeLevel"); + const mediumAssociations = getAssociationsByCodeNew(mediumOptions, medium); + setMediumAssociations(mediumAssociations); + + console.log(getGrades); + + const commonGradeInState = filterAndMapAssociations( + "gradeLevel", + getGrades, + store?.stateassociations, + "code" + ); + const commonGradeInBoard = filterAndMapAssociations( + "gradeLevel", + getGrades, + boardAssociations, + "code" + ); + const commonGradeInMedium = filterAndMapAssociations( + "gradeLevel", + getGrades, + mediumAssociations, + "code" + ); + + const commonGradeInStateBoard = findCommonAssociations( + commonGradeInState, + commonGradeInBoard + ); + const overAllCommonGrade = findCommonAssociations( + commonGradeInStateBoard, + commonGradeInMedium + ); + + setGrade(overAllCommonGrade); + setGradeOptions(overAllCommonGrade); + }; + + const fetchAndSetTypeData = (grade: any) => { + const gradeAssociations = getAssociationsByCodeNew(gradeOptions, grade); + setGradeAssociations(gradeAssociations); + const type = getOptionsByCategory(store?.framedata, "courseType"); + console.log(type); + + const commonTypeInState = filterAndMapAssociations( + "courseType", + type, + store?.stateassociations, + "code" + ); + const commonTypeInBoard = filterAndMapAssociations( + "courseType", + type, + boardAssociations, + "code" + ); + const commonTypeInMedium = filterAndMapAssociations( + "courseType", + type, + mediumAssociations, + "code" + ); + const commonTypeInGrade = filterAndMapAssociations( + "courseType", + type, + gradeAssociations, + "code" + ); + + const commonTypeData = findCommonAssociations( + commonTypeInState, + commonTypeInBoard + ); + const commonType2Data = findCommonAssociations( + commonTypeInMedium, + commonTypeInGrade + ); + const commonType3Data = findCommonAssociations( + commonTypeData, + commonType2Data + ); + + console.log(`commonTypeOverall`, commonType3Data); + setTypeOptions(commonType3Data); + setType(commonType3Data); + }; + + useEffect(() => { + if (selectedmedium) { + fetchAndSetGradeData(selectedmedium); + } + }, [selectedmedium]); + + useEffect(() => { + if (selectedgrade) { + fetchAndSetTypeData(selectedgrade); + } + }, [selectedgrade]); + + // useEffect(() => { + // if (selectedtype) { + // fetchAndSetSubData(selectedtype); + // } + // }, [selectedtype]); + if (loading) { return ; } @@ -181,6 +297,7 @@ const SubjectDetails = () => { }; const handleMediumChange = (event: any) => { + localStorage.setItem("selectedMedium", event.target.value); const medium = event.target.value; setSelectedmedium(medium); setTaxonomyMedium(medium); @@ -188,140 +305,54 @@ const SubjectDetails = () => { setSelectedtype([null]); setSubject([null]); - if (medium) { - const getGrades = getOptionsByCategory(store?.framedata, "gradeLevel"); - const mediumAssociations = getAssociationsByCodeNew( - mediumOptions, - medium - ); - setMediumAssociations(mediumAssociations); - - console.log(getGrades); - - const commonGradeInState = filterAndMapAssociations( - "gradeLevel", - getGrades, - store?.stateassociations, - "code" - ); - const commonGradeInBoard = filterAndMapAssociations( - "gradeLevel", - getGrades, - boardAssociations, - "code" - ); - const commonGradeInMedium = filterAndMapAssociations( - "gradeLevel", - getGrades, - mediumAssociations, - "code" - ); - - const commonGradeInStateBoard = findCommonAssociations( - commonGradeInState, - commonGradeInBoard - ); - const overAllCommonGrade = findCommonAssociations( - commonGradeInStateBoard, - commonGradeInMedium - ); - - setGrade(overAllCommonGrade); - setGradeOptions(overAllCommonGrade); - } const windowUrl = window.location.pathname; - const cleanedUrl = windowUrl.replace(/^\//, ''); - const env = cleanedUrl.split("/")[0]; - - const telemetryInteract = { - context: { - env: env, - cdata: [], - }, - edata: { - id: 'change-medium', - - type: TelemetryEventType.CLICK, - subtype: '', - pageid: cleanedUrl, - }, - }; - telemetryFactory.interact(telemetryInteract); + const cleanedUrl = windowUrl.replace(/^\//, ""); + const env = cleanedUrl.split("/")[0]; + + const telemetryInteract = { + context: { + env: env, + cdata: [], + }, + edata: { + id: "change-medium", + + type: TelemetryEventType.CLICK, + subtype: "", + pageid: cleanedUrl, + }, + }; + telemetryFactory.interact(telemetryInteract); }; const handleGradeChange = (event: any) => { + localStorage.setItem("selectedGrade", event.target.value); const grade = event.target.value; setTaxonomyGrade(grade); setSelectedgrade(grade); - if (grade) { - const gradeAssociations = getAssociationsByCodeNew(gradeOptions, grade); - setGradeAssociations(gradeAssociations); - const type = getOptionsByCategory(store?.framedata, "courseType"); - console.log(type); - const commonTypeInState = filterAndMapAssociations( - "courseType", - type, - store?.stateassociations, - "code" - ); - const commonTypeInBoard = filterAndMapAssociations( - "courseType", - type, - boardAssociations, - "code" - ); - const commonTypeInMedium = filterAndMapAssociations( - "courseType", - type, - mediumAssociations, - "code" - ); - const commonTypeInGrade = filterAndMapAssociations( - "courseType", - type, - gradeAssociations, - "code" - ); - - const commonTypeData = findCommonAssociations( - commonTypeInState, - commonTypeInBoard - ); - const commonType2Data = findCommonAssociations( - commonTypeInMedium, - commonTypeInGrade - ); - const commonType3Data = findCommonAssociations( - commonTypeData, - commonType2Data - ); - - console.log(`commonTypeOverall`, commonType3Data); - setTypeOptions(commonType3Data); - setType(commonType3Data); - } const windowUrl = window.location.pathname; - const cleanedUrl = windowUrl.replace(/^\//, ''); - const env = cleanedUrl.split("/")[0]; - - const telemetryInteract = { - context: { - env: env, - cdata: [], - }, - edata: { - id: 'grade_change', - - type: TelemetryEventType.CLICK, - subtype: '', - pageid: cleanedUrl, - }, - }; - telemetryFactory.interact(telemetryInteract); + const cleanedUrl = windowUrl.replace(/^\//, ""); + const env = cleanedUrl.split("/")[0]; + + const telemetryInteract = { + context: { + env: env, + cdata: [], + }, + edata: { + id: "grade_change", + + type: TelemetryEventType.CLICK, + subtype: "", + pageid: cleanedUrl, + }, + }; + telemetryFactory.interact(telemetryInteract); }; const handleTypeChange = (event: any) => { + localStorage.setItem("selectedType", event.target.value); const type = event.target.value; setTaxonomyType(type); setSelectedtype(type); @@ -408,23 +439,23 @@ const SubjectDetails = () => { ); } const windowUrl = window.location.pathname; - const cleanedUrl = windowUrl.replace(/^\//, ''); - const env = cleanedUrl.split("/")[0]; - - const telemetryInteract = { - context: { - env: env, - cdata: [], - }, - edata: { - id: 'change_type', - - type: TelemetryEventType.CLICK, - subtype: '', - pageid: cleanedUrl, - }, - }; - telemetryFactory.interact(telemetryInteract); + const cleanedUrl = windowUrl.replace(/^\//, ""); + const env = cleanedUrl.split("/")[0]; + + const telemetryInteract = { + context: { + env: env, + cdata: [], + }, + edata: { + id: "change_type", + + type: TelemetryEventType.CLICK, + subtype: "", + pageid: cleanedUrl, + }, + }; + telemetryFactory.interact(telemetryInteract); }; return ( diff --git a/src/services/CohortService/cohortService.ts b/src/services/CohortService/cohortService.ts index dbc38500..19bc9d16 100644 --- a/src/services/CohortService/cohortService.ts +++ b/src/services/CohortService/cohortService.ts @@ -95,7 +95,7 @@ export const createCohort = async (userData: any, t?:any): Promise => { if (axios.isAxiosError(error) && error.response) { if (error.response.status === 409) { - showToastMessage(t("COMMON.ALREADY_EXIST"), "info"); + showToastMessage(t("COMMON.ALREADY_EXIST"), "error"); } diff --git a/src/services/PlayerService.tsx b/src/services/PlayerService.tsx index 332ce590..40d31930 100644 --- a/src/services/PlayerService.tsx +++ b/src/services/PlayerService.tsx @@ -42,3 +42,40 @@ export const getQumlData = async (identifier: any) => { throw error; } }; + +export const fetchBulkContents = async (identifiers: string[]) => { + try { + const options = { + request: { + filters: { + identifier: identifiers, + }, + fields: [ + "name", + "appIcon", + "medium", + "subject", + "resourceType", + "contentType", + "organisation", + "topic", + "mimeType", + "trackable", + "gradeLevel" + ], + } + } + const response = await axios.post(URL_CONFIG.API.COMPOSITE_SEARCH, options); + console.log('response =====>', response); + const result = response?.data?.result; + if (response?.data?.result?.QuestionSet?.length) { + result.content = [...result.content, ...result.QuestionSet]; + } + + return result.content; + } catch (error) { + console.error('Error fetching content:', error); + throw error; + } +}; + diff --git a/src/utils/Helper.ts b/src/utils/Helper.ts index 5b4358d3..aa3e0c69 100644 --- a/src/utils/Helper.ts +++ b/src/utils/Helper.ts @@ -353,7 +353,7 @@ export const filterAndMapAssociations = ( } return options - .filter((option) => { + ?.filter((option) => { const optionCode = option[codeKey]; return associationsList.some( diff --git a/src/utils/app.constant.ts b/src/utils/app.constant.ts index 74e318e0..a6bd5d03 100644 --- a/src/utils/app.constant.ts +++ b/src/utils/app.constant.ts @@ -8,10 +8,10 @@ export enum Role { CENTRAL_ADMIN = "Central Admin MME", LEARNERS = "Learners", FACILITATORS = "Facilitators", - CONTENT_CREATOR= "Content Creator", + CONTENT_CREATOR = "Content Creator", CONTENT_REVIEWER = "Content Reviewer", - SCTA ="State Admin SCTA", - CCTA="Central Admin CCTA" + SCTA = "State Admin SCTA", + CCTA = "Central Admin CCTA" } @@ -34,14 +34,14 @@ export enum Storage { } export enum FormContext { USERS = "USERS", - COHORTS="cohorts" + COHORTS = "cohorts" } export enum TelemetryEventType { CLICK = 'CLICK', SEARCH = 'SEARCH', VIEW = 'VIEW', - RADIO="RADIO" + RADIO = "RADIO" } export enum FormContextType { @@ -50,8 +50,8 @@ export enum FormContextType { TEAM_LEADER = "TEAM LEADER", ADMIN = "ADMIN", ADMIN_CENTER = "ADMIN_CENTER", - COHORT="cohort", - CONTENT_CREATOR="CONTENT CREATOR" + COHORT = "cohort", + CONTENT_CREATOR = "CONTENT CREATOR" } export enum RoleId { @@ -59,7 +59,7 @@ export enum RoleId { TEACHER = "3bde0028-6900-4900-9d05-eeb608843718", TEAM_LEADER = "9dd9328f-1bc7-444f-96e3-c5e1daa3514a", ADMIN = "ee482faf-8a41-45fe-9656-5533dd6a787c", - SCTA="f972a14e-afdb-4502-8ede-cf1fcf171e46" + SCTA = "f972a14e-afdb-4502-8ede-cf1fcf171e46" } export enum DataKey { @@ -96,8 +96,8 @@ export enum CohortTypes { export enum FormValues { FEMALE = "FEMALE", MALE = "MALE", - REGULAR="REGULAR", - REMOTE="REMOTE" + REGULAR = "REGULAR", + REMOTE = "REMOTE" } export enum InputTypes { @@ -120,7 +120,7 @@ export const QueryKeys = { } -export const monthColors:any = { +export const monthColors: any = { "Jan": "#99CCFF", "Mar": "#D9B2FF", "Apr": "#FFABAB", @@ -135,6 +135,7 @@ export const monthColors:any = { }; export enum ResourceType { - PREREQUISITE = "prerequisite", - POSTREQUISITE = "postrequisite", + LEARNER_PRE_REQUISITE = "prerequisite", + LEARNER_POST_REQUISITE = "postrequisite", + FACILITATOR_REQUISITE = "facilitator-requisite", } \ No newline at end of file diff --git a/src/utils/url.config.ts b/src/utils/url.config.ts index 844d8f9b..61a34ae1 100644 --- a/src/utils/url.config.ts +++ b/src/utils/url.config.ts @@ -9,5 +9,6 @@ export const URL_CONFIG = { CONTENT_READ: "/api/content/v1/read/", HIERARCHY_API: "/action/questionset/v2/hierarchy/", QUESTIONSET_READ: "/action/questionset/v2/read/", + COMPOSITE_SEARCH: '/action/composite/v3/search', }, };