diff --git a/src/components/MarkBulkAttendance.tsx b/src/components/MarkBulkAttendance.tsx new file mode 100644 index 00000000..5b5bc89a --- /dev/null +++ b/src/components/MarkBulkAttendance.tsx @@ -0,0 +1,426 @@ +import { Box, Button, Fade, Modal, Typography } from '@mui/material'; +import React, { useEffect } from 'react'; +import Loader from './Loader'; +import AttendanceStatusListView from './AttendanceStatusListView'; +import { useTranslation } from 'next-i18next'; +import { shortDateFormat } from '../utils/Helper'; +import CloseIcon from '@mui/icons-material/Close'; +import { useTheme } from '@mui/material/styles'; +import Backdrop from '@mui/material/Backdrop'; +import { getMyCohortMemberList } from '@/services/MyClassDetailsService'; +import { + attendanceStatusList, + bulkAttendance, +} from '@/services/AttendanceService'; +import Snackbar, { SnackbarOrigin } from '@mui/material/Snackbar'; +import { AttendanceStatusListProps } from '../utils/Interfaces'; + +interface State extends SnackbarOrigin { + openModal: boolean; +} +interface MarkBulkAttendanceProps { + open: boolean; + onClose: () => void; + classId: string; + selectedDate: Date; + onSaveSuccess: () => void; +} + +const MarkBulkAttendace: React.FC = ({ + open, + onClose, + classId, + selectedDate, + onSaveSuccess, +}) => { + const { t } = useTranslation(); + const theme = useTheme(); + const [loading, setLoading] = React.useState(false); + // const [open, setOpen] = React.useState(false); + const [showUpdateButton, setShowUpdateButton] = React.useState(false); + const [cohortMemberList, setCohortMemberList] = React.useState>([]); + const [bulkAttendanceStatus, setBulkAttendanceStatus] = React.useState(''); + const [isAllAttendanceMarked, setIsAllAttendanceMarked] = + React.useState(false); + const [numberOfCohortMembers, setNumberOfCohortMembers] = React.useState(0); + const [state, setState] = React.useState({ + openModal: false, + vertical: 'top', + horizontal: 'center', + }); + const { vertical, horizontal, openModal } = state; + + // const handleModalToggle = () => setOpen(!open); + const modalContainer = { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: 300, + bgcolor: theme.palette.warning['A400'], + border: '2px solid #000', + boxShadow: 24, + p: 4, + }; + + const submitBulkAttendanceAction = ( + isBulkAction: boolean, + status: string, + id?: string | undefined + ) => { + const updatedAttendanceList = cohortMemberList?.map((user: any) => { + if (isBulkAction) { + user.attendance = status; + setBulkAttendanceStatus(status); + } else { + setBulkAttendanceStatus(''); + if (user.userId === id) { + user.attendance = status; + } + } + return user; + }); + setCohortMemberList(updatedAttendanceList); + const hasEmptyAttendance = () => { + const allAttendance = updatedAttendanceList.some( + (user) => user.attendance === '' + ); + setIsAllAttendanceMarked(!allAttendance); + if (!allAttendance) { + setShowUpdateButton(true); + } + }; + hasEmptyAttendance(); + }; + + useEffect(() => { + submitBulkAttendanceAction(true, '', ''); + const getCohortMemberList = async () => { + setLoading(true); + try { + if (classId) { + const limit = 100; + const page = 0; + const filters = { cohortId: classId }; + const response = await getMyCohortMemberList({ + limit, + page, + filters, + }); + const resp = response?.data?.userDetails; + + if (resp) { + const nameUserIdArray = resp?.map((entry: any) => ({ + userId: entry.userId, + name: entry.name, + })); + if (nameUserIdArray && selectedDate) { + const formatSelectedDate = shortDateFormat(selectedDate); + const userAttendanceStatusList = async () => { + const attendanceStatusData: AttendanceStatusListProps = { + limit: 200, + page: 1, + filters: { + fromDate: formatSelectedDate, + toDate: formatSelectedDate, + }, + }; + const res = await attendanceStatusList(attendanceStatusData); + const response = res?.data?.attendanceList; + console.log('attendanceStatusList', response); + if (nameUserIdArray && response) { + const getUserAttendanceStatus = ( + nameUserIdArray: any[], + response: any[] + ) => { + const userAttendanceArray: { + userId: any; + attendance: any; + }[] = []; + + nameUserIdArray.forEach((user) => { + const userId = user.userId; + const attendance = response.find( + (status) => status.userId === userId + ); + if (attendance) { + userAttendanceArray.push({ + userId, + attendance: attendance.attendance, + }); + } + }); + return userAttendanceArray; + }; + const userAttendanceArray = getUserAttendanceStatus( + nameUserIdArray, + response + ); + console.log('userAttendanceArray', userAttendanceArray); + + if (nameUserIdArray && userAttendanceArray) { + const mergeArrays = ( + nameUserIdArray: { userId: string; name: string }[], + userAttendanceArray: { + userId: string; + attendance: string; + }[] + ): { + userId: string; + name: string; + attendance: string; + }[] => { + const newArray: { + userId: string; + name: string; + attendance: string; + }[] = []; + nameUserIdArray.forEach((user) => { + const userId = user.userId; + const attendanceEntry = userAttendanceArray.find( + (entry) => entry.userId === userId + ); + if (attendanceEntry) { + newArray.push({ + userId, + name: user.name, + attendance: attendanceEntry.attendance, + }); + } + }); + if (newArray.length != 0) { + setCohortMemberList(newArray); + setNumberOfCohortMembers(newArray?.length); + } else { + setCohortMemberList(nameUserIdArray); + setNumberOfCohortMembers(nameUserIdArray?.length); + } + return newArray; + }; + mergeArrays(nameUserIdArray, userAttendanceArray); + } + } + setLoading(false); + }; + userAttendanceStatusList(); + } + } + } + } catch (error) { + console.error('Error fetching cohort list:', error); + setLoading(false); + } finally { + setLoading(false); + } + }; + + if (classId !== '') { + getCohortMemberList(); + } + }, [classId, selectedDate]); + + const handleSave = () => { + onClose(); + const userAttendance = cohortMemberList?.map((user: any) => { + return { + userId: user.userId, + attendance: user.attendance, + }; + }); + if (userAttendance) { + const date = shortDateFormat(selectedDate); + const data = { + attendanceDate: date, + contextId: classId, + userAttendance, + }; + const markBulkAttendance = async () => { + setLoading(true); + try { + const response = await bulkAttendance(data); + const resp = response?.data; + setShowUpdateButton(true); + onClose(); + setLoading(false); + if (onSaveSuccess) { + onSaveSuccess(); + } + } catch (error) { + console.error('Error fetching cohort list:', error); + setLoading(false); + } + handleClick({ vertical: 'bottom', horizontal: 'center' })(); + }; + markBulkAttendance(); + } + }; + + const handleClick = (newState: SnackbarOrigin) => () => { + setState({ ...newState, openModal: true }); + }; + + const handleClose = () => { + setState({ ...state, openModal: false }); + }; + + return ( + + + + + + + + + {t('COMMON.MARK_CENTER_ATTENDANCE')} + + + {shortDateFormat(selectedDate)} + + + onClose()}> + + + + + {loading && ( + + )} + + + {t('ATTENDANCE.TOTAL_STUDENTS', { + count: numberOfCohortMembers, + })} + + {cohortMemberList && cohortMemberList?.length != 0 ? ( + + + + {cohortMemberList?.map( + ( + user: any //cohort member list should have userId, attendance, name + ) => ( + + ) + )} + + + + + + + ) : ( + + {t('COMMON.NO_DATA_FOUND')} + + )} + + + + + + + + ); +}; + +export default MarkBulkAttendace; diff --git a/src/pages/attendance-history.tsx b/src/pages/attendance-history.tsx index 59bc09b6..8549bdef 100644 --- a/src/pages/attendance-history.tsx +++ b/src/pages/attendance-history.tsx @@ -31,7 +31,6 @@ import { cohort, AttendanceStatusListProps, } from '../utils/Interfaces'; -import MarkAttendance from '../components/MarkAttendance'; import { useTranslation } from 'next-i18next'; import Loader from '../components/Loader'; import MonthCalender from '@/components/MonthCalender'; @@ -54,7 +53,8 @@ interface user { attendance?: string; key?: string; } -import AttendanceStatus from '@/components/AttendaceStatus'; +import AttendanceStatus from '@/components/AttendanceStatus'; +import MarkBulkAttendance from '@/components/MarkBulkAttendance'; const UserAttendanceHistory = () => { const theme = useTheme(); @@ -86,6 +86,8 @@ const UserAttendanceHistory = () => { setOpenMarkAttendance(!openMarkAttendance); const [loading, setLoading] = React.useState(false); const [AttendanceMessage, setAttendanceMessage] = React.useState(''); + const [open, setOpen] = useState(false); + const [handleSaveHasRun, setHandleSaveHasRun] = React.useState(false); let userId: string; const currentDate = getTodayDate(); @@ -97,6 +99,14 @@ const UserAttendanceHistory = () => { window.history.back(); }; + const handleOpen = () => { + setOpen(true); + }; + + const handleClose = () => { + setOpen(false); + }; + // API call to get center list useEffect(() => { const fetchCohortList = async () => { @@ -199,7 +209,7 @@ const UserAttendanceHistory = () => { } }; fetchData(); - }, [classId]); + }, [classId, handleSaveHasRun]); //API for getting student list const getCohortMemberList = async () => { @@ -410,6 +420,7 @@ const UserAttendanceHistory = () => { const handleCohortSelection = (event: SelectChangeEvent) => { setClassId(event.target.value as string); + setHandleSaveHasRun(!handleSaveHasRun); }; const handleSearchClear = () => { @@ -606,7 +617,7 @@ const UserAttendanceHistory = () => { @@ -731,14 +742,12 @@ const UserAttendanceHistory = () => { )} - setHandleSaveHasRun(true)} />