diff --git a/VERSION b/VERSION
index 4d9fbcf..06edb38 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-4.25.0
+4.26.0
diff --git a/play-life-backend/main.go b/play-life-backend/main.go
index 45daf78..514c99e 100644
--- a/play-life-backend/main.go
+++ b/play-life-backend/main.go
@@ -8551,6 +8551,49 @@ 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(
+ ¤tRepetitionPeriod,
+ ¤tRepetitionDate,
+ ¤tNextShowAt,
+ )
+ 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 значений
var updateSQL string
var updateArgs []interface{}
@@ -8564,24 +8607,46 @@ func (a *App) updateTaskHandler(w http.ResponseWriter, r *http.Request) {
}
if repetitionPeriod.Valid {
- // Для repetition_period выставляем сегодняшнюю дату
- now := time.Now().In(loc)
+ // Для 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
`
- updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionPeriod.String, now, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
+ updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionPeriod.String, nextShowAtValue, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
} else if repetitionDate.Valid {
- // Вычисляем next_show_at для задачи с repetition_date
- nextShowAt := calculateNextShowAtFromRepetitionDate(repetitionDate.String, time.Now().In(loc))
- if nextShowAt != nil {
+ // Вычисляем 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, nextShowAt, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
+ updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, repetitionDate.String, nextShowAtValue, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
} else {
updateSQL = `
UPDATE tasks
@@ -8591,12 +8656,24 @@ func (a *App) updateTaskHandler(w http.ResponseWriter, r *http.Request) {
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 = NULL, wishlist_id = $4, reward_policy = $5, group_name = $6
- WHERE id = $7
+ 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
`
- updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
+ updateArgs = []interface{}{strings.TrimSpace(req.Name), rewardMessage, progressionBase, nextShowAtValue, newWishlistID, rewardPolicyValue, req.GroupName, taskID}
}
_, err = tx.Exec(updateSQL, updateArgs...)
diff --git a/play-life-web/package.json b/play-life-web/package.json
index faddf70..3113baf 100644
--- a/play-life-web/package.json
+++ b/play-life-web/package.json
@@ -1,6 +1,6 @@
{
"name": "play-life-web",
- "version": "4.25.0",
+ "version": "4.26.0",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/play-life-web/src/App.jsx b/play-life-web/src/App.jsx
index 3e7d4f4..3381669 100644
--- a/play-life-web/src/App.jsx
+++ b/play-life-web/src/App.jsx
@@ -104,6 +104,9 @@ function AppContent() {
// Модальное окно выбора типа задачи
const [showAddModal, setShowAddModal] = useState(false)
+
+ // Ref для функции открытия модала добавления записи в CurrentWeek
+ const currentWeekAddModalRef = useRef(null)
// Кеширование данных
const [currentWeekData, setCurrentWeekData] = useState(null)
@@ -995,6 +998,9 @@ function AppContent() {
onRetry={fetchCurrentWeekData}
allProjectsData={fullStatisticsData}
onNavigate={handleNavigate}
+ onOpenAddModal={(setOpenFn) => {
+ currentWeekAddModalRef.current = setOpenFn
+ }}
/>
@@ -1206,7 +1212,10 @@ function AppContent() {
{loadedTabs.tracking && (
)}
@@ -1290,6 +1299,32 @@ function AppContent() {
)}
+ {/* Кнопка добавления записи (только для таба current - экран прогресса) */}
+ {!isFullscreenTab && activeTab === 'current' && (
+
+ )}
+
{/* Кнопка добавления словаря (только для таба dictionaries) */}
{activeTab === 'dictionaries' && (