diff --git a/support-module/src/main/java/com/saudigitus/support_module/data/local/SyncErrorsRepository.kt b/support-module/src/main/java/com/saudigitus/support_module/data/local/SyncErrorsRepository.kt new file mode 100644 index 0000000000..1d8d271be5 --- /dev/null +++ b/support-module/src/main/java/com/saudigitus/support_module/data/local/SyncErrorsRepository.kt @@ -0,0 +1,8 @@ +package com.saudigitus.support_module.data.local + +import com.saudigitus.support_module.data.models.erros.ErrorModel +import kotlinx.coroutines.flow.Flow + +interface SyncErrorsRepository { + fun getSyncErrors(): Flow> +} \ No newline at end of file diff --git a/support-module/src/main/java/com/saudigitus/support_module/data/local/repository/SyncErrorsRepositoryImpl.kt b/support-module/src/main/java/com/saudigitus/support_module/data/local/repository/SyncErrorsRepositoryImpl.kt new file mode 100644 index 0000000000..acc5808bd8 --- /dev/null +++ b/support-module/src/main/java/com/saudigitus/support_module/data/local/repository/SyncErrorsRepositoryImpl.kt @@ -0,0 +1,32 @@ +package com.saudigitus.support_module.data.local.repository + +import com.saudigitus.support_module.data.local.SyncErrorsRepository +import com.saudigitus.support_module.data.models.erros.ErrorModel +import com.saudigitus.support_module.utils.ErrorModelMapper +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf +import org.hisp.dhis.android.core.D2 + +class SyncErrorsRepositoryImpl( + private val d2: D2, + private val errorMapper: ErrorModelMapper, +): SyncErrorsRepository { + override fun getSyncErrors(): Flow> { + + val errors: MutableList = ArrayList() + errors.addAll( + errorMapper.mapD2Error(d2.maintenanceModule().d2Errors().blockingGet()), + ) + errors.addAll( + errorMapper.mapConflict( + d2.importModule().trackerImportConflicts().blockingGet(), + ), + ) + errors.addAll( + errorMapper.mapFKViolation( + d2.maintenanceModule().foreignKeyViolations().blockingGet(), + ), + ) + return flowOf(errors.toList()) + } +} \ No newline at end of file diff --git a/support-module/src/main/java/com/saudigitus/support_module/data/models/erros/ErrorModel.kt b/support-module/src/main/java/com/saudigitus/support_module/data/models/erros/ErrorModel.kt new file mode 100644 index 0000000000..2ea4ce1938 --- /dev/null +++ b/support-module/src/main/java/com/saudigitus/support_module/data/models/erros/ErrorModel.kt @@ -0,0 +1,11 @@ +package com.saudigitus.support_module.data.models.erros + +import java.util.Date + +data class ErrorModel( + val creationDate: Date?, + val errorCode: String?, + val errorDescription: String?, + val errorComponent: String?, + var isSelected: Boolean = false, +) \ No newline at end of file diff --git a/support-module/src/main/java/com/saudigitus/support_module/di/AppModule.kt b/support-module/src/main/java/com/saudigitus/support_module/di/AppModule.kt index 3613dcdc1a..8c757d4477 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/di/AppModule.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/di/AppModule.kt @@ -1,10 +1,15 @@ package com.saudigitus.support_module.di import android.app.Application +import androidx.compose.ui.res.stringResource import androidx.room.Room +import com.saudigitus.support_module.R import com.saudigitus.support_module.data.local.ManualsRepository +import com.saudigitus.support_module.data.local.SyncErrorsRepository import com.saudigitus.support_module.data.local.database.AppDatabase import com.saudigitus.support_module.data.local.repository.ManualsRepositoryImp +import com.saudigitus.support_module.data.local.repository.SyncErrorsRepositoryImpl +import com.saudigitus.support_module.utils.ErrorModelMapper import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -28,10 +33,17 @@ object AppModule { /** * Inject ManualsRepository */ - @Provides @Singleton fun providesManualRepository(appDatabase: AppDatabase, d2: D2): ManualsRepository { return ManualsRepositoryImp(appDatabase.manualsDAO(), d2 = d2) } + /** + * Inject SyncErrorsRepository + */ + @Provides + @Singleton fun providesSyncErrorsRepository(app: Application, d2: D2): SyncErrorsRepository { + return SyncErrorsRepositoryImpl(errorMapper = ErrorModelMapper(fkMessage = app.getString(R.string.fk_message)), d2 = d2) + } + } \ No newline at end of file diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/Routes.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/Routes.kt index 98c92b8fac..49e1cadb83 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/ui/Routes.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/Routes.kt @@ -5,6 +5,9 @@ sealed class Screen(val route: String) { object Manuals : Screen("manuals") object Support : Screen("support") object ViewPdf : Screen("pdf_view/{path}") + object SyncErrors : Screen("sync_errors") + object GeneralErrors : Screen("general_errors") + } diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/SupportScreen/ErrorsViewModel.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/SupportScreen/ErrorsViewModel.kt new file mode 100644 index 0000000000..63faab85dc --- /dev/null +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/SupportScreen/ErrorsViewModel.kt @@ -0,0 +1,41 @@ +package com.saudigitus.support_module.ui.SupportScreen + +import android.content.Context +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.saudigitus.support_module.data.local.ManualsRepository +import com.saudigitus.support_module.data.local.SyncErrorsRepository +import com.saudigitus.support_module.ui.ManualsUiState +import com.saudigitus.support_module.ui.errorsScreen.ErrorUiState +import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class ErrorsViewModel @Inject internal constructor( + private val repository: SyncErrorsRepository, + @ApplicationContext private val context: Context +) : ViewModel() { + + private val _errorsUiState = MutableStateFlow(ErrorUiState()) + val errorsUiState = _errorsUiState.asStateFlow() + + private fun getErrors(){ + viewModelScope.launch { + _errorsUiState.update {it.copy(isLoading = true)} + repository.getSyncErrors().collect{ errors -> + _errorsUiState.update { + it.copy(errorsItems = errors, isLoading = false) + } + } + } + } + + init { + getErrors() + } +} \ No newline at end of file diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/SupportScreen/SupportScreen.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/SupportScreen/SupportScreen.kt index 65ca0333b2..e076be5fdb 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/ui/SupportScreen/SupportScreen.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/SupportScreen/SupportScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Warning import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -15,10 +16,15 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavHostController import com.saudigitus.support_module.R +import com.saudigitus.support_module.ui.Screen +import com.saudigitus.support_module.ui.SupportScreen.ErrorsViewModel import com.saudigitus.support_module.ui.components.BasicApp import com.saudigitus.support_module.ui.components.SimpleCard +import com.saudigitus.support_module.ui.manualScreen.ManualViewModel import timber.log.Timber @OptIn(ExperimentalMaterial3Api::class) @@ -44,9 +50,19 @@ fun SupportScreen( color = Color.Gray ) Spacer(Modifier.height(20.dp)) - SimpleCard(title = stringResource(id = R.string.sync_errord), icon = Icons.Default.Close) + SimpleCard(title = stringResource( + id = R.string.sync_errord), + icon = Icons.Default.Close, + onClick = { + navController.navigate(Screen.SyncErrors.route) + }) Spacer(Modifier.height(20.dp)) - SimpleCard(title = stringResource(id = R.string.other_errors) , icon = Icons.Default.Warning) + SimpleCard(title = stringResource( + id = R.string.other_errors), + icon = Icons.Default.Warning, + onClick = { + navController.navigate(Screen.GeneralErrors.route) + }) } } ) diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/components/CustomCard.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/components/CustomCard.kt index a12da7281c..86fb5acf85 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/ui/components/CustomCard.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/components/CustomCard.kt @@ -21,15 +21,19 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import com.saudigitus.support_module.ui.theme.Blue700 +import org.hisp.dhis.mobile.ui.designsystem.theme.Radius +import org.hisp.dhis.mobile.ui.designsystem.theme.dropShadow @Composable fun CustomCard(imageResId: Int, title: String, onClick: () -> Unit) { Card( modifier = Modifier .size(150.dp) - .shadow(2.dp, RoundedCornerShape(16.dp)) - .clip(RoundedCornerShape(16.dp)) + .dropShadow(shape = RoundedCornerShape(Radius.XS)) + .clip(RoundedCornerShape(10.dp)) .clickable { onClick() }, + shape = RoundedCornerShape(Radius.XS), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(50.dp), ) { @@ -46,7 +50,7 @@ fun CustomCard(imageResId: Int, title: String, onClick: () -> Unit) { Spacer(modifier = Modifier.height(8.dp)) Text( text = title, - color = Color.Black, + color = Blue700, fontWeight = FontWeight.Bold ) } diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/components/ErrorComponent.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/components/ErrorComponent.kt index 1a239e3488..fa93bd5258 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/ui/components/ErrorComponent.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/components/ErrorComponent.kt @@ -3,6 +3,7 @@ package com.saudigitus.support_module.ui.components import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -21,43 +22,49 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.example.viewtest.ui.manualScreen.ErrosScreen @Composable -fun ErrorComponent(error: String) { +fun ErrorComponent(error: String, type: String, comp: String, date: String) { Card( shape = RoundedCornerShape(8.dp), modifier = Modifier .border(1.dp, Color.Red, RoundedCornerShape(8.dp)) // Red border ) { - // Applying background to the entire card content - Row( + Column( modifier = Modifier .fillMaxWidth() .background(Color(0xFFFFCDD2)) .padding(8.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ){ + ) { + + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ){ + Text( + text = date, + fontSize = 12.sp, + color = Color.Gray + ) + Text( + text = "$type $comp", + fontSize = 10.sp, + color = Color.Red + ) + } Text( text = error, - ) - Icon( - imageVector = Icons.Filled.Close, - contentDescription = "title", - modifier = Modifier - // .fillMaxWidth() // Ensures the text takes up the card width - .background(Color(0xFFFFCDD2)) - .size(20.dp), - - tint = Color.Gray + fontSize = 12.sp, + color = Color.Black ) } + } } @Preview(showBackground = true) @Composable fun ScreenPreview() { - ErrorComponent("Error It is a long established fact reader") + ErrorComponent("Error It is a long established fact reader", "FK", "server","2012-15-54") } \ No newline at end of file diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/components/ListCard.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/components/ListCard.kt index 8787936a56..271ce619bd 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/ui/components/ListCard.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/components/ListCard.kt @@ -31,6 +31,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.saudigitus.support_module.R import com.saudigitus.support_module.ui.ManualsUiState +import org.hisp.dhis.mobile.ui.designsystem.theme.Radius +import org.hisp.dhis.mobile.ui.designsystem.theme.dropShadow @Composable fun ListCard( @@ -45,11 +47,11 @@ fun ListCard( modifier = Modifier .fillMaxWidth() .size(width = 0.dp, height = 80.dp) - .shadow(2.dp, RoundedCornerShape(16.dp)) - .clip(RoundedCornerShape(16.dp)) + .dropShadow(shape = RoundedCornerShape(Radius.XS)) .clickable(onClick = onClick), + shape = RoundedCornerShape(Radius.XS), colors = CardDefaults.cardColors(containerColor = Color.White), - elevation = CardDefaults.cardElevation(50.dp), + elevation = CardDefaults.cardElevation(10.dp), ){ Row( modifier = Modifier diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/components/SimpleCard.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/components/SimpleCard.kt index d9a695fe08..704d3c4757 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/ui/components/SimpleCard.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/components/SimpleCard.kt @@ -1,5 +1,6 @@ package com.saudigitus.support_module.ui.components +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -25,15 +26,23 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.saudigitus.support_module.ui.theme.Blue700 +import org.hisp.dhis.mobile.ui.designsystem.theme.Radius +import org.hisp.dhis.mobile.ui.designsystem.theme.dropShadow @Composable -fun SimpleCard(title: String, icon: androidx.compose.ui.graphics.vector.ImageVector) { +fun SimpleCard( + title: String, + icon: androidx.compose.ui.graphics.vector.ImageVector, + onClick: () -> Unit) { Card( modifier = Modifier .fillMaxWidth() .size(width = 0.dp, height = 70.dp) - .shadow(2.dp, RoundedCornerShape(16.dp)) - .clip(RoundedCornerShape(16.dp)), + .dropShadow(shape = RoundedCornerShape(Radius.XS)) + .clip(RoundedCornerShape(10.dp)) + .clickable(onClick = onClick), + shape = RoundedCornerShape(Radius.XS), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(50.dp), ){ @@ -53,13 +62,12 @@ fun SimpleCard(title: String, icon: androidx.compose.ui.graphics.vector.ImageVec text = title, fontSize = 14.sp, overflow = TextOverflow.Ellipsis, - color = Color.Black + color = Blue700 ) } Icon( imageVector = icon, contentDescription = title, - // modifier = Modifier.size(48.dp), tint = Color.Black ) } @@ -69,5 +77,5 @@ fun SimpleCard(title: String, icon: androidx.compose.ui.graphics.vector.ImageVec @Preview(showBackground = true) @Composable fun SimpleCardPreview() { - SimpleCard(title = "Manual subtitle here alfa", icon = Icons.AutoMirrored.Filled.KeyboardArrowRight) + SimpleCard(title = "Manual subtitle here alfa", icon = Icons.AutoMirrored.Filled.KeyboardArrowRight, onClick = {}) } \ No newline at end of file diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/errorsScreen/ErrorUiState.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/errorsScreen/ErrorUiState.kt new file mode 100644 index 0000000000..8482d4e1dd --- /dev/null +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/errorsScreen/ErrorUiState.kt @@ -0,0 +1,8 @@ +package com.saudigitus.support_module.ui.errorsScreen + +import com.saudigitus.support_module.data.models.erros.ErrorModel + +data class ErrorUiState( + val isLoading: Boolean = false, + val errorsItems: List = emptyList() +) \ No newline at end of file diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/errorsScreen/ErrorsScreen.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/errorsScreen/ErrorsScreen.kt index 237d3405f5..ae682c37c1 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/ui/errorsScreen/ErrorsScreen.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/errorsScreen/ErrorsScreen.kt @@ -3,45 +3,64 @@ package com.example.viewtest.ui.manualScreen import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.KeyboardArrowRight -import androidx.compose.material.icons.filled.Send +import androidx.compose.material.icons.automirrored.filled.Send import androidx.compose.material3.ExtendedFloatingActionButton -import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon -import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue 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.input.pointer.PointerIcon.Companion.Text +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavHostController import com.saudigitus.support_module.R import com.saudigitus.support_module.ui.components.BasicApp import com.saudigitus.support_module.ui.components.ErrorComponent -import com.saudigitus.support_module.ui.components.ListCard -import com.saudigitus.support_module.ui.MenuScreen +import com.saudigitus.support_module.ui.SupportScreen.ErrorsViewModel +import com.saudigitus.support_module.ui.theme.app_blue_color @Composable -fun ErrosScreen( - //viewModel: MenuViewModel, - //onBack: () -> Unit +fun ErrorsScreen( + navController: NavHostController, + onBack: () -> Unit ) { - BasicApp(title = "Relatar erro de sincronização", content = { + val viewModel = hiltViewModel() + val errorsUiState by viewModel.errorsUiState.collectAsStateWithLifecycle() + + + BasicApp( + title = stringResource(id = R.string.sync_errors_view_title) , + onBack = onBack, + fab = { + ExtendedFloatingActionButton( + icon = { Icon(Icons.AutoMirrored.Filled.Send, contentDescription = "Send") }, // Icon on the FAB + text = { Text(stringResource(id = R.string.fab_send_lb)) }, // Text on the FAB + onClick = { /* Action when clicked */ }, + containerColor = app_blue_color, // Background color of the FAB + contentColor = Color.White // Color of the text and icon + ) + }, + content = { Column( modifier = Modifier .fillMaxSize() @@ -52,16 +71,25 @@ fun ErrosScreen( ) { Column { Text( - text = "Erros de sincronização", + text =(errorsUiState.errorsItems.size.toString())+ " "+ stringResource(id = R.string.sync_errors), fontSize = 16.sp, color = Color.Gray ) Spacer(Modifier.height(10.dp)) - ErrorComponent("Error It is a long established fact reader") - Spacer(Modifier.height(10.dp)) - ErrorComponent("Error It is a long established fact reader") - Spacer(Modifier.height(10.dp)) - ErrorComponent("Error It is a long established fact reader") + + LazyColumn( + modifier = Modifier.fillMaxWidth() + .height(400.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(errorsUiState.errorsItems) { error -> + ErrorComponent( + error = error.errorDescription.toString(), + type = error.errorCode.toString(), + comp = error.errorComponent ?: "", + date = error.creationDate.toString()) + } + } } val textState = remember { mutableStateOf("") } @@ -69,12 +97,12 @@ fun ErrosScreen( TextField( value = textState.value, onValueChange = { textState.value = it }, - label = { Text(text = "Message") }, + label = { Text(text = stringResource(id = R.string.textarea_label)) }, modifier = Modifier.fillMaxWidth(), - minLines = 8, - maxLines = 8, // Allows up to 5 lines + minLines = 6, + maxLines = 6, keyboardOptions = KeyboardOptions.Default.copy( - imeAction = ImeAction.Default // Allows multiline input + imeAction = ImeAction.Default ) ) Spacer(Modifier.height(20.dp)) @@ -88,5 +116,5 @@ fun ErrosScreen( @Preview(showBackground = true) @Composable fun ScreenPreview() { - ErrosScreen() + ErrorsScreen(navController = NavHostController(LocalContext.current), onBack = {}) } \ No newline at end of file diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/generalErrorsScreen/GeneralReportScreen.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/generalErrorsScreen/GeneralReportScreen.kt index 1e49f141fe..3c3ff48681 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/ui/generalErrorsScreen/GeneralReportScreen.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/generalErrorsScreen/GeneralReportScreen.kt @@ -27,28 +27,35 @@ 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.platform.LocalContext import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.navigation.NavHostController import com.saudigitus.support_module.R import com.saudigitus.support_module.ui.components.BasicApp import com.saudigitus.support_module.ui.components.ErrorComponent +import com.saudigitus.support_module.ui.theme.Blue700 +import com.saudigitus.support_module.ui.theme.app_blue_color @Composable fun GeneralReportScreen( - //viewModel: MenuViewModel, - //onBack: () -> Unit + navController: NavHostController, + onBack: () -> Unit ) { - BasicApp(title = "Relatar erro de sincronização", + BasicApp( + title = stringResource(id = R.string.general_errors_view_title) , + onBack = onBack, fab = { ExtendedFloatingActionButton( icon = { Icon(Icons.AutoMirrored.Filled.Send, contentDescription = "Send") }, // Icon on the FAB - text = { Text("Enviar") }, // Text on the FAB + text = { Text(stringResource(id = R.string.fab_send_lb)) }, // Text on the FAB onClick = { /* Action when clicked */ }, - containerColor = Color.White, // Background color of the FAB - contentColor = Color(0xFF2C98F0) // Color of the text and icon + containerColor = app_blue_color, + contentColor = Color.White ) }, content = { @@ -56,7 +63,7 @@ fun GeneralReportScreen( Column( modifier = Modifier .fillMaxSize() - .background(color = Color(0xFFFFFFFF)) + .background(color = Color.White) .padding(16.dp), verticalArrangement = Arrangement.SpaceBetween, horizontalAlignment = Alignment.Start @@ -65,15 +72,15 @@ fun GeneralReportScreen( horizontalAlignment = Alignment.CenterHorizontally ) { Image( - painter = painterResource(id = R.drawable.support), // Substitua 'your_image' pelo nome do seu arquivo + painter = painterResource(id = R.drawable.support), contentDescription = null, - modifier = Modifier.size(80.dp) + modifier = Modifier.size(50.dp) ) Spacer(modifier = Modifier.height(20.dp)) Text( - text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the", - fontSize = 16.sp, - color = Color.Gray + text = stringResource(id = R.string.general_errors_view_lb), + fontSize = 12.sp, + color = Blue700 ) Spacer(Modifier.height(10.dp)) } @@ -82,10 +89,10 @@ fun GeneralReportScreen( TextField( value = textState.value, onValueChange = { textState.value = it }, - label = { Text(text = "Message") }, + label = { Text(text = stringResource(id = R.string.textarea_label)) }, modifier = Modifier.fillMaxWidth(), - minLines = 12, - maxLines = 12, // Allows up to 5 lines + minLines = 20, + maxLines = 20, // Allows up to 5 lines keyboardOptions = KeyboardOptions.Default.copy( imeAction = ImeAction.Default // Allows multiline input ) @@ -98,5 +105,5 @@ fun GeneralReportScreen( @Preview(showBackground = true) @Composable fun GenScreenPreview() { - GeneralReportScreen() + GeneralReportScreen(navController = NavHostController(LocalContext.current), onBack = {}) } \ No newline at end of file diff --git a/support-module/src/main/java/com/saudigitus/support_module/ui/theme/Color.kt b/support-module/src/main/java/com/saudigitus/support_module/ui/theme/Color.kt index aaa053a257..588483cbba 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/ui/theme/Color.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/ui/theme/Color.kt @@ -2,6 +2,7 @@ package com.saudigitus.support_module.ui.theme import androidx.compose.ui.graphics.Color +val Blue700: Color = Color(0xFF1260BA) val md_theme_light_primary = Color(0xFF0062A2) val md_theme_light_onPrimary = Color(0xFFFFFFFF) val md_theme_light_primaryContainer = Color(0xFFD1E4FF) diff --git a/support-module/src/main/java/com/saudigitus/support_module/utils/AppNavHost.kt b/support-module/src/main/java/com/saudigitus/support_module/utils/AppNavHost.kt index 42d7090ea3..3101b1278b 100644 --- a/support-module/src/main/java/com/saudigitus/support_module/utils/AppNavHost.kt +++ b/support-module/src/main/java/com/saudigitus/support_module/utils/AppNavHost.kt @@ -4,8 +4,10 @@ import androidx.compose.ui.platform.LocalContext import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import com.example.viewtest.ui.manualScreen.ErrorsScreen import com.saudigitus.support_module.ui.MenuScreen import com.saudigitus.support_module.ui.Screen +import com.saudigitus.support_module.ui.manualScreen.GeneralReportScreen import com.saudigitus.support_module.ui.manualScreen.ManualScreen import com.saudigitus.support_module.ui.manualScreen.PdfViewer import timber.log.Timber @@ -32,6 +34,16 @@ fun AppNavHost(navController: NavHostController, route: String, activity: Activi activity.finish() }) } + composable(Screen.SyncErrors.route) { + ErrorsScreen(navController = navController, onBack = { + navController.popBackStack() + }) + } + composable(Screen.GeneralErrors.route) { + GeneralReportScreen(navController = navController, onBack = { + navController.popBackStack() + }) + } composable(Screen.ViewPdf.route) { backStackEntry -> val encodedPath = backStackEntry.arguments?.getString("path") val filePath = encodedPath?.let { URLDecoder.decode(it, StandardCharsets.UTF_8.toString()) } diff --git a/support-module/src/main/java/com/saudigitus/support_module/utils/ErrorModelMapper.kt b/support-module/src/main/java/com/saudigitus/support_module/utils/ErrorModelMapper.kt new file mode 100644 index 0000000000..8fc875925c --- /dev/null +++ b/support-module/src/main/java/com/saudigitus/support_module/utils/ErrorModelMapper.kt @@ -0,0 +1,62 @@ +package com.saudigitus.support_module.utils + +import com.saudigitus.support_module.data.models.erros.ErrorModel +import org.hisp.dhis.android.core.imports.TrackerImportConflict +import org.hisp.dhis.android.core.maintenance.D2Error +import org.hisp.dhis.android.core.maintenance.ForeignKeyViolation + +class ErrorModelMapper(private val fkMessage: String) { + + companion object { + const val FK = "FK" + } + + fun mapD2Error(errors: List): List { + return errors.map { + map(it) + } + } + + fun map(error: D2Error): ErrorModel { + return ErrorModel( + error.created(), + error.httpErrorCode().toString(), + error.errorDescription(), + error.errorComponent()?.name ?: "", + ) + } + + fun mapConflict(conflicts: List): List { + return conflicts.map { + map(it) + } + } + + fun map(conflict: TrackerImportConflict): ErrorModel { + return ErrorModel( + conflict.created(), + conflict.errorCode(), + conflict.displayDescription() ?: conflict.conflict(), + conflict.status()?.name, + ) + } + + fun mapFKViolation(fKViolations: List): List { + return fKViolations.map { + map(it) + } + } + + fun map(fKViolation: ForeignKeyViolation): ErrorModel { + val toTable = fKViolation.toTable() ?: "" + val fromTable = fKViolation.fromTable() ?: "" + val toUid = fKViolation.notFoundValue() ?: "" + val fromUid = fKViolation.fromObjectUid() ?: "" + return ErrorModel( + fKViolation.created(), + FK, + fkMessage.format(toTable, toUid, fromTable, fromUid), + "", + ) + } +} diff --git a/support-module/src/main/res/values/strings.xml b/support-module/src/main/res/values/strings.xml index d887fd19b2..50b50cb80e 100644 --- a/support-module/src/main/res/values/strings.xml +++ b/support-module/src/main/res/values/strings.xml @@ -8,6 +8,13 @@ Suporte ao utilizador Relatar erros de sincronização Relatar outros erros - + Selecione o tipo de erro que pretende relatar para o suporte. Manual do Utilizador + Missing %s %s from %s %s + Relatar erros de sincronização + Erros de sincronização + Relatar outros erros + Enviar + Descreva com detalhes o erro decorrido com passos para que a equipa possa reproduzir + Descrição do erro \ No newline at end of file