finished 2nd lab

This commit is contained in:
Zyzf 2023-10-18 23:00:08 +04:00
parent 192e5da4c3
commit 8891bef085
14 changed files with 915 additions and 84 deletions

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>

View File

@ -0,0 +1,41 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
</profile>
</component>

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">

View File

@ -3,14 +3,18 @@ package com.zyzf.coffeepreorder.coffee.composeui
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
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.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
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.items
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
@ -18,7 +22,7 @@ import androidx.compose.material.icons.outlined.Create
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledIconButton import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.ModalBottomSheet
@ -42,7 +46,6 @@ import androidx.navigation.NavController
import com.zyzf.coffeepreorder.R import com.zyzf.coffeepreorder.R
import com.zyzf.coffeepreorder.coffee.model.Coffee import com.zyzf.coffeepreorder.coffee.model.Coffee
import com.zyzf.coffeepreorder.coffee.model.getCoffee import com.zyzf.coffeepreorder.coffee.model.getCoffee
import com.zyzf.coffeepreorder.composeui.navigation.Screen
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -51,13 +54,14 @@ fun CoffeeList(navController: NavController?) {
val openDialog = remember { mutableStateOf(false) } val openDialog = remember { mutableStateOf(false) }
val add = remember { mutableStateOf(false) } val add = remember { mutableStateOf(false) }
val coffee = remember { mutableStateOf(Coffee("", 0.0, "", 1)) } val coffee = remember { mutableStateOf(Coffee("", 0.0, "", 1)) }
Column(Modifier.padding(all = 10.dp), horizontalAlignment = Alignment.CenterHorizontally) { val itemsList = getCoffee().toList()
getCoffee().forEachIndexed { index, currentCoffee -> LazyColumn(
val coffeeId = Screen.CoffeeView.route.replace("{id}", index.toString()) horizontalAlignment = Alignment.CenterHorizontally) {
items(itemsList) { currentCoffee ->
Row(modifier = Modifier Row(modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.heightIn(max = 130.dp) .heightIn(max = 140.dp)
.padding(bottom = 10.dp), .padding(bottom = 10.dp, top = 10.dp),
horizontalArrangement = Arrangement.SpaceAround) { horizontalArrangement = Arrangement.SpaceAround) {
Image(bitmap = ImageBitmap.imageResource(currentCoffee.image), Image(bitmap = ImageBitmap.imageResource(currentCoffee.image),
contentDescription = "Кофе", modifier = Modifier contentDescription = "Кофе", modifier = Modifier
@ -102,7 +106,12 @@ fun CoffeeList(navController: NavController?) {
} }
} }
} }
FilledIconButton(onClick = { coffee.value = Coffee("", 0.0, "", 1) ; add.value = true; openDialog.value = true }, Modifier.padding(start = 10.dp)) { }
Box(modifier = Modifier.fillMaxSize()) {
FloatingActionButton(onClick = { coffee.value = Coffee("", 0.0, "", 1) ; add.value = true; openDialog.value = true },
Modifier
.padding(all = 20.dp)
.align(alignment = Alignment.BottomEnd)) {
Icon( Icon(
imageVector = Icons.Filled.Add, imageVector = Icons.Filled.Add,
contentDescription = "Add", contentDescription = "Add",
@ -112,7 +121,9 @@ fun CoffeeList(navController: NavController?) {
} }
if (openDialog.value) { if (openDialog.value) {
ModalBottomSheet(onDismissRequest = { openDialog.value = false }) { ModalBottomSheet(onDismissRequest = { openDialog.value = false }) {
Column(modifier = Modifier.fillMaxWidth().padding(all = 10.dp), Column(modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
horizontalAlignment = Alignment.CenterHorizontally) { horizontalAlignment = Alignment.CenterHorizontally) {
OutlinedTextField(modifier = Modifier.fillMaxWidth(), OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = coffee.value.name, onValueChange = {}, readOnly = true, value = coffee.value.name, onValueChange = {}, readOnly = true,

View File

@ -14,6 +14,14 @@ fun getCoffee(): List<Coffee> {
return listOf( return listOf(
Coffee("Coffee1", 200.0, "Ing1", R.drawable.coffee_image), Coffee("Coffee1", 200.0, "Ing1", R.drawable.coffee_image),
Coffee("Coffee2", 300.0, "Ing2", R.drawable.coffee_image), Coffee("Coffee2", 300.0, "Ing2", R.drawable.coffee_image),
Coffee("Coffee3", 500.0, "Ing3", R.drawable.coffee_image),
Coffee("Coffee3", 500.0, "Ing3", R.drawable.coffee_image),
Coffee("Coffee3", 500.0, "Ing3", R.drawable.coffee_image),
Coffee("Coffee3", 500.0, "Ing3", R.drawable.coffee_image),
Coffee("Coffee3", 500.0, "Ing3", R.drawable.coffee_image),
Coffee("Coffee3", 500.0, "Ing3", R.drawable.coffee_image),
Coffee("Coffee3", 500.0, "Ing3", R.drawable.coffee_image),
Coffee("Coffee3", 500.0, "Ing3", R.drawable.coffee_image),
Coffee("Coffee3", 500.0, "Ing3", R.drawable.coffee_image) Coffee("Coffee3", 500.0, "Ing3", R.drawable.coffee_image)
) )
} }

View File

@ -1,66 +0,0 @@
package com.zyzf.coffeepreorder.composeui
import android.content.Intent
import android.content.res.Configuration
import android.net.Uri
import android.widget.TextView
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.zyzf.coffeepreorder.R
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
@Composable
fun About() {
val localContext = LocalContext.current
val aboutText = localContext.resources.getText(R.string.about_text)
val urlOnClick = {
val openURL = Intent(Intent.ACTION_VIEW)
openURL.data = Uri.parse("https://ulstu.ru/")
localContext.startActivity(openURL)
}
Column(Modifier.padding(all = 10.dp)) {
AndroidView(
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = urlOnClick),
factory = { context -> TextView(context) },
update = { it.text = aboutText }
)
Spacer(Modifier.padding(bottom = 10.dp))
Button(
modifier = Modifier.fillMaxWidth(),
onClick = urlOnClick
) {
Text(stringResource(id = R.string.about_title))
}
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun AboutPreview() {
CoffeePreorderTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
About()
}
}
}

View File

@ -0,0 +1,156 @@
package com.zyzf.coffeepreorder.composeui
import android.content.res.Configuration
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.res.imageResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.zyzf.coffeepreorder.coffee.model.getCoffee
import com.zyzf.coffeepreorder.composeui.navigation.Screen
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Cart(navController: NavController?) {
val openDialog = remember { mutableStateOf(false) }
val itemsList = getCoffee().toList()
LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally) {
items(itemsList) { currentCoffee ->
Row(modifier = Modifier
.fillMaxWidth()
.heightIn(max = 140.dp)
.padding(bottom = 10.dp, top = 10.dp),
horizontalArrangement = Arrangement.SpaceAround) {
Image(bitmap = ImageBitmap.imageResource(currentCoffee.image),
contentDescription = "Кофе", modifier = Modifier
.fillMaxHeight()
.weight(1f))
Column(
Modifier
.weight(2f)
.padding(start = 20.dp)) {
Text(text = currentCoffee.name, fontSize = 25.sp)
Text(text = String.format("%.2f", currentCoffee.cost), fontSize = 20.sp)
Text(text = currentCoffee.ingredients, fontSize = 15.sp)
Row(
Modifier
.fillMaxWidth()
.padding(top = 5.dp)) {
Button(
onClick = { openDialog.value = true },
shape = CircleShape,
modifier = Modifier.padding(start = 10.dp, end = 10.dp),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.error
)
) {
// Inner content including an icon and a text label
Icon(
imageVector = Icons.Default.Clear,
contentDescription = "Favorite",
modifier = Modifier.size(20.dp)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text(text = "Удалить из корзины")
}
}
}
}
}
}
Box(modifier = Modifier.fillMaxSize()) {
ExtendedFloatingActionButton(
onClick = { navController?.navigate(Screen.Order.route) },
icon = { Icon(Icons.Filled.Add, "Сделать заказ") },
text = { Text(text = "Сделать заказ") },
modifier = Modifier.align(alignment = Alignment.BottomEnd).padding(all = 20.dp),
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary
)
}
if (openDialog.value) {
AlertDialog(
icon = {
Icon(Icons.Default.Clear, contentDescription = "Example Icon")
},
title = {
Text(text = "Подтверждение")
},
text = {
Text(text = "Вы хотите удалить элемент из корзины?")
},
onDismissRequest = {
openDialog.value = false
},
confirmButton = {
TextButton(
onClick = {
openDialog.value = false
/* TODO */
}
) {
Text("Да")
}
},
dismissButton = {
TextButton(
onClick = {
openDialog.value = false
}
) {
Text("Нет")
}
}
)
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun CoffeeListPreview() {
CoffeePreorderTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
Cart(navController = null)
}
}
}

View File

@ -0,0 +1,105 @@
package com.zyzf.coffeepreorder.composeui
import android.content.res.Configuration
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.zyzf.coffeepreorder.R
import com.zyzf.coffeepreorder.composeui.navigation.Screen
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
@Composable
fun Login(navController: NavController?) {
Column(Modifier.padding(all = 10.dp), horizontalAlignment = Alignment.CenterHorizontally) {
Image(
painter = painterResource(id = R.drawable.coffee_image),
contentDescription = "Logo",
modifier = Modifier.size(150.dp)
)
Spacer(modifier = Modifier.padding(all = 20.dp))
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_login_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_passw_label))
}
)
Spacer(modifier = Modifier.padding(all = 20.dp))
Button(
onClick = { navController?.navigate(Screen.CoffeeList.route) },
shape = CircleShape,
modifier = Modifier.fillMaxWidth(fraction = 0.75f),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary
)
) {
// Inner content including an icon and a text label
Icon(
imageVector = Icons.Default.Check,
contentDescription = "Favorite",
modifier = Modifier.size(20.dp)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text(text = "Войти")
}
Button(
onClick = { navController?.navigate(Screen.Register.route) },
shape = CircleShape,
modifier = Modifier.fillMaxWidth(fraction = 0.75f),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.secondaryContainer,
contentColor = MaterialTheme.colorScheme.secondary
)
) {
// Inner content including an icon and a text label
Icon(
imageVector = Icons.Default.Add,
contentDescription = "Favorite",
modifier = Modifier.size(20.dp)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text(text = "Зарегистрироваться")
}
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun LoginPreview() {
CoffeePreorderTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
Login(null)
}
}
}

View File

@ -0,0 +1,173 @@
package com.zyzf.coffeepreorder.composeui
import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Create
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.DatePicker
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TimePicker
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.material3.rememberTimePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.navigation.NavController
import com.zyzf.coffeepreorder.composeui.navigation.Screen
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Order(navController: NavController?) {
val openDatePicker = remember { mutableStateOf(false) }
val openTimePicker = remember { mutableStateOf(false) }
val calendar = Calendar.getInstance()
val datePickerState = rememberDatePickerState(initialSelectedDateMillis = calendar.timeInMillis)
val timePickerState = rememberTimePickerState(is24Hour = true, initialHour = calendar.get(Calendar.HOUR_OF_DAY), initialMinute = calendar.get(Calendar.MINUTE))
val formatter = SimpleDateFormat("dd.MM.yyyy", Locale.ROOT)
Column(Modifier.padding(all = 10.dp), horizontalAlignment = Alignment.CenterHorizontally) {
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically) {
OutlinedTextField(
value = formatter.format(Date(datePickerState.selectedDateMillis!!)), onValueChange = {}, readOnly = true,
label = {
Text("Дата")
}
)
Spacer(modifier = Modifier.padding(all = 10.dp))
FilledIconButton(onClick = { openDatePicker.value = true },
colors = IconButtonDefaults.filledIconButtonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary,
)) {
Icon(imageVector = Icons.Default.Create, contentDescription = "Выбрать дату")
}
}
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically) {
OutlinedTextField(
value = "${timePickerState.hour}:${timePickerState.minute}", onValueChange = {}, readOnly = true,
label = {
Text("Время")
}
)
Spacer(modifier = Modifier.padding(all = 10.dp))
FilledIconButton(onClick = { openTimePicker.value = true },
colors = IconButtonDefaults.filledIconButtonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary,
)) {
Icon(imageVector = Icons.Default.Create, contentDescription = "Выбрать время")
}
}
Spacer(modifier = Modifier.padding(all = 20.dp))
Text(text = "Сумма: xxx")
}
Box(modifier = Modifier.fillMaxSize()) {
ExtendedFloatingActionButton(
onClick = { navController?.navigate(Screen.CoffeeList.route) },
icon = { Icon(Icons.Filled.Add, "Оформить заказ") },
text = { Text(text = "Оформить заказ") },
modifier = Modifier
.align(alignment = Alignment.BottomEnd)
.padding(all = 20.dp),
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary
)
}
if (openDatePicker.value) {
Dialog(onDismissRequest = { openDatePicker.value = false },
properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = true, usePlatformDefaultWidth = false)) {
Card(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.7f)
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column(verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.End) {
Button(
onClick = { openDatePicker.value = false },
modifier = Modifier.padding(10.dp),
) {
Text("Ок")
}
DatePicker(
state = datePickerState,
modifier = Modifier.fillMaxSize().padding(10.dp)
)
}
}
}
}
if (openTimePicker.value) {
Dialog(onDismissRequest = { openTimePicker.value = false },
properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = true)) {
Card(
modifier = Modifier
.fillMaxWidth(1f)
.fillMaxHeight(0.55f)
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column(verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) {
Button(
onClick = { openTimePicker.value = false },
modifier = Modifier.padding(10.dp),
) {
Text("Ок")
}
TimePicker(
state = timePickerState,
modifier = Modifier.fillMaxSize().padding(10.dp)
)
}
}
}
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun OrderPreview() {
CoffeePreorderTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
Order(null)
}
}
}

