Все компоненты, диалоги и экраны переработаны в соответствии с ФТТ

Этот коммит содержится в:
Глеб Иваницкий 2024-12-17 00:15:27 +03:00
родитель a2417d4c88
Коммит 58bf4c05f5
21 изменённых файлов: 632 добавлений и 339 удалений

Просмотреть файл

@ -1,7 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="#ffffff" android:pathData="M18,4.54m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
<path android:fillColor="#ffffff" android:pathData="M15,17h-2c0,1.65 -1.35,3 -3,3s-3,-1.35 -3,-3 1.35,-3 3,-3v-2c-2.76,0 -5,2.24 -5,5s2.24,5 5,5 5,-2.24 5,-5zM18,13.5h-1.86l1.67,-3.67C18.42,8.5 17.44,7 15.96,7h-5.2c-0.81,0 -1.54,0.47 -1.87,1.2l-0.28,0.76c-0.21,0.56 0.11,1.17 0.68,1.33 0.49,0.14 1,-0.11 1.2,-0.58l0.3,-0.71L13,9l-1.83,4.1c-0.6,1.33 0.39,2.9 1.85,2.9L18,16v4c0,0.55 0.45,1 1,1s1,-0.45 1,-1v-4.5c0,-1.1 -0.9,-2 -2,-2z"/>
</vector>

Просмотреть файл

@ -1,5 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="#ffffff" android:pathData="M11.5,3.5c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,1.1 -0.9,2 -2,2S11.5,4.6 11.5,3.5zM18.53,11c-1.57,0.01 -2.94,-0.9 -3.6,-2.21l-0.79,-1.67l0,0c-0.17,-0.35 -0.44,-0.65 -0.8,-0.85c-0.62,-0.36 -1.35,-0.34 -1.94,-0.03l0,-0.01L7.01,8.73C6.39,9.08 6,9.74 6,10.46V13c0,0.55 0.45,1 1,1h0c0.55,0 1,-0.45 1,-1v-2.54l1.5,-0.85C9.18,10.71 9,11.85 9,13v5.33L7,21c-0.33,0.44 -0.24,1.07 0.2,1.4c0.44,0.33 1.07,0.24 1.4,-0.2l2.04,-2.72c0.23,-0.31 0.37,-0.69 0.4,-1.08l0.18,-2.94L13,18v4c0,0.55 0.45,1 1,1h0c0.55,0 1,-0.45 1,-1v-4.87c0,-0.41 -0.13,-0.81 -0.36,-1.15l-1.6,-2.29c0,0 0,0 0,-0.01c-0.11,-1.16 0.07,-2.32 0.46,-3.4c0.81,1.23 2.05,2.14 3.51,2.52v0.03V13c0,0.28 0.22,0.5 0.5,0.5S18,13.28 18,13v-0.16V12.5c0,-0.28 0.22,-0.5 0.5,-0.5s0.5,0.22 0.5,0.5v10c0,0.28 0.22,0.5 0.5,0.5s0.5,-0.22 0.5,-0.5v-10C20,11.68 19.34,10.99 18.53,11z"/>
</vector>

Просмотреть файл

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="#ffffff" android:pathData="M10.67,13.02C10.45,13.01 10.23,13 10,13c-2.42,0 -4.68,0.67 -6.61,1.82C2.51,15.34 2,16.32 2,17.35V19c0,0.55 0.45,1 1,1h8.26C10.47,18.87 10,17.49 10,16C10,14.93 10.25,13.93 10.67,13.02z"/>
<path android:fillColor="#ffffff" android:pathData="M10,8m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"/>
<path android:fillColor="#ffffff" android:pathData="M20.75,16c0,-0.22 -0.03,-0.42 -0.06,-0.63l0.84,-0.73c0.18,-0.16 0.22,-0.42 0.1,-0.63l-0.59,-1.02c-0.12,-0.21 -0.37,-0.3 -0.59,-0.22l-1.06,0.36c-0.32,-0.27 -0.68,-0.48 -1.08,-0.63l-0.22,-1.09c-0.05,-0.23 -0.25,-0.4 -0.49,-0.4h-1.18c-0.24,0 -0.44,0.17 -0.49,0.4l-0.22,1.09c-0.4,0.15 -0.76,0.36 -1.08,0.63l-1.06,-0.36c-0.23,-0.08 -0.47,0.02 -0.59,0.22l-0.59,1.02c-0.12,0.21 -0.08,0.47 0.1,0.63l0.84,0.73c-0.03,0.21 -0.06,0.41 -0.06,0.63s0.03,0.42 0.06,0.63l-0.84,0.73c-0.18,0.16 -0.22,0.42 -0.1,0.63l0.59,1.02c0.12,0.21 0.37,0.3 0.59,0.22l1.06,-0.36c0.32,0.27 0.68,0.48 1.08,0.63l0.22,1.09c0.05,0.23 0.25,0.4 0.49,0.4h1.18c0.24,0 0.44,-0.17 0.49,-0.4l0.22,-1.09c0.4,-0.15 0.76,-0.36 1.08,-0.63l1.06,0.36c0.23,0.08 0.47,-0.02 0.59,-0.22l0.59,-1.02c0.12,-0.21 0.08,-0.47 -0.1,-0.63l-0.84,-0.73C20.72,16.42 20.75,16.22 20.75,16zM17,18c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2s2,0.9 2,2S18.1,18 17,18z"/>
</vector>

