diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index a8a563b..96a1bca 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -12,6 +12,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d1e84f..cb41a95 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,9 +1,6 @@
+
-
-
+
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pmulabs/MainActivity.kt b/app/src/main/java/com/example/pmulabs/MainActivity.kt
index aa660d7..ccbac64 100644
--- a/app/src/main/java/com/example/pmulabs/MainActivity.kt
+++ b/app/src/main/java/com/example/pmulabs/MainActivity.kt
@@ -6,10 +6,10 @@ import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.rememberNavController
-import com.example.pmulabs.viewModels.CurrentUserViewModel
import com.example.pmulabs.graphs.RootNavigationGraph
import com.example.pmulabs.ui.theme.PMULabsTheme
import com.example.pmulabs.viewModels.AppViewModelProvider
+import com.example.pmulabs.viewModels.CurrentUserViewModel
import com.example.pmulabs.viewModels.SearchViewModel
class MainActivity : ComponentActivity() {
@@ -19,7 +19,7 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
PMULabsTheme {
- RootNavigationGraph(navController = rememberNavController(),searchViewModel, currentUserViewModel = viewModel(factory = AppViewModelProvider.Factory))
+ RootNavigationGraph(navController = rememberNavController(),searchViewModel=searchViewModel, currentUserViewModel = viewModel(factory = AppViewModelProvider.Factory))
}
}
}
diff --git a/app/src/main/java/com/example/pmulabs/api/NewsPortalService.kt b/app/src/main/java/com/example/pmulabs/api/NewsPortalService.kt
index 5fe2fb8..fb8809c 100644
--- a/app/src/main/java/com/example/pmulabs/api/NewsPortalService.kt
+++ b/app/src/main/java/com/example/pmulabs/api/NewsPortalService.kt
@@ -2,6 +2,7 @@ package com.example.pmulabs.api
import com.example.pmulabs.api.model.ArticleRemote
import com.example.pmulabs.api.model.CommentRemote
+import com.example.pmulabs.api.model.ReportRemote
import com.example.pmulabs.api.model.TagRemote
import com.example.pmulabs.api.model.UserRemote
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
@@ -19,6 +20,11 @@ import retrofit2.http.Path
import retrofit2.http.Query
interface NewsPortalService {
+ @GET("report")
+ suspend fun getReport(
+ @Query("startDate") startDate: Long,
+ @Query("endDate") endDate: Long
+ ): List
@GET("users")
suspend fun getUsers(): List
@GET("tags")
diff --git a/app/src/main/java/com/example/pmulabs/api/model/ReportRemote.kt b/app/src/main/java/com/example/pmulabs/api/model/ReportRemote.kt
new file mode 100644
index 0000000..7a2c8de
--- /dev/null
+++ b/app/src/main/java/com/example/pmulabs/api/model/ReportRemote.kt
@@ -0,0 +1,12 @@
+package com.example.pmulabs.api.model
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ReportRemote(
+ val title: String = "",
+ val publishDate: Long = 0,
+ val tagName: String = "",
+ val userName: String = "",
+ val comments: Int = 0
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pmulabs/api/repository/RestUserRepository.kt b/app/src/main/java/com/example/pmulabs/api/repository/RestUserRepository.kt
index 47cbbd9..2851f07 100644
--- a/app/src/main/java/com/example/pmulabs/api/repository/RestUserRepository.kt
+++ b/app/src/main/java/com/example/pmulabs/api/repository/RestUserRepository.kt
@@ -1,6 +1,7 @@
package com.example.pmulabs.api.repository
import com.example.pmulabs.api.NewsPortalService
+import com.example.pmulabs.api.model.ReportRemote
import com.example.pmulabs.api.model.toArticle
import com.example.pmulabs.api.model.toComment
import com.example.pmulabs.api.model.toTag
@@ -27,6 +28,11 @@ class RestUserRepository(
service.createUser(user.toUserRemote()).toUser()
}
+ override suspend fun getReport(startDate: Long, endDate: Long):List
+ {
+ return service.getReport(startDate,endDate)
+ }
+
override suspend fun updateUser(user: User) {
user.id?.let { service.updateUser(it, user.toUserRemote()).toUser() }
}
diff --git a/app/src/main/java/com/example/pmulabs/basecomponents/navigate/BottomBarScreen.kt b/app/src/main/java/com/example/pmulabs/basecomponents/navigate/BottomBarScreen.kt
index 797fea2..32c7d17 100644
--- a/app/src/main/java/com/example/pmulabs/basecomponents/navigate/BottomBarScreen.kt
+++ b/app/src/main/java/com/example/pmulabs/basecomponents/navigate/BottomBarScreen.kt
@@ -84,4 +84,10 @@ sealed class BottomBarScreen(
icon= R.drawable.ic_bottom_info,
iconFocused=R.drawable.ic_bottom_info_focused
)
+ object Report: BottomBarScreen(
+ route = "REPORT",
+ title="Report",
+ icon= R.drawable.ic_bottom_info,
+ iconFocused=R.drawable.ic_bottom_info_focused
+ )
}
diff --git a/app/src/main/java/com/example/pmulabs/graphs/HomeNavGraph.kt b/app/src/main/java/com/example/pmulabs/graphs/HomeNavGraph.kt
index 1768ada..de3de5d 100644
--- a/app/src/main/java/com/example/pmulabs/graphs/HomeNavGraph.kt
+++ b/app/src/main/java/com/example/pmulabs/graphs/HomeNavGraph.kt
@@ -18,6 +18,7 @@ import com.example.pmulabs.screensMobile.CoopScreen
import com.example.pmulabs.screensMobile.InfoScreen
import com.example.pmulabs.screensMobile.MainScreen
import com.example.pmulabs.screensMobile.ProfileScreen
+import com.example.pmulabs.screensMobile.ReportScreen
import com.example.pmulabs.screensMobile.TagsScreen
import com.example.pmulabs.screensMobile.filterScreens.CalendarScreen
import com.example.pmulabs.screensMobile.filterScreens.SearchByTagScreen
@@ -26,10 +27,11 @@ import com.example.pmulabs.viewModels.AppViewModelProvider
import com.example.pmulabs.viewModels.ArticlePageScreenViewModel
import com.example.pmulabs.viewModels.ArticleScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
+import com.example.pmulabs.viewModels.ReportViewModel
import com.example.pmulabs.viewModels.TagItemViewModel
@Composable
-fun HomeNavGraph(navController: NavHostController,articlePageScreenViewModel: ArticlePageScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), tagItemViewModel: TagItemViewModel = viewModel(factory = AppViewModelProvider.Factory), articleScreenViewModel: ArticleScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
+fun HomeNavGraph(navController: NavHostController,reportViewModel: ReportViewModel= viewModel(factory = AppViewModelProvider.Factory),articlePageScreenViewModel: ArticlePageScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), tagItemViewModel: TagItemViewModel = viewModel(factory = AppViewModelProvider.Factory), articleScreenViewModel: ArticleScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
NavHost(
navController = navController,
route = Graph.MAIN,
@@ -84,5 +86,8 @@ fun HomeNavGraph(navController: NavHostController,articlePageScreenViewModel: Ar
composable(route=BottomBarScreen.Categories.route){
TagsScreen(navController,Modifier, tagItemViewModel, currentUserViewModel)
}
+ composable(route=BottomBarScreen.Report.route){
+ ReportScreen(navController, reportViewModel)
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pmulabs/graphs/RootNavGraph.kt b/app/src/main/java/com/example/pmulabs/graphs/RootNavGraph.kt
index 29d6625..781f701 100644
--- a/app/src/main/java/com/example/pmulabs/graphs/RootNavGraph.kt
+++ b/app/src/main/java/com/example/pmulabs/graphs/RootNavGraph.kt
@@ -14,13 +14,14 @@ import com.example.pmulabs.viewModels.ArticleScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
import com.example.pmulabs.viewModels.EntryScreenViewModel
import com.example.pmulabs.viewModels.RegisterScreenViewModel
+import com.example.pmulabs.viewModels.ReportViewModel
import com.example.pmulabs.viewModels.SearchViewModel
import com.example.pmulabs.viewModels.TagItemViewModel
const val USERID_ARGUMENT="userId"
@Composable
-fun RootNavigationGraph(navController: NavHostController, searchViewModel: SearchViewModel,articlePageScreenViewModel: ArticlePageScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), tagItemViewModel: TagItemViewModel = viewModel(factory = AppViewModelProvider.Factory), articleScreenViewModel: ArticleScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), registerScreenViewModel: RegisterScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), entryScreenViewModel: EntryScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
+fun RootNavigationGraph(navController: NavHostController,reportViewModel: ReportViewModel= viewModel(factory = AppViewModelProvider.Factory), searchViewModel: SearchViewModel,articlePageScreenViewModel: ArticlePageScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), tagItemViewModel: TagItemViewModel = viewModel(factory = AppViewModelProvider.Factory), articleScreenViewModel: ArticleScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), registerScreenViewModel: RegisterScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), entryScreenViewModel: EntryScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)){
NavHost(
navController=navController,
route = Graph.ROOT,
@@ -31,7 +32,7 @@ fun RootNavigationGraph(navController: NavHostController, searchViewModel: Searc
arguments = listOf(navArgument(USERID_ARGUMENT){
type= NavType.StringType
})){
- LoadScreen(searchViewModel = searchViewModel, articleScreenViewModel = articleScreenViewModel, articlePageScreenViewModel = articlePageScreenViewModel, tagItemViewModel = tagItemViewModel,currentUserViewModel = currentUserViewModel)
+ LoadScreen(searchViewModel = searchViewModel,reportViewModel=reportViewModel, articleScreenViewModel = articleScreenViewModel, articlePageScreenViewModel = articlePageScreenViewModel, tagItemViewModel = tagItemViewModel,currentUserViewModel = currentUserViewModel)
}
}
}
diff --git a/app/src/main/java/com/example/pmulabs/room/repository/OfflineUserRepository.kt b/app/src/main/java/com/example/pmulabs/room/repository/OfflineUserRepository.kt
index f765989..6902cf5 100644
--- a/app/src/main/java/com/example/pmulabs/room/repository/OfflineUserRepository.kt
+++ b/app/src/main/java/com/example/pmulabs/room/repository/OfflineUserRepository.kt
@@ -1,5 +1,6 @@
package com.example.pmulabs.room.repository
+import com.example.pmulabs.api.model.ReportRemote
import com.example.pmulabs.room.dao.UserDao
import com.example.pmulabs.room.models.Article
import com.example.pmulabs.room.models.Comment
@@ -16,4 +17,8 @@ class OfflineUserRepository(private val userDao: UserDao) : UserRepository {
override suspend fun getUserComms(idUser: Int): List = userDao.getUserComms(idUser)
override suspend fun getUserArticles(idUser: Int): List = userDao.getUserArticles(idUser)
override suspend fun getUserTags(idUser: Int): List = userDao.getUserTags(idUser)
+ override suspend fun getReport(startDate: Long, endDate: Long): List {
+ TODO("Not yet implemented")
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pmulabs/room/repository/UserRepository.kt b/app/src/main/java/com/example/pmulabs/room/repository/UserRepository.kt
index 2c03030..db7f853 100644
--- a/app/src/main/java/com/example/pmulabs/room/repository/UserRepository.kt
+++ b/app/src/main/java/com/example/pmulabs/room/repository/UserRepository.kt
@@ -1,5 +1,6 @@
package com.example.pmulabs.room.repository
+import com.example.pmulabs.api.model.ReportRemote
import com.example.pmulabs.room.models.Article
import com.example.pmulabs.room.models.Comment
import com.example.pmulabs.room.models.Tag
@@ -14,4 +15,5 @@ interface UserRepository {
suspend fun getUserComms(idUser: Int): List
suspend fun getUserArticles(idUser: Int): List
suspend fun getUserTags(idUser: Int): List
+ suspend fun getReport(startDate: Long, endDate: Long):List
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/MainScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/MainScreen.kt
index ee2562f..0a88ebf 100644
--- a/app/src/main/java/com/example/pmulabs/screensMobile/MainScreen.kt
+++ b/app/src/main/java/com/example/pmulabs/screensMobile/MainScreen.kt
@@ -46,6 +46,7 @@ import com.example.pmulabs.viewModels.AppViewModelProvider
import com.example.pmulabs.viewModels.ArticlePageScreenViewModel
import com.example.pmulabs.viewModels.ArticleScreenViewModel
import com.example.pmulabs.viewModels.CurrentUserViewModel
+import com.example.pmulabs.viewModels.ReportViewModel
import com.example.pmulabs.viewModels.SearchViewModel
import com.example.pmulabs.viewModels.SearchWidget
import com.example.pmulabs.viewModels.TagItemViewModel
@@ -94,7 +95,7 @@ fun MainScreen(navController: NavController, modifier: Modifier = Modifier, arti
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun LoadScreen(navController: NavHostController=rememberNavController(),articlePageScreenViewModel: ArticlePageScreenViewModel, tagItemViewModel: TagItemViewModel, articleScreenViewModel: ArticleScreenViewModel, searchViewModel: SearchViewModel, currentUserViewModel: CurrentUserViewModel){
+fun LoadScreen(navController: NavHostController=rememberNavController(), reportViewModel: ReportViewModel= viewModel(factory = AppViewModelProvider.Factory),articlePageScreenViewModel: ArticlePageScreenViewModel, tagItemViewModel: TagItemViewModel, articleScreenViewModel: ArticleScreenViewModel, searchViewModel: SearchViewModel, currentUserViewModel: CurrentUserViewModel){
val searchWidgetState by searchViewModel.searchWidgetState
val searchTextState by searchViewModel.searchTextState
@@ -257,7 +258,7 @@ fun LoadScreen(navController: NavHostController=rememberNavController(),articleP
) {
Modifier
.padding(it)
- HomeNavGraph(navController = navController,articlePageScreenViewModel, tagItemViewModel,articleScreenViewModel,currentUserViewModel)
+ HomeNavGraph(navController = navController, reportViewModel = reportViewModel,articlePageScreenViewModel, tagItemViewModel,articleScreenViewModel,currentUserViewModel)
}
}
diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/ProfileScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/ProfileScreen.kt
index c676190..5a358e2 100644
--- a/app/src/main/java/com/example/pmulabs/screensMobile/ProfileScreen.kt
+++ b/app/src/main/java/com/example/pmulabs/screensMobile/ProfileScreen.kt
@@ -1,17 +1,14 @@
package com.example.pmulabs.screensMobile
import android.annotation.SuppressLint
-import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
-import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
@@ -33,7 +30,6 @@ import androidx.compose.material3.ButtonColors
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
@@ -62,6 +58,7 @@ import androidx.compose.ui.unit.toSize
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.example.pmulabs.R
+import com.example.pmulabs.basecomponents.navigate.BottomBarScreen
import com.example.pmulabs.designElem.elem.ValidateEmail
import com.example.pmulabs.designElem.elem.isValidEmail
import com.example.pmulabs.room.models.Article
@@ -79,13 +76,11 @@ import java.util.Date
@Composable
fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier,articleScreenViewModel: ArticleScreenViewModel= viewModel(factory = AppViewModelProvider.Factory),tagItemViewModel: TagItemViewModel= viewModel(factory = AppViewModelProvider.Factory),articlePageScreenViewModel: ArticlePageScreenViewModel= viewModel(factory = AppViewModelProvider.Factory), currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
- articleScreenViewModel.setArticleList()
var getUser by remember { mutableStateOf(currentUserViewModel.user) }
var openDialogUser by remember { mutableStateOf(false) }
var email by remember { mutableStateOf(getUser?.email) }
var password by remember { mutableStateOf(getUser?.password) }
var nickname by remember { mutableStateOf(getUser?.nickname) }
- val getArticles = articleScreenViewModel.getArticles
val coroutineScope = rememberCoroutineScope()
articlePageScreenViewModel.setTagList()
@@ -515,129 +510,36 @@ fun ProfileScreen(navController: NavController, modifier: Modifier = Modifier,ar
.wrapContentHeight(align = Alignment.CenterVertically)
.clickable { openDialogUser = true })
}
- }
- }
-
- item {
- Spacer(modifier = Modifier.padding(10.dp))
- Box(
- modifier = Modifier
- .offset(
- x = 9.dp,
- y = 220.dp
- )
- .requiredWidth(width = 393.dp)
- .requiredHeight(height = 282.dp)
- ) {
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 0.dp,
- y = 27.1240234375.dp
+ y = 419.dp
)
- .requiredWidth(width = 393.dp)
- .requiredHeight(height = 255.dp)
+ .requiredWidth(width = 200.dp)
+ .requiredHeight(height = 44.dp)
) {
Box(
modifier = Modifier
- .requiredWidth(width = 393.dp)
- .requiredHeight(height = 255.dp)
- .clip(shape = RoundedCornerShape(5.dp))
- .background(color = Color.White)
- .border(
- border = BorderStroke(3.dp, Color(0xffdbdbf1)),
- shape = RoundedCornerShape(5.dp)
- )
- )
-
- LazyColumn(
- contentPadding = PaddingValues(
- top = 28.dp,
- bottom = 0.dp,
- start = 10.dp,
- end = 10.dp
- ),
- verticalArrangement = Arrangement.spacedBy(1.dp)
- ) {
- if (getArticles.size != 0) {
- items(count = getArticles.size) { index ->
- val article = getArticles[index]
- if (article?.userId == getUser?.id) {
- Spacer(modifier = Modifier.padding(5.dp))
- Text(
- text = "${article?.title}",
- color = Color(0xff423a99),
- style = TextStyle(
- fontSize = 15.sp,
- fontWeight = FontWeight.Bold
- ),
- modifier = Modifier
- .align(alignment = Alignment.TopStart)
- /*.clickable {
- navController.navigate(
- BottomBarScreen.ArticlePage.passId(
- article?.id.toString()
- )
- )
- }*/
- )
- Spacer(modifier = Modifier.padding(5.dp))
- HorizontalDivider(
- thickness = 3.dp,
- modifier = Modifier
- .border(BorderStroke(3.dp, Color(0xffdbdbf1))),
- color = Color(0xffdbdbf1)
- )
- }
- }
- } else {
- item {
- Text(
- text = "Статей пока нет!",
- color = Color(0xff423a99),
- style = TextStyle(
- fontSize = 15.sp,
- fontWeight = FontWeight.Bold
- ),
- modifier = Modifier
- .align(alignment = Alignment.TopStart)
- )
- }
- }
-
- }
-
- }
- Box(
- modifier = Modifier
- .requiredWidth(width = 393.dp)
- .requiredHeight(height = 54.dp)
- ) {
- Box(
- modifier = Modifier
- .requiredWidth(width = 393.dp)
- .requiredHeight(height = 54.dp)
+ .requiredWidth(width = 200.dp)
+ .requiredHeight(height = 44.dp)
.clip(shape = RoundedCornerShape(15.dp))
.background(color = Color(0xff423a99))
)
Text(
- text = "Articles:",
- color = Color.White,
+ text = "Get Report",
+ color = Color(0xffdbdbf1),
+ textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 17.sp,
fontWeight = FontWeight.Bold
),
modifier = Modifier
- .align(alignment = Alignment.TopStart)
- .offset(
- x = 24.dp,
- y = 0.dp
- )
- .requiredWidth(width = 210.dp)
- .requiredHeight(height = 54.dp)
+ .requiredWidth(width = 200.dp)
+ .requiredHeight(height = 44.dp)
.wrapContentHeight(align = Alignment.CenterVertically)
- )
+ .clickable { navController.navigate(BottomBarScreen.Report.route)})
}
}
}
diff --git a/app/src/main/java/com/example/pmulabs/screensMobile/ReportScreen.kt b/app/src/main/java/com/example/pmulabs/screensMobile/ReportScreen.kt
new file mode 100644
index 0000000..f181ba0
--- /dev/null
+++ b/app/src/main/java/com/example/pmulabs/screensMobile/ReportScreen.kt
@@ -0,0 +1,280 @@
+package com.example.pmulabs.screensMobile
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+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.layout.width
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonColors
+import androidx.compose.material3.DatePicker
+import androidx.compose.material3.DatePickerColors
+import androidx.compose.material3.DisplayMode
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextFieldDefaults
+import androidx.compose.material3.rememberDatePickerState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.lifecycle.viewmodel.compose.viewModel
+import androidx.navigation.NavController
+import com.example.pmulabs.api.model.ReportRemote
+import com.example.pmulabs.designElem.elem.BackButton
+import com.example.pmulabs.viewModels.AppViewModelProvider
+import com.example.pmulabs.viewModels.ReportViewModel
+import kotlinx.coroutines.launch
+import java.text.SimpleDateFormat
+import java.util.Date
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun ReportScreen(navController: NavController?, viewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory))
+{
+ val dateStateStart = rememberDatePickerState(initialDisplayMode = DisplayMode.Input)
+ val dateStateEnd = rememberDatePickerState(initialDisplayMode = DisplayMode.Input)
+
+ val coroutineScope = rememberCoroutineScope()
+ val reportResultPageState = viewModel.reportResultPageUiState
+ LazyColumn(
+ contentPadding = PaddingValues(top=75.dp, bottom = 70.dp, start = 10.dp,end=10.dp),
+ verticalArrangement = Arrangement.spacedBy(15.dp),
+ modifier = Modifier
+ .background(Color.White)
+ .fillMaxSize(),
+ horizontalAlignment = Alignment.CenterHorizontally
+ )
+ {
+ item{
+ BackButton(modifier=Modifier
+ .clickable {
+ reportResultPageState.resReport= emptyList()
+ navController?.popBackStack()
+ })
+ }
+ item {
+ DatePicker(
+ title = {
+ Text(
+ text = "Start Date",
+ style = MaterialTheme.typography.headlineLarge
+ )
+ },
+ state = dateStateStart,
+ colors= DatePickerColors(
+ containerColor = Color.White,
+ currentYearContentColor=Color(0xff423a99),
+ dateTextFieldColors = TextFieldDefaults.textFieldColors(
+ Color(0xff423a99),
+ containerColor = Color.White,
+ focusedLabelColor = Color(0xff423a99),
+ focusedPlaceholderColor = Color(0xff423a99),
+ focusedTrailingIconColor = Color(0xff423a99)
+ ),
+ dayContentColor=Color(0xff423a99),
+ dayInSelectionRangeContainerColor=Color(0xff423a99),
+ dayInSelectionRangeContentColor=Color(0xff423a99),
+ disabledDayContentColor=Color(0xff423a99),
+ disabledSelectedDayContainerColor=Color(0xff423a99),
+ disabledSelectedDayContentColor=Color(0xff423a99),
+ disabledSelectedYearContainerColor=Color(0xff423a99),
+ disabledSelectedYearContentColor=Color(0xff423a99),
+ disabledYearContentColor=Color(0xff423a99),
+ dividerColor=Color(0xff423a99),
+ headlineContentColor=Color(0xff423a99),
+ navigationContentColor=Color(0xff423a99),
+ selectedDayContainerColor=Color(0xff423a99),
+ selectedDayContentColor=Color.White,
+ selectedYearContainerColor=Color(0xff423a99),
+ selectedYearContentColor=Color.White,
+ subheadContentColor=Color(0xff423a99),
+ titleContentColor=Color(0xff423a99),
+ todayContentColor=Color(0xff423a99),
+ todayDateBorderColor=Color(0xff423a99),
+ weekdayContentColor=Color(0xff423a99),
+ yearContentColor=Color(0xff423a99)
+ ),
+ )
+ val selectedDateStart = dateStateStart.selectedDateMillis
+ if (selectedDateStart != null) {
+ val resultDate = selectedDateStart
+ viewModel.onUpdate(viewModel.reportPageUiState.reportDetails.copy(startDate = resultDate))
+ } else {
+ viewModel.onUpdate(viewModel.reportPageUiState.reportDetails.copy(startDate = 0))
+ }
+
+
+ DatePicker(
+ title ={
+ Text(
+ text = "End Date",
+ style = MaterialTheme.typography.headlineLarge
+ )},
+ state = dateStateEnd,
+ colors= DatePickerColors(
+ containerColor = Color.White,
+ currentYearContentColor=Color(0xff423a99),
+ dateTextFieldColors = TextFieldDefaults.textFieldColors(
+ Color(0xff423a99),
+ containerColor = Color.White,
+ focusedLabelColor = Color(0xff423a99),
+ focusedPlaceholderColor = Color(0xff423a99),
+ focusedTrailingIconColor = Color(0xff423a99)
+ ),
+ dayContentColor=Color(0xff423a99),
+ dayInSelectionRangeContainerColor=Color(0xff423a99),
+ dayInSelectionRangeContentColor=Color(0xff423a99),
+ disabledDayContentColor=Color(0xff423a99),
+ disabledSelectedDayContainerColor=Color(0xff423a99),
+ disabledSelectedDayContentColor=Color(0xff423a99),
+ disabledSelectedYearContainerColor=Color(0xff423a99),
+ disabledSelectedYearContentColor=Color(0xff423a99),
+ disabledYearContentColor=Color(0xff423a99),
+ dividerColor=Color(0xff423a99),
+ headlineContentColor=Color(0xff423a99),
+ navigationContentColor=Color(0xff423a99),
+ selectedDayContainerColor=Color(0xff423a99),
+ selectedDayContentColor=Color.White,
+ selectedYearContainerColor=Color(0xff423a99),
+ selectedYearContentColor=Color.White,
+ subheadContentColor=Color(0xff423a99),
+ titleContentColor=Color(0xff423a99),
+ todayContentColor=Color(0xff423a99),
+ todayDateBorderColor=Color(0xff423a99),
+ weekdayContentColor=Color(0xff423a99),
+ yearContentColor=Color(0xff423a99)
+ ),
+ )
+ val selectedDateEnd = dateStateEnd.selectedDateMillis
+ if (selectedDateEnd != null) {
+ val resultDate = selectedDateEnd
+ viewModel.onUpdate(viewModel.reportPageUiState.reportDetails.copy(endDate = resultDate))
+ } else {
+ viewModel.onUpdate(viewModel.reportPageUiState.reportDetails.copy(endDate = 0))
+ }
+
+ Spacer(modifier = Modifier.height(16.dp))
+ Button(
+ colors = ButtonColors(
+ containerColor = Color(0xff423a99),
+ disabledContainerColor = Color(0xff423a99),
+ contentColor = Color.White,
+ disabledContentColor = Color.White
+ ),
+ onClick = {
+ coroutineScope.launch { viewModel.getReport() }
+ },
+ enabled = viewModel.reportPageUiState.isEntryValid,
+ modifier = Modifier
+ .fillMaxWidth(0.5f)
+ .height(50.dp)
+ ) {
+ Text(text = "Get Report", fontSize = 20.sp)
+ }
+ Spacer(modifier = Modifier.height(32.dp))
+ Text(
+ color = Color(0xff423a99),
+ text = "Result",
+ style = MaterialTheme.typography.headlineLarge
+ )
+ TableScreen(reportData = reportResultPageState.resReport)
+ }
+ }
+}
+
+@Composable
+fun ItemCell(
+ title: String,
+ commentCount: Int,
+ category: String,
+ userName: String,
+ date: String
+) {
+ Box(
+ modifier = Modifier
+ .width(400.dp)
+ .padding(8.dp)
+ .clip(shape = RoundedCornerShape(5.dp))
+ .background(Color(0xffdbdbf1))
+
+ ) {
+ Column(Modifier.padding(16.dp)) {
+ Text(
+ text = "Заголовок: $title",
+ color = Color(0xff423a99),
+ style = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold),
+ modifier = Modifier.padding(bottom = 8.dp)
+ )
+ Text(
+ text = "Кол-во комментариев: $commentCount",
+ color = Color(0xff423a99),
+ style = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold),
+ modifier = Modifier.padding(bottom = 8.dp)
+ )
+ Text(
+ text = "Категория: $category",
+ color = Color(0xff423a99),
+ style = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold),
+ modifier = Modifier.padding(bottom = 8.dp)
+ )
+ Text(
+ text = "Автор: $userName",
+ color = Color(0xff423a99),
+ style = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold),
+ modifier = Modifier.padding(bottom = 8.dp)
+ )
+ Text(
+ text = "Дата публикации: $date",
+ color = Color(0xff423a99),
+ style = TextStyle(fontSize = 14.sp, fontWeight = FontWeight.Bold),
+ modifier = Modifier.padding(bottom = 8.dp)
+ )
+ }
+ }
+}
+
+
+@Composable
+fun TableScreen(reportData: List) {
+
+ val column1Weight = .8f // 30%
+ val column2Weight = 1f // 30%
+ val formatter = SimpleDateFormat("dd-MMMM-YY")
+
+ Column(
+ Modifier
+ .padding(16.dp)) {
+
+ // Here are all the lines of your table.
+ reportData.forEach {
+ val (title, publishDate, tagName, userName,comments) = it
+ Row(Modifier.fillMaxWidth()) {
+ ItemCell(
+ title,
+ comments,
+ tagName,
+ userName,
+ formatter.format(Date(publishDate)).toString()
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/pmulabs/viewModels/AppViewModelProvider.kt b/app/src/main/java/com/example/pmulabs/viewModels/AppViewModelProvider.kt
index 3d39aa4..02017a3 100644
--- a/app/src/main/java/com/example/pmulabs/viewModels/AppViewModelProvider.kt
+++ b/app/src/main/java/com/example/pmulabs/viewModels/AppViewModelProvider.kt
@@ -32,6 +32,9 @@ object AppViewModelProvider {
initializer {
ArticlePageScreenViewModel(newsPortalApplication().container.tagRestRepository,newsPortalApplication().container.commentRestRepository,newsPortalApplication().container.articleRestRepository,newsPortalApplication().container.userRestRepository)
}
+ initializer {
+ ReportViewModel(newsPortalApplication().container.userRestRepository)
+ }
}
}
diff --git a/app/src/main/java/com/example/pmulabs/viewModels/ArticlePageScreenViewModel.kt b/app/src/main/java/com/example/pmulabs/viewModels/ArticlePageScreenViewModel.kt
index 13c5393..425af87 100644
--- a/app/src/main/java/com/example/pmulabs/viewModels/ArticlePageScreenViewModel.kt
+++ b/app/src/main/java/com/example/pmulabs/viewModels/ArticlePageScreenViewModel.kt
@@ -44,6 +44,7 @@ class ArticlePageScreenViewModel(
}
}
+
var userList by mutableStateOf>(emptyList())
fun setUserList() {
viewModelScope.launch(Dispatchers.IO) {
diff --git a/app/src/main/java/com/example/pmulabs/viewModels/ReportViewModel.kt b/app/src/main/java/com/example/pmulabs/viewModels/ReportViewModel.kt
new file mode 100644
index 0000000..30d5277
--- /dev/null
+++ b/app/src/main/java/com/example/pmulabs/viewModels/ReportViewModel.kt
@@ -0,0 +1,47 @@
+package com.example.pmulabs.viewModels
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.lifecycle.ViewModel
+import com.example.pmulabs.api.model.ReportRemote
+import com.example.pmulabs.room.repository.UserRepository
+
+class ReportViewModel(
+ private val userRepository: UserRepository
+) : ViewModel() {
+ var reportPageUiState by mutableStateOf(ReportPageUiState())
+ private set
+
+ var reportResultPageUiState by mutableStateOf(ReportResultPageUiState())
+ private set
+
+ fun onUpdate(reportDetails: ReportDetails)
+ {
+ reportPageUiState = ReportPageUiState(reportDetails = reportDetails,isEntryValid = validateInput(reportDetails))
+ }
+ private fun validateInput(uiState: ReportDetails = reportPageUiState.reportDetails): Boolean {
+ return with(uiState) {
+ startDate >=0
+ && endDate >=0
+ && startDate < endDate
+ }
+ }
+ suspend fun getReport(){
+ val res = userRepository.getReport(reportPageUiState.reportDetails.startDate, reportPageUiState.reportDetails.endDate)
+ reportResultPageUiState = ReportResultPageUiState(res)
+ }
+}
+
+data class ReportDetails(
+ val startDate: Long = 0,
+ val endDate: Long = 0
+)
+data class ReportPageUiState(
+ val reportDetails: ReportDetails = ReportDetails(),
+ val isEntryValid: Boolean = false
+)
+
+data class ReportResultPageUiState(
+ var resReport:List = emptyList()
+)
\ No newline at end of file
diff --git a/server/data.json b/server/data.json
new file mode 100644
index 0000000..4806355
--- /dev/null
+++ b/server/data.json
@@ -0,0 +1,225 @@
+{
+ "users": [
+ {
+ "id": 1,
+ "nickname": "LatinosMishas",
+ "email": "llmisha@gmail.com",
+ "password": "user1",
+ "role": "user"
+ },
+ {
+ "id": 2,
+ "nickname": "Kasablanka",
+ "email": "kasyul@gmail.com",
+ "password": "user2",
+ "role": "user"
+ },
+ {
+ "id": 3,
+ "nickname": "Ilonherber",
+ "email": "ihlon82@gmail.com",
+ "password": "user3",
+ "role": "user"
+ },
+ {
+ "id": 4,
+ "nickname": "AnnaLibert",
+ "email": "libert@gmail.com",
+ "password": "user4",
+ "role": "user"
+ },
+ {
+ "id": 5,
+ "nickname": "ffff",
+ "email": "fff@mail.ru",
+ "password": "qqq",
+ "role": "user"
+ }
+ ],
+ "tags": [
+ {
+ "id": 1,
+ "title": "Тег_1",
+ "userId": 2
+ },
+ {
+ "title": "Тег_2",
+ "id": 2,
+ "userId": 1
+ },
+ {
+ "id": 3,
+ "title": "Тег_3",
+ "userId": 3
+ },
+ {
+ "id": 4,
+ "title": "Тег_4",
+ "userId": 2
+ },
+ {
+ "title": "Тег_5",
+ "id": 5,
+ "userId": 1
+ },
+ {
+ "id": 6,
+ "title": "Тег_6",
+ "userId": 3
+ }
+ ],
+ "articles": [
+ {
+ "id": 1,
+ "title": "Tesla Cybertruck, уничтожающий всех по прямой, застрял на небольшом холме. Его вытащил Ford",
+ "text": "У автомобили были проблемы с ПО и летняя резина\nВ Сети появился видеоролик, в котором показано, как новейший Tesla Cybertruck, уничтожающий конкурентов в гонках по прямой, не смог подняться в горку.\n\nTesla Cybertruck с ёлкой в багажнике застрял на склоне небольшого заснеженного холма. Его при помощи буксировочной тросса пытался вытащить пикап Ford. Достать автомобиль удалось с большим трудом.",
+ "publishDate": 1687392000000,
+ "userId": 1,
+ "tagId": 6
+ },
+ {
+ "id": 2,
+ "title": "Заголовок 2",
+ "text": "Текст статьи с заголовком 2",
+ "publishDate": 1670889600000,
+ "userId": 3,
+ "tagId": 2
+ },
+ {
+ "id": 3,
+ "title": "Заголовок 3",
+ "text": "Текст статьи с заголовком 3",
+ "publishDate": 1685836800000,
+ "userId": 2,
+ "tagId": 1
+ },
+ {
+ "id": 4,
+ "title": "Заголовок 4",
+ "text": "Текст статьи с заголовком 4",
+ "publishDate": 1678752000000,
+ "userId": 3,
+ "tagId": 3
+ },
+ {
+ "id": 5,
+ "title": "Ракету «Союз» с новой «Арктикой» установили на старте Байконура",
+ "text": "Пуск запланирован на 16 декабря\nСегодня, 13 декабря 2023 года, ракету космического назначения «Союз-2.1б» с гидрометеорологическим спутником «Арктика-М» № 2 транспортировали на стартовый комплекс 31-й площадки космодрома Байконур. Об этом рассказала пресс-служба Роскосмоса. ",
+ "publishDate": 1674086400000,
+ "userId": 1,
+ "tagId": 4
+ },
+ {
+ "id": 6,
+ "title": "Заголовок 6",
+ "text": "Текст статьи с заголовком 6",
+ "publishDate": 1687392000000,
+ "userId": 2,
+ "tagId": 4
+ },
+ {
+ "id": 7,
+ "title": "Заголовок 7",
+ "text": "Текст статьи с заголовком 7",
+ "publishDate": 1674086400000,
+ "userId": 3,
+ "tagId": 5
+ },
+ {
+ "id": 8,
+ "title": "«Сбер» решил выпускать телевизоры диагональю до 75 дюймов в Новгородской области. Вся продукция будет проходить строгий контроль качества",
+ "text": "На заводе будут работать более 200 человек\n«Сбер» планирует расширить производство умных телевизоров в России, выбрав для этого Новгородскую область. Об этом сообщает инсайдерский канал «ё-Пром | Импортозамещение в промышленности».\n\nКомпания намерена локализовать до 50% производства своих телевизоров в особой экономической зоне «Новгородская» до конца 2024 года, сотрудничая при этом со своим партнером SberDevices.\n\nУмные телевизоры Sber поступили в продажу с марта 2022 года и в настоящее время производятся на заводе «Витязь» в Беларуси. Оснащение российской производственной площадки запланировано на следующий год, а запуск производства телевизоров с диагональю от 43 до 75 дюймов намечен на четвертый квартал 2024 года. Телевизоры будут работать под управлением операционной системы «Салют ТВ».",
+ "publishDate": 1670889600000,
+ "userId": 1,
+ "tagId": 3
+ },
+ {
+ "id": 9,
+ "title": "Epic Games после победы в суде над Google переключит внимание на Apple",
+ "text": "Тим Суини прямо сказал:\n\n«Апелляция Apple находится в очереди на рассмотрение в Верховном суде США».\n\nВ прошлом Epic Games уже боролась с Apple в аналогичном судебном процессе. Решение было принято в пользу Apple, но Тим Суини сейчас как никогда мотивирован, чтобы это оспорить.\n\nПомимо Apple, Тим Суини выразил заинтересованность в борьбе с такими платформами, как Steam и Xbox. По сути, компания хочет вывести Fortnite на все платформы без требования о 30%-ном отчислении владельцу платформы.\n\nИлон Макс поздравил Тима Суини с победой, подчеркнув, что она в будущем может привести к серьезным изменениям.",
+ "publishDate": 1702460121998,
+ "userId": 1,
+ "tagId": 4
+ }
+ ],
+ "comments": [
+ {
+ "id": 1,
+ "text": "Текст комментария 1",
+ "userId": 1,
+ "articleId": 8
+ },
+ {
+ "id": 2,
+ "text": "Текст комментария 2",
+ "userId": 2,
+ "articleId": 2
+ },
+ {
+ "id": 3,
+ "text": "Текст комментария 3",
+ "userId": 3,
+ "articleId": 3
+ },
+ {
+ "id": 4,
+ "text": "Текст комментария 4",
+ "userId": 1,
+ "articleId": 4
+ },
+ {
+ "id": 5,
+ "text": "Текст комментария 5",
+ "userId": 2,
+ "articleId": 1
+ },
+ {
+ "id": 6,
+ "text": "Текст комментария 6",
+ "userId": 3,
+ "articleId": 4
+ },
+ {
+ "id": 7,
+ "text": "Текст комментария 7",
+ "userId": 1,
+ "articleId": 6
+ },
+ {
+ "id": 8,
+ "text": "Текст комментария 8",
+ "userId": 2,
+ "articleId": 7
+ },
+ {
+ "id": 9,
+ "text": "Текст комментария 9",
+ "userId": 3,
+ "articleId": 1
+ },
+ {
+ "id": 11,
+ "text": "Текст комментария 11",
+ "userId": 2,
+ "articleId": 3
+ },
+ {
+ "id": 12,
+ "text": "Текст комментария 102",
+ "userId": 1,
+ "articleId": 2
+ },
+ {
+ "id": 13,
+ "text": "новый комментарий",
+ "userId": 1,
+ "articleId": 1
+ },
+ {
+ "id": 14,
+ "text": "aaaa",
+ "userId": 1,
+ "articleId": 2
+ }
+ ]
+}
\ No newline at end of file
diff --git a/server/package.json b/server/package.json
index 1a051f8..729ba53 100644
--- a/server/package.json
+++ b/server/package.json
@@ -2,7 +2,7 @@
"name": "fake-db",
"version": "1.0.0",
"scripts": {
- "start": "json-server --watch data.json --host 0.0.0.0 -p 8079"
+ "start": "json-server --watch data.json --middlewares ./report.js --host 0.0.0.0 -p 8079"
},
"dependencies": {
},
diff --git a/server/report.js b/server/report.js
new file mode 100644
index 0000000..2b237bc
--- /dev/null
+++ b/server/report.js
@@ -0,0 +1,44 @@
+module.exports = (req, res, next) => {
+ const isReportRequest = req.url.startsWith("/report") && req.method === "GET";
+
+ if (!isReportRequest) {
+ next();
+ return;
+ }
+
+ try {
+ const { startDate, endDate } = req.query;
+ delete require.cache[require.resolve("./data.json")];
+ const data = require("./data.json");
+
+ const filteredArticles = data.articles.filter((article) => {
+ const articleDate = new Date(article.publishDate);
+ return (
+ articleDate >= startDate && articleDate <= endDate
+ );
+ });
+ console.log(filteredArticles);
+
+ const articleComm = filteredArticles.map((article) => {
+ const commentsCount = data.comments.filter(
+ (comment) => comment.articleId === article.id
+ ).length;
+ const tag = data.tags.filter(
+ (tag) => tag.id === article.tagId
+ )[0].title;
+ const user = data.users.filter(
+ (user) => user.id === article.userId
+ )[0].nickname;
+ return { title: article.title, publishDate: article.publishDate,tagName:tag, userName:user, comments: commentsCount };
+ });
+
+ articleComm.sort((a, b) => b.publishDate - a.publishDate)
+
+ console.log(articleComm);
+
+ res.json(articleComm);
+ } catch (error) {
+ console.error("Error processing report: ", error);
+ res.status(500).json({ message: "Internal Server Error" });
+ }
+};