From 045116c9e56a02ee164b5a4e59785bbbcc923e94 Mon Sep 17 00:00:00 2001 From: Rushikesh-Sonawane99 Date: Thu, 4 Jul 2024 00:24:01 +0530 Subject: [PATCH 1/4] Issue #PS-1154 feat: Written service and integrated api to display cohorts on dashboard as per heirarchy for TL and facilitator and created CohortSelectionSection Component --- src/components/CohortSelectionSection.tsx | 322 ++++++++++++++++++++++ src/pages/dashboard.tsx | 157 ++--------- src/services/CohortServices.ts | 2 - 3 files changed, 349 insertions(+), 132 deletions(-) create mode 100644 src/components/CohortSelectionSection.tsx diff --git a/src/components/CohortSelectionSection.tsx b/src/components/CohortSelectionSection.tsx new file mode 100644 index 00000000..4d4b9116 --- /dev/null +++ b/src/components/CohortSelectionSection.tsx @@ -0,0 +1,322 @@ +import { getCohortList } from '@/services/CohortServices'; +import React, { useEffect } from 'react'; +import { useRouter } from 'next/navigation'; +import { cohort } from '@/utils/Interfaces'; +import { + Box, + FormControl, + MenuItem, + Select, + SelectChangeEvent, + Typography, +} from '@mui/material'; +import ReactGA from 'react-ga4'; +import { useTheme } from '@mui/material/styles'; +import { useTranslation } from 'next-i18next'; +import Loader from './Loader'; + +interface CohortSelectionSectionProps { + classId: string; + setClassId: React.Dispatch>; + userId: string | null; + setUserId: React.Dispatch>; + isAuthenticated?: boolean; + setIsAuthenticated?: React.Dispatch>; + loading: boolean; + setLoading: React.Dispatch>; + cohortsData: Array; + setCohortsData: React.Dispatch>>; + manipulatedCohortData?: Array; + setManipulatedCohortData?: React.Dispatch>>; + blockName: string; + isManipulationRequired?: boolean; + setBlockName: React.Dispatch>; + handleSaveHasRun?: boolean; + setHandleSaveHasRun?: React.Dispatch>; + isCustomFieldRequired?: boolean; +} + + +const CohortSelectionSection: React.FC = ({ + classId, + setClassId, + userId, + setUserId, + isAuthenticated, + setIsAuthenticated, + loading, + setLoading, + cohortsData, + setCohortsData, + manipulatedCohortData, + setManipulatedCohortData, + isManipulationRequired = true, + blockName, + setBlockName, + handleSaveHasRun, + setHandleSaveHasRun, + isCustomFieldRequired = false, +}) => { + const router = useRouter(); + const theme = useTheme(); + const { t } = useTranslation(); + + useEffect(() => { + if (typeof window !== 'undefined' && window.localStorage) { + const token = localStorage.getItem('token'); + const storedUserId = localStorage.getItem('userId'); + setClassId(localStorage.getItem('classId') || ''); + if (token) { + setIsAuthenticated?.(true); + } else { + router.push('/login'); + } + setUserId(storedUserId); + } + }, [router, setClassId, setIsAuthenticated, setUserId]); + + useEffect(() => { + // const userId = localStorage.getItem('userId'); + // if (userId) { + // setUserId(userId); + // } + if (userId) { + setLoading(true); + const fetchCohorts = async () => { + try { + const response = await getCohortList(userId, {customField: isCustomFieldRequired.toString()}); + console.log('Response:', response); + if (response && response.length > 0) { + if (response[0].type === 'COHORT') { + let filteredData = response + ?.map((item: any) => ({ + cohortId: item?.cohortId, + parentId: item?.parentId, + name: item?.cohortName || item?.name, + })) + ?.filter(Boolean); + setCohortsData(filteredData); + if (filteredData.length > 0) { + if (typeof window !== 'undefined' && window.localStorage) { + const cohort = localStorage.getItem('classId') || ''; + if (cohort !== '') { + setClassId(localStorage.getItem('classId') || ''); + } else { + localStorage.setItem( + 'classId', + filteredData?.[0]?.cohortId + ); + setClassId(filteredData?.[0]?.cohortId); + } + } + if(isManipulationRequired){ + setManipulatedCohortData?.( + filteredData.concat({ cohortId: 'all', name: 'All Centers' }) + ); + }else{ + setManipulatedCohortData?.(filteredData); + } + + } + } else if (response[0].type === 'BLOCK') { + setBlockName(response[0].name || response[0].cohortName); + const filteredData = response[0].childData + ?.map((item: any) => ({ + cohortId: item?.cohortId, + parentId: item?.parentId, + name: item?.cohortName || item?.name, + })) + ?.filter(Boolean); + setCohortsData(filteredData); + + if (filteredData.length > 0) { + if (typeof window !== 'undefined' && window.localStorage) { + const cohort = localStorage.getItem('classId') || ''; + if (cohort !== '') { + setClassId(localStorage.getItem('classId') || ''); + } else { + localStorage.setItem( + 'classId', + filteredData?.[0]?.cohortId + ); + setClassId(filteredData?.[0]?.cohortId); + } + } + } + setManipulatedCohortData?.(filteredData); + } + } + setLoading(false); + } catch (error) { + console.error('Error fetching cohort list', error); + setLoading(false); + } + }; + + fetchCohorts(); + } + }, [userId, setCohortsData, setLoading, setClassId, setManipulatedCohortData, setBlockName, isCustomFieldRequired]); + + const handleCohortSelection = (event: SelectChangeEvent) => { + setClassId(event.target.value as string); + ReactGA.event('cohort-selection-dashboard', { + selectedCohortID: event.target.value, + }); + localStorage.setItem('classId', event.target.value); + {setHandleSaveHasRun? setHandleSaveHasRun(!handleSaveHasRun): null} + + + // ---------- set cohortId and stateName----------- + const cohort_id = event.target.value; + localStorage.setItem('cohortId', cohort_id); + + const get_state_name: string | null = getStateByCohortId(cohort_id); + if (get_state_name) { + localStorage.setItem('stateName', get_state_name); + } else { + localStorage.setItem('stateName', ''); + console.log('NO State For Selected Cohort'); + } + function getStateByCohortId(cohortId: any) { + const cohort = cohortsData?.find((item) => item.cohortId === cohortId); + return cohort ? cohort?.state : null; + } + }; + + return ( + + {loading && } + {!loading && cohortsData && ( + + {loading && } + {!loading && cohortsData && ( + + {blockName ? ( + + + {blockName} + + + + {cohortsData?.length > 1 ? ( + + + + ) : ( + + {cohortsData[0]?.name} + + )} + + + + ) : ( + + + + {cohortsData?.length > 1 ? ( + + + + ) : ( + + {cohortsData[0]?.name} + + )} + + + + )} + + )} + + )} + + ); +}; + +export default CohortSelectionSection; diff --git a/src/pages/dashboard.tsx b/src/pages/dashboard.tsx index b65ae95a..633e4dc1 100644 --- a/src/pages/dashboard.tsx +++ b/src/pages/dashboard.tsx @@ -6,17 +6,7 @@ import { cohortAttendancePercentParam, cohortMemberList, } from '../utils/Interfaces'; -import { - Box, - Button, - FormControl, - Grid, - MenuItem, - Select, - SelectChangeEvent, - Stack, - Typography, -} from '@mui/material'; +import { Box, Button, Grid, Stack, Typography } from '@mui/material'; import { CircularProgressbar, buildStyles } from 'react-circular-progressbar'; import React, { useEffect } from 'react'; import { @@ -24,7 +14,6 @@ import { getAllCenterAttendance, getCohortAttendance, } from '../services/AttendanceService'; -// import Snackbar, { SnackbarOrigin } from '@mui/material/Snackbar'; import { format, isAfter, isValid, parse, startOfDay } from 'date-fns'; import { formatSelectedDate, @@ -46,7 +35,6 @@ import ReactGA from 'react-ga4'; import WeekCalender from '@/components/WeekCalender'; import { calculatePercentage } from '@/utils/attendanceStats'; import calendar from '../assets/images/calendar.svg'; -import { cohortList } from '../services/CohortServices'; import { getMyCohortMemberList } from '@/services/MyClassDetailsService'; import { logEvent } from '@/utils/googleAnalytics'; import { lowLearnerAttendanceLimit } from './../../app.config'; @@ -57,7 +45,8 @@ import useDeterminePathColor from '../hooks/useDeterminePathColor'; import { useRouter } from 'next/navigation'; import { useTheme } from '@mui/material/styles'; import { useTranslation } from 'next-i18next'; -import { useCohortList } from '@/services/queries'; +import CohortSelectionSection from '@/components/CohortSelectionSection'; + interface DashboardProps { // buttonText: string; } @@ -96,6 +85,7 @@ const Dashboard: React.FC = () => { sevenDaysAgo.setDate(currentDate.getDate() - modifyAttendanceLimit); const formattedSevenDaysAgo = shortDateFormat(sevenDaysAgo); const [userId, setUserId] = React.useState(null); + const [blockName, setBlockName] = React.useState(''); useEffect(() => { setIsClient(true); @@ -144,51 +134,6 @@ const Dashboard: React.FC = () => { const page = 0; const filters = { userId: userId || '' }; - useEffect(() => { - if (userId) { - setLoading(true); - const fetchCohorts = async () => { - try { - const response = await cohortList({ limit, page, filters }); - const extractedNames = response?.results?.cohortDetails; - localStorage.setItem( - 'parentCohortId', - extractedNames?.[0].cohortData?.parentId - ); - - const filteredData = extractedNames - ?.map((item: any) => ({ - cohortId: item?.cohortId, - parentId: item?.parentId, - name: item?.name, - })) - ?.filter(Boolean); - setCohortsData(filteredData); - if (filteredData.length > 0) { - if (typeof window !== 'undefined' && window.localStorage) { - const cohort = localStorage.getItem('classId') || ''; - if (cohort !== '') { - setClassId(localStorage.getItem('classId') || ''); - } else { - localStorage.setItem('classId', filteredData?.[0]?.cohortId); - setClassId(filteredData?.[0]?.cohortId); - } - } - setManipulatedCohortData( - filteredData.concat({ cohortId: 'all', name: 'All Centers' }) - ); - } - setLoading(false); - } catch (error) { - console.error('Error fetching cohort list', error); - setLoading(false); - } - }; - - fetchCohorts(); - } - }, [userId]); - //API for getting student list useEffect(() => { const getCohortMemberList = async () => { @@ -210,7 +155,7 @@ const Dashboard: React.FC = () => { name: toPascalCase(entry.name), })); if (nameUserIdArray) { - //Write logic to call class missed api + //Logic to call class missed api const fromDate = startDateRange; const toDate = endDateRange; const filters = { @@ -248,7 +193,7 @@ const Dashboard: React.FC = () => { (user) => user.absent && (user.present_percent < lowLearnerAttendanceLimit || - user.present_percent === undefined) //TODO: Modify here condition to show low attendance learners + user.present_percent === undefined) ); // Extract names of these students @@ -308,7 +253,7 @@ const Dashboard: React.FC = () => { scope: 'student', contextId: cohortId, }; - console.log('Filters:', filters); // Log filters to ensure contextId is set + // console.log('Filters:', filters); try { const response = await getAllCenterAttendance({ @@ -396,15 +341,6 @@ const Dashboard: React.FC = () => { }); }; - const handleCohortSelection = (event: SelectChangeEvent) => { - setClassId(event.target.value as string); - ReactGA.event('cohort-selection-dashboard', { - selectedCohortID: event.target.value, - }); - localStorage.setItem('classId', event.target.value); - setHandleSaveHasRun(!handleSaveHasRun); - }; - const getMonthName = (dateString: string) => { try { const parsedDate = parse(dateString, 'yyyy-MM-dd', new Date()); @@ -597,65 +533,26 @@ const Dashboard: React.FC = () => { /> - - - {cohortsData?.length > 1 ? ( - - - - ) : ( - - {cohortsData[0]?.name} - - )} - - - {/* TODO: Write logic to disable this block on all select */} + + {/* Logic to disable this block on all select */} => { let apiUrl: string = `${process.env.NEXT_PUBLIC_BASE_URL}/cohort/mycohorts/${userId}?children=true`; - const filterParams = new URLSearchParams(filters).toString(); if (filterParams) { apiUrl += `&${filterParams}`; } - try { const response = await get(apiUrl); return response?.data?.result; From b49ca208726f5dbf5434cff496c4e4115c9d7ab0 Mon Sep 17 00:00:00 2001 From: Rushikesh-Sonawane99 Date: Thu, 4 Jul 2024 00:25:40 +0530 Subject: [PATCH 2/4] Issue #PS-1155 feat: Integrated api to display cohorts as per heirarchy for TL and facilitator on attendance-history page --- src/pages/attendance-history.tsx | 165 ++++++------------------------- 1 file changed, 29 insertions(+), 136 deletions(-) diff --git a/src/pages/attendance-history.tsx b/src/pages/attendance-history.tsx index c8024edf..51838439 100644 --- a/src/pages/attendance-history.tsx +++ b/src/pages/attendance-history.tsx @@ -7,14 +7,10 @@ import { import { Box, Button, - FormControl, Grid, IconButton, InputBase, - MenuItem, Paper, - Select, - SelectChangeEvent, Stack, Typography, } from '@mui/material'; @@ -42,7 +38,6 @@ import SortingModal from '../components/SortingModal'; import UpDownButton from '@/components/UpDownButton'; import { attendanceStatusList } from '../services/AttendanceService'; import { calculatePercentage } from '@/utils/attendanceStats'; -import { cohortList } from '@/services/CohortServices'; import { cohortMemberList } from '../utils/Interfaces'; import { getMyCohortMemberList } from '@/services/MyClassDetailsService'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; @@ -53,6 +48,7 @@ import { useTranslation } from 'next-i18next'; import { logEvent } from '@/utils/googleAnalytics'; import { showToastMessage } from '@/components/Toastify'; import { Status } from '@/utils/app.constant'; +import CohortSelectionSection from '@/components/CohortSelectionSection'; interface user { memberStatus: string; @@ -88,10 +84,15 @@ const UserAttendanceHistory = () => { const [loading, setLoading] = React.useState(false); const [open, setOpen] = useState(false); const [handleSaveHasRun, setHandleSaveHasRun] = React.useState(false); + const [blockName, setBlockName] = React.useState(''); + const [isAuthenticated, setIsAuthenticated] = React.useState(false); + const [userId, setUserId] = React.useState(null); + const [manipulatedCohortData, setManipulatedCohortData] = + React.useState>(cohortsData); const searchRef = useRef(null); const pathname = usePathname(); - let userId: string; + // let userId: string; const currentDate = getTodayDate(); const handleOpen = () => { @@ -117,66 +118,6 @@ const UserAttendanceHistory = () => { } }, []); - // API call to get center list - useEffect(() => { - const fetchCohortList = async () => { - const userId = localStorage.getItem('userId'); - setLoading(true); - try { - if (userId) { - const limit = 0; - const page = 0; - const filters = { userId: userId }; - const resp = await cohortList({ limit, page, filters }); - const extractedNames = resp?.results?.cohortDetails; - const filteredData = extractedNames - ?.map((item: any) => { - const stateNameField = item?.customFields.find( - (field: any) => field.label === 'State Name' - ); - const stateName = stateNameField ? stateNameField.value : ''; - - return { - cohortId: item?.cohortId, - name: item?.name, - state: stateName, - }; - }) - ?.filter(Boolean); - - setCohortsData(filteredData); - // setClassId(filteredData?.[0]?.cohortId); - // localStorage.setItem('classId', filteredData?.[0]?.cohortId); - - // ----- add state name to localstorage---------- - if ( - extractedNames?.length > 0 && - extractedNames?.[0].cohortData.customFields - ) { - const customFields = extractedNames?.[0].cohortData.customFields; - const stateNameField = customFields?.find( - (field: any) => field.label === 'State Name' - ); - if (stateNameField) { - const state_name = stateNameField.value; - if (state_name) { - localStorage.setItem('stateName', state_name); - } else { - localStorage.setItem('stateName', ''); - } - } - } - setLoading(false); - } - } catch (error) { - console.error('Error fetching cohort list:', error); - showToastMessage(t('COMMON.SOMETHING_WENT_WRONG'), 'error'); - setLoading(false); - } - }; - fetchCohortList(); - }, []); - useEffect(() => { const getAttendanceStats = async () => { if (classId !== '' && classId !== undefined) { @@ -414,26 +355,6 @@ const UserAttendanceHistory = () => { } }; - const handleCohortSelection = (event: SelectChangeEvent) => { - setClassId(event.target.value as string); - ReactGA.event('cohort-selection-attendance-history-page', { - selectedCohortID: event.target.value, - }); - setHandleSaveHasRun(!handleSaveHasRun); - - // ---------- set cohortId and stateName----------- - const cohort_id = event.target.value; - localStorage.setItem('cohortId', cohort_id); - - const get_state_name: string | null = getStateByCohortId(cohort_id); - if (get_state_name) { - localStorage.setItem('stateName', get_state_name); - } else { - localStorage.setItem('stateName', ''); - console.log('NO State For Selected Cohortksdbj'); - } - }; - function getStateByCohortId(cohortId: any) { const cohort = cohortsData?.find((item) => item.cohortId === cohortId); return cohort ? cohort?.state : null; @@ -635,56 +556,28 @@ const UserAttendanceHistory = () => { - - {cohortsData?.length > 1 ? ( - - - - ) : ( - - {cohortsData[0]?.name} - - )} + + + Date: Thu, 4 Jul 2024 00:26:21 +0530 Subject: [PATCH 3/4] Issue #PS-1156 feat: Integrated api to display cohorts as per heirarchy for TL and facilitator on attendance-overview page --- src/pages/attendance-overview.tsx | 159 +++++------------------------- 1 file changed, 22 insertions(+), 137 deletions(-) diff --git a/src/pages/attendance-overview.tsx b/src/pages/attendance-overview.tsx index 5c8a5f3e..6a8928e2 100644 --- a/src/pages/attendance-overview.tsx +++ b/src/pages/attendance-overview.tsx @@ -3,14 +3,10 @@ import { Box, Button, - FormControl, Grid, IconButton, InputBase, - MenuItem, Paper, - Select, - SelectChangeEvent, Stack, Typography, } from '@mui/material'; @@ -45,7 +41,6 @@ import SearchIcon from '@mui/icons-material/Search'; import SortingModal from '@/components/SortingModal'; import StudentsStatsList from '@/components/LearnerAttendanceStatsListView'; import UpDownButton from '@/components/UpDownButton'; -import { cohortList } from '@/services/CohortServices'; import { getMyCohortMemberList } from '@/services/MyClassDetailsService'; import { lowLearnerAttendanceLimit } from './../../app.config'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; @@ -55,6 +50,7 @@ import { useTheme } from '@mui/material/styles'; import { useTranslation } from 'next-i18next'; import { logEvent } from '@/utils/googleAnalytics'; import { showToastMessage } from '@/components/Toastify'; +import CohortSelectionSection from '@/components/CohortSelectionSection'; interface AttendanceOverviewProps { // buttonText: string; @@ -71,6 +67,7 @@ const AttendanceOverview: React.FC = () => { React.useState>(cohortsData); const [allCenterAttendanceData, setAllCenterAttendanceData] = React.useState(cohortsData); + const [isAuthenticated, setIsAuthenticated] = React.useState(false); const [loading, setLoading] = React.useState(false); const [searchWord, setSearchWord] = React.useState(''); @@ -84,7 +81,7 @@ const AttendanceOverview: React.FC = () => { Array >([]); const [currentDayMonth, setCurrentDayMonth] = React.useState(''); - const [userId, setUserId] = React.useState(''); + const [userId, setUserId] = React.useState(null); const [selectedValue, setSelectedValue] = React.useState(''); const [presentPercentage, setPresentPercentage] = React.useState< string | number @@ -94,6 +91,7 @@ const AttendanceOverview: React.FC = () => { const [numberOfDaysAttendanceMarked, setNumberOfDaysAttendanceMarked] = useState(0); const [dateRange, setDateRange] = React.useState(''); + const [blockName, setBlockName] = React.useState(''); const theme = useTheme(); const pathname = usePathname(); @@ -184,72 +182,6 @@ const AttendanceOverview: React.FC = () => { }), ]); - // API call to get center list - useEffect(() => { - const fetchCohortList = async () => { - const userId = localStorage.getItem('userId'); - if (userId) { - setUserId(userId); - } - setLoading(true); - try { - if (userId) { - const limit = 0; - const page = 0; - const filters = { userId: userId }; - const resp = await cohortList({ limit, page, filters }); - const response = resp?.results; - const cohortDetails = response?.cohortDetails || []; - - const filteredData = cohortDetails?.map((item: any) => { - const stateNameField = item?.customFields.find( - (field: any) => field.label === 'State Name' - ); - const stateName = stateNameField ? stateNameField.value : ''; - - return { - cohortId: item?.cohortId, - name: toPascalCase(item?.name), - state: stateName, - }; - }); - - setCohortsData(filteredData); - - if (filteredData.length > 0) { - // setClassId(filteredData[0].cohortId); - - // add state name to localstorage - if (cohortDetails?.length > 0 && cohortDetails?.[0].customFields) { - const customFields = cohortDetails?.[0].customFields; - const stateNameField = customFields?.find( - (field: any) => field.label === 'State Name' - ); - if (stateNameField) { - const state_name = stateNameField.value; - if (state_name) { - localStorage.setItem('stateName', state_name); - } else { - localStorage.setItem('stateName', ''); - console.log('No State Name'); - } - } - } - setManipulatedCohortData( - filteredData.concat({ cohortId: 'all', name: 'All Centers' }) - ); - } - } - setLoading(false); - } catch (error) { - console.error('Error fetching cohort list:', error); - showToastMessage(t('COMMON.SOMETHING_WENT_WRONG'), 'error'); - setLoading(false); - } - }; - fetchCohortList(); - }, []); - const handleDateRangeSelected = ({ fromDate, toDate }: any) => { console.log('Date Range Selected:', { fromDate, toDate }); setIsFromDate(fromDate); @@ -457,30 +389,6 @@ const AttendanceOverview: React.FC = () => { // setDisplayStudentList(learnerData); // },[searchWord == ""]) - const handleCohortSelection = (event: SelectChangeEvent) => { - setClassId(event.target.value as string); - ReactGA.event('cohort-selection-attendance-overview-page', { - selectedCohortID: event.target.value, - }); - - // ---------- set cohortId and stateName----------- - const cohort_id = event.target.value; - localStorage.setItem('cohortId', cohort_id); - - const get_state_name: string | null = getStateByCohortId(cohort_id); - if (get_state_name) { - localStorage.setItem('stateName', get_state_name); - } else { - localStorage.setItem('stateName', ''); - console.log('NO State For Selected Cohort'); - } - }; - - function getStateByCohortId(cohortId: any) { - const cohort = cohortsData?.find((item) => item.cohortId === cohortId); - return cohort ? cohort?.state : null; - } - const handleSearchClear = () => { setSearchWord(''); setDisplayStudentList(learnerData); @@ -618,47 +526,24 @@ const AttendanceOverview: React.FC = () => { {t('ATTENDANCE.ATTENDANCE_OVERVIEW')} - - - {cohortsData?.length > 1 ? ( - - - - ) : ( - - {cohortsData[0]?.name} - - )} + + From dc4c8b246f71c450646184ad0dfe60ecb97d2f28 Mon Sep 17 00:00:00 2001 From: Rushikesh-Sonawane99 Date: Thu, 4 Jul 2024 00:37:27 +0530 Subject: [PATCH 4/4] Updated PR by resolving code rabbit comment --- src/components/CohortSelectionSection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/CohortSelectionSection.tsx b/src/components/CohortSelectionSection.tsx index 4d4b9116..4593c572 100644 --- a/src/components/CohortSelectionSection.tsx +++ b/src/components/CohortSelectionSection.tsx @@ -163,7 +163,7 @@ const CohortSelectionSection: React.FC = ({ selectedCohortID: event.target.value, }); localStorage.setItem('classId', event.target.value); - {setHandleSaveHasRun? setHandleSaveHasRun(!handleSaveHasRun): null} + setHandleSaveHasRun?.(!handleSaveHasRun) // ---------- set cohortId and stateName-----------