Redesign dashboard top-4 stats as separate cards
Frontend half of the dashboard stat-card redesign, matching the provided mockup. The 4 metrics used to be plain rows sharing one bordered box (_add_metric -> a single metric_grid inside one _card). Replaced with 4 independently-_card-wrapped panels in a responsive GridContainer (4 cols / 2 compact, same threshold _update_responsive already used). Each card now has: a colored icon badge, title + info glyph, a big value, a colored trend/status line, a small visual, and a footer caption: - Question Bank Rating / CCS Rating: a new minimal DashboardSparkline (dashboard_sparkline.gd) fed from the current rating and the week-ago snapshot (reconstructed client-side from the delta the API already returns - no separate history endpoint needed). Trend line and caption come from the new delta/percentile fields; both degrade to a plain single-point sparkline and a rated-count caption when no snapshot exists yet. - Exam Readiness: a new DashboardSegmentBar (dashboard_segment_bar.gd - nothing like a segmented pill progress indicator existed anywhere in the codebase) instead of a sparkline, colored by the High/Medium/Low label; shows a neutral "complete a simulation" state when the user has none yet rather than a fabricated readiness. - Average Score: reuses the existing ProgressBar/_style_progress, relabeled from "First-Attempt Accuracy". Dropped the old "Study Time" card (not part of the mockup - the underlying data still drives the weekly activity chart below, it just no longer gets a dedicated top-line number) and the now-fully-unused _format_duration. Verified headlessly: instantiated the real screen against fake DashboardService data, confirmed every card's value/trend/caption text and the segment-bar/progress-bar values match the mockup exactly, and rendered actual screenshots of both the populated and "no data yet" fallback states.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
extends Control
|
||||
|
||||
const Brand := preload("res://scripts/ui/medmind_style.gd")
|
||||
const GAP := 6.0
|
||||
const CORNER_RADIUS := 4
|
||||
|
||||
var filled_segments := 0
|
||||
var total_segments := 4
|
||||
var accent := Color.WHITE
|
||||
var dark := true
|
||||
|
||||
|
||||
func set_progress(next_filled: int, next_total: int, next_accent: Color, dark_mode: bool) -> void:
|
||||
filled_segments = next_filled
|
||||
total_segments = maxi(1, next_total)
|
||||
accent = next_accent
|
||||
dark = dark_mode
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
var segment_width: float = (size.x - GAP * float(total_segments - 1)) / float(total_segments)
|
||||
if segment_width <= 0.0:
|
||||
return
|
||||
var filled_box := StyleBoxFlat.new()
|
||||
filled_box.bg_color = accent
|
||||
filled_box.set_corner_radius_all(CORNER_RADIUS)
|
||||
var track_box := StyleBoxFlat.new()
|
||||
track_box.bg_color = Brand.muted_color(dark).lerp(Brand.background_color(dark), 0.5)
|
||||
track_box.set_corner_radius_all(CORNER_RADIUS)
|
||||
for index in range(total_segments):
|
||||
var x: float = index * (segment_width + GAP)
|
||||
var rect := Rect2(x, 0.0, segment_width, size.y)
|
||||
draw_style_box(filled_box if index < filled_segments else track_box, rect)
|
||||
Reference in New Issue
Block a user