diff --git a/src/App.js b/src/App.js index 0077d92..154a90e 100644 --- a/src/App.js +++ b/src/App.js @@ -22,6 +22,7 @@ import DetailRoomEducation from "./_screens/home/detail-room-education"; import EducationDepartmentHome from "./_screens/home/education-department"; import { Alert } from "./_components/Alert"; import OutstandingTeacher from "./_screens/home/outstanding-teacher"; +import { TYPE_DISPATCH } from "./_constants/common"; function App() { const dispatch = useDispatch(); @@ -44,7 +45,14 @@ function App() { dispatch(alertActions?.clear()); }); }, []); - // console.log("authen: ", authentication); + + useEffect(() => { + if(authentication?.user?.role === "student"||authentication?.user?.role === "parent") + dispatch({ + type: TYPE_DISPATCH.RESET_AUTHENTICATION, + }); + }, []) + return (
diff --git a/src/_components/Header/index.js b/src/_components/Header/index.js index cd2a912..43db49e 100644 --- a/src/_components/Header/index.js +++ b/src/_components/Header/index.js @@ -4,6 +4,10 @@ import { configConstants } from "../../_constants"; export default function Header({ icon, title, subtitles = [] }) { const authentication = useSelector((state) => state.authentication); + const { fullname, organization_name, role } = authentication?.user || {}; + const hasFullName = fullname || organization_name; + + const fullName = role === "organization_admin" ? `Hiệu trưởng ${hasFullName}` : fullname; return (
@@ -21,7 +25,7 @@ export default function Header({ icon, title, subtitles = [] }) {

-

{authentication?.user?.fullname}

+

{fullName}

{ - if(action.payload?.user?.role !=="student"){ switch (action.type) { case TYPE_DISPATCH.LOGIN: return { @@ -19,10 +18,6 @@ const authentication = (state = initialState, action) => { default: return state; } - }else{ - alert('Bạn không có quyền truy cập'); - return initialState; - } }; export { authentication }; diff --git a/src/_screens/criteria/criteria-manage/index.js b/src/_screens/criteria/criteria-manage/index.js index 8244f88..fc1c69c 100644 --- a/src/_screens/criteria/criteria-manage/index.js +++ b/src/_screens/criteria/criteria-manage/index.js @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import Header from "../../../_components/Header"; import { renderIconSearchInput, @@ -40,6 +40,7 @@ export default function CriteriaManage() { const [limitOnline] = useState(10); const [offsetOnline, setOffsetOnline] = useState(0); const [isEndOnlineClasses, setIsEndOnlineClasses] = useState(false); + const listRef = useRef(null); const dispatch = useDispatch(); const changeProvince = (item) => { setProvinceSelect(item); @@ -55,6 +56,15 @@ export default function CriteriaManage() { setDistrictSelect(item); }; + const scrollToTop = () => { + if (listRef.current) { + listRef.current.scrollTo({ + top: 0, + behavior: 'smooth', + }); + } + }; + const handleSelectAll = () => { if (listData?.every((item) => listIdSelected?.includes(item?.school_id))) { setListIdSelected((prev) => @@ -141,6 +151,10 @@ export default function CriteriaManage() { ) { return; } + scrollToTop() + setOffsetOnline(0) + setLoadMoreOnline(true) + setIsEndOnlineClasses(false) setIsFiltered(true); getDataCriteria(true); }; @@ -320,12 +334,14 @@ export default function CriteriaManage() { } addParam('school_name', searchText); - const endPoint = `/report/api_report/getOrganizationAndCriteria${ - queryParams.length ? `?${queryParams.join("&")}` : "" - }&limit=${limitOnline}&offset=${offsetOnlineMore}`; + const endPoint = `/report/api_report/getOrganizationAndCriteria?limit=${limitOnline}&offset=${offsetOnlineMore}${ + queryParams.length ? `&${queryParams.join("&")}` : "" + }`; const res = await apiCaller(endPoint, "GET"); - if (res?.status) { + if (!res){ + setIsEndOnlineClasses(true); + } else { listNext = res?.data; setOffsetOnline(offsetOnline + limitOnline); if (res?.data?.length < limitOnline) { @@ -425,7 +441,7 @@ export default function CriteriaManage() { onClick={handleSelectAll} placement="right" /> -
+
{listData?.map((item, index) => { return (
diff --git a/src/_screens/criteria/criteria-setting/criteriaSetting.style.scss b/src/_screens/criteria/criteria-setting/criteriaSetting.style.scss index 71a5f57..cc5cb9f 100644 --- a/src/_screens/criteria/criteria-setting/criteriaSetting.style.scss +++ b/src/_screens/criteria/criteria-setting/criteriaSetting.style.scss @@ -94,6 +94,7 @@ display: flex; align-items: center; gap: 32px; + width: max-content; .criteria-setting-item-detail-label { display: flex; @@ -120,8 +121,8 @@ border-radius: 4px; padding: 0; margin-right: 1px; - height: 2.8rem; - width: 60px; + height: 2.4rem; + width: 40px; font-size: 1.8rem; text-align: center; color: var(--primary-color); diff --git a/src/_screens/criteria/criteria-setting/index.js b/src/_screens/criteria/criteria-setting/index.js index ba85337..f063b49 100644 --- a/src/_screens/criteria/criteria-setting/index.js +++ b/src/_screens/criteria/criteria-setting/index.js @@ -160,13 +160,33 @@ export default function CriteriaSetting() { return !isRead } - const isSaveDisabled = () => { - return ( - (criteriaTarget.assign.enable && - (!criteriaTarget.assign.target1 || !criteriaTarget.assign.target2)) || - (criteriaTarget.studentDone.enable && - (!criteriaTarget.studentDone.target1 || !criteriaTarget.studentDone.target2)) - ); + const isValid = () => { + if (criteriaTarget.assign.enable) { + if (!criteriaTarget.studentDone.enable) { + return ( + !(criteriaTarget.assign.target1 && + criteriaTarget.assign.target2 && + criteriaTarget.assign.target1 < criteriaTarget.assign.target2) + ); + } else { + return ( + !(criteriaTarget.assign.target1 && + criteriaTarget.assign.target2 && + criteriaTarget.assign.target1 < criteriaTarget.assign.target2 && + criteriaTarget.studentDone.target1 != null && + criteriaTarget.studentDone.target2 != null && + criteriaTarget.studentDone.target1 < criteriaTarget.studentDone.target2) + ); + } + } else if (criteriaTarget.studentDone.enable) { + return ( + !(criteriaTarget.studentDone.target1 != null && + criteriaTarget.studentDone.target2 != null && + criteriaTarget.studentDone.target1 < criteriaTarget.studentDone.target2) + ); + } else { + return true; + } }; const renderRightItem = ({ title, desc, valueName, unit, key, maxLengthInput }) => { return ( @@ -206,8 +226,7 @@ export default function CriteriaSetting() { const value = e.target.value; if (!/^[1-9]\d*$/.test(value) && value !== "") { return; - } - if (!!maxLengthInput && value.length > maxLengthInput) { + }else if (!!maxLengthInput && e.target.value.length > maxLengthInput) { return; } setCriteriaTarget({ @@ -240,8 +259,7 @@ export default function CriteriaSetting() { onChange={(e) => { if (!/^[1-9]\d*$/.test(e.target.value) && e.target.value !== "") { return; - } - if (!!maxLengthInput && e.target.value.length > maxLengthInput) { + }else if (!!maxLengthInput && e.target.value.length > maxLengthInput) { return; } setCriteriaTarget({ @@ -322,7 +340,7 @@ export default function CriteriaSetting() { Quay lại {authentication?.user?.role === USER_ROLE.ADMIN && ( - Lưu + Lưu )}
diff --git a/src/_screens/home/admin/adminHome.style.scss b/src/_screens/home/admin/adminHome.style.scss index 218abf9..5d62491 100644 --- a/src/_screens/home/admin/adminHome.style.scss +++ b/src/_screens/home/admin/adminHome.style.scss @@ -7,7 +7,7 @@ overflow: auto; .admin-home-left-side { - width: 30%; + min-width: 340px; border-right: 1px solid #4d4d4d; .admin-home-form-select { diff --git a/src/_screens/home/admin/index.js b/src/_screens/home/admin/index.js index 61f5449..bf5c74e 100644 --- a/src/_screens/home/admin/index.js +++ b/src/_screens/home/admin/index.js @@ -9,7 +9,7 @@ import PrimaryButton from "../../../_components/Button/PrimaryButton"; import RateStar from "../../../_components/RateStar"; import RootRadioGroup from "../../../_components/RootRadioGroup"; import { LIST_TYPE_FILTER_ADMIN_HOME } from "../../../_constants/common"; -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import InputText from "../../../_components/Auth/InputText"; import { apiCaller, history } from "../../../_helpers"; import { configConstants, PATH } from "../../../_constants"; @@ -42,6 +42,7 @@ export default function AdminHome() { const [limitOnline] = useState(10); const [offsetOnline, setOffsetOnline] = useState(0); const [isEndOnlineClasses, setIsEndOnlineClasses] = useState(false); + const listRef = useRef(null); const dispatch = useDispatch(); const isFilterSchool = typeFilter === LIST_TYPE_FILTER_ADMIN_HOME[0]?.value; @@ -77,6 +78,15 @@ export default function AdminHome() { } }; + const scrollToTop = () => { + if (listRef.current) { + listRef.current.scrollTo({ + top: 0, + behavior: 'smooth', + }); + } + }; + const getDataTeacher = async () => { try { setIsLoading(true); @@ -186,6 +196,10 @@ export default function AdminHome() { const handleSubmit = () => { if (isFilterSchool) { + scrollToTop() + setOffsetOnline(0) + setLoadMoreOnline(true) + setIsEndOnlineClasses(false) setIsSearched(true); getData(); return; @@ -269,12 +283,14 @@ export default function AdminHome() { if(!!searchTextSchool){ queryParams.push(`name_school_find=${searchTextSchool}`) } - const endPoint = `/api_organization/get_organization${ - queryParams.length ? `?${queryParams.join("&")}` : "" - }&limit=${limitOnline}&offset=${offsetOnlineMore}`; + const endPoint = `/api_organization/get_organization?limit=${limitOnline}&offset=${offsetOnlineMore} + ${ + queryParams.length ? `&${queryParams.join("&")}` : "" + }`; const res = await apiCaller(endPoint, "GET"); - - if (res?.status) { + if(!res){ + setIsEndOnlineClasses(true); + } else { concatListSide = res?.data; setOffsetOnline(offsetOnline + limitOnline); if (res?.data?.length < limitOnline) { @@ -364,7 +380,7 @@ export default function AdminHome() { )}
-
+
{listSchool.map((item, index) => { return (
{ + if (listRef.current) { + listRef.current.scrollTo({ + top: 0, + behavior: 'smooth', + }); + } + }; const handleFilter = () => { + setOffsetOnline(0) + setLoadMoreOnline(true) + setIsEndOnlineClasses(false) + setIsFiltered(true); + scrollToTop() getData(); }; @@ -66,9 +84,9 @@ export default function DetailGrade() { item?.assign_number_level || 0, `${item?.student_done_per || 0}%`, item?.student_done_per_level || 0, - schoolName || '', - "", - "", + item?.organization_name || '', + item?.district ||'', + item?.province ||'', !!month?.value ? month.value : getListMonthBySemester(semester.value) @@ -118,6 +136,61 @@ export default function DetailGrade() { getData(); }, []) + + const handleScroll = (e) => { + if ( + e.target.scrollHeight - e.target.scrollTop < e.target.clientHeight + 5 && + isLoadMoreOnline && + !isLoading + ) { + onLoadMoreClasses(); + } + }; + + // Load More Classes for Teacher + const onLoadMoreClasses = async () => { + let offsetOnlineMore = offsetOnline + limitOnline; + let listNext = []; + setIsLoading(true); + try { + if (!isEndOnlineClasses) { + const endPoint = `/report/api_report/getListClassInGradeOrganization?school_id=${ + schoolId + }&grade_id=${ + gradeId + }${ + !!schoolYear?.value ? `&year=${schoolYear?.value}` : "" + }${ + !!semester?.value ? `&semester=${semester?.value}` : "" + }${ + !!month?.value ? `&month=${month?.value}` : "" + }&limit=${limitOnline}&offset=${offsetOnlineMore}`; + const res = await apiCaller(endPoint, "GET"); + console.log('res',res); + if(!res){ + setIsEndOnlineClasses(true); + } else { + listNext = res?.data; + setOffsetOnline(offsetOnline + limitOnline); + if (res?.data?.length < limitOnline) { + setLoadMoreOnline(false); + if (res?.data?.length == 0) setLoadMoreOnline(false); + setIsEndOnlineClasses(true); + } + } + } else { + setIsEndOnlineClasses(true); + } + + let listPrev = listClass; + setListClass(listPrev?.concat(listNext)); + } catch (e) { + } finally { + setIsLoading(false); + } + }; + + return (
- {/*
- {}}>{'<'} - {}}>{'>'} -
*/}
{!!listClass?.length && Xuất excel}
-
+
{!isLoading && !listClass?.length && (

Không có lớp nào @@ -208,6 +277,10 @@ export default function DetailGrade() { ); })}

+ {/*
+ {}}>{'<'} + {}}>{'>'} +
*/}
diff --git a/src/_screens/home/headmaster/index.js b/src/_screens/home/headmaster/index.js index 058f321..5188c80 100644 --- a/src/_screens/home/headmaster/index.js +++ b/src/_screens/home/headmaster/index.js @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import PrimaryButton from "../../../_components/Button/PrimaryButton"; import Header from "../../../_components/Header"; import RateStar from "../../../_components/RateStar"; @@ -42,13 +42,32 @@ export default function HeadmasterHome() { const [listTeacher, setListTeacher] = useState([]); const [isLoading, setIsLoading] = useState(false); const [criteriaSchool, setCriteriaSchool] = useState(); + const [isLoadMoreOnline, setLoadMoreOnline] = useState(true); + const [limitOnline] = useState(10); + const [offsetOnline, setOffsetOnline] = useState(0); + const [isEndOnlineClasses, setIsEndOnlineClasses] = useState(false); + const listRef = useRef(null); const schoolName = !!schoolId ? !!school_name ? decodeURIComponent(school_name) : '' - : `Hiệu trưởng ${authentication?.user?.organization_name}`; + : `${authentication?.user?.organization_name}`; const id = !!schoolId ? schoolId : authentication?.user?.organization_id; + const scrollToTop = () => { + if (listRef.current) { + listRef.current.scrollTo({ + top: 0, + behavior: 'smooth', + }); + } + }; + const changeSemester = (item) => { + setOffsetOnline(0) + setLoadMoreOnline(true) + setIsEndOnlineClasses(false) + setIsFiltered(true); + scrollToTop() setSemester(item); setMonth(getListMonthBySemester(item?.value)?.[0]); }; @@ -73,12 +92,9 @@ export default function HeadmasterHome() { item?.criteria_teacher?.assign_number_level || 0, item?.criteria_teacher?.student_done_per_level || 0, item?.criteria_teacher?.criteria_level || 0, - //trường - "", - // Huyện - "", - // Tỉnh - "", + item?.organization_name || '', + item?.district ||'', + item?.province ||'', !!month?.value ? month.value : getListMonthBySemester(semester.value) @@ -148,6 +164,50 @@ export default function HeadmasterHome() { } } + const handleScroll = (e) => { + if ( + e.target.scrollHeight - e.target.scrollTop < e.target.clientHeight + 5 && + isLoadMoreOnline && + !isLoading + ) { + onLoadMoreClasses(); + } + }; + + // Load More Classes for Teacher + const onLoadMoreClasses = async () => { + let offsetOnlineMore = offsetOnline + limitOnline; + let listNext = []; + setIsLoading(true); + try { + if (!isEndOnlineClasses) { + const endPoint = `/report/api_report/teacherByOrganizationId?organization_id=${id}&limit=${limitOnline}&offset=${offsetOnlineMore}`; + const res = await apiCaller(endPoint, "GET"); + + if (!res){ + setIsEndOnlineClasses(true); + } else { + listNext = res?.data; + setOffsetOnline(offsetOnline + limitOnline); + if (res?.data?.length < limitOnline) { + setLoadMoreOnline(false); + if (res?.data?.length == 0) setLoadMoreOnline(false); + setIsEndOnlineClasses(true); + } + } + } else { + setIsEndOnlineClasses(true); + } + + let listPrev = listTeacher; + setListTeacher(listPrev?.concat(listNext)); + } catch (e) { + } finally { + setIsLoading(false); + } + }; + + const getDataCriteriaSchool = async () => { try { setIsLoading(true); @@ -292,7 +352,7 @@ export default function HeadmasterHome() {
) : ( -
+
{!isLoading && !listTeacher?.length && (

Không có giáo viên nào diff --git a/src/_screens/home/teacher/index.js b/src/_screens/home/teacher/index.js index a3ffe54..1306247 100644 --- a/src/_screens/home/teacher/index.js +++ b/src/_screens/home/teacher/index.js @@ -15,7 +15,7 @@ import { listAlphabet, PRIMARY_COLOR, } from "../../../_constants/common"; -import { useEffect, useState } from "react"; +import { useEffect, useState,useRef } from "react"; import { apiCaller, history } from "../../../_helpers"; import { configConstants } from "../../../_constants"; import { exportExcel } from "../../../_helpers/utils"; @@ -39,12 +39,23 @@ export default function TeacherHome() { const [limitOnline] = useState(10); const [offsetOnline, setOffsetOnline] = useState(0); const [isEndOnlineClasses, setIsEndOnlineClasses] = useState(false); + const [totalClass, setTotalClass] = useState(0) + const [totalAssign, settotalAssign] = useState(0) + const listRef = useRef(null) const teacherName = !!teacherId ? !!teacher_name ? decodeURIComponent(teacher_name) : '' : authentication?.user?.fullname; const id = !!teacherId ? teacherId : authentication?.user?.id; + const scrollToTop = () => { + if (listRef.current) { + listRef.current.scrollTo({ + top: 0, + behavior: 'smooth', + }); + } + }; const getData = async () => { try { setIsLoading(true); @@ -60,6 +71,8 @@ export default function TeacherHome() { const res = await apiCaller(endPoint, "GET"); if (res?.status) { + setTotalClass(res?.total_class); + settotalAssign(res?.total_assign); setCriteria(res?.criteria_teacher); setListClass(res?.data); } @@ -84,6 +97,11 @@ export default function TeacherHome() { }; const handleFilter = () => { + scrollToTop() + setOffsetOnline(0) + setLoadMoreOnline(true) + setIsEndOnlineClasses(false) + setListClass([]) getData(); }; @@ -96,9 +114,9 @@ export default function TeacherHome() { "Tiêu chí giao bài", "Tỷ lệ học sinh làm bài", "Tiêu chí tỷ lệ học sinh làm bài", - // "Trường", - // "Huyện", - // "Tỉnh", + "Trường", + "Huyện", + "Tỉnh", "Tháng", "học kỳ", "Niên khóa", @@ -111,9 +129,9 @@ export default function TeacherHome() { item?.assign_number_level || 0, `${item?.student_done_per || 0}%`, item?.student_done_per_level || 0, - // "Trường", - // "Huyện", - // "Tỉnh", + item?.organization_name || '', + item?.organization_district ||'', + item?.organization_province ||'', !!month?.value ? month.value : getListMonthBySemester(semester.value) @@ -156,7 +174,6 @@ export default function TeacherHome() { try { if (!isEndOnlineClasses) { let queryParams = [] - if(!!semester?.value){ queryParams.push(`&semester=${semester?.value}`) } @@ -164,10 +181,12 @@ export default function TeacherHome() { queryParams.push(`month=${month?.value}`) } const endPoint = - `/api_exercise_report/teacher_report_summary?teacher_id=${id}&year=${schoolYear?.value}${queryParams.length ? `${queryParams.join("&")}` : ""} - &limit=${limitOnline}&offset=${offsetOnlineMore}`; + `/api_exercise_report/teacher_report_summary?teacher_id=${id}&year=${schoolYear?.value.trim()}&limit=${limitOnline}&offset=${offsetOnlineMore}` + + (queryParams.length > 0 ? `&${queryParams.join("&")}` : ""); const res = await apiCaller(endPoint, "GET"); - if (res?.status) { + if (!res){ + setIsEndOnlineClasses(true); + } else { concatListSide = res?.data; setOffsetOnline(offsetOnline + limitOnline); if (res?.data?.length < limitOnline) { @@ -224,13 +243,13 @@ export default function TeacherHome() {

{"Tổng số lớp: "} - {listClass?.length} + {totalClass}
{"Tổng số lần giao: "} - {countAss(listClass)} + {totalAssign}
@@ -264,7 +283,7 @@ export default function TeacherHome() { Xuất excel )}
-
+
{listClass?.map((item) => { return (
diff --git a/src/_screens/login/index.js b/src/_screens/login/index.js index d1ba479..6b01fcc 100644 --- a/src/_screens/login/index.js +++ b/src/_screens/login/index.js @@ -75,12 +75,25 @@ export default function Login() { dataSubmit, ); if (res?.status) { + if(res.data_user.role === "student"||res.data_user.role === "parent"){ + dispatch({ + type: TYPE_DISPATCH.RESET_AUTHENTICATION, + }); + dispatch( + alertActions.error({ + message: 'Bạn không có quyền truy cập', + }), + ); + return false + // persistor.purge(); + // window.location.href = PATH.login; + } handleLoginSuccess(res); } } catch (err) { dispatch( alertActions.error({ - message: err?.toString(), + message: err.toString() }), ); }