4.19.0: Добавлены позиции подзадач
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m34s

This commit is contained in:
poignatov
2026-02-04 21:21:07 +03:00
parent 09ab87b6dd
commit a60bfe97dc
7 changed files with 203 additions and 18 deletions

View File

@@ -261,6 +261,46 @@
margin-bottom: 0.75rem;
}
.subtask-position-controls {
display: flex;
flex-direction: column;
gap: 0.25rem;
flex-shrink: 0;
}
.move-subtask-button {
padding: 0.25rem;
background: #f3f4f6;
color: #6b7280;
border: 1px solid #d1d5db;
border-radius: 0.25rem;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
width: 2rem;
height: 1.75rem;
flex-shrink: 0;
}
.move-subtask-button:hover:not(:disabled) {
background: #e5e7eb;
border-color: #9ca3af;
color: #374151;
}
.move-subtask-button:disabled {
opacity: 0.4;
cursor: not-allowed;
background: #f9fafb;
}
.move-subtask-button:focus {
outline: none;
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
}
.subtask-name-input {
flex: 1;
margin-bottom: 0;

View File

@@ -313,10 +313,11 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
// Для задач-тестов не загружаем подзадачи
setSubtasks([])
} else {
setSubtasks(data.subtasks.map(st => ({
setSubtasks(data.subtasks.map((st, index) => ({
id: st.task.id,
name: st.task.name || '',
reward_message: st.task.reward_message || '',
position: st.task.position !== undefined && st.task.position !== null ? st.task.position : index,
rewards: st.rewards.map(r => ({
position: r.position,
project_name: r.project_name,
@@ -483,6 +484,7 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
id: null,
name: '',
reward_message: '',
position: subtasks.length,
rewards: []
}])
}
@@ -520,7 +522,38 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
}
const handleRemoveSubtask = (index) => {
setSubtasks(subtasks.filter((_, i) => i !== index))
const newSubtasks = subtasks.filter((_, i) => i !== index)
// Пересчитываем позиции после удаления
newSubtasks.forEach((st, i) => {
st.position = i
})
setSubtasks(newSubtasks)
}
const handleMoveSubtaskUp = (index) => {
if (index === 0) return // Нельзя переместить первый элемент вверх
const newSubtasks = [...subtasks]
const temp = newSubtasks[index]
newSubtasks[index] = newSubtasks[index - 1]
newSubtasks[index - 1] = temp
// Обновляем позиции
newSubtasks.forEach((st, i) => {
st.position = i
})
setSubtasks(newSubtasks)
}
const handleMoveSubtaskDown = (index) => {
if (index === subtasks.length - 1) return // Нельзя переместить последний элемент вниз
const newSubtasks = [...subtasks]
const temp = newSubtasks[index]
newSubtasks[index] = newSubtasks[index + 1]
newSubtasks[index + 1] = temp
// Обновляем позиции
newSubtasks.forEach((st, i) => {
st.position = i
})
setSubtasks(newSubtasks)
}
const handleSubmit = async (e) => {
@@ -657,10 +690,11 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
value: parseFloat(r.value) || 0,
use_progression: !!(progressionBase && r.use_progression)
})),
subtasks: isTest ? [] : subtasks.map(st => ({
subtasks: isTest ? [] : subtasks.map((st, index) => ({
id: st.id || undefined,
name: st.name.trim() || null,
reward_message: st.reward_message.trim() || null,
position: st.position !== undefined && st.position !== null ? st.position : index,
rewards: st.rewards.map(r => ({
position: r.position,
project_name: r.project_name.trim(),
@@ -1073,6 +1107,30 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
{subtasks.map((subtask, index) => (
<div key={index} className="subtask-form-item">
<div className="subtask-header-row">
<div className="subtask-position-controls">
<button
type="button"
onClick={() => handleMoveSubtaskUp(index)}
className="move-subtask-button"
disabled={index === 0}
title="Переместить вверх"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<polyline points="18 15 12 9 6 15"></polyline>
</svg>
</button>
<button
type="button"
onClick={() => handleMoveSubtaskDown(index)}
className="move-subtask-button"
disabled={index === subtasks.length - 1}
title="Переместить вниз"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<input
type="text"
value={subtask.name}