[Pharo] Personal fitness tracker web app.
Transformed workout and weight logging pages into log components.
Changed files
src/MyFitnessTracker/MFTLog.class.st
@@ -0,0 +1,28 @@
1
Added:
Class {
2
Added:
#name : 'MFTLog',
3
Added:
#superclass : 'SBSComponent',
4
Added:
#instVars : [
5
Added:
'title'
6
Added:
],
7
Added:
#category : 'MyFitnessTracker-Components',
8
Added:
#package : 'MyFitnessTracker',
9
Added:
#tag : 'Components'
10
Added:
}
11
Added:
12
Added:
{ #category : 'rendering' }
13
Added:
MFTLog >> renderLogOn: html with: aBlock [
14
Added:
15
Added:
html div: aBlock
16
Added:
]
17
Added:
18
Added:
{ #category : 'accessing' }
19
Added:
MFTLog >> title [
20
Added:
21
Added:
^ title
22
Added:
]
23
Added:
24
Added:
{ #category : 'accessing' }
25
Added:
MFTLog >> title: anObject [
26
Added:
27
Added:
title := anObject
28
Added:
]
src/MyFitnessTracker/MFTLogsPage.class.st
@@ -0,0 +1,43 @@
1
Added:
Class {
2
Added:
#name : 'MFTLogsPage',
3
Added:
#superclass : 'MFTPage',
4
Added:
#instVars : [
5
Added:
'activeLog',
6
Added:
'logs'
7
Added:
],
8
Added:
#category : 'MyFitnessTracker-Components',
9
Added:
#package : 'MyFitnessTracker',
10
Added:
#tag : 'Components'
11
Added:
}
12
Added:
13
Added:
{ #category : 'initialization' }
14
Added:
MFTLogsPage >> initialize [
15
Added:
16
Added:
super initialize.
17
Added:
title := 'logs'.
18
Added:
logs := {
19
Added:
MFTWorkoutsLog new.
20
Added:
MFTWeightsLog new }.
21
Added:
activeLog := logs first
22
Added:
]
23
Added:
24
Added:
{ #category : 'rendering' }
25
Added:
MFTLogsPage >> renderContentOn: html [
26
Added:
27
Added:
self renderPageOn: html with: [
28
Added:
self renderLogNavigationOn: html.
29
Added:
html render: activeLog ]
30
Added:
]
31
Added:
32
Added:
{ #category : 'rendering' }
33
Added:
MFTLogsPage >> renderLogNavigationOn: html [
34
Added:
35
Added:
html form
36
Added:
class: 'mb-3';
37
Added:
with: [
38
Added:
html navigation flexColumn with: [
39
Added:
logs do: [ :log |
40
Added:
html navigationLink
41
Added:
callback: [ activeLog := log ];
42
Added:
with: log title ] ] ]
43
Added:
]
src/MyFitnessTracker/MFTWeightsListPage.class.st
@@ -1,141 +0,0 @@
1
Removed:
Class {
2
Removed:
#name : 'MFTWeightsListPage',
3
Removed:
#superclass : 'MFTPage',
4
Removed:
#instVars : [
5
Removed:
'weights'
6
Removed:
],
7
Removed:
#category : 'MyFitnessTracker-Components',
8
Removed:
#package : 'MyFitnessTracker',
9
Removed:
#tag : 'Components'
10
Removed:
}
11
Removed:
12
Removed:
{ #category : 'adding' }
13
Removed:
MFTWeightsListPage >> addWeight [
14
Removed:
15
Removed:
| newWeight |
16
Removed:
newWeight := self call: MFTWeightDialog new.
17
Removed:
newWeight ifNil: [ ^ self ].
18
Removed:
(weights anySatisfy: [ :existingWeight |
19
Removed:
existingWeight date = newWeight date and: [
20
Removed:
existingWeight value = newWeight value ] ]) ifTrue: [ ^ self ].
21
Removed:
22
Removed:
self session user isLoggedIn
23
Removed:
ifTrue: [ self session db insert: newWeight ]
24
Removed:
ifFalse: [ weights add: newWeight ]
25
Removed:
]
26
Removed:
27
Removed:
{ #category : 'accessing' }
28
Removed:
MFTWeightsListPage >> editWeight: oldWeight [
29
Removed:
30
Removed:
| newWeight |
31
Removed:
newWeight := self call: (MFTWeightDialog edit: oldWeight copy).
32
Removed:
(oldWeight value = newWeight value and: [
33
Removed:
oldWeight date = newWeight date ]) ifTrue: [ ^ self ].
34
Removed:
35
Removed:
self session user isLoggedIn
36
Removed:
ifTrue: [ self session db update: oldWeight with: newWeight ]
37
Removed:
ifFalse: [
38
Removed:
weights
39
Removed:
remove: oldWeight;
40
Removed:
add: newWeight ]
41
Removed:
]
42
Removed:
43
Removed:
{ #category : 'initialization' }
44
Removed:
MFTWeightsListPage >> initialize [
45
Removed:
46
Removed:
super initialize.
47
Removed:
title := 'weights'.
48
Removed:
weights := OrderedCollection new
49
Removed:
]
50
Removed:
51
Removed:
{ #category : 'as yet unclassified' }
52
Removed:
MFTWeightsListPage >> randomWittyCTA [
53
Removed:
54
Removed:
| listOfStrings randomString |
55
Removed:
listOfStrings := #( 'First time?' 'Get your sweat on!'
56
Removed:
'Go go go!' 'Go get ''em, Tiger!' ).
57
Removed:
randomString := listOfStrings atRandom.
58
Removed:
^ randomString
59
Removed:
]
60
Removed:
61
Removed:
{ #category : 'accessing' }
62
Removed:
MFTWeightsListPage >> removeWeight: aMFTWeight [
63
Removed:
64
Removed:
self session user isLoggedIn
65
Removed:
ifTrue: [ self session db delete: aMFTWeight ]
66
Removed:
ifFalse: [ weights remove: aMFTWeight ]
67
Removed:
]
68
Removed:
69
Removed:
{ #category : 'rendering' }
70
Removed:
MFTWeightsListPage >> renderActionsButtonGroupOn: html [
71
Removed:
72
Removed:
html form: [
73
Removed:
html buttonGroup: [
74
Removed:
html formButton
75
Removed:
bePrimary;
76
Removed:
callback: [ self addWeight ];
77
Removed:
with: 'Log weight'.
78
Removed:
html formButton
79
Removed:
beSecondary;
80
Removed:
callback: [ self viewAnalytics ];
81
Removed:
with: 'View progress' ] ]
82
Removed:
]
83
Removed:
84
Removed:
{ #category : 'rendering' }
85
Removed:
MFTWeightsListPage >> renderContentOn: html [
86
Removed:
87
Removed:
weights := self session user weights sort: [ :a :b | a date > b date ].
88
Removed:
self renderPageOn: html with: [
89
Removed:
weights ifEmpty: [
90
Removed:
html jumbotron: [ html heading: self randomWittyCTA ] ].
91
Removed:
self renderActionsButtonGroupOn: html.
92
Removed:
weights ifNotEmpty: [ self renderWeightsAsTableOn: html ] ]
93
Removed:
]
94
Removed:
95
Removed:
{ #category : 'rendering' }
96
Removed:
MFTWeightsListPage >> renderWeightActionsButtonGroupOn: html for: aMFTWeight [
97
Removed:
98
Removed:
html form: [
99
Removed:
html buttonGroup
100
Removed:
beSmall;
101
Removed:
with: [
102
Removed:
html formButton
103
Removed:
beSecondary;
104
Removed:
formControl;
105
Removed:
callback: [ self editWeight: aMFTWeight ];
106
Removed:
with: 'Edit'.
107
Removed:
html formButton
108
Removed:
beDanger;
109
Removed:
formControl;
110
Removed:
callback: [ self removeWeight: aMFTWeight ];
111
Removed:
with: 'Delete' ] ]
112
Removed:
]
113
Removed:
114
Removed:
{ #category : 'rendering' }
115
Removed:
MFTWeightsListPage >> renderWeightsAsTableOn: html [
116
Removed:
117
Removed:
html table
118
Removed:
class: 'table table-striped';
119
Removed:
with: [
120
Removed:
html tableHead: [
121
Removed:
html
122
Removed:
tableHeading;
123
Removed:
tableHeading: 'Date'.
124
Removed:
html tableHeading
125
Removed:
style: 'text-align: right';
126
Removed:
with: 'Value' ].
127
Removed:
weights do: [ :weight |
128
Removed:
html tableRow: [
129
Removed:
html tableData: [
130
Removed:
self renderWeightActionsButtonGroupOn: html for: weight ].
131
Removed:
html tableData: weight date yyyymmdd.
132
Removed:
html tableData
133
Removed:
style: 'text-align: right';
134
Removed:
with: weight value ] ] ]
135
Removed:
]
136
Removed:
137
Removed:
{ #category : 'adding' }
138
Removed:
MFTWeightsListPage >> viewAnalytics [
139
Removed:
140
Removed:
self call: (MFTAnalyticsPage for: #weights)
141
Removed:
]
src/MyFitnessTracker/MFTWeightsLog.class.st
@@ -0,0 +1,141 @@
1
Added:
Class {
2
Added:
#name : 'MFTWeightsLog',
3
Added:
#superclass : 'MFTLog',
4
Added:
#instVars : [
5
Added:
'weights'
6
Added:
],
7
Added:
#category : 'MyFitnessTracker-Components',
8
Added:
#package : 'MyFitnessTracker',
9
Added:
#tag : 'Components'
10
Added:
}
11
Added:
12
Added:
{ #category : 'adding' }
13
Added:
MFTWeightsLog >> addWeight [
14
Added:
15
Added:
| newWeight |
16
Added:
newWeight := self call: MFTWeightDialog new.
17
Added:
newWeight ifNil: [ ^ self ].
18
Added:
(weights anySatisfy: [ :existingWeight |
19
Added:
existingWeight date = newWeight date and: [
20
Added:
existingWeight value = newWeight value ] ]) ifTrue: [ ^ self ].
21
Added:
22
Added:
self session user isLoggedIn
23
Added:
ifTrue: [ self session db insert: newWeight ]
24
Added:
ifFalse: [ weights add: newWeight ]
25
Added:
]
26
Added:
27
Added:
{ #category : 'accessing' }
28
Added:
MFTWeightsLog >> editWeight: oldWeight [
29
Added:
30
Added:
| newWeight |
31
Added:
newWeight := self call: (MFTWeightDialog edit: oldWeight copy).
32
Added:
(oldWeight value = newWeight value and: [
33
Added:
oldWeight date = newWeight date ]) ifTrue: [ ^ self ].
34
Added:
35
Added:
self session user isLoggedIn
36
Added:
ifTrue: [ self session db update: oldWeight with: newWeight ]
37
Added:
ifFalse: [
38
Added:
weights
39
Added:
remove: oldWeight;
40
Added:
add: newWeight ]
41
Added:
]
42
Added:
43
Added:
{ #category : 'initialization' }
44
Added:
MFTWeightsLog >> initialize [
45
Added:
46
Added:
super initialize.
47
Added:
title := 'weights'.
48
Added:
weights := OrderedCollection new
49
Added:
]
50
Added:
51
Added:
{ #category : 'as yet unclassified' }
52
Added:
MFTWeightsLog >> randomWittyCTA [
53
Added:
54
Added:
| listOfStrings randomString |
55
Added:
listOfStrings := #( 'First time?' 'Get your sweat on!'
56
Added:
'Go go go!' 'Go get ''em, Tiger!' ).
57
Added:
randomString := listOfStrings atRandom.
58
Added:
^ randomString
59
Added:
]
60
Added:
61
Added:
{ #category : 'accessing' }
62
Added:
MFTWeightsLog >> removeWeight: aMFTWeight [
63
Added:
64
Added:
self session user isLoggedIn
65
Added:
ifTrue: [ self session db delete: aMFTWeight ]
66
Added:
ifFalse: [ weights remove: aMFTWeight ]
67
Added:
]
68
Added:
69
Added:
{ #category : 'rendering' }
70
Added:
MFTWeightsLog >> renderActionsButtonGroupOn: html [
71
Added:
72
Added:
html form: [
73
Added:
html buttonGroup: [
74
Added:
html formButton
75
Added:
bePrimary;
76
Added:
callback: [ self addWeight ];
77
Added:
with: 'Log weight'.
78
Added:
html formButton
79
Added:
beSecondary;
80
Added:
callback: [ self viewAnalytics ];
81
Added:
with: 'View progress' ] ]
82
Added:
]
83
Added:
84
Added:
{ #category : 'rendering' }
85
Added:
MFTWeightsLog >> renderContentOn: html [
86
Added:
87
Added:
weights := self session user weights sort: [ :a :b | a date > b date ].
88
Added:
self renderLogOn: html with: [
89
Added:
weights ifEmpty: [
90
Added:
html jumbotron: [ html heading: self randomWittyCTA ] ].
91
Added:
self renderActionsButtonGroupOn: html.
92
Added:
weights ifNotEmpty: [ self renderWeightsAsTableOn: html ] ]
93
Added:
]
94
Added:
95
Added:
{ #category : 'rendering' }
96
Added:
MFTWeightsLog >> renderWeightActionsButtonGroupOn: html for: aMFTWeight [
97
Added:
98
Added:
html form: [
99
Added:
html buttonGroup
100
Added:
beSmall;
101
Added:
with: [
102
Added:
html formButton
103
Added:
beSecondary;
104
Added:
formControl;
105
Added:
callback: [ self editWeight: aMFTWeight ];
106
Added:
with: 'Edit'.
107
Added:
html formButton
108
Added:
beDanger;
109
Added:
formControl;
110
Added:
callback: [ self removeWeight: aMFTWeight ];
111
Added:
with: 'Delete' ] ]
112
Added:
]
113
Added:
114
Added:
{ #category : 'rendering' }
115
Added:
MFTWeightsLog >> renderWeightsAsTableOn: html [
116
Added:
117
Added:
html table
118
Added:
class: 'table table-striped';
119
Added:
with: [
120
Added:
html tableHead: [
121
Added:
html
122
Added:
tableHeading;
123
Added:
tableHeading: 'Date'.
124
Added:
html tableHeading
125
Added:
style: 'text-align: right';
126
Added:
with: 'Value' ].
127
Added:
weights do: [ :weight |
128
Added:
html tableRow: [
129
Added:
html tableData: [
130
Added:
self renderWeightActionsButtonGroupOn: html for: weight ].
131
Added:
html tableData: weight date yyyymmdd.
132
Added:
html tableData
133
Added:
style: 'text-align: right';
134
Added:
with: weight value ] ] ]
135
Added:
]
136
Added:
137
Added:
{ #category : 'adding' }
138
Added:
MFTWeightsLog >> viewAnalytics [
139
Added:
140
Added:
self call: (MFTAnalyticsPage for: #weights)
141
Added:
]
src/MyFitnessTracker/MFTWorkoutsListPage.class.st
@@ -1,172 +0,0 @@
1
Removed:
"
2
Removed:
I represent the list of user workouts retrieved from the database.
3
Removed:
4
Removed:
I am rendered by `MFTRootComponent` when the user views their workouts. I know about user workouts retrieved from the database.
5
Removed:
6
Removed:
* Collaborators
7
Removed:
8
Removed:
- I work with lists of `MFTWorkout`s.
9
Removed:
- I might work with `MFTExercise class`canonical exercises once the variable is implemented.
10
Removed:
11
Removed:
Public API and Key Messages
12
Removed:
13
Removed:
- message one
14
Removed:
- message two
15
Removed:
- (for bonus points) how to create instances.
16
Removed:
17
Removed:
One simple example is simply gorgeous.
18
Removed:
19
Removed:
Internal Representation and Key Implementation Points.
20
Removed:
21
Removed:
22
Removed:
Implementation Points
23
Removed:
"
24
Removed:
Class {
25
Removed:
#name : 'MFTWorkoutsListPage',
26
Removed:
#superclass : 'MFTPage',
27
Removed:
#instVars : [
28
Removed:
'workouts'
29
Removed:
],
30
Removed:
#category : 'MyFitnessTracker-Components',
31
Removed:
#package : 'MyFitnessTracker',
32
Removed:
#tag : 'Components'
33
Removed:
}
34
Removed:
35
Removed:
{ #category : 'adding' }
36
Removed:
MFTWorkoutsListPage >> addWorkout [
37
Removed:
38
Removed:
| newWorkout |
39
Removed:
newWorkout := self call: MFTWorkoutTask new.
40
Removed:
newWorkout ifNil: [ ^ self ].
41
Removed:
42
Removed:
self session user isLoggedIn
43
Removed:
ifTrue: [ self session db insert: newWorkout ]
44
Removed:
ifFalse: [ workouts add: newWorkout ]
45
Removed:
]
46
Removed:
47
Removed:
{ #category : 'hooks' }
48
Removed:
MFTWorkoutsListPage >> children [
49
Removed:
50
Removed:
^ self session user workouts
51
Removed:
]
52
Removed:
53
Removed:
{ #category : 'accessing' }
54
Removed:
MFTWorkoutsListPage >> confirmDelete: workout [
55
Removed:
56
Removed:
(self call: (MFTConfirmDialog delete: workout)) ifFalse: [ ^ self ].
57
Removed:
self session user isLoggedIn
58
Removed:
ifTrue: [ self session db delete: workout ]
59
Removed:
ifFalse: [ workouts remove: workout ]
60
Removed:
]
61
Removed:
62
Removed:
{ #category : 'as yet unclassified' }
63
Removed:
MFTWorkoutsListPage >> editWorkout: oldWorkout [
64
Removed:
65
Removed:
| newWorkout |
66
Removed:
newWorkout := self call: (MFTWorkoutTask edit: oldWorkout copy).
67
Removed:
newWorkout ifNil: [ ^ self ].
68
Removed:
69
Removed:
self session user isLoggedIn
70
Removed:
ifTrue: [ self session db update: oldWorkout with: newWorkout ]
71
Removed:
ifFalse: [
72
Removed:
workouts
73
Removed:
remove: oldWorkout;
74
Removed:
add: newWorkout ]
75
Removed:
]
76
Removed:
77
Removed:
{ #category : 'initialization' }
78
Removed:
MFTWorkoutsListPage >> initialize [
79
Removed:
80
Removed:
super initialize.
81
Removed:
title := 'workouts'.
82
Removed:
workouts := OrderedCollection new
83
Removed:
]
84
Removed:
85
Removed:
{ #category : 'as yet unclassified' }
86
Removed:
MFTWorkoutsListPage >> randomWittyCTA [
87
Removed:
88
Removed:
| listOfStrings randomString |
89
Removed:
listOfStrings := #( 'First time?' 'Get your sweat on!'
90
Removed:
'Go go go!' 'Go get ''em, Tiger!' ).
91
Removed:
randomString := listOfStrings atRandom.
92
Removed:
^ randomString
93
Removed:
]
94
Removed:
95
Removed:
{ #category : 'rendering' }
96
Removed:
MFTWorkoutsListPage >> renderActionsButtonGroupOn: html [
97
Removed:
98
Removed:
html form: [
99
Removed:
html buttonGroup: [
100
Removed:
html formButton
101
Removed:
bePrimary;
102
Removed:
callback: [ self addWorkout ];
103
Removed:
with: 'Log workout'.
104
Removed:
html formButton
105
Removed:
beSecondary;
106
Removed:
callback: [ self viewAnalytics ];
107
Removed:
with: 'View progress' ] ]
108
Removed:
]
109
Removed:
110
Removed:
{ #category : 'rendering' }
111
Removed:
MFTWorkoutsListPage >> renderContentOn: html [
112
Removed:
113
Removed:
workouts := self session user workouts sort: [ :a :b |
114
Removed:
a date > b date ].
115
Removed:
self renderPageOn: html with: [
116
Removed:
workouts ifEmpty: [
117
Removed:
html jumbotron: [ html heading: self randomWittyCTA ] ].
118
Removed:
self renderActionsButtonGroupOn: html.
119
Removed:
workouts ifNotEmpty: [ self renderWorkoutsAsAccordionOn: html ] ]
120
Removed:
]
121
Removed:
122
Removed:
{ #category : 'rendering' }
123
Removed:
MFTWorkoutsListPage >> renderWorkoutActionsButtonGroup: html for: workout [
124
Removed:
125
Removed:
html form: [
126
Removed:
html buttonGroup: [
127
Removed:
html formButton
128
Removed:
bePrimary;
129
Removed:
callback: [ self editWorkout: workout ];
130
Removed:
with: 'Edit'.
131
Removed:
html formButton
132
Removed:
beDanger;
133
Removed:
callback: [ self confirmDelete: workout ];
134
Removed:
with: 'Delete' ] ]
135
Removed:
]
136
Removed:
137
Removed:
{ #category : 'rendering' }
138
Removed:
MFTWorkoutsListPage >> renderWorkoutsAsAccordionOn: html [
139
Removed:
140
Removed:
html accordion
141
Removed:
id: 'accordion';
142
Removed:
class: 'my-3';
143
Removed:
with: [
144
Removed:
workouts doWithIndex: [ :workout :i |
145
Removed:
html accordionItem: [
146
Removed:
html accordionHeading: [
147
Removed:
html accordionButton
148
Removed:
dataToggle: 'collapse';
149
Removed:
dataTarget: '#collapse' , i asString;
150
Removed:
with: [
151
Removed:
html text:
152
Removed:
workout date yyyymmdd , ', ' , workout date dayOfWeekName.
153
Removed:
workout primaryMuscleGroup ifNotNil: [
154
Removed:
html
155
Removed:
text: ':';
156
Removed:
space;
157
Removed:
emphasis: workout primaryMuscleGroup englishName ] ] ].
158
Removed:
html accordionCollapse
159
Removed:
id: 'collapse' , i asString;
160
Removed:
class: 'collapse';
161
Removed:
dataAttributeAt: 'bs-parent' put: '#accordion';
162
Removed:
with: [
163
Removed:
html accordionBody with: [
164
Removed:
html render: workout.
165
Removed:
self renderWorkoutActionsButtonGroup: html for: workout ] ] ] ] ]
166
Removed:
]
167
Removed:
168
Removed:
{ #category : 'adding' }
169
Removed:
MFTWorkoutsListPage >> viewAnalytics [
170
Removed:
171
Removed:
self call: (MFTAnalyticsPage for: #workouts)
172
Removed:
]
src/MyFitnessTracker/MFTWorkoutsLog.class.st
@@ -0,0 +1,172 @@
1
Added:
"
2
Added:
I represent the list of user workouts retrieved from the database.
3
Added:
4
Added:
I am rendered by `MFTRootComponent` when the user views their workouts. I know about user workouts retrieved from the database.
5
Added:
6
Added:
* Collaborators
7
Added:
8
Added:
- I work with lists of `MFTWorkout`s.
9
Added:
- I might work with `MFTExercise class`canonical exercises once the variable is implemented.
10
Added:
11
Added:
Public API and Key Messages
12
Added:
13
Added:
- message one
14
Added:
- message two
15
Added:
- (for bonus points) how to create instances.
16
Added:
17
Added:
One simple example is simply gorgeous.
18
Added:
19
Added:
Internal Representation and Key Implementation Points.
20
Added:
21
Added:
22
Added:
Implementation Points
23
Added:
"
24
Added:
Class {
25
Added:
#name : 'MFTWorkoutsLog',
26
Added:
#superclass : 'MFTLog',
27
Added:
#instVars : [
28
Added:
'workouts'
29
Added:
],
30
Added:
#category : 'MyFitnessTracker-Components',
31
Added:
#package : 'MyFitnessTracker',
32
Added:
#tag : 'Components'
33
Added:
}
34
Added:
35
Added:
{ #category : 'adding' }
36
Added:
MFTWorkoutsLog >> addWorkout [
37
Added:
38
Added:
| newWorkout |
39
Added:
newWorkout := self call: MFTWorkoutTask new.
40
Added:
newWorkout ifNil: [ ^ self ].
41
Added:
42
Added:
self session user isLoggedIn
43
Added:
ifTrue: [ self session db insert: newWorkout ]
44
Added:
ifFalse: [ workouts add: newWorkout ]
45
Added:
]
46
Added:
47
Added:
{ #category : 'hooks' }
48
Added:
MFTWorkoutsLog >> children [
49
Added:
50
Added:
^ self session user workouts
51
Added:
]
52
Added:
53
Added:
{ #category : 'accessing' }
54
Added:
MFTWorkoutsLog >> confirmDelete: workout [
55
Added:
56
Added:
(self call: (MFTConfirmDialog delete: workout)) ifFalse: [ ^ self ].
57
Added:
self session user isLoggedIn
58
Added:
ifTrue: [ self session db delete: workout ]
59
Added:
ifFalse: [ workouts remove: workout ]
60
Added:
]
61
Added:
62
Added:
{ #category : 'as yet unclassified' }
63
Added:
MFTWorkoutsLog >> editWorkout: oldWorkout [
64
Added:
65
Added:
| newWorkout |
66
Added:
newWorkout := self call: (MFTWorkoutTask edit: oldWorkout copy).
67
Added:
newWorkout ifNil: [ ^ self ].
68
Added:
69
Added:
self session user isLoggedIn
70
Added:
ifTrue: [ self session db update: oldWorkout with: newWorkout ]
71
Added:
ifFalse: [
72
Added:
workouts
73
Added:
remove: oldWorkout;
74
Added:
add: newWorkout ]
75
Added:
]
76
Added:
77
Added:
{ #category : 'initialization' }
78
Added:
MFTWorkoutsLog >> initialize [
79
Added:
80
Added:
super initialize.
81
Added:
title := 'workouts'.
82
Added:
workouts := OrderedCollection new
83
Added:
]
84
Added:
85
Added:
{ #category : 'as yet unclassified' }
86
Added:
MFTWorkoutsLog >> randomWittyCTA [
87
Added:
88
Added:
| listOfStrings randomString |
89
Added:
listOfStrings := #( 'First time?' 'Get your sweat on!'
90
Added:
'Go go go!' 'Go get ''em, Tiger!' ).
91
Added:
randomString := listOfStrings atRandom.
92
Added:
^ randomString
93
Added:
]
94
Added:
95
Added:
{ #category : 'rendering' }
96
Added:
MFTWorkoutsLog >> renderActionsButtonGroupOn: html [
97
Added:
98
Added:
html form: [
99
Added:
html buttonGroup: [
100
Added:
html formButton
101
Added:
bePrimary;
102
Added:
callback: [ self addWorkout ];
103
Added:
with: 'Log workout'.
104
Added:
html formButton
105
Added:
beSecondary;
106
Added:
callback: [ self viewAnalytics ];
107
Added:
with: 'View progress' ] ]
108
Added:
]
109
Added:
110
Added:
{ #category : 'rendering' }
111
Added:
MFTWorkoutsLog >> renderContentOn: html [
112
Added:
113
Added:
workouts := self session user workouts sort: [ :a :b |
114
Added:
a date > b date ].
115
Added:
self renderLogOn: html with: [
116
Added:
workouts ifEmpty: [
117
Added:
html jumbotron: [ html heading: self randomWittyCTA ] ].
118
Added:
self renderActionsButtonGroupOn: html.
119
Added:
workouts ifNotEmpty: [ self renderWorkoutsAsAccordionOn: html ] ]
120
Added:
]
121
Added:
122
Added:
{ #category : 'rendering' }
123
Added:
MFTWorkoutsLog >> renderWorkoutActionsButtonGroup: html for: workout [
124
Added:
125
Added:
html form: [
126
Added:
html buttonGroup: [
127
Added:
html formButton
128
Added:
bePrimary;
129
Added:
callback: [ self editWorkout: workout ];
130
Added:
with: 'Edit'.
131
Added:
html formButton
132
Added:
beDanger;
133
Added:
callback: [ self confirmDelete: workout ];
134
Added:
with: 'Delete' ] ]
135
Added:
]
136
Added:
137
Added:
{ #category : 'rendering' }
138
Added:
MFTWorkoutsLog >> renderWorkoutsAsAccordionOn: html [
139
Added:
140
Added:
html accordion
141
Added:
id: 'accordion';
142
Added:
class: 'my-3';
143
Added:
with: [
144
Added:
workouts doWithIndex: [ :workout :i |
145
Added:
html accordionItem: [
146
Added:
html accordionHeading: [
147
Added:
html accordionButton
148
Added:
dataToggle: 'collapse';
149
Added:
dataTarget: '#collapse' , i asString;
150
Added:
with: [
151
Added:
html text:
152
Added:
workout date yyyymmdd , ', ' , workout date dayOfWeekName.
153
Added:
workout primaryMuscleGroup ifNotNil: [
154
Added:
html
155
Added:
text: ':';
156
Added:
space;
157
Added:
emphasis: workout primaryMuscleGroup englishName ] ] ].
158
Added:
html accordionCollapse
159
Added:
id: 'collapse' , i asString;
160
Added:
class: 'collapse';
161
Added:
dataAttributeAt: 'bs-parent' put: '#accordion';
162
Added:
with: [
163
Added:
html accordionBody with: [
164
Added:
html render: workout.
165
Added:
self renderWorkoutActionsButtonGroup: html for: workout ] ] ] ] ]
166
Added:
]
167
Added:
168
Added:
{ #category : 'adding' }
169
Added:
MFTWorkoutsLog >> viewAnalytics [
170
Added:
171
Added:
self call: (MFTAnalyticsPage for: #workouts)
172
Added:
]