Skip to content

Commit ef23d7e

Browse files
committed
Merge origin/leader with conflicts
2 parents d8e0c19 + 7c5f798 commit ef23d7e

53 files changed

Lines changed: 699 additions & 571 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,18 @@
11
## Description
22

3-
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
3+
Please include a summary of the change and which issue is fixed.
44

55
Fixes # (issue)
66

7-
## Change Type (select one)
7+
## Change Type
88

9-
- [ ] 🐛 Bug fix (non-breaking change fixing an issue)
10-
- [ ] ✨ New feature (non-breaking change adding functionality)
11-
- [ ] 💥 Breaking change (fix/feature causing existing functionality to break)
12-
- [ ] 🏗️ Refactoring (code change that neither fixes bug nor adds feature)
13-
- [ ] 📚 Documentation (changes only affecting documentation)
14-
- [ ] 🎨 Styling (changes that do not affect functionality)
9+
- 🐛 Bug fix (non-breaking change fixing an issue)
10+
- ✨ New feature (non-breaking change adding functionality)
11+
- 💥 Breaking change (fix/feature causing existing functionality to break)
12+
- 🏗️ Refactoring (code change that neither fixes bug nor adds feature)
13+
- 📚 Documentation (changes only affecting documentation)
14+
- 🎨 Styling (changes that do not affect functionality)
1515

16-
## PR Scope Checklist
16+
## Related Issues
1717

18-
_This checklist is mandatory for all PRs._
19-
20-
- [ ] **PR has a clear, single purpose:** The title and description of the PR clearly state the purpose of the change.
21-
- [ ] **All changes relate to the stated objective:** The code changes should be directly related to the purpose of the PR.
22-
- [ ] **No unrelated cleanup or refactoring:** The PR should not contain any changes that are not directly related to the stated objective.
23-
- [ ] **Title and description match the actual changes:** The title and description should accurately reflect the changes in the PR.
24-
- [ ] **Tests cover the specific change scope:** The tests should be focused on the changes in the PR and should not include unrelated tests.
25-
26-
## Impact Assessment
27-
28-
- [ ] Changes are **backward compatible** (or breaking changes are documented)
29-
- [ ] **Tests** are added/updated for new functionality
30-
- [ ] **Documentation** is updated if needed
31-
- [ ] **ADR** is created/updated for significant architectural changes
18+
Closes #(issue_number)

.github/actions/setup-env/action.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ runs:
5353
- name: Install GitHub CLI
5454
shell: bash
5555
run: |
56+
if command -v gh &> /dev/null; then
57+
echo "GitHub CLI already installed: $(gh --version)"
58+
exit 0
59+
fi
60+
5661
mkdir -p $HOME/.local/bin
5762
# Detect OS and Architecture
5863
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
@@ -67,7 +72,7 @@ runs:
6772
URL="https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_${OS}_${ARCH}.tar.gz"
6873
6974
echo "Downloading GitHub CLI from $URL"
70-
curl -L "$URL" -o gh.tar.gz
75+
curl -f -L --retry 3 --retry-delay 5 "$URL" -o gh.tar.gz
7176
tar xvf gh.tar.gz
7277
7378
# Move binary to local bin

