forked from Olympic/NTO-2025-Android-TeamTask
Compare commits
2 Commits
beb48ab41e
...
40a8428a19
| Author | SHA1 | Date | |
|---|---|---|---|
| 40a8428a19 | |||
| 9e603f87e6 |
@@ -1,4 +1,4 @@
|
|||||||
# НТО 2025. II отборочный этап. Командные задания — Android
|
# НТО 2025. II отборочный этап. Командные задания — Android
|
||||||
|
|
||||||
## 📖 Предыстория
|
## 📖 Предыстория
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package ru.myitschool.work.data.repo
|
package ru.myitschool.work.data.repo
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.datastore.preferences.preferencesDataStore
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class RootActivity : ComponentActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
|
actionBar?.hide()
|
||||||
setContent {
|
setContent {
|
||||||
WorkTheme {
|
WorkTheme {
|
||||||
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package ru.myitschool.work.ui.screen.auth
|
|||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@@ -9,7 +10,9 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -20,11 +23,14 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
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 io.ktor.websocket.Frame
|
||||||
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.ui.nav.MainScreenDestination
|
||||||
@@ -50,8 +56,20 @@ fun AuthScreen(
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(all = 24.dp),
|
.padding(all = 24.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Top
|
||||||
) {
|
) {
|
||||||
|
Spacer(modifier = Modifier.size(48.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.auth_name),
|
||||||
|
style = MaterialTheme.typography.displaySmall.copy(
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.size(48.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.auth_title),
|
text = stringResource(R.string.auth_title),
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
@@ -60,7 +78,7 @@ fun AuthScreen(
|
|||||||
when (val currentState = state) {
|
when (val currentState = state) {
|
||||||
is AuthState.Data -> Content(viewModel, currentState)
|
is AuthState.Data -> Content(viewModel, currentState)
|
||||||
is AuthState.Loading -> {
|
is AuthState.Loading -> {
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
Spacer(modifier = Modifier.size(24.dp))
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
modifier = Modifier.size(64.dp)
|
modifier = Modifier.size(64.dp)
|
||||||
)
|
)
|
||||||
@@ -76,28 +94,31 @@ private fun Content(
|
|||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Auth.CODE_INPUT)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
value = state.code,
|
||||||
|
onValueChange = { viewModel.onIntent(AuthIntent.TextInput(it)) },
|
||||||
|
label = { Text(stringResource(R.string.auth_label)) },
|
||||||
|
placeholder = { Text("Введите код сотрудника") }
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
|
||||||
if (state.isErrorVisible) {
|
if (state.isErrorVisible) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.testTag(TestIds.Auth.ERROR),
|
.testTag(TestIds.Auth.ERROR),
|
||||||
text = "Неверный код или ошибка сервера",
|
text = "Неверный код или ошибка сервера",
|
||||||
color = Color.Red,
|
color = MaterialTheme.colorScheme.error,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(8.dp))
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
TextField(
|
|
||||||
modifier = Modifier
|
|
||||||
.testTag(TestIds.Auth.CODE_INPUT)
|
|
||||||
.fillMaxWidth(),
|
|
||||||
value = state.code,
|
|
||||||
onValueChange = { viewModel.onIntent(AuthIntent.TextInput(it)) },
|
|
||||||
label = { Text(stringResource(R.string.auth_label)) }
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
@@ -109,6 +130,16 @@ private fun Content(
|
|||||||
},
|
},
|
||||||
enabled = state.isButtonEnabled
|
enabled = state.isButtonEnabled
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.auth_sign_in))
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.auth_sign_in))
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_arrow_right),
|
||||||
|
contentDescription = "Войти"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import androidx.compose.foundation.selection.selectable
|
|||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.RadioButton
|
import androidx.compose.material3.RadioButton
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
@@ -27,9 +28,12 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
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 ru.myitschool.work.R
|
||||||
import ru.myitschool.work.core.TestIds
|
import ru.myitschool.work.core.TestIds
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -112,14 +116,34 @@ private fun BookErrorContent(
|
|||||||
modifier = Modifier.testTag(TestIds.Book.REFRESH_BUTTON),
|
modifier = Modifier.testTag(TestIds.Book.REFRESH_BUTTON),
|
||||||
onClick = onRefresh
|
onClick = onRefresh
|
||||||
) {
|
) {
|
||||||
Text("Обновить")
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.main_screen_refresh))
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_refresh),
|
||||||
|
contentDescription = "Обновить"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.size(8.dp))
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON),
|
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON),
|
||||||
onClick = onBack
|
onClick = onBack
|
||||||
) {
|
) {
|
||||||
Text("Назад")
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_back),
|
||||||
|
contentDescription = "Назад"
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Text(text = stringResource(R.string.book_screen_back))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,14 +169,34 @@ private fun BookEmptyContent(
|
|||||||
modifier = Modifier.testTag(TestIds.Book.REFRESH_BUTTON),
|
modifier = Modifier.testTag(TestIds.Book.REFRESH_BUTTON),
|
||||||
onClick = onRefresh
|
onClick = onRefresh
|
||||||
) {
|
) {
|
||||||
Text("Обновить")
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.main_screen_refresh))
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_refresh),
|
||||||
|
contentDescription = "Обновить"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.size(8.dp))
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON),
|
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON),
|
||||||
onClick = onBack
|
onClick = onBack
|
||||||
) {
|
) {
|
||||||
Text("Назад")
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_back),
|
||||||
|
contentDescription = "Назад"
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Text(text = stringResource(R.string.book_screen_back))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,19 +223,39 @@ private fun BookDataContent(
|
|||||||
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON),
|
modifier = Modifier.testTag(TestIds.Book.BACK_BUTTON),
|
||||||
onClick = onBack
|
onClick = onBack
|
||||||
) {
|
) {
|
||||||
Text("Назад")
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_back),
|
||||||
|
contentDescription = "Назад"
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Text(text = stringResource(R.string.book_screen_back))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier.testTag(TestIds.Book.REFRESH_BUTTON),
|
modifier = Modifier.testTag(TestIds.Book.REFRESH_BUTTON),
|
||||||
onClick = onRefresh
|
onClick = onRefresh
|
||||||
) {
|
) {
|
||||||
Text("Обновить")
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.main_screen_refresh))
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_refresh),
|
||||||
|
contentDescription = "Обновить"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
// Вкладки с датами
|
|
||||||
LazyRow(
|
LazyRow(
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
@@ -214,7 +278,7 @@ private fun BookDataContent(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
// Список мест
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
@@ -262,7 +326,17 @@ private fun BookDataContent(
|
|||||||
onClick = onBook,
|
onClick = onBook,
|
||||||
enabled = state.places.any { it.isSelected }
|
enabled = state.places.any { it.isSelected }
|
||||||
) {
|
) {
|
||||||
Text("Забронировать")
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.book_screen_book))
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_arrow_right),
|
||||||
|
contentDescription = "Забронировать"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,12 @@ import androidx.compose.foundation.shape.CircleShape
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Person
|
import androidx.compose.material.icons.filled.Person
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.SegmentedButtonDefaults.Icon
|
import androidx.compose.material3.SegmentedButtonDefaults.Icon
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -28,12 +30,19 @@ import androidx.compose.runtime.getValue
|
|||||||
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.colorResource
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
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.SubcomposeAsyncImage
|
import coil3.compose.SubcomposeAsyncImage
|
||||||
|
import org.intellij.lang.annotations.JdkConstants
|
||||||
|
import ru.myitschool.work.R
|
||||||
import ru.myitschool.work.core.TestIds
|
import ru.myitschool.work.core.TestIds
|
||||||
import ru.myitschool.work.ui.nav.AuthScreenDestination
|
import ru.myitschool.work.ui.nav.AuthScreenDestination
|
||||||
import ru.myitschool.work.ui.nav.BookScreenDestination
|
import ru.myitschool.work.ui.nav.BookScreenDestination
|
||||||
@@ -130,6 +139,8 @@ private fun MainDataContent(
|
|||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
@@ -147,38 +158,47 @@ private fun MainDataContent(
|
|||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.testTag(TestIds.Main.PROFILE_NAME),
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Main.PROFILE_NAME)
|
||||||
|
.weight(1f),
|
||||||
text = state.name,
|
text = state.name,
|
||||||
style = MaterialTheme.typography.titleMedium
|
style = MaterialTheme.typography.titleMedium
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Main.LOGOUT_BUTTON),
|
||||||
|
onClick = onLogout,
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
contentColor = MaterialTheme.colorScheme.errorContainer,
|
||||||
|
containerColor = MaterialTheme.colorScheme.onErrorContainer
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
) {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text("Выход")
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_logout),
|
||||||
|
contentDescription = "Выйти"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
Spacer(modifier = Modifier.size(24.dp))
|
||||||
|
|
||||||
Row(
|
Text(
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
text = stringResource(R.string.main_screen_title),
|
||||||
) {
|
style = MaterialTheme.typography.titleLarge.copy(
|
||||||
Button(
|
fontWeight = FontWeight.Bold
|
||||||
modifier = Modifier.testTag(TestIds.Main.LOGOUT_BUTTON),
|
)
|
||||||
onClick = onLogout
|
)
|
||||||
) {
|
|
||||||
Text("Выход")
|
|
||||||
}
|
|
||||||
Button(
|
|
||||||
modifier = Modifier.testTag(TestIds.Main.REFRESH_BUTTON),
|
|
||||||
onClick = onRefresh
|
|
||||||
) {
|
|
||||||
Text("Обновить")
|
|
||||||
}
|
|
||||||
Button(
|
|
||||||
modifier = Modifier.testTag(TestIds.Main.ADD_BUTTON),
|
|
||||||
onClick = onAddBooking
|
|
||||||
) {
|
|
||||||
Text("Бронь")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
Spacer(modifier = Modifier.size(20.dp))
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
@@ -192,20 +212,85 @@ private fun MainDataContent(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(12.dp)
|
modifier = Modifier.padding(12.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Row(modifier = Modifier.fillMaxWidth(),
|
||||||
modifier = Modifier.testTag(TestIds.Main.ITEM_DATE),
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.main_screen_date),
|
||||||
|
style = MaterialTheme.typography.bodyLarge.copy(
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.testTag(TestIds.Main.ITEM_DATE),
|
||||||
text = item.dateLabel,
|
text = item.dateLabel,
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyLarge.copy(
|
||||||
)
|
fontWeight = FontWeight.Bold
|
||||||
Text(
|
)
|
||||||
modifier = Modifier.testTag(TestIds.Main.ITEM_PLACE),
|
)
|
||||||
text = item.roomName,
|
}
|
||||||
style = MaterialTheme.typography.bodySmall
|
Row(
|
||||||
)
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.main_screen_place),
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.testTag(TestIds.Main.ITEM_PLACE),
|
||||||
|
text = item.roomName,
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
modifier = Modifier.testTag(TestIds.Main.REFRESH_BUTTON),
|
||||||
|
onClick = onRefresh
|
||||||
|
) { Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.main_screen_refresh))
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_refresh),
|
||||||
|
contentDescription = "Обновить"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
modifier = Modifier.testTag(TestIds.Main.ADD_BUTTON),
|
||||||
|
onClick = onAddBooking
|
||||||
|
) { Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.main_screen_new_book))
|
||||||
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_add),
|
||||||
|
contentDescription = "Новая бронь"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -32,26 +32,26 @@ private val LightColorScheme = lightColorScheme(
|
|||||||
*/
|
*/
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun WorkTheme(
|
fun WorkTheme(
|
||||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||||
// Dynamic color is available on Android 12+
|
// Dynamic color is available on Android 12+
|
||||||
dynamicColor: Boolean = true,
|
dynamicColor: Boolean = true,
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
val colorScheme = when {
|
val colorScheme = when {
|
||||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
darkTheme -> DarkColorScheme
|
||||||
|
else -> LightColorScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
darkTheme -> DarkColorScheme
|
MaterialTheme(
|
||||||
else -> LightColorScheme
|
colorScheme = colorScheme,
|
||||||
|
typography = Typography,
|
||||||
|
content = content
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialTheme(
|
|
||||||
colorScheme = colorScheme,
|
|
||||||
typography = Typography,
|
|
||||||
content = content
|
|
||||||
)
|
|
||||||
}
|
|
||||||
14
app/src/main/res/drawable/ic_add.xml
Normal file
14
app/src/main/res/drawable/ic_add.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="16dp"
|
||||||
|
android:height="16dp"
|
||||||
|
android:viewportWidth="16"
|
||||||
|
android:viewportHeight="16">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M0.5,8.5v-1h15v1Z"
|
||||||
|
android:fillType="evenOdd"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M8.5,15.5h-1V0.5h1Z"
|
||||||
|
android:fillType="evenOdd"/>
|
||||||
|
</vector>
|
||||||
5
app/src/main/res/drawable/ic_arrow_right.xml
Normal file
5
app/src/main/res/drawable/ic_arrow_right.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="16dp" android:viewportHeight="24" android:viewportWidth="24" android:width="16dp">
|
||||||
|
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M11.293,4.707l6.293,6.293l-13.586,0l0,2l13.586,0l-6.293,6.293l1.414,1.414l8.707,-8.707l-8.707,-8.707l-1.414,1.414z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
9
app/src/main/res/drawable/ic_back.xml
Normal file
9
app/src/main/res/drawable/ic_back.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="16dp"
|
||||||
|
android:height="16dp"
|
||||||
|
android:viewportWidth="16"
|
||||||
|
android:viewportHeight="16">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M11.62,3.81l-4.19,4.19l4.19,4.19l-1.53,1.52l-5.71,-5.71l5.71,-5.71l1.53,1.52z"/>
|
||||||
|
</vector>
|
||||||
9
app/src/main/res/drawable/ic_logout.xml
Normal file
9
app/src/main/res/drawable/ic_logout.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="16dp" android:viewportHeight="32" android:viewportWidth="32" android:width="16dp">
|
||||||
|
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M27.9,2.58a0.86,0.86 0,0 0,-0.07 -0.1,0.71 0.71,0 0,0 -0.19,-0.23l0,0 -0.09,0a1.12,1.12 0,0 0,-0.25 -0.11L27.1,2 27,2H12a1,1 0,0 0,-1 1V9a1,1 0,0 0,2 0V4h7.19L16.71,5A1,1 0,0 0,16 6V25H13V22a1,1 0,0 0,-2 0v4a1,1 0,0 0,1 1h4v2a1,1 0,0 0,0.4 0.8,1 1,0 0,0 0.6,0.2 1,1 0,0 0,0.29 0l10,-3A1,1 0,0 0,28 26V3A1,1 0,0 0,27.9 2.58ZM26,25.26l-8,2.4V6.74l8,-2.4Z"/>
|
||||||
|
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M7.41,17H14a1,1 0,0 0,0 -2H7.41l1.3,-1.29a1,1 0,0 0,-1.42 -1.42l-3,3a1,1 0,0 0,-0.21 0.33,1 1,0 0,0 0,0.76 1,1 0,0 0,0.21 0.33l3,3a1,1 0,0 0,1.42 0,1 1,0 0,0 0,-1.42Z"/>
|
||||||
|
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M20,17a1,1 0,0 0,0 -2h0a1,1 0,1 0,0 2Z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
5
app/src/main/res/drawable/ic_refresh.xml
Normal file
5
app/src/main/res/drawable/ic_refresh.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="16dp" android:viewportHeight="24" android:viewportWidth="24" android:width="16dp">
|
||||||
|
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M12,3A8.959,8.959 0,0 0,5 6.339V4H3v6H9V8H6.274A6.982,6.982 0,1 1,5.22 13.751l-1.936,0.5A9,9 0,1 0,12 3Z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
@@ -1,7 +1,15 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Work</string>
|
<string name="app_name">Work</string>
|
||||||
<string name="title_activity_root">RootActivity</string>
|
<string name="title_activity_root">RootActivity</string>
|
||||||
<string name="auth_title">Привет! Введи код для авторизации</string>
|
<string name="auth_name">Система бронирования</string>
|
||||||
|
<string name="auth_title">Вход в систему</string>
|
||||||
<string name="auth_label">Код</string>
|
<string name="auth_label">Код</string>
|
||||||
<string name="auth_sign_in">Войти</string>
|
<string name="auth_sign_in">Войти</string>
|
||||||
|
<string name="main_screen_date">Дата:</string>
|
||||||
|
<string name="main_screen_place">Место:</string>
|
||||||
|
<string name="main_screen_title">Мои бронирования</string>
|
||||||
|
<string name="main_screen_refresh">Обновить</string>
|
||||||
|
<string name="main_screen_new_book">Новая бронь</string>
|
||||||
|
<string name="book_screen_book">Забронировать</string>
|
||||||
|
<string name="book_screen_back">Назад</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,21 +1,16 @@
|
|||||||
# Project-wide Gradle settings.
|
## For more details on how to configure your build environment visit
|
||||||
# IDE (e.g. Android Studio) users:
|
|
||||||
# Gradle settings configured through the IDE *will override*
|
|
||||||
# any settings specified in this file.
|
|
||||||
# For more details on how to configure your build environment visit
|
|
||||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
#
|
||||||
# Specifies the JVM arguments used for the daemon process.
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
# The setting is particularly useful for tweaking memory settings.
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
# Default value: -Xmx1024m -XX:MaxPermSize=256m
|
||||||
|
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||||
|
#
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
# This option should only be used with decoupled projects. More details, visit
|
# This option should only be used with decoupled projects. For more details, visit
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||||
# org.gradle.parallel=true
|
# org.gradle.parallel=true
|
||||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
#Thu Dec 04 14:16:52 GMT+07:00 2025
|
||||||
# Android operating system, and which are packaged with your app's APK
|
|
||||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
|
||||||
android.useAndroidX=true
|
|
||||||
# Enables namespacing of each library's R class so that its R class includes only the
|
|
||||||
# resources declared in the library itself and none from the library's dependencies,
|
|
||||||
# thereby reducing the size of the R class for that library
|
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
|
android.useAndroidX=true
|
||||||
|
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M" -Dfile.encoding\=UTF-8
|
||||||
|
|||||||
Reference in New Issue
Block a user