hevy-shared 1.0.842 → 1.0.844
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/built/index.d.ts +0 -6
- package/built/tests/utils.test.js +133 -60
- package/built/utils.d.ts +6 -8
- package/built/utils.js +35 -65
- package/package.json +1 -2
package/built/index.d.ts
CHANGED
|
@@ -569,9 +569,6 @@ export interface UserProfile {
|
|
|
569
569
|
weekly_workout_durations: WeeklyWorkoutDuration[];
|
|
570
570
|
mutual_followers: PreviewMutualUser[];
|
|
571
571
|
}
|
|
572
|
-
export interface UserWorkoutStreakCount {
|
|
573
|
-
streak_count: number;
|
|
574
|
-
}
|
|
575
572
|
export interface PublicUserProfile {
|
|
576
573
|
private_profile: boolean;
|
|
577
574
|
username: string;
|
|
@@ -1864,6 +1861,3 @@ export interface FolderLinkPreviewMetadataResponse extends LinkPreviewMetadataRe
|
|
|
1864
1861
|
username: string;
|
|
1865
1862
|
routine_count: number;
|
|
1866
1863
|
}
|
|
1867
|
-
export interface StartTimeableWorkout {
|
|
1868
|
-
start_time: number;
|
|
1869
|
-
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const dayjs_1 = __importDefault(require("dayjs"));
|
|
7
3
|
const utils_1 = require("../utils");
|
|
8
4
|
describe('utils', () => {
|
|
9
5
|
describe('isValidUsername', () => {
|
|
@@ -325,6 +321,139 @@ describe('utils', () => {
|
|
|
325
321
|
expect((0, utils_1.formatDurationInput)('99:99')).toBe('99:99');
|
|
326
322
|
});
|
|
327
323
|
});
|
|
324
|
+
describe('getEstimatedExercisesDurationSeconds', () => {
|
|
325
|
+
const testCases = [
|
|
326
|
+
{
|
|
327
|
+
exercises: [
|
|
328
|
+
{
|
|
329
|
+
exercise_type: 'duration',
|
|
330
|
+
rest_seconds: 10,
|
|
331
|
+
sets: [{ duration_seconds: 50, indicator: 'normal' }],
|
|
332
|
+
},
|
|
333
|
+
],
|
|
334
|
+
expectedDuration: 50 + 10,
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
exercises: [
|
|
338
|
+
{
|
|
339
|
+
exercise_type: 'floors_duration',
|
|
340
|
+
rest_seconds: 10,
|
|
341
|
+
sets: [{ duration_seconds: 0, indicator: 'normal' }],
|
|
342
|
+
},
|
|
343
|
+
],
|
|
344
|
+
expectedDuration: 10,
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
exercises: [
|
|
348
|
+
{
|
|
349
|
+
exercise_type: 'weight_duration',
|
|
350
|
+
rest_seconds: null,
|
|
351
|
+
sets: [{ duration_seconds: 30, indicator: 'normal' }],
|
|
352
|
+
},
|
|
353
|
+
],
|
|
354
|
+
expectedDuration: 30 + utils_1.ESTIMATED_REST_TIMER_DURATION,
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
exercises: [
|
|
358
|
+
{
|
|
359
|
+
exercise_type: 'distance_duration',
|
|
360
|
+
rest_seconds: 120,
|
|
361
|
+
sets: [{ duration_seconds: 40, indicator: 'normal' }],
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
expectedDuration: 40 + 120,
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
exercises: [
|
|
368
|
+
{
|
|
369
|
+
exercise_type: 'weight_duration',
|
|
370
|
+
rest_seconds: 120,
|
|
371
|
+
sets: [{ duration_seconds: null, indicator: 'normal' }],
|
|
372
|
+
},
|
|
373
|
+
],
|
|
374
|
+
expectedDuration: 120 + utils_1.ESTIMATED_SET_DURATION,
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
exercises: [
|
|
378
|
+
{
|
|
379
|
+
exercise_type: 'duration',
|
|
380
|
+
rest_seconds: 0,
|
|
381
|
+
sets: [{ duration_seconds: null, indicator: 'normal' }],
|
|
382
|
+
},
|
|
383
|
+
],
|
|
384
|
+
expectedDuration: utils_1.ESTIMATED_SET_DURATION,
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
exercises: [
|
|
388
|
+
{
|
|
389
|
+
exercise_type: 'reps_only',
|
|
390
|
+
rest_seconds: 180,
|
|
391
|
+
sets: [{ duration_seconds: null, indicator: 'normal' }],
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
exercise_type: 'reps_only',
|
|
395
|
+
rest_seconds: 180,
|
|
396
|
+
sets: [
|
|
397
|
+
{
|
|
398
|
+
duration_seconds: 0,
|
|
399
|
+
indicator: 'normal',
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
duration_seconds: 0,
|
|
403
|
+
indicator: 'normal',
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
duration_seconds: 0,
|
|
407
|
+
indicator: 'normal',
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
duration_seconds: 0,
|
|
411
|
+
indicator: 'normal',
|
|
412
|
+
},
|
|
413
|
+
],
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
expectedDuration: (180 + utils_1.ESTIMATED_SET_DURATION) * 5,
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
exercises: [
|
|
420
|
+
{
|
|
421
|
+
exercise_type: 'reps_only',
|
|
422
|
+
rest_seconds: null,
|
|
423
|
+
sets: [{ duration_seconds: null, indicator: 'normal' }],
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
exercise_type: 'reps_only',
|
|
427
|
+
rest_seconds: null,
|
|
428
|
+
sets: [
|
|
429
|
+
{
|
|
430
|
+
duration_seconds: 0,
|
|
431
|
+
indicator: 'normal',
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
duration_seconds: 0,
|
|
435
|
+
indicator: 'dropset',
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
duration_seconds: 0,
|
|
439
|
+
indicator: 'normal',
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
duration_seconds: 0,
|
|
443
|
+
indicator: 'dropset',
|
|
444
|
+
},
|
|
445
|
+
],
|
|
446
|
+
},
|
|
447
|
+
],
|
|
448
|
+
expectedDuration: utils_1.ESTIMATED_REST_TIMER_DURATION * 3 + 5 * utils_1.ESTIMATED_SET_DURATION,
|
|
449
|
+
},
|
|
450
|
+
];
|
|
451
|
+
testCases.forEach((testCase) => {
|
|
452
|
+
it(`getEstimatedExercisesDurationSeconds`, () => {
|
|
453
|
+
expect((0, utils_1.getEstimatedExercisesDurationSeconds)(testCase)).toBe(testCase.expectedDuration);
|
|
454
|
+
});
|
|
455
|
+
});
|
|
456
|
+
});
|
|
328
457
|
describe('splitAtUsernamesAndLinks', () => {
|
|
329
458
|
it('Takes a string and returns an array of FormatAtText', () => {
|
|
330
459
|
const inputOutputs = [
|
|
@@ -510,60 +639,4 @@ describe('utils', () => {
|
|
|
510
639
|
expect((0, utils_1.getYoutubeVideoId)('https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstleyVEVO')).toBe('dQw4w9WgXcQ');
|
|
511
640
|
});
|
|
512
641
|
});
|
|
513
|
-
describe('calculateCurrentWeekStreak', () => {
|
|
514
|
-
it("Doesn't include gaps in the streak count", () => {
|
|
515
|
-
const workouts = [
|
|
516
|
-
{ start_time: (0, dayjs_1.default)('2025-11-05').unix() },
|
|
517
|
-
{ start_time: (0, dayjs_1.default)('2025-11-02').unix() },
|
|
518
|
-
{ start_time: (0, dayjs_1.default)('2025-10-31').unix() },
|
|
519
|
-
{ start_time: (0, dayjs_1.default)('2025-10-23').unix() },
|
|
520
|
-
{ start_time: (0, dayjs_1.default)('2025-10-10').unix() },
|
|
521
|
-
];
|
|
522
|
-
const firstWeekday = 'sunday';
|
|
523
|
-
const untilUnix = (0, dayjs_1.default)('2025-11-06').unix();
|
|
524
|
-
expect((0, utils_1.calculateCurrentWeekStreak)(workouts, firstWeekday, untilUnix)).toBe(3);
|
|
525
|
-
});
|
|
526
|
-
it("Calculates a potentially non-zero streak when the user hasn't worked out this week yet", () => {
|
|
527
|
-
const workouts = [
|
|
528
|
-
{ start_time: (0, dayjs_1.default)('2025-10-31').unix() },
|
|
529
|
-
{ start_time: (0, dayjs_1.default)('2025-10-23').unix() },
|
|
530
|
-
{ start_time: (0, dayjs_1.default)('2025-10-20').unix() },
|
|
531
|
-
{ start_time: (0, dayjs_1.default)('2025-10-14').unix() + 1 },
|
|
532
|
-
{ start_time: (0, dayjs_1.default)('2025-10-12').unix() },
|
|
533
|
-
];
|
|
534
|
-
const firstWeekday = 'monday';
|
|
535
|
-
const untilUnix = (0, dayjs_1.default)('2025-11-06').unix();
|
|
536
|
-
expect((0, utils_1.calculateCurrentWeekStreak)(workouts, firstWeekday, untilUnix)).toBe(4);
|
|
537
|
-
});
|
|
538
|
-
it('Includes this week in the streak count if the user worked out this week', () => {
|
|
539
|
-
const workouts = [
|
|
540
|
-
{ start_time: (0, dayjs_1.default)('2025-11-05').unix() },
|
|
541
|
-
{ start_time: (0, dayjs_1.default)('2025-10-31').unix() },
|
|
542
|
-
{ start_time: (0, dayjs_1.default)('2025-10-23').unix() },
|
|
543
|
-
{ start_time: (0, dayjs_1.default)('2025-10-20').unix() },
|
|
544
|
-
{ start_time: (0, dayjs_1.default)('2025-10-14').unix() },
|
|
545
|
-
{ start_time: (0, dayjs_1.default)('2025-10-07').unix() },
|
|
546
|
-
];
|
|
547
|
-
const firstWeekday = 'monday';
|
|
548
|
-
const untilUnix = (0, dayjs_1.default)('2025-11-06').unix();
|
|
549
|
-
expect((0, utils_1.calculateCurrentWeekStreak)(workouts, firstWeekday, untilUnix)).toBe(5);
|
|
550
|
-
});
|
|
551
|
-
it("Returns 0 if the user hasn't worked out", () => {
|
|
552
|
-
const workouts = [];
|
|
553
|
-
const firstWeekday = 'friday';
|
|
554
|
-
const untilUnix = (0, dayjs_1.default)('2025-10-10').unix();
|
|
555
|
-
expect((0, utils_1.calculateCurrentWeekStreak)(workouts, firstWeekday, untilUnix)).toBe(0);
|
|
556
|
-
});
|
|
557
|
-
it('Returns 0 if the user has not worked out this week and last week', () => {
|
|
558
|
-
const workouts = [
|
|
559
|
-
{ start_time: (0, dayjs_1.default)('2025-10-23').unix() },
|
|
560
|
-
{ start_time: (0, dayjs_1.default)('2025-10-20').unix() },
|
|
561
|
-
{ start_time: (0, dayjs_1.default)('2025-10-13').unix() },
|
|
562
|
-
{ start_time: (0, dayjs_1.default)('2025-10-07').unix() },
|
|
563
|
-
];
|
|
564
|
-
const firstWeekday = 'sunday';
|
|
565
|
-
const untilUnix = (0, dayjs_1.default)('2025-11-05').unix();
|
|
566
|
-
expect((0, utils_1.calculateCurrentWeekStreak)(workouts, firstWeekday, untilUnix)).toBe(0);
|
|
567
|
-
});
|
|
568
|
-
});
|
|
569
642
|
});
|
package/built/utils.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { BaseExerciseTemplate, FormatAtText, Result, StartTimeableWorkout, StrengthLevel, UserExerciseSet, Weekday } from '.';
|
|
1
|
+
import { BaseExerciseTemplate, ExerciseType, FormatAtText, Result, SetType, StrengthLevel, UserExerciseSet, UserFacingSetIndicator } from '.';
|
|
3
2
|
/**
|
|
4
3
|
* Doesn't matter what you throw in the function it'll
|
|
5
4
|
* always return a number. Non number values will return
|
|
@@ -176,14 +175,19 @@ export interface TotalSetCountWorkout {
|
|
|
176
175
|
*/
|
|
177
176
|
export declare const userExerciseSetWeight: (set: UserExerciseSet, exerciseStore: BaseExerciseTemplate[], hundredPercentBodyweightExercise: boolean) => number;
|
|
178
177
|
export declare const workoutSetCount: (w: TotalSetCountWorkout) => number;
|
|
178
|
+
export declare const UserFacingIndicatorToSetIndicator: (indicator: UserFacingSetIndicator) => SetType;
|
|
179
179
|
interface GetEstimatedExercisesDuration {
|
|
180
180
|
exercises: {
|
|
181
181
|
rest_seconds: number | null;
|
|
182
|
+
exercise_type: ExerciseType;
|
|
182
183
|
sets: {
|
|
183
184
|
duration_seconds?: number | null;
|
|
185
|
+
indicator: SetType;
|
|
184
186
|
}[];
|
|
185
187
|
}[];
|
|
186
188
|
}
|
|
189
|
+
export declare const ESTIMATED_SET_DURATION = 45;
|
|
190
|
+
export declare const ESTIMATED_REST_TIMER_DURATION = 90;
|
|
187
191
|
export declare const getEstimatedExercisesDurationSeconds: ({ exercises, }: GetEstimatedExercisesDuration) => number;
|
|
188
192
|
export declare const oneRepMaxPercentageMap: {
|
|
189
193
|
[s: number]: number;
|
|
@@ -236,10 +240,4 @@ export declare const isVersionAGreaterOrEqualToVersionB: (versionA: string, vers
|
|
|
236
240
|
export declare const splitAtUsernamesAndLinks: (text: string) => FormatAtText[];
|
|
237
241
|
export declare const validateYoutubeUrl: (url: string) => boolean;
|
|
238
242
|
export declare const getYoutubeVideoId: (url: string) => string | undefined;
|
|
239
|
-
/**@param workouts must be sorted descending by start_time */
|
|
240
|
-
export declare const calculateCurrentWeekStreak: (workouts: StartTimeableWorkout[], firstWeekday: Weekday, untilUnix?: number) => number;
|
|
241
|
-
export declare const startOfWeek: (d: Dayjs, firstDayOfWeek: Weekday) => Dayjs;
|
|
242
|
-
export declare const weekdayNumberMap: {
|
|
243
|
-
[key in Weekday]: number;
|
|
244
|
-
};
|
|
245
243
|
export {};
|
package/built/utils.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
const dayjs_1 = __importDefault(require("dayjs"));
|
|
3
|
+
exports.getYoutubeVideoId = exports.validateYoutubeUrl = exports.splitAtUsernamesAndLinks = exports.isVersionAGreaterOrEqualToVersionB = exports.generateUserGroupValue = exports.generateUserGroup = exports.isBaseExerciseTemplate = exports.getStrengthLevelFromPercentile = exports.numberToLocaleString = exports.numberWithCommas = exports.setVolume = exports.oneRepMax = exports.oneRepMaxPercentageMap = exports.getEstimatedExercisesDurationSeconds = exports.ESTIMATED_REST_TIMER_DURATION = exports.ESTIMATED_SET_DURATION = exports.UserFacingIndicatorToSetIndicator = exports.workoutSetCount = exports.userExerciseSetWeight = exports.workoutDistanceMeters = exports.workoutReps = exports.workoutDurationSeconds = exports.removeAccents = exports.getClosestDataPointAroundTargetDate = exports.getClosestDataPointBeforeTargetDate = exports.findMapped = exports.stringToNumber = exports.forceStringToNumber = exports.formatDurationInput = exports.isValidFormattedTime = exports.isWholeNumber = exports.isNumber = exports.isValidUuid = exports.isValidPhoneNumber = exports.isValidWebUrl = exports.URL_REGEX = exports.isValidEmail = exports.secondsToWordFormatMinutes = exports.secondsToWordFormat = exports.secondsToClockFormat = exports.secondsToClockParts = exports.isValidUsername = exports.roundToWholeNumber = exports.roundToOneDecimal = exports.roundToTwoDecimal = exports.divide = exports.clampNumber = exports.num = void 0;
|
|
8
4
|
/**
|
|
9
5
|
* Doesn't matter what you throw in the function it'll
|
|
10
6
|
* always return a number. Non number values will return
|
|
@@ -142,7 +138,7 @@ exports.URL_REGEX = RegExp([
|
|
|
142
138
|
// followed by the top-level domain
|
|
143
139
|
/[a-z]{2,10}/,
|
|
144
140
|
// optionally followed by a path
|
|
145
|
-
/(\/[-a-z0-9@:%_
|
|
141
|
+
/(\/[-a-z0-9@:%_+.~#?!&/=]*)?/,
|
|
146
142
|
]
|
|
147
143
|
.map((r) => r.source)
|
|
148
144
|
.join(''));
|
|
@@ -448,18 +444,45 @@ const workoutSetCount = (w) => {
|
|
|
448
444
|
}, 0);
|
|
449
445
|
};
|
|
450
446
|
exports.workoutSetCount = workoutSetCount;
|
|
451
|
-
const
|
|
452
|
-
|
|
447
|
+
const UserFacingIndicatorToSetIndicator = (indicator) => {
|
|
448
|
+
switch (indicator) {
|
|
449
|
+
case 'dropset':
|
|
450
|
+
return 'dropset';
|
|
451
|
+
case 'warmup':
|
|
452
|
+
return 'warmup';
|
|
453
|
+
case 'failure':
|
|
454
|
+
return 'failure';
|
|
455
|
+
default:
|
|
456
|
+
return 'normal';
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
exports.UserFacingIndicatorToSetIndicator = UserFacingIndicatorToSetIndicator;
|
|
460
|
+
exports.ESTIMATED_SET_DURATION = 45;
|
|
461
|
+
exports.ESTIMATED_REST_TIMER_DURATION = 90;
|
|
462
|
+
const isDurationExercise = (type) => {
|
|
463
|
+
return (type === 'duration' ||
|
|
464
|
+
type === 'weight_duration' ||
|
|
465
|
+
type === 'distance_duration' ||
|
|
466
|
+
type === 'floors_duration' ||
|
|
467
|
+
type === 'steps_duration');
|
|
468
|
+
};
|
|
453
469
|
const getEstimatedExercisesDurationSeconds = ({ exercises, }) => {
|
|
454
470
|
const totalSeconds = exercises.reduce((exercisesTotal, exercise) => {
|
|
455
471
|
var _a;
|
|
456
|
-
const restPerSet = (_a = exercise.rest_seconds) !== null && _a !== void 0 ? _a : ESTIMATED_REST_TIMER_DURATION;
|
|
457
|
-
const
|
|
472
|
+
const restPerSet = (_a = exercise.rest_seconds) !== null && _a !== void 0 ? _a : exports.ESTIMATED_REST_TIMER_DURATION;
|
|
473
|
+
const setsTotal = exercise.sets.reduce((setTotal, set) => {
|
|
458
474
|
var _a;
|
|
459
|
-
|
|
475
|
+
// Sometimes we get 0 values for duration on exercises that aren't duration.
|
|
476
|
+
// Added this check to prevent having a estimated duration of 0 for these.
|
|
477
|
+
const duration = isDurationExercise(exercise.exercise_type)
|
|
478
|
+
? (_a = set.duration_seconds) !== null && _a !== void 0 ? _a : exports.ESTIMATED_SET_DURATION
|
|
479
|
+
: exports.ESTIMATED_SET_DURATION;
|
|
480
|
+
// if it is a dropset, we don't add the rest time
|
|
481
|
+
if (set.indicator === 'dropset')
|
|
482
|
+
return setTotal + duration;
|
|
460
483
|
return setTotal + duration + restPerSet;
|
|
461
484
|
}, 0);
|
|
462
|
-
return exercisesTotal +
|
|
485
|
+
return exercisesTotal + setsTotal;
|
|
463
486
|
}, 0);
|
|
464
487
|
return totalSeconds;
|
|
465
488
|
};
|
|
@@ -693,56 +716,3 @@ const getYoutubeVideoId = (url) => {
|
|
|
693
716
|
return match && match[1] && match[1].length === 11 ? match[1] : undefined;
|
|
694
717
|
};
|
|
695
718
|
exports.getYoutubeVideoId = getYoutubeVideoId;
|
|
696
|
-
/**@param workouts must be sorted descending by start_time */
|
|
697
|
-
const calculateCurrentWeekStreak = (workouts, firstWeekday, untilUnix = (0, dayjs_1.default)().unix()) => {
|
|
698
|
-
let streakCount = 0;
|
|
699
|
-
let weekStart = (0, exports.startOfWeek)(dayjs_1.default.unix(untilUnix), firstWeekday).subtract(1, 'week');
|
|
700
|
-
let weekEnd = weekStart.add(1, 'week');
|
|
701
|
-
let i = 0;
|
|
702
|
-
/** Iterate through the workouts from most recent to least and keep track of the week-long
|
|
703
|
-
* sliding window in which there needs to be a workout present in order for the streak to count.
|
|
704
|
-
* If there is a workout present during this window, move the window into the past by a week
|
|
705
|
-
* and keep iterating through the workouts. If there are no workouts during this window,
|
|
706
|
-
* the streak count is not incremented.
|
|
707
|
-
*/
|
|
708
|
-
while (i < workouts.length) {
|
|
709
|
-
const workoutStart = workouts[i].start_time;
|
|
710
|
-
if (workoutStart >= weekStart.unix() && workoutStart <= weekEnd.unix()) {
|
|
711
|
-
streakCount += 1;
|
|
712
|
-
weekStart = weekStart.subtract(1, 'week');
|
|
713
|
-
weekEnd = weekEnd.subtract(1, 'week');
|
|
714
|
-
}
|
|
715
|
-
else if (workoutStart < weekStart.unix()) {
|
|
716
|
-
/** This workout is before the sliding window. We don't get to this point unless
|
|
717
|
-
* the user didn't workout during the window. So that means the streak is over
|
|
718
|
-
*/
|
|
719
|
-
break;
|
|
720
|
-
}
|
|
721
|
-
i += 1;
|
|
722
|
-
}
|
|
723
|
-
weekStart = (0, exports.startOfWeek)(dayjs_1.default.unix(untilUnix), firstWeekday);
|
|
724
|
-
weekEnd = weekStart.add(1, 'week');
|
|
725
|
-
if (workouts.find(({ start_time }) => start_time >= weekStart.unix() && start_time <= weekEnd.unix())) {
|
|
726
|
-
streakCount += 1;
|
|
727
|
-
}
|
|
728
|
-
return streakCount;
|
|
729
|
-
};
|
|
730
|
-
exports.calculateCurrentWeekStreak = calculateCurrentWeekStreak;
|
|
731
|
-
const startOfWeek = (d, firstDayOfWeek) => {
|
|
732
|
-
const firstDayOfWeekIndex = exports.weekdayNumberMap[firstDayOfWeek];
|
|
733
|
-
let testDay = d;
|
|
734
|
-
while (testDay.day() !== firstDayOfWeekIndex) {
|
|
735
|
-
testDay = testDay.subtract(1, 'day');
|
|
736
|
-
}
|
|
737
|
-
return testDay.startOf('day');
|
|
738
|
-
};
|
|
739
|
-
exports.startOfWeek = startOfWeek;
|
|
740
|
-
exports.weekdayNumberMap = {
|
|
741
|
-
sunday: 0,
|
|
742
|
-
monday: 1,
|
|
743
|
-
tuesday: 2,
|
|
744
|
-
wednesday: 3,
|
|
745
|
-
thursday: 4,
|
|
746
|
-
friday: 5,
|
|
747
|
-
saturday: 6,
|
|
748
|
-
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hevy-shared",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.844",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "built/index.js",
|
|
6
6
|
"types": "built/index.d.ts",
|
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
"typescript": "5.8.2"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"dayjs": "^1.11.19",
|
|
50
49
|
"lodash": "^4.17.21"
|
|
51
50
|
}
|
|
52
51
|
}
|