From 2bb856f2fd71fda503665e173c79ac3c5c0bfdd9 Mon Sep 17 00:00:00 2001 From: PhuocNTB Date: Tue, 7 Jul 2026 06:52:33 +0700 Subject: [PATCH] fix ui --- management/src/components/StudentAvatar.tsx | 46 ++- .../src/components/StudentDetailModal.tsx | 6 +- .../src/components/WorkspaceSeatingChart.tsx | 119 ++------ management/src/index.css | 266 ++++++++++++++++++ 4 files changed, 325 insertions(+), 112 deletions(-) diff --git a/management/src/components/StudentAvatar.tsx b/management/src/components/StudentAvatar.tsx index 92e6f91..e89a2a4 100644 --- a/management/src/components/StudentAvatar.tsx +++ b/management/src/components/StudentAvatar.tsx @@ -12,13 +12,25 @@ interface StudentAvatarProps { avatar?: string | null; isOnline?: boolean; size?: number; + showStatusBadge?: boolean; } +export const StudentOnlineBadge: React.FC<{ + isOnline: boolean; + size?: 'sm' | 'md'; +}> = ({ isOnline, size = 'sm' }) => ( + + + {isOnline ? 'Online' : 'Offline'} + +); + export const StudentAvatar: React.FC = ({ fullName, avatar, isOnline = false, size = 48, + showStatusBadge = true, }) => { const [imgFailed, setImgFailed] = useState(false); const avatarUrl = normalizeAvatarUrl(avatar); @@ -30,20 +42,28 @@ export const StudentAvatar: React.FC = ({ }, [avatarUrl]); return ( -
- {showImage ? ( - {fullName} setImgFailed(true)} +
+
+ {showImage ? ( + {fullName} setImgFailed(true)} + /> + ) : ( + initial + )} +
+ {showStatusBadge && ( + - ) : ( - initial )}
); diff --git a/management/src/components/StudentDetailModal.tsx b/management/src/components/StudentDetailModal.tsx index 6646171..5f92f96 100644 --- a/management/src/components/StudentDetailModal.tsx +++ b/management/src/components/StudentDetailModal.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import type { StudentItem, StudentSessionLogItem } from '../api'; -import { StudentAvatar } from './StudentAvatar'; +import { StudentAvatar, StudentOnlineBadge } from './StudentAvatar'; import { ProctorStreamPanels } from './ProctorStreamPanels'; interface StudentDetailModalProps { @@ -48,8 +48,8 @@ export const StudentDetailModal: React.FC = ({
Trạng thái - - {isOnline ? '● Online' : '○ Offline'} + +
{student.phone && ( diff --git a/management/src/components/WorkspaceSeatingChart.tsx b/management/src/components/WorkspaceSeatingChart.tsx index e3cd364..282a35d 100644 --- a/management/src/components/WorkspaceSeatingChart.tsx +++ b/management/src/components/WorkspaceSeatingChart.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState, useMemo } from 'react'; import type { SeatingTemplate } from './SeatingTemplatesSection'; -import { StudentAvatar } from './StudentAvatar'; +import { StudentAvatar, StudentOnlineBadge } from './StudentAvatar'; interface WorkspaceSeatingChartProps { workspaceId: string; // 'class-' or 'exam-' @@ -330,30 +330,8 @@ export const WorkspaceSeatingChart: React.FC = ({ onDragLeave={handleDragLeave} onDrop={(e) => !isLocked && handleDrop(e, r, c)} onClick={() => isEditingStructure && handleToggleCellLock(r, c)} - className={`seating-grid-cell ${isLocked ? 'locked' : ''} ${isHovered ? 'dragover' : ''}`} - style={{ - minHeight: '80px', - border: isEditingStructure ? '1.5px dashed var(--border-color)' : '1px solid var(--border-color)', - borderRadius: '8px', - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - padding: '0.4rem', - position: 'relative', - backgroundColor: isLocked - ? '#e5e7eb' - : isHovered - ? '#dbeafe' - : student - ? '#ffffff' - : '#f9fafb', - color: isLocked ? '#9ca3af' : 'inherit', - cursor: isEditingStructure ? 'pointer' : student ? 'grab' : 'default', - boxShadow: student ? 'var(--shadow-sm)' : 'none', - transition: 'var(--transition)', - borderColor: isHovered ? 'var(--accent)' : isLocked ? '#e5e7eb' : 'var(--border-color)', - }} + className={`seating-grid-cell ${isLocked ? 'locked' : ''} ${isHovered ? 'dragover' : ''} ${student && !isLocked ? (isOnline ? 'occupied-online' : 'occupied-offline') : ''}`} + style={isEditingStructure ? { border: '1.5px dashed var(--border-color)', cursor: 'pointer' } : undefined} draggable={!!student && !isEditingStructure} onDragStart={(e) => student && handleDragStart(e, `cell:${key}`)} > @@ -363,8 +341,8 @@ export const WorkspaceSeatingChart: React.FC = ({ Khóa
) : student ? ( -
{ if (!isEditingStructure && onStudentClick) { onStudentClick(student.rkId); @@ -373,63 +351,34 @@ export const WorkspaceSeatingChart: React.FC = ({ > {!isEditingStructure && ( )} - - + + {student.fullName.split(' ').pop()} - + {student.studentCode} + {!isEditingStructure && } {student.paperTitle && ( - + 📄 {student.paperTitle} )}
) : ( -
- +
+ H{r + 1}-C{c + 1} - Trống + Trống
)}
@@ -458,18 +407,9 @@ export const WorkspaceSeatingChart: React.FC = ({ {/* Grid Container */}
{gridItems} @@ -709,8 +649,8 @@ export const WorkspaceSeatingChart: React.FC = ({ {seatLabel} - - {isOnline ? 'Online' : 'Offline'} + +