feat: add delete account button in settings, implement all remaining achievements
All checks were successful
CI / build (push) Successful in 37s

- Add delete all data button with red danger style and confirmation prompt
- Add DeleteUserData repo method that wipes user from all tables in a transaction
- Add helper methods deleteAccountPrompt and deleteAccountConfirm
- Implement consistency_master, perfect_week, remote_veteran, onsite_master achievements
- Add GetDailyXPInRange and SumWorkSecondsByWorkType repo methods
- Update Dockerfile to alpine3.23, docker-compose to use env vars for proxy/paths
This commit is contained in:
2026-06-25 12:27:03 +03:30
parent 0926323d18
commit 5670b0455d
7 changed files with 185 additions and 8 deletions

View File

@@ -241,6 +241,9 @@ func (h *Handler) checkAchievements(userID int64, stats *domain.RPGStats, workSe
h.checkHourAchievements(u, stats, totalHours)
h.checkSessionAchievements(u, workSeconds, isWeekend)
h.checkLevelAchievements(u, stats)
h.checkConsistencyAchievements(u, userID, date)
h.checkPerfectWeekAchievements(u, userID, date)
h.checkWorkTypeAchievements(u, userID)
return u.unlocked
}
@@ -334,3 +337,63 @@ func (h *Handler) checkLevelAchievements(u *achievementUnlocker, stats *domain.R
u.unlock("level_50")
}
}
func (h *Handler) checkConsistencyAchievements(u *achievementUnlocker, userID int64, today string) {
t, err := time.Parse(domain.DateLayout, today)
if err != nil {
return
}
sevenDaysAgo := t.AddDate(0, 0, -7).Format(domain.DateLayout)
yesterday := t.AddDate(0, 0, -1).Format(domain.DateLayout)
records, err := h.Repo.GetDailyXPInRange(userID, sevenDaysAgo, yesterday)
if err != nil {
return
}
if len(records) < 7 {
return
}
allHaveSixHours := true
for _, r := range records {
if r.WorkSeconds < 6*domain.SecondsPerHour {
allHaveSixHours = false
break
}
}
if allHaveSixHours {
u.unlock("consistency_master")
}
}
func (h *Handler) checkPerfectWeekAchievements(u *achievementUnlocker, userID int64, today string) {
t, err := time.Parse(domain.DateLayout, today)
if err != nil {
return
}
start := t.AddDate(0, 0, -6).Format(domain.DateLayout)
days, err := h.Repo.GetUserDaysInRange(userID, start, today)
if err != nil {
return
}
if len(days) < 7 {
return
}
for _, d := range days {
if d.IsDayOff {
return
}
}
u.unlock("perfect_week")
}
func (h *Handler) checkWorkTypeAchievements(u *achievementUnlocker, userID int64) {
rem, ons, err := h.Repo.SumWorkSecondsByWorkType(userID)
if err != nil {
return
}
if rem >= 100*domain.SecondsPerHour {
u.unlock("remote_veteran")
}
if ons >= 100*domain.SecondsPerHour {
u.unlock("onsite_master")
}
}