Lab5 finish

This commit is contained in:
Kate 2024-01-08 22:36:11 +04:00
parent 053970541a
commit 7356ccb00b
10 changed files with 1 additions and 363 deletions

View File

@ -16,17 +16,10 @@ import retrofit2.http.Path
import retrofit2.http.Query import retrofit2.http.Query
import ru.ulstu.`is`.pmu.api.model.UserRemote import ru.ulstu.`is`.pmu.api.model.UserRemote
import ru.ulstu.`is`.pmu.api.model.PetRemote import ru.ulstu.`is`.pmu.api.model.PetRemote
import ru.ulstu.`is`.pmu.api.report.ReportRemote
interface MyServerService { interface MyServerService {
@GET("report")
suspend fun getReportInfo(
@Query("fromDate") fromDate: String,
@Query("toDate") toDate: String
): List<ReportRemote>
@GET("users") @GET("users")
suspend fun getUsers(): List<UserRemote> suspend fun getUsers(): List<UserRemote>

View File

@ -9,7 +9,6 @@ import kotlinx.coroutines.flow.Flow
import ru.ulstu.`is`.pmu.api.MyServerService import ru.ulstu.`is`.pmu.api.MyServerService
import ru.ulstu.`is`.pmu.api.model.toPet import ru.ulstu.`is`.pmu.api.model.toPet
import ru.ulstu.`is`.pmu.api.model.toPetRemote import ru.ulstu.`is`.pmu.api.model.toPetRemote
import ru.ulstu.`is`.pmu.api.report.ReportRemote
import ru.ulstu.`is`.pmu.api.user.RestUserRepository import ru.ulstu.`is`.pmu.api.user.RestUserRepository
import ru.ulstu.`is`.pmu.common.AppContainer import ru.ulstu.`is`.pmu.common.AppContainer
import ru.ulstu.`is`.pmu.common.PetRepository import ru.ulstu.`is`.pmu.common.PetRepository
@ -83,9 +82,5 @@ class RestPetRepository(
override suspend fun deletePet(pet: Pet) { override suspend fun deletePet(pet: Pet) {
service.deletePet(pet.uid).toPet() service.deletePet(pet.uid).toPet()
} }
suspend fun getReport(fromDate: String, toDate: String):List<ReportRemote>
{
return service.getReportInfo(fromDate,toDate)
}
} }

View File

@ -1,12 +0,0 @@
package ru.ulstu.`is`.pmu.api.report
import kotlinx.serialization.Serializable
@Serializable
data class ReportRemote(
val reportId: Int = 0,
val petid: Int = 0,
val petname: String = "",
val birthday: String = "",
val userid: Int = 0,
val login: String = ""
)

View File

@ -10,7 +10,6 @@ import ru.ulstu.`is`.pmu.ui.pet.edit.PetEditViewModel
import ru.ulstu.`is`.pmu.ui.pet.edit.UserDropDownViewModel import ru.ulstu.`is`.pmu.ui.pet.edit.UserDropDownViewModel
import ru.ulstu.`is`.pmu.ui.pet.list.PetListViewModel import ru.ulstu.`is`.pmu.ui.pet.list.PetListViewModel
import ru.ulstu.`is`.pmu.ui.pet.list.UserListViewModel import ru.ulstu.`is`.pmu.ui.pet.list.UserListViewModel
import ru.ulstu.`is`.pmu.ui.pet.report.ReportViewModel
object AppViewModelProvider { object AppViewModelProvider {
val Factory = viewModelFactory { val Factory = viewModelFactory {
@ -30,11 +29,6 @@ object AppViewModelProvider {
UserDropDownViewModel(petApplication().container.userRestRepository UserDropDownViewModel(petApplication().container.userRestRepository
) )
} }
initializer {
ReportViewModel(
petApplication().container.petRestRepository,
)
}
} }
} }

View File

