feat: добавлен список участников доски с возможностью перейти в их профиль
This commit is contained in:
@@ -8,7 +8,7 @@ import {
|
|||||||
addMemberAPI, assignMemberAPI, unassignMemberAPI, deleteMemberAPI, quitMemberAPI
|
addMemberAPI, assignMemberAPI, unassignMemberAPI, deleteMemberAPI, quitMemberAPI
|
||||||
} from './BoardAPI';
|
} from './BoardAPI';
|
||||||
|
|
||||||
export const useBoardLogic = (id, setError, setInfo, setCategories, setLoading) => {
|
export const useBoardLogic = (id, setError, setInfo, setCategories, setLoading, setItems) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const loadBoardData = useCallback(async () => {
|
const loadBoardData = useCallback(async () => {
|
||||||
@@ -17,6 +17,7 @@ export const useBoardLogic = (id, setError, setInfo, setCategories, setLoading)
|
|||||||
setError('');
|
setError('');
|
||||||
const response = await loadBoardDataAPI(id);
|
const response = await loadBoardDataAPI(id);
|
||||||
setInfo(response.data);
|
setInfo(response.data);
|
||||||
|
setItems(response.data.members)
|
||||||
setCategories(response.data.categories || []);
|
setCategories(response.data.categories || []);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.response?.data?.message === 'Token Error' ||
|
if (err.response?.data?.message === 'Token Error' ||
|
||||||
@@ -32,7 +33,7 @@ export const useBoardLogic = (id, setError, setInfo, setCategories, setLoading)
|
|||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}, [id, setError, setInfo, setCategories, setLoading, navigate]);
|
}, [id, setError, setInfo, setCategories, setLoading, setItems, navigate]);
|
||||||
|
|
||||||
const checkOwner = useCallback(async (ownerId, setIsOwner) => {
|
const checkOwner = useCallback(async (ownerId, setIsOwner) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams, useNavigate } from 'react-router-dom';
|
||||||
import { useBoardLogic } from './BoardLogic';
|
import { useBoardLogic } from './BoardLogic';
|
||||||
import Header from './../Header';
|
import Header from './../Header';
|
||||||
import './../css/Board.css';
|
import './../css/Board.css';
|
||||||
|
|
||||||
const KBBoard = () => {
|
const KBBoard = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [info, setInfo] = useState({});
|
const [info, setInfo] = useState({});
|
||||||
const [categories, setCategories] = useState([]);
|
const [categories, setCategories] = useState([]);
|
||||||
const [isOwner, setIsOwner] = useState(null);
|
const [isOwner, setIsOwner] = useState(null);
|
||||||
|
const [items, setItems] = useState([]);
|
||||||
|
|
||||||
|
const [memList, setMemList] = useState(false);
|
||||||
const [crTask, setCrTask] = useState(false);
|
const [crTask, setCrTask] = useState(false);
|
||||||
const [crCateg, setCrCateg] = useState(false);
|
const [crCateg, setCrCateg] = useState(false);
|
||||||
const [edTask, setEdTask] = useState(false);
|
const [edTask, setEdTask] = useState(false);
|
||||||
@@ -56,7 +59,20 @@ const KBBoard = () => {
|
|||||||
deleteBoards,
|
deleteBoards,
|
||||||
quitMember,
|
quitMember,
|
||||||
deleteMember
|
deleteMember
|
||||||
} = useBoardLogic(id, setError, setInfo, setCategories, setLoading);
|
} = useBoardLogic(id, setError, setInfo, setCategories, setLoading, setItems);
|
||||||
|
|
||||||
|
function ListItem({ item }) {
|
||||||
|
if (!item) return null;
|
||||||
|
const user = () => { navigate('/profile/' + item.id); };
|
||||||
|
return (
|
||||||
|
<button onClick={user}>
|
||||||
|
<div className="row">
|
||||||
|
<h3>{item.display_name}<img className='members-avatar' src={item.avatar_url}></img></h3>
|
||||||
|
<p><strong>Описание:</strong> {item.description ? item.description : 'Отсутствует'}</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (id) loadBoardData();
|
if (id) loadBoardData();
|
||||||
@@ -66,6 +82,9 @@ const KBBoard = () => {
|
|||||||
if (info?.owner?.id !== undefined) checkOwner(info?.owner?.id, setIsOwner);
|
if (info?.owner?.id !== undefined) checkOwner(info?.owner?.id, setIsOwner);
|
||||||
}, [info?.owner?.id, checkOwner, setIsOwner]);
|
}, [info?.owner?.id, checkOwner, setIsOwner]);
|
||||||
|
|
||||||
|
const modalMemList = () => {
|
||||||
|
setMemList(!memList);
|
||||||
|
}
|
||||||
const modalCrTask = (categori) => () => {
|
const modalCrTask = (categori) => () => {
|
||||||
setCrTask(!crTask);
|
setCrTask(!crTask);
|
||||||
setTaskCategori(categori);
|
setTaskCategori(categori);
|
||||||
@@ -182,6 +201,7 @@ const KBBoard = () => {
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
<h3>{info.title}</h3>
|
<h3>{info.title}</h3>
|
||||||
<p>
|
<p>
|
||||||
|
<button onClick={modalMemList}>
|
||||||
<strong>Участники: </strong>
|
<strong>Участники: </strong>
|
||||||
{(info.members || []).map((member) => (
|
{(info.members || []).map((member) => (
|
||||||
(member.id !== info.owner.id) ? (
|
(member.id !== info.owner.id) ? (
|
||||||
@@ -190,10 +210,13 @@ const KBBoard = () => {
|
|||||||
<></>
|
<></>
|
||||||
)
|
)
|
||||||
))}
|
))}
|
||||||
|
</button>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
<button onClick={()=>navigate('/profile/' + info.owner.id)}>
|
||||||
<strong>Владелец: </strong> {" "+info.owner?.display_name}
|
<strong>Владелец: </strong> {" "+info.owner?.display_name}
|
||||||
<img className="nav-avatar" src={info.owner?.avatar_url} alt=''></img>
|
<img className="nav-avatar" src={info.owner?.avatar_url} alt=''></img>
|
||||||
|
</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@@ -278,6 +301,25 @@ const KBBoard = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{memList && (
|
||||||
|
<div className="confirm-modal">
|
||||||
|
<div className="modal-content modal-member">
|
||||||
|
<div><h3>Изменение задачи</h3></div>
|
||||||
|
<label >Участники:</label>
|
||||||
|
<div className='task-list members-list'>
|
||||||
|
{items.length > 0 ? (
|
||||||
|
items.map((item) => (
|
||||||
|
<ListItem key={item.id} item={item} />
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<p>Нет участников</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<button onClick={modalMemList}>Закрыть</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{crCateg && (
|
{crCateg && (
|
||||||
<div className="confirm-modal">
|
<div className="confirm-modal">
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
|
|||||||
@@ -35,6 +35,10 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-content .row {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.members-avatar {
|
.members-avatar {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
@@ -43,10 +47,45 @@
|
|||||||
margin-right: -24px;
|
margin-right: -24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.row button {
|
||||||
|
background-color: #0000;
|
||||||
|
display: flex;
|
||||||
|
word-break: break-all;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: #CAD1D8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members-list{
|
||||||
|
gap: 6px;
|
||||||
|
padding: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members-list button{
|
||||||
|
border-radius: 6px;
|
||||||
|
margin: 0px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-around;
|
||||||
|
background-color: #3d4763;
|
||||||
|
}
|
||||||
|
|
||||||
|
.members-list button:hover{
|
||||||
|
box-shadow: 0 0 4px 1px #08e8de78;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-member {
|
||||||
|
flex: 0 1 auto; /* занимает всё свободное место */
|
||||||
|
overflow-y: auto; /* вертикальный скролл при переполнении */
|
||||||
|
overflow-x: hidden; /* горизонтальный скролл отключён */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.set-panel{
|
.set-panel{
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
|
max-height: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-buttons {
|
.modal-buttons {
|
||||||
|
|||||||
Reference in New Issue
Block a user