Reworked 'Levels' for progress

This commit is contained in:
2026-01-10 17:05:43 +01:00
parent 2c99454951
commit febb7ae87b
7 changed files with 241 additions and 14 deletions

View File

@@ -5,23 +5,63 @@ from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import datetime
import numpy as np
from utils import parse_float, get_bmi_status, get_bmi_icon
from gamification import get_level_info, get_level_title, GamificationManager, get_weight_loss_object
class DashboardFrame(ctk.CTkFrame):
def __init__(self, master, db: Database):
super().__init__(master)
self.db = db
self.profile = self.db.get_user_profile()
self.gm = GamificationManager(self.db)
self.setup_ui()
# Check for achievements on load
self.check_new_achievements()
def check_new_achievements(self):
new_unlocks = self.gm.check_achievements()
if new_unlocks:
for ach in new_unlocks:
self.show_achievement_popup(ach)
# Refresh profile to get new XP
self.profile = self.db.get_user_profile()
self.setup_ui() # Refresh UI to show new level
def show_achievement_popup(self, achievement):
# A simple top-level window or just a print for now
# In a real app, a nice overlay
print(f"ACHIEVEMENT UNLOCKED: {achievement['name']}")
def setup_ui(self):
self.clear_ui()
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(2, weight=1)
self.grid_rowconfigure(3, weight=1)
# Header
self.header = ctk.CTkLabel(self, text="Status & Prognosis", font=ctk.CTkFont(size=24, weight="bold"))
self.header.grid(row=0, column=0, pady=20, sticky="n")
# --- Header with Level ---
self.header_frame = ctk.CTkFrame(self, fg_color="transparent")
self.header_frame.grid(row=0, column=0, pady=20, sticky="ew", padx=20)
# Calculate Level
xp = self.profile['total_xp'] if self.profile else 0
level, curr_xp, req_xp = get_level_info(xp)
title = get_level_title(level)
progress_pct = curr_xp / req_xp
# Left: Title
ctk.CTkLabel(self.header_frame, text="Status & Prognosis", font=ctk.CTkFont(size=24, weight="bold")).pack(side="left")
# Right: Level Info
lvl_frame = ctk.CTkFrame(self.header_frame, fg_color="transparent")
lvl_frame.pack(side="right")
ctk.CTkLabel(lvl_frame, text=f"{title} (Lvl {level})", font=ctk.CTkFont(size=14, weight="bold")).pack(anchor="e")
prog_bar = ctk.CTkProgressBar(lvl_frame, width=150, height=10)
prog_bar.pack(pady=5)
prog_bar.set(progress_pct)
ctk.CTkLabel(lvl_frame, text=f"{curr_xp} / {req_xp} XP", font=ctk.CTkFont(size=10)).pack(anchor="e")
# Check if profile exists
if not self.profile:
@@ -91,7 +131,6 @@ class DashboardFrame(ctk.CTkFrame):
bmi_icon_img = get_bmi_icon(bmi, size=(80, 80))
# Layout BMI Card
# Left: Icon, Right: Text
bmi_inner = ctk.CTkFrame(bmi_frame, fg_color="transparent")
bmi_inner.pack(pady=10, padx=10)
@@ -116,6 +155,15 @@ class DashboardFrame(ctk.CTkFrame):
ctk.CTkLabel(weight_frame, text="Current Weight", font=ctk.CTkFont(size=14)).pack(pady=(10,0))
ctk.CTkLabel(weight_frame, text=w_text, font=ctk.CTkFont(size=30, weight="bold")).pack()
ctk.CTkLabel(weight_frame, text=g_text, font=ctk.CTkFont(size=12, slant="italic")).pack(pady=(0,10))
# Fun Weight Comparison
if logs and current_weight:
start_w = [l['weight'] for l in logs if l['weight']][0]
loss = start_w - current_weight
if loss > 0.5:
obj = get_weight_loss_object(loss)
if obj:
ctk.CTkLabel(weight_frame, text=f"Lost: {obj}", font=ctk.CTkFont(size=12, weight="bold"), text_color="#2ecc71").pack()
# Date Estimate Card
date_frame = ctk.CTkFrame(cards_frame)
@@ -151,7 +199,7 @@ class DashboardFrame(ctk.CTkFrame):
# --- Graph ---
self.graph_frame = ctk.CTkFrame(self)
self.graph_frame.grid(row=2, column=0, sticky="nsew", padx=20, pady=20)
self.graph_frame.grid(row=3, column=0, sticky="nsew", padx=20, pady=20)
self.plot_prognosis(valid_logs if 'valid_logs' in locals() else [])
@@ -183,4 +231,4 @@ class DashboardFrame(ctk.CTkFrame):
canvas = FigureCanvasTkAgg(fig, master=self.graph_frame)
canvas.draw()
canvas.get_tk_widget().pack(fill="both", expand=True)
canvas.get_tk_widget().pack(fill="both", expand=True)