[Pharo] Personal fitness tracker web app.
Added new pages and components, and made lots of miscellaneous enhancements.
- Added MFTAthlete, MFTAthletesArticle, and MFTPrize. - Heavily improved MFTLearnPage. - Removed instance variables for pages (workouts and weights). Instead, the MFTUser instance will store its own workouts and weights. - Started work on the MFTWorkoutTask component.
Changed files
- src/MyFitnessTracker/MFTAboutPage.class.st
- src/MyFitnessTracker/MFTAthlete.class.st
- src/MyFitnessTracker/MFTAthletesArticle.class.st
- src/MyFitnessTracker/MFTDefaultFooter.class.st
- src/MyFitnessTracker/MFTFooter.class.st
- src/MyFitnessTracker/MFTFooterComponent.class.st
- src/MyFitnessTracker/MFTLandingPage.class.st
- src/MyFitnessTracker/MFTLearnPage.class.st
- src/MyFitnessTracker/MFTLoginRegisterLogoutComponent.class.st
- src/MyFitnessTracker/MFTMainNavigationBarComponent.class.st
- src/MyFitnessTracker/MFTMainPublicCard.class.st
- src/MyFitnessTracker/MFTMikeMentzer.class.st
- src/MyFitnessTracker/MFTMuscleGroup.class.st
- src/MyFitnessTracker/MFTMusclesArticle.class.st
- src/MyFitnessTracker/MFTPage.class.st
- src/MyFitnessTracker/MFTPageManager.class.st
- src/MyFitnessTracker/MFTPrize.class.st
- src/MyFitnessTracker/MFTProfilePage.class.st
- src/MyFitnessTracker/MFTPublicLandingPage.class.st
- src/MyFitnessTracker/MFTScreenComponent.class.st
- src/MyFitnessTracker/MFTSession.class.st
- src/MyFitnessTracker/MFTUser.class.st
- src/MyFitnessTracker/MFTUserLandingPage.class.st
- src/MyFitnessTracker/MFTWeightVsTimeGraph.class.st
- src/MyFitnessTracker/MFTWeightsListPage.class.st
- src/MyFitnessTracker/MFTWorkout.class.st
- src/MyFitnessTracker/MFTWorkoutTask.class.st
- src/MyFitnessTracker/MFTWorkoutsListPage.class.st
src/MyFitnessTracker/MFTAboutPage.class.st
@@ -14,12 +14,8 @@
14
14
{ #category : #rendering }
15
15
MFTAboutPage >> renderBackgroundOn: html [
16
16
17
Removed:
html heading
18
Removed:
level: 1;
19
Removed:
with: 'Background'.
20
Removed:
html heading
21
Removed:
level: 2;
22
Removed:
with: 'Why I built this web app'.
17
Added:
html heading level1 with: 'Background'.
18
Added:
html heading level2 with: 'Why I built this web app'.
23
19
html
24
20
paragraph:
25
21
'I wanted a convenient way to record, perform data analysis, and create visualizations for my workouts.';
@@ -41,23 +37,28 @@
41
37
{ #category : #rendering }
42
38
MFTAboutPage >> renderCatchOn: html [
43
39
44
Removed:
html heading
45
Removed:
dangerText;
46
Removed:
with: 'The catch'.
40
Added:
html heading level1 dangerText with: 'The catch'.
47
41
html
48
42
paragraph:
49
43
'I''ve made some debatable compromises when it comes to My Fitness Tracker:';
50
44
unorderedList: [
51
45
html
52
Removed:
listItem: 'No external advertisements,';
46
Added:
listItem: 'No external advertisement,';
53
47
listItem:
54
48
'No cookies or personally identifying information stored,';
55
49
listItem:
56
50
'No paid feature, except for the storage of your training data beyond ten workouts.' ];
57
51
paragraph:
58
Removed:
'I know these design choices might frustrate and maybe even anger certain users; thankfully, all previously existing fitness tracking services do not abide by these design principles.';
52
Added:
'I know these design choices might frustrate and maybe even anger certain users; '
53
Added:
,
54
Added:
'thankfully, all previously existing fitness tracking services do not abide by these design principles.';
59
55
paragraph:
60
Removed:
'I am developing My Fitness Tracker for my own personal use case, first and foremost; secondly, for the benefit of as many fitness enthusiasts as possible; thirdly, because I''ve found to be a fun experience. I''m already rich of the joy this project has brought me, and the paid '
56
Added:
'I am developing My Fitness Tracker for my own personal use case, first and foremost; '
57
Added:
,
58
Added:
'secondly, for the benefit of as many fitness enthusiasts as possible; '
59
Added:
, 'thirdly, because I''ve found to be a fun experience. '
60
Added:
,
61
Added:
'I''m already rich of the joy this project has brought me, and the paid '
61
62
]
62
63
63
64
{ #category : #rendering }
@@ -66,7 +67,7 @@
66
67
self renderPageOn: html with: [
67
68
self renderVisionOn: html.
68
69
self renderBackgroundOn: html.
69
Removed:
self renderCatchOn: html]
70
Added:
self renderCatchOn: html ]
70
71
]
71
72
72
73
{ #category : #rendering }
src/MyFitnessTracker/MFTAthlete.class.st
@@ -0,0 +1,145 @@
1
Added:
Class {
2
Added:
#name : #MFTAthlete,
3
Added:
#superclass : #SBSComponent,
4
Added:
#instVars : [
5
Added:
'name',
6
Added:
'nickname',
7
Added:
'born',
8
Added:
'died',
9
Added:
'bio',
10
Added:
'workouts'
11
Added:
],
12
Added:
#category : #'MyFitnessTracker-Model'
13
Added:
}
14
Added:
15
Added:
{ #category : #'as yet unclassified' }
16
Added:
MFTAthlete class >> allAthletes [
17
Added:
18
Added:
^ { #'Arnold Alois Schwarzenneger'. #'Michael John Mentzer'.
19
Added:
#'Thomas Steven Platz' }
20
Added:
]
21
Added:
22
Added:
{ #category : #'instance creation' }
23
Added:
MFTAthlete class >> newFromDictionary: aDictionary [
24
Added:
25
Added:
^ self new
26
Added:
date: (Date fromString: (aDictionary at: 'date'));
27
Added:
primaryMuscle:
28
Added:
(MFTMuscle new latinName: (aDictionary at: 'primary_muscle'));
29
Added:
secondaryMuscles:
30
Added:
(MFTMuscle new latinName: (aDictionary at: 'secondary_muscles'));
31
Added:
yourself
32
Added:
]
33
Added:
34
Added:
{ #category : #accessing }
35
Added:
MFTAthlete class >> primaryMuscle: aMFTMuscle [
36
Added:
37
Added:
^ self new
38
Added:
primaryMuscle: aMFTMuscle;
39
Added:
yourself
40
Added:
]
41
Added:
42
Added:
{ #category : #accessing }
43
Added:
MFTAthlete class >> primaryMuscle: aMFTMuscle1 secondaryMuscles: aMFTMuscle2 [
44
Added:
^ self new
45
Added:
primaryMuscle: aMFTMuscle1;
46
Added:
secondaryMuscles: aMFTMuscle2;
47
Added:
yourself
48
Added:
]
49
Added:
50
Added:
{ #category : #accessing }
51
Added:
MFTAthlete >> bio [
52
Added:
53
Added:
^ bio
54
Added:
]
55
Added:
56
Added:
{ #category : #accessing }
57
Added:
MFTAthlete >> born [
58
Added:
59
Added:
^ born
60
Added:
]
61
Added:
62
Added:
{ #category : #accessing }
63
Added:
MFTAthlete >> died [
64
Added:
65
Added:
^ died
66
Added:
]
67
Added:
68
Added:
{ #category : #initialization }
69
Added:
MFTAthlete >> initialize [
70
Added:
71
Added:
super initialize.
72
Added:
name := 'John Default'.
73
Added:
nickname := 'Johnny D.'.
74
Added:
born := Date fromString: '01/01/2000'.
75
Added:
died := Date fromString: '01/01/2000'.
76
Added:
bio := 'John Default is still today regarded as one of the most default bodybuilders ever.'
77
Added:
]
78
Added:
79
Added:
{ #category : #accessing }
80
Added:
MFTAthlete >> name [
81
Added:
82
Added:
^ name
83
Added:
]
84
Added:
85
Added:
{ #category : #accessing }
86
Added:
MFTAthlete >> nickname [
87
Added:
88
Added:
^ nickname
89
Added:
]
90
Added:
91
Added:
{ #category : #accessing }
92
Added:
MFTAthlete >> prizes [
93
Added:
94
Added:
^ {
95
Added:
(MFTPrize year: 1989 competition: 'Default Prize' place: 1).
96
Added:
(MFTPrize year: 1988 competition: 'Default Prize' place: 2) }
97
Added:
]
98
Added:
99
Added:
{ #category : #rendering }
100
Added:
MFTAthlete >> renderContentOn: html [
101
Added:
102
Added:
html heading level2 with: name.
103
Added:
html heading level3 textMuted with:
104
Added:
nickname , ' (' , born year asString , '–' , died year asString
105
Added:
, ')'.
106
Added:
html outlineButton bePrimary
107
Added:
dataToggle: 'collapse';
108
Added:
dataTarget: '#collapsePrizes';
109
Added:
with: 'Prizes'.
110
Added:
html collapse
111
Added:
id: 'collapsePrizes';
112
Added:
with: [
113
Added:
html div
114
Added:
marginTopAndBottom: 3;
115
Added:
style: 'height: 14em; overflow: scroll';
116
Added:
with: [ self renderPrizesTableOn: html ] ].
117
Added:
html paragraph: bio
118
Added:
]
119
Added:
120
Added:
{ #category : #rendering }
121
Added:
MFTAthlete >> renderPrizesTableOn: html [
122
Added:
123
Added:
html table
124
Added:
class: 'table table-striped table-bordered';
125
Added:
with: [
126
Added:
html tableHead: [
127
Added:
html tableRow: [
128
Added:
html tableHeading: 'Year'.
129
Added:
html tableHeading: 'Competition'.
130
Added:
html tableHeading: 'Place'.
131
Added:
html tableHeading: 'Category' ] ].
132
Added:
html tableBody: [
133
Added:
self prizes do: [ :prize |
134
Added:
html tableRow: [
135
Added:
html tableData: prize year.
136
Added:
html tableData: prize competition.
137
Added:
html tableData: prize place.
138
Added:
html tableData: prize category ] ] ] ]
139
Added:
]
140
Added:
141
Added:
{ #category : #accessing }
142
Added:
MFTAthlete >> workouts [
143
Added:
144
Added:
^ workouts
145
Added:
]
src/MyFitnessTracker/MFTAthletesArticle.class.st
@@ -0,0 +1,23 @@
1
Added:
Class {
2
Added:
#name : #MFTAthletesArticle,
3
Added:
#superclass : #MFTArticle,
4
Added:
#instVars : [
5
Added:
'athletes'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Components'
8
Added:
}
9
Added:
10
Added:
{ #category : #initialization }
11
Added:
MFTAthletesArticle >> initialize [
12
Added:
13
Added:
super initialize.
14
Added:
title := 'Athletes'.
15
Added:
athletes := { MFTMikeMentzer new}
16
Added:
]
17
Added:
18
Added:
{ #category : #rendering }
19
Added:
MFTAthletesArticle >> renderContentOn: html [
20
Added:
21
Added:
html heading: title.
22
Added:
athletes do: [ :athlete | athlete renderContentOn: html ]
23
Added:
]
src/MyFitnessTracker/MFTDefaultFooter.class.st
@@ -0,0 +1,16 @@
1
Added:
Class {
2
Added:
#name : #MFTDefaultFooter,
3
Added:
#superclass : #MFTFooter,
4
Added:
#category : #'MyFitnessTracker-Components'
5
Added:
}
6
Added:
7
Added:
{ #category : #rendering }
8
Added:
MFTDefaultFooter >> renderContentOn: html [
9
Added:
10
Added:
html card
11
Added:
marginTop: 3;
12
Added:
class: 'align-items-center';
13
Added:
with: [
14
Added:
html cardHeader:
15
Added:
'Copyright 2023–' , Date today year asString , ' Marius PETER' ]
16
Added:
]
src/MyFitnessTracker/MFTFooter.class.st
@@ -0,0 +1,13 @@
1
Added:
Class {
2
Added:
#name : #MFTFooter,
3
Added:
#superclass : #SBSComponent,
4
Added:
#category : #'MyFitnessTracker-Components'
5
Added:
}
6
Added:
7
Added:
{ #category : #rendering }
8
Added:
MFTFooter >> renderContentOn: html [
9
Added:
10
Added:
html card
11
Added:
marginTop: 3;
12
Added:
with: [ html cardHeader: 'I am the default footer' ]
13
Added:
]
src/MyFitnessTracker/MFTFooterComponent.class.st
@@ -1,15 +0,0 @@
1
Removed:
Class {
2
Removed:
#name : #MFTFooterComponent,
3
Removed:
#superclass : #SBSComponent,
4
Removed:
#category : #'MyFitnessTracker-Components'
5
Removed:
}
6
Removed:
7
Removed:
{ #category : #rendering }
8
Removed:
MFTFooterComponent >> renderContentOn: html [
9
Removed:
10
Removed:
html card
11
Removed:
marginTop: 3;
12
Removed:
with: [
13
Removed:
html cardHeader:
14
Removed:
'Copyright 2023-' , Date today year asString , ' Marius PETER' ]
15
Removed:
]
src/MyFitnessTracker/MFTLandingPage.class.st
@@ -0,0 +1,41 @@
1
Added:
Class {
2
Added:
#name : #MFTLandingPage,
3
Added:
#superclass : #MFTPage,
4
Added:
#instVars : [
5
Added:
'cards'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Components'
8
Added:
}
9
Added:
10
Added:
{ #category : #hooks }
11
Added:
MFTLandingPage >> children [
12
Added:
13
Added:
^ cards
14
Added:
]
15
Added:
16
Added:
{ #category : #'as yet unclassified' }
17
Added:
MFTLandingPage >> defaultCards [
18
Added:
19
Added:
^ {
20
Added:
MFTCard new.
21
Added:
MFTCard new.
22
Added:
MFTCard new }
23
Added:
]
24
Added:
25
Added:
{ #category : #'as yet unclassified' }
26
Added:
MFTLandingPage >> initialize [
27
Added:
28
Added:
super initialize.
29
Added:
title := 'landingPage'.
30
Added:
cards := self defaultCards
31
Added:
]
32
Added:
33
Added:
{ #category : #rendering }
34
Added:
MFTLandingPage >> renderContentOn: html [
35
Added:
36
Added:
self renderPageOn: html with: [
37
Added:
html div
38
Added:
style:
39
Added:
'display: flex; flex-wrap: wrap; justify-content: space-around; gap: 1em';
40
Added:
with: [ cards do: [ :card | html render: card ] ] ]
41
Added:
]
src/MyFitnessTracker/MFTLearnPage.class.st
@@ -2,7 +2,8 @@
2
2
#name : #MFTLearnPage,
3
3
#superclass : #MFTPage,
4
4
#instVars : [
5
Removed:
'articles'
5
Added:
'articles',
6
Added:
'activeArticle'
6
7
],
7
8
#category : #'MyFitnessTracker-Components'
8
9
}
@@ -12,13 +13,36 @@
12
13
13
14
super initialize.
14
15
title := 'learn'.
15
Removed:
articles := Array with: MFTMusclesArticle new
16
Added:
articles := {
17
Added:
MFTAthletesArticle new.
18
Added:
MFTMusclesArticle new }.
19
Added:
activeArticle := articles first
16
20
]
17
21
18
22
{ #category : #rendering }
19
23
MFTLearnPage >> renderContentOn: html [
20
24
21
Removed:
self
22
Removed:
renderPageOn: html
23
Removed:
with: [ articles do: [ :each | html render: each ] ]
25
Added:
self renderPageOn: html with: [
26
Added:
html breadcrumb: [
27
Added:
html breadcrumbItem: [
28
Added:
html anchor
29
Added:
callback: [ self session pageManager activePage: #learn ];
30
Added:
with: 'Home' ].
31
Added:
html breadcrumbItem: [
32
Added:
html anchor
33
Added:
url: '#';
34
Added:
with: activeArticle title ].
35
Added:
html breadcrumbItem
36
Added:
beActive;
37
Added:
with: 'Data' ].
38
Added:
html div
39
Added:
class: 'table-of-contents';
40
Added:
with: [
41
Added:
html navigation flexColumn with: [
42
Added:
articles do: [ :article |
43
Added:
html navigationLink
44
Added:
beActiveIf: [ activeArticle = article ];
45
Added:
callback: [ activeArticle := article ];
46
Added:
with: article title ] ] ].
47
Added:
html render: activeArticle ]
24
48
]
src/MyFitnessTracker/MFTLoginRegisterLogoutComponent.class.st
@@ -11,7 +11,7 @@
11
11
MFTLoginRegisterLogoutComponent >> attemptLogin: aMFTUser [
12
12
"Attempt to match aMFTUser passwordHash against an existing user password_hash in the database.
13
13
14
Removed:
If a matching user is found, hydrate a MFTUser from the existingUser, and keep track of the database connection used to authenticate.
14
Added:
If a matching user is found, hydrate a MFTUser from the existingUser.
15
15
If no matching user is found, kill the connection."
16
16
17
17
| connection existingUser passwordHash |
src/MyFitnessTracker/MFTMainNavigationBarComponent.class.st
@@ -22,7 +22,6 @@
22
22
23
23
{ #category : #rendering }
24
24
MFTMainNavigationBarComponent >> renderContentOn: html [
25
Removed:
"FIXME: NavigationBar Bootstrap class cannot be sticky-top, otherwise login modals are hidden by a shadow..."
26
25
27
26
html navigationBar
28
27
beLight;
@@ -30,6 +29,7 @@
30
29
expandLarge;
31
30
marginBottom: 3;
32
31
paddingLeftAndRight: 3;
32
Added:
style: 'position: sticky; top: 0; z-index: 1051';
33
33
with: [ self renderNavigationBarItemsOn: html ]
34
34
]
35
35
@@ -38,27 +38,25 @@
38
38
39
39
| pm |
40
40
pm := self session pageManager.
41
Removed:
html navigationBarBrand
42
Removed:
callback: [ pm activePage: 1 ];
43
Removed:
with: 'MyFitnessTracker'.
44
41
"The toggler that is only visible when reducing the width of screen"
45
42
html navigationBarToggler
46
43
beButtonType;
47
44
collapse;
48
45
dataTarget: '#navbarCollapsed';
49
46
with: [ html navigationBarTogglerIcon ].
47
Added:
html navigationBarBrand
48
Added:
callback: [ pm activePage: 1 ];
49
Added:
with: 'MyFitnessTracker'.
50
50
html navigationBarCollapse collapse
51
51
id: 'navbarCollapsed';
52
52
with: [
53
53
html navigationBarNavigation: [
54
Removed:
pm mainPages doWithIndex: [ :page :i |
54
Added:
pm mainPages keysAndValuesDo: [ :key :value |
55
55
html navigationItem
56
Removed:
beActiveIf: [ pm activePage = page ];
56
Added:
beActiveIf: [ pm activePage = value ];
57
57
with: [
58
58
html navigationLink
59
Removed:
callback: [ pm activePage: i ];
60
Removed:
with: page title asCapitalizedPhrase ] ] ].
61
Removed:
html div
62
Removed:
class: 'ms-auto';
63
Removed:
with: [ html render: loginRegisterLogout ] ]
59
Added:
callback: [ pm activePage: key ];
60
Added:
with: value title asCapitalizedPhrase ] ] ] ].
61
Added:
html div: [ html render: loginRegisterLogout ]
64
62
]
src/MyFitnessTracker/MFTMainPublicCard.class.st
@@ -20,7 +20,10 @@
20
20
html displayHeading
21
21
level: 1;
22
22
with: 'Welcome to My Fitness Tracker!'.
23
Removed:
html big textMuted with: 'Free Software never looked so fit.'.
23
Added:
html heading
24
Added:
level: 2;
25
Added:
textMuted;
26
Added:
with: 'Free Software never looked so fit.'.
24
27
html form: [
25
28
html formButton
26
29
bePrimary;
src/MyFitnessTracker/MFTMikeMentzer.class.st
@@ -0,0 +1,101 @@
1
Added:
Class {
2
Added:
#name : #MFTMikeMentzer,
3
Added:
#superclass : #MFTAthlete,
4
Added:
#category : #'MyFitnessTracker-Model'
5
Added:
}
6
Added:
7
Added:
{ #category : #initialization }
8
Added:
MFTMikeMentzer >> initialize [
9
Added:
10
Added:
super initialize.
11
Added:
name := 'Michael John Mentzer'.
12
Added:
nickname := 'Mike Mentzer'.
13
Added:
born := Date fromString: '11/15/1951'.
14
Added:
died := Date fromString: '06/10/2001'.
15
Added:
bio := 'Mike Mentzer is most famous for his Heavy Duty training regimen.'.
16
Added:
]
17
Added:
18
Added:
{ #category : #accessing }
19
Added:
MFTMikeMentzer >> prizes [
20
Added:
21
Added:
^ {
22
Added:
(MFTPrize year: 1971 competition: 'Mr. Lancaster' place: 1).
23
Added:
(MFTPrize year: 1971 competition: 'AAU Mr. America' place: 10).
24
Added:
(MFTPrize year: 1971 competition: 'AAU Teen Mr America' place: 2).
25
Added:
(MFTPrize
26
Added:
year: 1975
27
Added:
competition: 'IFBB Mr. America'
28
Added:
place: 3
29
Added:
category: 'Medium').
30
Added:
(MFTPrize
31
Added:
year: 1975
32
Added:
competition: 'ABBA Mr. USA'
33
Added:
place: 2
34
Added:
category: 'Medium').
35
Added:
(MFTPrize
36
Added:
year: 1976
37
Added:
competition: 'IFBB Mr. America'
38
Added:
place: 1
39
Added:
category: 'Overall').
40
Added:
(MFTPrize
41
Added:
year: 1976
42
Added:
competition: 'IFBB Mr. America'
43
Added:
place: 1
44
Added:
category: 'Medium').
45
Added:
(MFTPrize
46
Added:
year: 1976
47
Added:
competition: 'IFBB Mr. Universe'
48
Added:
place: 2
49
Added:
category: 'MW').
50
Added:
(MFTPrize
51
Added:
year: 1977
52
Added:
competition: 'IFBB North American Championships'
53
Added:
place: 1
54
Added:
category: 'Overall').
55
Added:
(MFTPrize
56
Added:
year: 1977
57
Added:
competition: 'IFBB North American Championships'
58
Added:
place: 1
59
Added:
category: 'MW').
60
Added:
(MFTPrize
61
Added:
year: 1977
62
Added:
competition: 'IFBB Mr. Universe'
63
Added:
place: 2
64
Added:
category: 'HW').
65
Added:
(MFTPrize
66
Added:
year: 1978
67
Added:
competition: 'IFBB USA vs the World'
68
Added:
place: 1
69
Added:
category: 'HW').
70
Added:
(MFTPrize
71
Added:
year: 1978
72
Added:
competition: 'IFBB World Amateur Championships'
73
Added:
place: 1
74
Added:
category: 'HW').
75
Added:
(MFTPrize year: 1978 competition: 'IFBB Mr. Universe' place: 1).
76
Added:
(MFTPrize year: 1979 competition: 'IFBB Canada Pro Cup' place: 2).
77
Added:
(MFTPrize
78
Added:
year: 1979
79
Added:
competition: 'IFBB Florida Pro Invitational'
80
Added:
place: 1).
81
Added:
(MFTPrize
82
Added:
year: 1979
83
Added:
competition: 'IFBB Night of Champions'
84
Added:
place: 3).
85
Added:
(MFTPrize
86
Added:
year: 1979
87
Added:
competition: 'IFBB Mr. Olympia'
88
Added:
place: 2
89
Added:
category: 'Overall').
90
Added:
(MFTPrize
91
Added:
year: 1979
92
Added:
competition: 'IFBB Mr. Olympia'
93
Added:
place: 1
94
Added:
category: 'Heavyweight Division').
95
Added:
(MFTPrize
96
Added:
year: 1979
97
Added:
competition: 'IFBB Pittsburgh Pro Invitational'
98
Added:
place: 2).
99
Added:
(MFTPrize year: 1979 competition: 'IFBB Southern Pro Cup' place: 1).
100
Added:
(MFTPrize year: 1980 competition: 'IFBB Mr. Olympia' place: 5) }
101
Added:
]
src/MyFitnessTracker/MFTMuscleGroup.class.st
@@ -1,6 +1,6 @@
1
1
Class {
2
2
#name : #MFTMuscleGroup,
3
Removed:
#superclass : #Object,
3
Added:
#superclass : #SBSComponent,
4
4
#instVars : [
5
5
'englishName',
6
6
'latinName',
@@ -182,26 +182,25 @@
182
182
{ #category : #rendering }
183
183
MFTMuscleGroup >> renderContentOn: html [
184
184
185
Removed:
html container: [
186
Removed:
html heading level2 with: englishName capitalized.
187
Removed:
description ifNotEmpty: [
188
Removed:
html
189
Removed:
text: description;
190
Removed:
break ].
191
Removed:
muscles ifNotEmpty: [
192
Removed:
html
193
Removed:
text: 'This group is comprised of:';
194
Removed:
definitionList: [
195
Removed:
muscles do: [ :muscle |
196
Removed:
html definitionTerm: [
197
Removed:
html text: muscle englishName capitalized.
198
Removed:
muscle latinName ifNotEmpty: [
199
Removed:
html space.
200
Removed:
html text: '('.
201
Removed:
html anchor
202
Removed:
url: muscle linkTerminologiaAnatomica;
203
Removed:
with: muscle latinName.
204
Removed:
html text: ')' ] ].
205
Removed:
html definitionData: muscle description.
206
Removed:
muscle renderContentOn: html ] ] ] ]
185
Added:
html heading level2 with: englishName capitalized.
186
Added:
description ifNotEmpty: [
187
Added:
html
188
Added:
text: description;
189
Added:
break ].
190
Added:
muscles ifNotEmpty: [
191
Added:
html
192
Added:
text: 'This group is comprised of:';
193
Added:
definitionList: [
194
Added:
muscles do: [ :muscle |
195
Added:
html definitionTerm: [
196
Added:
html text: muscle englishName capitalized.
197
Added:
muscle latinName ifNotEmpty: [
198
Added:
html space.
199
Added:
html text: '('.
200
Added:
html anchor
201
Added:
url: muscle linkTerminologiaAnatomica;
202
Added:
with: muscle latinName.
203
Added:
html text: ')' ] ].
204
Added:
html definitionData: muscle description.
205
Added:
muscle renderContentOn: html ] ] ]
207
206
]
src/MyFitnessTracker/MFTMusclesArticle.class.st
@@ -7,6 +7,12 @@
7
7
#category : #'MyFitnessTracker-Components'
8
8
}
9
9
10
Added:
{ #category : #hooks }
11
Added:
MFTMusclesArticle >> children [
12
Added:
13
Added:
^ muscleGroups
14
Added:
]
15
Added:
10
16
{ #category : #initialization }
11
17
MFTMusclesArticle >> initialize [
12
18
@@ -24,5 +30,5 @@
24
30
MFTMusclesArticle >> renderContentOn: html [
25
31
26
32
html heading: title.
27
Removed:
muscleGroups do: [ :muscleGroup | muscleGroup renderContentOn: html ]
33
Added:
muscleGroups do: [ :muscleGroup | html render: muscleGroup ]
28
34
]
src/MyFitnessTracker/MFTPage.class.st
@@ -7,11 +7,17 @@
7
7
#category : #'MyFitnessTracker-Components'
8
8
}
9
9
10
Added:
{ #category : #'as yet unclassified' }
11
Added:
MFTPage >> loadUserData [
12
Added:
13
Added:
^ nil
14
Added:
]
15
Added:
10
16
{ #category : #rendering }
11
17
MFTPage >> renderPageOn: html with: aBlock [
12
18
13
19
html container
14
Removed:
style: 'max-width: 60vw';
20
Added:
style: 'max-width: 60rem';
15
21
with: aBlock
16
22
]
17
23
src/MyFitnessTracker/MFTPageManager.class.st
@@ -4,6 +4,8 @@
4
4
#instVars : [
5
5
'mainNavigationBar',
6
6
'mainPages',
7
Added:
'header',
8
Added:
'footer',
7
9
'activePage'
8
10
],
9
11
#category : #MyFitnessTracker
@@ -16,61 +18,70 @@
16
18
]
17
19
18
20
{ #category : #accessing }
19
Removed:
MFTPageManager >> activePage: anIndex [
21
Added:
MFTPageManager >> activePage: aKey [
20
22
21
Removed:
activePage := mainPages at: anIndex
23
Added:
activePage := mainPages at: aKey
22
24
]
23
25
24
26
{ #category : #'as yet unclassified' }
25
Removed:
MFTPageManager >> defaultFooter [
27
Added:
MFTPageManager >> defaultPublicPages [
26
28
27
Removed:
^ MFTFooterComponent new
29
Added:
^ OrderedDictionary newFrom: {
30
Added:
(#landing -> MFTPublicLandingPage new).
31
Added:
(#workouts -> MFTWorkoutsListPage new).
32
Added:
(#weights -> MFTWeightsListPage new).
33
Added:
(#learn -> MFTLearnPage new).
34
Added:
(#about -> MFTAboutPage new).
35
Added:
(#profile -> MFTProfilePage new) }
28
36
]
29
37
30
Removed:
{ #category : #'as yet unclassified' }
31
Removed:
MFTPageManager >> defaultPublicPages [
38
Added:
{ #category : #accessing }
39
Added:
MFTPageManager >> footer [
32
40
33
Removed:
^ {
34
Removed:
MFTPublicLandingPage new.
35
Removed:
MFTWorkoutsListPage placeholder.
36
Removed:
MFTWeightsListPage placeholder.
37
Removed:
MFTLearnPage new.
38
Removed:
MFTAboutPage new.
39
Removed:
MFTProfilePage new }
41
Added:
^ footer
40
42
]
41
43
42
Removed:
{ #category : #initialization }
43
Removed:
MFTPageManager >> initialize [
44
Added:
{ #category : #accessing }
45
Added:
MFTPageManager >> footer: anObject [
44
46
45
Removed:
mainNavigationBar := MFTMainNavigationBarComponent new.
46
Removed:
mainPages := self defaultPublicPages.
47
Removed:
activePage := mainPages at: 1
47
Added:
footer := anObject
48
48
]
49
49
50
Removed:
{ #category : #'as yet unclassified' }
51
Removed:
MFTPageManager >> loadUserLandingPage [
50
Added:
{ #category : #accessing }
51
Added:
MFTPageManager >> header [
52
52
53
Removed:
mainPages at: 1 put: MFTUserLandingPage new
53
Added:
^ header
54
54
]
55
55
56
Removed:
{ #category : #'as yet unclassified' }
57
Removed:
MFTPageManager >> loadUserPages [
56
Added:
{ #category : #accessing }
57
Added:
MFTPageManager >> header: anObject [
58
58
59
Removed:
self loadUserLandingPage.
60
Removed:
self loadUserWorkouts.
61
Removed:
self loadUserWeights.
59
Added:
header := anObject
62
60
]
63
61
62
Added:
{ #category : #initialization }
63
Added:
MFTPageManager >> initialize [
64
Added:
65
Added:
mainPages := self defaultPublicPages.
66
Added:
activePage := mainPages at: #landing.
67
Added:
68
Added:
mainNavigationBar := MFTMainNavigationBarComponent new.
69
Added:
header := MFTRegisterProspectEmailHeader new.
70
Added:
footer := MFTDefaultFooter new
71
Added:
]
72
Added:
64
73
{ #category : #'as yet unclassified' }
65
Removed:
MFTPageManager >> loadUserWeights [
74
Added:
MFTPageManager >> loadPublicPages [
66
75
67
Removed:
(mainPages at: 3) loadUserWeights
76
Added:
mainPages at: 1 put: MFTPublicLandingPage new.
77
Added:
self activePage: 1
68
78
]
69
79
70
80
{ #category : #'as yet unclassified' }
71
Removed:
MFTPageManager >> loadUserWorkouts [
81
Added:
MFTPageManager >> loadUserPages [
72
82
73
Removed:
(mainPages at: 2) loadUserWorkouts
83
Added:
mainPages do: [ :page | page loadUserData ].
84
Added:
self activePage: 1
74
85
]
75
86
76
87
{ #category : #accessing }
@@ -95,10 +106,4 @@
95
106
MFTPageManager >> mainPages: aCollection [
96
107
97
108
mainPages := aCollection
98
Removed:
]
99
Removed:
100
Removed:
{ #category : #'as yet unclassified' }
101
Removed:
MFTPageManager >> registerProspectEmailHeader [
102
Removed:
103
Removed:
^ MFTRegisterProspectEmailHeader new
104
109
]
src/MyFitnessTracker/MFTPrize.class.st
@@ -0,0 +1,80 @@
1
Added:
Class {
2
Added:
#name : #MFTPrize,
3
Added:
#superclass : #Object,
4
Added:
#instVars : [
5
Added:
'year',
6
Added:
'competition',
7
Added:
'place',
8
Added:
'category'
9
Added:
],
10
Added:
#category : #'MyFitnessTracker-Model'
11
Added:
}
12
Added:
13
Added:
{ #category : #'as yet unclassified' }
14
Added:
MFTPrize class >> year: aDate competition: aCompetition place: anInteger [
15
Added:
16
Added:
^ self new
17
Added:
year: aDate;
18
Added:
competition: aCompetition;
19
Added:
place: anInteger;
20
Added:
yourself
21
Added:
]
22
Added:
23
Added:
{ #category : #'as yet unclassified' }
24
Added:
MFTPrize class >> year: aDate competition: aCompetition place: anInteger category: aCategory [
25
Added:
26
Added:
^ self new
27
Added:
year: aDate;
28
Added:
competition: aCompetition;
29
Added:
place: anInteger;
30
Added:
category: aCategory;
31
Added:
yourself
32
Added:
]
33
Added:
34
Added:
{ #category : #accessing }
35
Added:
MFTPrize >> category [
36
Added:
37
Added:
^ category
38
Added:
]
39
Added:
40
Added:
{ #category : #accessing }
41
Added:
MFTPrize >> category: anObject [
42
Added:
43
Added:
category := anObject
44
Added:
]
45
Added:
46
Added:
{ #category : #accessing }
47
Added:
MFTPrize >> competition [
48
Added:
49
Added:
^ competition
50
Added:
]
51
Added:
52
Added:
{ #category : #accessing }
53
Added:
MFTPrize >> competition: anObject [
54
Added:
55
Added:
competition := anObject
56
Added:
]
57
Added:
58
Added:
{ #category : #accessing }
59
Added:
MFTPrize >> place [
60
Added:
61
Added:
^ place
62
Added:
]
63
Added:
64
Added:
{ #category : #accessing }
65
Added:
MFTPrize >> place: anObject [
66
Added:
67
Added:
place := anObject
68
Added:
]
69
Added:
70
Added:
{ #category : #accessing }
71
Added:
MFTPrize >> year [
72
Added:
73
Added:
^ year
74
Added:
]
75
Added:
76
Added:
{ #category : #accessing }
77
Added:
MFTPrize >> year: anObject [
78
Added:
79
Added:
year := anObject
80
Added:
]
src/MyFitnessTracker/MFTProfilePage.class.st
@@ -14,5 +14,47 @@
14
14
{ #category : #rendering }
15
15
MFTProfilePage >> renderContentOn: html [
16
16
17
Removed:
self renderPageOn: html with: [ html text: 'Welcome!' ]
17
Added:
| user |
18
Added:
user := self session user.
19
Added:
20
Added:
self renderPageOn: html with: [
21
Added:
html heading level1 with: [
22
Added:
html
23
Added:
code: self session user username;
24
Added:
text: '''s profile' ].
25
Added:
user isLoggedIn ifFalse: [
26
Added:
html paragraph: [
27
Added:
html
28
Added:
text:
29
Added:
'You aren''t logged in. To create an account, only two things are required: a unique username, and a password.';
30
Added:
break.
31
Added:
html anchor
32
Added:
callback: [ self error: 'TODO' ];
33
Added:
with: 'Why not collect more user data?' ].
34
Added:
html table
35
Added:
class: 'table';
36
Added:
with: [
37
Added:
user dataDictionary keysAndValuesDo: [ :key :value |
38
Added:
html tableRow: [
39
Added:
html tableData: key.
40
Added:
html tableData: value ] ] ] ] ]
41
Added:
]
42
Added:
43
Added:
{ #category : #rendering }
44
Added:
MFTProfilePage >> renderProfileActionsButtonGroupOn: html at: i [
45
Added:
46
Added:
html form: [
47
Added:
html buttonGroup
48
Added:
beSmall;
49
Added:
with: [
50
Added:
html formButton
51
Added:
beSecondary;
52
Added:
formControl;
53
Added:
callback: [ self editWeightAt: i ];
54
Added:
with: 'Edit'.
55
Added:
html formButton
56
Added:
beDanger;
57
Added:
formControl;
58
Added:
callback: [ self removeWeightAt: i ];
59
Added:
with: 'Delete' ] ]
18
60
]
src/MyFitnessTracker/MFTPublicLandingPage.class.st
@@ -1,18 +1,9 @@
1
1
Class {
2
2
#name : #MFTPublicLandingPage,
3
Removed:
#superclass : #MFTPage,
4
Removed:
#instVars : [
5
Removed:
'cards'
6
Removed:
],
3
Added:
#superclass : #MFTLandingPage,
7
4
#category : #'MyFitnessTracker-Components'
8
5
}
9
6
10
Removed:
{ #category : #hooks }
11
Removed:
MFTPublicLandingPage >> children [
12
Removed:
13
Removed:
^ cards
14
Removed:
]
15
Removed:
16
7
{ #category : #'as yet unclassified' }
17
8
MFTPublicLandingPage >> defaultCards [
18
9
@@ -31,12 +22,8 @@
31
22
cards := self defaultCards.
32
23
]
33
24
34
Removed:
{ #category : #rendering }
35
Removed:
MFTPublicLandingPage >> renderContentOn: html [
25
Added:
{ #category : #'as yet unclassified' }
26
Added:
MFTPublicLandingPage >> loadUserData [
36
27
37
Removed:
self renderPageOn: html with: [
38
Removed:
html div
39
Removed:
style:
40
Removed:
'display: flex; flex-wrap: wrap; justify-content: space-around; gap: 1em';
41
Removed:
with: [ cards do: [ :card | html render: card ] ] ]
28
Added:
self session pageManager mainPages at: #landing put: MFTUserLandingPage new
42
29
]
src/MyFitnessTracker/MFTScreenComponent.class.st
@@ -2,7 +2,6 @@
2
2
#name : #MFTScreenComponent,
3
3
#superclass : #SBSComponent,
4
4
#instVars : [
5
Removed:
'footer',
6
5
'pm'
7
6
],
8
7
#category : #'MyFitnessTracker-Components'
@@ -12,27 +11,25 @@
12
11
MFTScreenComponent >> children [
13
12
14
13
^ {
15
Removed:
pm registerProspectEmailHeader.
14
Added:
pm header.
16
15
pm mainNavigationBar.
17
16
pm activePage.
18
Removed:
footer }
17
Added:
pm footer }
19
18
]
20
19
21
20
{ #category : #initialization }
22
21
MFTScreenComponent >> initialize [
23
22
24
23
super initialize.
25
Removed:
pm := self session pageManager.
26
Removed:
footer := pm defaultFooter
24
Added:
pm := self session pageManager
27
25
]
28
26
29
27
{ #category : #rendering }
30
28
MFTScreenComponent >> renderContentOn: html [
31
29
32
Removed:
self session user isLoggedIn ifFalse: [
33
Removed:
html render: pm registerProspectEmailHeader ].
30
Added:
self session user isLoggedIn ifFalse: [ html render: pm header ].
34
31
html
35
32
render: pm mainNavigationBar;
36
33
render: pm activePage;
37
Removed:
render: footer
34
Added:
render: pm footer
38
35
]
src/MyFitnessTracker/MFTSession.class.st
@@ -61,7 +61,8 @@
61
61
MFTSession >> unregistered [
62
62
63
63
db connection close.
64
Removed:
user := MFTUser new
64
Added:
user := MFTUser new.
65
Added:
pageManager loadPublicPages
65
66
]
66
67
67
68
{ #category : #accessing }
src/MyFitnessTracker/MFTUser.class.st
@@ -34,10 +34,10 @@
34
34
username: 'mrs_default';
35
35
realFirstName: 'Deborah';
36
36
realLastName: 'Default';
37
Removed:
dateOfBirth: Date today;
37
Added:
dateOfBirth: (Date fromString: '01/01/2000');
38
38
isLoggedIn: false;
39
Removed:
workouts: MFTWorkoutsListPage placeholder workouts;
40
Removed:
weights: MFTWeightsListPage placeholder weights
39
Added:
workouts: self placeholderWorkouts;
40
Added:
weights: self placeholderWeights
41
41
]
42
42
43
43
{ #category : #'instance creation' }
@@ -61,6 +61,72 @@
61
61
yourself
62
62
]
63
63
64
Added:
{ #category : #'as yet unclassified' }
65
Added:
MFTUser class >> placeholderWeights [
66
Added:
67
Added:
^ OrderedCollection withAll: {
68
Added:
(MFTWeight date: (Date fromString: '01/01/2024') value: 90).
69
Added:
(MFTWeight date: (Date fromString: '01/02/2024') value: 91).
70
Added:
(MFTWeight date: (Date fromString: '01/03/2024') value: 92).
71
Added:
(MFTWeight date: (Date fromString: '01/04/2024') value: 93) }
72
Added:
]
73
Added:
74
Added:
{ #category : #'as yet unclassified' }
75
Added:
MFTUser class >> placeholderWorkouts [
76
Added:
77
Added:
| placeholderWorkouts workout1 workout2 workout3 |
78
Added:
placeholderWorkouts := OrderedCollection new.
79
Added:
workout1 := MFTWorkout new
80
Added:
date: (Date fromString: '01/03/2023');
81
Added:
primaryMuscle: MFTMuscleGroup chest;
82
Added:
exercises: (OrderedCollection
83
Added:
with: (MFTExercise cableRow sets: {
84
Added:
(MFTSet reps: 8 rpe: 6).
85
Added:
(MFTSet reps: 6 rpe: 8).
86
Added:
(MFTSet reps: 6 rpe: 10).
87
Added:
(MFTSet reps: 15 rpe: 4) })
88
Added:
with: (MFTExercise shoulderPressDumbell sets: {
89
Added:
(MFTSet reps: 10 rpe: 6).
90
Added:
(MFTSet reps: 6 rpe: 8).
91
Added:
(MFTSet reps: 6 rpe: 10) })
92
Added:
with: (MFTExercise declineBenchPress sets: {
93
Added:
(MFTSet reps: 5 rpe: 6).
94
Added:
(MFTSet reps: 6 rpe: 8).
95
Added:
(MFTSet reps: 8 rpe: 10) })).
96
Added:
workout2 := MFTWorkout new
97
Added:
date: (Date fromString: '01/02/2023');
98
Added:
exercises: (OrderedCollection
99
Added:
with: (MFTExercise cableRow sets: {
100
Added:
(MFTSet reps: 8 rpe: 6).
101
Added:
(MFTSet reps: 6 rpe: 8).
102
Added:
(MFTSet reps: 6 rpe: 10).
103
Added:
(MFTSet reps: 15 rpe: 4) })
104
Added:
with: MFTExercise shoulderPressDumbell
105
Added:
with: MFTExercise declineBenchPress).
106
Added:
workout3 := MFTWorkout new
107
Added:
date: (Date fromString: '01/01/2023');
108
Added:
addExercise: MFTExercise cableRow;
109
Added:
addExercise: MFTExercise shoulderPressDumbell;
110
Added:
addExercise: MFTExercise declineBenchPress.
111
Added:
placeholderWorkouts
112
Added:
add: workout1;
113
Added:
add: workout2;
114
Added:
add: workout3.
115
Added:
116
Added:
^ placeholderWorkouts
117
Added:
]
118
Added:
119
Added:
{ #category : #'as yet unclassified' }
120
Added:
MFTUser >> dataDictionary [
121
Added:
122
Added:
^ OrderedDictionary newFrom: {
123
Added:
(#username -> username).
124
Added:
(#'date of birth' -> dateOfBirth).
125
Added:
(#'first name' -> realFirstName).
126
Added:
(#'last name' -> realLastName).
127
Added:
(#'last login date and time' -> lastLoginDateAndTime) }
128
Added:
]
129
Added:
64
130
{ #category : #accessing }
65
131
MFTUser >> dateOfBirth [
66
132
@@ -83,6 +149,7 @@
83
149
realLastName := String new.
84
150
dateOfBirth := Date new.
85
151
isLoggedIn := false.
152
Added:
lastLoginDateAndTime := DateAndTime now asUTC rounded asString.
86
153
workouts := OrderedCollection new.
87
154
weights := OrderedCollection new
88
155
]
@@ -172,9 +239,9 @@
172
239
]
173
240
174
241
{ #category : #accessing }
175
Removed:
MFTUser >> weights: anObject [
242
Added:
MFTUser >> weights: aCollection [
176
243
177
Removed:
weights := anObject
244
Added:
weights := aCollection
178
245
]
179
246
180
247
{ #category : #accessing }
src/MyFitnessTracker/MFTUserLandingPage.class.st
@@ -1,27 +1,22 @@
1
1
Class {
2
2
#name : #MFTUserLandingPage,
3
Removed:
#superclass : #MFTPage,
3
Added:
#superclass : #MFTLandingPage,
4
4
#category : #'MyFitnessTracker-Components'
5
5
}
6
6
7
Removed:
{ #category : #initialization }
8
Removed:
MFTUserLandingPage >> initialize [
7
Added:
{ #category : #'as yet unclassified' }
8
Added:
MFTUserLandingPage >> defaultCards [
9
9
10
Removed:
super initialize.
11
Removed:
title := self session user username
10
Added:
^ {
11
Added:
MFTMainUserCard new.
12
Added:
MFTWorkoutsCard new.
13
Added:
MFTCard new }
12
14
]
13
15
14
Removed:
{ #category : #rendering }
15
Removed:
MFTUserLandingPage >> renderContentOn: html [
16
Added:
{ #category : #initialization }
17
Added:
MFTUserLandingPage >> initialize [
16
18
17
Removed:
self renderPageOn: html with: [
18
Removed:
html render: MFTMainUserCard new.
19
Removed:
html render: MFTWorkoutsCard new.
20
Removed:
html render: MFTCard new ]
21
Removed:
]
22
Removed:
23
Removed:
{ #category : #rendering }
24
Removed:
MFTUserLandingPage >> renderWorkoutsSummaryCardOn: html [
25
Removed:
26
Removed:
html card: [ html text: self session user username. ]
19
Added:
super initialize.
20
Added:
title := self session user username.
21
Added:
cards := self defaultCards
27
22
]
src/MyFitnessTracker/MFTWeightVsTimeGraph.class.st
@@ -29,9 +29,6 @@
29
29
datasets: [{
30
30
label: "weight",
31
31
data: ' , data asJavascript , ',
32
Removed:
backgroundColor: "rgba(255, 99, 132, 0.2)",
33
Removed:
borderColor: "rgba(255, 99, 132, 1)",
34
Removed:
borderWidth: 1
35
32
}]
36
33
},
37
34
options: {
src/MyFitnessTracker/MFTWeightsListPage.class.st
@@ -1,9 +1,6 @@
1
1
Class {
2
2
#name : #MFTWeightsListPage,
3
3
#superclass : #MFTPage,
4
Removed:
#instVars : [
5
Removed:
'weights'
6
Removed:
],
7
4
#category : #'MyFitnessTracker-Components'
8
5
}
9
6
@@ -30,7 +27,7 @@
30
27
{ #category : #accessing }
31
28
MFTWeightsListPage >> editWeightAt: i [
32
29
33
Removed:
self call: (MFTWeightDialog edit: (weights at: i))
30
Added:
self call: (MFTWeightDialog edit: (self session user weights at: i))
34
31
]
35
32
36
33
{ #category : #initialization }
@@ -38,14 +35,14 @@
38
35
39
36
super initialize.
40
37
title := 'weights'.
41
Removed:
weights := OrderedCollection new
38
Added:
42
39
]
43
40
44
41
{ #category : #'as yet unclassified' }
45
Removed:
MFTWeightsListPage >> loadUserWeights [
42
Added:
MFTWeightsListPage >> loadUserData [
46
43
47
Removed:
weights := self session db selectWeightsWhereUser:
48
Removed:
self session user
44
Added:
self session user weights:
45
Added:
(self session db selectWeightsWhereUser: self session user)
49
46
]
50
47
51
48
{ #category : #'as yet unclassified' }
@@ -61,7 +58,7 @@
61
58
{ #category : #accessing }
62
59
MFTWeightsListPage >> removeWeightAt: i [
63
60
64
Removed:
weights removeAt: i
61
Added:
self session user weights removeAt: i
65
62
]
66
63
67
64
{ #category : #rendering }
@@ -82,6 +79,8 @@
82
79
{ #category : #rendering }
83
80
MFTWeightsListPage >> renderContentOn: html [
84
81
82
Added:
| weights |
83
Added:
weights := self session user weights.
85
84
weights sort: [ :a :b | a date > b date ].
86
85
87
86
self renderPageOn: html with: [
@@ -121,7 +120,7 @@
121
120
tableHeading;
122
121
tableHeading: 'Date';
123
122
tableHeading: 'Value' ].
124
Removed:
weights doWithIndex: [ :weight :i |
123
Added:
self session user weights doWithIndex: [ :weight :i |
125
124
html tableRow: [
126
125
html tableData: [
127
126
self renderWeightActionsButtonGroupOn: html at: i ].
@@ -133,16 +132,4 @@
133
132
MFTWeightsListPage >> viewAnalytics [
134
133
135
134
self call: (MFTAnalyticsPage for: #weights)
136
Removed:
]
137
Removed:
138
Removed:
{ #category : #accessing }
139
Removed:
MFTWeightsListPage >> weights [
140
Removed:
141
Removed:
^ weights
142
Removed:
]
143
Removed:
144
Removed:
{ #category : #accessing }
145
Removed:
MFTWeightsListPage >> weights: aMFTWeightCollection [
146
Removed:
147
Removed:
weights := aMFTWeightCollection
148
135
]
src/MyFitnessTracker/MFTWorkout.class.st
@@ -10,6 +10,13 @@
10
10
#category : #'MyFitnessTracker-Model'
11
11
}
12
12
13
Added:
{ #category : #'as yet unclassified' }
14
Added:
MFTWorkout class >> allAthletes [
15
Added:
16
Added:
^ { #'Arnold Alois Schwarzenneger'. #'Michael John Mentzer'.
17
Added:
#'Thomas Steven Platz' }
18
Added:
]
19
Added:
13
20
{ #category : #'instance creation' }
14
21
MFTWorkout class >> newFromDictionary: aDictionary [
15
22
@@ -132,7 +139,7 @@
132
139
| grandTotal |
133
140
grandTotal := 0.
134
141
html table
135
Removed:
class: 'table table-striped';
142
Added:
class: 'table table-striped table-bordered';
136
143
with: [
137
144
self renderTableHeaderOn: html.
138
145
exercises do: [ :exercise |
src/MyFitnessTracker/MFTWorkoutTask.class.st
@@ -0,0 +1,29 @@
1
Added:
Class {
2
Added:
#name : #MFTWorkoutTask,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'workout',
6
Added:
'exercises',
7
Added:
'date'
8
Added:
],
9
Added:
#category : #'MyFitnessTracker-Dialogs'
10
Added:
}
11
Added:
12
Added:
{ #category : #running }
13
Added:
MFTWorkoutTask >> go [
14
Added:
15
Added:
workout := MFTWorkout new.
16
Added:
self setDate.
17
Added:
self setPrimaryMuscle.
18
Added:
self addExercises.
19
Added:
self confirmAndSaveWorkout
20
Added:
]
21
Added:
22
Added:
{ #category : #initialization }
23
Added:
MFTWorkoutTask >> setDate [
24
Added:
25
Added:
| dateComponent |
26
Added:
dateComponent := Date new.
27
Added:
date := self call: dateComponent.
28
Added:
workout date: date
29
Added:
]
src/MyFitnessTracker/MFTWorkoutsListPage.class.st
@@ -24,9 +24,6 @@
24
24
Class {
25
25
#name : #MFTWorkoutsListPage,
26
26
#superclass : #MFTPage,
27
Removed:
#instVars : [
28
Removed:
'workouts'
29
Removed:
],
30
27
#category : #'MyFitnessTracker-Components'
31
28
}
32
29
@@ -83,31 +80,32 @@
83
80
84
81
| newWorkout |
85
82
newWorkout := self call: MFTWorkoutDialog new.
86
Removed:
newWorkout ifNotNil: [ workouts add: newWorkout ]
83
Added:
newWorkout ifNotNil: [ self session user workouts add: newWorkout ]
87
84
]
88
85
89
86
{ #category : #hooks }
90
87
MFTWorkoutsListPage >> children [
91
88
92
Removed:
^ workouts
89
Added:
^ self session user workouts
93
90
]
94
91
95
92
{ #category : #accessing }
96
93
MFTWorkoutsListPage >> confirmDeleteAt: i [
97
94
98
95
| workout confirmed |
99
Removed:
workout := workouts at: i.
96
Added:
workout := self session user workouts at: i.
100
97
confirmed := self call: (MFTConfirmDialog delete: workout).
101
Removed:
confirmed ifTrue: [ workouts removeAt: i ]
98
Added:
confirmed ifTrue: [ self session user workouts removeAt: i ]
102
99
]
103
100
104
101
{ #category : #'as yet unclassified' }
105
102
MFTWorkoutsListPage >> editWorkoutAt: i [
106
103
107
104
| oldWorkout newWorkout |
108
Removed:
oldWorkout := workouts at: i.
105
Added:
oldWorkout := self session user workouts at: i.
109
106
newWorkout := self call: (MFTWorkoutDialog edit: oldWorkout).
110
Removed:
newWorkout ifNotNil: [ workouts at: i put: newWorkout ]
107
Added:
newWorkout ifNotNil: [
108
Added:
self session user workouts at: i put: newWorkout ]
111
109
]
112
110
113
111
{ #category : #initialization }
@@ -115,14 +113,14 @@
115
113
116
114
super initialize.
117
115
title := 'workouts'.
118
Removed:
workouts := OrderedCollection new
116
Added:
119
117
]
120
118
121
119
{ #category : #'as yet unclassified' }
122
Removed:
MFTWorkoutsListPage >> loadUserWorkouts [
120
Added:
MFTWorkoutsListPage >> loadUserData [
123
121
124
Removed:
workouts := self session db selectWorkoutsWhereUser:
125
Removed:
self session user
122
Added:
self session user workouts:
123
Added:
(self session db selectWorkoutsWhereUser: self session user)
126
124
]
127
125
128
126
{ #category : #'as yet unclassified' }
@@ -153,6 +151,8 @@
153
151
{ #category : #rendering }
154
152
MFTWorkoutsListPage >> renderContentOn: html [
155
153
154
Added:
| workouts |
155
Added:
workouts := self session user workouts.
156
156
workouts sort: [ :a :b | a date > b date ].
157
157
158
158
self renderPageOn: html with: [
@@ -184,7 +184,7 @@
184
184
id: 'accordion';
185
185
class: 'mt-3';
186
186
with: [
187
Removed:
workouts doWithIndex: [ :workout :i |
187
Added:
self session user workouts doWithIndex: [ :workout :i |
188
188
html accordionItem: [
189
189
html accordionHeading: [
190
190
html accordionButton
@@ -218,16 +218,4 @@
218
218
MFTWorkoutsListPage >> viewAnalytics [
219
219
220
220
self call: (MFTAnalyticsPage for: #workouts)
221
Removed:
]
222
Removed:
223
Removed:
{ #category : #accessing }
224
Removed:
MFTWorkoutsListPage >> workouts [
225
Removed:
226
Removed:
^ workouts
227
Removed:
]
228
Removed:
229
Removed:
{ #category : #accessing }
230
Removed:
MFTWorkoutsListPage >> workouts: aMFTWorkoutCollection [
231
Removed:
232
Removed:
workouts := aMFTWorkoutCollection
233
221
]