From 52d62dbc961094cb5c4b9cb568f959651b5de032 Mon Sep 17 00:00:00 2001 From: PhuocNTB Date: Mon, 6 Jul 2026 09:58:31 +0700 Subject: [PATCH] fix view --- .../src/components/WorkspaceSeatingChart.tsx | 342 ++++++++++++------ 1 file changed, 237 insertions(+), 105 deletions(-) diff --git a/management/src/components/WorkspaceSeatingChart.tsx b/management/src/components/WorkspaceSeatingChart.tsx index c313cec..bac4888 100644 --- a/management/src/components/WorkspaceSeatingChart.tsx +++ b/management/src/components/WorkspaceSeatingChart.tsx @@ -44,6 +44,32 @@ export const WorkspaceSeatingChart: React.FC = ({ const [dragOverCell, setDragOverCell] = useState(null); const [saveNotice, setSaveNotice] = useState(null); + // Toggle layout view modes + const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid'); + const [listSearchQuery, setListSearchQuery] = useState(''); + + // Reverse map seat positions for list view + const studentSeats = useMemo(() => { + if (!layout) return {} as Record; + const mapping: Record = {}; + Object.entries(layout.seats).forEach(([cellKey, rkId]) => { + const [rStr, cStr] = cellKey.split(','); + const r = Number(rStr) + 1; + const c = Number(cStr) + 1; + mapping[rkId] = `Hàng ${r}, Cột ${c}`; + }); + return mapping; + }, [layout]); + + // Filter student list + const filteredListStudents = useMemo(() => { + return students.filter( + (s) => + s.fullName.toLowerCase().includes(listSearchQuery.toLowerCase()) || + s.studentCode.toLowerCase().includes(listSearchQuery.toLowerCase()) + ); + }, [students, listSearchQuery]); + // Load templates and layout useEffect(() => { // Load templates @@ -531,127 +557,233 @@ export const WorkspaceSeatingChart: React.FC = ({ ) : ( // Seating Workspace View -
- +
{/* Main Seating Panel */} -
+
{/* Toolbar */}
-
- - +
+
+ + +
+ + {viewMode === 'grid' && ( + <> + + + + )}
-
- - -
+ {viewMode === 'grid' && ( +
+ + +
+ )}
- {isEditingStructure && ( -
- 💡 Đang ở chế độ chỉnh sửa: Click chuột vào các ô trong sơ đồ để thay đổi khóa/mở các vị trí. + {viewMode === 'grid' ? ( + <> + {isEditingStructure && ( +
+ 💡 Đang ở chế độ chỉnh sửa: Click chuột vào các ô trong sơ đồ để thay đổi khóa/mở các vị trí. +
+ )} + {renderSeatingGrid()} + + ) : ( + // List View of Students +
+
+ setListSearchQuery(e.target.value)} + /> +
+
+ {filteredListStudents.length === 0 ? ( +
+ Không tìm thấy sinh viên nào. +
+ ) : ( + + + + + + + + + + + + {filteredListStudents.map((s) => { + const isOnline = onlineIds.includes(s.rkId); + const seatLabel = studentSeats[s.rkId] || 'Chưa xếp chỗ'; + return ( + + + + + + + + ); + })} + +
Sinh viênMã SVVị trí chỗ ngồiTrạng tháiThao tác
+
+ +
{s.fullName}
+
+
{s.studentCode} + + {seatLabel} + + + {isOnline ? 'Online' : 'Offline'} + + +
+ )} +
)} - - {/* Render Grid */} - {renderSeatingGrid()}
{/* Right Panel: Unseated Students list */} -
-
-

- Chưa vào chỗ - - {unseatedStudents.length} SV - -

-

- Kéo thả sinh viên bên dưới vào vị trí trống trên sơ đồ. -

-
+ {viewMode === 'grid' && ( +
+
+

+ Chưa vào chỗ + + {unseatedStudents.length} SV + +

+

+ Kéo thả sinh viên bên dưới vào vị trí trống trên sơ đồ. +

+
- setSearchQuery(e.target.value)} - /> + setSearchQuery(e.target.value)} + /> -
- {filteredUnseatedStudents.length === 0 ? ( -
- Không tìm thấy sinh viên nào. -
- ) : ( - filteredUnseatedStudents.map((s) => { - const isOnline = onlineIds.includes(s.rkId); - return ( -
handleDragStart(e, `unseated:${s.rkId}`)} - onClick={() => onStudentClick && onStudentClick(s.rkId)} - style={{ - display: 'flex', - alignItems: 'center', - gap: '0.5rem', - padding: '0.5rem', - border: '1px solid var(--border-color)', - borderRadius: '8px', - backgroundColor: '#ffffff', - cursor: onStudentClick ? 'pointer' : 'grab', - transition: 'var(--transition)', - userSelect: 'none', - boxShadow: 'var(--shadow-sm)', - }} - className="student-drag-item" - > - -
- - {s.fullName} - - - {s.studentCode} - +
+ {filteredUnseatedStudents.length === 0 ? ( +
+ Không tìm thấy sinh viên nào. +
+ ) : ( + filteredUnseatedStudents.map((s) => { + const isOnline = onlineIds.includes(s.rkId); + return ( +
handleDragStart(e, `unseated:${s.rkId}`)} + onClick={() => onStudentClick && onStudentClick(s.rkId)} + style={{ + display: 'flex', + alignItems: 'center', + gap: '0.5rem', + padding: '0.5rem', + border: '1px solid var(--border-color)', + borderRadius: '8px', + backgroundColor: '#ffffff', + cursor: onStudentClick ? 'pointer' : 'grab', + transition: 'var(--transition)', + userSelect: 'none', + boxShadow: 'var(--shadow-sm)', + }} + className="student-drag-item" + > + +
+ + {s.fullName} + + + {s.studentCode} + +
+
- -
- ); - }) - )} + ); + }) + )} +
-
+ )}
)}