Изменение сортировки и оптимизация кода
This commit is contained in:
41
package.json
41
package.json
@@ -1,41 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "client",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@testing-library/dom": "^10.4.1",
|
|
||||||
"@testing-library/jest-dom": "^6.9.1",
|
|
||||||
"@testing-library/react": "^16.3.1",
|
|
||||||
"@testing-library/user-event": "^13.5.0",
|
|
||||||
"axios": "^1.13.2",
|
|
||||||
"react": "^19.2.3",
|
|
||||||
"react-dom": "^19.2.3",
|
|
||||||
"react-router-dom": "^7.11.0",
|
|
||||||
"react-scripts": "5.0.1",
|
|
||||||
"web-vitals": "^2.1.4"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"start": "PORT=24452 react-scripts start",
|
|
||||||
"build": "react-scripts build --port=24452",
|
|
||||||
"test": "react-scripts test --port=24452",
|
|
||||||
"eject": "react-scripts eject --port=24452"
|
|
||||||
},
|
|
||||||
"eslintConfig": {
|
|
||||||
"extends": [
|
|
||||||
"react-app",
|
|
||||||
"react-app/jest"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"browserslist": {
|
|
||||||
"production": [
|
|
||||||
">0.2%",
|
|
||||||
"not dead",
|
|
||||||
"not op_mini all"
|
|
||||||
],
|
|
||||||
"development": [
|
|
||||||
"last 1 chrome version",
|
|
||||||
"last 1 firefox version",
|
|
||||||
"last 1 safari version"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,30 @@
|
|||||||
import React, { useState, useEffect, useRef } from 'react';
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import Header from './Header';
|
import Header from './Header';
|
||||||
|
|
||||||
function ListItem({ item }) {
|
const KBBoardsList = () => {
|
||||||
const navigate = useNavigate();
|
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 [list, setList] = useState(20);
|
||||||
|
|
||||||
|
const [title, setTitle] = useState('');
|
||||||
|
const [description, setDescription] = useState('');
|
||||||
|
const [items, setItems] = useState([]);
|
||||||
|
|
||||||
|
|
||||||
|
function ListItem({ item }) {
|
||||||
if (!item) return null;
|
if (!item) return null;
|
||||||
|
|
||||||
const openBoard = () => { navigate('/kanban-board/' + item.id); };
|
const openBoard = () => { navigate('/kanban-board/' + item.id); };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li>
|
<li>
|
||||||
<button onClick={openBoard}>
|
<button onClick={openBoard}>
|
||||||
@@ -25,68 +41,12 @@ function ListItem({ item }) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const KBBoardsList = () => {
|
const loadBoardList = useCallback(async () => {
|
||||||
const [error, setError] = useState('');
|
clearTimeout(debounceRef.current);
|
||||||
const [sort_method, setSortMethod] = useState('title');
|
|
||||||
const [reverse, setReverse] = useState(false);
|
|
||||||
const [search_text, setSearchText] = useState('');
|
|
||||||
const [title, setTitle] = useState('');
|
|
||||||
const [description, setDescription] = useState('');
|
|
||||||
const [items, setItems] = useState([]);
|
|
||||||
const [showCreateModal, setShowCreateModal] = useState(false);
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
|
||||||
const [filteredItems, setFilteredItems] = useState([]);
|
|
||||||
const [page, setPage] = useState(1);
|
|
||||||
const [list, setList] = useState(20);
|
|
||||||
const debounceRef = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const loadBoardList = async () => {
|
|
||||||
try {
|
try {
|
||||||
|
debounceRef.current = setTimeout(async () => {
|
||||||
var newList = { sort_method, reverse, search_text, page, list };
|
var newList = { sort_method, reverse, search_text, page, list };
|
||||||
const response = await axios.post('/api/boards/list', newList);
|
const response = await axios.post('/api/boards/list', newList);
|
||||||
if (Array.isArray(response.data)) {
|
|
||||||
setItems(response.data);
|
|
||||||
} else {
|
|
||||||
// Если данных нет или они не массив — ставим пустой массив
|
|
||||||
setItems([]);
|
|
||||||
if (response.data?.detail === 'Доски отсутствуют.') {
|
|
||||||
console.log('Доски отсутствуют');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
if (err.response.data.message === 'Token Error' || err.response.data.message === 'Invalid Token') {
|
|
||||||
setError('Вы не авторизованы');
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.href = '/login';
|
|
||||||
}, 1500);
|
|
||||||
} else {
|
|
||||||
setError('Ошибка загрузки досок');
|
|
||||||
console.log(err);
|
|
||||||
setItems([]); // Гарантируем, что items — массив
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
loadBoardList()
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
clearTimeout(debounceRef.current);
|
|
||||||
debounceRef.current = setTimeout(() => {
|
|
||||||
setFilteredItems(
|
|
||||||
items.filter(item =>
|
|
||||||
item.title.toLowerCase().includes(searchQuery.toLowerCase())
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}, 300); // 300 мс задержка
|
|
||||||
}, [searchQuery, items]);
|
|
||||||
|
|
||||||
const sortList = async (method = sort_method, isReverse = reverse) => {
|
|
||||||
try {
|
|
||||||
const newList = { sort_method: method, reverse: isReverse, search_text };
|
|
||||||
const response = await axios.post('/api/boards/list', newList);
|
|
||||||
|
|
||||||
if (Array.isArray(response.data)) {
|
if (Array.isArray(response.data)) {
|
||||||
setItems(response.data);
|
setItems(response.data);
|
||||||
} else {
|
} else {
|
||||||
@@ -95,57 +55,47 @@ const KBBoardsList = () => {
|
|||||||
console.log('Доски отсутствуют');
|
console.log('Доски отсутствуют');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setTimer(400)
|
||||||
|
}, timer);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.response?.data?.message === 'Token Error' || err.response?.data?.message === 'Invalid Token') {
|
if (err.response?.data?.message === 'Token Error' || err.response?.data?.message === 'Invalid Token') {
|
||||||
setError('Вы не авторизованы');
|
setError('Вы не авторизованы');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = '/login';
|
navigate('/login');
|
||||||
}, 1500);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
setError('Ошибка загрузки досок');
|
setError('Ошибка загрузки досок');
|
||||||
console.log(err);
|
console.log(err);
|
||||||
setItems([]);
|
setItems([]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}, [sort_method, reverse, search_text, page, list, timer, setItems, setError, navigate]);
|
||||||
|
|
||||||
const setFilterTitle = async () => {
|
useEffect(() => {
|
||||||
const newMethod = 'title';
|
loadBoardList();
|
||||||
const newReverse = sort_method === 'title' ? !reverse : false;
|
}, [loadBoardList]);
|
||||||
|
|
||||||
|
const setFilter = (method) => () => {
|
||||||
|
const newMethod = method;
|
||||||
|
const newReverse = sort_method === method ? !reverse : false;
|
||||||
|
|
||||||
setSortMethod(newMethod);
|
setSortMethod(newMethod);
|
||||||
setReverse(newReverse);
|
setReverse(newReverse);
|
||||||
|
setTimer(100);
|
||||||
await sortList(newMethod, newReverse);
|
|
||||||
};
|
|
||||||
|
|
||||||
const setFilterOwner = async () => {
|
|
||||||
const newMethod = 'owner';
|
|
||||||
const newReverse = sort_method === 'owner' ? !reverse : false;
|
|
||||||
|
|
||||||
setSortMethod(newMethod);
|
|
||||||
setReverse(newReverse);
|
|
||||||
|
|
||||||
await sortList(newMethod, newReverse);
|
|
||||||
};
|
|
||||||
|
|
||||||
const setFilterUptime = async () => {
|
|
||||||
const newMethod = 'update_time';
|
|
||||||
const newReverse = sort_method === 'update_time' ? !reverse : false;
|
|
||||||
|
|
||||||
setSortMethod(newMethod);
|
|
||||||
setReverse(newReverse);
|
|
||||||
|
|
||||||
await sortList(newMethod, newReverse);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createBoard = async () => {
|
const createBoard = async () => {
|
||||||
try {
|
try {
|
||||||
|
setLoading(true)
|
||||||
const newBoard = { title, description };
|
const newBoard = { title, description };
|
||||||
await axios.post('/api/boards/create', newBoard);
|
await axios.post('/api/boards/create', newBoard);
|
||||||
setShowCreateModal(false)
|
setShowCreateModal(false);
|
||||||
|
await loadBoardList();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError('Ошибка');
|
setError('Ошибка');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -159,25 +109,24 @@ const KBBoardsList = () => {
|
|||||||
{
|
{
|
||||||
error && <div className="error">{error}</div>
|
error && <div className="error">{error}</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className="kan-ban-list-sort">
|
<div className="kan-ban-list-sort">
|
||||||
<h3>Сортировка по:</h3>
|
<h3>Сортировка по:</h3>
|
||||||
<div className="nav-sort">
|
<div className="nav-sort">
|
||||||
<button onClick={setFilterTitle}>
|
<button onClick={setFilter('title')}>
|
||||||
Названию
|
Названию
|
||||||
</button>
|
</button>
|
||||||
<button onClick={setFilterOwner}>
|
<button onClick={setFilter('owner')}>
|
||||||
Создателю
|
Создателю
|
||||||
</button>
|
</button>
|
||||||
<button onClick={setFilterUptime}>
|
<button onClick={setFilter('update_time')}>
|
||||||
Дате обновления
|
Дате обновления
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Поиск по названию..."
|
placeholder="Поиск по названию..."
|
||||||
value={searchQuery}
|
value={search_text}
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
onChange={(e) => setSearchText(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="kan-ban-list">
|
<div className="kan-ban-list">
|
||||||
@@ -185,9 +134,9 @@ const KBBoardsList = () => {
|
|||||||
<h3>Доступные канбан доски:</h3>
|
<h3>Доступные канбан доски:</h3>
|
||||||
<button onClick={openCreateModal}>Создать канбан-доску</button>
|
<button onClick={openCreateModal}>Создать канбан-доску</button>
|
||||||
</div>
|
</div>
|
||||||
{filteredItems.length > 0 ? (
|
{items.length > 0 ? (
|
||||||
<ul>
|
<ul>
|
||||||
{filteredItems.map((item) => (
|
{items.map((item) => (
|
||||||
<ListItem key={item.id} item={item} />
|
<ListItem key={item.id} item={item} />
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user