@@ -10,86 +10,125 @@ import Domain
10
10
import MockData
11
11
import Kingfisher
12
12
import Flow
13
+ import Common
13
14
14
15
public struct RapidExerciseDetailView : View {
15
16
16
- let data : RapidExercisePresentation
17
- @State private var showsSecondaryMuscles : Bool = false
17
+ @StateObject var viewModel : RapidExerciseDetailViewModel
18
18
19
- public init ( exercise: Domain . RapidExerciseDomain ) {
20
- data = . init( domain: exercise)
19
+ public init (
20
+ exercise: Domain . RapidExerciseDomain ,
21
+ exerciseRepository: ExerciseRepository
22
+ ) {
23
+ _viewModel = . init( wrappedValue: . init(
24
+ exercise: exercise,
25
+ exerciseRepository: exerciseRepository
26
+ ) )
21
27
}
22
28
23
29
public var body : some View {
24
30
ScrollView {
25
-
26
- KFAnimatedImage ( . init( string: data. gifUrl) )
27
-
31
+ KFAnimatedImage ( . init( string: viewModel. data. gifUrl) )
28
32
VStack ( alignment: . leading) {
29
- Text ( data. equipment. capitalized)
33
+ Text ( viewModel . data. equipment. capitalized)
30
34
. fontWeight ( . black)
31
-
32
35
Divider ( )
33
-
34
- HStack {
35
- Text ( " Body Part: " )
36
- . foregroundStyle ( Color ( uiColor: . secondaryLabel) )
37
- . italic ( )
38
- Text ( " \( data. bodyPart. rawValue. capitalized) ( \( data. target. capitalized) ) " )
39
- }
40
-
36
+ bodyPartsView
41
37
Spacer ( minLength: 8 )
42
-
43
- Section {
44
- if showsSecondaryMuscles {
45
- HFlow {
46
- ForEach ( data. secondaryMuscles, id: \. self) { secondaryMuscle in
47
- Text ( secondaryMuscle)
48
- . padding ( . vertical, 4 )
49
- . padding ( . horizontal, 8 )
50
- . background (
51
- RoundedRectangle ( cornerRadius: 8 )
52
- . fill ( Color ( uiColor: . secondarySystemGroupedBackground) )
53
- )
54
- }
55
- }
56
- }
57
- } header: {
58
- Button {
59
- showsSecondaryMuscles. toggle ( )
60
- } label: {
61
- HStack {
62
- Text ( " secondary muscles " . capitalized)
63
- }
64
- }
65
- }
66
-
38
+ secondayMusclesView
67
39
Spacer ( minLength: 12 )
68
-
69
-
70
40
Text ( " Instructions " )
71
41
. font ( . title)
72
42
. padding ( . bottom, 8 )
73
-
74
-
75
- ForEach ( Array ( zip ( data. instructions. indices, data. instructions) ) , id: \. 0 ) { ( index, instruction) in
76
- HStack ( alignment: . top) {
77
- Text ( " \( index + 1 ) . " )
78
- Text ( instruction)
79
- . fixedSize ( horizontal: false , vertical: true )
80
- }
81
- . padding ( . bottom, 8 )
82
- }
83
-
84
-
43
+ instructionsView
85
44
}
86
45
. padding ( . horizontal)
87
46
88
47
Spacer ( minLength: 60 )
89
48
}
90
- . animation ( . default, value: showsSecondaryMuscles)
91
- . navigationTitle ( data. name. capitalized)
49
+ . animation ( . default, value: viewModel . showsSecondaryMuscles)
50
+ . navigationTitle ( viewModel . data. name. capitalized)
92
51
. scrollIndicators ( . hidden)
52
+ . overlay {
53
+ ZStack {
54
+ if viewModel. loading {
55
+ ProgressView ( )
56
+ }
57
+
58
+ if viewModel. showsAddButton {
59
+ VStack {
60
+ Spacer ( )
61
+
62
+ HStack {
63
+ Spacer ( )
64
+ Button {
65
+ viewModel. add ( )
66
+ } label: {
67
+ Image ( systemName: " pencil.tip.crop.circle.badge.plus " )
68
+ . padding ( )
69
+ . background {
70
+ Circle ( )
71
+ . fill ( . thickMaterial)
72
+ . shadow ( radius: 10 )
73
+ }
74
+ }
75
+ . buttonStyle ( . plain)
76
+ . padding ( )
77
+ }
78
+ }
79
+ }
80
+
81
+ if viewModel. snackbarMessage != nil {
82
+ Common . SnackbarView ( message: $viewModel. snackbarMessage)
83
+ }
84
+ }
85
+ }
86
+ }
87
+
88
+ var bodyPartsView : some View {
89
+ HStack {
90
+ Text ( " Body Part: " )
91
+ . foregroundStyle ( Color ( uiColor: . secondaryLabel) )
92
+ . italic ( )
93
+ Text ( " \( viewModel. data. bodyPart. rawValue. capitalized) ( \( viewModel. data. target. capitalized) ) " )
94
+ }
95
+ }
96
+
97
+ var secondayMusclesView : some View {
98
+ Section {
99
+ if viewModel. showsSecondaryMuscles {
100
+ HFlow {
101
+ ForEach ( viewModel. data. secondaryMuscles, id: \. self) { secondaryMuscle in
102
+ Text ( secondaryMuscle)
103
+ . padding ( . vertical, 4 )
104
+ . padding ( . horizontal, 8 )
105
+ . background (
106
+ RoundedRectangle ( cornerRadius: 8 )
107
+ . fill ( Color ( uiColor: . secondarySystemGroupedBackground) )
108
+ )
109
+ }
110
+ }
111
+ }
112
+ } header: {
113
+ Button {
114
+ viewModel. showsSecondaryMuscles. toggle ( )
115
+ } label: {
116
+ HStack {
117
+ Text ( " secondary muscles " . capitalized)
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ var instructionsView : some View {
124
+ ForEach ( Array ( zip ( viewModel. data. instructions. indices, viewModel. data. instructions) ) , id: \. 0 ) { ( index, instruction) in
125
+ HStack ( alignment: . top) {
126
+ Text ( " \( index + 1 ) . " )
127
+ Text ( instruction)
128
+ . fixedSize ( horizontal: false , vertical: true )
129
+ }
130
+ . padding ( . bottom, 8 )
131
+ }
93
132
}
94
133
}
95
134
@@ -98,7 +137,10 @@ public struct RapidExerciseDetailView: View {
98
137
let repository = RapidRepositoryMock ( )
99
138
100
139
return NavigationStack {
101
- RapidExerciseDetailView ( exercise: repository. get ( ) [ 0 ] )
140
+ RapidExerciseDetailView (
141
+ exercise: repository. get ( ) [ 0 ] ,
142
+ exerciseRepository: ExerciseRepositoryMock ( )
143
+ )
102
144
. preferredColorScheme ( . dark)
103
145
}
104
146
}
0 commit comments