This commit is contained in:
@@ -36,6 +36,16 @@ export const AttendancePanel: React.FC<AttendancePanelProps> = ({ classId }) =>
|
|||||||
const [pushing, setPushing] = useState(false);
|
const [pushing, setPushing] = useState(false);
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
const [selectedStudentRkIds, setSelectedStudentRkIds] = useState<number[]>([]);
|
const [selectedStudentRkIds, setSelectedStudentRkIds] = useState<number[]>([]);
|
||||||
|
const [isCollapsed, setIsCollapsed] = useState(false);
|
||||||
|
|
||||||
|
const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
|
||||||
|
const scrollTop = e.currentTarget.scrollTop;
|
||||||
|
if (scrollTop > 20) {
|
||||||
|
setIsCollapsed(true);
|
||||||
|
} else if (scrollTop <= 5) {
|
||||||
|
setIsCollapsed(false);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
const loadShifts = useCallback(async () => {
|
const loadShifts = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -210,6 +220,14 @@ export const AttendancePanel: React.FC<AttendancePanelProps> = ({ classId }) =>
|
|||||||
onChange={e => setSearchQuery(e.target.value)}
|
onChange={e => setSearchQuery(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-secondary"
|
||||||
|
onClick={() => setIsCollapsed(!isCollapsed)}
|
||||||
|
title={isCollapsed ? 'Hiện đầy đủ thông tin chi tiết' : 'Ẩn bớt thông tin chi tiết để xem bảng to hơn'}
|
||||||
|
>
|
||||||
|
{isCollapsed ? '📂 Chi tiết' : '📁 Thu gọn'}
|
||||||
|
</button>
|
||||||
<button type="button" className="btn btn-secondary" onClick={() => loadAttendance(false)} disabled={loading}>
|
<button type="button" className="btn btn-secondary" onClick={() => loadAttendance(false)} disabled={loading}>
|
||||||
Tải lại
|
Tải lại
|
||||||
</button>
|
</button>
|
||||||
@@ -218,6 +236,8 @@ export const AttendancePanel: React.FC<AttendancePanelProps> = ({ classId }) =>
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{!isCollapsed && (
|
||||||
|
<>
|
||||||
<div
|
<div
|
||||||
className={`attendance-qldt-banner${
|
className={`attendance-qldt-banner${
|
||||||
qldtSynced ? (qldtDirty ? ' attendance-qldt-banner--stale' : ' attendance-qldt-banner--synced') : ''
|
qldtSynced ? (qldtDirty ? ' attendance-qldt-banner--stale' : ' attendance-qldt-banner--synced') : ''
|
||||||
@@ -279,6 +299,8 @@ export const AttendancePanel: React.FC<AttendancePanelProps> = ({ classId }) =>
|
|||||||
<div style={{ padding: '0.65rem 0.85rem', background: '#fef3c7', border: '1px solid #fcd34d', borderRadius: '4px', color: '#92400e', fontSize: '0.82rem', display: 'flex', alignItems: 'center', gap: '0.35rem', margin: '4px 0 10px 0', lineHeight: '1.4' }}>
|
<div style={{ padding: '0.65rem 0.85rem', background: '#fef3c7', border: '1px solid #fcd34d', borderRadius: '4px', color: '#92400e', fontSize: '0.82rem', display: 'flex', alignItems: 'center', gap: '0.35rem', margin: '4px 0 10px 0', lineHeight: '1.4' }}>
|
||||||
💡 <strong>Lưu ý:</strong> Hệ thống hiện tại chỉ ghi nhận điểm danh học tập nội bộ và <strong>KHÔNG tự động lưu lên QLĐT</strong>. Thầy cô vui lòng kiểm tra kỹ trạng thái của sinh viên, sau đó bấm nút <strong>Đẩy QLĐT</strong> ở góc phải bên trên để đồng bộ điểm danh chính thức.
|
💡 <strong>Lưu ý:</strong> Hệ thống hiện tại chỉ ghi nhận điểm danh học tập nội bộ và <strong>KHÔNG tự động lưu lên QLĐT</strong>. Thầy cô vui lòng kiểm tra kỹ trạng thái của sinh viên, sau đó bấm nút <strong>Đẩy QLĐT</strong> ở góc phải bên trên để đồng bộ điểm danh chính thức.
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{selectedStudentRkIds.length > 0 && (
|
{selectedStudentRkIds.length > 0 && (
|
||||||
<div className="attendance-bulk-actions">
|
<div className="attendance-bulk-actions">
|
||||||
@@ -309,7 +331,7 @@ export const AttendancePanel: React.FC<AttendancePanelProps> = ({ classId }) =>
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="attendance-table-scroll table-wrapper">
|
<div className="attendance-table-scroll table-wrapper" onScroll={handleScroll}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="empty-state"><div className="sync-spinner" style={{ width: 28, height: 28 }} /></div>
|
<div className="empty-state"><div className="sync-spinner" style={{ width: 28, height: 28 }} /></div>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
Reference in New Issue
Block a user