View File

@ -0,0 +1,258 @@
package com.zyzf.coffeepreorder.composeui
import android.content.res.Configuration
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Create
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.ExitToApp
import androidx.compose.material.icons.outlined.Clear
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.zyzf.coffeepreorder.R
import com.zyzf.coffeepreorder.composeui.navigation.Screen
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
@Composable
fun Profile(navController: NavController?) {
val openDialogEdit = remember { mutableStateOf(false) }
val openDialogExit = remember { mutableStateOf(false) }
val openDialogDelete = remember { mutableStateOf(false) }
Column(Modifier.padding(all = 10.dp), horizontalAlignment = Alignment.CenterHorizontally) {
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "zyzf", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_login_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "Калышев Ян", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_fio_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "+79911152503", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_phone_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "Старый пароль", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_oldpassw_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "Новый пароль", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_newpassw_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "Подтверждение пароля", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_confpassw_label))
}
)
Spacer(modifier = Modifier.padding(all = 20.dp))
Button(
onClick = { openDialogEdit.value = true },
shape = CircleShape,
modifier = Modifier.fillMaxWidth(fraction = 0.75f),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary
)
) {
// Inner content including an icon and a text label
Icon(
imageVector = Icons.Default.Create,
contentDescription = "Favorite",
modifier = Modifier.size(20.dp)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text(text = "Редактировать")
}
Button(
onClick = { openDialogExit.value = true },
shape = CircleShape,
modifier = Modifier.fillMaxWidth(fraction = 0.75f),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.error
)
) {
// Inner content including an icon and a text label
Icon(
imageVector = Icons.Default.ExitToApp,
contentDescription = "Favorite",
modifier = Modifier.size(20.dp)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text(text = "Выход")
}
OutlinedButton(
onClick = { openDialogDelete.value = true },
shape = CircleShape,
modifier = Modifier.fillMaxWidth(fraction = 0.75f),
border= BorderStroke(1.dp, MaterialTheme.colorScheme.error),
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
contentColor = MaterialTheme.colorScheme.error
)
) {
// Inner content including an icon and a text label
Icon(
imageVector = Icons.Outlined.Clear,
contentDescription = "Удалить",
modifier = Modifier.size(20.dp)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text(text = "Удалить аккаунт")
}
}
if (openDialogEdit.value) {
AlertDialog(
icon = {
Icon(Icons.Default.Edit, contentDescription = "Example Icon")
},
title = {
Text(text = "Подтверждение")
},
text = {
Text(text = "Вы хотите применить изменения?")
},
onDismissRequest = {
openDialogEdit.value = false
},
confirmButton = {
TextButton(
onClick = {
openDialogEdit.value = false
/* TODO */
}
) {
Text("Да")
}
},
dismissButton = {
TextButton(
onClick = {
openDialogEdit.value = false
}
) {
Text("Нет")
}
}
)
}
if (openDialogExit.value) {
AlertDialog(
icon = {
Icon(Icons.Default.ExitToApp, contentDescription = "Example Icon")
},
title = {
Text(text = "Подтверждение")
},
text = {
Text(text = "Вы хотите выйти из аккаунта?")
},
onDismissRequest = {
openDialogExit.value = false
},
confirmButton = {
TextButton(
onClick = {
openDialogExit.value = false
navController?.navigate(Screen.Login.route)
}
) {
Text("Да")
}
},
dismissButton = {
TextButton(
onClick = {
openDialogExit.value = false
}
) {
Text("Нет")
}
}
)
}
if (openDialogDelete.value) {
AlertDialog(
icon = {
Icon(Icons.Default.Close, contentDescription = "Example Icon")
},
title = {
Text(text = "Подтверждение")
},
text = {
Text(text = "Вы хотите удалить аккаунт?")
},
onDismissRequest = {
openDialogDelete.value = false
},
confirmButton = {
TextButton(
onClick = {
openDialogDelete.value = false
/* TODO */
}
) {
Text("Да")
}
},
dismissButton = {
TextButton(
onClick = {
openDialogDelete.value = false
}
) {
Text("Нет")
}
}
)
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun ProfilePreview() {
CoffeePreorderTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
Profile(null)
}
}
}

