diff --git a/src/components/tile/TilesOverlay.js b/src/components/tile/TilesOverlay.js index e280013..40215bf 100644 --- a/src/components/tile/TilesOverlay.js +++ b/src/components/tile/TilesOverlay.js @@ -1,5 +1,5 @@ import React, { useState } from "react"; -import { Box, Close, Grid, useThemeUI } from "theme-ui"; +import { Box, Close, Grid, useThemeUI, IconButton, Text, Flex } from "theme-ui"; import { useSpring, animated, config } from "react-spring"; import ReactResizeDetector from "react-resize-detector"; import SimpleBar from "simplebar-react"; @@ -10,8 +10,20 @@ import TilesUngroupDroppable from "./TilesUngroupDroppable"; import useResponsiveLayout from "../../hooks/useResponsiveLayout"; +import ChangeNicknameIcon from "../../icons/ChangeNicknameIcon"; + +import GroupNameModal from "../../modals/GroupNameModal"; + +import { renameGroup } from "../../helpers/group"; + function TilesOverlay({ children }) { - const { openGroupId, onGroupClose, onGroupSelect } = useGroup(); + const { + groups, + openGroupId, + onGroupClose, + onGroupSelect, + onGroupsChange, + } = useGroup(); const { theme } = useThemeUI(); @@ -34,6 +46,14 @@ function TilesOverlay({ children }) { setOverlaySize({ width, height }); } + const [isGroupNameModalOpen, setIsGroupNameModalOpen] = useState(false); + function handleGroupNameChange(name) { + onGroupsChange(renameGroup(groups, openGroupId, name)); + setIsGroupNameModalOpen(false); + } + + const group = groups.find((group) => group.id === openGroupId); + return ( <> {openGroupId && ( @@ -88,13 +108,32 @@ function TilesOverlay({ children }) { borderColor: "border", cursor: "default", display: "flex", - alignItems: "flex-end", - justifyContent: "center", + justifyContent: "flex-start", + alignItems: "center", position: "relative", + flexDirection: "column", }} bg="background" onClick={(e) => e.stopPropagation()} > + <Flex my={1} sx={{ position: "relative" }}> + <Text as="p" my="2px"> + {group?.name} + </Text> + <IconButton + sx={{ + width: "24px", + height: "24px", + position: group?.name ? "absolute" : "relative", + left: group?.name ? "100%" : 0, + }} + title="Edit Group" + aria-label="Edit Group" + onClick={() => setIsGroupNameModalOpen(true)} + > + <ChangeNicknameIcon /> + </IconButton> + </Flex> <SimpleBar style={{ width: containerSize.width - 16, @@ -123,6 +162,12 @@ function TilesOverlay({ children }) { </Box> </animated.div> </ReactResizeDetector> + <GroupNameModal + isOpen={isGroupNameModalOpen} + name={group?.name} + onSubmit={handleGroupNameChange} + onRequestClose={() => setIsGroupNameModalOpen(false)} + /> </> ); } diff --git a/src/helpers/group.js b/src/helpers/group.js index 9b81aea..a23313e 100644 --- a/src/helpers/group.js +++ b/src/helpers/group.js @@ -221,3 +221,18 @@ export function getItemNames(items, itemKey = "id") { } return names; } + +/** + * Immutably rename a group + * @param {Group[]} groups + * @param {string} groupId + * @param {string} newName + */ +export function renameGroup(groups, groupId, newName) { + let newGroups = cloneDeep(groups); + const groupIndex = newGroups.findIndex((group) => group.id === groupId); + if (groupIndex >= 0) { + newGroups[groupIndex].name = newName; + } + return newGroups; +} diff --git a/src/modals/GroupNameModal.js b/src/modals/GroupNameModal.js new file mode 100644 index 0000000..f410256 --- /dev/null +++ b/src/modals/GroupNameModal.js @@ -0,0 +1,51 @@ +import React, { useState, useRef, useEffect } from "react"; +import { Box, Input, Button, Label, Flex } from "theme-ui"; + +import Modal from "../components/Modal"; + +function GroupNameModal({ isOpen, name, onSubmit, onRequestClose }) { + const [tmpName, setTempName] = useState(name); + + useEffect(() => { + setTempName(name); + }, [name]); + + function handleChange(event) { + setTempName(event.target.value); + } + + function handleSubmit(event) { + event.preventDefault(); + onSubmit(tmpName); + } + + const inputRef = useRef(); + function focusInput() { + inputRef.current && inputRef.current.focus(); + } + + return ( + <Modal + isOpen={isOpen} + onRequestClose={onRequestClose} + onAfterOpen={focusInput} + > + <Box as="form" onSubmit={handleSubmit}> + <Label py={2} htmlFor="name"> + Group Name + </Label> + <Input + id="name" + value={tmpName} + onChange={handleChange} + ref={inputRef} + /> + <Flex py={2}> + <Button sx={{ flexGrow: 1 }}>Save</Button> + </Flex> + </Box> + </Modal> + ); +} + +export default GroupNameModal;