fix:Отображение задач и страницы
Пофикшено отображение задач для неавторизованных и авторизованных пользователей. Так же пофикшено отображение информации на сайте. Пофикшено отображение "отсутсвия задач" пока пользователь незалогинен.
This commit is contained in:
144
src/Mainpage.js
144
src/Mainpage.js
@@ -1,103 +1,107 @@
|
|||||||
import {useEffect, useState} from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import Header from './Header';
|
import Header from './Header';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
import './css/Mainpage.css';
|
import './css/Mainpage.css';
|
||||||
|
|
||||||
const Mainpage = () => {
|
const Mainpage = () => {
|
||||||
const [tasks, setTasks] = useState([]);
|
const [tasks, setTasks] = useState([]);
|
||||||
const [error_message, setErrorMessage] = useState(null);
|
const [errorMessage, setErrorMessage] = useState(null);
|
||||||
const [count, setCount] = useState(0);
|
const [count, setCount] = useState(0);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const checkSession = async () => {
|
const checkSession = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get('/api/users/my_tasks');
|
const response = await axios.get('/api/users/my_tasks');
|
||||||
|
|
||||||
// если нет ошибки — пользователь авторизован
|
|
||||||
setTasks(response.data.tasks || []);
|
setTasks(response.data.tasks || []);
|
||||||
setCount(response.data.count || 0);
|
setCount(response.data.count || 0);
|
||||||
setErrorMessage('');
|
setErrorMessage(null);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const message = err.response?.data?.message || 'Ошибка авторизации';
|
const message = err.response?.data?.message || 'Ошибка авторизации';
|
||||||
setErrorMessage(message);
|
setErrorMessage(message);
|
||||||
}
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
checkSession();
|
checkSession();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const isAuthenticated = !error_message;
|
const isAuthenticated = !errorMessage;
|
||||||
|
|
||||||
|
const formatDeadline = (deadline) => {
|
||||||
|
if (!deadline) return 'Отсутствует';
|
||||||
|
const d = new Date(deadline);
|
||||||
|
const day = String(d.getDate()).padStart(2, '0');
|
||||||
|
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||||
|
const year = d.getFullYear();
|
||||||
|
return `${day}.${month}.${year}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTaskClick = (boardId) => {
|
||||||
|
navigate(`/kanban-board/${boardId}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showScrollbar = count > 3;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header/>
|
<Header />
|
||||||
<div className="content-wrapper">
|
<div className="mainpage">
|
||||||
{!isAuthenticated && (
|
<div className="mainpage__intro">
|
||||||
<div className="main-layout">
|
<div className="left-content">
|
||||||
<div>
|
<h1>Kanban-доска Fool-Stack</h1>
|
||||||
|
<p>
|
||||||
<h2 className="margin">
|
Kanban-доска помогает видеть весь процесс целиком: что запланировано, что уже в работе и что готово.
|
||||||
Наведите порядок в задачах за минуту
|
Перетаскивайте карточки между колонками, фиксируйте договорённости и не теряйте контекст — всё в одном месте.
|
||||||
</h2>
|
</p>
|
||||||
|
|
||||||
<p className="com">
|
|
||||||
Kanban-доска помогает видеть весь процесс целиком: что запланировано,
|
|
||||||
что уже в работе и что готово. Перетаскивайте карточки между колонками,
|
|
||||||
фиксируйте договорённости и не теряйте контекст — всё в одном месте.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 style={{ marginTop: "30px" }}>
|
|
||||||
Как это работает:
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<ul className="com">
|
|
||||||
<li>
|
|
||||||
Создайте карточку с задачей, добавьте описание и сроки.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Перемещайте её по этапам <strong>Сделать → В работе → Готово</strong>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Смотрите прогресс по команде и быстро находите узкие места.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 style={{ marginTop: "30px" }}>
|
|
||||||
Начните сейчас
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<p className="com">
|
|
||||||
Войдите или зарегистрируйтесь, чтобы сохранять доски, открывать доступ
|
|
||||||
коллегам и синхронизировать задачи между устройствами.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{isAuthenticated && (
|
<div className="tasks-container">
|
||||||
<div className="main-layout">
|
{loading ? (
|
||||||
<div className="tasks-box">
|
<>
|
||||||
<h3>Задачи ({count})</h3>
|
<h3 className="tasks-title">Ваши задачи</h3>
|
||||||
|
<p>Загрузка...</p>
|
||||||
{tasks.length > 0 ? (
|
</>
|
||||||
<ul>
|
) : isAuthenticated ? (
|
||||||
{tasks.map((task, index) => (
|
<>
|
||||||
<li key={index}>
|
<h3 className="tasks-title">Ваши задачи</h3>
|
||||||
{task.title || task.name || `Задача ${index + 1}`}
|
{count === 0 ? (
|
||||||
</li>
|
<p>Нет задач</p>
|
||||||
))}
|
) : (
|
||||||
</ul>
|
<div
|
||||||
) : (
|
className={`tasks-list-wrapper ${showScrollbar ? 'scrollable' : ''}`}
|
||||||
<p>Нет задач</p>
|
>
|
||||||
)}
|
<ul className="tasks-list">
|
||||||
</div>
|
{tasks.map((task) => (
|
||||||
|
<li
|
||||||
|
key={task.id}
|
||||||
|
className="task-item"
|
||||||
|
onClick={() => handleTaskClick(task.board_id)}
|
||||||
|
>
|
||||||
|
<div><strong>{task.title}</strong></div>
|
||||||
|
<div><strong>Доска:</strong> {task.board_title}</div>
|
||||||
|
<div><strong>Дедлайн:</strong> {formatDeadline(task.deadline)}</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<h3 className="tasks-title">Ваши задачи</h3>
|
||||||
|
<p>Войдите, чтобы увидеть свои задачи.</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Mainpage;
|
export default Mainpage;
|
||||||
|
//TODO: проверка правильности отображения даты в отображении
|
||||||
@@ -1,53 +1,102 @@
|
|||||||
.content-wrapper{
|
.mainpage {
|
||||||
transition: all .4s ease;
|
transition: all .4s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-layout {
|
.mainpage__intro {
|
||||||
background-color: #1f2430;
|
background-color: #1f2430;
|
||||||
border-radius: 8px;
|
border-radius: 6px;
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-content {
|
.left-content {
|
||||||
flex: 1;
|
flex: 0 0 60%; /* Сжата справа, чтобы tasks расширился в центр */
|
||||||
text-align: left; /* Выравнивание текста слева */
|
text-align: left;
|
||||||
|
background-color: #2b3245;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-content h1,
|
.left-content h1,
|
||||||
.left-content p,
|
.left-content p,
|
||||||
.left-content li {
|
.left-content li {
|
||||||
|
margin: 6px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: #CAD1D8;
|
color: #CAD1D8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tasks-box {
|
.tasks-container {
|
||||||
flex: 0 0 300px; /* Фиксированная ширина бокса справа */
|
flex: 0 0 400px; /* Расширено влево к центру */
|
||||||
background-color: #33404d;
|
background-color: #2b3245;
|
||||||
border-radius: 8px;
|
border-radius: 6px;
|
||||||
padding: 20px;
|
padding: 10px;
|
||||||
border: 1px solid #999;
|
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tasks-box h3 {
|
/* Остальной CSS без изменений */
|
||||||
margin-top: 0;
|
.tasks-title {
|
||||||
|
margin: 0 0 15px 0;
|
||||||
color: #CAD1D8;
|
color: #CAD1D8;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
background-color: #2b3245;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tasks-box ul {
|
.tasks-list {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
max-height: 250px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tasks-box li {
|
.tasks-list::-webkit-scrollbar {
|
||||||
background-color: #1f2430;
|
width: 8px;
|
||||||
margin-bottom: 10px;
|
}
|
||||||
padding: 10px;
|
|
||||||
border-radius: 4px;
|
.tasks-list::-webkit-scrollbar-track {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tasks-list::-webkit-scrollbar-thumb {
|
||||||
|
background: #aaa;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tasks-list::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-item {
|
||||||
|
background-color: #3d4763;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 8px;
|
||||||
color: #CAD1D8;
|
color: #CAD1D8;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-item:hover {
|
||||||
|
background-color: #4a587e;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user