View File

@ -0,0 +1,111 @@
package com.zyzf.coffeepreorder.composeui
import android.content.res.Configuration
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.zyzf.coffeepreorder.R
import com.zyzf.coffeepreorder.composeui.navigation.Screen
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
@Composable
fun Register(navController: NavController?) {
Column(Modifier.padding(all = 10.dp), horizontalAlignment = Alignment.CenterHorizontally) {
Image(
painter = painterResource(id = R.drawable.coffee_image),
contentDescription = "Logo",
modifier = Modifier.size(150.dp)
)
Spacer(modifier = Modifier.padding(all = 20.dp))
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_login_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_fio_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_phone_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_oldpassw_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_newpassw_label))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
value = "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.profile_confpassw_label))
}
)
Spacer(modifier = Modifier.padding(all = 20.dp))
Button(
onClick = { navController?.navigate(Screen.CoffeeList.route) },
shape = CircleShape,
modifier = Modifier.fillMaxWidth(fraction = 0.75f),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary
)
) {
// Inner content including an icon and a text label
Icon(
imageVector = Icons.Default.Add,
contentDescription = "Favorite",
modifier = Modifier.size(20.dp)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text(text = "Зарегистрироваться")
}
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun RegisterPreview() {
CoffeePreorderTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
Register(null)
}
}
}

