coursework complete
This commit is contained in:
parent
9b7acce5b6
commit
00169e7020
@ -12,6 +12,6 @@
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2023-10-27T17:41:35.449717700Z" />
|
||||
<timeTargetWasSelectedWithDropDown value="2023-12-26T09:35:26.870656500Z" />
|
||||
</component>
|
||||
</project>
|
@ -1,9 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<ReportRemote>
|
||||
@GET("users")
|
||||
suspend fun getUsers(): List<UserRemote>
|
||||
@GET("tags")
|
||||
|
@ -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
|
||||
)
|
@ -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<ReportRemote>
|
||||
{
|
||||
return service.getReport(startDate,endDate)
|
||||
}
|
||||
|
||||
override suspend fun updateUser(user: User) {
|
||||
user.id?.let { service.updateUser(it, user.toUserRemote()).toUser() }
|
||||
}
|
||||
|
@ -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
|
||||
)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Comment> = userDao.getUserComms(idUser)
|
||||
override suspend fun getUserArticles(idUser: Int): List<Article> = userDao.getUserArticles(idUser)
|
||||
override suspend fun getUserTags(idUser: Int): List<Tag> = userDao.getUserTags(idUser)
|
||||
override suspend fun getReport(startDate: Long, endDate: Long): List<ReportRemote> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
@ -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<Comment>
|
||||
suspend fun getUserArticles(idUser: Int): List<Article>
|
||||
suspend fun getUserTags(idUser: Int): List<Tag>
|
||||
suspend fun getReport(startDate: Long, endDate: Long):List<ReportRemote>
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<ReportRemote>) {
|
||||
|
||||
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()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@ class ArticlePageScreenViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var userList by mutableStateOf<List<User>>(emptyList())
|
||||
fun setUserList() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
|
@ -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<ReportRemote> = emptyList()
|
||||
)
|
225
server/data.json
Normal file
225
server/data.json
Normal file
@ -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
|
||||
}
|
||||
]
|
||||
}
|
@ -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": {
|
||||
},
|
||||
|
44
server/report.js
Normal file
44
server/report.js
Normal file
@ -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" });
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user