File size: 4,279 Bytes
3d4aa49
 
7b6976e
3d4aa49
 
 
 
7b6976e
 
 
 
 
3d4aa49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ac30c1e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d4aa49
a3df4ef
 
 
 
 
 
 
 
 
 
 
 
3d4aa49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import './WeeklySummary.css';

function WeeklySummary({ summary, recommendation, weekKey, isCurrentWeek, weeksOfData, longestRun, hasPrevWeek, hasNextWeek, onPrevWeek, onNextWeek }) {
  const hasRuns = summary.run_count > 0;

  return (
    <div className="weekly-summary card">
      <div className="week-nav">
        <button className="week-nav-btn" disabled={!hasPrevWeek} onClick={onPrevWeek} aria-label="Previous week">&lsaquo;</button>
        <h2>{isCurrentWeek ? 'This Week' : 'Week'} <span className="week-label">{weekKey}</span></h2>
        <button className="week-nav-btn" disabled={!hasNextWeek} onClick={onNextWeek} aria-label="Next week">&rsaquo;</button>
      </div>

      {hasRuns ? (
        <>
          <div className="stats-grid">
            <div className="stat-card">
              <span className="stat-value">{summary.total_distance_km.toFixed(1)}</span>
              <span className="stat-label">km total</span>
            </div>
            <div className="stat-card">
              <span className="stat-value">{summary.total_training_load.toFixed(0)}</span>
              <span className="stat-label">training load</span>
            </div>
            <div className="stat-card">
              <span className="stat-value">{summary.run_count}</span>
              <span className="stat-label">runs</span>
            </div>
            <div className="stat-card">
              <span className="stat-value">{summary.avg_pace.toFixed(1)}</span>
              <span className="stat-label">min/km avg</span>
            </div>
          </div>

          {longestRun && (
            <div className="longest-run">
              <h3>
                Single Run Cap <span className="rec-method">(BJSM 30-day)</span>
                <span className="info-tip-wrapper">
                  <span className="info-icon">β“˜</span>
                  <span className="info-tooltip">
                    Overuse injury risk increases when a single session exceeds 10% of the longest run in the past 30 days.
                    <a href="https://bjsm.bmj.com/content/59/17/1203" target="_blank" rel="noopener noreferrer">
                      Read the paper&nbsp;β†’
                    </a>
                  </span>
                </span>
              </h3>
              <div className="rec-row">
                <span className="rec-label">Longest run (30d)</span>
                <span className="rec-value">{longestRun.longest_km} km</span>
              </div>
              <div className="rec-row">
                <span className="rec-label">Max next run (+10%)</span>
                <span className="rec-value threshold-value">{longestRun.threshold_km} km</span>
              </div>
            </div>
          )}

          <div className="recommendation">
            <h3>
              Next Week Target <span className="rec-method">(ACWR, {weeksOfData || 1}w avg)</span>
              <span className="info-tip-wrapper">
                <span className="info-icon">β“˜</span>
                <span className="info-tooltip">
                  The Acute:Chronic Workload Ratio compares your recent training to your rolling average over the last {weeksOfData || 1} week{(weeksOfData || 1) > 1 ? 's' : ''} (up to 4). A safe range is 0.8–1.3Γ— chronic load.
                  <a href="https://bjsm.bmj.com/content/50/5/273" target="_blank" rel="noopener noreferrer">
                    Read the paper&nbsp;β†’
                  </a>
                </span>
              </span>
            </h3>
            <div className="rec-row">
              <span className="rec-label">Distance</span>
              <span className="rec-value">
                {recommendation.min_distance} – {recommendation.max_distance} km
              </span>
            </div>
            <div className="rec-row">
              <span className="rec-label">Training Load</span>
              <span className="rec-value">
                {recommendation.min_load} – {recommendation.max_load}
              </span>
            </div>
          </div>
        </>
      ) : (
        <p className="empty-message">No runs logged this week yet. Add your first run to see stats and recommendations.</p>
      )}
    </div>
  );
}

export default WeeklySummary;