Dialog components for adding a workout and its exercises.

Commit
efc01d7a2ff7e6104a75b9f7c019ca07d0cf5bb0
Author
Marius Peter <marius.peter@tutanota.com>
Author date
Committer
Marius Peter <marius.peter@tutanota.com>
Committer date
Changed files
src/MyFitnessTracker/MFTExerciseDialog.class.st
index 00000000..9112cd6a 000000..100644
@@ -0,0 +1,159 @@
1 Added: Class {
2 Added: #name : #MFTExerciseDialog,
3 Added: #superclass : #SBSComponent,
4 Added: #instVars : [
5 Added: 'exercise',
6 Added: 'sets',
7 Added: 'addOrEdit'
8 Added: ],
9 Added: #classInstVars : [
10 Added: 'exercise'
11 Added: ],
12 Added: #category : #'MyFitnessTracker-Dialogs'
13 Added: }
14 Added:
15 Added: { #category : #accessing }
16 Added: MFTExerciseDialog >> addOrEdit [
17 Added:
18 Added: ^ addOrEdit
19 Added: ]
20 Added:
21 Added: { #category : #accessing }
22 Added: MFTExerciseDialog >> addOrEdit: aRole [
23 Added:
24 Added: addOrEdit := aRole
25 Added: ]
26 Added:
27 Added: { #category : #accessing }
28 Added: MFTExerciseDialog >> exercise [
29 Added:
30 Added: ^ exercise
31 Added: ]
32 Added:
33 Added: { #category : #accessing }
34 Added: MFTExerciseDialog >> exercise: aMFTExercise [
35 Added:
36 Added: exercise := aMFTExercise
37 Added: ]
38 Added:
39 Added: { #category : #initialization }
40 Added: MFTExerciseDialog >> initialize [
41 Added:
42 Added: super initialize.
43 Added: exercise := MFTExercise new.
44 Added: sets := OrderedCollection new.
45 Added: addOrEdit := #add
46 Added: ]
47 Added:
48 Added: { #category : #rendering }
49 Added: MFTExerciseDialog >> renderAddSetRowOn: html [
50 Added:
51 Added: html tableRow: [
52 Added: html tableData: [
53 Added: html outlineButton
54 Added: bePrimary;
55 Added: beSmall;
56 Added: callback: [ sets add: MFTSet new ];
57 Added: with: 'Add' ].
58 Added: html
59 Added: tableData;
60 Added: tableData ]
61 Added: ]
62 Added:
63 Added: { #category : #rendering }
64 Added: MFTExerciseDialog >> renderContentOn: html [
65 Added:
66 Added: html container: [
67 Added: html heading: addOrEdit capitalized , ' exercise'.
68 Added: html form: [
69 Added: self renderExerciseSelectOn: html.
70 Added: self renderSetsTableOn: html.
71 Added: self renderSubmitExerciseOn: html ] ]
72 Added: ]
73 Added:
74 Added: { #category : #rendering }
75 Added: MFTExerciseDialog >> renderExerciseSelectOn: html [
76 Added:
77 Added: html formGroup: [
78 Added: html label: 'Exercise'.
79 Added: html select formControl
80 Added: list: MFTUtils allExercises;
81 Added: selected: exercise;
82 Added: labels: [ :each | each name ];
83 Added: callback: [ :value | exercise := value ] ]
84 Added: ]
85 Added:
86 Added: { #category : #rendering }
87 Added: MFTExerciseDialog >> renderSetsRowsOn: html [
88 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?"
89 Added:
90 Added: sets doWithIndex: [ :set :i |
91 Added: html tableRow: [
92 Added: html tableData: [
93 Added: html buttonGroup: [
94 Added: html outlineButton
95 Added: beSecondary;
96 Added: beSmall;
97 Added: callback: [ sets removeAt: i ];
98 Added: with: 'Remove'.
99 Added: html outlineButton
100 Added: beSecondary;
101 Added: beSmall;
102 Added: callback: [ sets add: set afterIndex: i ];
103 Added: with: 'Duplicate' ] ].
104 Added: html tableData: [
105 Added: html numberInput
106 Added: placeholder: 10;
107 Added: value: set reps;
108 Added: callback: [ :value | value ifNotNil: [ set reps: value ] ] ].
109 Added: html tableData: [
110 Added: html numberInput
111 Added: placeholder: 80;
112 Added: value: set rpe;
113 Added: callback: [ :value | value ifNotNil: [ set rpe: value ] ] ] ] ]
114 Added: ]
115 Added:
116 Added: { #category : #rendering }
117 Added: MFTExerciseDialog >> renderSetsTableOn: html [
118 Added:
119 Added: html formGroup: [
120 Added: html label: 'Sets'.
121 Added: html table
122 Added: class: 'table table-hover';
123 Added: with: [
124 Added: sets ifNotEmpty: [ self renderTableHeaderOn: html ].
125 Added: self renderSetsRowsOn: html.
126 Added: self renderAddSetRowOn: html ] ]
127 Added: ]
128 Added:
129 Added: { #category : #rendering }
130 Added: MFTExerciseDialog >> renderSubmitExerciseOn: html [
131 Added:
132 Added: html formGroup: [
133 Added: "html text: (sets collect: #reps).
134 Added: html break.
135 Added: html text: (sets collect: #rpe)."
136 Added: html buttonGroup: [
137 Added: html formButton
138 Added: bePrimary;
139 Added: beSubmit;
140 Added: callback: [
141 Added: sets removeAllSuchThat: [ :each |
142 Added: each reps isNil or: [ each reps = '' ] ].
143 Added: self answer: (exercise sets: sets) ];
144 Added: with: 'Submit'.
145 Added: html formButton
146 Added: beSecondary;
147 Added: callback: [ self answer: nil ];
148 Added: with: 'Cancel' ] ]
149 Added: ]
150 Added:
151 Added: { #category : #rendering }
152 Added: MFTExerciseDialog >> renderTableHeaderOn: html [
153 Added:
154 Added: html tableHead: [
155 Added: html
156 Added: tableHeading;
157 Added: tableHeading: 'Reps';
158 Added: tableHeading: 'RPE' ]
159 Added: ]
src/MyFitnessTracker/MFTWorkoutDialog.class.st
index 00000000..0a08f1f4 000000..100644
@@ -0,0 +1,195 @@
1 Added: Class {
2 Added: #name : #MFTWorkoutDialog,
3 Added: #superclass : #SBSComponent,
4 Added: #instVars : [
5 Added: 'workout',
6 Added: 'addOrEdit'
7 Added: ],
8 Added: #category : #'MyFitnessTracker-Dialogs'
9 Added: }
10 Added:
11 Added: { #category : #adding }
12 Added: MFTWorkoutDialog >> addExercise [
13 Added:
14 Added: | exercise |
15 Added: exercise := self call: MFTExerciseDialog new.
16 Added: exercise ifNotNil: [ workout exercises add: exercise ]
17 Added: ]
18 Added:
19 Added: { #category : #accessing }
20 Added: MFTWorkoutDialog >> addOrEdit [
21 Added:
22 Added: ^ addOrEdit
23 Added: ]
24 Added:
25 Added: { #category : #accessing }
26 Added: MFTWorkoutDialog >> addOrEdit: aRole [
27 Added:
28 Added: addOrEdit := aRole
29 Added: ]
30 Added:
31 Added: { #category : #'as yet unclassified' }
32 Added: MFTWorkoutDialog >> editExercise: i [
33 Added:
34 Added: | oldExercise newExercise |
35 Added: oldExercise := workout exercises at: i.
36 Added: newExercise := self call: (MFTExerciseDialog edit: oldExercise).
37 Added: newExercise ifNotNil: [ workout exercises at: i put: newExercise ]
38 Added: ]
39 Added:
40 Added: { #category : #initialization }
41 Added: MFTWorkoutDialog >> initialize [
42 Added:
43 Added: super initialize.
44 Added: workout := MFTWorkout new.
45 Added: addOrEdit := #add
46 Added: ]
47 Added:
48 Added: { #category : #rendering }
49 Added: MFTWorkoutDialog >> renderAddExerciseButtonOn: html [
50 Added:
51 Added: html outlineButton
52 Added: bePrimary;
53 Added: beSmall;
54 Added: callback: [ self addExercise ];
55 Added: with: 'Add'
56 Added: ]
57 Added:
58 Added: { #category : #rendering }
59 Added: MFTWorkoutDialog >> renderAddExerciseRowOn: html [
60 Added:
61 Added: html tableRow: [
62 Added: html tableData: [ self renderAddExerciseButtonOn: html ].
63 Added: 1 to: 3 do: [ :each | html tableData ] ]
64 Added: ]
65 Added:
66 Added: { #category : #rendering }
67 Added: MFTWorkoutDialog >> renderContentOn: html [
68 Added:
69 Added: html container: [
70 Added: html heading: 'Add workout'.
71 Added: html form: [
72 Added: self renderDateInputOn: html.
73 Added: self renderExercisesTableOn: html.
74 Added: self renderPrimaryMuscleSelectOn: html.
75 Added: "TODO: use the workout guessPrimaryMuscle."
76 Added: self renderSecondaryMusclesSelectOn: html.
77 Added: self renderSubmitWorkoutOn: html ] ]
78 Added: ]
79 Added:
80 Added: { #category : #rendering }
81 Added: MFTWorkoutDialog >> renderDateInputOn: html [
82 Added:
83 Added: html formGroup: [
84 Added: html label: 'Date'.
85 Added: html dateInput5 formControl
86 Added: value: workout date yyyymmdd;
87 Added: callback: [ :date | workout date: (Date fromString: date) ] ]
88 Added: ]
89 Added:
90 Added: { #category : #rendering }
91 Added: MFTWorkoutDialog >> renderExerciseActionsButtonGroupOn: html at: i [
92 Added:
93 Added: html buttonGroup: [
94 Added: html outlineButton
95 Added: beSecondary;
96 Added: beSmall;
97 Added: callback: [ workout exercises removeAt: i ];
98 Added: with: 'Delete'.
99 Added: html outlineButton
100 Added: beSecondary;
101 Added: beSmall;
102 Added: callback: [ self editExercise: i ];
103 Added: with: 'Edit' ]
104 Added: ]
105 Added:
106 Added: { #category : #rendering }
107 Added: MFTWorkoutDialog >> renderExercisesRowsOn: html [
108 Added:
109 Added: workout exercises doWithIndex: [ :exercise :i |
110 Added: html tableRow: [
111 Added: html tableData: [
112 Added: self renderExerciseActionsButtonGroupOn: html at: i ].
113 Added: html tableData: exercise name.
114 Added: html tableData: exercise primaryMuscle name.
115 Added: html tableData: exercise repsBySet asCommaString ] ]
116 Added: ]
117 Added:
118 Added: { #category : #rendering }
119 Added: MFTWorkoutDialog >> renderExercisesTableOn: html [
120 Added:
121 Added: html formGroup: [
122 Added: html label: 'Exercises'.
123 Added: html table
124 Added: class: 'table table-hover';
125 Added: with: [
126 Added: workout exercises isNotEmpty ifTrue: [
127 Added: self renderTableHeaderOn: html ].
128 Added: self renderExercisesRowsOn: html.
129 Added: self renderAddExerciseRowOn: html ] ]
130 Added: ]
131 Added:
132 Added: { #category : #rendering }
133 Added: MFTWorkoutDialog >> renderPrimaryMuscleSelectOn: html [
134 Added: "TODO: use the workout guessPrimaryMuscle."
135 Added:
136 Added: html formGroup: [
137 Added: html label: 'Primary muscle'.
138 Added: html select formControl
139 Added: list: MFTUtils allMuscleGroups;
140 Added: selected: workout primaryMuscle;
141 Added: labels: [ :muscleGroup | muscleGroup name ];
142 Added: callback: [ :group | workout primaryMuscle: group ] ]
143 Added: ]
144 Added:
145 Added: { #category : #rendering }
146 Added: MFTWorkoutDialog >> renderSecondaryMusclesSelectOn: html [
147 Added:
148 Added: html formGroup: [
149 Added: html label: 'Secondary muscles'.
150 Added: html multiSelect formControl
151 Added: list: MFTUtils allMuscleGroups;
152 Added: selected: workout secondaryMuscles;
153 Added: labels: [ :muscleGroup | muscleGroup name ];
154 Added: callback: [ :groups | workout secondaryMuscles: groups ] ]
155 Added: ]
156 Added:
157 Added: { #category : #rendering }
158 Added: MFTWorkoutDialog >> renderSubmitWorkoutOn: html [
159 Added:
160 Added: html formGroup: [
161 Added: html buttonGroup: [
162 Added: html formButton
163 Added: bePrimary;
164 Added: beSubmit;
165 Added: callback: [ self answer: workout ];
166 Added: with: 'Submit'.
167 Added: html formButton
168 Added: beSecondary;
169 Added: callback: [ self answer: nil ];
170 Added: with: 'Cancel' ] ]
171 Added: ]
172 Added:
173 Added: { #category : #rendering }
174 Added: MFTWorkoutDialog >> renderTableHeaderOn: html [
175 Added:
176 Added: html tableHead: [
177 Added: html
178 Added: tableHeading;
179 Added: tableHeading: 'Name';
180 Added: tableHeading: 'Muscles'.
181 Added: ((workout exercises collect: #sets) anySatisfy: #isNotEmpty)
182 Added: ifTrue: [ html tableHeading: 'Sets' ] ]
183 Added: ]
184 Added:
185 Added: { #category : #accessing }
186 Added: MFTWorkoutDialog >> workout [
187 Added:
188 Added: ^ workout
189 Added: ]
190 Added:
191 Added: { #category : #accessing }
192 Added: MFTWorkoutDialog >> workout: aMFTWorkout [
193 Added:
194 Added: workout := aMFTWorkout
195 Added: ]