diff --git a/src/assets/main.css b/src/assets/main.css index 238b7b3..affddc1 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -210,3 +210,17 @@ html.platform-macos #root { border-radius: 12px; overflow: hidden; } + +.ss-group-board-modal .ant-modal { + max-height: calc(100vh - 24px); +} + +.ss-group-board-modal .ant-modal-content { + max-height: calc(100vh - 24px); + display: flex; + flex-direction: column; +} + +.ss-group-board-modal .ant-modal-body { + overflow-y: auto; +} diff --git a/src/components/StudentManager.tsx b/src/components/StudentManager.tsx index 444719e..e87f63f 100644 --- a/src/components/StudentManager.tsx +++ b/src/components/StudentManager.tsx @@ -14,7 +14,7 @@ import { Select, } from "antd" import type { ColumnsType } from "antd/es/table" -import { UploadOutlined, MoreOutlined } from "@ant-design/icons" +import { UploadOutlined, MoreOutlined, PlusOutlined } from "@ant-design/icons" import { useTranslation } from "react-i18next" import { TagEditorDialog } from "./TagEditorDialog" import { getAvatarFromExtraJson, setAvatarInExtraJson } from "../utils/studentAvatar" @@ -104,6 +104,7 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { const [groupBoardSaving, setGroupBoardSaving] = useState(false) const [groupBoard, setGroupBoard] = useState>({}) const [groupBoardOrder, setGroupBoardOrder] = useState([]) + const [groupBoardNewGroupName, setGroupBoardNewGroupName] = useState("") const [pointerDraggingStudentId, setPointerDraggingStudentId] = useState(null) const [pointerTargetGroup, setPointerTargetGroup] = useState(null) const [pointerDragStudentName, setPointerDragStudentName] = useState("") @@ -378,9 +379,33 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { }) setGroupBoardOrder(order) setGroupBoard(board) + setGroupBoardNewGroupName("") setGroupBoardVisible(true) } + const handleCreateGroupInBoard = () => { + const name = groupBoardNewGroupName.trim() + if (!name) { + messageApi.warning(t("students.groupBoardGroupNameRequired")) + return + } + if (name === UNGROUPED_KEY) { + messageApi.warning(t("students.groupBoardGroupNameInvalid")) + return + } + if (groupBoardOrder.includes(name)) { + messageApi.warning(t("students.groupBoardGroupExists")) + return + } + + setGroupBoard((prev) => ({ ...prev, [name]: [] })) + setGroupBoardOrder((prev) => { + const withoutUngrouped = prev.filter((key) => key !== UNGROUPED_KEY) + return [...withoutUngrouped, name, UNGROUPED_KEY] + }) + setGroupBoardNewGroupName("") + } + const moveStudentToGroup = (studentId: number, targetGroup: string) => { setGroupBoard((prev) => { let movingStudent: student | null = null @@ -1356,6 +1381,7 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { open={groupBoardVisible} onCancel={() => { setGroupBoardVisible(false) + setGroupBoardNewGroupName("") draggingStudentIdRef.current = null pointerDragSourceGroupRef.current = null pointerDragTargetGroupRef.current = null @@ -1369,11 +1395,25 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { cancelText={t("common.cancel")} okButtonProps={{ loading: groupBoardSaving }} width="90%" + wrapClassName="ss-group-board-modal" + styles={{ body: { maxHeight: "calc(100vh - 220px)", overflowY: "auto" } }} destroyOnHidden >
{t("students.groupBoardHint")}
+ + setGroupBoardNewGroupName(e.target.value)} + onPressEnter={handleCreateGroupInBoard} + placeholder={t("students.groupBoardNewGroupPlaceholder")} + maxLength={32} + /> + +