View File

@ -34,7 +34,11 @@ import androidx.navigation.navArgument
import com.zyzf.coffeepreorder.R import com.zyzf.coffeepreorder.R
import com.zyzf.coffeepreorder.coffee.composeui.CoffeeList import com.zyzf.coffeepreorder.coffee.composeui.CoffeeList
import com.zyzf.coffeepreorder.coffee.composeui.CoffeeView import com.zyzf.coffeepreorder.coffee.composeui.CoffeeView
import com.zyzf.coffeepreorder.composeui.About import com.zyzf.coffeepreorder.composeui.Cart
import com.zyzf.coffeepreorder.composeui.Login
import com.zyzf.coffeepreorder.composeui.Order
import com.zyzf.coffeepreorder.composeui.Profile
import com.zyzf.coffeepreorder.composeui.Register
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -102,11 +106,15 @@ fun Navhost(
) { ) {
NavHost( NavHost(
navController, navController,
startDestination = Screen.CoffeeList.route, startDestination = Screen.Login.route,
modifier.padding(innerPadding) modifier.padding(innerPadding)
) { ) {
composable(Screen.Login.route) { Login(navController) }
composable(Screen.Register.route) { Register(navController) }
composable(Screen.CoffeeList.route) { CoffeeList(navController) } composable(Screen.CoffeeList.route) { CoffeeList(navController) }
composable(Screen.About.route) { About() } composable(Screen.Profile.route) { Profile(navController) }
composable(Screen.Cart.route) { Cart(navController) }
composable(Screen.Order.route) { Order(navController) }
composable( composable(
Screen.CoffeeView.route, Screen.CoffeeView.route,
arguments = listOf(navArgument("id") { type = NavType.IntType }) arguments = listOf(navArgument("id") { type = NavType.IntType })
@ -116,7 +124,6 @@ fun Navhost(
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun MainNavbar() { fun MainNavbar() {
val navController = rememberNavController() val navController = rememberNavController()

View File

@ -2,9 +2,10 @@ package com.zyzf.coffeepreorder.composeui.navigation
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.List import androidx.compose.material.icons.filled.List
import androidx.compose.material.icons.filled.ShoppingCart
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import com.zyzf.coffeepreorder.R import com.zyzf.coffeepreorder.R
@ -14,11 +15,23 @@ enum class Screen(
val icon: ImageVector = Icons.Filled.Favorite, val icon: ImageVector = Icons.Filled.Favorite,
val showInBottomBar: Boolean = true val showInBottomBar: Boolean = true
) { ) {
Login(
"login", R.string.coffee_login, showInBottomBar = false
),
Register(
"register", R.string.coffee_register, showInBottomBar = false
),
CoffeeList( CoffeeList(
"coffee-list", R.string.coffee_main_title, Icons.Filled.List "coffee-list", R.string.coffee_main_title, Icons.Filled.List
), ),
About( Profile(
"about", R.string.about_title, Icons.Filled.Info "profile", R.string.profile_title, Icons.Filled.AccountCircle
),
Cart(
"cart", R.string.coffee_cart, Icons.Filled.ShoppingCart
),
Order(
"order", R.string.coffee_order, Icons.Filled.ShoppingCart
), ),
CoffeeView( CoffeeView(
"coffee-view/{id}", R.string.coffee_view_title, showInBottomBar = false "coffee-view/{id}", R.string.coffee_view_title, showInBottomBar = false
@ -27,7 +40,8 @@ enum class Screen(
companion object { companion object {
val bottomBarItems = listOf( val bottomBarItems = listOf(
CoffeeList, CoffeeList,
About, Profile,
Cart,
) )
fun getItem(route: String): Screen? { fun getItem(route: String): Screen? {

View File

@ -1,11 +1,24 @@
<resources> <resources>
<string name="app_name">Coffee Preorder</string> <string name="app_name">Coffee Preorder</string>
<string name="coffee_login">Логин</string>
<string name="coffee_register">Регистрация</string>
<string name="coffee_main_title">Меню</string> <string name="coffee_main_title">Меню</string>
<string name="coffee_cart">Корзина</string>
<string name="coffee_order">Заказ</string>
<string name="coffee_name">Название</string> <string name="coffee_name">Название</string>
<string name="coffee_cost">Стоимость</string> <string name="coffee_cost">Стоимость</string>
<string name="coffee_ingredients">Ингредиенты</string> <string name="coffee_ingredients">Ингредиенты</string>
<string name="coffee_view_title">Изменить кофе</string> <string name="coffee_view_title">Изменить кофе</string>
<string name="profile_title">Профиль</string>
<string name="profile_login_label">Логин</string>
<string name="profile_fio_label">ФИО</string>
<string name="profile_phone_label">Телефон</string>
<string name="profile_passw_label">Пароль</string>
<string name="profile_oldpassw_label">Старый пароль</string>
<string name="profile_newpassw_label">Новый пароль</string>
<string name="profile_confpassw_label">Подтверждение пароля</string>
<string name="student_firstname">Имя</string> <string name="student_firstname">Имя</string>
<string name="student_lastname">Фамилия</string> <string name="student_lastname">Фамилия</string>
<string name="student_group">Группа</string> <string name="student_group">Группа</string>