@ -33,7 +33,6 @@ import ru.ulstu.`is`.pmu.ui.pet.edit.PetEdit
import ru.ulstu.`is`.pmu.ui.pet.list.PetList import ru.ulstu.`is`.pmu.ui.pet.list.PetList
import ru.ulstu.`is`.pmu.ui.pet.list.PetUserList import ru.ulstu.`is`.pmu.ui.pet.list.PetUserList
import ru.ulstu.`is`.pmu.ui.pet.list.UserList import ru.ulstu.`is`.pmu.ui.pet.list.UserList
import ru.ulstu.`is`.pmu.ui.pet.report.ReportPage
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -104,7 +103,6 @@ fun Navhost(
startDestination = Screen.PetList.route, startDestination = Screen.PetList.route,
modifier.padding(innerPadding) modifier.padding(innerPadding)
) { ) {
composable(Screen.Report.route) { ReportPage(navController = navController) }
composable(Screen.PetList.route) { PetList(navController) } composable(Screen.PetList.route) { PetList(navController) }
composable(Screen.UserList.route) { UserList(navController) } composable(Screen.UserList.route) { UserList(navController) }
composable( composable(

View File

@ -18,9 +18,6 @@ enum class Screen(
PetList( PetList(
"pet-list", R.string.list_pet, Icons.Filled.Home "pet-list", R.string.list_pet, Icons.Filled.Home
), ),
Report(
"report", R.string.report, Icons.Filled.Info
),
PetUserList( PetUserList(
"pet-user-list/{id}", R.string.list_pet, showInBottomBar = false "pet-user-list/{id}", R.string.list_pet, showInBottomBar = false
), ),
@ -35,7 +32,6 @@ enum class Screen(
val bottomBarItems = listOf( val bottomBarItems = listOf(
UserList, UserList,
PetList, PetList,
Report
) )
fun getItem(route: String): Screen? { fun getItem(route: String): Screen? {

View File

@ -1,197 +0,0 @@
package ru.ulstu.`is`.pmu.ui.pet.report
import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.graphics.Paint
import android.graphics.pdf.PdfDocument
import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import android.widget.CalendarView
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import ru.ulstu.`is`.pmu.R
import ru.ulstu.`is`.pmu.api.report.ReportRemote
import ru.ulstu.`is`.pmu.common.AppViewModelProvider
import java.io.IOException
import java.io.OutputStream
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ReportPage (navController: NavController?, viewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory))
{
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
val reportResultPageState = viewModel.reportResultPageUiState
// Здесь вы можете определить startDate и endDate
val startDate = viewModel.reportPageUiState.reportDetails.startDate
val endDate = viewModel.reportPageUiState.reportDetails.endDate
Column(
modifier = Modifier
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
)
{
Text(
text = stringResource(id = R.string.startDate),
style = MaterialTheme.typography.headlineLarge
)
CustomCalendarView(selectedDate = startDate) { selectedDate ->
viewModel.onUpdate(viewModel.reportPageUiState.reportDetails.copy(startDate = selectedDate))
}
Text(
text = stringResource(id = R.string.endDate),
style = MaterialTheme.typography.headlineLarge
)
CustomCalendarView(selectedDate = endDate) { selectedDate ->
viewModel.onUpdate(viewModel.reportPageUiState.reportDetails.copy(endDate = selectedDate))
}
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {coroutineScope.launch { viewModel.getReport()} },
enabled = viewModel.reportPageUiState.isEntryValid,
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp)
.border(4.dp, MaterialTheme.colorScheme.onPrimary, shape = RoundedCornerShape(10.dp)),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary)
) {
Text("Сформировать отчет")
}
Spacer(modifier = Modifier.height(32.dp))
Text(
text = "Результат",
style = MaterialTheme.typography.headlineLarge
)
TableScreen(reportData = reportResultPageState.resReport)
Spacer(modifier = Modifier.height(16.dp))
}
}
@Composable
fun CustomCalendarView(
selectedDate: Date,
onDateSelected: (Date) -> Unit
) {
AndroidView(
modifier = Modifier.wrapContentSize(),
factory = { context ->
CalendarView(context).apply {
// Настройка CalendarView
val calendar = Calendar.getInstance()
calendar.time = selectedDate
// Установка начальной выбранной даты
date = calendar.timeInMillis
setOnDateChangeListener { _, year, month, dayOfMonth ->
calendar.set(Calendar.YEAR, year)
calendar.set(Calendar.MONTH, month)
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
val newSelectedDate = calendar.time
// Установка новой выбранной даты
date = calendar.timeInMillis
// Вызов колбэка для передачи выбранной даты в родительский компонент
onDateSelected(newSelectedDate)
}
}
}
)
}
@Composable
fun RowScope.TableCell(
text: String,
weight: Float
) {
Text(
text = text,
Modifier
.border(1.dp, Color.Black)
.weight(weight)
.padding(8.dp)
)
}
@Composable
fun TableScreen(reportData: List<ReportRemote>) {
Column(
Modifier
.padding(16.dp)) {
Row(Modifier.background(Color.White)) {
TableCell(text = "", weight = 1f)
TableCell(text = "Id питомца", weight = 1f)
TableCell(text = "Имя", weight = 1f)
TableCell(text = "Д/р", weight = 1f)
TableCell(text = "Id хозяина", weight = 1f)
TableCell(text = "Логин", weight = 1f)
}
// Here are all the lines of your table.
reportData.forEach {
val (reportId, petid, petname, birthday, userid, login) = it
Row(Modifier.fillMaxWidth()) {
TableCell(text = reportId.toString(), weight = 1f)
TableCell(text = petid.toString(), weight = 1f)
TableCell(text = petname, weight = 1f)
TableCell(text = birthday, weight = 1f)
TableCell(text = userid.toString(), weight = 1f)
TableCell(text = login, weight = 1f)
}
}
}
}

View File

@ -1,53 +0,0 @@
package ru.ulstu.`is`.pmu.ui.pet.report
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import ru.ulstu.`is`.pmu.api.pet.RestPetRepository
import ru.ulstu.`is`.pmu.api.report.ReportRemote
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
class ReportViewModel(private val restPetRepository: RestPetRepository): 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 != Date(0) && endDate != Date(0) && startDate < endDate
}
}
suspend fun getReport() {
val startDateQueryParam = SimpleDateFormat("dd.MM.yyyy").format(reportPageUiState.reportDetails.startDate)
val endDateQueryParam = SimpleDateFormat("dd.MM.yyyy").format(reportPageUiState.reportDetails.endDate)
// Вызов репозитория с отформатированными датами
val res = restPetRepository.getReport(startDateQueryParam, endDateQueryParam)
reportResultPageUiState = ReportResultPageUiState(res)
}
}
data class ReportDetails(
val startDate: Date = Calendar.getInstance().time,
val endDate: Date = Calendar.getInstance().time
)
data class ReportPageUiState(
val reportDetails: ReportDetails = ReportDetails(),
val isEntryValid: Boolean = false
)
data class ReportResultPageUiState(
var resReport: List<ReportRemote> = emptyList()
)

