1
1
package com.maksimowiczm.foodyou.feature.diary
2
2
3
+ import androidx.compose.animation.core.FastOutLinearInEasing
4
+ import androidx.compose.animation.core.LinearOutSlowInEasing
5
+ import androidx.compose.animation.core.tween
6
+ import androidx.compose.animation.scaleOut
7
+ import androidx.compose.animation.slideInVertically
8
+ import androidx.compose.animation.slideOutVertically
9
+ import androidx.compose.material3.MaterialTheme
10
+ import androidx.compose.material3.Surface
11
+ import androidx.compose.ui.unit.dp
3
12
import androidx.navigation.NavController
4
13
import androidx.navigation.NavGraphBuilder
14
+ import androidx.navigation.compose.composable
5
15
import androidx.navigation.navOptions
6
16
import androidx.navigation.toRoute
7
17
import com.maksimowiczm.foodyou.feature.Feature
@@ -18,9 +28,11 @@ import com.maksimowiczm.foodyou.feature.diary.data.ProductRepositoryImpl
18
28
import com.maksimowiczm.foodyou.feature.diary.database.DiaryDatabase
19
29
import com.maksimowiczm.foodyou.feature.diary.network.OpenFoodFactsRemoteMediatorFactory
20
30
import com.maksimowiczm.foodyou.feature.diary.network.ProductRemoteMediatorFactory
21
- import com.maksimowiczm.foodyou.feature.diary.ui.DiaryViewModel
22
31
import com.maksimowiczm.foodyou.feature.diary.ui.MealApp
23
32
import com.maksimowiczm.foodyou.feature.diary.ui.caloriescard.CaloriesCard
33
+ import com.maksimowiczm.foodyou.feature.diary.ui.caloriescard.CaloriesCardViewModel
34
+ import com.maksimowiczm.foodyou.feature.diary.ui.caloriesscreen.CaloriesScreen
35
+ import com.maksimowiczm.foodyou.feature.diary.ui.caloriesscreen.CaloriesScreenViewModel
24
36
import com.maksimowiczm.foodyou.feature.diary.ui.goalssettings.GoalsSettingsListItem
25
37
import com.maksimowiczm.foodyou.feature.diary.ui.goalssettings.GoalsSettingsScreen
26
38
import com.maksimowiczm.foodyou.feature.diary.ui.goalssettings.GoalsSettingsViewModel
@@ -38,16 +50,21 @@ import com.maksimowiczm.foodyou.feature.diary.ui.openfoodfactssettings.OpenFoodF
38
50
import com.maksimowiczm.foodyou.feature.diary.ui.openfoodfactssettings.buildOpenFoodFactsSettingsListItem
39
51
import com.maksimowiczm.foodyou.feature.diary.ui.openfoodfactssettings.flagCdnCountryFlag
40
52
import com.maksimowiczm.foodyou.feature.diary.ui.product.create.CreateProductViewModel
53
+ import com.maksimowiczm.foodyou.feature.diary.ui.product.update.UpdateProductDialog
41
54
import com.maksimowiczm.foodyou.feature.diary.ui.product.update.UpdateProductViewModel
42
55
import com.maksimowiczm.foodyou.feature.diary.ui.search.OpenFoodFactsSearchHintViewModel
43
56
import com.maksimowiczm.foodyou.feature.diary.ui.search.SearchViewModel
44
57
import com.maksimowiczm.foodyou.navigation.crossfadeComposable
45
58
import com.maksimowiczm.foodyou.navigation.forwardBackwardComposable
59
+ import com.maksimowiczm.foodyou.ui.motion.crossfadeIn
60
+ import kotlinx.datetime.LocalDate
46
61
import kotlinx.serialization.Serializable
62
+ import org.koin.compose.viewmodel.koinViewModel
47
63
import org.koin.core.module.Module
48
64
import org.koin.core.module.dsl.factoryOf
49
65
import org.koin.core.module.dsl.singleOf
50
66
import org.koin.core.module.dsl.viewModelOf
67
+ import org.koin.core.parameter.parametersOf
51
68
import org.koin.dsl.bind
52
69
import org.koin.dsl.module
53
70
@@ -77,10 +94,21 @@ object DiaryFeature : Feature {
77
94
)
78
95
}
79
96
),
80
- HomeFeature { _ , modifier, homeState ->
97
+ HomeFeature { animatedVisibilityScope , modifier, homeState ->
81
98
CaloriesCard (
99
+ animatedVisibilityScope = animatedVisibilityScope,
82
100
homeState = homeState,
83
- modifier = modifier
101
+ modifier = modifier,
102
+ onClick = {
103
+ navController.navigate(
104
+ route = CaloriesDetails (
105
+ epochDay = homeState.selectedDate.toEpochDays()
106
+ ),
107
+ navOptions = navOptions {
108
+ launchSingleTop = true
109
+ }
110
+ )
111
+ }
84
112
)
85
113
}
86
114
)
@@ -139,6 +167,12 @@ object DiaryFeature : Feature {
139
167
@Serializable
140
168
private data class MealAdd (val epochDay : Int , val mealId : Long )
141
169
170
+ @Serializable
171
+ private data class CaloriesDetails (val epochDay : Int )
172
+
173
+ @Serializable
174
+ private data class EditProductDialog (val productId : Long )
175
+
142
176
override fun NavGraphBuilder.graph (navController : NavController ) {
143
177
forwardBackwardComposable<GoalsSettings > {
144
178
GoalsSettingsScreen (
@@ -208,6 +242,65 @@ object DiaryFeature : Feature {
208
242
}
209
243
)
210
244
}
245
+
246
+ crossfadeComposable<CaloriesDetails > {
247
+ val (epochDay) = it.toRoute<CaloriesDetails >()
248
+ val date = LocalDate .fromEpochDays(epochDay)
249
+
250
+ CaloriesScreen (
251
+ date = date,
252
+ animatedVisibilityScope = this @crossfadeComposable,
253
+ onProductClick = {
254
+ navController.navigate(
255
+ route = EditProductDialog (
256
+ productId = it.id
257
+ ),
258
+ navOptions = navOptions {
259
+ launchSingleTop = true
260
+ }
261
+ )
262
+ }
263
+ )
264
+ }
265
+
266
+ composable<EditProductDialog >(
267
+ enterTransition = {
268
+ crossfadeIn() + slideInVertically(
269
+ animationSpec = tween(
270
+ easing = LinearOutSlowInEasing
271
+ ),
272
+ initialOffsetY = { it }
273
+ )
274
+ },
275
+ exitTransition = {
276
+ slideOutVertically(
277
+ animationSpec = tween(
278
+ easing = FastOutLinearInEasing
279
+ ),
280
+ targetOffsetY = { it }
281
+ ) + scaleOut(
282
+ targetScale = 0.8f ,
283
+ animationSpec = tween(
284
+ easing = FastOutLinearInEasing
285
+ )
286
+ )
287
+ }
288
+ ) {
289
+ val (productId) = it.toRoute<EditProductDialog >()
290
+
291
+ Surface (
292
+ shadowElevation = 6 .dp,
293
+ shape = MaterialTheme .shapes.medium
294
+ ) {
295
+ UpdateProductDialog (
296
+ onClose = { navController.popBackStack<EditProductDialog >(inclusive = true ) },
297
+ onSuccess = { navController.popBackStack<EditProductDialog >(inclusive = true ) },
298
+ viewModel = koinViewModel(
299
+ parameters = { parametersOf(productId) }
300
+ )
301
+ )
302
+ }
303
+ }
211
304
}
212
305
213
306
override val module: Module = module {
@@ -228,8 +321,6 @@ object DiaryFeature : Feature {
228
321
229
322
factoryOf(::DiaryRepositoryImpl ).bind<DiaryRepository >()
230
323
231
- viewModelOf(::DiaryViewModel )
232
-
233
324
viewModelOf(::GoalsSettingsViewModel )
234
325
235
326
viewModelOf(::MealsSettingsScreenViewModel )
@@ -245,5 +336,8 @@ object DiaryFeature : Feature {
245
336
factory { get<DiaryDatabase >().addFoodDao() }
246
337
factory { get<DiaryDatabase >().productDao() }
247
338
factory { get<DiaryDatabase >().openFoodFactsDao() }
339
+
340
+ viewModelOf(::CaloriesCardViewModel )
341
+ viewModelOf(::CaloriesScreenViewModel )
248
342
}
249
343
}
0 commit comments