diff --git a/app/src/main/java/ru/ulstu/is/pmu/api/MyServerService.kt b/app/src/main/java/ru/ulstu/is/pmu/api/MyServerService.kt index f1e7671..187752d 100644 --- a/app/src/main/java/ru/ulstu/is/pmu/api/MyServerService.kt +++ b/app/src/main/java/ru/ulstu/is/pmu/api/MyServerService.kt @@ -16,17 +16,10 @@ import retrofit2.http.Path import retrofit2.http.Query import ru.ulstu.`is`.pmu.api.model.UserRemote import ru.ulstu.`is`.pmu.api.model.PetRemote -import ru.ulstu.`is`.pmu.api.report.ReportRemote interface MyServerService { - @GET("report") - suspend fun getReportInfo( - @Query("fromDate") fromDate: String, - @Query("toDate") toDate: String - ): List - @GET("users") suspend fun getUsers(): List diff --git a/app/src/main/java/ru/ulstu/is/pmu/api/pet/RestPetRepository.kt b/app/src/main/java/ru/ulstu/is/pmu/api/pet/RestPetRepository.kt index c3ba137..5271edd 100644 --- a/app/src/main/java/ru/ulstu/is/pmu/api/pet/RestPetRepository.kt +++ b/app/src/main/java/ru/ulstu/is/pmu/api/pet/RestPetRepository.kt @@ -9,7 +9,6 @@ import kotlinx.coroutines.flow.Flow import ru.ulstu.`is`.pmu.api.MyServerService import ru.ulstu.`is`.pmu.api.model.toPet 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.common.AppContainer import ru.ulstu.`is`.pmu.common.PetRepository @@ -83,9 +82,5 @@ class RestPetRepository( override suspend fun deletePet(pet: Pet) { service.deletePet(pet.uid).toPet() } - suspend fun getReport(fromDate: String, toDate: String):List - { - return service.getReportInfo(fromDate,toDate) - } } \ No newline at end of file diff --git a/app/src/main/java/ru/ulstu/is/pmu/api/report/ReportRemote.kt b/app/src/main/java/ru/ulstu/is/pmu/api/report/ReportRemote.kt deleted file mode 100644 index 88fa7fe..0000000 --- a/app/src/main/java/ru/ulstu/is/pmu/api/report/ReportRemote.kt +++ /dev/null @@ -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 = "" -) \ No newline at end of file diff --git a/app/src/main/java/ru/ulstu/is/pmu/common/AppViewModelProvider.kt b/app/src/main/java/ru/ulstu/is/pmu/common/AppViewModelProvider.kt index 1ab1298..10458de 100644 --- a/app/src/main/java/ru/ulstu/is/pmu/common/AppViewModelProvider.kt +++ b/app/src/main/java/ru/ulstu/is/pmu/common/AppViewModelProvider.kt @@ -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.list.PetListViewModel import ru.ulstu.`is`.pmu.ui.pet.list.UserListViewModel -import ru.ulstu.`is`.pmu.ui.pet.report.ReportViewModel object AppViewModelProvider { val Factory = viewModelFactory { @@ -30,11 +29,6 @@ object AppViewModelProvider { UserDropDownViewModel(petApplication().container.userRestRepository ) } - initializer { - ReportViewModel( - petApplication().container.petRestRepository, - ) - } } } diff --git a/app/src/main/java/ru/ulstu/is/pmu/ui/navigation/MainNavbar.kt b/app/src/main/java/ru/ulstu/is/pmu/ui/navigation/MainNavbar.kt index 409c0de..a25c9b4 100644 --- a/app/src/main/java/ru/ulstu/is/pmu/ui/navigation/MainNavbar.kt +++ b/app/src/main/java/ru/ulstu/is/pmu/ui/navigation/MainNavbar.kt @@ -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.PetUserList import ru.ulstu.`is`.pmu.ui.pet.list.UserList -import ru.ulstu.`is`.pmu.ui.pet.report.ReportPage @OptIn(ExperimentalMaterial3Api::class) @@ -104,7 +103,6 @@ fun Navhost( startDestination = Screen.PetList.route, modifier.padding(innerPadding) ) { - composable(Screen.Report.route) { ReportPage(navController = navController) } composable(Screen.PetList.route) { PetList(navController) } composable(Screen.UserList.route) { UserList(navController) } composable( diff --git a/app/src/main/java/ru/ulstu/is/pmu/ui/navigation/Screen.kt b/app/src/main/java/ru/ulstu/is/pmu/ui/navigation/Screen.kt index 6a86f1e..1aa0eb5 100644 --- a/app/src/main/java/ru/ulstu/is/pmu/ui/navigation/Screen.kt +++ b/app/src/main/java/ru/ulstu/is/pmu/ui/navigation/Screen.kt @@ -18,9 +18,6 @@ enum class Screen( PetList( "pet-list", R.string.list_pet, Icons.Filled.Home ), - Report( - "report", R.string.report, Icons.Filled.Info - ), PetUserList( "pet-user-list/{id}", R.string.list_pet, showInBottomBar = false ), @@ -35,7 +32,6 @@ enum class Screen( val bottomBarItems = listOf( UserList, PetList, - Report ) fun getItem(route: String): Screen? { diff --git a/app/src/main/java/ru/ulstu/is/pmu/ui/pet/report/ReportPage.kt b/app/src/main/java/ru/ulstu/is/pmu/ui/pet/report/ReportPage.kt deleted file mode 100644 index 65d59e5..0000000 --- a/app/src/main/java/ru/ulstu/is/pmu/ui/pet/report/ReportPage.kt +++ /dev/null @@ -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) { - 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) - - } - } - } -} - diff --git a/app/src/main/java/ru/ulstu/is/pmu/ui/pet/report/ReportViewModel.kt b/app/src/main/java/ru/ulstu/is/pmu/ui/pet/report/ReportViewModel.kt deleted file mode 100644 index 1385786..0000000 --- a/app/src/main/java/ru/ulstu/is/pmu/ui/pet/report/ReportViewModel.kt +++ /dev/null @@ -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 = emptyList() -) \ No newline at end of file diff --git a/server/package.json b/server/package.json index d4cd6c0..866afbe 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 --middlewares ./router.js --host 0.0.0.0 -p 8079" + "start": "json-server --watch data.json --host 0.0.0.0 -p 8079" }, "dependencies": { "pdfkit": "^0.14.0" diff --git a/server/router.js b/server/router.js deleted file mode 100644 index b14c2ac..0000000 --- a/server/router.js +++ /dev/null @@ -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'; -}