UNPKG

@eureca/eureca-ui

Version:

UI component library of Eureca's user and admin apps

212 lines (186 loc) 5.25 kB
import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { DragDropContext } from 'react-beautiful-dnd'; import { Flex } from '../Flex'; import { Column } from './column'; import { AddColumn } from './add-column'; function Board({ values, onChange, cardsOptions, onAddCard, onClickCard, columnMenu, onClickColumnMenu, phaseOptions, onClickCardAction, }) { const [boardData, setBoardData] = useState(() => values); function onDragEnd(result) { const { destination, source, draggableId } = result; // dropped outside board if (!destination) { return; } // dropped in the same position if (destination.droppableId === source.droppableId && destination.index === source.index) { return; } const start = boardData.columns[source.droppableId]; const finish = boardData.columns[destination.droppableId]; // same column drag if (start === finish) { const newTaskIds = [...start.taskIds]; newTaskIds.splice(source.index, 1); newTaskIds.splice(destination.index, 0, draggableId); const newColumn = { ...start, taskIds: newTaskIds, }; const newBoardData = { ...boardData, columns: { ...boardData.columns, [newColumn.id]: newColumn, }, }; setBoardData(newBoardData); return; } // diff column drag const startTaskIds = [...start.taskIds]; startTaskIds.splice(source.index, 1); const newStart = { ...start, taskIds: startTaskIds, }; const finishTaskIds = [...finish.taskIds]; finishTaskIds.splice(destination.index, 0, draggableId); const newFinish = { ...finish, taskIds: finishTaskIds, }; const newBoardData = { ...boardData, columns: { ...boardData.columns, [newStart.id]: newStart, [newFinish.id]: newFinish, }, }; setBoardData(newBoardData); } function insert(arr, index, newItem) { return [...arr.slice(0, index), newItem, ...arr.slice(index)]; } function handleAdd(value) { const size = Object.keys(boardData.columns).length; const newColumn = { id: `${size}`, title: value, points: '', taskIds: [], }; const newBoardData = { ...boardData, columns: { ...boardData.columns, [size]: newColumn, }, columnOrder: insert(boardData.columnOrder, size - 1, newColumn.id), }; setBoardData(newBoardData); } useEffect(() => { setBoardData(values); }, [values]); useEffect(() => { onChange(boardData); }, [onChange, boardData]); return ( <DragDropContext onDragEnd={onDragEnd}> <Flex directionRow style={{ overflowX: 'scroll' }}> {boardData.columnOrder.map((columnId, index, arr) => { const column = boardData.columns[columnId]; const tasks = column.taskIds.map(taskId => boardData.tasks.find(task => task.id === taskId) ); if (index === arr.length - 1) { return ( <React.Fragment key={columnId}> <AddColumn add={handleAdd} phaseOptions={phaseOptions} /> <Column column={column} tasks={tasks} cardsOptions={cardsOptions} onAddCard={onAddCard} onClickCard={onClickCard} columnMenu={columnMenu} onClickColumnMenu={onClickColumnMenu} onClickCardAction={onClickCardAction} /> </React.Fragment> ); } return ( <Column column={column} tasks={tasks} key={columnId} cardsOptions={cardsOptions} onAddCard={onAddCard} onClickCard={onClickCard} columnMenu={columnMenu} onClickColumnMenu={onClickColumnMenu} onClickCardAction={onClickCardAction} /> ); })} </Flex> </DragDropContext> ); } Board.defaultProps = { values: { tasks: [], columns: {}, columnOrder: [], }, cardsOptions: [], columnMenu: [], onChange: () => {}, onAddCard: () => {}, onClickCard: () => {}, onClickColumnMenu: () => {}, pathOptions: [ { id: 0, value: '', label: '', icon: null, }, ], }; Board.propTypes = { values: PropTypes.shape({ tasks: PropTypes.array.isRequired, columns: PropTypes.object.isRequired, columnOrder: PropTypes.array.isRequired, }).isRequired, cardsOptions: PropTypes.array, columnMenu: PropTypes.array, onChange: PropTypes.func, onAddCard: PropTypes.func, onClickCard: PropTypes.func, onClickColumnMenu: PropTypes.func, phaseOptions: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), label: PropTypes.string, icon: PropTypes.oneOfType([PropTypes.node, PropTypes.element]), }) ), onClickCardAction: PropTypes.func, }; export { Board };