.github/automated-labels.json

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
{
2-
"review": [
3-
"approved",
4-
"changes-requested",
5-
"ai-reviewed",
6-
"ci-failure"
7-
],
2+
"review": ["approved", "changes-requested", "ai-reviewed", "ci-failure"],
83
"scope_prefix": "scope:",
94
"obsolete": [
105
"ready-for-approval",

.github/pull_request_template.md

Lines changed: 0 additions & 49 deletions
This file was deleted.

.github/workflows/pr-enrichment.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,12 @@ jobs:
232232
- **Correct format:** \`## Change Type: 🐛 Bug fix (non-breaking change fixing an issue)\`
233233
- **Incorrect format:** Do NOT include the list of other options or checkboxes (\`- [ ] ...\`).
234234
235+
**No Checkboxes:**
236+
Do NOT include any checkbox formatting (e.g., \`- [ ]\`) in any part of the generated description.
237+
238+
**Section Relevance:**
239+
Only include the "Changes Made" and "Testing" sections if there is specific, relevant information to provide based on the PR data. If a section has no relevant content, omit it entirely to reduce "template slop".
240+
235241
### Output Format
236242
You MUST return a valid JSON object. Do not include markdown formatting like \`\`\`json.
237243
{

app/api/workout/route.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// app/api/workout/route.ts
21
import { NextResponse } from 'next/server'
32
import { parseGoogleDocTable } from '@/services/googleDocParser'
43
import logger from '@/utils/logger'
@@ -15,12 +14,11 @@ export async function GET(request: Request) {
1514
}
1615

1716
try {
18-
// We use the export endpoint to get raw HTML.
1917
// NOTE: The Google Doc must be shared as "Anyone with the link can view"
2018
const exportUrl = `https://docs.google.com/document/d/${docId}/export?format=html`
2119

2220
const response = await fetch(exportUrl, {
23-
next: { revalidate: 60 }, // Cache for 60 seconds to avoid hitting Google limits
21+
next: { revalidate: 60 },
2422
})
2523

2624
if (!response.ok) {

app/client/connect/ConnectView.tsx

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import WorkoutSummary from './WorkoutSummary'
1616
import UserSettings from './UserSettings'
1717
import { SignalQualityIndicator } from './SignalQualityIndicator'
1818
import WorkoutControls from './WorkoutControls'
19+
import ResetSection from './components/ResetSection'
1920
import { useState, useEffect } from 'react'
2021
import logger from '@/utils/logger'
2122
import { MeasurementSystem, Gender } from '../../../types/core'
@@ -76,38 +77,6 @@ interface ConnectViewProps {
7677
onEndWorkout: () => void
7778
}
7879

79-
interface ResetSectionProps {
80-
onReset: () => void
81-
isResetting: boolean
82-
}
83-
84-
const ResetSection = ({ onReset, isResetting }: ResetSectionProps) => (
85-
<Box
86-
sx={{
87-
textAlign: 'center',
88-
mt: 4,
89-
pt: 4,
90-
borderTop: '1px solid #eee',
91-
}}
92-
>
93-
<Button
94-
variant="contained"
95-
color="error"
96-
onClick={onReset}
97-
disabled={isResetting}
98-
>
99-
{isResetting ? 'Resetting...' : 'Reset System & Device'}
100-
</Button>
101-
<Typography
102-
variant="caption"
103-
display="block"
104-
sx={{ mt: 1, color: 'text.secondary' }}
105-
>
106-
Resets server state AND forgets Bluetooth device connection.
107-
</Typography>
108-
</Box>
109-
)
110-
11180
export default function ConnectView({
11281
duration,
11382
caloriesBurned,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import Box from '@mui/material/Box'
2+
import Button from '@mui/material/Button'
3+
import Typography from '@mui/material/Typography'
4+
5+
export interface ResetSectionProps {
6+
onReset: () => void
7+
isResetting: boolean
8+
}
9+
10+
const ResetSection = ({ onReset, isResetting }: ResetSectionProps) => (
11+
<Box
12+
sx={{
13+
textAlign: 'center',
14+
mt: 4,
15+
pt: 4,
16+
borderTop: 1,
17+
borderColor: 'divider',
18+
}}
19+
>
20+
<Button
21+
variant="contained"
22+
color="error"
23+
onClick={onReset}
24+
disabled={isResetting}
25+
>
26+
{isResetting ? 'Resetting...' : 'Reset Permissions & Settings'}
27+
</Button>
28+
<Typography
29+
variant="caption"
30+
display="block"
31+
sx={{ mt: 1, color: 'text.secondary' }}
32+
>
33+
Resets stored permissions and device settings, including Bluetooth
34+
connection.
35+
</Typography>
36+
</Box>
37+
)
38+
39+
export default ResetSection

app/client/experimental/components/ExperimentalAnalyticsPage.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// app/client/experimental/components/ExperimentalAnalyticsPage.tsx
22
'use client'
33
import { useState, useEffect, useMemo, useRef, useCallback } from 'react'
4-
import { Container, Box, Button } from '@mui/material'
4+
import { Container, Box, Button, Skeleton } from '@mui/material'
55
import dynamic from 'next/dynamic'
66
import { useWebSocket } from '@/context/WebSocketContext'
77
import { useWorkoutSessionManager } from '@/hooks/useWorkoutSessionManager'
@@ -21,6 +21,11 @@ import CalorieTracker from './CalorieTracker'
2121
import SessionList from './SessionList'
2222
import SessionDetail from './SessionDetail'
2323

24+
const HeartRateTimeSeries = dynamic(() => import('./HeartRateTimeSeries'), {
25+
ssr: false,
26+
loading: () => <Skeleton variant="rectangular" height={300} />,
27+
})
28+
2429
const defaultTimeInZones: Record<HeartRateZone, number> = {
2530
ZONE_0: 0,
2631
ZONE_1: 0,
@@ -31,10 +36,6 @@ const defaultTimeInZones: Record<HeartRateZone, number> = {
3136
ZONE_6: 0,
3237
}
3338

34-
const HeartRateTimeSeries = dynamic(() => import('./HeartRateTimeSeries'), {
35-
ssr: false,
36-
})
37-
3839
type View = 'active' | 'list' | 'detail'
3940

4041
const ExperimentalAnalyticsPage = () => {

app/client/experimental/components/HeartRateTimeSeries.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// app/client/experimental/components/HeartRateTimeSeries.tsx
22
'use client'
3-
import { Card, CardContent, Typography, Box } from '@mui/material'
3+
import { useMemo } from 'react'
4+
import { Card, CardContent, Typography, Box, useTheme } from '@mui/material'
45
import { HrDataPoint } from '@/lib/workout-session-storage'
56
import {
67
LineChart,
@@ -18,28 +19,44 @@ interface HeartRateTimeSeriesProps {
1819
}
1920

2021
const HeartRateTimeSeries = ({ hrHistory }: HeartRateTimeSeriesProps) => {
22+
const theme = useTheme()
23+
24+
const formatTime = useMemo(() => {
25+
const formatter = new Intl.DateTimeFormat(undefined, {
26+
hour: '2-digit',
27+
minute: '2-digit',
28+
second: '2-digit',
29+
})
30+
return (time: number) => formatter.format(new Date(time))
31+
}, [])
32+
2133
return (
2234
<Card>
2335
<CardContent>
2436
<Typography variant="h5" gutterBottom>
2537
Heart Rate Over Time
2638
</Typography>
27-
<Box sx={{ height: 300 }} data-testid="hr-time-series-chart">
39+
<Box
40+
sx={{ height: 300, minHeight: 300 }}
41+
data-testid="hr-time-series-chart"
42+
>
2843
<ResponsiveContainer width="100%" height="100%">
2944
<LineChart data={hrHistory} syncId="anyId">
30-
<CartesianGrid strokeDasharray="3 3" />
31-
<XAxis
32-
dataKey="time"
33-
tickFormatter={(time) => new Date(time).toLocaleTimeString()}
45+
<CartesianGrid
46+
strokeDasharray="3 3"
47+
stroke={theme.palette.divider}
3448
/>
49+
<XAxis dataKey="time" tickFormatter={formatTime} />
3550
<YAxis domain={['auto', 'auto']} />
3651
<Tooltip />
3752
<Legend />
3853
<Line
3954
type="monotone"
4055
dataKey="hr"
41-
stroke="#8884d8"
42-
activeDot={{ r: 8 }}
56+
stroke={theme.palette.primary.main}
57+
strokeWidth={2}
58+
dot={false}
59+
activeDot={{ r: 6 }}
4360
/>
4461
</LineChart>
4562
</ResponsiveContainer>

0 commit comments

Comments
 (0)