This commit is contained in:
Екатерина Рогашова 2023-12-28 00:26:42 +04:00
parent 989a86b77c
commit 5e4ab376b5
18 changed files with 454 additions and 394 deletions

View File

@ -44,7 +44,8 @@ fun BottomBar(navController: NavHostController){
BottomBarScreen.House,
BottomBarScreen.Kpop,
BottomBarScreen.LessonEdit,
BottomBarScreen.LessonRecord
BottomBarScreen.LessonRecord,
BottomBarScreen.Report
)
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination=navBackStackEntry?.destination

View File

@ -30,9 +30,10 @@ import com.example.myapplication.ui.lesson.LessonList
import com.example.myapplication.ui.lesson.LessonListViewModel
import com.example.myapplication.ui.navigation.Screen
import com.example.myapplication.ui.user.CurrentUserViewModel
import com.example.myapplication.ui.user.ReportViewModel
@Composable
fun HomeNavGraph(navController: NavHostController, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory), lessonListViewModel: LessonListViewModel = viewModel(factory = AppViewModelProvider.Factory)){
fun HomeNavGraph(navController: NavHostController, currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory), lessonListViewModel: LessonListViewModel = viewModel(factory = AppViewModelProvider.Factory), reportViewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory)){
Column {
TopBar()
NavHost(
@ -47,7 +48,7 @@ fun HomeNavGraph(navController: NavHostController, currentUserViewModel: Current
composable(route = BottomBarScreen.Contemp.route) { Contemp() }
composable(route = BottomBarScreen.BrDance.route) { BrDance() }
composable(route = BottomBarScreen.Kpop.route) { Kpop() }
composable(route = BottomBarScreen.Report.route) { Report() }
composable(route = BottomBarScreen.Report.route) { Report(navController, Modifier, reportViewModel) }
composable(
BottomBarScreen.LessonEdit.route,
arguments = listOf(navArgument("id") { type = NavType.IntType })

View File

@ -342,38 +342,7 @@ fun Profile(navController: NavController, modifier: Modifier = Modifier, lessonL
.wrapContentHeight(align = Alignment.CenterVertically)
.clickable { openDialogUser = true })
}
// Box(
// modifier = Modifier
// .align(alignment = Alignment.TopStart)
// .offset(
// x = 0.dp,
// y = 300.dp
// )
// .requiredWidth(width = 200.dp)
// .requiredHeight(height = 44.dp)
// )
// {
// Box(
// modifier = Modifier
// .fillMaxWidth()
// .requiredWidth(width = 300.dp)
// .height(50.dp)
// .background(Color.Black),
// )
// Text(
// text = "Выйти",
// color = Color.White,
// textAlign = TextAlign.Center,
// style = TextStyle(
// fontSize = 17.sp,
// fontWeight = FontWeight.Bold
// ),
// modifier = Modifier
// .requiredWidth(width = 200.dp)
// .requiredHeight(height = 44.dp)
// .wrapContentHeight(align = Alignment.CenterVertically))
// //.clickable { navController.navigate(route = AuthScreen.Enter.route); getUser = null })
// }
}
}
item {
@ -416,20 +385,7 @@ fun Profile(navController: NavController, modifier: Modifier = Modifier, lessonL
.fillMaxWidth()
)
}
else{
Text(
text = "Отчет",
color = Color.Black,
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 24.sp,
fontWeight = FontWeight.Bold
),
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
)
}
}
}
}
@ -475,26 +431,6 @@ fun Profile(navController: NavController, modifier: Modifier = Modifier, lessonL
.requiredHeight(80.dp)
)
}
else{
Text(
text = "Получить отчет",
color = Color.Black,
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 17.sp,
fontWeight = FontWeight.Bold
),
modifier = Modifier
.requiredWidth(width = 343.dp)
.requiredHeight(height = 44.dp)
.wrapContentHeight(align = Alignment.CenterVertically)
.align(Alignment.Center)
.clickable(
onClick = {
navController.navigate("report")
})
)
}
}
if (getUser?.role == RoleEnum.User) {
Box(

View File

@ -12,32 +12,39 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.example.myapplication.ui.AppViewModelProvider
import com.example.myapplication.ui.user.ReportViewModel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
@Composable
fun Report() {
var startRecord by remember { mutableStateOf("") }
var endRecord by remember { mutableStateOf("") }
fun Report(navController: NavController, modifier: Modifier = Modifier, viewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
val reportPageUiState = viewModel.reportPageUiState
val coroutineScope = rememberCoroutineScope()
Column(
modifier = Modifier.padding(16.dp)
modifier = modifier.padding(16.dp)
) {
// Поле ввода для startRecord
TextField(
value = startRecord,
onValueChange = { startRecord = it },
label = { Text("Start Record") },
value = reportPageUiState.reportDetails.startRecord.toString(),
onValueChange = { viewModel.onUpdate(reportPageUiState.reportDetails.copy(startRecord = it.toIntOrNull() ?: 0)) },
label = { Text("От") },
modifier = Modifier.fillMaxWidth()
)
// Поле ввода для endRecord
TextField(
value = endRecord,
onValueChange = { endRecord = it },
label = { Text("End Record") },
value = reportPageUiState.reportDetails.endRecord.toString(),
onValueChange = { viewModel.onUpdate(reportPageUiState.reportDetails.copy(endRecord = it.toIntOrNull() ?: 0)) },
label = { Text("До") },
modifier = Modifier.fillMaxWidth()
)
@ -46,10 +53,22 @@ fun Report() {
// Кнопка "Сформировать"
Button(
onClick = {
coroutineScope.launch {
viewModel.getReport()
}
},
enabled = reportPageUiState.isEntryValid,
modifier = Modifier.align(Alignment.CenterHorizontally)
) {
Text(text = "Сформировать")
}
// Вывод занятий, у которых countRecords входит в диапазон startRecord и endRecord
val reportResultPageUiState = viewModel.reportResultPageUiState
for (report in reportResultPageUiState.resReport) {
if (report.countRecords in reportPageUiState.reportDetails.startRecord..reportPageUiState.reportDetails.endRecord) {
Text(text = "Занятие: ${report.time}, Количество оставшихся записей: ${report.countRecords}")
}
}
}
}

View File

@ -22,8 +22,8 @@ import retrofit2.http.Query
interface MyServerService {
@GET("report")
suspend fun getReport(
@Query("startDate") startRecord: Int,
@Query("endDate") endRecord: Int
@Query("startRecord") startRecord: Int,
@Query("endRecord") endRecord: Int
): List<ReportRemote>
@GET("days")
suspend fun getDays(): List<DayOfWeekRemote>

View File

@ -9,6 +9,7 @@ import androidx.paging.PagingSource
import com.example.myapplication.api.MyServerService
import com.example.myapplication.api.day.RestDayOfWeekRepository
import com.example.myapplication.api.direction.RestDirectionRepository
import com.example.myapplication.api.model.ReportRemote
import com.example.myapplication.api.model.toLesson
import com.example.myapplication.api.model.toLessonRemote
import com.example.myapplication.dataBase.AppContainer
@ -62,7 +63,12 @@ class RestLessonRepository(
}
override suspend fun deleteLesson(lesson: Lesson) {
service.deleteLesson(lesson.uid).toLesson()
lesson.uid.let { service.deleteLesson(it).toLesson() }
}
override suspend fun getReport(startRecord: Int, endRecord: Int):List<ReportRemote>
{
return service.getReport(startRecord,endRecord)
}
}

View File

@ -4,9 +4,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class ReportRemote(
val lessonName: String = "",
val lessonDay: String = "",
val lessonTime: String = "",
val countRecords: Int = 0,
val countFreeRecords: Int = 0
val time: String = "",
val teacher: String = "",
val countRecords: Int = 0
)

View File

@ -51,10 +51,7 @@ class RestUserRepository(
return existUsers.map { it.value }.sortedBy { it.uid }
}
override suspend fun getReport(startRecord: Int, endRecord: Int):List<ReportRemote>
{
return service.getReport(startRecord,endRecord)
}
override suspend fun getUserById(uid: Int?): User? =
uid?.let { service.getUserById(it).toUser() }

View File

@ -26,7 +26,7 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun remoteKeysDao(): RemoteKeysDao
companion object {
private const val DB_NAME: String = "bd111"
private const val DB_NAME: String = "bd1111"
@Volatile
private var INSTANCE: AppDatabase? = null

View File

@ -11,15 +11,15 @@ import androidx.room.PrimaryKey
entity = DayOfWeek::class,
parentColumns = ["uid"],
childColumns = ["day_id"],
onDelete = ForeignKey.RESTRICT,
onUpdate = ForeignKey.RESTRICT
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
),
ForeignKey(
entity = Direction::class,
parentColumns = ["uid"],
childColumns = ["direction_id"],
onDelete = ForeignKey.RESTRICT,
onUpdate = ForeignKey.RESTRICT
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
]
)

View File

@ -2,6 +2,7 @@ package com.example.myapplication.dataBase.repository
import androidx.paging.PagingData
import androidx.paging.PagingSource
import com.example.myapplication.api.model.ReportRemote
import com.example.myapplication.dataBase.model.Lesson
import kotlinx.coroutines.flow.Flow
@ -11,4 +12,5 @@ interface LessonRepository {
suspend fun deleteLesson(lesson: Lesson)
fun getAllLessons(): Flow<PagingData<Lesson>>
suspend fun getLesson(uid: Int): Lesson
suspend fun getReport(startRecord: Int, endRecord: Int):List<ReportRemote>
}

View File

@ -4,6 +4,7 @@ import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingSource
import com.example.myapplication.api.model.ReportRemote
import com.example.myapplication.dataBase.AppContainer
import com.example.myapplication.dataBase.dao.LessonDao
import com.example.myapplication.dataBase.model.Lesson
@ -24,7 +25,9 @@ class OfflineLessonRepository(private val lessonDao: LessonDao) : LessonReposito
override suspend fun deleteLesson(lesson: Lesson) = lessonDao.delete(lesson)
suspend fun clearLessons() = lessonDao.deleteAll()
override suspend fun getLesson(uid: Int): Lesson = lessonDao.getLessonByUid(uid).first()
override suspend fun getReport(startRecord: Int, endRecord: Int): List<ReportRemote> {
TODO("Not yet implemented")
}
suspend fun insertLessons(lessons: List<Lesson>) =
lessonDao.insert(*lessons.toTypedArray())
}

View File

@ -16,7 +16,5 @@ class OfflineUserRepository(private val userDao: UserDao) : UserRepository {
override suspend fun getUserById(uid: Int?): User = userDao.getUserById(uid).first()
override suspend fun getAllUsers(): List<User> = userDao.getAll()
override suspend fun getReport(startRecord: Int, endRecord: Int): List<ReportRemote> {
TODO("Not yet implemented")
}
}

View File

@ -10,5 +10,5 @@ interface UserRepository {
suspend fun deleteUser(user: User)
suspend fun getUserById(uid: Int?): User?
suspend fun getAllUsers(): List<User>
suspend fun getReport(startRecord: Int, endRecord: Int):List<ReportRemote>
}

View File

@ -13,6 +13,7 @@ import com.example.myapplication.ui.lesson.LessonListViewModel
import com.example.myapplication.ui.user.CurrentUserViewModel
import com.example.myapplication.ui.user.EntryViewModel
import com.example.myapplication.ui.user.RegisterViewModel
import com.example.myapplication.ui.user.ReportViewModel
object AppViewModelProvider {
val Factory = viewModelFactory {
@ -40,6 +41,9 @@ object AppViewModelProvider {
initializer {
CurrentUserViewModel(lessonApplication().container.userRestRepository)
}
initializer {
ReportViewModel(lessonApplication().container.lessonRestRepository)
}
}
}

View File

@ -142,6 +142,7 @@ fun LessonList(
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DismissBackground(dismissState: DismissState) {
@ -201,9 +202,21 @@ private fun LessonList(
lessonList: LazyPagingItems<Lesson>,
onClick: (id: Int) -> Unit,
onSwipe: (lesson: Lesson) -> Unit
) {
val refreshScope = rememberCoroutineScope()
var refreshing by remember { mutableStateOf(false) }
fun refresh() = refreshScope.launch {
refreshing = true
lessonList.refresh()
refreshing = false
}
val state = rememberPullRefreshState(refreshing, ::refresh)
Box(
modifier = modifier.pullRefresh(state)
) {
Column(
modifier = modifier
modifier = modifier.fillMaxSize()
) {
if (lessonList.itemSnapshotList.isEmpty()) {
Text(
@ -214,7 +227,11 @@ private fun LessonList(
} else {
val filteredLessons = lessonList.itemSnapshotList.filter { it?.dayOfWeekId == 1 }
if (filteredLessons.isNotEmpty()) {
Text(text = "Понедельник", style = TextStyle(fontSize = 24.sp), textAlign = TextAlign.Center)
Text(
text = "Понедельник",
style = TextStyle(fontSize = 20.sp),
textAlign = TextAlign.Center
)
}
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(items = filteredLessons, key = { it?.uid ?: "" }) { lesson ->
@ -240,8 +257,6 @@ private fun LessonList(
onClick = onClick
)
}
}
LaunchedEffect(show) {
if (!show) {
delay(800)
@ -251,11 +266,14 @@ private fun LessonList(
}
}
}
}
}
val filteredLessons1 = lessonList.itemSnapshotList.filter { it?.dayOfWeekId == 2 }
if (filteredLessons1.isNotEmpty()) {
Text(text = "Вторник", style = TextStyle(fontSize = 24.sp))
Text(text = "Вторник", style = TextStyle(fontSize = 20.sp))
}
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(items = filteredLessons1, key = { it?.uid ?: "" }) { lesson ->
@ -281,8 +299,6 @@ private fun LessonList(
onClick = onClick
)
}
}
LaunchedEffect(show) {
if (!show) {
delay(800)
@ -292,11 +308,14 @@ private fun LessonList(
}
}
}
}
}
val filteredLessons2 = lessonList.itemSnapshotList.filter { it?.dayOfWeekId == 3 }
if (filteredLessons2.isNotEmpty()) {
Text(text = "Среда", style = TextStyle(fontSize = 24.sp))
Text(text = "Среда", style = TextStyle(fontSize = 20.sp))
}
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(items = filteredLessons2, key = { it?.uid ?: "" }) { lesson ->
@ -322,8 +341,6 @@ private fun LessonList(
onClick = onClick
)
}
}
LaunchedEffect(show) {
if (!show) {
delay(800)
@ -333,11 +350,14 @@ private fun LessonList(
}
}
}
}
}
val filteredLessons3 = lessonList.itemSnapshotList.filter { it?.dayOfWeekId == 4 }
if (filteredLessons3.isNotEmpty()) {
Text(text = "Четверг", style = TextStyle(fontSize = 24.sp))
Text(text = "Четверг", style = TextStyle(fontSize = 20.sp))
}
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(items = filteredLessons3, key = { it?.uid ?: "" }) { lesson ->
@ -363,8 +383,6 @@ private fun LessonList(
onClick = onClick
)
}
}
LaunchedEffect(show) {
if (!show) {
delay(800)
@ -374,11 +392,14 @@ private fun LessonList(
}
}
}
}
}
val filteredLessons4 = lessonList.itemSnapshotList.filter { it?.dayOfWeekId == 5 }
if (filteredLessons4.isNotEmpty()) {
Text(text = "Пятница", style = TextStyle(fontSize = 24.sp))
Text(text = "Пятница", style = TextStyle(fontSize = 20.sp))
}
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(items = filteredLessons4, key = { it?.uid ?: "" }) { lesson ->
@ -404,8 +425,6 @@ private fun LessonList(
onClick = onClick
)
}
}
LaunchedEffect(show) {
if (!show) {
delay(800)
@ -415,11 +434,14 @@ private fun LessonList(
}
}
}
}
}
val filteredLessons5 = lessonList.itemSnapshotList.filter { it?.dayOfWeekId == 6 }
if (filteredLessons5.isNotEmpty()) {
Text(text = "Суббота", style = TextStyle(fontSize = 24.sp))
Text(text = "Суббота", style = TextStyle(fontSize = 20.sp))
}
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(items = filteredLessons5, key = { it?.uid ?: "" }) { lesson ->
@ -445,8 +467,6 @@ private fun LessonList(
onClick = onClick
)
}
}
LaunchedEffect(show) {
if (!show) {
delay(800)
@ -457,10 +477,11 @@ private fun LessonList(
}
}
}
}
val filteredLessons6 = lessonList.itemSnapshotList.filter { it?.dayOfWeekId == 7 }
if (filteredLessons6.isNotEmpty()) {
Text(text = "Воскресенье", style = TextStyle(fontSize = 24.sp))
Text(text = "Воскресенье", style = TextStyle(fontSize = 20.sp))
}
LazyColumn(modifier = Modifier.padding(all = 10.dp)) {
items(items = filteredLessons6, key = { it?.uid ?: "" }) { lesson ->
@ -486,8 +507,6 @@ private fun LessonList(
onClick = onClick
)
}
}
LaunchedEffect(show) {
if (!show) {
delay(800)
@ -497,6 +516,9 @@ private fun LessonList(
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,46 @@
package com.example.myapplication.ui.user
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.example.myapplication.api.model.ReportRemote
import com.example.myapplication.dataBase.repository.LessonRepository
import com.example.myapplication.dataBase.repository.UserRepository
class ReportViewModel(private val lessonRepository: LessonRepository) : 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) {
startRecord >=0
&& endRecord >=0
&& startRecord < endRecord
}
}
suspend fun getReport(){
val res = lessonRepository.getReport(reportPageUiState.reportDetails.startRecord, reportPageUiState.reportDetails.endRecord)
reportResultPageUiState = ReportResultPageUiState(res)
}
}
data class ReportDetails(
val startRecord: Int = 0,
val endRecord: Int = 0
)
data class ReportPageUiState(
val reportDetails: ReportDetails = ReportDetails(),
val isEntryValid: Boolean = false
)
data class ReportResultPageUiState(
var resReport:List<ReportRemote> = emptyList()
)

