diff --git a/src/components/BoardManager.tsx b/src/components/BoardManager.tsx index 7f7f4cc..e802e00 100644 --- a/src/components/BoardManager.tsx +++ b/src/components/BoardManager.tsx @@ -83,6 +83,11 @@ interface DragState { containerSize: number } +const getFirstLeafId = (node: LayoutNode): string => { + if (node.type === "leaf") return node.id + return getFirstLeafId(node.first) +} + const makeId = () => typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() @@ -345,6 +350,9 @@ export const BoardManager: React.FC = ({ canManage }) => { const [errorMap, setErrorMap] = useState>({}) const [dragState, setDragState] = useState(null) const [editingListId, setEditingListId] = useState(null) + const [selectedLeafNodeId, setSelectedLeafNodeId] = useState(null) + const [renameVisible, setRenameVisible] = useState(false) + const [renameValue, setRenameValue] = useState("") const panelRefs = useRef>({}) @@ -511,6 +519,15 @@ ORDER BY reward_points DESC, score DESC`, if (!activeBoardId && boards.length > 0) setActiveBoardId(boards[0].id) }, [activeBoardId, boards]) + useEffect(() => { + if (!activeBoard) { + setSelectedLeafNodeId(null) + return + } + const firstLeafId = getFirstLeafId(activeBoard.layout) + setSelectedLeafNodeId((prev) => prev || firstLeafId) + }, [activeBoard?.id, activeBoard?.layout]) + useEffect(() => { if (!activeBoard) return runAllInBoard(activeBoard).catch(() => void 0) @@ -567,6 +584,18 @@ ORDER BY reward_points DESC, score DESC`, ) } + const openRenameModal = () => { + if (!activeBoard) return + setRenameValue(activeBoard.name) + setRenameVisible(true) + } + + const submitRenameBoard = () => { + if (!activeBoard) return + updateBoardName(activeBoard.id, renameValue.trim() || t("board.untitledBoard")) + setRenameVisible(false) + } + const addBoard = () => { if (!canManage) return const newBoard = createDefaultBoard() @@ -628,6 +657,11 @@ ORDER BY reward_points DESC, score DESC`, ) } + const splitSelectedLeaf = (direction: SplitDirection) => { + if (!activeBoard || !selectedLeafNodeId) return + addListBySplit(activeBoard.id, selectedLeafNodeId, direction) + } + const removeList = (boardId: string, listId: string) => { if (!canManage) return @@ -874,10 +908,18 @@ ORDER BY reward_points DESC, score DESC`, const renderLeafPanel = (board: BoardConfig, leaf: LayoutLeafNode): React.JSX.Element => { const list = board.lists.find((item) => item.id === leaf.listId) if (!list) return + const isSelected = selectedLeafNodeId === leaf.id return ( setSelectedLeafNodeId(leaf.id)} + style={{ + height: "100%", + backgroundColor: "var(--ss-card-bg)", + border: isSelected ? "1px solid var(--ant-color-primary, #1677ff)" : "1px solid var(--ss-border-color)", + boxShadow: isSelected ? "0 8px 18px rgba(22, 119, 255, 0.14)" : undefined, + cursor: "pointer", + }} styles={{ body: { height: "100%", display: "flex", flexDirection: "column", padding: 12 } }} title={{list.name}} extra={ @@ -888,12 +930,6 @@ ORDER BY reward_points DESC, score DESC`, - - removeList(board.id, list.id)} @@ -996,6 +1032,23 @@ ORDER BY reward_points DESC, score DESC`, {canManage ? t("board.editable") : t("board.readonly")} + + + @@ -1016,34 +1069,17 @@ ORDER BY reward_points DESC, score DESC`, {activeBoard ? ( - - - removeBoard(activeBoard.id)} disabled={!canManage}> - - - - } - style={{ backgroundColor: "var(--ss-card-bg)" }} - > - updateBoardName(activeBoard.id, e.target.value.trim())} - placeholder={t("board.boardNamePlaceholder")} - disabled={!canManage} - /> - {saving && ( - - {t("board.saving")} - - )} - + + + removeBoard(activeBoard.id)} disabled={!canManage}> + + + {saving && {t("board.saving")}} + {renderBoardWorkspace()} @@ -1054,6 +1090,17 @@ ORDER BY reward_points DESC, score DESC`, )} + setRenameVisible(false)} + onOk={submitRenameBoard} + okText={t("common.confirm")} + cancelText={t("common.cancel")} + > + setRenameValue(e.target.value)} placeholder={t("board.boardNamePlaceholder")} /> + +