feat: добавлен раздел 'Бесконечные' для задач с периодичностью 0
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 45s

This commit is contained in:
poignatov
2026-01-06 14:31:00 +03:00
parent a6065d7ff1
commit 647c549ec9
3 changed files with 63 additions and 9 deletions

View File

@@ -1 +1 @@
2.9.1 2.10.0

View File

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

View File

@@ -15,6 +15,15 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, onRefresh }) {
const [selectedTaskForDetail, setSelectedTaskForDetail] = useState(null) const [selectedTaskForDetail, setSelectedTaskForDetail] = useState(null)
const [isCompleting, setIsCompleting] = useState(false) const [isCompleting, setIsCompleting] = useState(false)
const [expandedCompleted, setExpandedCompleted] = useState({}) const [expandedCompleted, setExpandedCompleted] = useState({})
// Загружаем состояние раскрытия "Бесконечные" из localStorage (по умолчанию true)
const [expandedInfinite, setExpandedInfinite] = useState(() => {
try {
const saved = localStorage.getItem('taskList_expandedInfinite')
return saved ? JSON.parse(saved) : {}
} catch {
return {}
}
})
const [toast, setToast] = useState(null) const [toast, setToast] = useState(null)
// Для отслеживания изменений в списке задач (чтобы не перезагружать детали без необходимости) // Для отслеживания изменений в списке задач (чтобы не перезагружать детали без необходимости)
@@ -149,6 +158,22 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, onRefresh }) {
})) }))
} }
const toggleInfiniteExpanded = (projectName) => {
setExpandedInfinite(prev => {
const newState = {
...prev,
[projectName]: !prev[projectName]
}
// Сохраняем в localStorage
try {
localStorage.setItem('taskList_expandedInfinite', JSON.stringify(newState))
} catch (err) {
console.error('Error saving expandedInfinite to localStorage:', err)
}
return newState
})
}
// Получаем все проекты из наград задачи и подзадач // Получаем все проекты из наград задачи и подзадач
const getTaskProjects = (task) => { const getTaskProjects = (task) => {
const projects = new Set() const projects = new Set()
@@ -256,9 +281,11 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, onRefresh }) {
// Определяем, в какую группу попадает задача // Определяем, в какую группу попадает задача
let isCompleted = false let isCompleted = false
let isInfinite = false
// Если у задачи период повторения = 0, она всегда в невыполненных // Если у задачи период повторения = 0, она в бесконечных
if (task.repetition_period && isZeroPeriod(task.repetition_period)) { if (task.repetition_period && isZeroPeriod(task.repetition_period)) {
isInfinite = true
isCompleted = false isCompleted = false
} else if (task.repetition_period) { } else if (task.repetition_period) {
// Если есть repetition_period (и он не 0), проверяем логику повторения // Если есть repetition_period (и он не 0), проверяем логику повторения
@@ -297,11 +324,14 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, onRefresh }) {
if (!groups[projectName]) { if (!groups[projectName]) {
groups[projectName] = { groups[projectName] = {
notCompleted: [], notCompleted: [],
completed: [] completed: [],
infinite: []
} }
} }
if (isCompleted) { if (isInfinite) {
groups[projectName].infinite.push(task)
} else if (isCompleted) {
groups[projectName].completed.push(task) groups[projectName].completed.push(task)
} else { } else {
groups[projectName].notCompleted.push(task) groups[projectName].notCompleted.push(task)
@@ -391,7 +421,12 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, onRefresh }) {
{projectNames.map(projectName => { {projectNames.map(projectName => {
const group = groupedTasks[projectName] const group = groupedTasks[projectName]
const hasCompleted = group.completed.length > 0 const hasCompleted = group.completed.length > 0
const isExpanded = expandedCompleted[projectName] const hasInfinite = group.infinite.length > 0
const isCompletedExpanded = expandedCompleted[projectName]
// По умолчанию бесконечные раскрыты (true), если не сохранено иное
const isInfiniteExpanded = expandedInfinite[projectName] !== undefined
? expandedInfinite[projectName]
: true
return ( return (
<div key={projectName} className="project-group"> <div key={projectName} className="project-group">
@@ -405,6 +440,25 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, onRefresh }) {
</div> </div>
)} )}
{hasInfinite && (
<div className="completed-section">
<button
className="completed-toggle"
onClick={() => toggleInfiniteExpanded(projectName)}
>
<span className="completed-toggle-icon">
{isInfiniteExpanded ? '▼' : '▶'}
</span>
<span>Бесконечные ({group.infinite.length})</span>
</button>
{isInfiniteExpanded && (
<div className="task-group completed-tasks">
{group.infinite.map(renderTaskItem)}
</div>
)}
</div>
)}
{hasCompleted && ( {hasCompleted && (
<div className="completed-section"> <div className="completed-section">
<button <button
@@ -412,11 +466,11 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, onRefresh }) {
onClick={() => toggleCompletedExpanded(projectName)} onClick={() => toggleCompletedExpanded(projectName)}
> >
<span className="completed-toggle-icon"> <span className="completed-toggle-icon">
{isExpanded ? '▼' : '▶'} {isCompletedExpanded ? '▼' : '▶'}
</span> </span>
<span>Выполненные ({group.completed.length})</span> <span>Выполненные ({group.completed.length})</span>
</button> </button>
{isExpanded && ( {isCompletedExpanded && (
<div className="task-group completed-tasks"> <div className="task-group completed-tasks">
{group.completed.map(renderTaskItem)} {group.completed.map(renderTaskItem)}
</div> </div>
@@ -424,7 +478,7 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, onRefresh }) {
</div> </div>
)} )}
{group.notCompleted.length === 0 && !hasCompleted && ( {group.notCompleted.length === 0 && !hasCompleted && !hasInfinite && (
<div className="empty-group">Нет задач в этой группе</div> <div className="empty-group">Нет задач в этой группе</div>
)} )}
</div> </div>