diff --git a/src/components/ListItem/index.js b/src/components/ListItem/index.js index 9a4bf89..396d3b6 100644 --- a/src/components/ListItem/index.js +++ b/src/components/ListItem/index.js @@ -4,6 +4,7 @@ import { useHistory } from 'react-router-dom' import TaskIcon from 'assets/tasks/task.svg' import Actions from 'components/Actions' import FavouriteIcon from 'components/TaskActionsIcons' +import { MoreHorizontal } from 'react-feather' const StyledListItem = styled.div` position: relative; @@ -74,6 +75,7 @@ const ListItem = ({ onClick, userGuid, groupGuid, + showActionsIcon, }) => { const history = useHistory() @@ -91,16 +93,20 @@ const ListItem = ({ {showFavourite && } - {showActions && itemType && ( - - )} + {showActions && + itemType && + (showActionsIcon ? ( + + ) : ( + + ))} ) diff --git a/src/views/AcceptTasks/group.js b/src/views/AcceptTasks/group.js new file mode 100644 index 0000000..9604311 --- /dev/null +++ b/src/views/AcceptTasks/group.js @@ -0,0 +1,275 @@ +import React, { useEffect } from 'react' +import styled, { keyframes } from 'styled-components' +import { useParams } from 'react-router-dom' +import { + Accordion, + AccordionItem, + AccordionItemHeading, + AccordionItemButton, + AccordionItemPanel, +} from 'react-accessible-accordion' +import { Check } from 'react-feather' +import ListItem from 'components/ListItem' +import { COMPLETION_STATUS, ITEM_TYPES } from 'consts' +import { useSelector } from 'react-redux' +import { StyledAcceptIcon } from '../../components/TaskActionsIcons' +import { useDispatch } from 'react-redux' +import { updateGroupMemberTask } from '../../redux/actionCreators' +import { acceptGroupMemeberTasks } from '../../api' + +const StyledAcceptTasks = styled.div` + height: 100%; + background-color: ${({ theme }) => theme.color.background}; + pointer-events: all; + overflow: auto; +` + +const Subheading = styled.h3` + margin: 0; + font-size: 18px; + font-weight: normal; +` + +const Content = styled.div` + > ${Subheading} { + margin-bottom: 1rem; + } +` + +const AcceptTasksAction = styled.div` + position: fixed; + bottom: 0; + left: 0; + box-sizing: border-box; + width: 100%; + padding: 4rem; + z-index: 1; + animation: ${keyframes` + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } + `} 200ms linear; +` + +const ActivityItem = styled.div` + display: flex; + align-items: center; + + > span { + padding: 1rem; + } + + :last-child { + justify-content: center; + + > span { + padding-top: 2rem; + } + } +` + +const StyledListItem = styled.div` + padding: 0 3.5rem 2rem 3.5rem; + text-decoration: none; +` + +const HorizontalLine = styled.hr` + margin: 0 3.5rem 2.5rem 3.5rem; +` + +const initialList = [] + +const getInitialCheckboxData = group => + group.members.map(member => ({ + selected: false, + name: member.memberName, + id: member.memberId, + tasks: member.memberTasks, + })) + +const Group = ({ group }) => { + const dispatch = useDispatch() + const { taskGuid } = useParams() + const groupsData = useSelector(state => state.user.userGroups) + const generalTranslations = useSelector(state => state.translations.yleiset) + const [memberIdList, setMemberIdList] = React.useState(initialList) + const [selectedGroup, setSelectedGroup] = React.useState() + const [checkboxData, setCheckboxData] = React.useState( + getInitialCheckboxData(group) + ) + useEffect(() => setCheckboxData(getInitialCheckboxData(group)), [ + groupsData, + group, + ]) + + if (!generalTranslations || !groupsData) return null + + const groupName = group.name + const ageGroup = group.ageGroup + const ageGroupId = group.id + const title = '' + groupName + ' / ' + ageGroup + + function isCompleted(memberTasks) { + const completedTasks = Object.keys(memberTasks).filter( + guid => memberTasks[guid] === COMPLETION_STATUS.COMPLETED + ) + const isCompleted = !!completedTasks.find(guid => guid === taskGuid) + + return isCompleted + } + function updateGroup(group) { + if (selectedGroup) { + setSelectedGroup(null) + } else { + setSelectedGroup(group) + } + } + + function handleChange(event) { + if (event.target.name === 'checkAll') { + checkboxData.map(member => { + return handleCheckboxSelection(Number(member.id), event.target.checked) + }) + } else { + handleCheckboxSelection(Number(event.target.value), event.target.checked) + } + + const editableList = checkboxData.reduce((idList, data) => { + if (data.selected) { + idList.push(data.id.toString()) + } + return idList + }, []) + + setMemberIdList(editableList) + } + + async function handleSubmit() { + try { + const data = { + userIds: memberIdList, + } + await acceptGroupMemeberTasks(data, taskGuid) + for (let id of memberIdList) { + dispatch( + updateGroupMemberTask({ + task_guid: taskGuid, + user_guid: Number(id), + completion_status: COMPLETION_STATUS.COMPLETED, + groupGuid: Number(selectedGroup), + }) + ) + } + } catch (e) { + console.log(e) + } + setMemberIdList(initialList) + } + + function handleCheckboxSelection(memberId, isChecked) { + const editableCheckboxData = checkboxData + editableCheckboxData.map(member => { + if (member.id === memberId && isChecked) { + member.selected = true + } + if (member.id === memberId && !isChecked) { + member.selected = false + } + return setCheckboxData(editableCheckboxData) + }) + } + + const CHECK_STYLE = { + float: 'right', + margin: 0, + width: '1.3rem', + height: '1.3rem', + } + + return ( + + + updateGroup(ageGroupId)} + key={ageGroupId} + > + + + + + + + + + + + + + + {checkboxData.map(member => { + return ( + + + {isCompleted(member.tasks) ? ( + + ) : ( + + )} + + ) + })} + + + + + + {memberIdList.length > 0 ? ( + + + + Lisää valituille + + + ) : null} + + ) +} + +export default Group diff --git a/src/views/AcceptTasks/index.js b/src/views/AcceptTasks/index.js index 2399711..ef04e83 100644 --- a/src/views/AcceptTasks/index.js +++ b/src/views/AcceptTasks/index.js @@ -1,22 +1,10 @@ import React from 'react' -import styled, { keyframes } from 'styled-components' -import { useHistory, useParams } from 'react-router-dom' -import { - Accordion, - AccordionItem, - AccordionItemHeading, - AccordionItemButton, - AccordionItemPanel, -} from 'react-accessible-accordion' +import styled from 'styled-components' +import { useHistory } from 'react-router-dom' import { X } from 'react-feather' -import ListItem from 'components/ListItem' -import { COMPLETION_STATUS, ITEM_TYPES } from 'consts' import { useSelector } from 'react-redux' import { determineLanguageFromUrl, getTermInLanguage } from 'helpers' -import { StyledAcceptIcon } from '../../components/TaskActionsIcons' -import { useDispatch } from 'react-redux' -import { updateGroupMemberTask } from '../../redux/actionCreators' -import { acceptGroupMemeberTasks } from '../../api' +import Group from './group' const StyledAcceptTasks = styled.div` height: 100%; @@ -53,101 +41,13 @@ const Content = styled.div` margin-bottom: 1rem; } ` - -const AcceptTasksAction = styled.div` - position: fixed; - bottom: 0; - left: 0; - box-sizing: border-box; - width: 100%; - padding: 4rem; - z-index: 1; - animation: ${keyframes` - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } - `} 200ms linear; -` - -const ActivityItem = styled.div` - display: flex; - align-items: center; - - > span { - padding: 1rem; - } - - :last-child { - justify-content: center; - - > span { - padding-top: 2rem; - } - } -` - -const StyledListItem = styled.div` - padding: 0 3.5rem 2rem 3.5rem; - text-decoration: none; -` - -const initialList = [] - const AcceptTasks = () => { - const dispatch = useDispatch() - const { taskGuid } = useParams() const history = useHistory() const language = determineLanguageFromUrl(window.location) const groupsData = useSelector(state => state.user.userGroups) const generalTranslations = useSelector(state => state.translations.yleiset) - const [memberIdList, setMemberIdList] = React.useState(initialList) - const [selectedGroup, setSelectedGroup] = React.useState() if (!generalTranslations || !groupsData) return null - function updateGroup(group) { - if (selectedGroup) { - setSelectedGroup(null) - } else { - setSelectedGroup(group) - } - } - - function handleChange(event) { - const editableList = memberIdList.slice(0) - if (memberIdList.includes(event.target.value)) { - const index = memberIdList.findIndex(id => id === event.target.value) - editableList.splice(index, 1) - } else { - editableList.push(event.target.value) - } - setMemberIdList(editableList) - } - - async function handleSubmit() { - try { - const data = { - userIds: memberIdList, - } - await acceptGroupMemeberTasks(data, taskGuid) - - for (let id of memberIdList) { - dispatch( - updateGroupMemberTask({ - task_guid: taskGuid, - user_guid: id, - completion_status: COMPLETION_STATUS.ACTIVE, - groupGuid: selectedGroup, - }) - ) - } - } catch (e) { - console.log(e) - } - } - return (
@@ -159,68 +59,9 @@ const AcceptTasks = () => { {getTermInLanguage(generalTranslations, 'own_groups', language)} {groupsData.map(group => { - const groupName = group.name - const ageGroup = group.ageGroup - const ageGroupId = group.id - const title = '' + groupName + ' / ' + ageGroup - return ( - updateGroup(ageGroupId)} - key={ageGroupId} - > - - - - - - - - - {group.members.map(member => { - return ( - - - - - ) - })} - - - - - ) + return })} - - - - Lisää valituille - - ) }