Просмотреть файл

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="#ffffff" android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
</vector>

Просмотреть файл

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="#ffffff" android:pathData="M15,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM6,10L6,8c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v2L2,10c-0.55,0 -1,0.45 -1,1s0.45,1 1,1h2v2c0,0.55 0.45,1 1,1s1,-0.45 1,-1v-2h2c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1L6,10zM15,14c-2.67,0 -8,1.34 -8,4v1c0,0.55 0.45,1 1,1h14c0.55,0 1,-0.45 1,-1v-1c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

Просмотреть файл

@ -1,11 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="#ffffff" android:pathData="M16.5,2.38m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
<path android:fillColor="#ffffff" android:pathData="M24,10.88v-3.7l-4.99,-2.11c-0.98,-0.41 -2.12,-0.07 -2.71,0.81l0,0l-1,1.6c-0.67,1.18 -1.91,2.06 -3.41,2.32l0.06,0.06c0.69,0.69 1.52,1.07 2.46,1.17c0.8,-0.42 1.52,-0.98 2.09,-1.64l0.6,3l-1.16,1.1L15,14.38v0.76v5.74c0,0.55 0.45,1 1,1h0c0.55,0 1,-0.45 1,-1v-5l2.1,-2l1.62,7.19c0.11,0.47 0.53,0.81 1.02,0.81h0c0.66,0 1.15,-0.6 1.02,-1.24l-1.94,-9.76l-0.62,-3.1l1.8,0.7v2.4c0,0.55 0.45,1 1,1h0C23.55,11.88 24,11.43 24,10.88z"/>
<path android:fillColor="#ffffff" android:pathData="M10.29,8.09c0.22,0.15 0.47,0.24 0.72,0.29c0.13,0.02 0.25,0.04 0.38,0.04s0.26,-0.01 0.38,-0.04c0.13,-0.02 0.25,-0.06 0.37,-0.11c0.24,-0.1 0.47,-0.24 0.66,-0.44c0.49,-0.49 0.67,-1.17 0.55,-1.8C13.28,5.66 13.1,5.29 12.8,5c-0.19,-0.19 -0.42,-0.34 -0.66,-0.44c-0.12,-0.05 -0.24,-0.09 -0.37,-0.11s-0.25,-0.04 -0.38,-0.04c-0.12,0 -0.23,0.01 -0.35,0.03c-0.14,0.02 -0.28,0.06 -0.41,0.11C10.4,4.66 10.17,4.81 9.98,5C9.68,5.29 9.5,5.66 9.43,6.03c-0.12,0.63 0.06,1.31 0.55,1.8C10.07,7.93 10.18,8.01 10.29,8.09z"/>
<path android:fillColor="#ffffff" android:pathData="M11.24,10.56l-2,-2c-0.1,-0.1 -0.2,-0.18 -0.31,-0.26C8.71,8.16 8.46,8.06 8.21,8.02C8.08,7.99 7.96,7.98 7.83,7.98c-0.51,0 -1.02,0.2 -1.41,0.59l-3.34,3.34c-0.41,0.41 -0.62,0.98 -0.58,1.54C2.5,13.63 2.54,13.82 2.61,14l1.07,2.95l-2.92,2.92c-0.39,0.39 -0.39,1.02 0,1.41l0,0c0.39,0.39 1.02,0.39 1.41,0l3.54,-3.54v-2.22L7,16.75v4.13c0,0.55 0.45,1 1,1h0c0.55,0 1,-0.45 1,-1v-5l-2.12,-2.12l2.36,-2.36l0.71,0.71l0,0c1.02,1 2.28,1.69 3.79,1.94c0.64,0.11 1.21,-0.45 1.16,-1.1v0c-0.03,-0.48 -0.4,-0.87 -0.87,-0.94C12.9,11.83 11.97,11.29 11.24,10.56z"/>
</vector>