View File

@ -63,33 +63,60 @@
"classNumber": 2,
"dayOfWeekId": 1,
"directionId": 1,
"countRecord": 6
"countRecord": 5
},
{
"teacher": "Ирина",
"time": "11.00",
"classNumber": 7,
"dayOfWeekId": 4,
"directionId": 5,
"countRecord": 3,
"id": 4
},
{
"teacher": "Надежда",
"time": "15.00",
"classNumber": 1,
"dayOfWeekId": 4,
"directionId": 6,
"countRecord": 4,
"id": 5
},
{
"id": 3,
"teacher": "Мария",
"time": "17:00",
"classNumber": 3,
"dayOfWeekId": 2,
"directionId": 3,
"countRecord": 2
"time": "17.00",
"classNumber": 1,
"dayOfWeekId": 4,
"directionId": 1,
"countRecord": 7,
"id": 6
},
{
"id": 4,
"teacher": "Алла",
"time": "9:30",
"id": 7,
"teacher": "Назиля",
"time": "14.00",
"classNumber": 6,
"dayOfWeekId": 3,
"dayOfWeekId": 5,
"directionId": 3,
"countRecord": 4
"countRecord": 3
},
{
"teacher": "Алина",
"time": "10:00",
"classNumber": 5,
"dayOfWeekId": 2,
"directionId": 2,
"countRecord": 5,
"id": 8
}
],
"users": [
{
"id": 1,
"userName": "user1",
"fio": "Анна Викторовна Сомова",
"password": "1234",
"fio": "Анна Викторовна Мухина",
"role": "Admin",
"lessonId": null
},
@ -113,9 +140,9 @@
"id": 7,
"userName": "user77",
"password": "user7",
"fio": "user7",
"fio": "user77",
"role": "User",
"lessonId": null
"lessonId": 7
},
{
"id": 8,