Files
Kanban-Front/src/KBBoardsList.js

213 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState, useEffect, useRef, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';
import Header from './Header';
import './css/BoardList.css';
const KBBoardsList = () => {
const navigate = useNavigate();
const debounceRef = useRef(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const [showCreateModal, setShowCreateModal] = useState(false);
const [timer, setTimer] = useState(400)
const [sort_method, setSortMethod] = useState('title');
const [reverse, setReverse] = useState(false);
const [search_text, setSearchText] = useState('');
const [page, setPage] = useState(1);
const [limit, setLimit] = useState(5);
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const [items, setItems] = useState([]);
const [totalItems, setTotalItems] = useState(null);
function ListItem({ item }) {
if (!item) return null;
const openBoard = () => { navigate('/kanban-board/' + item.id); };
return (
<li>
<button onClick={openBoard}>
<div className="sort-row">
<h3>{item.title}</h3>
<p><strong>Владелец:</strong> {item.owner_display_name}</p>
</div>
<div className="sort-row">
<p><strong>Описание:</strong> {item.description ? item.description : 'Отсутствует'}</p>
</div>
</button>
</li>
);
};
const Pagination = () => {
const totalPages = Math.ceil(totalItems / limit);
if (totalPages <= 1) return null;
const pages = [];
for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}
return (
<div className="pagination">
{pages.map((pageNum) => (
<button
key={pageNum}
onClick={() => setPage(pageNum)}
className={page === pageNum ? 'active' : ''}
disabled={loading}
> {pageNum} </button>
))}
</div>
);
};
const loadBoardList = useCallback(async () => {
clearTimeout(debounceRef.current);
debounceRef.current = setTimeout(async () => {
try {
const newList = { sort_method, reverse, search_text, page, limit };
const response = await axios.post('/api/boards/list', newList, {withCredentials: true });
if (Array.isArray(response.data.boards)) {
setItems(response.data.boards);
setTotalItems(response.data.count || response.data.boards.length);
} else {
setItems([]);
setTotalItems(0)
if (response.data?.detail === 'Доски отсутствуют.') {
console.log('Доски отсутствуют');
}
}
} catch (err) {
if (err.response?.data?.message === 'Token Error' || err.response?.data?.message === 'Invalid Token') {
setError('Вы не авторизованы');
setTimeout(() => {
navigate('/login');
}, 1000);
} else {
setError('Ошибка загрузки досок');
console.log(err);
setItems([]);
}
}
setTimer(400)
}, timer);
}, [sort_method, reverse, search_text, page, limit, timer, setItems, setTotalItems, setError, navigate]);
useEffect(() => {
loadBoardList();
}, [page, loadBoardList]);
const setFilter = (method) => () => {
const newMethod = method;
const newReverse = sort_method === method ? !reverse : false;
setSortMethod(newMethod);
setReverse(newReverse);
setTimer(100);
};
const createBoard = async (e) => {
e.preventDefault();
try {
setLoading(true)
const newBoard = { title, description };
await axios.post('/api/boards/create', newBoard);
setShowCreateModal(false);
await loadBoardList();
} catch (err) {
setError('Ошибка');
} finally {
setLoading(false);
}
};
const openCreateModal = () => { setShowCreateModal(true) };
const closeCreateModal = () => { setShowCreateModal(false); setDescription(''); setTitle('') };
return (
<>
<Header />
<div className="profile-page">
{
error && <div className="error">{error}</div>
}
<div className="kan-ban-list-sort">
<h3>Сортировка по:</h3>
<div className="nav-sort">
<button onClick={setFilter('title')}>
Названию
</button>
<button onClick={setFilter('owner')}>
Создателю
</button>
<button onClick={setFilter('update_time')}>
Дате обновления
</button>
</div>
<input
type="text"
placeholder="Поиск по названию..."
value={search_text}
onChange={(e) => setSearchText(e.target.value)}
/>
</div>
<div className="kan-ban-list">
<div className="inf">
<h3>Доступные канбан доски:</h3>
<button onClick={openCreateModal}>Создать канбан-доску</button>
</div>
{items.length > 0 ? (
<ul>
{items.map((item) => (
<ListItem key={item.id} item={item} />
))}
</ul>
) : (
<p>Нет данных</p>
)}
</div>
<Pagination />
</div>
{showCreateModal && (
<div className="confirm-modal">
<div className="modal-content">
<p><strong>Придумайте название и описание канбан доски</strong></p>
<form onSubmit={createBoard}>
<div>
<label>Название:</label>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
/>
</div>
<div>
<label>Описание:</label>
<input
type="text"
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
</div>
<div className="modal-buttons">
<button type="submit" disabled={loading}>{loading ? 'Создание...' : 'Создать'}</button>
<button onClick={closeCreateModal}>Отменить</button>
</div>
</form>
</div>
</div>
)}
</>
);
}
export default KBBoardsList;