Просмотреть файл

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="#ffffff" android:pathData="M21,12.22C21,6.73 16.74,3 12,3c-4.69,0 -9,3.65 -9,9.28C2.4,12.62 2,13.26 2,14v2c0,1.1 0.9,2 2,2h0c0.55,0 1,-0.45 1,-1l0,-4.81c0,-3.83 2.95,-7.18 6.78,-7.29c3.96,-0.12 7.22,3.06 7.22,7V19h-7c-0.55,0 -1,0.45 -1,1v0c0,0.55 0.45,1 1,1h7c1.1,0 2,-0.9 2,-2v-1.22c0.59,-0.31 1,-0.92 1,-1.64v-2.3C22,13.14 21.59,12.53 21,12.22z"/>
<path android:fillColor="#ffffff" android:pathData="M9,13m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/>
<path android:fillColor="#ffffff" android:pathData="M15,13m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/>
<path android:fillColor="#ffffff" android:pathData="M18,11.03C17.52,8.18 15.04,6 12.05,6c-3.03,0 -6.29,2.51 -6.03,6.45c2.47,-1.01 4.33,-3.21 4.86,-5.89C12.19,9.19 14.88,11 18,11.03z"/>
</vector>

Просмотреть файл

@ -2,6 +2,8 @@ package ru.csasq.beeapp
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Badge
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator
@ -24,16 +26,13 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import org.jetbrains.compose.resources.painterResource
import bee_app_frontend.composeapp.generated.resources.Res
import bee_app_frontend.composeapp.generated.resources.round_accessible_forward_24
import bee_app_frontend.composeapp.generated.resources.round_elderly_24
import bee_app_frontend.composeapp.generated.resources.round_group_24
import bee_app_frontend.composeapp.generated.resources.round_sports_kabaddi_24
import bee_app_frontend.composeapp.generated.resources.round_person_add_24
import bee_app_frontend.composeapp.generated.resources.round_support_agent_24
import org.jetbrains.compose.resources.DrawableResource
import ru.csasq.beeapp.ui.screens.AuthorRequestsScreen
import ru.csasq.beeapp.ui.screens.CustomerRequestsScreen
import ru.csasq.beeapp.ui.screens.SignaturesScreen
import ru.csasq.beeapp.ui.screens.RegistrationRequestsScreen
import ru.csasq.beeapp.ui.screens.UserRequestsScreen
import ru.csasq.beeapp.ui.screens.UsersScreen
import ru.csasq.beeapp.ui.theme.darkScheme
@ -41,27 +40,25 @@ sealed class Screen(
val route: String,
val title: String,
val icon: DrawableResource,
val badge: Int? = null,
) {
data object UserRequests : Screen(
route = "user-requests",
title = "Обращения",
icon = Res.drawable.round_support_agent_24,
badge = 24,
)
data object RegistrationRequests : Screen(
route = "registration-requests",
title = "Запросы на регистрацию",
icon = Res.drawable.round_person_add_24,
badge = 5,
)
data object Users : Screen(
route = "users",
title = "Пользователи",
icon = Res.drawable.round_group_24,
)
data object AuthorRequests : Screen(
route = "author-requests",
title = "Запросы авторов",
icon = Res.drawable.round_elderly_24,
)
data object CustomerRequests : Screen(
route = "customer-requests",
title = "Запросы пользователей",
icon = Res.drawable.round_sports_kabaddi_24,
)
data object Signatures : Screen(
route = "signatures",
title = "Подписи",
icon = Res.drawable.round_accessible_forward_24,
)
}
@OptIn(ExperimentalMaterial3Api::class)
@ -85,7 +82,7 @@ fun App() {
TopAppBar(
title = {
Text(
text = "Пчелки «Жу-жу-жу!»",
text = "Помощник пчеловода",
overflow = TextOverflow.Ellipsis,
softWrap = false,
)
@ -103,18 +100,29 @@ fun App() {
NavigationBar {
val navBackStackEntry = navController.currentBackStackEntryAsState()
val items = listOf(
Screen.UserRequests,
Screen.RegistrationRequests,
Screen.Users,
Screen.AuthorRequests,
Screen.CustomerRequests,
Screen.Signatures,
)
items.forEach { screen ->
NavigationBarItem(
icon = {
Icon(
painter = painterResource(screen.icon),
contentDescription = null,
)
BadgedBox(
badge = {
when {
screen.badge != null -> Badge {
Text(
text = screen.badge.toString(),
)
}
}
},
) {
Icon(
painter = painterResource(screen.icon),
contentDescription = null,
)
}
},
label = {
Text(
@ -153,8 +161,20 @@ fun App() {
) {
paddingValues -> NavHost(
navController = navController,
startDestination = Screen.Users.route,
startDestination = Screen.UserRequests.route,
) {
composable(Screen.UserRequests.route) {
UserRequestsScreen(
navController = navController,
paddingValues = paddingValues,
)
}
composable(Screen.RegistrationRequests.route) {
RegistrationRequestsScreen(
navController = navController,
paddingValues = paddingValues,
)
}
composable(Screen.Users.route) {
UsersScreen(
navController = navController,
@ -162,24 +182,6 @@ fun App() {
addUserButtonState = floatingActionButtonState,
)
}
composable(Screen.AuthorRequests.route) {
AuthorRequestsScreen(
navController = navController,
paddingValues = paddingValues,
)
}
composable(Screen.CustomerRequests.route) {
CustomerRequestsScreen(
navController = navController,
paddingValues = paddingValues,
)
}
composable(Screen.Signatures.route) {
SignaturesScreen(
navController = navController,
paddingValues = paddingValues,
)
}
}
}
}

Просмотреть файл

@ -36,26 +36,40 @@ import androidx.compose.ui.unit.dp
import bee_app_frontend.composeapp.generated.resources.Res
import bee_app_frontend.composeapp.generated.resources.round_check_24
import bee_app_frontend.composeapp.generated.resources.round_close_24
import bee_app_frontend.composeapp.generated.resources.round_manage_accounts_24
import org.jetbrains.compose.resources.painterResource
import ru.csasq.beeapp.ui.screens.AuthorRequest
import ru.csasq.beeapp.ui.screens.RegistrationRequest
@Composable
fun AuthorRequestCard(
authorRequest: AuthorRequest,
spoilerState: MutableState<AuthorRequest?>,
fun RegistrationRequestCard(
registrationRequest: RegistrationRequest,
spoilerState: MutableState<RegistrationRequest?>,
onAccept: () -> Unit,
onEdit: () -> Unit,
onDecline: () -> Unit,
) {
val backgroundColor = animateColorAsState(
targetValue = if (spoilerState.value == authorRequest) MaterialTheme.colorScheme.primary.copy(alpha = 0.12f) else Color.Transparent,
targetValue = when (spoilerState.value) {
registrationRequest -> MaterialTheme.colorScheme.primary.copy(
alpha = 0.12f,
)
else -> Color.Transparent
},
)
val horizontalPadding = animateDpAsState(
targetValue = if (spoilerState.value == authorRequest) 16.dp else 0.dp,
targetValue = when (spoilerState.value) {
registrationRequest -> 16.dp
else -> 0.dp
},
)
val shapeState = animateDpAsState(
targetValue = if (spoilerState.value == authorRequest) 28.0.dp else 0.0.dp,
targetValue = when (spoilerState.value) {
registrationRequest -> 28.0.dp
else -> 0.0.dp
},
)
val cardColors = CardDefaults.cardColors()
Card(
modifier = Modifier
.padding(
@ -64,8 +78,8 @@ fun AuthorRequestCard(
.fillMaxWidth(),
onClick = {
spoilerState.value = when (spoilerState.value) {
authorRequest -> null
else -> authorRequest
registrationRequest -> null
else -> registrationRequest
}
},
shape = RoundedCornerShape(shapeState.value),
@ -83,7 +97,7 @@ fun AuthorRequestCard(
.padding(16.dp),
) {
Text(
text = authorRequest.title,
text = registrationRequest.fullName,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = MaterialTheme.typography.titleLarge,
@ -92,14 +106,14 @@ fun AuthorRequestCard(
modifier = Modifier.height(4.dp),
)
Text(
text = authorRequest.description,
text = registrationRequest.region,
overflow = TextOverflow.Ellipsis,
maxLines = 3,
style = MaterialTheme.typography.bodyMedium,
)
}
AnimatedVisibility(
visible = spoilerState.value == authorRequest,
visible = spoilerState.value == registrationRequest,
) {
HorizontalDivider()
Row(
@ -108,7 +122,7 @@ fun AuthorRequestCard(
.height(IntrinsicSize.Min),
horizontalArrangement = Arrangement.SpaceBetween,
) {
AuthorRequestButton(
RegistrationRequestButton(
modifier = Modifier
.weight(
weight = 1f,
@ -118,7 +132,17 @@ fun AuthorRequestCard(
painter = painterResource(Res.drawable.round_check_24),
onClick = onAccept,
)
AuthorRequestButton(
RegistrationRequestButton(
modifier = Modifier
.weight(
weight = 1f,
fill = true,
),
title = "Изменить",
painter = painterResource(Res.drawable.round_manage_accounts_24),
onClick = onEdit,
)
RegistrationRequestButton(
modifier = Modifier
.weight(
weight = 1f,
@ -135,7 +159,7 @@ fun AuthorRequestCard(
}
@Composable
fun AuthorRequestButton(
fun RegistrationRequestButton(
modifier: Modifier = Modifier,
title: String,
painter: Painter,

Просмотреть файл

@ -11,11 +11,11 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ru.csasq.beeapp.ui.screens.User
@Composable
fun UserCard(
title: String,
caption: String,
user: User,
onClick: (() -> Unit),
) {
Column(
@ -27,14 +27,14 @@ fun UserCard(
.padding(16.dp),
) {
Text(
text = title,
text = user.fullName,
style = MaterialTheme.typography.titleLarge,
)
Spacer(
modifier = Modifier.height(4.dp),
)
Text(
text = caption,
text = user.phoneNumber,
style = MaterialTheme.typography.bodyMedium,
)
}

Просмотреть файл

@ -12,11 +12,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import ru.csasq.beeapp.ui.screens.UserRequest
@Composable
fun CustomerRequestCard(
title: String,
description: String,
fun UserRequestCard(
userRequest: UserRequest,
onClick: (() -> Unit),
) {
Column(
@ -28,14 +28,14 @@ fun CustomerRequestCard(
.padding(16.dp),
) {
Text(
text = title,
text = userRequest.region,
style = MaterialTheme.typography.titleLarge,
)
Spacer(
modifier = Modifier.height(4.dp),
)
Text(
text = description,
text = userRequest.topic,
overflow = TextOverflow.Ellipsis,
maxLines = 3,
style = MaterialTheme.typography.bodyMedium,

Просмотреть файл

@ -0,0 +1,192 @@
package ru.csasq.beeapp.ui.dialogs
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import bee_app_frontend.composeapp.generated.resources.Res
import bee_app_frontend.composeapp.generated.resources.round_close_24
import bee_app_frontend.composeapp.generated.resources.round_more_vert_24
import org.jetbrains.compose.resources.painterResource
import ru.csasq.beeapp.ui.screens.User
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun UserDialog(
user: User,
onDismiss: () -> Unit,
onSave: () -> Unit,
onDelete: (() -> Unit)? = null,
onDecline: (() -> Unit)? = null,
properties: DialogProperties = DialogProperties(
usePlatformDefaultWidth = false,
),
) {
Dialog(
onDismissRequest = onDismiss,
properties = properties,
) {
Scaffold(
modifier = Modifier
.fillMaxSize(),
topBar = {
TopAppBar(
title = {
Text(
text = when {
onDelete != null -> "Изменить пользователя"
else -> "Создать пользователя"
},
overflow = TextOverflow.Ellipsis,
softWrap = false,
)
},
navigationIcon = {
IconButton(
onClick = onDismiss,
) {
Icon(
painter = painterResource(Res.drawable.round_close_24),
contentDescription = null,
)
}
},
actions = {
Button(
onClick = onSave,
) {
Text(
text = "Сохранить",
)
}
if (onDelete == null && onDecline == null) {
Spacer(
modifier = Modifier
.width(16.dp),
)
return@TopAppBar
}
val dropdownMenuState = remember {
mutableStateOf(false)
}
IconButton(
onClick = {
dropdownMenuState.value = true
},
) {
Icon(
painter = painterResource(Res.drawable.round_more_vert_24),
contentDescription = null,
)
}
DropdownMenu(
expanded = dropdownMenuState.value,
onDismissRequest = {
dropdownMenuState.value = false
},
) {
onDelete?.let {
DropdownMenuItem(
text = {
Text(
text = "Удалить",
)
},
onClick = it,
)
}
onDecline?.let {
DropdownMenuItem(
text = {
Text(
text = "Отклонить",
)
},
onClick = it,
)
}
}
},
)
},
) { paddingValues ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.padding(
horizontal = 16.dp,
),
) {
Column(
modifier = Modifier
.weight(1f)
.verticalScroll(
state = rememberScrollState(),
)
) {
val fullNameState = remember {
mutableStateOf(user.fullName)
}
OutlinedTextField(
value = fullNameState.value,
onValueChange = {
fullNameState.value = it
},
modifier = Modifier
.fillMaxWidth(),
label = {
Text(
text = "Имя пользователя",
)
},
)
Spacer(
modifier = Modifier.height(16.dp),
)
val phoneNumberState = remember {
mutableStateOf(user.phoneNumber)
}
OutlinedTextField(
value = phoneNumberState.value,
onValueChange = {
phoneNumberState.value = it
},
modifier = Modifier
.fillMaxWidth(),
label = {
Text(
text = "Номер телефона",
)
},
)
}
}
}
}
}

Просмотреть файл

@ -4,27 +4,25 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
@ -34,31 +32,21 @@ import androidx.compose.ui.window.DialogProperties
import bee_app_frontend.composeapp.generated.resources.Res
import bee_app_frontend.composeapp.generated.resources.round_close_24
import org.jetbrains.compose.resources.painterResource
import ru.csasq.beeapp.ui.screens.CustomerRequest
import ru.csasq.beeapp.ui.screens.UserRequest
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CustomerRequestDialog(
dialogState: MutableState<CustomerRequest?>,
fun UserRequestDialog(
userRequest: UserRequest,
onDismiss: () -> Unit,
onAccept: () -> Unit,
onDecline: () -> Unit,
properties: DialogProperties = DialogProperties(
usePlatformDefaultWidth = false,
),
) {
val coroutine = rememberCoroutineScope()
val progressIndicatorState = remember {
mutableStateOf(false)
}
val titleState = remember {
mutableStateOf(dialogState.value?.title)
}
val descriptionState = remember {
mutableStateOf(dialogState.value?.description)
}
Dialog(
onDismissRequest = {
dialogState.value = null
},
onDismissRequest = onDismiss,
properties = properties,
) {
val verticalScrollState = rememberScrollState()
@ -82,18 +70,14 @@ fun CustomerRequestDialog(
TopAppBar(
title = {
Text(
text = dialogState.value?.id?.let {
"Изменить сценарий"
} ?: "Добавить сценарий",
text = "Обращение пользователя",
overflow = TextOverflow.Ellipsis,
softWrap = false,
)
},
navigationIcon = {
IconButton(
onClick = {
dialogState.value = null
},
onClick = onDismiss,
) {
Icon(
painter = painterResource(Res.drawable.round_close_24),
@ -120,21 +104,82 @@ fun CustomerRequestDialog(
state = verticalScrollState,
)
) {
Text(
text = dialogState.value?.title!!,
style = MaterialTheme.typography.titleLarge,
OutlinedTextField(
value = userRequest.topic,
onValueChange = {},
modifier = Modifier
.fillMaxWidth(),
readOnly = true,
label = {
Text(
text = "Тема обращения",
)
},
)
Spacer(
modifier = Modifier.height(4.dp),
modifier = Modifier.height(16.dp),
)
Text(
text = dialogState.value?.description!!,
style = MaterialTheme.typography.bodyMedium,
OutlinedTextField(
value = userRequest.user.fullName,
onValueChange = {},
modifier = Modifier
.fillMaxWidth(),
readOnly = true,
label = {
Text(
text = "ФИО заявителя",
)
},
)
Spacer(
modifier = Modifier.height(16.dp),
)
OutlinedTextField(
value = userRequest.user.phoneNumber,
onValueChange = {},
modifier = Modifier
.fillMaxWidth(),
readOnly = true,
label = {
Text(
text = "Номер телефона",
)
},
)
Spacer(
modifier = Modifier.height(16.dp),
)
OutlinedTextField(
value = userRequest.region + ", " + userRequest.location,
onValueChange = {},
modifier = Modifier
.fillMaxWidth(),
readOnly = true,
label = {
Text(
text = "Регион и место",
)
},
)
Spacer(
modifier = Modifier.height(16.dp),
)
OutlinedTextField(
value = userRequest.text,
onValueChange = {},
modifier = Modifier
.fillMaxWidth(),
readOnly = true,
label = {
Text(
text = "Сутевая часть",
)
},
)
}
Row {
Button(
onClick = {},
onClick = onAccept,
modifier = Modifier
.weight(1f),
) {
@ -143,10 +188,10 @@ fun CustomerRequestDialog(
)
}
Spacer(
modifier = Modifier.width(8.dp),
modifier = Modifier.width(16.dp),
)
OutlinedButton(
onClick = {},
onClick = onDecline,
modifier = Modifier
.weight(1f),
) {

Просмотреть файл

@ -1,59 +0,0 @@
package ru.csasq.beeapp.ui.screens
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.navigation.NavController
import ru.csasq.beeapp.ui.components.AuthorRequestCard
data class AuthorRequest(
val id: Int,
val title: String,
val description: String,
)
@Composable
fun AuthorRequestsScreen(
navController: NavController,
paddingValues: PaddingValues,
) {
Column(
modifier = Modifier
.padding(
paddingValues = paddingValues,
)
.fillMaxSize()
.verticalScroll(
state = rememberScrollState(),
),
) {
val authorRequestList = mutableListOf<AuthorRequest>()
val spoilerState = remember {
mutableStateOf<AuthorRequest?>(null)
}
for (id in 1..25) {
authorRequestList.add(
AuthorRequest(
id = id,
title = "Заявляю о пропаже пчел",
description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
)
)
}
authorRequestList.forEach {
AuthorRequestCard(
authorRequest = it,
spoilerState = spoilerState,
onAccept = {},
onDecline = {},
)
}
}
}

Просмотреть файл

@ -1,71 +0,0 @@
package ru.csasq.beeapp.ui.screens
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.navigation.NavController
import ru.csasq.beeapp.ui.components.AuthorRequestCard
import ru.csasq.beeapp.ui.components.CustomerRequestCard
import ru.csasq.beeapp.ui.components.UserCard
import ru.csasq.beeapp.ui.dialogs.CustomerRequestDialog
data class CustomerRequest(
val id: Int,
val title: String,
val description: String,
val attachments: List<Int>,
)
@Composable
fun CustomerRequestsScreen(
navController: NavController,
paddingValues: PaddingValues,
) {
Column(
modifier = Modifier
.padding(
paddingValues = paddingValues,
)
.fillMaxSize()
.verticalScroll(
state = rememberScrollState(),
),
) {
val customerRequestList = mutableListOf<CustomerRequest>()
val dialogState = remember {
mutableStateOf<CustomerRequest?>(null)
}
for (id in 1..25) {
customerRequestList.add(
CustomerRequest(
id = id,
title = "Заявка $id",
description = "Я вмер",
attachments = listOf(),
)
)
}
customerRequestList.forEach {
CustomerRequestCard(
title = it.title,
description = it.description,
onClick = {
dialogState.value = it
},
)
}
dialogState.value?.let {
CustomerRequestDialog(
dialogState = dialogState,
)
}
}
}

Просмотреть файл

@ -0,0 +1,93 @@
package ru.csasq.beeapp.ui.screens
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.navigation.NavController
import ru.csasq.beeapp.ui.components.RegistrationRequestCard
import ru.csasq.beeapp.ui.dialogs.UserDialog
data class RegistrationRequest(
val id: Int,
val fullName: String,
val phoneNumber: String,
val region: String,
)
@Composable
fun RegistrationRequestsScreen(
navController: NavController,
paddingValues: PaddingValues,
) {
Column(
modifier = Modifier
.padding(
paddingValues = paddingValues,
)
.fillMaxSize()
.verticalScroll(
state = rememberScrollState(),
),
) {
val registrationRequestList = mutableListOf<RegistrationRequest>()
val spoilerState = remember {
mutableStateOf<RegistrationRequest?>(null)
}
val dialogState = remember {
mutableStateOf<User?>(null)
}
for (id in 1..5) {
registrationRequestList.add(
RegistrationRequest(
id = id,
fullName = "Иваницкий Глеб Олегович",
phoneNumber = "+79954426969",
region = "Узловский район",
)
)
}
registrationRequestList.forEach {
RegistrationRequestCard(
registrationRequest = it,
spoilerState = spoilerState,
onAccept = {
spoilerState.value = null
},
onEdit = {
dialogState.value = User(
fullName = it.fullName,
phoneNumber = it.phoneNumber,
)
spoilerState.value = null
},
onDecline = {
spoilerState.value = null
},
)
}
dialogState.value?.let {
UserDialog(
user = it,
onDismiss = {
dialogState.value = null
},
onSave = {
dialogState.value = null
},
onDecline = {
dialogState.value = null
},
)
}
}
}

Просмотреть файл

@ -1,38 +0,0 @@
package ru.csasq.beeapp.ui.screens
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
@Composable
fun SignaturesScreen(
navController: NavController,
paddingValues: PaddingValues,
) {
Column(
modifier = Modifier
.padding(
paddingValues = paddingValues,
)
.fillMaxSize()
.verticalScroll(
state = rememberScrollState(),
),
) {
Text (
text = "Здесь будет список подписей",
modifier = Modifier
.padding(
horizontal = 16.dp,
)
)
}
}

Просмотреть файл

@ -0,0 +1,89 @@
package ru.csasq.beeapp.ui.screens
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.navigation.NavController
import ru.csasq.beeapp.ui.components.UserRequestCard
import ru.csasq.beeapp.ui.dialogs.UserRequestDialog
data class UserRequest(
val id: Int,
val user: User,
val region: String,
val location: String,
val topic: String,
val text: String,
val images: List<Int>,
)
@Composable
fun UserRequestsScreen(
navController: NavController,
paddingValues: PaddingValues,
) {
Column(
modifier = Modifier
.padding(
paddingValues = paddingValues,
)
.fillMaxSize()
.verticalScroll(
state = rememberScrollState(),
),
) {
val userRequestList = mutableListOf<UserRequest>()
val dialogState = remember {
mutableStateOf<UserRequest?>(null)
}
val user = User(
id = 1,
fullName = "Иваницкий Глеб Олегович",
phoneNumber = "+79954426969",
)
for (id in 1..24) {
userRequestList.add(
UserRequest(
id = id,
user = user,
region = "Узловский район",
location = "пер. Центральный, возле поля",
topic = "Фиксация гибели пчел",
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
images = listOf(),
)
)
}
userRequestList.forEach {
UserRequestCard(
userRequest = it,
onClick = {
dialogState.value = it
},
)
}
dialogState.value?.let {
UserRequestDialog(
userRequest = it,
onDismiss = {
dialogState.value = null
},
onAccept = {
dialogState.value = null
},
onDecline = {
dialogState.value = null
},
)
}
}
}

Просмотреть файл

@ -1,19 +1,13 @@
package ru.csasq.beeapp.ui.screens
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Badge
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@ -21,15 +15,19 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import bee_app_frontend.composeapp.generated.resources.Res
import bee_app_frontend.composeapp.generated.resources.round_add_24
import bee_app_frontend.composeapp.generated.resources.round_close_24
import org.jetbrains.compose.resources.painterResource
import ru.csasq.beeapp.ui.components.UserCard
import ru.csasq.beeapp.ui.dialogs.UserDialog
data class User(
val id: Int? = null,
var fullName: String = "",
var phoneNumber: String = "",
)
@Composable
fun UsersScreen(
@ -50,6 +48,10 @@ fun UsersScreen(
previousValue = it
}
}
val dialogState = remember {
mutableStateOf<User?>(null)
}
val userList = mutableListOf<User>()
Column(
modifier = Modifier
@ -61,36 +63,21 @@ fun UsersScreen(
state = verticalScrollState,
),
) {
Row(
modifier = Modifier
.background(
color = MaterialTheme.colorScheme.onPrimaryContainer,
for (id in 1..17) {
userList.add(
User(
id = id,
fullName = "Иваницкий Глеб Олегович",
phoneNumber = "+79954426969",
)
.padding(16.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = "Заявки на регистрацию",
color = MaterialTheme.colorScheme.onPrimary,
)
Badge(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary,
) {
Text(
text = "24",
modifier = Modifier
.padding(8.dp),
)
}
}
repeat(25) {
userList.forEach {
UserCard(
title = "Иваницкий Глеб Олегович",
caption = "Гавносос последней степени критинизма",
onClick = {},
user = it,
onClick = {
dialogState.value = it
},
)
}
}
@ -108,9 +95,27 @@ fun UsersScreen(
contentDescription = null,
)
},
onClick = {},
onClick = {
dialogState.value = User()
},
expanded = addUserButtonExpandedState.value,
)
}
dialogState.value?.let {
UserDialog(
user = it,
onDismiss = {
dialogState.value = null
},
onSave = {
dialogState.value = null
},
onDelete = it.id?.let {
{
dialogState.value = null
}
}
)
}
}

Просмотреть файл

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0" />
<meta name="color-scheme" content="dark light" />
<title>Пчелки «Жу-жу-жу!»</title>
<title>Помощник пчеловода</title>
<link type="text/css" rel="stylesheet" href="/styles.css" />
<script type="application/javascript" src="/composeApp.js"></script>
</head>

Просмотреть файл

@ -4,4 +4,8 @@ html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
}
canvas {
outline: none;
}