First request #5

Closed
student-21892 wants to merge 14 commits from student-21892/NTO-2025-Android-minipigs:main into main
Showing only changes of commit 100a3adbb2 - Show all commits

View File

@@ -1,28 +1,38 @@
package ru.myitschool.work.ui.screen.main package ru.myitschool.work.ui.screen.main
import android.graphics.drawable.Icon
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Logout import androidx.compose.material.icons.automirrored.outlined.Logout
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.BookmarkBorder
import androidx.compose.material.icons.filled.ChevronRight
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedCard
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.LaunchedEffect
@@ -31,12 +41,14 @@ 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.draw.shadow
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.testTag
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.rememberAsyncImagePainter import coil3.compose.rememberAsyncImagePainter
import ru.myitschool.work.core.TestIds
@Composable @Composable
fun MainScreen( fun MainScreen(
@@ -45,9 +57,32 @@ fun MainScreen(
) { ) {
val state by viewModel.uiState.collectAsState() val state by viewModel.uiState.collectAsState()
val bookings = listOf(
Booking(time = "08:00", place = "Meeting Room A"),
Booking(time = "09:30", place = "Conference Hall 1"),
Booking(time = "10:00", place = "CEO Office"),
Booking(time = "11:15", place = "Training Room B"),
Booking(time = "12:00", place = "Cafeteria (Lunch Meeting)"),
Booking(time = "13:30", place = "Boardroom"),
Booking(time = "14:00", place = "Design Studio"),
Booking(time = "15:00", place = "Meeting Room C"),
Booking(time = "16:15", place = "HR Office"),
Booking(time = "17:00", place = "Auditorium"),
Booking(time = "09:00", place = "Meeting Room B"),
Booking(time = "10:30", place = "Client Lounge"),
Booking(time = "11:00", place = "Server Room"),
Booking(time = "13:00", place = "Rooftop Terrace"),
Booking(time = "14:30", place = "Lab 3"),
Booking(time = "15:45", place = "Reception Area"),
Booking(time = "18:00", place = "Parking Lot (Team Event)"),
Booking(time = "19:30", place = "Offsite - Sky Bar"),
Booking(time = "08:30", place = "Video Conference Room"),
Booking(time = "16:30", place = "Gym (Wellness Session)")
)
when (val currentState = state) { when (val currentState = state) {
is MainState.Error -> { is MainState.Error -> {
Text("ИДИ НАХУЙ") Text("TEST_ERROR", modifier = Modifier.testTag(TestIds.Main.ERROR))
} }
is MainState.Loading -> { is MainState.Loading -> {
@@ -66,89 +101,130 @@ fun MainScreen(
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(top = 40.dp) .padding(top = 20.dp),
.height(200.dp),
) { ) {
IconButton( FilledTonalIconButton(
onClick = { viewModel.onIntent(MainIntent.Logout) }, onClick = { viewModel.onIntent(MainIntent.Logout) },
modifier = Modifier modifier = Modifier
.align(Alignment.TopEnd) .align(Alignment.TopEnd)
.size(20.dp) .size(40.dp)
.aspectRatio(1f) .aspectRatio(1f)
.offset(x = -30.dp, y = 40.dp) .offset(x = -16.dp)
.testTag(TestIds.Main.LOGOUT_BUTTON),
enabled = true,
shape = MaterialTheme.shapes.extraLarge,
colors = IconButtonDefaults.filledTonalIconButtonColors(
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.onErrorContainer
)
) { ) {
Icon( Icon(
Icons.AutoMirrored.Outlined.Logout, Icons.AutoMirrored.Outlined.Logout,
contentDescription = null, contentDescription = null,
tint = MaterialTheme.colorScheme.error,
modifier = Modifier modifier = Modifier
.fillMaxSize() .size(20.dp)
.shadow(7.dp) )
) } }
Column(
Row( modifier = Modifier.fillMaxWidth(),
modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally
verticalAlignment = Alignment.CenterVertically
) { ) {
Column( Column(
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier modifier = Modifier
.padding(start = 30.dp)
.size(120.dp) .size(120.dp)
.aspectRatio(1f) .aspectRatio(1f)
.background(MaterialTheme.colorScheme.primaryContainer, CircleShape) .background(MaterialTheme.colorScheme.inverseOnSurface, CircleShape)
) { ) {
Image( Image(
painter = rememberAsyncImagePainter("https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg"), painter = rememberAsyncImagePainter("https://catalog-cdn.detmir.st/media/2fe02057f9915e72a378795d32c79ea9.jpeg"),
contentDescription = null, contentDescription = null,
contentScale = ContentScale.Fit, contentScale = ContentScale.Fit,
modifier = Modifier.size(105.dp).clip(CircleShape) modifier = Modifier
.size(105.dp)
.clip(CircleShape)
.testTag(TestIds.Main.PROFILE_IMAGE)
) )
} }
Spacer(modifier = Modifier.size(12.dp))
Text(
text = "Smirnova Anna",
style = MaterialTheme.typography.titleLarge,
modifier = Modifier
.testTag(TestIds.Main.PROFILE_NAME)
)
Spacer(modifier = Modifier.size(16.dp))
}
}
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.surfaceContainerLow, RoundedCornerShape(topEnd = 24.dp , topStart = 24.dp))
) {
Column(
modifier = Modifier.fillMaxWidth()
) {
Row(
modifier = Modifier
.padding(vertical = 16.dp, horizontal = 16.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.Absolute.SpaceBetween
) {
Icon(
imageVector = Icons.Default.BookmarkBorder,
contentDescription = null,
tint = MaterialTheme.colorScheme.secondaryFixed
)
Text(
text = "Бронирования",
style = MaterialTheme.typography.titleMedium,
)
IconButton(
onClick = { viewModel.onIntent(MainIntent.Fetch) },
modifier = Modifier
.size(24.dp)
.aspectRatio(1f)
.testTag(TestIds.Main.REFRESH_BUTTON),
enabled = true,
) {
Icon(
Icons.Default.Refresh,
contentDescription = null,
modifier = Modifier
.fillMaxSize()
)
}
}
HorizontalDivider(
color = MaterialTheme.colorScheme.outlineVariant,
thickness = 1.dp,
)
LazyColumn(
modifier = Modifier
.fillMaxWidth()
) {
itemsIndexed(bookings) { index, booking ->
Booking(booking = booking, index = index)
}
} }
} }
// Box( FloatingActionButton(
// modifier = Modifier onClick = { },
// .fillMaxSize() containerColor = MaterialTheme.colorScheme.secondaryContainer,
// .background(MaterialTheme.colorScheme.surfaceContainerLow, RoundedCornerShape(topEnd = 24.dp , topStart = 24.dp)) contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
// ) { modifier = Modifier
// LazyColumn( .align(Alignment.BottomEnd)
// modifier = Modifier .offset(x = -16.dp, y = -16.dp)
// .fillMaxWidth() .testTag(TestIds.Main.ADD_BUTTON)
// .padding(horizontal = 20.dp) ) {
// .padding(top = 8.dp) Icon(Icons.Default.Add, contentDescription = "Добавить")
// ) { }
// items(
// items = [], }
// key = { item -> item.id }
// ) { entry ->
// OutlinedCard(
// modifier = Modifier
// .fillMaxWidth()
// .padding(top = 12.dp)
// ) {
// Text(
// text = entry.time,
// style = MaterialTheme.typography.titleMedium,
// fontWeight = FontWeight.Light,
// modifier = Modifier
// .padding(start = 16.dp)
// .padding(top = 12.dp)
// )
// Text(
// text = entry.place.name,
// style = MaterialTheme.typography.titleMedium,
// fontWeight = FontWeight.Normal,
// modifier = Modifier
// .padding(start = 16.dp)
// .padding(bottom = 12.dp)
// )
// }
// }
// }
} }
} }
} }
@@ -158,3 +234,47 @@ fun MainScreen(
} }
} }
@Composable
private fun Booking(booking: Booking, index: Int){
Row(
modifier = Modifier
.fillMaxWidth()
// .clickable { }
.padding(horizontal = 16.dp, vertical = 12.dp)
.testTag(TestIds.Main.getIdItemByPosition(index)),
verticalAlignment = Alignment.CenterVertically
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = booking.time,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.testTag(TestIds.Main.ITEM_DATE)
)
Text(
text = booking.place,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.onSurface,
modifier = Modifier.testTag(TestIds.Main.ITEM_PLACE)
)
}
Icon(
imageVector = Icons.Default.ChevronRight,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
HorizontalDivider(
color = MaterialTheme.colorScheme.outlineVariant,
thickness = 1.dp,
modifier = Modifier.padding(start = 16.dp)
)
}
data class Booking(
val time: String,
val place: String
)