/*! * Copyright (c) 2024 PLANKA Software GmbH * Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md */ import React, { useCallback, useContext, useMemo, useState } from 'react'; import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import { Droppable } from 'react-beautiful-dnd'; import { Progress } from 'semantic-ui-react'; import { useDidUpdate } from '../../../lib/hooks'; import selectors from '../../../selectors'; import { isListArchiveOrTrash } from '../../../utils/record-helpers'; import DroppableTypes from '../../../constants/DroppableTypes'; import { BoardMembershipRoles } from '../../../constants/Enums'; import { ClosableContext } from '../../../contexts'; import Task from './Task'; import AddTask from './AddTask'; import styles from './TaskList.module.scss'; const TaskList = React.memo(({ id }) => { const selectTaskListById = useMemo(() => selectors.makeSelectTaskListById(), []); const selectListById = useMemo(() => selectors.makeSelectListById(), []); const selectTasksByTaskListId = useMemo(() => selectors.makeSelectTasksByTaskListId(), []); const taskList = useSelector((state) => selectTaskListById(state, id)); const tasks = useSelector((state) => selectTasksByTaskListId(state, id)); const canEdit = useSelector((state) => { const { listId } = selectors.selectCurrentCard(state); const list = selectListById(state, listId); if (isListArchiveOrTrash(list)) { return false; } const boardMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state); return !!boardMembership && boardMembership.role === BoardMembershipRoles.EDITOR; }); const [t] = useTranslation(); const [isAddOpened, setIsAddOpened] = useState(false); const [, , setIsClosableActive] = useContext(ClosableContext); // TODO: move to selector? const completedTasksTotal = useMemo( () => tasks.reduce((result, task) => (task.isCompleted ? result + 1 : result), 0), [tasks], ); const handleAddClick = useCallback(() => { setIsAddOpened(true); }, []); const handleAddClose = useCallback(() => { setIsAddOpened(false); }, []); useDidUpdate(() => { setIsClosableActive(isAddOpened); }, [isAddOpened]); return ( <> {tasks.length > 0 && ( <> {completedTasksTotal}/{tasks.length} )} {({ innerRef, droppableProps, placeholder }) => ( // eslint-disable-next-line react/jsx-props-no-spreading
{tasks.map((task, index) => ( ))} {placeholder}
)}
{canEdit && ( )} ); }); TaskList.propTypes = { id: PropTypes.string.isRequired, }; export default TaskList;