diff --git a/app/src/main/java/com/example/mobileapp/api/ServerService.kt b/app/src/main/java/com/example/mobileapp/api/ServerService.kt index a4611ad..425bc33 100644 --- a/app/src/main/java/com/example/mobileapp/api/ServerService.kt +++ b/app/src/main/java/com/example/mobileapp/api/ServerService.kt @@ -1,6 +1,7 @@ package com.example.mobileapp.api import com.example.mobileapp.api.model.MailRemote +import com.example.mobileapp.api.model.ReportRemote import com.example.mobileapp.api.model.StoryRemote import com.example.mobileapp.api.model.UserRemote import com.example.mobileapp.api.model.UserRemoteSignIn @@ -105,6 +106,13 @@ interface ServerService { @Path("id") id: Int ) + //REPORT + @GET("report/createReport/{dateFrom}/{dateTo}") + suspend fun createReport( + @Path("dateFrom") dateFrom: Long, + @Path("dateTo") dateTo: Long + ): ReportRemote + //INSTANCE companion object { private const val BASE_URL = "https://7hz21fz1-8080.euw.devtunnels.ms/api/" diff --git a/app/src/main/java/com/example/mobileapp/api/model/ReportRemote.kt b/app/src/main/java/com/example/mobileapp/api/model/ReportRemote.kt index aadcbe9..496b466 100644 --- a/app/src/main/java/com/example/mobileapp/api/model/ReportRemote.kt +++ b/app/src/main/java/com/example/mobileapp/api/model/ReportRemote.kt @@ -2,9 +2,11 @@ package com.example.mobileapp.api.model import kotlinx.serialization.Serializable -/* @Serializable data class ReportRemote( - + val dateFrom: Long, + val dateTo: Long, + val postCount: Int, + val mostPostAuthor: String, + val mostPostCount: Int ) -*/ diff --git a/app/src/main/java/com/example/mobileapp/api/repository/RestReportRepository.kt b/app/src/main/java/com/example/mobileapp/api/repository/RestReportRepository.kt index fa53a52..f85ece5 100644 --- a/app/src/main/java/com/example/mobileapp/api/repository/RestReportRepository.kt +++ b/app/src/main/java/com/example/mobileapp/api/repository/RestReportRepository.kt @@ -1,8 +1,9 @@ package com.example.mobileapp.api.repository import com.example.mobileapp.api.ServerService +import com.example.mobileapp.api.model.ReportRemote import com.example.mobileapp.database.repositories.ReportRepository class RestReportRepository(private var service: ServerService): ReportRepository { - + override suspend fun createReport(dateFrom: Long, dateTo: Long): ReportRemote = service.createReport(dateFrom, dateTo) } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/components/InputContent.kt b/app/src/main/java/com/example/mobileapp/components/InputContent.kt index ce57e2d..7ae51fa 100644 --- a/app/src/main/java/com/example/mobileapp/components/InputContent.kt +++ b/app/src/main/java/com/example/mobileapp/components/InputContent.kt @@ -1,5 +1,8 @@ package com.example.mobileapp.components +import android.app.DatePickerDialog +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -19,15 +22,21 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable 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.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.example.mobileapp.ui.theme.ButtonColor2 import com.example.mobileapp.ui.theme.MobileAppTheme +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale val buttonHeightStandard = 72.dp @@ -163,6 +172,52 @@ fun ActiveButton(label: String, backgroundColor: Color, textColor: Color, onClic } } +@Composable +fun DatePicker(startValue: Long? = null, onDateSelected: (Long) -> Unit) { + val context = LocalContext.current + + val calendar = Calendar.getInstance() + val year = calendar.get(Calendar.YEAR) + val month = calendar.get(Calendar.MONTH) + val day = calendar.get(Calendar.DAY_OF_MONTH) + + val dateFormatter = remember { SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()) } + val selectedDate = remember { mutableStateOf(0) } + + startValue?.let { + selectedDate.value = startValue + } + + val datePickerDialog = remember { mutableStateOf(DatePickerDialog(context)) } + + Column( + modifier = Modifier + .fillMaxWidth(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text(text = "Selected Date: ${dateFormatter.format(selectedDate.value)}") + ActiveButton(label = "Выбрать дату", backgroundColor = ButtonColor2, + textColor = Color.White, onClickAction = { + datePickerDialog.value = DatePickerDialog( + context, + { _, year: Int, month: Int, dayOfMonth: Int -> + val selectedDateInMillis = Calendar.getInstance().apply { + set(year, month, dayOfMonth) + }.timeInMillis + + selectedDate.value = selectedDateInMillis + onDateSelected(selectedDateInMillis) + }, + year, + month, + day + ) + datePickerDialog.value.show() + }) + } +} + @Preview(showBackground = true) @Composable fun PlaceholderTextFieldPreview() { diff --git a/app/src/main/java/com/example/mobileapp/components/ListContent.kt b/app/src/main/java/com/example/mobileapp/components/ListContent.kt index 1633f08..d6cf1f3 100644 --- a/app/src/main/java/com/example/mobileapp/components/ListContent.kt +++ b/app/src/main/java/com/example/mobileapp/components/ListContent.kt @@ -281,7 +281,7 @@ fun addNewListItem(navController: NavHostController, destination: String){ }, shape = RoundedCornerShape(15.dp), colors = CardDefaults.cardColors( - containerColor = BackgroundItem2 + containerColor = Color.White ), elevation = CardDefaults.cardElevation( defaultElevation = 8.dp @@ -304,7 +304,9 @@ fun addNewListItem(navController: NavHostController, destination: String){ text = "Добавить", fontSize = 28.sp, fontWeight = FontWeight.Bold, - modifier = Modifier.padding(start = 32.dp)) + modifier = Modifier.padding(start = 32.dp), + color = Color.Black + ) } } } diff --git a/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt b/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt index 095c69a..c56c7f7 100644 --- a/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt +++ b/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt @@ -22,6 +22,7 @@ import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource @@ -53,8 +54,9 @@ import com.example.mobileapp.screens.StoryViewScreen val navBarItems = listOf( NavBarItem(route = "main", label = "Главная", icon = R.drawable.home), NavBarItem(route = "story", label = "Создание", icon = R.drawable.edit), - NavBarItem(route = "mail", label = "Уведомления", icon = R.drawable.mail), - NavBarItem(route = "settings", label = "Настройки", icon = R.drawable.settings), + NavBarItem(route = "mail", label = "Почта", icon = R.drawable.mail), + NavBarItem(route = "report", label = "Отчёт", icon = R.drawable.report), + NavBarItem(route = "settings", label = "Настройки", icon = R.drawable.settings) ) @OptIn(ExperimentalMaterial3Api::class) @@ -69,8 +71,10 @@ fun NavBar(navController: NavHostController) { visible = topBarState.value, enter = slideInVertically(initialOffsetY = { it }), exit = slideOutVertically(targetOffsetY = { it }), + content = { TopAppBar( + modifier = Modifier.fillMaxWidth(), title = { Text( text = "Storyteller!", @@ -79,7 +83,8 @@ fun NavBar(navController: NavHostController) { Font( R.font.roboto_regular, FontWeight.Bold ) - ) + ), + color = Color.Black ) } ) @@ -204,8 +209,8 @@ fun NavBar(navController: NavHostController) { } composable("report"){ topBarState.value = false - bottomBarState.value = false - ReportScreen(navController = navController) + bottomBarState.value = true + ReportScreen() } } } diff --git a/app/src/main/java/com/example/mobileapp/database/repositories/ReportRepository.kt b/app/src/main/java/com/example/mobileapp/database/repositories/ReportRepository.kt index 2362ed6..27da0ab 100644 --- a/app/src/main/java/com/example/mobileapp/database/repositories/ReportRepository.kt +++ b/app/src/main/java/com/example/mobileapp/database/repositories/ReportRepository.kt @@ -1,4 +1,7 @@ package com.example.mobileapp.database.repositories +import com.example.mobileapp.api.model.ReportRemote + interface ReportRepository { + suspend fun createReport(dateFrom: Long, dateTo: Long): ReportRemote } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/database/viewmodels/ReportViewModel.kt b/app/src/main/java/com/example/mobileapp/database/viewmodels/ReportViewModel.kt index 938b449..d3cd9a4 100644 --- a/app/src/main/java/com/example/mobileapp/database/viewmodels/ReportViewModel.kt +++ b/app/src/main/java/com/example/mobileapp/database/viewmodels/ReportViewModel.kt @@ -1,7 +1,22 @@ package com.example.mobileapp.database.viewmodels +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.mobileapp.api.model.ReportRemote import com.example.mobileapp.database.repositories.ReportRepository +import kotlinx.coroutines.launch class ReportViewModel(private val reportRepository: ReportRepository): ViewModel() { + private var _report = mutableStateOf(null) + val report: MutableState get() = _report + + fun createReport(dateFrom: Long, dateTo: Long) = viewModelScope.launch { + _report.value = reportRepository.createReport(dateFrom, dateTo) + } + + fun clearReport(){ + _report.value = null + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/screens/ReportScreen.kt b/app/src/main/java/com/example/mobileapp/screens/ReportScreen.kt index 499ab70..5690573 100644 --- a/app/src/main/java/com/example/mobileapp/screens/ReportScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/ReportScreen.kt @@ -1,21 +1,59 @@ package com.example.mobileapp.screens +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController +import com.example.mobileapp.components.ActiveButton +import com.example.mobileapp.components.DatePicker import com.example.mobileapp.database.viewmodels.MobileAppViewModelProvider import com.example.mobileapp.database.viewmodels.ReportViewModel +import com.example.mobileapp.ui.theme.ButtonColor2 +import java.text.SimpleDateFormat +import java.util.Date @Composable -fun ReportScreen(navController: NavController, +fun ReportScreen( reportViewModel: ReportViewModel = viewModel(factory = MobileAppViewModelProvider.Factory)){ + val dateFormat = SimpleDateFormat("dd.MM.yyyy") + + val dateFrom = remember { mutableStateOf(Date().time) } + val dateTo = remember { mutableStateOf(Date().time) } + Column( modifier = Modifier - .fillMaxWidth() + .fillMaxWidth(), + verticalArrangement = Arrangement.Center ) { - + if(reportViewModel.report.value == null) { + DatePicker(startValue = dateFrom.value, onDateSelected = { newDateFrom -> + dateFrom.value = newDateFrom + }) + DatePicker(startValue = dateTo.value, onDateSelected = { newDateTo -> + dateTo.value = newDateTo + }) + ActiveButton(label = "Сформировать", backgroundColor = ButtonColor2, + textColor = Color.White, onClickAction = { + reportViewModel.createReport(dateFrom.value, dateTo.value) + }) + } + else{ + Text(text = "Дата с ${dateFormat.format(reportViewModel.report.value?.dateFrom?.let { Date(it) })}") + Text(text = "Дата по ${dateFormat.format(reportViewModel.report.value?.dateTo?.let { Date(it) })}") + Text(text = "Кол-в публикаций за период: ${reportViewModel.report.value?.postCount}") + Text(text = "Наибольшее число публикаций у: ${reportViewModel.report.value?.mostPostAuthor}") + Text(text = "Кол-во публикаций у пользователя:${reportViewModel.report.value?.mostPostCount}") + ActiveButton(label = "Сбросить", backgroundColor = ButtonColor2, + textColor = Color.White, onClickAction = { + reportViewModel.clearReport() + }) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/screens/ViewScreens.kt b/app/src/main/java/com/example/mobileapp/screens/ViewScreens.kt index 4cba9da..3f69274 100644 --- a/app/src/main/java/com/example/mobileapp/screens/ViewScreens.kt +++ b/app/src/main/java/com/example/mobileapp/screens/ViewScreens.kt @@ -14,8 +14,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -34,6 +32,7 @@ import com.example.mobileapp.R import com.example.mobileapp.components.NavigationButton import com.example.mobileapp.database.viewmodels.MailViewModel import com.example.mobileapp.database.viewmodels.MobileAppViewModelProvider +import com.example.mobileapp.database.viewmodels.ReportViewModel import com.example.mobileapp.database.viewmodels.StoryViewModel import com.example.mobileapp.database.viewmodels.UserViewModel import com.example.mobileapp.ui.theme.ButtonColor2