diff --git a/config.json b/config.json index c446144f..527f8c0c 100644 --- a/config.json +++ b/config.json @@ -18,14 +18,14 @@ "code": "or" } ], - "firebaseConfig": { - "apiKey": "process.env.NEXT_PUBLIC_FCM_API_KEY", - "authDomain": "backend-e99c8.firebaseapp.com", - "projectId": "backend-e99c8", - "storageBucket": "backend-e99c8.appspot.com", - "messagingSenderId": "839139131975", - "appId": "1:839139131975:web:90af50d01e2eb0f510e762", - "measurementId": "G-5237RSF3TC" - }, - "vapidKey": "process.env.NEXT_PUBLIC_VAPID_KEY" -} + "firebaseConfig": { + "apiKey": "AIzaSyCmhNz-HMkkf42QNmnf7pnZm49FP5g4INw", + "authDomain": "backend-e99c8.firebaseapp.com", + "projectId": "backend-e99c8", + "storageBucket": "backend-e99c8.appspot.com", + "messagingSenderId": "839139131975", + "appId": "1:839139131975:web:90af50d01e2eb0f510e762", + "measurementId": "G-5237RSF3TC" + }, + "vapidKey": "BOZ_JkC62vr767LoC7APU26ZdGYW5htBkfqIEtsVX6zmE3Fi-XgcN_TggSaXKh5rGKcaa4vuQxaYiRPU2B955GI" +} \ No newline at end of file diff --git a/firebase.js b/firebase.js index ad6c83ef..044a7116 100644 --- a/firebase.js +++ b/firebase.js @@ -6,7 +6,7 @@ const firebaseApp = initializeApp(config.firebaseConfig); let messaging; if (typeof window !== 'undefined') { - messaging = getMessaging(); + messaging = getMessaging(); } export const requestPermission = async () => { diff --git a/next.config.mjs b/next.config.mjs index 6fdecce3..4ac7a4fb 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -11,6 +11,17 @@ const remotes = (isServer) => { }; }; +const PORTAL_BASE_URL = "https://sunbird-editor.tekdinext.com"; + +const routes = { + API: { + GENERAL: { + CONTENT_PREVIEW: "/content/preview/:path*", + CONTENT_PLUGINS: "/content-plugins/:path*" + } + } +}; + const nextConfig = { eslint: { // Disabling on production builds because we're running checks on PRs via GitHub Actions. @@ -66,6 +77,14 @@ const nextConfig = { source: '/app/telemetry', // Match telemetry route destination: `${process.env.WORKSPACE_BASE_URL}/api/telemetry`, // Redirect to telemetry proxy }, + { + source: routes.API.GENERAL.CONTENT_PREVIEW, + destination: `${PORTAL_BASE_URL}${routes.API.GENERAL.CONTENT_PREVIEW}`, // Proxy to portal + }, + { + source: routes.API.GENERAL.CONTENT_PLUGINS, + destination: `${PORTAL_BASE_URL}${routes.API.GENERAL.CONTENT_PLUGINS}`, // Proxy to portal + } ]; }, webpack: (config, { isServer }) => { diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 915e8935..4f52cd1f 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -136,7 +136,9 @@ "CENTER": "Center", "AND_COUNT_MORE": "and {{count}} more", "RETURN_TO_LOGIN": "Return to Login", - "NO_CENTER_FOUND": "No Center found" + "NO_CENTER_FOUND": "No Center found", + "FILTER_BY":"Filter By", + "ALL":"All" }, "LOGIN_PAGE": { "USERNAME": "Username", @@ -600,7 +602,14 @@ "NOT_STARTED":"Not Started", "COMPLETED":"Completed", "INPROGRESS":"In-Progress", - "NO_DATA_FOUND":"No {{entity}} found" + "NO_DATA_FOUND":"No {{entity}} found", + "NO_RESULT_FOUND":"No Observations found for {{entity}}", + "NO_OBSERVATION_EXPIRED":"No observation expired for {{entity}}", + "DAYS_LEFT":"Days left", + "THIS_OBSERVATION_EXPIRED":"This observation is expired", + "DUE_DATE":"Due date" + + } } diff --git a/src/components/AddFacilitator.tsx b/src/components/AddFacilitator.tsx index f8c68727..1f2b96ff 100644 --- a/src/components/AddFacilitator.tsx +++ b/src/components/AddFacilitator.tsx @@ -305,7 +305,7 @@ const AddFacilitatorModal: React.FC = ({ id: 'facilitator-updated-success', type: Telemetry.CLICK, subtype: '', - pageid: 'cleanedUrl', + pageid: cleanedUrl }, }; telemetryFactory.interact(telemetryInteract); diff --git a/src/components/FilterSelect.tsx b/src/components/FilterSelect.tsx new file mode 100644 index 00000000..a938a6c5 --- /dev/null +++ b/src/components/FilterSelect.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { FormControl, InputLabel, Select, MenuItem, SelectChangeEvent } from '@mui/material'; + +interface FilterSelectProps { + menuItems: { value: string; label: string }[]; + selectedOption: string; + handleFilterChange: (event: SelectChangeEvent) => void; + label: string; + sx?: object; +} + +const FilterSelect: React.FC = ({ + menuItems, + selectedOption, + handleFilterChange, + label, + sx = {} +}) => { + return ( + + {label} + + + ); +}; + +export default FilterSelect; diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 49b7af90..2e83823c 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -18,6 +18,7 @@ import { useTranslation } from 'next-i18next'; import StyledMenu from './StyledMenu'; import AccountCircleOutlinedIcon from '@mui/icons-material/AccountCircleOutlined'; import { useDirection } from '../hooks/useDirection'; +import useStore from '../store/store'; interface HeaderProps { toggleDrawer?: (newOpen: boolean) => () => void; @@ -34,6 +35,8 @@ const Header: React.FC = ({ toggleDrawer, openDrawer }) => { const { t } = useTranslation(); const pathname = usePathname(); const theme = useTheme(); + const store = useStore(); + const isActiveYear = store.isActiveYearSelected; const [userId, setUserId] = useState(''); const [openMenu, setOpenMenu] = useState(false); @@ -170,7 +173,7 @@ const Header: React.FC = ({ toggleDrawer, openDrawer }) => { width={44} src={logoLight} alt="logo" - onClick={() => router.push('/dashboard')} + onClick={() => isActiveYear && router.push('/dashboard')} style={{ marginRight: isRTL ? '20px' : '0px' }} /> diff --git a/src/components/LearnersListItem.tsx b/src/components/LearnersListItem.tsx index d9526bcb..bc08d435 100644 --- a/src/components/LearnersListItem.tsx +++ b/src/components/LearnersListItem.tsx @@ -101,6 +101,7 @@ const LearnersListItem: React.FC = ({ const setCohortLearnerDeleteId = manageUserStore( (state) => state.setCohortLearnerDeleteId ); + const isActiveYear = userStore.isActiveYearSelected; useEffect(() => { if (reloadState) { @@ -625,7 +626,7 @@ const LearnersListItem: React.FC = ({ )} - { isMobile ? toggleDrawer('bottom', true)(event) @@ -636,7 +637,7 @@ const LearnersListItem: React.FC = ({ color: theme.palette.warning['300'], cursor: 'pointer', }} - /> + />} diff --git a/src/components/ManageUser.tsx b/src/components/ManageUser.tsx index ed82e6a1..e386e0e8 100644 --- a/src/components/ManageUser.tsx +++ b/src/components/ManageUser.tsx @@ -73,6 +73,7 @@ const ManageUser: React.FC = ({ const newStore = useStore(); const queryClient = useQueryClient(); const { dir, isRTL } = useDirection(); + const isActiveYear = newStore.isActiveYearSelected; const [value, setValue] = React.useState(1); const [users, setUsers] = useState< @@ -506,7 +507,7 @@ const ManageUser: React.FC = ({ {value === 1 && ( <> - {!isFromFLProfile && ( + {!isFromFLProfile && isActiveYear && ( () => void; @@ -53,6 +55,10 @@ const MenuDrawer: React.FC = ({ const store = useStore(); const userRole = store.userRole; const { isRTL } = useDirection(); + const setIsActiveYearSelected = useStore( + (state: { setIsActiveYearSelected: any }) => state.setIsActiveYearSelected + ); + const isActiveYear = store.isActiveYearSelected; useEffect(() => setIsOpen(open), [open]); @@ -85,7 +91,21 @@ const MenuDrawer: React.FC = ({ setSelectedSessionId(event.target.value); console.log('selected academic year id', event.target.value); localStorage.setItem('academicYearId', event.target.value); - window.location.reload(); + + // Check if the selected academic year is active + const selectedYear = academicYearList?.find( + (year) => year.id === event.target.value + ); + const isActive = selectedYear ? selectedYear.isActive : false; + // localStorage.setItem('isActiveYearSelected', JSON.stringify(isActive)); + setIsActiveYearSelected(isActive); + if (isActive) { + window.location.reload(); + } else { + router.push('/centers').then(() => { + window.location.reload(); + }); + } }; const closeDrawer = () => { @@ -227,37 +247,39 @@ const MenuDrawer: React.FC = ({ - - - + padding: isDashboard + ? '16px 18px !important' + : '0px 18px !important', + marginTop: '25px', + color: isDashboard ? '#2E1500' : theme.palette.warning.A200, + fontWeight: isDashboard ? '600' : 500, + '&:hover': { + background: isDashboard + ? theme.palette.primary.main + : 'transparent', + }, + }} + startIcon={ + + } + onClick={navigateToDashboard} + > + {t('DASHBOARD.DASHBOARD')} + + + )} - - - - {!isEliminatedFromBuild('Assessments', 'feature') && ( + + padding: isCoursePlanner + ? '16px 18px !important' + : '0px 18px !important', + color: isCoursePlanner ? '#2E1500' : theme.palette.warning.A200, + fontWeight: isCoursePlanner ? '600' : 500, + '&:hover': { + background: isCoursePlanner + ? theme.palette.primary.main + : 'transparent', + }, + marginTop: '15px', + gap: '10px', + }} + startIcon={ + CheckBook Icon + } + onClick={() => { + router.push(`/course-planner`); + }} + > + {t('COURSE_PLANNER.COURSE_PLANNER')} + + + )} + {!isEliminatedFromBuild('Assessments', 'feature') && isActiveYear && ( */} - - - + padding: '0px 18px !important', + gap: '10px', + color: theme.palette.secondary.main, + fontWeight: 500, + '&:hover': { + background: 'transparent', + }, + marginTop: '15px', + }} + endIcon={ + + } + onClick={() => { + localStorage.removeItem('hasSeenTutorial'); + setTimeout(() => { + closeDrawer(); + router.push(`/`); + }, 0); + }} + > + {t('GUIDE_TOUR.LEARN_HOW_TO_USE')} + + + )} ); }; -export default MenuDrawer; +export default MenuDrawer; \ No newline at end of file diff --git a/src/components/ObservationCard.tsx b/src/components/ObservationCard.tsx index 2f9acf00..2c7e2bda 100644 --- a/src/components/ObservationCard.tsx +++ b/src/components/ObservationCard.tsx @@ -1,7 +1,9 @@ -import { Box, Typography, Card, CardContent } from '@mui/material'; +import { Box, Typography, Card, CardContent, Tooltip, Chip } from '@mui/material'; import React, { useEffect, useState } from 'react'; import AssignmentOutlinedIcon from '@mui/icons-material/AssignmentOutlined'; -import { formatEndDate } from '@/utils/Helper'; +import { formatDate, formatEndDate } from '@/utils/Helper'; +import { useTranslation } from 'react-i18next'; +import { LeftDays } from '@/utils/app.constant'; interface ObservationCardProp { name?: string; @@ -18,125 +20,122 @@ const ObservationCard: React.FC = ({ description, onCardClick, startDate, - endDate + endDate, }) => { - const [remainingDays, setRemainingDays] = useState(""); - const [remainingTimes, setRemainingTimes] = useState(); - + const [remainingDays, setRemainingDays] = useState('N/A'); + const [remainingTimes, setRemainingTimes] = useState(0); + const { t } = useTranslation(); useEffect(() => { - const today = new Date(); - console.log("endDate", endDate) - if(endDate) - { - const targetDate = new Date(endDate.toString()); - console.log("targetDate", targetDate) - const diffTime = Math.abs(targetDate?.getTime() - today.getTime()); - const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); - - setRemainingTimes(diffDays) - if(diffDays) - { - - const remainingTime=formatEndDate({diffDays}) - setRemainingDays(remainingTime) + const today = new Date(); + if (endDate) { + const targetDate = new Date(endDate.toString()); + const diffTime = targetDate.getTime() - today.getTime(); + const diffDays = Math.ceil(diffTime / LeftDays.ONE_DAY_IN_MILLISECONDS); + setRemainingTimes(diffDays); + if (diffDays > 0) { + setRemainingDays(formatEndDate({ diffDays })); + } else { + setRemainingDays(0); + setRemainingTimes(0); } - } - }, [endDate]); + return ( - onCardClick?.(id || '')} + - - - - - {remainingDays} left - - + onCardClick?.(id || '')} + > + + + {/* {remainingDays !== 0 && ( + + )} */} + + - {name} - - {/* Description */} - {description && ( - + {description} + + )} + +{endDate &&( - {description} - - )} - - {/* - 16 Jun, 2024 - 31 Dec, 2024 - */} - - - + + {t('OBSERVATION.DUE_DATE')}: + + + {endDate ? formatDate(endDate) : 'N/A'} + + )} + + + + ); }; diff --git a/src/components/Searchbar.tsx b/src/components/Searchbar.tsx index af7f90bd..5a29cac0 100644 --- a/src/components/Searchbar.tsx +++ b/src/components/Searchbar.tsx @@ -10,6 +10,8 @@ import { import SearchIcon from '@mui/icons-material/Search'; import ClearIcon from '@mui/icons-material/Clear'; import { debounce } from '@/utils/Helper'; +import { Telemetry } from '@/utils/app.constant'; +import { telemetryFactory } from '@/utils/telemetry'; export interface SearchBarProps { onSearch: (value: string) => void; @@ -50,6 +52,25 @@ const SearchBar: React.FC = ({ { handleSearch(searchTerm); + + + const windowUrl = window.location.pathname; + const cleanedUrl = windowUrl.replace(/^\//, ''); + const env = cleanedUrl.split("/")[0]; +console.log(env) + const telemetryInteract = { + context: { + env: env, + cdata: [], + }, + edata: { + id: 'search-value:'+searchTerm, + type: Telemetry.SEARCH, + subtype: '', + pageid: cleanedUrl, + }, + }; + telemetryFactory.interact(telemetryInteract); } }; diff --git a/src/components/observations/ObservationComponent.tsx b/src/components/observations/ObservationComponent.tsx index 2c0c2abd..6226af1b 100644 --- a/src/components/observations/ObservationComponent.tsx +++ b/src/components/observations/ObservationComponent.tsx @@ -9,6 +9,8 @@ import { mock } from 'node:test'; import { showToastMessage } from '../Toastify'; import { useTranslation } from 'react-i18next'; import { useRouter } from 'next/router'; +import { Telemetry } from '@/utils/app.constant'; +import { telemetryFactory } from '@/utils/telemetry'; @@ -153,22 +155,59 @@ const ObservationComponent: React.FC = ({ observationQues const response= await updateSubmission({submissionId, submissionData}) if((event as CustomEvent).detail.status==="draft") { + showToastMessage( t('OBSERVATION.FORM_SAVED_SUCCESSFULLY'), 'success'); + t('OBSERVATION.FORM_SAVED_SUCCESSFULLY') - showToastMessage( t('OBSERVATION.FORM_SUBMIT_SUCCESSFULLY'), 'success'); // window.history.back(); // router.push( // `${localStorage.getItem('observationPath')}` // ); + const windowUrl = window.location.pathname; + const cleanedUrl = windowUrl.replace(/^\//, ''); + const telemetryInteract = { + context: { + env: 'observation', + cdata: [], + }, + edata: { + id: 'save-observation-successfully', + type: Telemetry.CLICK, + subtype: '', + pageid: cleanedUrl, + }, + }; + telemetryFactory.interact(telemetryInteract); } else if((event as CustomEvent).detail.status==="submit") { - showToastMessage( t('OBSERVATION.FORM_SAVED_SUCCESSFULLY'), 'success'); + showToastMessage( t('OBSERVATION.FORM_SUBMIT_SUCCESSFULLY'), 'success'); + // window.history.back(); router.push( `${localStorage.getItem('observationPath')}` ); + + + const windowUrl = window.location.pathname; + const cleanedUrl = windowUrl.replace(/^\//, ''); + const telemetryInteract = { + context: { + env: 'observation', + cdata: [], + }, + edata: { + id: 'submit-observation-successfully', + type: Telemetry.CLICK, + subtype: '', + pageid: cleanedUrl, + }, + }; + telemetryFactory.interact(telemetryInteract); + + + } }; diff --git a/src/pages/assessments/index.tsx b/src/pages/assessments/index.tsx index 4918c7c7..9d4202d5 100644 --- a/src/pages/assessments/index.tsx +++ b/src/pages/assessments/index.tsx @@ -13,7 +13,7 @@ import { import { getMyCohortMemberList } from '@/services/MyClassDetailsService'; import { toPascalCase } from '@/utils/Helper'; import { ICohort } from '@/utils/Interfaces'; -import { AssessmentStatus, Role, Status } from '@/utils/app.constant'; +import { AssessmentStatus, Role, Status, Telemetry } from '@/utils/app.constant'; import withAccessControl from '@/utils/hoc/withAccessControl'; import ArrowDropDownSharpIcon from '@mui/icons-material/ArrowDropDownSharp'; import { @@ -34,6 +34,7 @@ import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; import { accessControl, AssessmentType, AttendanceAPILimit, Program } from '../../../app.config'; import { useDirection } from '../../hooks/useDirection'; +import { telemetryFactory } from '@/utils/telemetry'; const DEFAULT_STATUS_ORDER = { [AssessmentStatus.NOT_STARTED]: 0, @@ -399,7 +400,27 @@ const Assessments = () => { style={{ borderRadius: '4px', }} - onChange={(e) => setAssessmentType(e.target.value)} + onChange={(e) => + {setAssessmentType(e.target.value) + const windowUrl = window.location.pathname; + const cleanedUrl = windowUrl.replace(/^\//, ''); + + + const telemetryInteract = { + context: { + env: 'assessments', + cdata: [], + }, + edata: { + id: 'filter-by-assessment-type:'+e.target.value, + type: Telemetry.CLICK, + subtype: '', + pageid: cleanedUrl + }, + }; + telemetryFactory.interact(telemetryInteract); + + }} defaultValue={'pre'} value={assessmentType} > diff --git a/src/pages/attendance-history.tsx b/src/pages/attendance-history.tsx index ae68821a..2c8c3e03 100644 --- a/src/pages/attendance-history.tsx +++ b/src/pages/attendance-history.tsx @@ -56,12 +56,15 @@ import { telemetryFactory } from '@/utils/telemetry'; import NoDataFound from '@/components/common/NoDataFound'; import { fetchAttendanceDetails } from '@/components/AttendanceDetails'; import { useDirection } from '../hooks/useDirection'; +import useStore from '@/store/store'; const UserAttendanceHistory = () => { const theme = useTheme(); const { t } = useTranslation(); const { dir, isRTL } = useDirection(); const { push } = useRouter(); + const store = useStore(); + const isActiveYear = store.isActiveYearSelected; const [selectedDate, setSelectedDate] = useState(new Date()); const [classId, setClassId] = React.useState(''); const [cohortsData, setCohortsData] = React.useState>([]); @@ -159,6 +162,7 @@ const UserAttendanceHistory = () => { } else { push('/login', undefined, { locale: 'en' }); } + !isActiveYear && push('/centers'); } }, []); diff --git a/src/pages/attendance-overview.tsx b/src/pages/attendance-overview.tsx index e21b3fa3..044d95e8 100644 --- a/src/pages/attendance-overview.tsx +++ b/src/pages/attendance-overview.tsx @@ -56,6 +56,7 @@ import { getMenuItems, Telemetry } from '@/utils/app.constant'; import { telemetryFactory } from '@/utils/telemetry'; import NoDataFound from '@/components/common/NoDataFound'; import { useDirection } from '../hooks/useDirection'; +import useStore from '@/store/store'; interface AttendanceOverviewProps { // buttonText: string; @@ -100,6 +101,8 @@ const AttendanceOverview: React.FC = () => { const theme = useTheme(); const pathname = usePathname(); + const store = useStore(); + const isActiveYear = store.isActiveYearSelected; const menuItems = getMenuItems(t, dateRange, currentDayMonth); @@ -120,6 +123,7 @@ const AttendanceOverview: React.FC = () => { } else { push('/login', undefined, { locale: 'en' }); } + !isActiveYear && push('/centers'); } }, []); diff --git a/src/pages/board-enrollment/index.tsx b/src/pages/board-enrollment/index.tsx index 62710216..aa1b7eef 100644 --- a/src/pages/board-enrollment/index.tsx +++ b/src/pages/board-enrollment/index.tsx @@ -20,12 +20,15 @@ import { useDirection } from '../../hooks/useDirection'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import { useRouter } from 'next/router'; import React, { useEffect, useState } from 'react'; +import useStore from '@/store/store'; const BoardEnrollment = () => { const theme = useTheme(); const { t } = useTranslation(); const { dir, isRTL } = useDirection(); const router = useRouter(); + const store = useStore(); + const isActiveYear = store.isActiveYearSelected; const [boardEnrollmentList, setBoardEnrollmentList] = useState([]); const [activeStep, setActiveStep] = React.useState(0); const [classId, setClassId] = React.useState(''); @@ -59,6 +62,7 @@ const BoardEnrollment = () => { } else { router.push('/login', undefined, { locale: 'en' }); } + !isActiveYear && router.push('/centers'); } }, []); diff --git a/src/pages/centers/[cohortId]/index.tsx b/src/pages/centers/[cohortId]/index.tsx index 1d6d808a..2374fcd9 100644 --- a/src/pages/centers/[cohortId]/index.tsx +++ b/src/pages/centers/[cohortId]/index.tsx @@ -72,6 +72,7 @@ import { useDirection } from '../../../hooks/useDirection'; import dynamic from 'next/dynamic'; import { isEliminatedFromBuild } from '../../../../featureEliminationUtil'; import { telemetryFactory } from '@/utils/telemetry'; +import useStore from '@/store/store'; let SessionCardFooter: ComponentType | null = null; if (!isEliminatedFromBuild('SessionCardFooter', 'component')) { SessionCardFooter = dynamic(() => import('@/components/SessionCardFooter'), { @@ -107,8 +108,10 @@ if (!isEliminatedFromBuild('Schedule', 'component')) { } const CohortPage = () => { + const userStore = useStore(); + const isActiveYear = userStore.isActiveYearSelected; const [value, setValue] = React.useState(() => { - return isEliminatedFromBuild('Events', 'feature') ? 2 : 1; + return isEliminatedFromBuild('Events', 'feature') || !isActiveYear ? 2 : 1; }); const [showDetails, setShowDetails] = React.useState(false); const [classId, setClassId] = React.useState(''); @@ -118,7 +121,7 @@ const CohortPage = () => { const { dir, isRTL } = useDirection(); const [role, setRole] = React.useState(''); - const store = manageUserStore(); + // const store = manageUserStore(); const setDistrictCode = manageUserStore( (state: { setDistrictCode: any }) => state.setDistrictCode ); @@ -540,7 +543,7 @@ const cleanedUrl = windowUrl.replace(/^\//, ''); - {role === Role.TEAM_LEADER && ( + {role === Role.TEAM_LEADER && isActiveYear && ( - {!isEliminatedFromBuild('Events', 'feature') && ( + {!isEliminatedFromBuild('Events', 'feature') && isActiveYear && ( )} @@ -937,48 +940,54 @@ const cleanedUrl = windowUrl.replace(/^\//, ''); {value === 2 && ( <> - - - - - { - router.push('/attendance-overview'); - }} - > - {t('COMMON.REVIEW_ATTENDANCE')} + {isActiveYear && ( + + + + + + { + router.push('/attendance-overview'); + }} + > + {t('COMMON.REVIEW_ATTENDANCE')} + + + - - + )} { const setType = taxonomyStore((state) => state.setType); const store = useStore(); const userRole = store.userRole; + const isActiveYear = store.isActiveYearSelected; const handleChange = (event: React.SyntheticEvent, newValue: number) => { setValue(newValue); @@ -470,7 +471,7 @@ const CentersPage = () => { 'showCreateCenterButton', accessControl, userRole - ) && ( + ) && isActiveYear && ( + + {t('PROFILE.EDIT_PROFILE')} + + + + + + )} {openAddLearnerModal && (
@@ -993,21 +1013,22 @@ const LearnerProfile: React.FC = ({ - {(!isEliminatedFromBuild("AssessmentReport", "component") && AssessmentReport) && - - - - - - - - } + {!isEliminatedFromBuild('AssessmentReport', 'component') && + AssessmentReport && isActiveYear && ( + + + + + + + + )} ); }; diff --git a/src/pages/login.tsx b/src/pages/login.tsx index 4db4ce85..3ad181f8 100644 --- a/src/pages/login.tsx +++ b/src/pages/login.tsx @@ -37,6 +37,9 @@ import loginImg from './../assets/images/login-image.jpg'; const LoginPage = () => { const { t, i18n } = useTranslation(); + const setIsActiveYearSelected = useStore( + (state: { setIsActiveYearSelected: any }) => state.setIsActiveYearSelected + ); const setUserId = manageUserStore((state) => state.setUserId); const setUserRole = useStore( (state: { setUserRole: any }) => state.setUserRole @@ -174,6 +177,7 @@ const LoginPage = () => { ); const activeSessionId = activeSession ? activeSession.id : ''; localStorage.setItem('academicYearId', activeSessionId); + setIsActiveYearSelected(true); if (activeSessionId) { setLoading(false); router.push('/dashboard'); diff --git a/src/pages/observation/[observationId]/index.tsx b/src/pages/observation/[observationId]/index.tsx index 5c42b6e1..ae2ba7db 100644 --- a/src/pages/observation/[observationId]/index.tsx +++ b/src/pages/observation/[observationId]/index.tsx @@ -16,7 +16,7 @@ import React, { useEffect, useState, useMemo } from 'react'; import { useRouter } from 'next/router'; import Header from '@/components/Header'; // import AddEntityModal from '@/components/observations/AddEntityModal'; -import { ObservationEntityType, Role , ObservationStatus} from '@/utils/app.constant'; +import { ObservationEntityType, Role , ObservationStatus, Telemetry} from '@/utils/app.constant'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import { GetStaticPaths } from 'next'; import { toPascalCase } from '@/utils/Helper'; @@ -27,6 +27,7 @@ import { } from '@/services/MyClassDetailsService'; import KeyboardBackspaceOutlinedIcon from '@mui/icons-material/KeyboardBackspaceOutlined'; import SearchIcon from '@mui/icons-material/Search'; +import { formatDate } from '@/utils/Helper'; import Pagination from '@mui/material/Pagination'; import { CohortMemberList } from '@/utils/Interfaces'; @@ -34,11 +35,13 @@ import { addEntities, checkEntityStatus, fetchEntities, + targetSolution, } from '@/services/ObservationServices'; import { useTranslation } from 'react-i18next'; import { CheckBoxOutlineBlankRounded } from '@mui/icons-material'; import Entity from '@/components/observations/Entity'; import SearchBar from '@/components/Searchbar'; +import { telemetryFactory } from '@/utils/telemetry'; interface EntityData { cohortId?: string; name?: string; @@ -53,6 +56,8 @@ const ObservationDetails = () => { const { observationName } = router.query; const [myCohortList, setMyCohortList] = useState([]); + const [centerList, setCenterList] = useState([]); + const [myCohortListForCenter, setmyCohortListForCenter] = useState([]); const [cohortIdData, setCohortIdData] = useState([]); const [entityIds, setEntityIds] = useState([]); @@ -75,9 +80,13 @@ const ObservationDetails = () => { const [limit, setLimit] = React.useState(pageLimit); const [searchInput, setSearchInput] = useState(''); - const [description, setDescription] = useState(''); const { t } = useTranslation(); + const [observationData, setObservationData] = useState([]); + const [observationDescription, setObservationDescription] = useState(); + const [observationEndDate, setObservationEndDate] = useState(""); + + const theme = useTheme(); @@ -140,9 +149,26 @@ const ObservationDetails = () => { fetchCohorts(); }, [searchInput]); - + useEffect(() => { + const fetchObservationData = async () => { + try { + const response = await targetSolution(); + setObservationData(response?.result?.data || []); + + } catch (error) { + console.error('Error fetching cohort list:', error); + } + }; + fetchObservationData(); + }, []); + + useEffect(() => { + const result = observationData?.find((item:any) => item._id === Id); + setObservationDescription(result?.description) + setObservationEndDate(result?.endDate) + }, [Id, observationData]); useEffect(() => { const fetchEntityList = async () => { @@ -239,14 +265,14 @@ const ObservationDetails = () => { if(entityId) { const response = await checkEntityStatus({ observationId, entityId }); - console.log("response.result.length",response.result.length) - if(response.result.length!==0) + console.log("response.result.length",response?.result?.length) + if(response?.result?.length!==0) { - if(response?.result[0]?.evidencesStatus[0]?.status==="draft") + if(response?.result[response?.result?.length-1]?.evidencesStatus[0]?.status==="draft") setFirstEntityStatus("draft") - else if(response?.result[0]?.evidencesStatus[0]?.status==="completed") + else if(response?.result[response?.result?.length-1]?.evidencesStatus[0]?.status==="completed") setFirstEntityStatus("completed") - else if(response?.result[0]?.evidencesStatus[0]?.status==="notstarted") + else if(response?.result[response?.result?.length-1]?.evidencesStatus[0]?.status==="notstarted") setFirstEntityStatus("notstarted") } @@ -320,6 +346,7 @@ const ObservationDetails = () => { } finally { } }; + if(selectedCohort && selectedCohort!=='') handleCohortChange(); }, [page, selectedCohort, searchInput]); @@ -352,6 +379,21 @@ const ObservationDetails = () => { setPage(0); setSelectedCohort(event.target.value); localStorage.setItem("selectedCohort",event.target.value) + const windowUrl = window.location.pathname; + const cleanedUrl = windowUrl.replace(/^\//, ''); + const telemetryInteract = { + context: { + env: 'observation', + cdata: [], + }, + edata: { + id: 'filter-by-center:'+event.target.value, + type: Telemetry.CLICK, + subtype: '', + pageid: cleanedUrl, + }, + }; + telemetryFactory.interact(telemetryInteract); }; const onStartObservation = (cohortId: any) => { @@ -360,6 +402,8 @@ const ObservationDetails = () => { const basePath = router.asPath.split('?')[0]; const newFullPath = `${basePath}/questionary`; const { observationName } = router.query; + const { Id } = router.query; + const queryParams = { cohortId: cohortId, Id: Id , observationName: observationName }; router.push({ @@ -400,7 +444,7 @@ const ObservationDetails = () => { const renderEntityData = (data: EntityData[], entityType: string) => { if (!data || data.length === 0) { - return {t('OBSERVATION.NO_DATA_FOUND',{ + return {t('OBSERVATION.NO_DATA_FOUND',{ entity:entity, })} ; @@ -460,13 +504,7 @@ const ObservationDetails = () => { }; - useEffect(() => { - const data= typeof window !== 'undefined' - ? localStorage.getItem("observationDescription") || '' - : ''; - setDescription(data) - }, []); - + return ( <>
@@ -488,7 +526,7 @@ const ObservationDetails = () => { }} onClick={handleBackEvent} /> - {observationName} + {observationName} @@ -496,14 +534,18 @@ const ObservationDetails = () => { {' '} {/* Increased the left side size */} - + - - {t('OBSERVATION.OBSERVATION_DETAILS')} + + {t('OBSERVATION.OBSERVATION_DETAILS')} - - {description} + + + {observationDescription} + + {t('OBSERVATION.DUE_DATE')}: {formatDate(observationEndDate?.toString()) || "N/A"} + { }} > {entity !== ObservationEntityType?.CENTER && ( - - - {t('ATTENDANCE.CENTER_NAME')} + + + + {t('ATTENDANCE.CENTER_NAME')} + {t('COMMON.LOW_TO_HIGH')} + {t('COMMON.HIGH_TO_LOW')} + + )} + {typeof window !== 'undefined' && window.localStorage&& localStorage.getItem('role')=== Role.TEAM_LEADER &&( + )} + + {entityNames && entityNames.map((name, index) => ( { borderRadius: 1, }} > - + {t('OBSERVATION.OBSERVATIONS', { name: toPascalCase(name), })} @@ -123,25 +284,62 @@ const ObservationForms: React.FC = () => { {filteredObservationData.filter((item: any) => item.entityType === name).length > 0 && value===0? ( filteredObservationData - .filter((item: any) => item.entityType === name) + .filter((item: any) => item.entityType === name && new Date(item.endDate) > currentDate) .map((item: any) => ( - onCardClick(item?.solutionId, item?.entityType, item?.name, item?._id, item?.description) + onCardClick(item?.solutionId, item?.entityType, item?.name, item?._id, item?.description, item?.endDate) } description={item?.description} endDate={item?.endDate} /> )) - ) : value===0 &&( - - - Observations are coming soon for {toPascalCase(name)} + ) :value === 1 ? ( + filteredObservationData.filter((item: any) => item.entityType === name && new Date(item.endDate) <= currentDate).length > 0 ? ( + filteredObservationData + .filter((item: any) => item.entityType === name && new Date(item.endDate) <= currentDate) + .map((item: any) => ( + + + // onCardClick(item?.solutionId, item?.entityType, item?.name, item?._id, item?.description) + // } + description={item?.description} + endDate={item?.endDate} + /> + + )) + ) : searchInput === "" ?( + + {t('OBSERVATION.NO_RESULT_FOUND', { + entity: toPascalCase(name), + })} + + ):( + + {t('OBSERVATION.NO_RESULT_FOUND', { + entity: toPascalCase(name), + })} + + ) + ) : searchInput === "" && value === 0 ? ( + + {t('OBSERVATION.NO_RESULT_FOUND', { + entity: toPascalCase(name), + })} + ) : ( + + {t('OBSERVATION.NO_RESULT_FOUND', { + entity: toPascalCase(name), + })} + )} + ))} diff --git a/src/pages/play/content/[identifier].tsx b/src/pages/play/content/[identifier].tsx index 5c8585d4..62b2d653 100644 --- a/src/pages/play/content/[identifier].tsx +++ b/src/pages/play/content/[identifier].tsx @@ -7,6 +7,8 @@ import { getHierarchy, getQumlData, } from '@/services/PlayerService'; +import { Box } from '@mui/material'; +import Header from '@/components/Header'; // @ts-ignore const SunbirdPlayers = dynamic(() => import('editor/SunbirdPlayers'), { @@ -105,7 +107,16 @@ const players: React.FC = () => { loadContent(); }, [identifier]); - return !loading ? : null; + return ( + + +
+ + + {!loading ? : null} + + + ); }; export async function getStaticPaths() { diff --git a/src/pages/topic-detail-view.tsx b/src/pages/topic-detail-view.tsx index ad810677..6a335d92 100644 --- a/src/pages/topic-detail-view.tsx +++ b/src/pages/topic-detail-view.tsx @@ -21,6 +21,7 @@ import useCourseStore from '@/store/coursePlannerStore'; import CourseAccordion from '@/components/CourseAccordion'; import { useDirection } from '../hooks/useDirection'; import { ResourcesType } from '@/utils/app.constant'; +import router from 'next/router'; const TopicDetailView = () => { const [value, setValue] = React.useState(1); @@ -33,7 +34,8 @@ const TopicDetailView = () => { const store = useCourseStore(); const handleBackEvent = () => { - window.history.back(); + // window.history.back(); + router.push(`/course-planner-detail`); logEvent({ action: 'back-button-clicked-attendance-overview', category: 'Attendance Overview Page', @@ -41,6 +43,10 @@ const TopicDetailView = () => { }); }; + const handlePlayers = () => { + sessionStorage.setItem('previousPage', window.location.href); + }; + return ( @@ -122,7 +128,7 @@ const TopicDetailView = () => { {value === 1 && ( - + = ({ const { userId }: any = router.query; const queryClient = useQueryClient(); const theme = useTheme(); + const store = useStore(); + const isActiveYear = store.isActiveYearSelected; + const [userData, setUserData] = useState(null); const [userName, setUserName] = useState(null); const [customFieldsData, setCustomFieldsData] = useState([]); @@ -430,12 +434,14 @@ const TeacherProfile: React.FC = ({ - {})} - isFromFLProfile={true} - teacherUserId={userId} - /> + {isActiveYear && ( + {})} + isFromFLProfile={true} + teacherUserId={userId} + /> + )} )} = ({ width: '100%', }} > - {userRole === Role.TEAM_LEADER && userId !== selfUserId ? ( + {userRole === Role.TEAM_LEADER && + userId !== selfUserId && + isActiveYear ? (