feat: initial project scaffold with Watch companion app

This commit is contained in:
2026-08-04 17:28:06 +02:00
parent adbb4f01c5
commit 43b6467efb
65 changed files with 6361 additions and 166 deletions
+15
View File
@@ -0,0 +1,15 @@
import { type WorkoutSet } from "@types/workout";
export function calculateTotalDistance(sets: WorkoutSet[]): number {
return sets.reduce((acc, set) => acc + set.distancePerRep * set.repCount, 0);
}
export function calculateTotalDuration(sets: WorkoutSet[]): number {
return sets.reduce((acc, set) => {
const swimTime = set.targetTime
? set.targetTime * set.repCount
: 0;
const restTime = set.restType === "none" ? 0 : set.restDuration * (set.repCount - 1);
return acc + swimTime + restTime;
}, 0);
}
+15
View File
@@ -0,0 +1,15 @@
export function calculateSwolf(strokeCount: number, durationSeconds: number): number {
return strokeCount + Math.round(durationSeconds);
}
export function calculateAvgSwolf(
laps: { strokeCount?: number; duration: number }[]
): number {
const validLaps = laps.filter((l) => l.strokeCount != null);
if (validLaps.length === 0) return 0;
const total = validLaps.reduce(
(acc, l) => acc + calculateSwolf(l.strokeCount!, l.duration),
0
);
return Math.round(total / validLaps.length);
}
+6
View File
@@ -0,0 +1,6 @@
export function formatDistance(meters: number): string {
if (meters >= 1000) {
return `${(meters / 1000).toFixed(1)}km`;
}
return `${meters}m`;
}
+18
View File
@@ -0,0 +1,18 @@
export function formatTime(seconds: number): string {
const hrs = Math.floor(seconds / 3600);
const mins = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
if (hrs > 0) {
return `${hrs}:${String(mins).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
}
return `${mins}:${String(secs).padStart(2, "0")}`;
}
export function formatPace(distanceMeters: number, durationSeconds: number): string {
if (distanceMeters === 0) return "--:--";
const paceSeconds = (durationSeconds / distanceMeters) * 100;
const mins = Math.floor(paceSeconds / 60);
const secs = Math.floor(paceSeconds % 60);
return `${mins}:${String(secs).padStart(2, "0")}/100m`;
}