View File

@ -2,7 +2,7 @@
"name": "fake-db", "name": "fake-db",
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
"start": "json-server --watch data.json --middlewares ./router.js --host 0.0.0.0 -p 8079" "start": "json-server --watch data.json --host 0.0.0.0 -p 8079"
}, },
"dependencies": { "dependencies": {
"pdfkit": "^0.14.0" "pdfkit": "^0.14.0"

View File

@ -1,76 +0,0 @@
const fs = require('fs');
const path = require('path');
module.exports = (req, res, next) => {
const data = JSON.parse(fs.readFileSync(path.join(__dirname, 'data.json'), 'utf8'));
if (req.url.startsWith('/search') && req.method === 'GET') {
try {
const searchText = req.query.name;
const searched = data.pets.filter(
(pet) =>
pet.name.toLowerCase().includes(searchText.toLowerCase())
);
return res.json(searched);
} catch (error) {
console.error('Error loading data:', error);
res.status(500).json({ message: 'Internal Server Error' });
}
} else if (req.url.startsWith('/report') && req.method === 'GET') {
try {
// Добавляем фильтрацию по дате рождения
const fromDate = req.query.fromDate;
const toDate = req.query.toDate;
const filteredData = filterByBirthday(data.pets, fromDate, toDate);
// Возвращаем отфильтрованные данные в формате отчета
const reportData = generateReport(filteredData);
res.json(reportData);
} catch (error) {
console.error('Error loading data:', error);
return res.status(500).json({ message: 'Internal Server Error' });
}
} else {
next();
}
};
// Функция generateReport для создания отчета с id
function generateReport(pets) {
return pets.map((pet, index) => ({
reportId: index + 1, // Уникальный id отчета (можете использовать другую логику)
petid: pet.id,
petname: pet.name,
birthday: pet.birthday,
userid: pet.userId,
login: getUserLogin(pet.userId)
}));
}
// Функция для фильтрации по дате рождения
function filterByBirthday(pets, fromDate, toDate) {
if (!fromDate && !toDate) {
return pets;
}
const filteredPets = pets.filter((pet) => {
const petBirthday = parseDate(pet.birthday);
return (!fromDate || petBirthday >= parseDate(fromDate)) &&
(!toDate || petBirthday <= parseDate(toDate));
});
return filteredPets;
}
// Функция для парсинга даты из строки в формате "dd.MM.yyyy"
function parseDate(dateString) {
const [day, month, year] = dateString.split('.').map(Number);
return new Date(year, month - 1, day);
}
// Функция для получения логина пользователя по userId
function getUserLogin(userId) {
const data = JSON.parse(fs.readFileSync(path.join(__dirname, 'data.json'), 'utf8'));
const user = data.users.find((user) => user.id === userId);
return user ? user.login : 'Unknown';
}