Commit d7e060c1 by Aleksandr

Template for Job details screen

parent fa0d47f7
...@@ -6,7 +6,7 @@ annotation class Argument { ...@@ -6,7 +6,7 @@ annotation class Argument {
const val URI = "URI" const val URI = "URI"
const val LATITUDE = "LATITUDE" const val LATITUDE = "LATITUDE"
const val LONGITUDE = "LONGITUDE" const val LONGITUDE = "LONGITUDE"
const val SPOT_ID = "SPOT_ID"
const val SPOT_CODE = "SPOT_CODE" const val SPOT_CODE = "SPOT_CODE"
const val ID = "ID"
} }
} }
...@@ -11,16 +11,14 @@ import androidx.navigation.NavType ...@@ -11,16 +11,14 @@ import androidx.navigation.NavType
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.isidroid.c23.ui.navigation.Content import com.isidroid.c23.ui.navigation.Content
import com.isidroid.c23.ui.navigation.Home
import com.isidroid.c23.ui.navigation.Map import com.isidroid.c23.ui.navigation.Map
import com.isidroid.c23.ui.navigation.PrintJobs import com.isidroid.c23.ui.navigation.PrintJobs
import com.isidroid.c23.ui.navigation.RenderPreview import com.isidroid.c23.ui.navigation.RenderPreview
val String?.isEdgeToEdge val String?.isEdgeToEdge
get() = arrayOf( get() = !arrayOf(
RenderPreview.route, Home.route,
Content.route,
Map.route,
PrintJobs.route
).any { ).any {
this?.contains(it) == true this?.contains(it) == true
} }
...@@ -54,7 +52,7 @@ fun BasicNavHost( ...@@ -54,7 +52,7 @@ fun BasicNavHost(
) )
} }
internal fun makeNavArgument(name: String, type: NavType<*>, nullable: Boolean = true, defaultValue: Any? = null) = navArgument(name){ internal fun makeNavArgument(name: String, type: NavType<*>, nullable: Boolean = true, defaultValue: Any? = null) = navArgument(name) {
this.type = type this.type = type
this.nullable = nullable this.nullable = nullable
this.defaultValue = defaultValue this.defaultValue = defaultValue
......
...@@ -2,6 +2,7 @@ package com.isidroid.c23.ui._component ...@@ -2,6 +2,7 @@ package com.isidroid.c23.ui._component
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.KeyboardArrowLeft import androidx.compose.material.icons.automirrored.rounded.KeyboardArrowLeft
......
...@@ -22,4 +22,8 @@ object Map: NavDirection { ...@@ -22,4 +22,8 @@ object Map: NavDirection {
object PrintJobs: NavDirection { object PrintJobs: NavDirection {
override val route: String = "PrintJobs" override val route: String = "PrintJobs"
} }
\ No newline at end of file
object JobDetails: NavDirection {
override val route: String = "JobDetails"
}
...@@ -11,6 +11,7 @@ import com.isidroid.c23.ext.isDebug ...@@ -11,6 +11,7 @@ import com.isidroid.c23.ext.isDebug
import com.isidroid.c23.ext.makeNavArgument import com.isidroid.c23.ext.makeNavArgument
import com.isidroid.c23.ui.navigation.destinations.ContentScreenDestination import com.isidroid.c23.ui.navigation.destinations.ContentScreenDestination
import com.isidroid.c23.ui.navigation.destinations.HomeScreenDestination import com.isidroid.c23.ui.navigation.destinations.HomeScreenDestination
import com.isidroid.c23.ui.navigation.destinations.JobDetailsDestination
import com.isidroid.c23.ui.navigation.destinations.MapScreenDestination import com.isidroid.c23.ui.navigation.destinations.MapScreenDestination
import com.isidroid.c23.ui.navigation.destinations.PrintJobsScreenDestination import com.isidroid.c23.ui.navigation.destinations.PrintJobsScreenDestination
import com.isidroid.c23.ui.navigation.destinations.RenderScreenDestination import com.isidroid.c23.ui.navigation.destinations.RenderScreenDestination
...@@ -46,6 +47,14 @@ fun AppNavHost( ...@@ -46,6 +47,14 @@ fun AppNavHost(
), ),
content = { MapScreenDestination(navController) } content = { MapScreenDestination(navController) }
) )
composable(
route = routeJobDetails(id = "{${Argument.ID}}"),
arguments = listOf(
makeNavArgument(Argument.ID, NavType.StringType, nullable = true)
),
content = { JobDetailsDestination(navController) }
)
} }
} }
...@@ -15,3 +15,7 @@ internal fun routeMap(lat: String? = null, lng: String? = null, spotCode: String ...@@ -15,3 +15,7 @@ internal fun routeMap(lat: String? = null, lng: String? = null, spotCode: String
.appendQueryParameter(Argument.LONGITUDE, lng) .appendQueryParameter(Argument.LONGITUDE, lng)
.appendQueryParameter(Argument.SPOT_CODE, spotCode) .appendQueryParameter(Argument.SPOT_CODE, spotCode)
.toString() .toString()
internal fun routeJobDetails(id: String = Argument.ID) = JobDetails.route.toUri().buildUpon()
.appendQueryParameter(Argument.ID, id)
.toString()
\ No newline at end of file
package com.isidroid.c23.ui.navigation.destinations
import androidx.compose.runtime.Composable
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.isidroid.c23.ui.screen.details.JobDetailsContract
import com.isidroid.c23.ui.screen.details.JobDetailsScreen
import com.isidroid.c23.ui.screen.details.JobDetailsViewModel
import com.isidroid.c23.ui.screen.print_jobs.PrintJobsContract
import com.isidroid.c23.ui.screen.print_jobs.PrintJobsScreen
import com.isidroid.c23.ui.screen.print_jobs.PrintJobsViewModel
@Composable
fun JobDetailsDestination(navController: NavHostController) {
val viewModel: JobDetailsViewModel = hiltViewModel()
JobDetailsScreen(
state = viewModel.viewState,
effectFlow = viewModel.effect,
onEventSent = { event -> viewModel.setEvent(event) },
onNavigationRequested = { effect ->
when (effect) {
JobDetailsContract.Effect.Navigation.ToBack -> navController.popBackStack()
}
},
)
}
\ No newline at end of file
...@@ -3,6 +3,7 @@ package com.isidroid.c23.ui.navigation.destinations ...@@ -3,6 +3,7 @@ package com.isidroid.c23.ui.navigation.destinations
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.isidroid.c23.ui.navigation.routeJobDetails
import com.isidroid.c23.ui.screen.print_jobs.PrintJobsContract import com.isidroid.c23.ui.screen.print_jobs.PrintJobsContract
import com.isidroid.c23.ui.screen.print_jobs.PrintJobsScreen import com.isidroid.c23.ui.screen.print_jobs.PrintJobsScreen
import com.isidroid.c23.ui.screen.print_jobs.PrintJobsViewModel import com.isidroid.c23.ui.screen.print_jobs.PrintJobsViewModel
...@@ -18,6 +19,7 @@ fun PrintJobsScreenDestination(navController: NavHostController) { ...@@ -18,6 +19,7 @@ fun PrintJobsScreenDestination(navController: NavHostController) {
onNavigationRequested = { effect -> onNavigationRequested = { effect ->
when (effect) { when (effect) {
PrintJobsContract.Effect.Navigation.ToBack -> navController.popBackStack() PrintJobsContract.Effect.Navigation.ToBack -> navController.popBackStack()
is PrintJobsContract.Effect.Navigation.ToDetails -> navController.navigate(routeJobDetails(id = effect.id))
} }
}, },
) )
......
package com.isidroid.c23.ui.screen.details
import com.isidroid.c23.ui.screen.content.ContentContract
import com.isidroid.core.vm.ViewEvent
import com.isidroid.core.vm.ViewSideEffect
import com.isidroid.core.vm.ViewState
class JobDetailsContract {
sealed interface Event : ViewEvent {
data object ToBack : Event
}
sealed interface Effect : ViewSideEffect {
sealed interface Navigation : Effect {
data object ToBack : Navigation
}
}
data class State(val i: Int = 0) : ViewState
}
\ No newline at end of file
package com.isidroid.c23.ui.screen.details
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import com.isidroid.c23.R
import com.isidroid.c23.ui._component.TopAppBarComponent
import com.isidroid.core.vm.SIDE_EFFECTS_KEY
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun JobDetailsScreen(
state: State<JobDetailsContract.State>,
effectFlow: Flow<JobDetailsContract.Effect>?,
onEventSent: (event: JobDetailsContract.Event) -> Unit,
onNavigationRequested: (navigationEffect: JobDetailsContract.Effect.Navigation) -> Unit,
modifier: Modifier = Modifier,
) {
LaunchedEffect(SIDE_EFFECTS_KEY) {
effectFlow?.collect { effect ->
when (effect) {
is JobDetailsContract.Effect.Navigation -> onNavigationRequested(effect)
}
}
}
BackHandler { onEventSent(JobDetailsContract.Event.ToBack) }
Scaffold(
modifier = modifier.fillMaxSize(),
topBar = {
TopAppBarComponent(
text = "Print job details",
colors = TopAppBarDefaults.topAppBarColors(),
onNavigationClick = { onEventSent(JobDetailsContract.Event.ToBack) }
)
}
) { paddingValues ->
Box(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Screen is under construction")
}
}
}
package com.isidroid.c23.ui.screen.details
import com.isidroid.c23.ext.isDebug
import com.isidroid.core.vm.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class JobDetailsViewModel @Inject constructor() : BaseViewModel<JobDetailsContract.Event, JobDetailsContract.State, JobDetailsContract.Effect>() {
override val isDebug: Boolean = isDebug()
override fun setInitialState(): JobDetailsContract.State = JobDetailsContract.State()
override suspend fun handleEvents(event: JobDetailsContract.Event) {
when(event){
JobDetailsContract.Event.ToBack -> setEffect { JobDetailsContract.Effect.Navigation.ToBack }
}
}
}
\ No newline at end of file
package com.isidroid.c23.ui.screen.print_jobs package com.isidroid.c23.ui.screen.print_jobs
import com.isidroid.c23.domain.dto.PrintJobListItem import com.isidroid.c23.domain.dto.PrintJobListItem
import com.isidroid.c23.ui.screen.content.ContentContract
import com.isidroid.core.vm.ViewEvent import com.isidroid.core.vm.ViewEvent
import com.isidroid.core.vm.ViewSideEffect import com.isidroid.core.vm.ViewSideEffect
import com.isidroid.core.vm.ViewState import com.isidroid.core.vm.ViewState
import com.isidroid.job.model.PrintJob
class PrintJobsContract { class PrintJobsContract {
sealed interface Event : ViewEvent { sealed interface Event : ViewEvent {
data object ToBack : Event data object ToBack : Event
data class ToDetails(val id: String) : Event
} }
sealed interface Effect : ViewSideEffect { sealed interface Effect : ViewSideEffect {
sealed interface Navigation : Effect { sealed interface Navigation : Effect {
data object ToBack : Navigation data object ToBack : Navigation
data class ToDetails(val id: String) : Navigation
} }
} }
......
package com.isidroid.c23.ui.screen.print_jobs package com.isidroid.c23.ui.screen.print_jobs
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
...@@ -36,11 +37,13 @@ fun PrintJobsScreen( ...@@ -36,11 +37,13 @@ fun PrintJobsScreen(
} }
} }
BackHandler { onEventSent(PrintJobsContract.Event.ToBack) }
Scaffold( Scaffold(
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
topBar = { topBar = {
TopAppBarComponent( TopAppBarComponent(
text = stringResource(id = R.string.print_job_list), text = stringResource(id = R.string.print_job_list),
colors = TopAppBarDefaults.topAppBarColors(), colors = TopAppBarDefaults.topAppBarColors(),
onNavigationClick = { onEventSent(PrintJobsContract.Event.ToBack) } onNavigationClick = { onEventSent(PrintJobsContract.Event.ToBack) }
) )
...@@ -49,14 +52,19 @@ fun PrintJobsScreen( ...@@ -49,14 +52,19 @@ fun PrintJobsScreen(
ListComponent( ListComponent(
state = state, state = state,
modifier = Modifier.padding(paddingValues) onEventSent = onEventSent,
modifier = Modifier.padding(paddingValues),
) )
} }
} }
@Composable @Composable
private fun ListComponent(state: State<PrintJobsContract.State>, modifier: Modifier) { private fun ListComponent(
state: State<PrintJobsContract.State>,
onEventSent: (event: PrintJobsContract.Event) -> Unit,
modifier: Modifier
) {
val list = state.value.jobs ?: return val list = state.value.jobs ?: return
LazyColumn(modifier) { LazyColumn(modifier) {
...@@ -69,7 +77,8 @@ private fun ListComponent(state: State<PrintJobsContract.State>, modifier: Modif ...@@ -69,7 +77,8 @@ private fun ListComponent(state: State<PrintJobsContract.State>, modifier: Modif
accessCode = item.accessCode, accessCode = item.accessCode,
statusColor = item.statusColor, statusColor = item.statusColor,
createdAt = item.createdAt, createdAt = item.createdAt,
modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp) modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp),
clickOnCard = { onEventSent(PrintJobsContract.Event.ToDetails(item.id)) }
) )
} }
} }
......
...@@ -8,10 +8,8 @@ import com.isidroid.core.vm.BaseViewModel ...@@ -8,10 +8,8 @@ import com.isidroid.core.vm.BaseViewModel
import com.isidroid.utils.catchTimber import com.isidroid.utils.catchTimber
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
...@@ -27,6 +25,7 @@ class PrintJobsViewModel @Inject constructor( ...@@ -27,6 +25,7 @@ class PrintJobsViewModel @Inject constructor(
override suspend fun handleEvents(event: PrintJobsContract.Event) { override suspend fun handleEvents(event: PrintJobsContract.Event) {
when (event) { when (event) {
PrintJobsContract.Event.ToBack -> setEffect { PrintJobsContract.Effect.Navigation.ToBack } PrintJobsContract.Event.ToBack -> setEffect { PrintJobsContract.Effect.Navigation.ToBack }
is PrintJobsContract.Event.ToDetails -> setEffect { PrintJobsContract.Effect.Navigation.ToDetails(event.id) }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment