From 23b536c2440f9eac179cdd92f38105829d1b2a19 Mon Sep 17 00:00:00 2001 From: Vladiysss <139554971+Vladiysss@users.noreply.github.com> Date: Wed, 4 Feb 2026 01:14:55 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=81=D0=BE=D1=80=D1=82=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=B8=20=D0=BE=D0=BF=D1=82=D0=B8=D0=BC=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 41 ----------- src/KBBoardsList.js | 171 ++++++++++++++++---------------------------- 2 files changed, 60 insertions(+), 152 deletions(-) delete mode 100644 package.json diff --git a/package.json b/package.json deleted file mode 100644 index a474ea0..0000000 --- a/package.json +++ /dev/null @@ -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" - ] - } -} diff --git a/src/KBBoardsList.js b/src/KBBoardsList.js index a2cf204..87de0c4 100644 --- a/src/KBBoardsList.js +++ b/src/KBBoardsList.js @@ -1,151 +1,101 @@ -import React, { useState, useEffect, useRef } from 'react'; +import { useState, useEffect, useRef, useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; import axios from 'axios'; import Header from './Header'; -function ListItem({ item }) { - const navigate = useNavigate(); - if (!item) return null; - - const openBoard = () => { navigate('/kanban-board/' + item.id); }; - - return ( -
  • - -
  • - ); -}; - 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 [list, setList] = useState(20); + 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 { + function ListItem({ item }) { + if (!item) return null; + const openBoard = () => { navigate('/kanban-board/' + item.id); }; + return ( +
  • + +
  • + ); + }; + + const loadBoardList = useCallback(async () => { + clearTimeout(debounceRef.current); + try { + debounceRef.current = setTimeout(async () => { var newList = { sort_method, reverse, search_text, page, list }; 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)) { - setItems(response.data); - } else { - setItems([]); - if (response.data?.detail === 'Доски отсутствуют.') { - console.log('Доски отсутствуют'); - } - } + setTimer(400) + }, timer); } catch (err) { if (err.response?.data?.message === 'Token Error' || err.response?.data?.message === 'Invalid Token') { setError('Вы не авторизованы'); setTimeout(() => { - window.location.href = '/login'; - }, 1500); + navigate('/login'); + }, 1000); } else { setError('Ошибка загрузки досок'); console.log(err); setItems([]); } } - }; + }, [sort_method, reverse, search_text, page, list, timer, setItems, setError, navigate]); - const setFilterTitle = async () => { - const newMethod = 'title'; - const newReverse = sort_method === 'title' ? !reverse : false; + useEffect(() => { + loadBoardList(); + }, [loadBoardList]); + + const setFilter = (method) => () => { + const newMethod = method; + const newReverse = sort_method === method ? !reverse : false; setSortMethod(newMethod); setReverse(newReverse); - - 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); + setTimer(100); }; const createBoard = async () => { try { + setLoading(true) const newBoard = { title, description }; await axios.post('/api/boards/create', newBoard); - setShowCreateModal(false) + setShowCreateModal(false); + await loadBoardList(); } catch (err) { setError('Ошибка'); + } finally { + setLoading(false); + } }; @@ -159,25 +109,24 @@ const KBBoardsList = () => { { error &&
    {error}
    } -

    Сортировка по:

    - - -
    setSearchQuery(e.target.value)} + value={search_text} + onChange={(e) => setSearchText(e.target.value)} />
    @@ -185,9 +134,9 @@ const KBBoardsList = () => {

    Доступные канбан доски:

    - {filteredItems.length > 0 ? ( + {items.length > 0 ? (