[Pharo] Personal fitness tracker web app.
Started rework for regular and irregular set groups.
Changed files
- src/MyFitnessTracker/MFTDialog.class.st
- src/MyFitnessTracker/MFTExerciseDialog.class.st
- src/MyFitnessTracker/MFTExerciseDialogOld.class.st
- src/MyFitnessTracker/MFTExercisesDialog.class.st
- src/MyFitnessTracker/MFTSet.class.st
- src/MyFitnessTracker/MFTSetDialog.class.st
- src/MyFitnessTracker/MFTSetGroup.class.st
- src/MyFitnessTracker/MFTSetGroupDialog.class.st
- src/MyFitnessTracker/MFTSetGroupsDialog.class.st
- src/MyFitnessTracker/MFTSetsDialog.class.st
- src/MyFitnessTracker/MFTWorkout.class.st
- src/MyFitnessTracker/MFTWorkoutTask.class.st
src/MyFitnessTracker/MFTDialog.class.st
@@ -3,6 +3,7 @@
3
3
#superclass : #SBSComponent,
4
4
#instVars : [
5
5
'heading',
6
Added:
'subheading',
6
7
'component',
7
8
'action',
8
9
'completion'
@@ -131,7 +132,9 @@
131
132
html container
132
133
style: 'max-width: 40rem';
133
134
with: [
134
Removed:
html heading: self heading.
135
Added:
html heading level1 with: self heading.
136
Added:
subheading ifNotNil: [
137
Added:
html heading level3 textMuted with: subheading ].
135
138
html form: [
136
139
aBlock value.
137
140
html horizontalRule.
@@ -154,4 +157,16 @@
154
157
beSecondary;
155
158
callback: [ self answer: false ];
156
159
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
160
Added:
]
161
Added:
162
Added:
{ #category : #accessing }
163
Added:
MFTDialog >> subheading [
164
Added:
165
Added:
^ subheading
166
Added:
]
167
Added:
168
Added:
{ #category : #accessing }
169
Added:
MFTDialog >> subheading: aString [
170
Added:
171
Added:
subheading := aString
157
172
]
src/MyFitnessTracker/MFTExerciseDialog.class.st
@@ -0,0 +1,77 @@
1
Added:
Class {
2
Added:
#name : #MFTExerciseDialog,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'allExercises',
6
Added:
'selectedExercise'
7
Added:
],
8
Added:
#category : #'MyFitnessTracker-Dialog'
9
Added:
}
10
Added:
11
Added:
{ #category : #actions }
12
Added:
MFTExerciseDialog class >> edit: aMFTExercise [
13
Added:
14
Added:
^ self new
15
Added:
exercise: aMFTExercise;
16
Added:
sets: aMFTExercise sets;
17
Added:
action: #edit;
18
Added:
yourself
19
Added:
]
20
Added:
21
Added:
{ #category : #accessing }
22
Added:
MFTExerciseDialog >> allExercises [
23
Added:
24
Added:
^ allExercises
25
Added:
]
26
Added:
27
Added:
{ #category : #accessing }
28
Added:
MFTExerciseDialog >> allExercises: anObject [
29
Added:
30
Added:
allExercises := anObject
31
Added:
]
32
Added:
33
Added:
{ #category : #initialization }
34
Added:
MFTExerciseDialog >> initialize [
35
Added:
36
Added:
super initialize.
37
Added:
allExercises := MFTSQLite3Database allExercises.
38
Added:
selectedExercise := allExercises first
39
Added:
]
40
Added:
41
Added:
{ #category : #rendering }
42
Added:
MFTExerciseDialog >> renderContentOn: html [
43
Added:
44
Added:
self renderDialogOn: html with: [ self renderExerciseSelectOn: html ]
45
Added:
]
46
Added:
47
Added:
{ #category : #rendering }
48
Added:
MFTExerciseDialog >> renderExerciseSelectOn: html [
49
Added:
50
Added:
selectedExercise := allExercises
51
Added:
detect: [ :exercise |
52
Added:
exercise id = selectedExercise id ]
53
Added:
ifNone: [ allExercises first ].
54
Added:
html formGroup: [
55
Added:
html label: 'Exercise'.
56
Added:
html select formControl
57
Added:
list: allExercises;
58
Added:
selected: selectedExercise;
59
Added:
callback: [ :value | selectedExercise := value ];
60
Added:
labels: [ :each | each englishName ] ]
61
Added:
]
62
Added:
63
Added:
{ #category : #delegation }
64
Added:
MFTExerciseDialog >> renderSubmitOn: html [
65
Added:
66
Added:
html buttonGroup: [
67
Added:
html formButton
68
Added:
beSubmit;
69
Added:
bePrimary;
70
Added:
callback: [ self answer: selectedExercise ];
71
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
72
Added:
html formButton
73
Added:
beSubmit;
74
Added:
beSecondary;
75
Added:
callback: [ self answer: nil ];
76
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
77
Added:
]
src/MyFitnessTracker/MFTExerciseDialogOld.class.st
@@ -0,0 +1,170 @@
1
Added:
Class {
2
Added:
#name : #MFTExerciseDialogOld,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'exercise',
6
Added:
'sets'
7
Added:
],
8
Added:
#category : #'MyFitnessTracker-Dialog'
9
Added:
}
10
Added:
11
Added:
{ #category : #actions }
12
Added:
MFTExerciseDialogOld class >> edit: aMFTExercise [
13
Added:
14
Added:
^ self new
15
Added:
exercise: aMFTExercise;
16
Added:
sets: aMFTExercise sets;
17
Added:
action: #edit;
18
Added:
yourself
19
Added:
]
20
Added:
21
Added:
{ #category : #accessing }
22
Added:
MFTExerciseDialogOld >> exercise [
23
Added:
24
Added:
^ exercise
25
Added:
]
26
Added:
27
Added:
{ #category : #accessing }
28
Added:
MFTExerciseDialogOld >> exercise: anObject [
29
Added:
30
Added:
exercise := anObject
31
Added:
]
32
Added:
33
Added:
{ #category : #initialization }
34
Added:
MFTExerciseDialogOld >> initialize [
35
Added:
36
Added:
super initialize.
37
Added:
exercise := MFTExercise new.
38
Added:
sets := OrderedCollection new
39
Added:
]
40
Added:
41
Added:
{ #category : #rendering }
42
Added:
MFTExerciseDialogOld >> renderAddSetRowOn: html [
43
Added:
44
Added:
html tableRow: [
45
Added:
html tableData: [
46
Added:
html outlineButton
47
Added:
bePrimary;
48
Added:
beSmall;
49
Added:
callback: [ sets add: MFTSet new ];
50
Added:
with: 'Add' ].
51
Added:
html
52
Added:
tableData;
53
Added:
tableData;
54
Added:
tableData ]
55
Added:
]
56
Added:
57
Added:
{ #category : #rendering }
58
Added:
MFTExerciseDialogOld >> renderContentOn: html [
59
Added:
60
Added:
self renderDialogOn: html with: [
61
Added:
self renderExercisesSelectOn: html.
62
Added:
self renderSetGroupTableOn: html ]
63
Added:
]
64
Added:
65
Added:
{ #category : #rendering }
66
Added:
MFTExerciseDialogOld >> renderExerciseSelectOn: html [
67
Added:
68
Added:
| allExercises selectedExercise |
69
Added:
allExercises := MFTUtils allExercises.
70
Added:
selectedExercise := allExercises
71
Added:
detect: [ :each |
72
Added:
each englishName = exercise englishName ]
73
Added:
ifNone: [ nil ].
74
Added:
html formGroup: [
75
Added:
html label: 'Exercise'.
76
Added:
html select formControl
77
Added:
list: allExercises;
78
Added:
selected: selectedExercise;
79
Added:
callback: [ :value | exercise := value ];
80
Added:
labels: [ :each | each englishName ] ]
81
Added:
]
82
Added:
83
Added:
{ #category : #rendering }
84
Added:
MFTExerciseDialogOld >> renderSetsRowsOn: html [
85
Added:
"TODO: something fishy is going on here. Why are reps and rpe instantiated as nil, but become the empty string after adding additional empty sets?"
86
Added:
87
Added:
sets doWithIndex: [ :set :i |
88
Added:
html tableRow: [
89
Added:
html tableData: [
90
Added:
html buttonGroup: [
91
Added:
html outlineButton
92
Added:
beDanger;
93
Added:
beSmall;
94
Added:
callback: [ sets removeAt: i ];
95
Added:
with: 'Remove'.
96
Added:
html outlineButton
97
Added:
beSecondary;
98
Added:
beSmall;
99
Added:
callback: [ sets add: set copy afterIndex: i ];
100
Added:
with: 'Duplicate' ] ].
101
Added:
html tableData: [
102
Added:
html numberInput formControl
103
Added:
value: set reps;
104
Added:
callback: [ :value | set reps: value asInteger ] ].
105
Added:
html tableData: [
106
Added:
html numberInput formControl
107
Added:
value: set weight;
108
Added:
callback: [ :value |
109
Added:
value
110
Added:
ifNotEmpty: [ set weight: value asNumber ]
111
Added:
ifEmpty: [ set weight: nil ] ] ].
112
Added:
html tableData: [
113
Added:
html numberInput formControl
114
Added:
value: set rpe;
115
Added:
callback: [ :value |
116
Added:
value
117
Added:
ifNotEmpty: [ set rpe: value asInteger ]
118
Added:
ifEmpty: [ set rpe: nil ] ] ] ] ]
119
Added:
]
120
Added:
121
Added:
{ #category : #rendering }
122
Added:
MFTExerciseDialogOld >> renderSetsTableOn: html [
123
Added:
124
Added:
html formGroup: [
125
Added:
html label: 'Sets'.
126
Added:
html table
127
Added:
class: 'table table-hover';
128
Added:
with: [
129
Added:
sets ifNotEmpty: [ self renderTableHeaderOn: html ].
130
Added:
self renderSetsRowsOn: html.
131
Added:
self renderAddSetRowOn: html ] ]
132
Added:
]
133
Added:
134
Added:
{ #category : #delegation }
135
Added:
MFTExerciseDialogOld >> renderSubmitOn: html [
136
Added:
137
Added:
html buttonGroup: [
138
Added:
html formButton
139
Added:
beSubmit;
140
Added:
bePrimary;
141
Added:
callback: [ self answer: (exercise sets: sets) ];
142
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
143
Added:
html formButton
144
Added:
beSubmit;
145
Added:
beSecondary;
146
Added:
callback: [ self answer: MFTExercise new ];
147
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
148
Added:
]
149
Added:
150
Added:
{ #category : #rendering }
151
Added:
MFTExerciseDialogOld >> renderTableHeaderOn: html [
152
Added:
153
Added:
html tableHead: [
154
Added:
html
155
Added:
tableHeading;
156
Added:
tableHeading: 'Reps';tableHeading: 'Weight';
157
Added:
tableHeading: 'RPE' ]
158
Added:
]
159
Added:
160
Added:
{ #category : #accessing }
161
Added:
MFTExerciseDialogOld >> sets [
162
Added:
163
Added:
^ sets
164
Added:
]
165
Added:
166
Added:
{ #category : #accessing }
167
Added:
MFTExerciseDialogOld >> sets: anObject [
168
Added:
169
Added:
sets := anObject
170
Added:
]
src/MyFitnessTracker/MFTExercisesDialog.class.st
@@ -0,0 +1,147 @@
1
Added:
Class {
2
Added:
#name : #MFTExercisesDialog,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'exercises'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Dialog'
8
Added:
}
9
Added:
10
Added:
{ #category : #actions }
11
Added:
MFTExercisesDialog class >> edit: aMFTExerciseCollection [
12
Added:
13
Added:
self halt.
14
Added:
^ self new
15
Added:
exercises: aMFTExerciseCollection;
16
Added:
action: #edit;
17
Added:
yourself
18
Added:
]
19
Added:
20
Added:
{ #category : #adding }
21
Added:
MFTExercisesDialog >> addExercise [
22
Added:
23
Added:
| exercise |
24
Added:
exercise := self call: MFTExerciseDialog new.
25
Added:
exercise ifNotNil: [ exercises add: exercise ]
26
Added:
]
27
Added:
28
Added:
{ #category : #accessing }
29
Added:
MFTExercisesDialog >> editExerciseAt: i [
30
Added:
31
Added:
| oldExercise newExercise |
32
Added:
oldExercise := exercises at: i.
33
Added:
newExercise := self call: (MFTExerciseDialog edit: oldExercise).
34
Added:
newExercise ifNotNil: [ exercises at: i put: newExercise ]
35
Added:
]
36
Added:
37
Added:
{ #category : #accessing }
38
Added:
MFTExercisesDialog >> exercises [
39
Added:
40
Added:
^ exercises
41
Added:
]
42
Added:
43
Added:
{ #category : #accessing }
44
Added:
MFTExercisesDialog >> exercises: aCollection [
45
Added:
46
Added:
exercises := aCollection
47
Added:
]
48
Added:
49
Added:
{ #category : #initialization }
50
Added:
MFTExercisesDialog >> initialize [
51
Added:
52
Added:
super initialize.
53
Added:
exercises := OrderedCollection new
54
Added:
]
55
Added:
56
Added:
{ #category : #rendering }
57
Added:
MFTExercisesDialog >> renderAddExerciseRowOn: html [
58
Added:
59
Added:
html buttonGroup: [
60
Added:
html outlineButton
61
Added:
bePrimary;
62
Added:
beSmall;
63
Added:
callback: [ self addExercise ];
64
Added:
with: 'Add' ]
65
Added:
]
66
Added:
67
Added:
{ #category : #rendering }
68
Added:
MFTExercisesDialog >> renderContentOn: html [
69
Added:
70
Added:
self renderDialogOn: html with: [
71
Added:
html table
72
Added:
class: 'table table-hover';
73
Added:
with: [ exercises ifNotEmpty: [ self renderExerciseTableOn: html ] ].
74
Added:
self renderAddExerciseRowOn: html ]
75
Added:
]
76
Added:
77
Added:
{ #category : #rendering }
78
Added:
MFTExercisesDialog >> renderExerciseActionsButtonGroupOn: html at: i [
79
Added:
80
Added:
html buttonGroup: [
81
Added:
html outlineButton
82
Added:
beSecondary;
83
Added:
beSmall;
84
Added:
callback: [ exercises removeAt: i ];
85
Added:
with: 'Delete'.
86
Added:
html outlineButton
87
Added:
beSecondary;
88
Added:
beSmall;
89
Added:
callback: [ self editExerciseAt: i ];
90
Added:
with: 'Edit' ]
91
Added:
]
92
Added:
93
Added:
{ #category : #rendering }
94
Added:
MFTExercisesDialog >> renderExerciseTableOn: html [
95
Added:
96
Added:
self renderExercisesTableHeaderOn: html.
97
Added:
exercises doWithIndex: [ :exercise :i |
98
Added:
html tableRow: [
99
Added:
html tableData: [
100
Added:
self renderExerciseActionsButtonGroupOn: html at: i ].
101
Added:
html tableData: exercise englishName.
102
Added:
html tableData: exercise primaryMuscle englishName.
103
Added:
((exercises collect: #sets) anySatisfy: #isNotEmpty) ifTrue: [
104
Added:
html tableData
105
Added:
style: 'text-align: right';
106
Added:
with: exercise repsBySet size ].
107
Added:
((exercises collect: #volume) anySatisfy: [ :volume | volume ~~ 0 ])
108
Added:
ifTrue: [
109
Added:
html tableData
110
Added:
style: 'text-align: right';
111
Added:
with: exercise volume ] ] ]
112
Added:
]
113
Added:
114
Added:
{ #category : #rendering }
115
Added:
MFTExercisesDialog >> renderExercisesTableHeaderOn: html [
116
Added:
117
Added:
html tableHead: [
118
Added:
html
119
Added:
tableHeading;
120
Added:
tableHeading: 'Exercise';
121
Added:
tableHeading: 'Primary Muscle'.
122
Added:
((exercises collect: #sets) anySatisfy: #isNotEmpty) ifTrue: [
123
Added:
html tableHeading
124
Added:
style: 'text-align: right';
125
Added:
with: 'Sets' ].
126
Added:
((exercises collect: #volume) anySatisfy: [ :volume | volume ~~ 0 ])
127
Added:
ifTrue: [
128
Added:
html tableHeading
129
Added:
style: 'text-align: right';
130
Added:
with: 'Volume' ] ]
131
Added:
]
132
Added:
133
Added:
{ #category : #rendering }
134
Added:
MFTExercisesDialog >> renderSubmitOn: html [
135
Added:
136
Added:
html buttonGroup: [
137
Added:
html formButton
138
Added:
beSubmit;
139
Added:
bePrimary;
140
Added:
callback: [ self answer: exercises ];
141
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
142
Added:
html formButton
143
Added:
beSubmit;
144
Added:
beSecondary;
145
Added:
callback: [ self answer: OrderedCollection new ];
146
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
147
Added:
]
src/MyFitnessTracker/MFTSet.class.st
@@ -124,12 +124,39 @@
124
124
(self new
125
125
id: 9;
126
126
workoutId: 3;
127
Removed:
exerciseId: 12;
127
Added:
exerciseId: 16;
128
128
groupId: 2;
129
129
number: 3;
130
130
reps: 5;
131
131
load: 100;
132
Removed:
rpe: 10) }.
132
Added:
rpe: 8).
133
Added:
(self new
134
Added:
id: 10;
135
Added:
workoutId: 3;
136
Added:
exerciseId: 17;
137
Added:
groupId: 2;
138
Added:
number: 4;
139
Added:
reps: 5;
140
Added:
load: 120;
141
Added:
rpe: 9).
142
Added:
(self new
143
Added:
id: 11;
144
Added:
workoutId: 3;
145
Added:
exerciseId: 16;
146
Added:
groupId: 2;
147
Added:
number: 3;
148
Added:
reps: 6;
149
Added:
load: 110;
150
Added:
rpe: 9).
151
Added:
(self new
152
Added:
id: 12;
153
Added:
workoutId: 3;
154
Added:
exerciseId: 17;
155
Added:
groupId: 2;
156
Added:
number: 4;
157
Added:
reps: 5;
158
Added:
load: 120;
159
Added:
rpe: 9) }.
133
160
134
161
^ OrderedCollection withAll: {
135
162
forWorkout1.
@@ -189,6 +216,12 @@
189
216
190
217
^ MFTSQLite3Database allExercises detect: [ :exercise |
191
218
exercise id = exerciseId ]
219
Added:
]
220
Added:
221
Added:
{ #category : #accessing }
222
Added:
MFTSet >> exercise: aMFTExercise [
223
Added:
224
Added:
exerciseId := aMFTExercise id
192
225
]
193
226
194
227
{ #category : #accessing }
src/MyFitnessTracker/MFTSetDialog.class.st
@@ -20,57 +20,43 @@
20
20
MFTSetDialog >> initialize [
21
21
22
22
super initialize.
23
Removed:
set := MFTSet new
23
Added:
set := MFTSet new reps: 8
24
24
]
25
25
26
26
{ #category : #rendering }
27
27
MFTSetDialog >> renderContentOn: html [
28
28
29
29
self renderDialogOn: html with: [
30
Removed:
self renderExerciseSelectOn: html.
31
Removed:
html formGroup: [
32
Removed:
html label: 'Reps'.
33
Removed:
html numberInput formControl
34
Removed:
value: set reps;
35
Removed:
callback: [ :value | set reps: value asInteger ] ].
36
Removed:
html formGroup: [
37
Removed:
html label: 'Load'.
38
Removed:
html numberInput formControl
39
Removed:
value: set load;
40
Removed:
callback: [ :value |
41
Removed:
value ifNotEmpty: [ set load: value asNumber ] ] ].
42
Removed:
html formGroup: [
43
Removed:
html label: 'RPE'.
44
Removed:
html numberInput formControl
45
Removed:
value: set rpe;
46
Removed:
callback: [ :value |
47
Removed:
value ifNotEmpty: [ set rpe: value asInteger ] ] ].
48
Removed:
html formGroup: [
49
Removed:
html label: 'Rest after (s)'.
50
Removed:
html numberInput formControl
51
Removed:
value: set restAfter;
52
Removed:
callback: [ :value |
53
Removed:
value ifNotEmpty: [ set restAfter: value asNumber ] ] ] ]
30
Added:
html table: [
31
Added:
html tableRow: [
32
Added:
html tableHeading: 'Reps'.
33
Added:
html tableData: [
34
Added:
html numberInput formControl
35
Added:
value: set reps;
36
Added:
callback: [ :value | set reps: value asInteger ] ] ].
37
Added:
html tableRow: [
38
Added:
html tableHeading: 'Load'.
39
Added:
html tableData: [
40
Added:
html numberInput formControl
41
Added:
value: set load;
42
Added:
callback: [ :value |
43
Added:
value ifNotEmpty: [ set load: value asNumber ] ] ] ].
44
Added:
html tableRow: [
45
Added:
html tableHeading: 'RPE'.
46
Added:
html tableData: [
47
Added:
html numberInput formControl
48
Added:
value: set rpe;
49
Added:
callback: [ :value |
50
Added:
value ifNotEmpty: [ set rpe: value asInteger ] ] ] ].
51
Added:
html tableRow: [
52
Added:
html tableHeading: 'Rest after (s)'.
53
Added:
html tableData: [
54
Added:
html numberInput formControl
55
Added:
value: set restAfter;
56
Added:
callback: [ :value |
57
Added:
value ifNotEmpty: [ set restAfter: value asNumber ] ] ] ] ] ]
54
58
]
55
59
56
Removed:
{ #category : #rendering }
57
Removed:
MFTSetDialog >> renderExerciseSelectOn: html [
58
Removed:
59
Removed:
| allExercises selectedExercise |
60
Removed:
allExercises := MFTSQLite3Database allExercises.
61
Removed:
selectedExercise := allExercises
62
Removed:
detect: [ :exercise |
63
Removed:
exercise id = set exerciseId ]
64
Removed:
ifNone: [ nil ].
65
Removed:
html formGroup: [
66
Removed:
html label: 'Exercise'.
67
Removed:
html select formControl
68
Removed:
list: allExercises;
69
Removed:
selected: selectedExercise;
70
Removed:
callback: [ :exercise | set exerciseId: exercise id ];
71
Removed:
labels: [ :exercise | exercise englishName ] ]
72
Removed:
]
73
Removed:
74
60
{ #category : #delegation }
75
61
MFTSetDialog >> renderSubmitOn: html [
76
62
@@ -78,25 +64,13 @@
78
64
html formButton
79
65
beSubmit;
80
66
bePrimary;
81
Removed:
callback: [
82
Removed:
self answer: (set reps ifNotNil: [ set ] ifNil: [ nil ]) ];
67
Added:
callback: [ self answer: (set reps ifNotNil: [ set ]) ];
83
68
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
84
69
html formButton
85
70
beSubmit;
86
71
beSecondary;
87
72
callback: [ self answer: nil ];
88
73
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
89
Removed:
]
90
Removed:
91
Removed:
{ #category : #rendering }
92
Removed:
MFTSetDialog >> renderTableHeaderOn: html [
93
Removed:
94
Removed:
html tableHead: [
95
Removed:
html
96
Removed:
tableHeading;
97
Removed:
tableHeading: 'Reps';
98
Removed:
tableHeading: 'Weight';
99
Removed:
tableHeading: 'RPE' ]
100
74
]
101
75
102
76
{ #category : #accessing }
src/MyFitnessTracker/MFTSetGroup.class.st
@@ -17,6 +17,62 @@
17
17
yourself
18
18
]
19
19
20
Added:
{ #category : #adding }
21
Added:
MFTSetGroup >> addSet: aMFTSet [
22
Added:
23
Added:
sets add: aMFTSet
24
Added:
]
25
Added:
26
Added:
{ #category : #initialization }
27
Added:
MFTSetGroup >> description [
28
Added:
29
Added:
self isSuperset ifTrue: [
30
Added:
| ex1 ex2 |
31
Added:
ex1 := sets first exercise.
32
Added:
ex2 := sets second exercise.
33
Added:
ex1 primaryMuscleGroupId = ex2 primaryMuscleGroupId ifTrue: [
34
Added:
^ 'agonist superset ({1})' format:
35
Added:
{ ex1 primaryMuscleGroup englishName } ].
36
Added:
(MFTMuscleGroup antagonistIds includes: {
37
Added:
ex1 primaryMuscleGroupId.
38
Added:
ex2 primaryMuscleGroupId } asSet) ifTrue: [
39
Added:
^ 'antagonist superset' ].
40
Added:
^ 'superset' ].
41
Added:
self isTriSet ifTrue: [ ^ 'tri-set' ].
42
Added:
self isGiantSet ifTrue: [ ^ 'giant set' ].
43
Added:
^ 'regular set'
44
Added:
]
45
Added:
46
Added:
{ #category : #'as yet unclassified' }
47
Added:
MFTSetGroup >> duplicateSet: aMFTSet [
48
Added:
49
Added:
sets add: aMFTSet after: aMFTSet
50
Added:
]
51
Added:
52
Added:
{ #category : #testing }
53
Added:
MFTSetGroup >> hasLoad [
54
Added:
55
Added:
^ sets anySatisfy: #hasLoad
56
Added:
]
57
Added:
58
Added:
{ #category : #testing }
59
Added:
MFTSetGroup >> hasRestAfter [
60
Added:
61
Added:
^ sets anySatisfy: #hasRestAfter
62
Added:
]
63
Added:
64
Added:
{ #category : #testing }
65
Added:
MFTSetGroup >> hasRpe [
66
Added:
67
Added:
^ sets anySatisfy: #hasRpe
68
Added:
]
69
Added:
70
Added:
{ #category : #testing }
71
Added:
MFTSetGroup >> hasVolume [
72
Added:
73
Added:
^ sets anySatisfy: #hasVolume
74
Added:
]
75
Added:
20
76
{ #category : #accessing }
21
77
MFTSetGroup >> id [
22
78
@@ -37,23 +93,47 @@
37
93
]
38
94
39
95
{ #category : #testing }
40
Removed:
MFTSetGroup >> isGiantset [
96
Added:
MFTSetGroup >> isGiantSet [
41
97
42
98
^ self uniqueExercisesInSets >= 4
43
99
]
44
100
45
101
{ #category : #testing }
102
Added:
MFTSetGroup >> isIrregularSetGroup [
103
Added:
104
Added:
^ self isRegularSetGroup not
105
Added:
]
106
Added:
107
Added:
{ #category : #testing }
108
Added:
MFTSetGroup >> isRegularSetGroup [
109
Added:
110
Added:
^ self uniqueExercisesInSets = 1
111
Added:
]
112
Added:
113
Added:
{ #category : #testing }
46
114
MFTSetGroup >> isSuperset [
47
115
48
116
^ self uniqueExercisesInSets = 2
49
117
]
50
118
51
119
{ #category : #testing }
52
Removed:
MFTSetGroup >> isTriset [
120
Added:
MFTSetGroup >> isTriSet [
53
121
54
122
^ self uniqueExercisesInSets = 3
55
123
]
56
124
125
Added:
{ #category : #adding }
126
Added:
MFTSetGroup >> removeSet: aMFTSet [
127
Added:
128
Added:
sets remove: aMFTSet
129
Added:
]
130
Added:
131
Added:
{ #category : #adding }
132
Added:
MFTSetGroup >> removeSets: aMFTSetCollection [
133
Added:
134
Added:
sets removeAll: aMFTSetCollection
135
Added:
]
136
Added:
57
137
{ #category : #accessing }
58
138
MFTSetGroup >> sets [
59
139
@@ -69,20 +149,9 @@
69
149
{ #category : #initialization }
70
150
MFTSetGroup >> type [
71
151
72
Removed:
self isSuperset ifTrue: [
73
Removed:
| ex1 ex2 |
74
Removed:
ex1 := sets first exercise.
75
Removed:
ex2 := sets second exercise.
76
Removed:
ex1 primaryMuscleGroupId = ex2 primaryMuscleGroupId ifTrue: [
77
Removed:
^ 'agonist superset ({1})' format:
78
Removed:
{ ex1 primaryMuscleGroup englishName } ].
79
Removed:
(MFTMuscleGroup antagonistIds includes: {
80
Removed:
ex1 primaryMuscleGroupId.
81
Removed:
ex2 primaryMuscleGroupId } asSet) ifTrue: [
82
Removed:
^ 'antagonist superset' ].
83
Removed:
^ 'superset' ].
84
Removed:
self isTriset ifTrue: [ ^ 'tri-set' ].
85
Removed:
self isGiantset ifTrue: [ ^ 'giant set' ].
152
Added:
self isSuperset ifTrue: [ ^ 'superset' ].
153
Added:
self isTriSet ifTrue: [ ^ 'tri-set' ].
154
Added:
self isGiantSet ifTrue: [ ^ 'giant set' ].
86
155
^ 'regular set'
87
156
]
88
157
@@ -93,4 +162,16 @@
93
162
| uniqueExerciseIds |
94
163
uniqueExerciseIds := (sets collect: #exerciseId) asSet.
95
164
^ uniqueExerciseIds size
165
Added:
]
166
Added:
167
Added:
{ #category : #'as yet unclassified' }
168
Added:
MFTSetGroup >> updateSet: aMFTSet1 with: aMFTSet2 [
169
Added:
170
Added:
sets at: (sets indexOf: aMFTSet1) put: aMFTSet2
171
Added:
]
172
Added:
173
Added:
{ #category : #'as yet unclassified' }
174
Added:
MFTSetGroup >> volume [
175
Added:
176
Added:
^ (sets collect: #volume) sum
96
177
]
src/MyFitnessTracker/MFTSetGroupDialog.class.st
@@ -0,0 +1,304 @@
1
Added:
Class {
2
Added:
#name : #MFTSetGroupDialog,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'allExercises',
6
Added:
'selectedExercises',
7
Added:
'setGroups'
8
Added:
],
9
Added:
#category : #'MyFitnessTracker-Dialog'
10
Added:
}
11
Added:
12
Added:
{ #category : #adding }
13
Added:
MFTSetGroupDialog >> addSet [
14
Added:
15
Added:
| set |
16
Added:
set := self call: MFTSetDialog new.
17
Added:
set ifNil: [ ^ self ].
18
Added:
setGroups ifEmpty: [
19
Added:
setGroups := OrderedCollection with: MFTSetGroup new ].
20
Added:
setGroups first addSet: (set exercise: selectedExercises first)
21
Added:
]
22
Added:
23
Added:
{ #category : #adding }
24
Added:
MFTSetGroupDialog >> addSetGroup: aMFTExerciseCollection [
25
Added:
26
Added:
| sets |
27
Added:
sets := self call:
28
Added:
((MFTSetsDialog newForIrregularSetGroup:
29
Added:
aMFTExerciseCollection) subheading:
30
Added:
((selectedExercises collect: #englishName) joinUsing: '/')).
31
Added:
sets ifEmpty: [ ^ self ].
32
Added:
setGroups add: (MFTSetGroup new sets: sets)
33
Added:
]
34
Added:
35
Added:
{ #category : #'as yet unclassified' }
36
Added:
MFTSetGroupDialog >> duplicateSetGroup: aMFTSetGroup [
37
Added:
38
Added:
setGroups add: aMFTSetGroup after: aMFTSetGroup
39
Added:
]
40
Added:
41
Added:
{ #category : #actions }
42
Added:
MFTSetGroupDialog >> edit: aMFTSetGroup [
43
Added:
44
Added:
nil
45
Added:
]
46
Added:
47
Added:
{ #category : #actions }
48
Added:
MFTSetGroupDialog >> editSetGroup: aMFTSetGroup [
49
Added:
50
Added:
| setOrGroup |
51
Added:
setOrGroup := aMFTSetGroup isRegularSetGroup
52
Added:
ifTrue: [
53
Added:
self call: (MFTSetDialog edit: aMFTSetGroup) ]
54
Added:
ifFalse: [
55
Added:
self call: (MFTSetsDialog edit: aMFTSetGroup) ]
56
Added:
]
57
Added:
58
Added:
{ #category : #initialization }
59
Added:
MFTSetGroupDialog >> initialize [
60
Added:
61
Added:
super initialize.
62
Added:
setGroups := OrderedCollection with:
63
Added:
(MFTSetGroup new sets:
64
Added:
(OrderedCollection with: (MFTSet new reps: 8))).
65
Added:
allExercises := MFTSQLite3Database allExercises.
66
Added:
selectedExercises := OrderedCollection with: allExercises first
67
Added:
]
68
Added:
69
Added:
{ #category : #rendering }
70
Added:
MFTSetGroupDialog >> makeGiantSet [
71
Added:
72
Added:
self heading: 'Giant Sets'.
73
Added:
selectedExercises := OrderedCollection withAll:
74
Added:
(allExercises copyFrom: 1 to: 5).
75
Added:
setGroups first sets: (selectedExercises collect: [ :exercise |
76
Added:
MFTSet new
77
Added:
reps: 8;
78
Added:
exercise: exercise ])
79
Added:
]
80
Added:
81
Added:
{ #category : #rendering }
82
Added:
MFTSetGroupDialog >> makeRegularExercise [
83
Added:
84
Added:
self heading: 'Sets'.
85
Added:
selectedExercises := OrderedCollection with: allExercises first.
86
Added:
self populateSetGroupsForExercises: selectedExercises
87
Added:
]
88
Added:
89
Added:
{ #category : #rendering }
90
Added:
MFTSetGroupDialog >> makeSuperset [
91
Added:
92
Added:
self heading: 'Supersets'.
93
Added:
selectedExercises := OrderedCollection
94
Added:
with: allExercises first
95
Added:
with: allExercises second.
96
Added:
self populateSetGroupsForExercises: selectedExercises
97
Added:
]
98
Added:
99
Added:
{ #category : #rendering }
100
Added:
MFTSetGroupDialog >> makeTriset [
101
Added:
102
Added:
self heading: 'Tri-sets'.
103
Added:
selectedExercises := OrderedCollection
104
Added:
with: allExercises first
105
Added:
with: allExercises second
106
Added:
with: allExercises third.
107
Added:
self populateSetGroupsForExercises: selectedExercises
108
Added:
]
109
Added:
110
Added:
{ #category : #'as yet unclassified' }
111
Added:
MFTSetGroupDialog >> populateSetGroupsForExercises: aMFTExerciseCollection [
112
Added:
113
Added:
setGroups := OrderedCollection with:
114
Added:
(MFTSetGroup new sets:
115
Added:
(aMFTExerciseCollection collect: [ :exercise |
116
Added:
MFTSet new
117
Added:
reps: 8;
118
Added:
exercise: exercise ]))
119
Added:
]
120
Added:
121
Added:
{ #category : #removing }
122
Added:
MFTSetGroupDialog >> removeSetGroup: aMFTSetGroup [
123
Added:
124
Added:
setGroups remove: aMFTSetGroup
125
Added:
]
126
Added:
127
Added:
{ #category : #rendering }
128
Added:
MFTSetGroupDialog >> renderConfigureSetGroupButtonsOn: html [
129
Added:
130
Added:
selectedExercises size = 1
131
Added:
ifTrue: [
132
Added:
html outlineButton bePrimary beSmall
133
Added:
class: 'me-2';
134
Added:
callback: [ self addSet ];
135
Added:
with: 'Add set' ]
136
Added:
ifFalse: [
137
Added:
html outlineButton bePrimary beSmall
138
Added:
class: 'me-2';
139
Added:
callback: [ self addSetGroup: selectedExercises ];
140
Added:
with: 'Add set group' ].
141
Added:
html buttonGroup: [
142
Added:
selectedExercises size ~~ 1 ifTrue: [
143
Added:
html outlineButton beSecondary beSmall
144
Added:
callback: [ self makeRegularExercise ];
145
Added:
with: 'Regular exercise' ].
146
Added:
selectedExercises size ~~ 2 ifTrue: [
147
Added:
html outlineButton beSecondary beSmall
148
Added:
callback: [ self makeSuperset ];
149
Added:
with: 'Superset' ].
150
Added:
selectedExercises size ~~ 3 ifTrue: [
151
Added:
html outlineButton beSecondary beSmall
152
Added:
callback: [ self makeTriset ];
153
Added:
with: 'Tri-set' ].
154
Added:
selectedExercises size < 4 ifTrue: [
155
Added:
html outlineButton beSecondary beSmall
156
Added:
callback: [ self makeGiantSet ];
157
Added:
with: 'Giant set' ] ]
158
Added:
]
159
Added:
160
Added:
{ #category : #rendering }
161
Added:
MFTSetGroupDialog >> renderContentOn: html [
162
Added:
163
Added:
self renderDialogOn: html with: [
164
Added:
self renderSelectExercisesOn: html.
165
Added:
html horizontalRule.
166
Added:
(setGroups collect: #sets) ifNotEmpty: [
167
Added:
self renderSetGroupTableOn: html ].
168
Added:
self renderConfigureSetGroupButtonsOn: html ]
169
Added:
]
170
Added:
171
Added:
{ #category : #rendering }
172
Added:
MFTSetGroupDialog >> renderSelectExercisesOn: html [
173
Added:
" selectedExercises := allExercises
174
Added:
detect: [ :exercise |
175
Added:
exercise id = selectedExercise id ]
176
Added:
ifNone: [ allExercises first ]."
177
Added:
178
Added:
selectedExercises doWithIndex: [ :selectedExercise :i |
179
Added:
html formGroup: [
180
Added:
html label: 'Exercise ' , (selectedExercises size > 1
181
Added:
ifTrue: [ i asString ]
182
Added:
ifFalse: [ '' ]).
183
Added:
html select formControl
184
Added:
list: allExercises;
185
Added:
selected: selectedExercise;
186
Added:
callback: [ :exercise | selectedExercises at: i put: exercise ];
187
Added:
labels: [ :each | each englishName ] ] ]
188
Added:
]
189
Added:
190
Added:
{ #category : #rendering }
191
Added:
MFTSetGroupDialog >> renderSetGroupRowsOn: html [
192
Added:
193
Added:
| renderLoad |
194
Added:
renderLoad := setGroups anySatisfy: #hasLoad.
195
Added:
setGroups do: [ :group |
196
Added:
html tableRow with: [
197
Added:
html tableData
198
Added:
attributeAt: 'rowspan' put: group sets size + 1;
199
Added:
style: 'vertical-align: middle';
200
Added:
with: [
201
Added:
html buttonGroup: [
202
Added:
html outlineButton
203
Added:
beDanger;
204
Added:
beSmall;
205
Added:
callback: [ self removeSetGroup: group ];
206
Added:
with: 'Remove'.
207
Added:
html outlineButton
208
Added:
beSecondary;
209
Added:
beSmall;
210
Added:
callback: [ self editSetGroup: group ];
211
Added:
with: 'Edit'.
212
Added:
html outlineButton
213
Added:
beSecondary;
214
Added:
beSmall;
215
Added:
callback: [ self duplicateSetGroup: group ];
216
Added:
with: 'Duplicate' ] ] ].
217
Added:
group sets do: [ :set |
218
Added:
html tableRow: [ "This row spans the amount of sets for a given exercise."
219
Added:
group isIrregularSetGroup ifTrue: [
220
Added:
html tableData with: set exercise englishName capitalized ].
221
Added:
html tableData
222
Added:
style: 'text-align: right';
223
Added:
with: set reps.
224
Added:
renderLoad ifTrue: [
225
Added:
html tableData
226
Added:
style: 'text-align: right';
227
Added:
with: set load ] ] ] ]
228
Added:
]
229
Added:
230
Added:
{ #category : #rendering }
231
Added:
MFTSetGroupDialog >> renderSetGroupTableHeaderOn: html [
232
Added:
233
Added:
| allSets |
234
Added:
allSets := setGroups collect: #sets.
235
Added:
html tableHead: [
236
Added:
html tableHeading.
237
Added:
(setGroups anySatisfy: #isIrregularSetGroup) ifTrue: [
238
Added:
html tableHeading with: 'Exercise' ].
239
Added:
html tableHeading
240
Added:
style: 'text-align: right';
241
Added:
with: 'Reps'.
242
Added:
(setGroups anySatisfy: #hasLoad) ifTrue: [
243
Added:
html tableHeading
244
Added:
style: 'text-align: right';
245
Added:
with: 'Load' ].
246
Added:
(setGroups anySatisfy: #hasRpe) ifTrue: [
247
Added:
html tableHeading
248
Added:
style: 'text-align: right';
249
Added:
with: 'RPE' ].
250
Added:
(setGroups anySatisfy: #hasRestAfter) ifTrue: [
251
Added:
html tableHeading
252
Added:
style: 'text-align: right';
253
Added:
with: 'Rest After (s)' ] ]
254
Added:
]
255
Added:
256
Added:
{ #category : #rendering }
257
Added:
MFTSetGroupDialog >> renderSetGroupTableOn: html [
258
Added:
259
Added:
html table
260
Added:
class: 'table table-bordered';
261
Added:
with: [
262
Added:
self renderSetGroupTableHeaderOn: html.
263
Added:
self renderSetGroupRowsOn: html ]
264
Added:
]
265
Added:
266
Added:
{ #category : #rendering }
267
Added:
MFTSetGroupDialog >> renderSubmitOn: html [
268
Added:
269
Added:
html buttonGroup: [
270
Added:
html formButton
271
Added:
beSubmit;
272
Added:
bePrimary;
273
Added:
callback: [ self answer: setGroups ];
274
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
275
Added:
html formButton
276
Added:
beSubmit;
277
Added:
beSecondary;
278
Added:
callback: [ self answer: nil ];
279
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
280
Added:
]
281
Added:
282
Added:
{ #category : #accessing }
283
Added:
MFTSetGroupDialog >> selectedExercises [
284
Added:
285
Added:
^ selectedExercises
286
Added:
]
287
Added:
288
Added:
{ #category : #accessing }
289
Added:
MFTSetGroupDialog >> selectedExercises: aMFTExerciseCollection [
290
Added:
291
Added:
selectedExercises := aMFTExerciseCollection
292
Added:
]
293
Added:
294
Added:
{ #category : #accessing }
295
Added:
MFTSetGroupDialog >> setGroups [
296
Added:
297
Added:
^ setGroups
298
Added:
]
299
Added:
300
Added:
{ #category : #accessing }
301
Added:
MFTSetGroupDialog >> setGroups: anObject [
302
Added:
303
Added:
setGroups := anObject
304
Added:
]
src/MyFitnessTracker/MFTSetGroupsDialog.class.st
@@ -17,27 +17,13 @@
17
17
]
18
18
19
19
{ #category : #adding }
20
Removed:
MFTSetGroupsDialog >> addSetGroup [
20
Added:
MFTSetGroupsDialog >> addExercise [
21
21
22
Removed:
| setGroup setsSize |
23
Removed:
setsSize := setGroups size + 1.
24
Removed:
setGroup := self call:
25
Removed:
(MFTSetDialog new heading: 'Set #' , setsSize asString).
26
Removed:
setGroup ifNil: [ ^ self ].
27
Removed:
setGroup
28
Removed:
number: setsSize;
29
Removed:
group: setsSize.
30
Removed:
setGroup add: setGroup
22
Added:
| setGroup |
23
Added:
setGroup := self call: (MFTSetGroupDialog new heading: 'Exercise').
24
Added:
setGroup ifNotNil: [ setGroups add: setGroup ]
31
25
]
32
26
33
Removed:
{ #category : #adding }
34
Removed:
MFTSetGroupsDialog >> addSuperset [
35
Removed:
36
Removed:
| superset |
37
Removed:
superset := self call: MFTSupersetDialog new.
38
Removed:
superset ifNotNil: [ setGroups add: superset ]
39
Removed:
]
40
Removed:
41
27
{ #category : #initialization }
42
28
MFTSetGroupsDialog >> initialize [
43
29
@@ -46,24 +32,13 @@
46
32
]
47
33
48
34
{ #category : #rendering }
49
Removed:
MFTSetGroupsDialog >> renderAddSetGroupsButtonsOn: html [
35
Added:
MFTSetGroupsDialog >> renderAddSetGroupButtonsOn: html [
50
36
51
Removed:
html buttonGroup: [
52
Removed:
html outlineButton
53
Removed:
bePrimary;
54
Removed:
beSmall;
55
Removed:
callback: [ self addSetGroup ];
56
Removed:
with: 'Add exercise'.
57
Removed:
html outlineButton
58
Removed:
beSecondary;
59
Removed:
beSmall;
60
Removed:
callback: [ self addSuperset ];
61
Removed:
with: 'Add superset'.
62
Removed:
html outlineButton
63
Removed:
beSecondary;
64
Removed:
beSmall;
65
Removed:
callback: [ self addSuperset ];
66
Removed:
with: 'Add tri-set' ]
37
Added:
html outlineButton
38
Added:
bePrimary;
39
Added:
beSmall;
40
Added:
callback: [ self addExercise ];
41
Added:
with: 'Add exercise'
67
42
]
68
43
69
44
{ #category : #rendering }
@@ -71,7 +46,7 @@
71
46
72
47
self renderDialogOn: html with: [
73
48
setGroups ifNotEmpty: [ self renderSetsTableOn: html ].
74
Removed:
self renderAddSetGroupsButtonsOn: html ]
49
Added:
self renderAddSetGroupButtonsOn: html ]
75
50
]
76
51
77
52
{ #category : #rendering }
@@ -93,32 +68,58 @@
93
68
]
94
69
95
70
{ #category : #rendering }
96
Removed:
MFTSetGroupsDialog >> renderSetsRowsOn: html [
71
Added:
MFTSetGroupsDialog >> renderSetGroupButtonsOn: html For: setGroup [
97
72
73
Added:
^ html buttonGroup: [
74
Added:
html outlineButton
75
Added:
beDanger;
76
Added:
beSmall;
77
Added:
callback: [ setGroups remove: setGroup ];
78
Added:
with: 'Remove'.
79
Added:
html outlineButton
80
Added:
beSecondary;
81
Added:
beSmall;
82
Added:
callback: [
83
Added:
setGroups
84
Added:
add: setGroup
85
Added:
afterIndex: (setGroups indexOf: setGroup) ];
86
Added:
with: 'Duplicate' ]
87
Added:
]
88
Added:
89
Added:
{ #category : #rendering }
90
Added:
MFTSetGroupsDialog >> renderSetGroupsRowsOn: html [
91
Added:
98
92
| renderLoad renderRpe renderRestAfter |
99
93
renderLoad := self renderLoad.
100
94
renderRpe := self renderRpe.
101
95
renderRestAfter := self renderRestAfter.
102
96
setGroups do: [ :setGroup |
103
Removed:
html tableRow: [
104
Removed:
html tableData: [
105
Removed:
html buttonGroup: [
106
Removed:
html outlineButton
107
Removed:
beDanger;
108
Removed:
beSmall;
109
Removed:
callback: [ setGroups remove: setGroup ];
110
Removed:
with: 'Remove'.
111
Removed:
html outlineButton
112
Removed:
beSecondary;
113
Removed:
beSmall;
114
Removed:
callback: [
115
Removed:
setGroups
116
Removed:
add: setGroup
117
Removed:
afterIndex: (setGroups indexOf: setGroup) ];
118
Removed:
with: 'Duplicate' ] ] ] ]
97
Added:
html tableRow
98
Added:
attributeAt: 'rowspan' put: setGroup sets size + 1;
99
Added:
with: [
100
Added:
html tableData: [
101
Added:
self renderSetGroupButtonsOn: html For: setGroup ] ].
102
Added:
setGroup sets do: [ :set |
103
Added:
html tableRow: [
104
Added:
html tableData.
105
Added:
html tableData: set exercise englishName.
106
Added:
html tableData: set reps ] ] ]
119
107
]
120
108
121
109
{ #category : #rendering }
110
Added:
MFTSetGroupsDialog >> renderSetGroupsTableHeaderOn: html [
111
Added:
112
Added:
html tableHead: [
113
Added:
html
114
Added:
tableHeading;
115
Added:
tableHeading: 'Exercise';
116
Added:
tableHeading: 'Reps'.
117
Added:
self renderLoad ifTrue: [ html tableHeading: 'Load' ].
118
Added:
self renderRpe ifTrue: [ html tableHeading: 'RPE' ].
119
Added:
self renderRestAfter ifTrue: [ html tableHeading: 'Rest after (s) ' ] ]
120
Added:
]
121
Added:
122
Added:
{ #category : #rendering }
122
123
MFTSetGroupsDialog >> renderSetsTableHeaderOn: html [
123
124
124
125
html tableHead: [
@@ -137,8 +138,8 @@
137
138
html table
138
139
class: 'table table-hover table-bordered';
139
140
with: [
140
Removed:
self renderSetsTableHeaderOn: html.
141
Removed:
self renderSetsRowsOn: html ]
141
Added:
self renderSetGroupsTableHeaderOn: html.
142
Added:
self renderSetGroupsRowsOn: html ]
142
143
]
143
144
144
145
{ #category : #rendering }
src/MyFitnessTracker/MFTSetsDialog.class.st
@@ -0,0 +1,101 @@
1
Added:
Class {
2
Added:
#name : #MFTSetsDialog,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'sets'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Dialog'
8
Added:
}
9
Added:
10
Added:
{ #category : #actions }
11
Added:
MFTSetsDialog class >> edit: aMFTSetCollection [
12
Added:
13
Added:
^ self new
14
Added:
sets: aMFTSetCollection;
15
Added:
action: #edit;
16
Added:
yourself
17
Added:
]
18
Added:
19
Added:
{ #category : #actions }
20
Added:
MFTSetsDialog class >> newForIrregularSetGroup: aMFTExerciseCollection [
21
Added:
22
Added:
^ self new
23
Added:
sets: (aMFTExerciseCollection collect: [ :exercise |
24
Added:
MFTSet new
25
Added:
reps: 8;
26
Added:
exercise: exercise ]);
27
Added:
yourself
28
Added:
]
29
Added:
30
Added:
{ #category : #initialization }
31
Added:
MFTSetsDialog >> initialize [
32
Added:
33
Added:
super initialize.
34
Added:
sets := OrderedCollection new
35
Added:
]
36
Added:
37
Added:
{ #category : #rendering }
38
Added:
MFTSetsDialog >> renderContentOn: html [
39
Added:
40
Added:
self renderDialogOn: html with: [
41
Added:
html table
42
Added:
class: 'table table-bordered';
43
Added:
with: [
44
Added:
html tableRow: [
45
Added:
html
46
Added:
tableHeading: 'Exercise';
47
Added:
tableHeading: 'Reps';
48
Added:
tableHeading: 'Load';
49
Added:
tableHeading: 'RPE';
50
Added:
tableHeading: 'Rest after (s)' ].
51
Added:
sets do: [ :set |
52
Added:
html tableRow: [
53
Added:
html tableData: set exercise englishName.
54
Added:
html tableData: [
55
Added:
html numberInput formControl
56
Added:
value: set reps;
57
Added:
callback: [ :value | set reps: value asInteger ] ].
58
Added:
html tableData: [
59
Added:
html numberInput formControl
60
Added:
value: set load;
61
Added:
callback: [ :value |
62
Added:
value ifNotEmpty: [ set load: value asNumber ] ] ].
63
Added:
html tableData: [
64
Added:
html numberInput formControl
65
Added:
value: set rpe;
66
Added:
callback: [ :value |
67
Added:
value ifNotEmpty: [ set rpe: value asInteger ] ] ].
68
Added:
html tableData: [
69
Added:
html numberInput formControl
70
Added:
value: set restAfter;
71
Added:
callback: [ :value |
72
Added:
value ifNotEmpty: [ set restAfter: value asNumber ] ] ] ] ] ] ]
73
Added:
]
74
Added:
75
Added:
{ #category : #delegation }
76
Added:
MFTSetsDialog >> renderSubmitOn: html [
77
Added:
78
Added:
html buttonGroup: [
79
Added:
html formButton
80
Added:
beSubmit;
81
Added:
bePrimary;
82
Added:
callback: [ self answer: sets ];
83
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
84
Added:
html formButton
85
Added:
beSubmit;
86
Added:
beSecondary;
87
Added:
callback: [ self answer: nil ];
88
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
89
Added:
]
90
Added:
91
Added:
{ #category : #accessing }
92
Added:
MFTSetsDialog >> sets [
93
Added:
94
Added:
^ sets
95
Added:
]
96
Added:
97
Added:
{ #category : #accessing }
98
Added:
MFTSetsDialog >> sets: anObject [
99
Added:
100
Added:
sets := anObject
101
Added:
]
src/MyFitnessTracker/MFTWorkout.class.st
@@ -62,6 +62,18 @@
62
62
]
63
63
64
64
{ #category : #'as yet unclassified' }
65
Added:
MFTWorkout >> allSetGroupsAreRegular [
66
Added:
67
Added:
^ self anySetGroupIsIrregular not
68
Added:
]
69
Added:
70
Added:
{ #category : #'as yet unclassified' }
71
Added:
MFTWorkout >> anySetGroupIsIrregular [
72
Added:
73
Added:
^ setGroups anySatisfy: [ :group | group isRegularSetGroup not ]
74
Added:
]
75
Added:
76
Added:
{ #category : #'as yet unclassified' }
65
77
MFTWorkout >> anySetHasLoad [
66
78
67
79
^ self sets anySatisfy: #hasLoad
@@ -155,63 +167,68 @@
155
167
]
156
168
157
169
{ #category : #rendering }
158
Removed:
MFTWorkout >> renderSetGroupsTableOn: html [
170
Added:
MFTWorkout >> renderSetGroupRowsOn: html [
159
171
160
Removed:
| renderLoad renderVolume |
172
Added:
| renderSetGroupsType renderLoad renderVolume |
173
Added:
"No need to render the type of set group, if it is regular."
174
Added:
renderSetGroupsType := self allSetGroupsAreRegular not.
161
175
renderLoad := self anySetHasLoad.
162
176
renderVolume := self anySetHasVolume.
163
177
164
Removed:
html table
165
Removed:
class: 'table table-bordered';
166
Removed:
with: [
167
Removed:
self renderSetsTableHeaderOn: html.
168
Removed:
self setGroups do: [ :group |
169
Removed:
html tableRow: [
170
Removed:
html tableHeading
171
Removed:
attributeAt: 'rowspan' put: group sets size + 1;
172
Removed:
style: 'vertical-align: middle';
173
Removed:
with: [ html text: group type capitalized ] ].
174
Removed:
group sets do: [ :set |
175
Removed:
html tableRow: [
176
Removed:
html tableData: set exercise englishName capitalized.
177
Removed:
html tableData
178
Removed:
style: 'text-align: right';
179
Removed:
with: set reps.
180
Removed:
renderLoad ifTrue: [
181
Removed:
html tableData
182
Removed:
style: 'text-align: right';
183
Removed:
with: set load ].
184
Removed:
renderVolume ifTrue: [
185
Removed:
html tableData
186
Removed:
style: 'text-align: right';
187
Removed:
with: set volume ] ] ] ].
188
Removed:
self renderSetsTableFooterOn: html ]
178
Added:
self setGroups do: [ :group |
179
Added:
| setsGroupedByExercise |
180
Added:
setsGroupedByExercise := group sets groupedBy: #exercise.
181
Added:
renderSetGroupsType ifTrue: [
182
Added:
html tableRow: [ "This row spans the amount of sets for this group + the amount of exercises + 1."
183
Added:
html tableHeading
184
Added:
attributeAt: 'rowspan'
185
Added:
put: group sets size + setsGroupedByExercise keys size + 1;
186
Added:
style: 'vertical-align: middle';
187
Added:
with: [ html text: group type capitalized ] ] ].
188
Added:
setsGroupedByExercise keysAndValuesDo: [ :exercise :sets |
189
Added:
html tableRow: [ "This row spans the amount of sets for a given exercise."
190
Added:
html tableData
191
Added:
attributeAt: 'rowspan' put: sets size + 1;
192
Added:
style: 'vertical-align: middle';
193
Added:
with: exercise englishName capitalized ].
194
Added:
sets do: [ :set |
195
Added:
html tableRow: [
196
Added:
html tableData
197
Added:
style: 'text-align: right';
198
Added:
with: set reps.
199
Added:
renderLoad ifTrue: [
200
Added:
html tableData
201
Added:
style: 'text-align: right';
202
Added:
with: set load ].
203
Added:
renderVolume ifTrue: [
204
Added:
html tableData
205
Added:
style: 'text-align: right';
206
Added:
with: set volume ] ] ] ] ]
189
207
]
190
208
191
209
{ #category : #rendering }
192
Removed:
MFTWorkout >> renderSetsTableFooterOn: html [
210
Added:
MFTWorkout >> renderSetGroupsTableFooterOn: html [
193
211
194
Removed:
| totalReps totalVolume |
212
Added:
| totalReps |
195
213
totalReps := (self sets collect: #reps) sum.
196
Removed:
totalVolume := (self sets collect: #volume) sum.
197
214
html tableFoot: [
198
Removed:
html tableData.
215
Added:
self anySetGroupIsIrregular ifTrue: [ html tableHeading ].
199
216
html tableData: 'Total'.
200
217
html tableData
201
218
style: 'text-align: right';
202
219
with: totalReps.
203
220
self anySetHasLoad ifTrue: [ html tableData ].
204
Removed:
totalVolume ~~ 0 ifTrue: [
221
Added:
self volume ~~ 0 ifTrue: [
205
222
html tableData
206
223
style: 'text-align: right';
207
Removed:
with: totalVolume ] ]
224
Added:
with: self volume ] ]
208
225
]
209
226
210
227
{ #category : #rendering }
211
Removed:
MFTWorkout >> renderSetsTableHeaderOn: html [
228
Added:
MFTWorkout >> renderSetGroupsTableHeaderOn: html [
212
229
213
230
html tableHead: [
214
Removed:
html tableHeading.
231
Added:
self allSetGroupsAreRegular ifFalse: [ html tableHeading ].
215
232
html tableHeading: 'Exercise'.
216
233
html tableHeading
217
234
style: 'text-align: right';
@@ -224,6 +241,17 @@
224
241
html tableHeading
225
242
style: 'text-align: right';
226
243
with: 'Volume' ] ]
244
Added:
]
245
Added:
246
Added:
{ #category : #rendering }
247
Added:
MFTWorkout >> renderSetGroupsTableOn: html [
248
Added:
249
Added:
html table
250
Added:
class: 'table table-bordered';
251
Added:
with: [
252
Added:
self renderSetGroupsTableHeaderOn: html.
253
Added:
self renderSetGroupRowsOn: html.
254
Added:
self renderSetGroupsTableFooterOn: html ]
227
255
]
228
256
229
257
{ #category : #accessing }
src/MyFitnessTracker/MFTWorkoutTask.class.st
@@ -38,9 +38,10 @@
38
38
action: action;
39
39
date: workout date;
40
40
completion: 20)).
41
Removed:
workout sets: (self call: (MFTSetsDialog new
41
Added:
workout setGroups: (self call: (MFTSetGroupsDialog new
42
42
action: action;
43
Removed:
sets: workout sets;
43
Added:
heading: 'Exercises';
44
Added:
setGroups: workout setGroups;
44
45
completion: 40)).
45
46
primaryMuscleGroup := self call: (MFTPrimaryMuscleGroupDialog new
46
47
action: action;