4.10.0: Добавлен поиск задач с иконкой
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m1s

This commit is contained in:
poignatov
2026-02-03 16:10:38 +03:00
parent 0162db46b3
commit b65dc30a9b
4 changed files with 108 additions and 4 deletions

View File

@@ -1 +1 @@
4.9.0 4.10.0

View File

@@ -1,6 +1,6 @@
{ {
"name": "play-life-web", "name": "play-life-web",
"version": "4.9.0", "version": "4.10.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@@ -4,6 +4,68 @@
padding-bottom: 2.5rem; /* Отступ для фиксированной кнопки добавления */ padding-bottom: 2.5rem; /* Отступ для фиксированной кнопки добавления */
} }
.task-search-container {
position: relative;
margin-bottom: 1.5rem;
}
.task-search-icon {
position: absolute;
left: 0.75rem;
top: 50%;
transform: translateY(-50%);
color: #9ca3af;
pointer-events: none;
z-index: 1;
}
.task-search-input {
width: 100%;
padding: 0.75rem 2.5rem 0.75rem 2.75rem;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
font-size: 1rem;
background: white;
color: #1f2937;
transition: all 0.2s;
}
.task-search-input:focus {
outline: none;
border-color: #6366f1;
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
}
.task-search-input::placeholder {
color: #9ca3af;
}
.task-search-clear {
position: absolute;
right: 0.75rem;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: #9ca3af;
cursor: pointer;
padding: 0.25rem;
font-size: 1.125rem;
line-height: 1;
border-radius: 0.25rem;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
}
.task-search-clear:hover {
background: #f3f4f6;
color: #1f2937;
}
.add-task-button { .add-task-button {
width: 100%; width: 100%;
padding: 0.75rem 1rem; padding: 0.75rem 1rem;

View File

@@ -18,6 +18,7 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
const [postponeDate, setPostponeDate] = useState('') const [postponeDate, setPostponeDate] = useState('')
const [isPostponing, setIsPostponing] = useState(false) const [isPostponing, setIsPostponing] = useState(false)
const [toast, setToast] = useState(null) const [toast, setToast] = useState(null)
const [searchQuery, setSearchQuery] = useState('')
const dateInputRef = useRef(null) const dateInputRef = useRef(null)
useEffect(() => { useEffect(() => {
@@ -443,9 +444,16 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
const today = new Date() const today = new Date()
today.setHours(0, 0, 0, 0) today.setHours(0, 0, 0, 0)
// Фильтруем задачи по поисковому запросу
const filteredTasks = searchQuery.trim()
? tasks.filter(task =>
task.name.toLowerCase().includes(searchQuery.toLowerCase())
)
: tasks
const groups = {} const groups = {}
tasks.forEach(task => { filteredTasks.forEach(task => {
const projects = getTaskProjects(task) const projects = getTaskProjects(task)
// Если у задачи нет проектов, добавляем в группу "Без проекта" // Если у задачи нет проектов, добавляем в группу "Без проекта"
@@ -534,7 +542,7 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
}) })
return groups return groups
}, [tasks]) }, [tasks, searchQuery])
// Сортируем проекты: сначала с невыполненными задачами, потом без них // Сортируем проекты: сначала с невыполненными задачами, потом без них
// Группа "Без проекта" всегда последняя в своей категории // Группа "Без проекта" всегда последняя в своей категории
@@ -813,6 +821,40 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
/> />
)} )}
{/* Поле поиска */}
<div className="task-search-container">
<svg
className="task-search-icon"
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
<input
type="text"
className="task-search-input"
placeholder="Поиск задач..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
{searchQuery && (
<button
className="task-search-clear"
onClick={() => setSearchQuery('')}
title="Очистить поиск"
>
</button>
)}
</div>
{projectNames.length === 0 && !loading && tasks.length === 0 && ( {projectNames.length === 0 && !loading && tasks.length === 0 && (
<div className="empty-state"> <div className="empty-state">
<p>Задач пока нет. Добавьте задачу через кнопку "Добавить".</p> <p>Задач пока нет. Добавьте задачу через кнопку "Добавить".</p>