[Pharo] Personal fitness tracker web app.
Removed a couple components.
Reuse potential was too low.
Changed files
- src/MyFitnessTracker-Web/MFTHomePage.class.st
- src/MyFitnessTracker-Web/MFTLogBookViewerComponent.class.st
- src/MyFitnessTracker-Web/MFTMainActionsComponent.class.st
- src/MyFitnessTracker-Web/MFTNavbarComponent.class.st
- src/MyFitnessTracker-Web/MFTPlanPage.class.st
- src/MyFitnessTracker-Web/MFTProfilePage.class.st
- src/MyFitnessTracker-Web/MFTRootComponent.class.st
- src/MyFitnessTracker-Web/MFTScreenComponent.class.st
- src/MyFitnessTracker-Web/MFTSetGroupLogEditorComponent.class.st
- src/MyFitnessTracker-Web/MFTSetGroupLogViewerComponent.class.st
- src/MyFitnessTracker-Web/MFTStatusComponent.class.st
- src/MyFitnessTracker-Web/MFTUser.class.st
- src/MyFitnessTracker-Web/MFTWorkoutLogEditorComponent.class.st
- src/MyFitnessTracker-Web/MFTWorkoutLogEditorPage.class.st
- src/MyFitnessTracker-Web/MFTWorkoutLogViewerComponent.class.st
- src/MyFitnessTracker-Web/MFTWorkoutPrescriptionViewerComponent.class.st
src/MyFitnessTracker-Web/MFTHomePage.class.st
@@ -2,70 +2,100 @@
2
2
#name : 'MFTHomePage',
3
3
#superclass : 'MFTPage',
4
4
#instVars : [
5
Removed:
'statusComponent',
6
Removed:
'homePageActionsComponent',
7
Removed:
'nextWorkoutComponent',
8
Removed:
'previousWorkoutLogsComponent'
5
Added:
'onLogWorkout'
9
6
],
10
7
#category : 'MyFitnessTracker-Web-Components',
11
8
#package : 'MyFitnessTracker-Web',
12
9
#tag : 'Components'
13
10
}
14
11
15
Removed:
{ #category : 'hooks' }
16
Removed:
MFTHomePage >> children [
12
Added:
{ #category : 'accessing' }
13
Added:
MFTHomePage >> onLogWorkout: aBlock [
17
14
18
Removed:
^ {
19
Removed:
statusComponent.
20
Removed:
homePageActionsComponent.
21
Removed:
nextWorkoutComponent.
22
Removed:
previousWorkoutLogsComponent }
15
Added:
onLogWorkout := aBlock
23
16
]
24
17
25
18
{ #category : 'initialization' }
26
Removed:
MFTHomePage >> initialize [
19
Added:
MFTHomePage >> previousWorkoutLogsComponent [
27
20
28
Removed:
| trainee |
29
Removed:
trainee := self session user trainee.
30
Removed:
31
Removed:
super initialize.
32
Removed:
statusComponent := MFTStatusComponent new.
33
Removed:
homePageActionsComponent := MFTMainActionsComponent new
34
Removed:
onLogWorkout: [
35
Removed:
| workoutLog |
36
Removed:
trainee := self session user trainee.
37
Removed:
workoutLog := self call:
38
Removed:
(MFTWorkoutLogEditorPage
39
Removed:
forWorkoutPrescription:
40
Removed:
trainee
41
Removed:
nextWorkoutPrescription).
42
Removed:
workoutLog ifNotNil: [
43
Removed:
trainee logWorkout: workoutLog ] ];
44
Removed:
yourself.
45
Removed:
nextWorkoutComponent := MFTWorkoutPrescriptionViewerComponent new
46
Removed:
heading: 'Next workout'.
47
Removed:
previousWorkoutLogsComponent := MFTLogBookViewerComponent new
48
Removed:
logBook: trainee logBook;
49
Removed:
heading: 'Previous workouts'
21
Added:
^ MFTLogBookViewerComponent new
22
Added:
logBook: self session user trainee logBook;
23
Added:
heading: 'Previous workouts'
50
24
]
51
25
52
26
{ #category : 'rendering' }
53
27
MFTHomePage >> renderContentOn: html [
54
28
29
Added:
self renderPageOn: html with: [
30
Added:
html heading
31
Added:
level: 1;
32
Added:
with: self session user trainee routine canonicalName capitalized.
33
Added:
self
34
Added:
renderStatusOn: html;
35
Added:
renderMainActionsOn: html;
36
Added:
renderNextWorkoutPrescriptionOn: html;
37
Added:
renderWorkoutLogBookOn: html ]
38
Added:
]
39
Added:
40
Added:
{ #category : 'rendering' }
41
Added:
MFTHomePage >> renderMainActionsOn: html [
42
Added:
43
Added:
html section: [
44
Added:
html anchor
45
Added:
callback: [ onLogWorkout value ];
46
Added:
with: 'Log workout' ]
47
Added:
]
48
Added:
49
Added:
{ #category : 'rendering' }
50
Added:
MFTHomePage >> renderNextWorkoutPrescriptionOn: html [
51
Added:
52
Added:
| workoutPrescription |
53
Added:
workoutPrescription := self session user trainee
54
Added:
nextWorkoutPrescription.
55
Added:
56
Added:
html section: [
57
Added:
html heading
58
Added:
level: 2;
59
Added:
with: 'Next workout'.
60
Added:
html heading
61
Added:
level: 3;
62
Added:
with: workoutPrescription canonicalName.
63
Added:
html orderedList: [
64
Added:
workoutPrescription setGroups do: [ :setGroup |
65
Added:
html listItem:
66
Added:
((setGroup sets collect: #exercise) joinUsing: ', ') ] ] ]
67
Added:
]
68
Added:
69
Added:
{ #category : 'rendering' }
70
Added:
MFTHomePage >> renderStatusOn: html [
71
Added:
55
72
| trainee |
56
73
trainee := self session user trainee.
57
Removed:
nextWorkoutComponent workoutPrescription:
58
Removed:
trainee nextWorkoutPrescription.
59
74
60
Removed:
self renderPageOn: html with: [
75
Added:
html section: [
76
Added:
html definitionList: [
77
Added:
trainee logBook durationSinceLastWorkout ifNotNil: [
78
Added:
html definitionTerm: 'Hours since last workout'.
79
Added:
html definitionData:
80
Added:
trainee logBook durationSinceLastWorkout asHours rounded asString ].
81
Added:
html definitionTerm: 'Recovery status'.
82
Added:
html definitionData: (trainee isRecovered
83
Added:
ifTrue: [ 'Fully recovered' ]
84
Added:
ifFalse: [ 'Not recovered yet' ]) ] ]
85
Added:
]
86
Added:
87
Added:
{ #category : 'rendering' }
88
Added:
MFTHomePage >> renderWorkoutLogBookOn: html [
89
Added:
90
Added:
| logBook |
91
Added:
logBook := self session user trainee logBook.
92
Added:
93
Added:
logBook workoutLogs ifNotEmpty: [
61
94
html heading
62
Removed:
level: 1;
63
Removed:
with: trainee routine canonicalName capitalized.
64
Removed:
html
65
Removed:
render: statusComponent;
66
Removed:
render: homePageActionsComponent;
67
Removed:
render: nextWorkoutComponent;
68
Removed:
render: previousWorkoutLogsComponent ]
95
Added:
level: 2;
96
Added:
with: 'Previous workouts'.
97
Added:
logBook workoutLogs reverseDo: [ :each |
98
Added:
html render: (MFTWorkoutLogViewerComponent forWorkoutLog: each) ] ]
69
99
]
70
100
71
101
{ #category : 'accessing' }
src/MyFitnessTracker-Web/MFTLogBookViewerComponent.class.st
@@ -49,8 +49,9 @@
49
49
MFTWorkoutLogViewerComponent
50
50
forWorkoutLog: each ].
51
51
52
Removed:
html heading
53
Removed:
level: 2;
54
Removed:
with: heading.
55
Removed:
logBookItemComponents reverseDo: [ :each | html render: each ]
52
Added:
logBook workoutLogs ifNotEmpty: [
53
Added:
html heading
54
Added:
level: 2;
55
Added:
with: heading.
56
Added:
logBookItemComponents reverseDo: [ :each | html render: each ] ]
56
57
]
src/MyFitnessTracker-Web/MFTMainActionsComponent.class.st
@@ -1,25 +0,0 @@
1
Removed:
Class {
2
Removed:
#name : 'MFTMainActionsComponent',
3
Removed:
#superclass : 'WAComponent',
4
Removed:
#instVars : [
5
Removed:
'onLogWorkout'
6
Removed:
],
7
Removed:
#category : 'MyFitnessTracker-Web-Components',
8
Removed:
#package : 'MyFitnessTracker-Web',
9
Removed:
#tag : 'Components'
10
Removed:
}
11
Removed:
12
Removed:
{ #category : 'accessing' }
13
Removed:
MFTMainActionsComponent >> onLogWorkout: aBlock [
14
Removed:
15
Removed:
onLogWorkout := aBlock
16
Removed:
]
17
Removed:
18
Removed:
{ #category : 'rendering' }
19
Removed:
MFTMainActionsComponent >> renderContentOn: html [
20
Removed:
21
Removed:
html section: [
22
Removed:
html anchor
23
Removed:
callback: [ onLogWorkout value ];
24
Removed:
with: 'Log workout' ]
25
Removed:
]
src/MyFitnessTracker-Web/MFTNavbarComponent.class.st
@@ -2,26 +2,82 @@
2
2
#name : 'MFTNavbarComponent',
3
3
#superclass : 'WAComponent',
4
4
#instVars : [
5
Removed:
'onHome'
5
Added:
'mainNavLinks'
6
6
],
7
7
#category : 'MyFitnessTracker-Web-Components',
8
8
#package : 'MyFitnessTracker-Web',
9
9
#tag : 'Components'
10
10
}
11
11
12
Added:
{ #category : 'initialization' }
13
Added:
MFTNavbarComponent >> initialize [
14
Added:
15
Added:
super initialize.
16
Added:
mainNavLinks := OrderedDictionary new
17
Added:
]
18
Added:
19
Added:
{ #category : 'initialization' }
20
Added:
MFTNavbarComponent >> mainNavLinks [
21
Added:
22
Added:
^ mainNavLinks
23
Added:
]
24
Added:
25
Added:
{ #category : 'initialization' }
26
Added:
MFTNavbarComponent >> mainNavPages [
27
Added:
28
Added:
^ { #home. #plan. #profile }
29
Added:
]
30
Added:
12
31
{ #category : 'accessing' }
32
Added:
MFTNavbarComponent >> onHome [
33
Added:
34
Added:
^ mainNavLinks at: #home
35
Added:
]
36
Added:
37
Added:
{ #category : 'accessing' }
13
38
MFTNavbarComponent >> onHome: aBlock [
14
39
15
Removed:
onHome := aBlock
40
Added:
mainNavLinks at: #home put: aBlock
16
41
]
17
42
43
Added:
{ #category : 'accessing' }
44
Added:
MFTNavbarComponent >> onPlan [
45
Added:
46
Added:
^ mainNavLinks at: #plan
47
Added:
]
48
Added:
49
Added:
{ #category : 'accessing' }
50
Added:
MFTNavbarComponent >> onPlan: aBlock [
51
Added:
52
Added:
mainNavLinks at: #plan put: aBlock
53
Added:
]
54
Added:
55
Added:
{ #category : 'accessing' }
56
Added:
MFTNavbarComponent >> onProfile [
57
Added:
58
Added:
^ mainNavLinks at: #profile
59
Added:
]
60
Added:
61
Added:
{ #category : 'initialization' }
62
Added:
MFTNavbarComponent >> onProfile: aBlock [
63
Added:
64
Added:
mainNavLinks at: #profile put: aBlock
65
Added:
]
66
Added:
18
67
{ #category : 'rendering' }
19
68
MFTNavbarComponent >> renderContentOn: html [
20
69
21
70
html navigation: [
22
Removed:
html unorderedList: [
23
Removed:
html listItem: [
24
Removed:
html anchor
25
Removed:
callback: [ onHome value ];
26
Removed:
with: 'Home' ] ] ]
71
Added:
html
72
Added:
unorderedList: [
73
Added:
mainNavLinks keysAndValuesDo: [ :titleKey :callback |
74
Added:
html listItem: [
75
Added:
html anchor
76
Added:
callback: callback;
77
Added:
with: titleKey ] ] ];
78
Added:
unorderedList: [
79
Added:
html listItem: [
80
Added:
html anchor
81
Added:
callback: [ mainNavLinks at: #logout ];
82
Added:
with: 'Logout' ] ] ]
27
83
]
src/MyFitnessTracker-Web/MFTPlanPage.class.st
@@ -0,0 +1,51 @@
1
Added:
Class {
2
Added:
#name : 'MFTPlanPage',
3
Added:
#superclass : 'MFTPage',
4
Added:
#category : 'MyFitnessTracker-Web-Components',
5
Added:
#package : 'MyFitnessTracker-Web',
6
Added:
#tag : 'Components'
7
Added:
}
8
Added:
9
Added:
{ #category : 'rendering' }
10
Added:
MFTPlanPage >> renderContentOn: html [
11
Added:
12
Added:
self renderPageOn: html with: [
13
Added:
html heading: 'Plan'.
14
Added:
self
15
Added:
renderCurrentPlanInfoOn: html;
16
Added:
renderPlanWorkoutsOn: html ]
17
Added:
]
18
Added:
19
Added:
{ #category : 'rendering' }
20
Added:
MFTPlanPage >> renderCurrentPlanInfoOn: html [
21
Added:
22
Added:
| routine |
23
Added:
routine := self session user trainee routine.
24
Added:
25
Added:
html section: [
26
Added:
html definitionList: [
27
Added:
html
28
Added:
definitionTerm: 'Current routine';
29
Added:
definitionData: routine canonicalName.
30
Added:
html
31
Added:
definitionTerm: 'Rest between workouts';
32
Added:
definitionData: '48 hours' ] ]
33
Added:
]
34
Added:
35
Added:
{ #category : 'rendering' }
36
Added:
MFTPlanPage >> renderPlanWorkoutsOn: html [
37
Added:
38
Added:
| routine |
39
Added:
routine := self session user trainee routine.
40
Added:
41
Added:
routine workouts do: [ :workoutPrescription |
42
Added:
html render:
43
Added:
(MFTWorkoutPrescriptionViewerComponent forPrescription:
44
Added:
workoutPrescription) ]
45
Added:
]
46
Added:
47
Added:
{ #category : 'accessing' }
48
Added:
MFTPlanPage >> title [
49
Added:
50
Added:
^ 'Plan for ' , self session user trainee canonicalName
51
Added:
]
src/MyFitnessTracker-Web/MFTProfilePage.class.st
@@ -0,0 +1,22 @@
1
Added:
Class {
2
Added:
#name : 'MFTProfilePage',
3
Added:
#superclass : 'MFTPage',
4
Added:
#category : 'MyFitnessTracker-Web-Components',
5
Added:
#package : 'MyFitnessTracker-Web',
6
Added:
#tag : 'Components'
7
Added:
}
8
Added:
9
Added:
{ #category : 'rendering' }
10
Added:
MFTProfilePage >> renderContentOn: html [
11
Added:
12
Added:
self renderPageOn: html with: [
13
Added:
html heading
14
Added:
level: 1;
15
Added:
with: self title ]
16
Added:
]
17
Added:
18
Added:
{ #category : 'accessing' }
19
Added:
MFTProfilePage >> title [
20
Added:
21
Added:
^ 'Profile for ' , self session user username
22
Added:
]
src/MyFitnessTracker-Web/MFTRootComponent.class.st
@@ -55,5 +55,7 @@
55
55
aRoot link
56
56
beShortcutIcon;
57
57
url: MFTFileLibrary / #faviconPng.
58
Added:
aRoot stylesheet url:
59
Added:
'https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css'.
58
60
aRoot stylesheet url: MFTFileLibrary / #defaultCss
59
61
]
src/MyFitnessTracker-Web/MFTScreenComponent.class.st
@@ -2,6 +2,7 @@
2
2
#name : 'MFTScreenComponent',
3
3
#superclass : 'WAComponent',
4
4
#instVars : [
5
Added:
'mainPages',
5
6
'activePage',
6
7
'navbar',
7
8
'footer'
@@ -18,12 +19,6 @@
18
19
]
19
20
20
21
{ #category : 'accessing' }
21
Removed:
MFTScreenComponent >> activePage: aMFTPage [
22
Removed:
23
Removed:
activePage := aMFTPage
24
Removed:
]
25
Removed:
26
Removed:
{ #category : 'accessing' }
27
22
MFTScreenComponent >> children [
28
23
29
24
^ {
@@ -48,13 +43,29 @@
48
43
MFTScreenComponent >> initialize [
49
44
50
45
super initialize.
51
Removed:
activePage := MFTHomePage new.
46
Added:
self initializeMainPages.
47
Added:
activePage := mainPages at: #home.
52
48
navbar := MFTNavbarComponent new
53
Removed:
onHome: [ self showHome ];
49
Added:
onHome: [ activePage := mainPages at: #home ];
50
Added:
onPlan: [ activePage := mainPages at: #plan ];
51
Added:
onProfile: [ activePage := mainPages at: #profile ];
54
52
yourself.
55
53
footer := MFTFooterComponent new
56
54
]
57
55
56
Added:
{ #category : 'initialization' }
57
Added:
MFTScreenComponent >> initializeMainPages [
58
Added:
59
Added:
mainPages := OrderedDictionary newFrom: {
60
Added:
(#home -> (MFTHomePage new onLogWorkout: [
61
Added:
activePage call:
62
Added:
(MFTWorkoutLogEditorPage forWorkoutPrescription:
63
Added:
self session user trainee
64
Added:
nextWorkoutPrescription) ])).
65
Added:
(#plan -> MFTPlanPage new).
66
Added:
(#profile -> MFTProfilePage new) }
67
Added:
]
68
Added:
58
69
{ #category : 'accessing' }
59
70
MFTScreenComponent >> navbar [
60
71
@@ -65,10 +76,4 @@
65
76
MFTScreenComponent >> navbar: aNavbar [
66
77
67
78
navbar := aNavbar
68
Removed:
]
69
Removed:
70
Removed:
{ #category : 'initialization' }
71
Removed:
MFTScreenComponent >> showHome [
72
Removed:
73
Removed:
self activePage: MFTHomePage new
74
79
]
src/MyFitnessTracker-Web/MFTSetGroupLogEditorComponent.class.st
@@ -20,70 +20,86 @@
20
20
{ #category : 'rendering' }
21
21
MFTSetGroupLogEditorComponent >> renderContentOn: html [
22
22
23
Removed:
html fieldSet: [
24
Removed:
html legend: setGroupLog prescription canonicalName capitalized.
23
Added:
html heading
24
Added:
level: 2;
25
Added:
with: setGroupLog prescription canonicalName capitalized.
26
Added:
html form: [
25
27
setGroupLog setsGroupedByExercise keysAndValuesDo: [ :exercise :sets |
26
28
self renderOn: html exercise: exercise sets: sets ].
27
Removed:
html button
28
Removed:
callback: [ self answer: setGroupLog ];
29
Removed:
with: 'Save' ]
29
Added:
self renderFormActionsOn: html ]
30
30
]
31
31
32
32
{ #category : 'rendering' }
33
Removed:
MFTSetGroupLogEditorComponent >> renderOn: html exercise: exercise sets: sets [
33
Added:
MFTSetGroupLogEditorComponent >> renderFormActionsOn: html [
34
34
35
Removed:
html div
36
Removed:
style: 'margin-bottom: 1rem';
35
Added:
html fieldSet
36
Added:
class: 'grid';
37
37
with: [
38
Removed:
html heading
39
Removed:
level: 3;
40
Removed:
with: exercise canonicalName capitalized.
41
38
html button
42
Removed:
callback: [
43
Removed:
setGroupLog
44
Removed:
addSet: (MFTSetLog forPrescription: sets last prescription)
45
Removed:
before: sets first ];
46
Removed:
with: 'Add warm-up set'.
39
Added:
callback: [ self answer: setGroupLog ];
40
Added:
with: 'Save'
47
41
48
Removed:
html table: [
49
Removed:
html
50
Removed:
tableHead: [
51
Removed:
html tableRow: [
52
Removed:
html
53
Removed:
tableHeading;
54
Removed:
tableHeading: 'Reps';
55
Removed:
tableHeading: 'Load';
56
Removed:
tableHeading: 'To Failure';
57
Removed:
tableHeading ] ];
58
Removed:
tableBody: [
59
Removed:
sets do: [ :setLog | self renderOn: html setLog: setLog ] ] ] ]
42
Added:
"html button
43
Added:
class: 'secondary';
44
Added:
callback: [ self answer: nil ];
45
Added:
with: 'Discard'" ]
60
46
]
61
47
62
48
{ #category : 'rendering' }
63
Removed:
MFTSetGroupLogEditorComponent >> renderOn: html setLog: setLog [
49
Added:
MFTSetGroupLogEditorComponent >> renderOn: html exercise: exercise sets: sets [
64
50
65
Removed:
html tableRow: [
66
Removed:
html
67
Removed:
tableData: (setGroupLog indexOfSet: setLog);
68
Removed:
tableData: [
69
Removed:
html numberInput
70
Removed:
placeholder: setLog prescription repScheme;
71
Removed:
callback: [ :value |
72
Removed:
value ifNotEmpty: [ setLog reps: value asNumber ] ];
73
Removed:
value: setLog reps ];
74
Removed:
tableData: [
75
Removed:
html numberInput
76
Removed:
callback: [ :value |
77
Removed:
value ifNotEmpty: [ setLog load: value asNumber ] ];
78
Removed:
value: setLog load ];
79
Removed:
tableData: [
80
Removed:
html checkbox
81
Removed:
callback: [ :value | setLog failureAchieved: value ];
82
Removed:
value: setLog failureAchieved ];
83
Removed:
tableData: [
84
Removed:
html button
85
Removed:
callback: [ setGroupLog removeSet: setLog ];
86
Removed:
with: 'Delete' ] ]
51
Added:
html div: [
52
Added:
html heading
53
Added:
level: 3;
54
Added:
with: exercise canonicalName capitalized.
55
Added:
html button
56
Added:
class: 'secondary outline';
57
Added:
callback: [
58
Added:
setGroupLog
59
Added:
addSet: (MFTSetLog forPrescription: sets last prescription)
60
Added:
before: sets first ];
61
Added:
with: 'Add warm-up set'.
62
Added:
self renderTableOn: html forSets: sets ]
63
Added:
]
64
Added:
65
Added:
{ #category : 'rendering' }
66
Added:
MFTSetGroupLogEditorComponent >> renderTableOn: html forSets: sets [
67
Added:
68
Added:
^ html table: [
69
Added:
html
70
Added:
tableHead: [
71
Added:
html tableRow: [
72
Added:
html
73
Added:
tableHeading;
74
Added:
tableHeading: 'Reps';
75
Added:
tableHeading: 'Load';
76
Added:
tableHeading: 'To Failure';
77
Added:
tableHeading ] ];
78
Added:
tableBody: [
79
Added:
sets do: [ :setLog |
80
Added:
html tableRow: [
81
Added:
html
82
Added:
tableData: (setGroupLog indexOfSet: setLog);
83
Added:
tableData: [
84
Added:
html numberInput
85
Added:
placeholder: setLog prescription repScheme;
86
Added:
callback: [ :value |
87
Added:
value ifNotEmpty: [ setLog reps: value asNumber ] ];
88
Added:
value: setLog reps ];
89
Added:
tableData: [
90
Added:
html numberInput
91
Added:
callback: [ :value |
92
Added:
value ifNotEmpty: [ setLog load: value asNumber ] ];
93
Added:
value: setLog load ];
94
Added:
tableData: [
95
Added:
html checkbox
96
Added:
callback: [ :value | setLog failureAchieved: value ];
97
Added:
value: setLog failureAchieved ];
98
Added:
tableData: [
99
Added:
html button
100
Added:
class: 'outline';
101
Added:
callback: [ setGroupLog removeSet: setLog ];
102
Added:
with: 'Delete' ] ] ] ] ]
87
103
]
88
104
89
105
{ #category : 'accessing' }
src/MyFitnessTracker-Web/MFTSetGroupLogViewerComponent.class.st
@@ -1,105 +0,0 @@
1
Removed:
Class {
2
Removed:
#name : 'MFTSetGroupLogViewerComponent',
3
Removed:
#superclass : 'WAComponent',
4
Removed:
#instVars : [
5
Removed:
'setGroupLog',
6
Removed:
'isEditable'
7
Removed:
],
8
Removed:
#category : 'MyFitnessTracker-Web-Components',
9
Removed:
#package : 'MyFitnessTracker-Web',
10
Removed:
#tag : 'Components'
11
Removed:
}
12
Removed:
13
Removed:
{ #category : 'as yet unclassified' }
14
Removed:
MFTSetGroupLogViewerComponent class >> forSetGroupLog: aMFTSetGroupLog [
15
Removed:
16
Removed:
^ self new
17
Removed:
setGroupLog: aMFTSetGroupLog;
18
Removed:
yourself
19
Removed:
]
20
Removed:
21
Removed:
{ #category : 'rendering' }
22
Removed:
MFTSetGroupLogViewerComponent >> beEditable [
23
Removed:
24
Removed:
isEditable := true
25
Removed:
]
26
Removed:
27
Removed:
{ #category : 'rendering' }
28
Removed:
MFTSetGroupLogViewerComponent >> initialize [
29
Removed:
30
Removed:
super initialize.
31
Removed:
isEditable := false
32
Removed:
]
33
Removed:
34
Removed:
{ #category : 'rendering' }
35
Removed:
MFTSetGroupLogViewerComponent >> isEditable [
36
Removed:
37
Removed:
^ isEditable
38
Removed:
]
39
Removed:
40
Removed:
{ #category : 'rendering' }
41
Removed:
MFTSetGroupLogViewerComponent >> renderContentOn: html [
42
Removed:
43
Removed:
| completelyLogged buttonLabel |
44
Removed:
completelyLogged := setGroupLog isCompletelyLogged.
45
Removed:
buttonLabel := completelyLogged
46
Removed:
ifTrue: [ 'Edit' ]
47
Removed:
ifFalse: [ 'Log' ].
48
Removed:
49
Removed:
html fieldSet: [
50
Removed:
html legend: setGroupLog canonicalName capitalized.
51
Removed:
completelyLogged
52
Removed:
ifTrue: [ self renderSetGroupLogDataOn: html ]
53
Removed:
ifFalse: [ self renderSetGroupLogExercisesOn: html ].
54
Removed:
isEditable ifTrue: [
55
Removed:
html button
56
Removed:
callback: [
57
Removed:
| editedLog |
58
Removed:
editedLog := self call:
59
Removed:
(MFTSetGroupLogEditorComponent forSetGroupLog:
60
Removed:
setGroupLog).
61
Removed:
editedLog ifNotNil: [ setGroupLog := editedLog ] ];
62
Removed:
with: buttonLabel ] ]
63
Removed:
]
64
Removed:
65
Removed:
{ #category : 'rendering' }
66
Removed:
MFTSetGroupLogViewerComponent >> renderSetGroupLogDataOn: html [
67
Removed:
68
Removed:
setGroupLog setsGroupedByExercise keysAndValuesDo: [ :exercise :sets |
69
Removed:
html heading
70
Removed:
level: 3;
71
Removed:
with: exercise canonicalName capitalized.
72
Removed:
html table: [
73
Removed:
html
74
Removed:
tableHead: [
75
Removed:
html tableRow: [
76
Removed:
html
77
Removed:
tableHeading;
78
Removed:
tableHeading: 'Reps';
79
Removed:
tableHeading: 'Load';
80
Removed:
tableHeading: 'To Failure' ] ];
81
Removed:
tableBody: [
82
Removed:
sets do: [ :set |
83
Removed:
html tableRow: [
84
Removed:
html
85
Removed:
tableData: (setGroupLog indexOfSet: set);
86
Removed:
tableData: set reps;
87
Removed:
tableData: set load;
88
Removed:
tableData: set failureAchieved ] ] ] ] ]
89
Removed:
]
90
Removed:
91
Removed:
{ #category : 'rendering' }
92
Removed:
MFTSetGroupLogViewerComponent >> renderSetGroupLogExercisesOn: html [
93
Removed:
94
Removed:
html heading
95
Removed:
level: 3;
96
Removed:
with: ((setGroupLog prescription uniqueExercisesInSets collect:
97
Removed:
#canonicalName) asOrderedCollection joinUsing: ', ')
98
Removed:
capitalized
99
Removed:
]
100
Removed:
101
Removed:
{ #category : 'accessing' }
102
Removed:
MFTSetGroupLogViewerComponent >> setGroupLog: aMFTSetGroupLog [
103
Removed:
104
Removed:
setGroupLog := aMFTSetGroupLog
105
Removed:
]
src/MyFitnessTracker-Web/MFTStatusComponent.class.st
@@ -1,25 +0,0 @@
1
Removed:
Class {
2
Removed:
#name : 'MFTStatusComponent',
3
Removed:
#superclass : 'WAComponent',
4
Removed:
#category : 'MyFitnessTracker-Web-Components',
5
Removed:
#package : 'MyFitnessTracker-Web',
6
Removed:
#tag : 'Components'
7
Removed:
}
8
Removed:
9
Removed:
{ #category : 'rendering' }
10
Removed:
MFTStatusComponent >> renderContentOn: html [
11
Removed:
12
Removed:
| trainee |
13
Removed:
trainee := self session user trainee.
14
Removed:
15
Removed:
html section: [
16
Removed:
html definitionList: [
17
Removed:
trainee logBook durationSinceLastWorkout ifNotNil: [
18
Removed:
html definitionTerm: 'Hours since last workout'.
19
Removed:
html definitionData:
20
Removed:
trainee logBook durationSinceLastWorkout asHours rounded asString ].
21
Removed:
html definitionTerm: 'Recovery status'.
22
Removed:
html definitionData: (trainee isRecovered
23
Removed:
ifTrue: [ 'Ready to train again' ]
24
Removed:
ifFalse: [ 'Not recovered yet, rest more' ]) ] ]
25
Removed:
]
src/MyFitnessTracker-Web/MFTUser.class.st
@@ -2,7 +2,8 @@
2
2
#name : 'MFTUser',
3
3
#superclass : 'Object',
4
4
#instVars : [
5
Removed:
'trainee'
5
Added:
'trainee',
6
Added:
'username'
6
7
],
7
8
#category : 'MyFitnessTracker-Web-Base',
8
9
#package : 'MyFitnessTracker-Web',
@@ -14,6 +15,7 @@
14
15
15
16
^ self new
16
17
trainee: MFTTrainee newDefault;
18
Added:
username: 'default_01';
17
19
yourself
18
20
]
19
21
@@ -27,4 +29,16 @@
27
29
MFTUser >> trainee: aMFTTrainee [
28
30
29
31
trainee := aMFTTrainee
32
Added:
]
33
Added:
34
Added:
{ #category : 'accessing' }
35
Added:
MFTUser >> username [
36
Added:
37
Added:
^ username
38
Added:
]
39
Added:
40
Added:
{ #category : 'accessing' }
41
Added:
MFTUser >> username: aString [
42
Added:
43
Added:
username := aString
30
44
]
src/MyFitnessTracker-Web/MFTWorkoutLogEditorComponent.class.st
@@ -3,7 +3,6 @@
3
3
#superclass : 'WAComponent',
4
4
#instVars : [
5
5
'workoutLog',
6
Removed:
'setGroupLogComponents',
7
6
'onSaveWorkout',
8
7
'onDiscardWorkout'
9
8
],
@@ -21,19 +20,13 @@
21
20
]
22
21
23
22
{ #category : 'as yet unclassified' }
24
Removed:
MFTWorkoutLogEditorComponent >> children [
23
Added:
MFTWorkoutLogEditorComponent class >> forWorkoutPrescription: aMFTWorkoutPrescription [
25
24
26
Removed:
^ setGroupLogComponents
25
Added:
^ self forWorkoutLog:
26
Added:
(MFTWorkoutLog forPrescription: aMFTWorkoutPrescription) startNow
27
27
]
28
28
29
29
{ #category : 'as yet unclassified' }
30
Removed:
MFTWorkoutLogEditorComponent >> initialize [
31
Removed:
32
Removed:
super initialize.
33
Removed:
setGroupLogComponents := OrderedCollection new
34
Removed:
]
35
Removed:
36
Removed:
{ #category : 'as yet unclassified' }
37
30
MFTWorkoutLogEditorComponent >> onDiscardWorkout: aBlock [
38
31
39
32
onDiscardWorkout := aBlock
@@ -49,70 +42,123 @@
49
42
MFTWorkoutLogEditorComponent >> renderContentOn: html [
50
43
51
44
html heading
52
Removed:
level: 1;
53
Removed:
with: 'Log Workout'.
54
Removed:
html heading
55
45
level: 2;
56
46
with: workoutLog prescription canonicalName.
57
47
html form: [
58
Removed:
self renderWorkoutLogMetadataOn: html.
59
Removed:
setGroupLogComponents do: [ :each | html render: each ].
60
Removed:
self renderFormActionsOn: html ]
48
Added:
self
49
Added:
renderWorkoutLogMetadataOn: html;
50
Added:
renderSetGroupLogsOn: html;
51
Added:
renderFormActionsOn: html ]
61
52
]
62
53
63
54
{ #category : 'as yet unclassified' }
64
55
MFTWorkoutLogEditorComponent >> renderFormActionsOn: html [
65
56
66
Removed:
html submitButton
67
Removed:
callback: [ onSaveWorkout value ];
68
Removed:
with: 'Save workout'.
57
Added:
html fieldSet
58
Added:
class: 'grid';
59
Added:
with: [
60
Added:
html submitButton
61
Added:
callback: [ onSaveWorkout value ];
62
Added:
with: 'Finish and save workout'.
69
63
70
Removed:
html submitButton
71
Removed:
callback: [ onDiscardWorkout value ];
72
Removed:
with: 'Discard workout'
64
Added:
html submitButton
65
Added:
class: 'secondary';
66
Added:
callback: [ onDiscardWorkout value ];
67
Added:
with: 'Discard workout' ]
73
68
]
74
69
70
Added:
{ #category : 'rendering' }
71
Added:
MFTWorkoutLogEditorComponent >> renderSetGroupLogData: setGroupLog on: html [
72
Added:
73
Added:
html table: [
74
Added:
html
75
Added:
tableHead: [
76
Added:
html tableRow: [
77
Added:
html
78
Added:
tableHeading: 'Exercise';
79
Added:
tableHeading: 'Reps';
80
Added:
tableHeading: 'Load';
81
Added:
tableHeading: 'Failure Achieved' ] ];
82
Added:
tableBody: [
83
Added:
setGroupLog sets do: [ :setLog |
84
Added:
html tableRow: [
85
Added:
html
86
Added:
tableData: setLog exercise;
87
Added:
tableData: setLog reps;
88
Added:
tableData: setLog load;
89
Added:
tableData: setLog failureAchieved ] ] ] ]
90
Added:
]
91
Added:
92
Added:
{ #category : 'rendering' }
93
Added:
MFTWorkoutLogEditorComponent >> renderSetGroupLogsOn: html [
94
Added:
95
Added:
workoutLog setGroups do: [ :setGroupLog |
96
Added:
| isCompletelyLogged |
97
Added:
isCompletelyLogged := setGroupLog isCompletelyLogged.
98
Added:
99
Added:
html fieldSet: [
100
Added:
html heading
101
Added:
level: 2;
102
Added:
with: setGroupLog canonicalName capitalized.
103
Added:
html heading
104
Added:
level: 3;
105
Added:
with:
106
Added:
(setGroupLog uniqueExercisesInSets asOrderedCollection
107
Added:
joinUsing: ', ').
108
Added:
109
Added:
110
Added:
isCompletelyLogged ifTrue: [
111
Added:
self renderSetGroupLogData: setGroupLog on: html ].
112
Added:
html anchor
113
Added:
callback: [
114
Added:
self call:
115
Added:
(MFTSetGroupLogEditorComponent forSetGroupLog: setGroupLog) ];
116
Added:
with: (isCompletelyLogged
117
Added:
ifTrue: 'Edit'
118
Added:
ifFalse: 'Log') ] ]
119
Added:
]
120
Added:
75
121
{ #category : 'as yet unclassified' }
76
122
MFTWorkoutLogEditorComponent >> renderWorkoutLogMetadataOn: html [
77
123
78
Removed:
html fieldSet: [
79
Removed:
html legend: 'Log info'.
80
Removed:
html div
81
Removed:
class: 'mft-form-items-container';
82
Removed:
with: [
83
Removed:
html label
84
Removed:
for: 'start-date';
85
Removed:
with: 'Start'.
86
Removed:
html span: [
87
Removed:
html dateInput5
88
Removed:
id: 'start-date';
89
Removed:
value: Date today yyyymmdd;
90
Removed:
callback: [ :value |
91
Removed:
workoutLog startDate:
92
Removed:
(Date readFrom: value pattern: 'yyyy-mm-dd') ].
93
Removed:
html timeInput5
94
Removed:
id: 'start-time';
95
Removed:
value: workoutLog start asTime print24;
96
Removed:
callback: [ :value |
97
Removed:
workoutLog startTime: (Time fromString: value) ] ] ].
98
Removed:
html div
99
Removed:
class: 'mft-form-items-container';
100
Removed:
with: [
101
Removed:
html label
102
Removed:
for: 'finish-date';
103
Removed:
with: 'Finish'.
104
Removed:
html span: [
105
Removed:
html dateInput5
106
Removed:
id: 'finish-date';
107
Removed:
value: Date today yyyymmdd;
108
Removed:
callback: [ :value |
109
Removed:
workoutLog finishDate:
110
Removed:
(Date readFrom: value pattern: 'yyyy-mm-dd') ].
111
Removed:
html timeInput5
112
Removed:
id: 'finish-time';
113
Removed:
callback: [ :value |
114
Removed:
value ifNotEmpty: [
115
Removed:
workoutLog finishTime: (Time fromString: value) ] ] ] ] ]
124
Added:
html fieldSet
125
Added:
class: 'grid';
126
Added:
with: [
127
Added:
html legend: 'Start'.
128
Added:
html dateInput5
129
Added:
value: Date today yyyymmdd;
130
Added:
callback: [ :value |
131
Added:
workoutLog startDate:
132
Added:
(Date readFrom: value pattern: 'yyyy-mm-dd') ].
133
Added:
html timeInput5
134
Added:
value: workoutLog start asTime print24;
135
Added:
callback: [ :value |
136
Added:
workoutLog startTime: (Time fromString: value) ].
137
Added:
html button
138
Added:
class: 'secondary outline';
139
Added:
callback: [
140
Added:
workoutLog startNow.
141
Added:
workoutLog finish: nil ];
142
Added:
with: 'Start now' ].
143
Added:
html fieldSet
144
Added:
class: 'grid';
145
Added:
with: [
146
Added:
html legend: 'Finish'.
147
Added:
html dateInput5
148
Added:
value: Date today yyyymmdd;
149
Added:
callback: [ :value |
150
Added:
workoutLog finishDate:
151
Added:
(Date readFrom: value pattern: 'yyyy-mm-dd') ].
152
Added:
html timeInput5
153
Added:
value:
154
Added:
(workoutLog finish ifNotNil: [ workoutLog finish asTime print24 ]);
155
Added:
callback: [ :value |
156
Added:
value ifNotEmpty: [
157
Added:
workoutLog finishTime: (Time fromString: value) ] ].
158
Added:
html button
159
Added:
class: 'secondary outline';
160
Added:
callback: [ workoutLog finishNow ];
161
Added:
with: 'Finish now' ]
116
162
]
117
163
118
164
{ #category : 'accessing' }
@@ -124,8 +170,5 @@
124
170
{ #category : 'accessing' }
125
171
MFTWorkoutLogEditorComponent >> workoutLog: aMFTWorkoutLog [
126
172
127
Removed:
workoutLog := aMFTWorkoutLog.
128
Removed:
setGroupLogComponents := workoutLog setGroups collect: [ :setGroupLog |
129
Removed:
(MFTSetGroupLogViewerComponent
130
Removed:
forSetGroupLog: setGroupLog) beEditable ]
173
Added:
workoutLog := aMFTWorkoutLog
131
174
]
src/MyFitnessTracker-Web/MFTWorkoutLogEditorPage.class.st
@@ -40,9 +40,11 @@
40
40
{ #category : 'rendering' }
41
41
MFTWorkoutLogEditorPage >> renderContentOn: html [
42
42
43
Removed:
self
44
Removed:
renderPageOn: html
45
Removed:
with: [ html render: workoutLogEditorComponent ]
43
Added:
self renderPageOn: html with: [
44
Added:
html heading
45
Added:
level: 1;
46
Added:
with: 'Log Workout'.
47
Added:
html render: workoutLogEditorComponent ]
46
48
]
47
49
48
50
{ #category : 'accessing' }
src/MyFitnessTracker-Web/MFTWorkoutLogViewerComponent.class.st
@@ -1,89 +0,0 @@
1
Removed:
Class {
2
Removed:
#name : 'MFTWorkoutLogViewerComponent',
3
Removed:
#superclass : 'WAComponent',
4
Removed:
#instVars : [
5
Removed:
'heading',
6
Removed:
'workoutLog',
7
Removed:
'beEditable',
8
Removed:
'setGroupLogComponents',
9
Removed:
'onEdit'
10
Removed:
],
11
Removed:
#category : 'MyFitnessTracker-Web-Components',
12
Removed:
#package : 'MyFitnessTracker-Web',
13
Removed:
#tag : 'Components'
14
Removed:
}
15
Removed:
16
Removed:
{ #category : 'as yet unclassified' }
17
Removed:
MFTWorkoutLogViewerComponent class >> forWorkoutLog: aMFTWorkoutLog [
18
Removed:
19
Removed:
^ self new
20
Removed:
workoutLog: aMFTWorkoutLog;
21
Removed:
yourself
22
Removed:
]
23
Removed:
24
Removed:
{ #category : 'accessing' }
25
Removed:
MFTWorkoutLogViewerComponent >> heading: aString [
26
Removed:
27
Removed:
heading := aString
28
Removed:
]
29
Removed:
30
Removed:
{ #category : 'initialization' }
31
Removed:
MFTWorkoutLogViewerComponent >> initialize [
32
Removed:
33
Removed:
super initialize.
34
Removed:
beEditable := false.
35
Removed:
setGroupLogComponents := OrderedCollection new
36
Removed:
]
37
Removed:
38
Removed:
{ #category : 'rendering' }
39
Removed:
MFTWorkoutLogViewerComponent >> onEdit: aBlock [
40
Removed:
41
Removed:
onEdit := aBlock
42
Removed:
]
43
Removed:
44
Removed:
{ #category : 'rendering' }
45
Removed:
MFTWorkoutLogViewerComponent >> renderContentOn: html [
46
Removed:
47
Removed:
html section: [
48
Removed:
html heading
49
Removed:
level: 2;
50
Removed:
with: heading.
51
Removed:
html heading
52
Removed:
level: 3;
53
Removed:
with: workoutLog prescription canonicalName.
54
Removed:
self renderWorkoutLogMetadataOn: html.
55
Removed:
setGroupLogComponents do: [ :each | html render: each ].
56
Removed:
self renderFormActionsOn: html ]
57
Removed:
]
58
Removed:
59
Removed:
{ #category : 'rendering' }
60
Removed:
MFTWorkoutLogViewerComponent >> renderFormActionsOn: html [
61
Removed:
62
Removed:
^ html form: [
63
Removed:
html button
64
Removed:
callback: [ onEdit value ];
65
Removed:
with: 'Edit' ]
66
Removed:
]
67
Removed:
68
Removed:
{ #category : 'rendering' }
69
Removed:
MFTWorkoutLogViewerComponent >> renderWorkoutLogMetadataOn: html [
70
Removed:
71
Removed:
html definitionList: [
72
Removed:
html
73
Removed:
definitionTerm: 'Start time';
74
Removed:
definitionData: workoutLog start asStringYMDHM;
75
Removed:
definitionTerm: 'Duration';
76
Removed:
definitionData:
77
Removed:
workoutLog duration asMinutes rounded asString , ' minutes';
78
Removed:
definitionTerm: 'Intensity factor';
79
Removed:
definitionData: workoutLog intensityFactor asString , '%' ]
80
Removed:
]
81
Removed:
82
Removed:
{ #category : 'accessing' }
83
Removed:
MFTWorkoutLogViewerComponent >> workoutLog: aMFTWorkoutLog [
84
Removed:
85
Removed:
workoutLog := aMFTWorkoutLog.
86
Removed:
setGroupLogComponents := workoutLog setGroups collect: [ :setGroupLog |
87
Removed:
MFTSetGroupLogViewerComponent
88
Removed:
forSetGroupLog: setGroupLog ]
89
Removed:
]
src/MyFitnessTracker-Web/MFTWorkoutPrescriptionViewerComponent.class.st
@@ -1,39 +0,0 @@
1
Removed:
Class {
2
Removed:
#name : 'MFTWorkoutPrescriptionViewerComponent',
3
Removed:
#superclass : 'WAComponent',
4
Removed:
#instVars : [
5
Removed:
'heading',
6
Removed:
'workoutPrescription'
7
Removed:
],
8
Removed:
#category : 'MyFitnessTracker-Web-Components',
9
Removed:
#package : 'MyFitnessTracker-Web',
10
Removed:
#tag : 'Components'
11
Removed:
}
12
Removed:
13
Removed:
{ #category : 'accessing' }
14
Removed:
MFTWorkoutPrescriptionViewerComponent >> heading: aString [
15
Removed:
16
Removed:
heading := aString
17
Removed:
]
18
Removed:
19
Removed:
{ #category : 'rendering' }
20
Removed:
MFTWorkoutPrescriptionViewerComponent >> renderContentOn: html [
21
Removed:
22
Removed:
html section: [
23
Removed:
html heading
24
Removed:
level: 2;
25
Removed:
with: heading.
26
Removed:
html heading
27
Removed:
level: 3;
28
Removed:
with: workoutPrescription canonicalName.
29
Removed:
html orderedList: [
30
Removed:
workoutPrescription setGroups do: [ :setGroup |
31
Removed:
html listItem:
32
Removed:
((setGroup sets collect: #exercise) joinUsing: ', ') ] ] ]
33
Removed:
]
34
Removed:
35
Removed:
{ #category : 'as yet unclassified' }
36
Removed:
MFTWorkoutPrescriptionViewerComponent >> workoutPrescription: aMFTWorkoutPrescription [
37
Removed:
38
Removed:
workoutPrescription := aMFTWorkoutPrescription
39
Removed:
]