5.0.1: Группа в форме задачи, next_show_at не меняется при редакт.
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m41s

This commit is contained in:
poignatov
2026-02-09 14:16:57 +03:00
parent b05bd51b5b
commit 5b53615d1a
5 changed files with 14 additions and 117 deletions

View File

@@ -1 +1 @@
5.0.0
5.0.1

View File

@@ -8708,129 +8708,31 @@ func (a *App) updateTaskHandler(w http.ResponseWriter, r *http.Request) {
rewardPolicyValue = nil // NULL для задач, не связанных с желаниями
}
// Получаем текущие значения repetition_period, repetition_date и next_show_at из БД
// для проверки, изменились ли поля повторения
var currentRepetitionPeriod sql.NullString
var currentRepetitionDate sql.NullString
var currentNextShowAt sql.NullTime
err = a.DB.QueryRow("SELECT repetition_period, repetition_date, next_show_at FROM tasks WHERE id = $1", taskID).Scan(
&currentRepetitionPeriod,
&currentRepetitionDate,
&currentNextShowAt,
)
if err != nil {
log.Printf("Error getting current repetition values: %v", err)
sendErrorWithCORS(w, fmt.Sprintf("Error getting task: %v", err), http.StatusInternalServerError)
return
}
// Проверяем, изменились ли поля повторения
repetitionChanged := false
if repetitionPeriod.Valid {
// Новое значение есть - проверяем, отличается ли от текущего
if !currentRepetitionPeriod.Valid || currentRepetitionPeriod.String != repetitionPeriod.String {
repetitionChanged = true
}
// Также проверяем, что текущее repetition_date было не NULL (если было, значит изменился тип повторения)
if currentRepetitionDate.Valid {
repetitionChanged = true
}
} else if repetitionDate.Valid {
// Новое значение есть - проверяем, отличается ли от текущего
if !currentRepetitionDate.Valid || currentRepetitionDate.String != repetitionDate.String {
repetitionChanged = true
}
// Также проверяем, что текущее repetition_period было не NULL (если было, значит изменился тип повторения)
if currentRepetitionPeriod.Valid {
repetitionChanged = true
}
} else {
// Оба поля NULL - проверяем, были ли они NULL до этого
if currentRepetitionPeriod.Valid || currentRepetitionDate.Valid {
repetitionChanged = true
}
}
// Используем условный SQL для обработки NULL значений
// Обновляем задачу без изменения next_show_at (он меняется только при завершении/откладывании)
var updateSQL string
var updateArgs []interface{}
// Получаем часовой пояс из переменной окружения (по умолчанию UTC)
timezoneStr := getEnv("TIMEZONE", "UTC")
loc, err := time.LoadLocation(timezoneStr)
if err != nil {
log.Printf("Warning: Invalid timezone '%s': %v. Using UTC instead.", timezoneStr, err)
loc = time.UTC
}
if repetitionPeriod.Valid {
// Для repetition_period выставляем сегодняшнюю дату только если поле изменилось
var nextShowAtValue interface{}
if repetitionChanged {
now := time.Now().In(loc)
nextShowAtValue = now
} else {
// Поле не изменилось - сохраняем текущее значение next_show_at
if currentNextShowAt.Valid {
nextShowAtValue = currentNextShowAt.Time
} else {
nextShowAtValue = nil
}
}
updateSQL = `
UPDATE tasks
SET name = $1, reward_message = $2, progression_base = $3, repetition_period = $4::INTERVAL, repetition_date = NULL, next_show_at = $5, wishlist_id = $6, reward_policy = $7, group_name = $8
WHERE id = $9
SET name = $1, reward_message = $2, progression_base = $3, repetition_period = $4::INTERVAL, repetition_date = NULL, wishlist_id = $5, reward_policy = $6, group_name = $7
WHERE id = $8
`
updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionPeriod.String, nextShowAtValue, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionPeriod.String, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
} else if repetitionDate.Valid {
// Вычисляем next_show_at для задачи с repetition_date только если поле изменилось
var nextShowAtValue interface{}
if repetitionChanged {
nextShowAt := calculateNextShowAtFromRepetitionDate(repetitionDate.String, time.Now().In(loc))
nextShowAtValue = nextShowAt
} else {
// Поле не изменилось - сохраняем текущее значение next_show_at
if currentNextShowAt.Valid {
nextShowAtValue = currentNextShowAt.Time
} else {
nextShowAtValue = nil
}
}
if nextShowAtValue != nil {
updateSQL = `
UPDATE tasks
SET name = $1, reward_message = $2, progression_base = $3, repetition_period = NULL, repetition_date = $4, next_show_at = $5, wishlist_id = $6, reward_policy = $7, group_name = $8
WHERE id = $9
`
updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionDate.String, nextShowAtValue, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
} else {
updateSQL = `
UPDATE tasks
SET name = $1, reward_message = $2, progression_base = $3, repetition_period = NULL, repetition_date = $4, wishlist_id = $5, reward_policy = $6, group_name = $7
WHERE id = $8
`
updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionDate.String, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
}
} else {
// Оба поля NULL - устанавливаем next_show_at в NULL только если поля повторения изменились
var nextShowAtValue interface{}
if repetitionChanged {
nextShowAtValue = nil
} else {
// Поля не изменились - сохраняем текущее значение next_show_at
if currentNextShowAt.Valid {
nextShowAtValue = currentNextShowAt.Time
} else {
nextShowAtValue = nil
}
}
updateSQL = `
UPDATE tasks
SET name = $1, reward_message = $2, progression_base = $3, repetition_period = NULL, repetition_date = NULL, next_show_at = $4, wishlist_id = $5, reward_policy = $6, group_name = $7
WHERE id = $8
SET name = $1, reward_message = $2, progression_base = $3, repetition_period = NULL, repetition_date = NULL, wishlist_id = $4, reward_policy = $5, group_name = $6
WHERE id = $7
`
updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, nextShowAtValue, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
}
_, err = tx.Exec(updateSQL, updateArgs...)

Binary file not shown.

View File

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

View File

@@ -95,6 +95,7 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
setRepetitionMode('after')
setRewards([])
setSubtasks([])
setGroupName('')
setError('')
setLoadingTask(false)
// Reset test-specific fields
@@ -159,6 +160,7 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
setName(data.task.name)
setRewardMessage(data.task.reward_message || '')
setProgressionBase(data.task.progression_base ? String(data.task.progression_base) : '')
setGroupName(data.task.group_name ?? '')
// Проверяем, является ли задача бесконечной (оба поля = 0)
const periodStr = data.task.repetition_period ? data.task.repetition_period.trim() : ''
@@ -368,13 +370,6 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
} else {
setRewardPolicy('personal') // Значение по умолчанию
}
// Загружаем группу
if (data.task.group_name) {
setGroupName(data.task.group_name)
} else {
setGroupName('')
}
} else {
setCurrentWishlistId(null)
setWishlistInfo(null)