fix: fix main screen

This commit is contained in:
2025-12-11 22:33:57 +03:00
parent 0a5803765e
commit e5df83f4e3

View File

@@ -16,30 +16,45 @@ import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import ru.myitschool.work.R import ru.myitschool.work.R
import ru.myitschool.work.core.TestIds import ru.myitschool.work.core.TestIds
import ru.myitschool.work.ui.nav.MainScreenDestination
import ru.myitschool.work.data.repo.AuthRepository import ru.myitschool.work.data.repo.AuthRepository
import ru.myitschool.work.ui.nav.AuthScreenDestination import ru.myitschool.work.ui.nav.AuthScreenDestination
import ru.myitschool.work.ui.nav.BookScreenDestination
/*
По умолчанию скрытое текстовое поле с ошибкой (main_error).
Требования к компонентам:
В случае любой ошибки необходимо скрыть все элементы, кроме текстового поля с ошибкой и кнопки обновления данных.
Для получения данных необходимо использовать сетевой запрос /api/<CODE>/info.
При нажатии на кнопку для выхода, все сохранённые данные пользователя должны быть очищены, а приложение должно открыть экран авторизации.
При нажатии кнопки бронирования необходимо открыть экран бронирования.
При нажатии на кнопку обновления данных — необходимо повторно вызывать сетевой запрос для получения актуальных данных.
Список бронирований должен быть отсортирован в порядке увеличения даты (например, 5 января -> 6 января -> 9 января).
*/
@Composable @Composable
fun MainScreen( fun MainScreen(
@@ -48,19 +63,46 @@ fun MainScreen(
) { ) {
val state by viewModel.uiState.collectAsState() val state by viewModel.uiState.collectAsState()
/* Column(
По умолчанию скрытое текстовое поле с ошибкой (main_error). modifier = Modifier
.fillMaxSize()
.imePadding()
.padding(20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top
) {
Button(
modifier = Modifier
.fillMaxWidth()
.testTag(TestIds.Main.REFRESH_BUTTON),
onClick = { /* обновить данные */ }
) {
Text(stringResource(R.string.refresh))
}
Требования к компонентам: Spacer(modifier = Modifier.size(8.dp))
В случае любой ошибки необходимо скрыть все элементы, кроме текстового поля с ошибкой и кнопки обновления данных. when (state) {
Для получения данных необходимо использовать сетевой запрос /api/<CODE>/info. is MainState.Error -> {
При нажатии на кнопку для выхода, все сохранённые данные пользователя должны быть очищены, а приложение должно открыть экран авторизации. ГОТОВО Text(
При нажатии кнопки бронирования необходимо открыть экран бронирования. text = (state as MainState.Error).message,
При нажатии на кнопку обновления данных — необходимо повторно вызывать сетевой запрос для получения актуальных данных. color = MaterialTheme.colorScheme.error,
Список бронирований должен быть отсортирован в порядке увеличения даты (например, 5 января -> 6 января -> 9 января). textAlign = TextAlign.Center,
*/ modifier = Modifier.fillMaxWidth()
)
}
is MainState.Loading -> {
CircularProgressIndicator()
}
is MainState.Data -> {
MainContent(navController = navController)
}
}
}
}
@Composable
fun MainContent(navController: NavController) {
val bookings = listOf( val bookings = listOf(
Booking(date = "2025-12-01", place = "Аудитория 1"), Booking(date = "2025-12-01", place = "Аудитория 1"),
Booking(date = "2025-12-01", place = "Аудитория 2"), Booking(date = "2025-12-01", place = "Аудитория 2"),
@@ -72,23 +114,8 @@ fun MainScreen(
Booking(date = "2025-12-04", place = "Спортивный зал"), Booking(date = "2025-12-04", place = "Спортивный зал"),
) )
LaunchedEffect(Unit) {
viewModel.actionFlow.collect {
navController.navigate(MainScreenDestination)
}
}
Column( Column(
modifier = Modifier modifier = Modifier.fillMaxSize()
.fillMaxSize()
.imePadding()
.padding(
start = 20.dp,
top = 20.dp,
end = 20.dp,
bottom = 0.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top
) { ) {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -102,26 +129,20 @@ fun MainScreen(
modifier = Modifier modifier = Modifier
.size(60.dp) .size(60.dp)
.clip(CircleShape) .clip(CircleShape)
.testTag(TestIds.Main.PROFILE_IMAGE)
) )
Spacer(modifier = Modifier.size(16.dp)) Spacer(modifier = Modifier.size(16.dp))
Text( Text(
text = "Иванов Иван Иванович", text = "Иванов Иван Иванович",
style = MaterialTheme.typography.titleLarge, style = MaterialTheme.typography.titleLarge
modifier = Modifier
.testTag(TestIds.Main.PROFILE_NAME)
) )
} }
Spacer(modifier = Modifier.size(8.dp)) Spacer(modifier = Modifier.size(8.dp))
Button( Button(
modifier = Modifier modifier = Modifier.fillMaxWidth(),
.fillMaxWidth()
.testTag(TestIds.Main.LOGOUT_BUTTON),
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.error, containerColor = MaterialTheme.colorScheme.error
contentColor = MaterialTheme.colorScheme.onError
), ),
onClick = { onClick = {
AuthRepository.clearCode() AuthRepository.clearCode()
@@ -134,35 +155,14 @@ fun MainScreen(
Spacer(modifier = Modifier.size(8.dp)) Spacer(modifier = Modifier.size(8.dp))
Button( Button(
modifier = Modifier modifier = Modifier.fillMaxWidth(),
.fillMaxWidth() onClick = { navController.navigate(BookScreenDestination) }
.testTag(TestIds.Main.REFRESH_BUTTON),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary,
contentColor = MaterialTheme.colorScheme.onPrimary
),
onClick = {
},
) {
Text(stringResource(R.string.refresh))
}
Spacer(modifier = Modifier.size(8.dp))
Button(
modifier = Modifier
.fillMaxWidth()
.testTag(TestIds.Main.ADD_BUTTON),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF2E7D32),
contentColor = Color.White
),
onClick = {
},
) { ) {
Text(stringResource(R.string.book_new)) Text(stringResource(R.string.book_new))
} }
Spacer(modifier = Modifier.size(8.dp))
Scaffold( Scaffold(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) { paddingValues -> ) { paddingValues ->
@@ -189,11 +189,6 @@ fun MainScreen(
} }
} }
data class Booking(
val date: String,
val place: String
)
@Composable @Composable
fun BookCard( fun BookCard(
date: String, date: String,
@@ -201,16 +196,9 @@ fun BookCard(
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val formattedDate = remember(date) { val formattedDate = remember(date) {
try { runCatching {
val parts = date.split("-") java.time.LocalDate.parse(date).format(java.time.format.DateTimeFormatter.ofPattern("dd.MM.yyyy"))
if (parts.size == 3) { }.getOrElse { date }
"${parts[2]}.${parts[1]}.${parts[0]}"
} else {
date
}
} catch (_: Exception) {
date
}
} }
Card( Card(
@@ -243,4 +231,9 @@ fun BookCard(
) )
} }
} }
} }
data class Booking(
val date: String,
val place: String
)