From 0fa4a9aae262efd8fe7bac75d5b328d3b85217d4 Mon Sep 17 00:00:00 2001 From: PhuocNTB Date: Fri, 3 Jul 2026 06:50:04 +0700 Subject: [PATCH] optimize diem danh --- management/src/components/AttendancePanel.tsx | 59 +++++++++++++++---- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/management/src/components/AttendancePanel.tsx b/management/src/components/AttendancePanel.tsx index d065ca3..6cb085a 100644 --- a/management/src/components/AttendancePanel.tsx +++ b/management/src/components/AttendancePanel.tsx @@ -49,17 +49,18 @@ export const AttendancePanel: React.FC = ({ classId }) => } }, [classId, date, period]); - const loadAttendance = useCallback(async () => { + const loadAttendance = useCallback(async (isBackground: boolean | any = false) => { + const isBg = isBackground === true; try { - setLoading(true); + if (!isBg) setLoading(true); const res = await apiFetchAttendance(classId, date, period); setRows(res.data || []); setShiftInfo(res.shift || null); - setSelectedStudentRkIds([]); // Clear selection when data changes + if (!isBg) setSelectedStudentRkIds([]); // Clear selection when data changes } catch (e: any) { alert(e.message || 'Không tải được điểm danh'); } finally { - setLoading(false); + if (!isBg) setLoading(false); } }, [classId, date, period]); @@ -93,30 +94,64 @@ export const AttendancePanel: React.FC = ({ classId }) => }, []); const handleStatusChange = async (studentRkId: number, status: number) => { + // Optimistic state update so the UI reacts instantly + setRows(prevRows => + prevRows.map(row => { + if (row.studentRkId === studentRkId) { + const matchedOpt = ATTENDANCE_STATUS_OPTIONS.find(o => o.value === status); + return { + ...row, + status, + statusLabel: matchedOpt ? matchedOpt.label : row.statusLabel, + statusEditedByTeacher: true, + }; + } + return row; + }) + ); + try { await apiUpdateAttendanceStatus(classId, { date, period, studentRkId, status }); - await loadAttendance(); + await loadAttendance(true); } catch (e: any) { alert(e.message || 'Cập nhật trạng thái thất bại'); + await loadAttendance(); // Rollback on failure } }; const handleBulkStatusChange = async (status: number) => { if (selectedStudentRkIds.length === 0) return; + + // Optimistic state update for selected students + setRows(prevRows => + prevRows.map(row => { + if (selectedStudentRkIds.includes(row.studentRkId)) { + const matchedOpt = ATTENDANCE_STATUS_OPTIONS.find(o => o.value === status); + return { + ...row, + status, + statusLabel: matchedOpt ? matchedOpt.label : row.statusLabel, + statusEditedByTeacher: true, + }; + } + return row; + }) + ); + + const idsToUpdate = [...selectedStudentRkIds]; + setSelectedStudentRkIds([]); + try { - setLoading(true); await apiUpdateAttendanceBulkStatus(classId, { date, period, - studentRkIds: selectedStudentRkIds, + studentRkIds: idsToUpdate, status, }); - setSelectedStudentRkIds([]); - await loadAttendance(); + await loadAttendance(true); } catch (e: any) { alert(e.message || 'Cập nhật hàng loạt thất bại'); - } finally { - setLoading(false); + await loadAttendance(); // Rollback } }; @@ -175,7 +210,7 @@ export const AttendancePanel: React.FC = ({ classId }) => onChange={e => setSearchQuery(e.target.value)} /> -