const { task, componentOwnerId, onCloseTaskDetails, removeTaskFromColumn, projectId, contract, addActionStatus, taskColumn, handleColumns, columnIndex } = props; const OverlayContainer = styled.div` left: 12px; right: 12px; bottom: 0px; top: 40px; position: absolute; z-index: 20; display: flex; background-color: rgba(0, 0, 0, 0.5); justify-content: center; padding-top: 100px; `; const PopupContainer = styled.div` position: relative; background-color: #1d1d21; padding: 1rem; width: 734px; height: fit-content; `; const Header = styled.div` display: flex; flex-direction: row; justify-content: space-between; align-items: center; `; const ActionsContainer = styled.div` display: flex; flex-direction: row; gap: 3px; align-items: center; items-center: center; `; const Text = styled.div` display: flex; column-gap: 0.5rem; align-items: center; color: #fff; font-family: Helvetica Neue; font-size: 24px; font-style: normal; font-weight: 500; line-height: 120% margin-bottom: 1rem; `; const Title = styled.input` color: #fff; font-family: Helvetica Neue; font-size: 20px; font-weight: 500; line-height: 24px; letter-spacing: 0em; text-align: left; width: 100%; height: 40px; padding: 8px 60px 8px 16px; margin-top: 1rem; margin-bottom: 1rem; border-radius: 4px; background-color: transparent; :focus { outline-color: #D0FC42; outline-style: solid; outline-width: 1px; } ::placeholder { color: #D0FC42; } border: none; `; const Input = styled.input` color: #fff; font-family: Helvetica Neue; font-size: 16px; font-weight: 400; line-height: 24px; letter-spacing: 0em; text-align: left; flex: 1; height: 40px; padding: 8px 60px 8px 16px; margin-top: 1rem; margin-bottom: 1rem; border-radius: 4px; background-color: transparent; :focus { outline-color: #D0FC42; outline-style: solid; outline-width: 1px; } ::placeholder { color: #D0FC42; } border: none; `; const Label = styled.label` color: #777583; font-family: Helvetica Neue; font-size: 16px; font-weight: 400; line-height: 24px; letter-spacing: 0em; text-align: left; width: 104px; height: 40px; padding: 8px 60px 8px 16px; margin-top: 1rem; margin-bottom: 1rem; border-radius: 4px; background-color: transparent; :focus { outline-color: #D0FC42; outline-style: solid; outline-width: 1px; } border: none; white-space: nowrap; `; const CloseButton = styled.div` color: #fff; :hover { color: #D0FC42; } cursor: pointer; `; const DeleteButton = styled.div` color: #fff; :hover { color: #D0FC42; } display: flex; flex-direction: row; cursor: pointer; text-align: center; color: #ffffff; justify-content: center; align-items: center; gap: 3px; `; const P = styled.p` padding-top: 14px; `; const InputContainer = styled.div` display: flex; flex-direction: row; align-items: center; gap: 68px; `; const Divider = styled.div` width: 100%; height: 1px; background-color: #282933; margin-top: 16px; margin-bottom: 16; `; const SuccessIcon = styled.div` color: #00FF66; `; const ErrorIcon = styled.div` color: #DC3545; `; const FieldContainer = styled.div` position: relative; width: 100%; `; const StatusIcon = styled.div` position: absolute; right: 1px; top: 35%; `; const MissingText = styled.div` position: absolute; right: 36%; top: 75%; font-family: Helvetica Neue; font-size: 16px; font-weight: 400; line-height: 24px; letter-spacing: 0em; color: red; `; const MissingTitle = styled.div` position: absolute; left: 14px; top: 75%; font-family: Helvetica Neue; font-size: 16px; font-weight: 400; line-height: 24px; letter-spacing: 0em; color: red; `; const LabelContainer = styled.div` width: 100%; `; const ReporterInfo = styled.div` display: flex; column-gap: 0.5rem; padding: 1rem; `; const ReporterId = styled.div` display: flex; justify-content: start; align-items: center; width: 100%; color: #fff; `; const [editTaskTitle, setEditTaskTitle] = useState(task.title); const [editTaskDescription, setEditTaskDescription] = useState(task.description); const [editTaskTitleMissing, setEditTaskTitleMissing] = useState(false); const [isDeleteTaskVisible, setIsDeleteTaskVisible] = useState(false); const [editTaskTitleStatus, setEditTaskTitleStatus] = useState(null); const [editTaskDescriptionStatus, setEditTaskDescriptionStatus] = useState(null); const onEditTaskTitle = (e) => { setEditTaskTitleMissing(false); setEditTaskTitle(e.target.value); }; const onEditTaskDescription = (e) => { setEditTaskDescription(e.target.value); }; const updateTaskTitle = useCallback(() => { if (!editTaskTitle || editTaskTitle.trim() === "") { setEditTaskTitleMissing(true); setTimeout(() => { setEditTaskTitleMissing(false); setEditTaskTitle(task.title); }, 3000); return; } if (task.title === editTaskTitle) { return; } try { setEditTaskTitleStatus("Saving"); const editedTask = { project_id: projectId, id: task.id, title: editTaskTitle, description: editTaskDescription, status: taskColumn, }; let newColumnsArray = []; const storageColumns = Storage.privateGet( "tempColumns" + contract + projectId ); if (storageColumns && JSON.parse(storageColumns).length > 0) { const columnsArray = JSON.parse(storageColumns); let filteredColumnsArray = []; if (columnsArray.find((task) => task.id === editTaskId)) { filteredColumnsArray = columnsArray.filter( (task) => task.id !== editTaskId ); } if (columnsArray.find((task) => task.title === oldTask.title)) { filteredColumnsArray = columnsArray.filter( (task) => task.title !== oldTask.title ); } newColumnsArray = filteredColumnsArray; newColumnsArray.push(editedTask); } else { newColumnsArray.push(editedTask); } const jsonStringArray = JSON.stringify(newColumnsArray); Storage.privateSet("tempColumns" + contract + projectId, jsonStringArray); handleColumns(projectId); Near.fakCalimeroCall(contract, "change_task_name", { project_id: projectId, task_id: task.id, new_title: editTaskTitle, }).then(() => { setEditTaskTitleStatus("Saved"); setTimeout(() => setEditTaskTitleStatus(null), 3000); }); } catch (e) { setEditTaskTitleStatus("Error"); setTimeout(() => setEditTaskTitleStatus(null), 3000); } }, [ task, editTaskTitle, editTaskDescription, projectId, contract, taskColumn, setEditTaskTitleStatus, ]); const updateTaskDescription = useCallback(() => { if (task.description === editTaskDescription) { return; } try { setEditTaskDescriptionStatus("Saving"); const editedTask = { project_id: projectId, id: task.id, title: editTaskTitle, description: editTaskDescription, status: taskColumn, }; let newColumns = []; const storageColumns = Storage.privateGet( "tempColumns" + contract + projectId ); if (storageColumns && JSON.parse(storageColumns).length > 0) { const parsedColumns = JSON.parse(storageColumns); let filteredParsedColumns = []; if (parsedColumns.find((task) => task.id === editTaskId)) { filteredParsedColumns = parsedColumns.filter( (task) => task.id !== editTaskId ); } newColumns = filteredParsedColumns; newColumns.push(editedTask); } else { newColumns.push(editedTask); } const jsonStringArray = JSON.stringify(newColumns); Storage.privateSet("tempColumns" + contract + projectId, jsonStringArray); handleColumns(projectId); Near.fakCalimeroCall(contract, "edit_task_description", { project_id: projectId, task_id: task.id, new_description: editTaskDescription, }).then(() => { setEditTaskDescriptionStatus("Saved"); setTimeout(() => setEditTaskDescriptionStatus(null), 3000); }); } catch (e) { setEditTaskDescriptionStatus("Error"); setTimeout(() => setEditTaskDescriptionStatus(null), 3000); } }, [ task, editTaskTitle, editTaskDescription, projectId, contract, taskColumn, setEditTaskDescriptionStatus, ]); const deleteTask = useCallback((task) => { const actionStatusPrefix = "Delete task"; let newActionStatus = { id: actionStatusPrefix + taskId, status: `Deleting task: ${task.id}` }; try { addActionStatus(newActionStatus); removeTaskFromColumn(task.id, columnIndex) Near.fakCalimeroCall(contract, "delete_task_by_id", { project_id: projectId, task_id: task.id, }).then(() => { newActionStatus.status = `Deleted task: ${taskId}`; addActionStatus(newActionStatus); }); } catch (e) { newActionStatus.status = `Error deleting task: ${taskId}`; addActionStatus(newActionStatus); } setIsDeleteTaskVisible(false); onCloseTaskDetails(); }, [projectId, contract, addActionStatus, columnIndex]); const taskCommentsEnabled = false; return ( <> {isDeleteTaskVisible && ( <Widget src={`${componentOwnerId}/widget/Calimero.TaskChain.ConfirmationPopup`} props={{ onClick: () => deleteTask(task), onClose: () => setIsDeleteTaskVisible(false), title: "Are you sure you want to delete the task?", }} /> )} <OverlayContainer> <PopupContainer> <Header> <ActionsContainer> <DeleteButton onClick={() => setIsDeleteTaskVisible(true)}> <i class="bi bi-trash"></i> <P>Delete</P> </DeleteButton> </ActionsContainer> <CloseButton onClick={onCloseTaskDetails}> <i class="bi bi-x-lg"></i> </CloseButton> </Header> <Divider /> <FieldContainer> <Title onChange={onEditTaskTitle} value={editTaskTitle} onBlur={updateTaskTitle} placeholder="Add Title"/> {editTaskTitleStatus && <StatusIcon> {editTaskTitleStatus === "Saving" && ( <Widget src={`${componentOwnerId}/widget/Calimero.TaskChain.Loader.Loader`} props={{ size: 16 }} /> )} {editTaskTitleStatus === "Saved" && ( <SuccessIcon> <i className="bi bi-check"></i> </SuccessIcon> )} {editTaskTitleStatus === "Error" && ( <ErrorIcon> <i className="bi bi-x-circle"></i> </ErrorIcon> )} </StatusIcon> } {editTaskTitleMissing && <MissingTitle> Missing title </MissingTitle> } </FieldContainer> <LabelContainer> <InputContainer> <Label>Created by</Label> <ReporterInfo> <Widget src={`${componentOwnerId}/widget/Calimero.TaskChain.ProfileIcon.UserProfileIcon`} props={{ accountId: task.reporter, componentOwnerId, }} /> <ReporterId>{task.reporter}</ReporterId> </ReporterInfo> </InputContainer> </LabelContainer> <FieldContainer> <InputContainer> <Label>Description</Label> <Input onChange={onEditTaskDescription} value={editTaskDescription} onBlur={updateTaskDescription} placeholder="Add Description"/> {editTaskDescriptionStatus && <StatusIcon> {editTaskDescriptionStatus === "Saving" && ( <Widget src={`${componentOwnerId}/widget/Calimero.TaskChain.Loader.Loader`} props={{ size: 16 }} /> )} {editTaskDescriptionStatus === "Saved" && ( <SuccessIcon> <i className="bi bi-check"></i> </SuccessIcon> )} {editTaskDescriptionStatus === "Error" && ( <ErrorIcon> <i className="bi bi-x-circle"></i> </ErrorIcon> )} </StatusIcon> } </InputContainer> </FieldContainer> {taskCommentsEnabled && <Widget src={`${componentOwnerId}/widget/Calimero.TaskChain.BoardContainer.Task.Comments`} props={{ componentOwnerId, comments: task.comments }} />} </PopupContainer> </OverlayContainer> </> );