bee
This commit is contained in:
parent
4b6bf8a1d7
commit
565abdca18
@ -20,7 +20,39 @@ kotlin {
|
|||||||
jvm("desktop")
|
jvm("desktop")
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
val desktopMain by getting
|
val exposedVersion = "0.61.0"
|
||||||
|
|
||||||
|
val desktopMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(compose.desktop.currentOs)
|
||||||
|
implementation(libs.kotlinx.coroutines.swing)
|
||||||
|
implementation("io.ktor:ktor-client-okhttp:2.3.2")
|
||||||
|
|
||||||
|
implementation("org.postgresql:postgresql:42.7.1")
|
||||||
|
|
||||||
|
implementation("org.jetbrains.exposed:exposed-core:$exposedVersion")
|
||||||
|
implementation("org.jetbrains.exposed:exposed-crypt:$exposedVersion")
|
||||||
|
implementation("org.jetbrains.exposed:exposed-dao:$exposedVersion")
|
||||||
|
implementation("org.jetbrains.exposed:exposed-jdbc:$exposedVersion")
|
||||||
|
implementation("org.jetbrains.exposed:exposed-jodatime:$exposedVersion")
|
||||||
|
implementation("org.jetbrains.exposed:exposed-java-time:$exposedVersion")
|
||||||
|
implementation("org.jetbrains.exposed:exposed-kotlin-datetime:$exposedVersion")
|
||||||
|
implementation("org.jetbrains.exposed:exposed-json:$exposedVersion")
|
||||||
|
implementation("org.jetbrains.exposed:exposed-money:$exposedVersion")
|
||||||
|
implementation("org.jetbrains.exposed:exposed-spring-boot-starter:$exposedVersion")
|
||||||
|
|
||||||
|
implementation("io.ktor:ktor-server-core:2.3.4")
|
||||||
|
implementation("io.ktor:ktor-server-netty:2.3.4")
|
||||||
|
implementation("io.ktor:ktor-server-content-negotiation:2.3.4")
|
||||||
|
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.4")
|
||||||
|
implementation("io.ktor:ktor-server-status-pages:2.3.4")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val commonMain by getting {
|
||||||
|
resources.srcDir("src/commonMain/composeResources")
|
||||||
|
}
|
||||||
|
|
||||||
androidMain.dependencies {
|
androidMain.dependencies {
|
||||||
implementation(compose.preview)
|
implementation(compose.preview)
|
||||||
@ -40,10 +72,16 @@ kotlin {
|
|||||||
implementation("cafe.adriel.voyager:voyager-screenmodel:$voyagerVersion")
|
implementation("cafe.adriel.voyager:voyager-screenmodel:$voyagerVersion")
|
||||||
implementation(compose.preview)
|
implementation(compose.preview)
|
||||||
implementation(libs.androidx.lifecycle.viewmodel)
|
implementation(libs.androidx.lifecycle.viewmodel)
|
||||||
|
implementation("media.kamel:kamel-image:0.7.0")
|
||||||
|
implementation("io.ktor:ktor-client-core:2.3.2")
|
||||||
|
implementation("io.ktor:ktor-client-cio:2.3.2")
|
||||||
|
implementation("io.ktor:ktor-client-okhttp:2.3.2")
|
||||||
|
implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
}
|
}
|
||||||
desktopMain.dependencies {
|
|
||||||
implementation(compose.desktop.currentOs)
|
|
||||||
implementation(libs.kotlinx.coroutines.swing)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,8 +110,12 @@ android {
|
|||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
isCoreLibraryDesugaringEnabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dependencies {
|
||||||
|
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
|
||||||
|
}
|
||||||
|
|
||||||
compose.desktop {
|
compose.desktop {
|
||||||
application {
|
application {
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import android.app.DatePickerDialog
|
||||||
|
import android.widget.DatePicker
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun DatePickerField(
|
||||||
|
onDateSelected: (String) -> Unit,
|
||||||
|
trigger: Boolean,
|
||||||
|
onDismissRequest: () -> Unit
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
if (trigger) {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
DatePickerDialog(
|
||||||
|
context,
|
||||||
|
{ _: DatePicker, year: Int, month: Int, dayOfMonth: Int ->
|
||||||
|
val formatted = "%02d.%02d.%04d".format(dayOfMonth, month + 1, year)
|
||||||
|
onDateSelected(formatted)
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
calendar.get(Calendar.YEAR),
|
||||||
|
calendar.get(Calendar.MONTH),
|
||||||
|
calendar.get(Calendar.DAY_OF_MONTH)
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import android.provider.OpenableColumns
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun GetPath(onPathSelected: (String) -> Unit) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
var launched by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
val launcher = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.GetContent(),
|
||||||
|
onResult = { uri: Uri? ->
|
||||||
|
if (uri != null) {
|
||||||
|
val inputStream = context.contentResolver.openInputStream(uri)
|
||||||
|
val fileName = getFileName(context.contentResolver, uri) ?: "temp_image.jpg"
|
||||||
|
val file = File(context.cacheDir, fileName)
|
||||||
|
val outputStream = FileOutputStream(file)
|
||||||
|
inputStream?.copyTo(outputStream)
|
||||||
|
inputStream?.close()
|
||||||
|
outputStream.close()
|
||||||
|
onPathSelected(file.absolutePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
if (!launched) {
|
||||||
|
launched = true
|
||||||
|
launcher.launch("image/*")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFileName(contentResolver: android.content.ContentResolver, uri: Uri): String? {
|
||||||
|
val returnCursor = contentResolver.query(uri, null, null, null, null)
|
||||||
|
returnCursor?.use {
|
||||||
|
val nameIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME)
|
||||||
|
if (it.moveToFirst()) {
|
||||||
|
return it.getString(nameIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import org.example.project.R
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun IconPrinter(resourceName: String, modifier: Modifier) {
|
||||||
|
val resId = when (resourceName) {
|
||||||
|
"calendar" -> R.drawable.map
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = resId),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = modifier,
|
||||||
|
contentScale = ContentScale.FillBounds
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
|
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.res.imageResource
|
||||||
|
import org.example.project.R
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun ImageFromPath(path: String, modifier: Modifier) {
|
||||||
|
val imageBitmap: ImageBitmap? = when {
|
||||||
|
path.isEmpty() -> {
|
||||||
|
ImageBitmap.imageResource(id = R.drawable.basic_photo)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val file = File(path)
|
||||||
|
if (file.exists()) {
|
||||||
|
val bitmap = BitmapFactory.decodeFile(file.absolutePath)
|
||||||
|
bitmap?.asImageBitmap()
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageBitmap != null) {
|
||||||
|
Image(
|
||||||
|
painter = BitmapPainter(imageBitmap),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = modifier,
|
||||||
|
contentScale = ContentScale.Crop
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Box(modifier = modifier.fillMaxSize())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import org.example.project.Models.Fond
|
||||||
|
import org.example.project.Models.User
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
actual class UserRepository {
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
actual fun fetchUsers(): List<User> {
|
||||||
|
var users = listOf(
|
||||||
|
User(
|
||||||
|
id = 1,
|
||||||
|
email = "email1@gmail.com",
|
||||||
|
password = "qwerty",
|
||||||
|
name = "bob",
|
||||||
|
surname = "bobby",
|
||||||
|
gender = "Мужской",
|
||||||
|
photopath = "/Users/rinchi/Desktop/vpn4ik.jpg",
|
||||||
|
LocalDate.of(2006, 1, 16),
|
||||||
|
country = "Russia",
|
||||||
|
active = false
|
||||||
|
),
|
||||||
|
User(
|
||||||
|
id = 2,
|
||||||
|
email = "email2@gmail.com",
|
||||||
|
password = "qwerty",
|
||||||
|
name = "bob",
|
||||||
|
surname = "bobby",
|
||||||
|
gender = "Мужской",
|
||||||
|
photopath = "/Users/rinchi/Desktop/vpn4ik.jpg",
|
||||||
|
LocalDate.of(2006, 1, 16),
|
||||||
|
country = "Russia",
|
||||||
|
active = false
|
||||||
|
), )
|
||||||
|
return users
|
||||||
|
}
|
||||||
|
actual fun regUser(user: User): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
actual fun fetchFonds(): List<Fond> {
|
||||||
|
var fonds = listOf(
|
||||||
|
Fond(
|
||||||
|
id = 1,
|
||||||
|
name = "first",
|
||||||
|
balance = 1000
|
||||||
|
),
|
||||||
|
Fond(
|
||||||
|
id = 2,
|
||||||
|
name = "second",
|
||||||
|
balance = 2000
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return fonds
|
||||||
|
}
|
||||||
|
actual fun withdrawalBalance(idFond: Int, dedSum: Int): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
actual fun getUserIdByEmail(email: String): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
actual fun updateUserActive(idUser: Int): Boolean{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
actual fun topUpBalance(idFond: Int, sum: Int): Boolean{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
BIN
composeApp/src/commonMain/composeResources/drawable/defPhoto.png
Normal file
BIN
composeApp/src/commonMain/composeResources/drawable/defPhoto.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
composeApp/src/commonMain/composeResources/drawable/map.jpg
Normal file
BIN
composeApp/src/commonMain/composeResources/drawable/map.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
package org.example.project.Models
|
||||||
|
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
data class Fond(
|
||||||
|
val id: Int,
|
||||||
|
val name: String,
|
||||||
|
val balance: Int
|
||||||
|
)
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.example.project.Models
|
||||||
|
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
|
data class User(
|
||||||
|
val id: Int,
|
||||||
|
val email: String,
|
||||||
|
val password: String,
|
||||||
|
val name: String,
|
||||||
|
val surname: String,
|
||||||
|
val gender: String,
|
||||||
|
val photopath: String,
|
||||||
|
val birthday: LocalDate,
|
||||||
|
val country: String,
|
||||||
|
val active: Boolean
|
||||||
|
)
|
@ -0,0 +1,10 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun DatePickerField(
|
||||||
|
onDateSelected: (String) -> Unit,
|
||||||
|
trigger: Boolean,
|
||||||
|
onDismissRequest: () -> Unit
|
||||||
|
)
|
@ -0,0 +1,106 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.DropdownMenu
|
||||||
|
import androidx.compose.material.DropdownMenuItem
|
||||||
|
import androidx.compose.material.Icon
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.TextUnit
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FieldWithDropdown(
|
||||||
|
label: String,
|
||||||
|
options: List<String>,
|
||||||
|
selectedOption: String,
|
||||||
|
onOptionSelected: (String) -> Unit,
|
||||||
|
fontSize: TextUnit,
|
||||||
|
labelWidth: Float
|
||||||
|
) {
|
||||||
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier.weight(labelWidth)) {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
fontSize = fontSize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.White, shape = RoundedCornerShape(4.dp))
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = Color(0xFFCCCCCC),
|
||||||
|
shape = RoundedCornerShape(4.dp)
|
||||||
|
)
|
||||||
|
.clickable { expanded = true }
|
||||||
|
.padding(12.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = selectedOption.ifEmpty { "..." },
|
||||||
|
fontSize = fontSize,
|
||||||
|
color = if (selectedOption.isEmpty()) Color.LightGray else Color.Black
|
||||||
|
)
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.ArrowDropDown,
|
||||||
|
contentDescription = "Dropdown Arrow",
|
||||||
|
tint = Color.Gray
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false },
|
||||||
|
modifier = Modifier
|
||||||
|
.background(Color.White)
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
options.forEach { option ->
|
||||||
|
DropdownMenuItem(
|
||||||
|
onClick = {
|
||||||
|
onOptionSelected(option)
|
||||||
|
expanded = false
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(option, fontSize = fontSize, color = Color.Black)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.material.OutlinedTextField
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.TextUnit
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FieldWithLabel(
|
||||||
|
label: String,
|
||||||
|
value: String,
|
||||||
|
onValueChange: (String) -> Unit,
|
||||||
|
placeholder: String,
|
||||||
|
fontSize: TextUnit,
|
||||||
|
labelWidth: Float,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier.weight(labelWidth)) {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
fontSize = fontSize,
|
||||||
|
modifier = Modifier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = onValueChange,
|
||||||
|
placeholder = {
|
||||||
|
if (placeholder.isNotEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = placeholder,
|
||||||
|
fontSize = fontSize,
|
||||||
|
color = Color.LightGray
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(
|
||||||
|
fontSize = fontSize,
|
||||||
|
color = Color.Black
|
||||||
|
),
|
||||||
|
enabled = enabled,
|
||||||
|
colors = androidx.compose.material.TextFieldDefaults.outlinedTextFieldColors(
|
||||||
|
backgroundColor = Color.White,
|
||||||
|
cursorColor = Color.Black,
|
||||||
|
textColor = Color.Black,
|
||||||
|
placeholderColor = Color.LightGray,
|
||||||
|
focusedBorderColor = Color(0xFFCCCCCC),
|
||||||
|
unfocusedBorderColor = Color(0xFFCCCCCC),
|
||||||
|
disabledBorderColor = Color(0xFFCCCCCC)
|
||||||
|
),
|
||||||
|
modifier = Modifier.weight(1f).wrapContentWidth().fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.material.OutlinedTextField
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.TextUnit
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FieldWithLabelInt(
|
||||||
|
label: String,
|
||||||
|
value: Int,
|
||||||
|
onValueChange: (Int) -> Unit,
|
||||||
|
placeholder: String,
|
||||||
|
fontSize: TextUnit,
|
||||||
|
labelWidth: Float,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier.weight(labelWidth)) {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
fontSize = fontSize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = value.toString(),
|
||||||
|
onValueChange = { newValue ->
|
||||||
|
val intValue = newValue.toIntOrNull()
|
||||||
|
if (intValue != null) {
|
||||||
|
onValueChange(intValue)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
placeholder = {
|
||||||
|
if (placeholder.isNotEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = placeholder,
|
||||||
|
fontSize = fontSize,
|
||||||
|
color = Color.LightGray
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(
|
||||||
|
fontSize = fontSize,
|
||||||
|
color = Color.Black
|
||||||
|
),
|
||||||
|
enabled = enabled,
|
||||||
|
colors = androidx.compose.material.TextFieldDefaults.outlinedTextFieldColors(
|
||||||
|
backgroundColor = Color.White,
|
||||||
|
cursorColor = Color.Black,
|
||||||
|
textColor = Color.Black,
|
||||||
|
placeholderColor = Color.LightGray,
|
||||||
|
focusedBorderColor = Color(0xFFCCCCCC),
|
||||||
|
unfocusedBorderColor = Color(0xFFCCCCCC),
|
||||||
|
disabledBorderColor = Color(0xFFCCCCCC)
|
||||||
|
),
|
||||||
|
keyboardOptions = KeyboardOptions(
|
||||||
|
keyboardType = KeyboardType.Number,
|
||||||
|
imeAction = ImeAction.Done
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.wrapContentWidth()
|
||||||
|
.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun GetPath(onPathSelected: (String) -> Unit)
|
@ -0,0 +1,7 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun IconPrinter(resourceName: String, modifier: Modifier = Modifier)
|
@ -0,0 +1,7 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun ImageFromPath(path: String = "", modifier: Modifier = Modifier)
|
@ -0,0 +1,33 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.TextUnit
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun InfoButton(text: String, fontSize: TextUnit, onClick: () -> Unit) {
|
||||||
|
Button(
|
||||||
|
onClick = onClick,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(80.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
) {
|
||||||
|
Text(text = text, fontStyle = FontStyle.Italic, fontSize = fontSize, textAlign = TextAlign.Center)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
|
||||||
|
class RegRunnerViewModel : ViewModel() {
|
||||||
|
var email by mutableStateOf("")
|
||||||
|
var password by mutableStateOf("")
|
||||||
|
var secondPassword by mutableStateOf("")
|
||||||
|
var name by mutableStateOf("")
|
||||||
|
var surname by mutableStateOf("")
|
||||||
|
var gender by mutableStateOf("")
|
||||||
|
var country by mutableStateOf("")
|
||||||
|
var photoPath by mutableStateOf("")
|
||||||
|
var dateBirthday by mutableStateOf("")
|
||||||
|
}
|
@ -6,16 +6,21 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
class TimerViewModel : ViewModel() {
|
class TimerViewModel : ViewModel() {
|
||||||
|
|
||||||
private val _remainingTime = MutableStateFlow("18 дней 17 часов и 10 минут до старта марафона")
|
|
||||||
val remainingTime: StateFlow<String> = _remainingTime
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
startTimer()
|
startTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val _remainingTime = MutableStateFlow("18 дней 17 часов и 10 минут до старта марафона")
|
||||||
|
val remainingTime: StateFlow<String> = _remainingTime
|
||||||
|
|
||||||
private fun startTimer() {
|
private fun startTimer() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
var remainingMillis = (18 * 24 * 60 * 60 * 1000) + (17 * 60 * 60 * 1000) + (10 * 60 * 1000)
|
var remainingMillis = (18 * 24 * 60 * 60 * 1000) + (17 * 60 * 60 * 1000) + (10 * 60 * 1000)
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import org.example.project.Models.Fond
|
||||||
|
import org.example.project.Models.User
|
||||||
|
|
||||||
|
expect class UserRepository() {
|
||||||
|
fun fetchUsers(): List<User>
|
||||||
|
fun regUser(user: User): Boolean
|
||||||
|
fun fetchFonds(): List<Fond>
|
||||||
|
fun withdrawalBalance(idFond: Int, dedSum: Int): Boolean
|
||||||
|
fun getUserIdByEmail(email: String): Int
|
||||||
|
fun updateUserActive(idUser: Int): Boolean
|
||||||
|
fun topUpBalance(idFond: Int, sum: Int): Boolean
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import org.example.project.Models.Fond
|
||||||
|
import org.example.project.Models.User
|
||||||
|
|
||||||
|
class UserViewModel {
|
||||||
|
private val userRepository = UserRepository()
|
||||||
|
|
||||||
|
fun getUsers(): List<User> {
|
||||||
|
return userRepository.fetchUsers()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun regUser(user: User): Boolean {
|
||||||
|
return userRepository.regUser(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFond(): List<Fond>{
|
||||||
|
return userRepository.fetchFonds()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withdrawalBalance(idFond: Int, dedSum: Int): Boolean{
|
||||||
|
return userRepository.withdrawalBalance(idFond, dedSum)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUserIdByEmail(email: String): Int{
|
||||||
|
return userRepository.getUserIdByEmail(email)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateUserActive(idUser: Int): Boolean{
|
||||||
|
return userRepository.updateUserActive(idUser)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun topUpBalance(idFond: Int, sum: Int): Boolean{
|
||||||
|
return userRepository.topUpBalance(idFond, sum)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,346 @@
|
|||||||
|
package org.example.project.ui.Screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.Icon
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Scaffold
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.DateRange
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import org.example.project.ViewModel.IconPrinter
|
||||||
|
import org.example.project.ViewModel.TimerViewModel
|
||||||
|
|
||||||
|
|
||||||
|
class AboutMarathonScreen(private val timerViewModel: TimerViewModel) : Screen {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = { AboutMarathonTopBar() },
|
||||||
|
bottomBar = { AboutMarathonBottomBar(timerViewModel = timerViewModel) }
|
||||||
|
) { paddingValues ->
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(paddingValues)
|
||||||
|
) {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
.padding(horizontal = 20.dp)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 25).sp
|
||||||
|
val fontSizeSecond = (maxWidth.value / 35).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
.fillMaxSize(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Информация о Marathon Skills 2016",
|
||||||
|
color = Color.Black,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSize,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(0.6f)
|
||||||
|
.padding(end = 8.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.aspectRatio(3f)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.border(width = 2.dp, color = Color.Black, shape = RoundedCornerShape(15.dp))
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.LightGray)
|
||||||
|
.clickable { },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
IconPrinter(
|
||||||
|
resourceName = "map",
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.aspectRatio(1.7f)
|
||||||
|
.border(2.dp, Color.Black, RoundedCornerShape(15.dp))
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.LightGray)
|
||||||
|
.clickable { },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
IconPrinter(
|
||||||
|
resourceName = "map",
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.aspectRatio(1.7f)
|
||||||
|
.border(2.dp, Color.Black, RoundedCornerShape(15.dp))
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.LightGray)
|
||||||
|
.clickable { },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
IconPrinter(
|
||||||
|
resourceName = "map",
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.aspectRatio(1.7f)
|
||||||
|
.border(2.dp, Color.Black, RoundedCornerShape(15.dp))
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.LightGray)
|
||||||
|
.clickable { },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
IconPrinter(
|
||||||
|
resourceName = "map",
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.aspectRatio(1.7f)
|
||||||
|
.border(2.dp, Color.Black, RoundedCornerShape(15.dp))
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.LightGray)
|
||||||
|
.clickable { },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
IconPrinter(
|
||||||
|
resourceName = "map",
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(start = 8.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Информация о Marathon Skills 2016",
|
||||||
|
color = Color.Black,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.3f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Информация о Marathon Skills 2016",
|
||||||
|
color = Color.Black,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.3f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Информация о Marathon Skills 2016",
|
||||||
|
color = Color.Black,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.3f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun AboutMarathonTopBar() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSizeButton = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeText = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Назад",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(24.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "MARATHON SKILLS 2016",
|
||||||
|
style = MaterialTheme.typography.h6,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
textAlign = TextAlign.Left,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = fontSizeText,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(64.dp))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Logout",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun AboutMarathonBottomBar(timerViewModel: TimerViewModel) {
|
||||||
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 50).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(8.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = remainingTime,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,217 @@
|
|||||||
|
package org.example.project.ui.Screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
|
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.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Scaffold
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import org.example.project.ViewModel.TimerViewModel
|
||||||
|
|
||||||
|
class ConfirmRunnerScreen(private val timerViewModel: TimerViewModel, private val idRunner: Int) :
|
||||||
|
Screen {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = { ConfirmRunnerTopBar() },
|
||||||
|
bottomBar = { ConfirmRunnerBottomBar(timerViewModel = timerViewModel) }
|
||||||
|
) { paddingValues ->
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.padding(paddingValues)
|
||||||
|
) {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
.padding(horizontal = 100.dp)
|
||||||
|
) {
|
||||||
|
val fontSizeFirst = (maxWidth.value / 30).sp
|
||||||
|
val fontSizeSecond = (maxWidth.value / 40).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth().padding(bottom = 16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.weight(0.2f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "Спасибо за вашу регистрацию в качестве бегуна!",
|
||||||
|
color = Color.Gray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.2f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "Спасибо за вашу регистрацию в качестве бегуна в Marathon Skills 2016!\n С вами свяжутся по поводу оплаты.",
|
||||||
|
color = Color.Black,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.2f))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(InfoRunnerScreen(timerViewModel, idRunner)) },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(48.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text("Ок", fontSize = fontSizeSecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ConfirmRunnerTopBar() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSizeButton = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeText = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Назад",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(24.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "MARATHON SKILLS 2016",
|
||||||
|
style = MaterialTheme.typography.h6,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
textAlign = TextAlign.Left,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = fontSizeText,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(64.dp))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Logout",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ConfirmRunnerBottomBar(timerViewModel: TimerViewModel) {
|
||||||
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 50).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(8.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = remainingTime,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,234 @@
|
|||||||
|
package org.example.project.ui.Screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
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.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Scaffold
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import org.example.project.ViewModel.TimerViewModel
|
||||||
|
|
||||||
|
class ConfirmSponsorScreen(private val timerViewModel: TimerViewModel, private val sumSpons: String, private val runner: String, private val blagot: String) :
|
||||||
|
Screen {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = { ConfirmSponsorTopBar() },
|
||||||
|
bottomBar = { ConfirmSponsorBottomBar(timerViewModel = timerViewModel) }
|
||||||
|
) { paddingValues ->
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.padding(paddingValues)
|
||||||
|
) {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
.padding(horizontal = 100.dp)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 60).sp
|
||||||
|
val fontSizeFirst = (maxWidth.value / 30).sp
|
||||||
|
val fontSizeSecond = (maxWidth.value / 40).sp
|
||||||
|
val fontSizeThird = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeFourth = (maxWidth.value / 10).sp
|
||||||
|
val fontSizeFiveth = (maxWidth.value / 20).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth().padding(bottom = 16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "Спасибо за вашу спонсорскую поддержку!",
|
||||||
|
color = Color.Gray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "Спасибо за поддержку бегуна в Marathon Skills 2016! Ваше пожертвование пойдёт в его благотворительную организацию",
|
||||||
|
color = Color.Black,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = runner,
|
||||||
|
color = Color.Black,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = blagot,
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFiveth,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = sumSpons,
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFourth,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(48.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text("Назад", fontSize = fontSizeSecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ConfirmSponsorTopBar() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSizeButton = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeText = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Назад",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(24.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "MARATHON SKILLS 2016",
|
||||||
|
style = MaterialTheme.typography.h6,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
textAlign = TextAlign.Left,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = fontSizeText,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ConfirmSponsorBottomBar(timerViewModel: TimerViewModel) {
|
||||||
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 50).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(8.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = remainingTime,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,71 +23,88 @@ import androidx.compose.runtime.*
|
|||||||
import androidx.compose.ui.Alignment
|
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.text.font.FontStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
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.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import org.example.project.ViewModel.RegRunnerViewModel
|
||||||
import org.example.project.ViewModel.TimerViewModel
|
import org.example.project.ViewModel.TimerViewModel
|
||||||
|
|
||||||
class RunnerScreen(private val timerViewModel: TimerViewModel) : Screen {
|
class RunnerScreen(private val timerViewModel: TimerViewModel) : Screen {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
val buttonSize = Modifier
|
|
||||||
.width(400.dp)
|
|
||||||
.height(80.dp)
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { RunnerTopBar() },
|
topBar = { RunnerTopBar() },
|
||||||
bottomBar = { RunnerBottomBar(timerViewModel = timerViewModel) }
|
bottomBar = { RunnerBottomBar(timerViewModel = timerViewModel) }
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(paddingValues)
|
.padding(paddingValues)
|
||||||
.fillMaxSize()
|
|
||||||
) {
|
) {
|
||||||
Column(
|
BoxWithConstraints(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.align(Alignment.Center)
|
.align(Alignment.Center)
|
||||||
.padding(horizontal = 30.dp),
|
.padding(horizontal = 100.dp)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = { },
|
onClick = { navigator.push(LoginScreen(timerViewModel)) },
|
||||||
modifier = buttonSize,
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
backgroundColor = Color.LightGray,
|
backgroundColor = Color.LightGray,
|
||||||
contentColor = Color.Black
|
contentColor = Color.Black
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(15.dp)
|
shape = RoundedCornerShape(15.dp)
|
||||||
) {
|
) {
|
||||||
Text("Я участвовал ранее",
|
Text(
|
||||||
fontSize = 16.sp
|
"Я участвовал ранее",
|
||||||
|
fontSize = fontSize
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.weight(0.25f))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = { },
|
onClick = { navigator.push(RegRunnerScreen(timerViewModel)) },
|
||||||
modifier = buttonSize,
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
backgroundColor = Color.LightGray,
|
backgroundColor = Color.LightGray,
|
||||||
contentColor = Color.Black
|
contentColor = Color.Black
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(15.dp)
|
shape = RoundedCornerShape(15.dp)
|
||||||
) {
|
) {
|
||||||
Text("Я новый участник",
|
Text(
|
||||||
fontSize = 16.sp
|
"Я новый участник",
|
||||||
|
fontSize = fontSize
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = { },
|
onClick = { navigator.push(LoginScreen(timerViewModel)) },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.BottomEnd)
|
.align(Alignment.BottomEnd)
|
||||||
.height(65.dp)
|
.height(65.dp)
|
||||||
@ -108,6 +125,15 @@ class RunnerScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
private fun RunnerTopBar() {
|
private fun RunnerTopBar() {
|
||||||
val navigator = LocalNavigator.currentOrThrow
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSizeButton = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeText = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -129,8 +155,10 @@ class RunnerScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
.wrapContentWidth()
|
.wrapContentWidth()
|
||||||
|
|
||||||
) {
|
) {
|
||||||
Text(text = "Назад",
|
Text(
|
||||||
|
text = "Назад",
|
||||||
color = Color.Black,
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,17 +170,25 @@ class RunnerScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
textAlign = TextAlign.Left,
|
textAlign = TextAlign.Left,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = MaterialTheme.typography.h4.fontSize,
|
fontSize = fontSizeText,
|
||||||
color = Color.White
|
color = Color.White
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(64.dp))
|
Spacer(modifier = Modifier.width(64.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun RunnerBottomBar(timerViewModel: TimerViewModel) {
|
private fun RunnerBottomBar(timerViewModel: TimerViewModel) {
|
||||||
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 50).sp
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -161,8 +197,13 @@ class RunnerScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
.padding(8.dp),
|
.padding(8.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Text(text = remainingTime,
|
Text(
|
||||||
color = Color.White)
|
text = remainingTime,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,466 @@
|
|||||||
|
package org.example.project.ui.Screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.OutlinedTextField
|
||||||
|
import androidx.compose.material.Scaffold
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import org.example.project.ViewModel.FieldWithDropdown
|
||||||
|
import org.example.project.ViewModel.FieldWithLabel
|
||||||
|
import org.example.project.ViewModel.TimerViewModel
|
||||||
|
import org.example.project.ViewModel.UserViewModel
|
||||||
|
|
||||||
|
class ForSponsorScreen(private val timerViewModel: TimerViewModel) : Screen {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
val viewModel = UserViewModel()
|
||||||
|
val fonds = viewModel.getFond()
|
||||||
|
val runners = viewModel.getUsers()
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = { ForSponsorTopBar() },
|
||||||
|
bottomBar = { ForSposnorBottomBar(timerViewModel = timerViewModel) }
|
||||||
|
) { paddingValues ->
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.padding(paddingValues)
|
||||||
|
) {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
.padding(horizontal = 100.dp)
|
||||||
|
) {
|
||||||
|
val fontSizeFirst = (maxWidth.value / 30).sp
|
||||||
|
val fontSizeSecond = (maxWidth.value / 40).sp
|
||||||
|
val fontSizeThird = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeFourth = (maxWidth.value / 10).sp
|
||||||
|
val labelWidth = 0.5f
|
||||||
|
var fondsNames = fonds.map { it.name }
|
||||||
|
var runnersNames = runners.map { it.name }
|
||||||
|
var selectedFondName by remember { mutableStateOf("") }
|
||||||
|
var fio by remember { mutableStateOf("") }
|
||||||
|
var runner by remember { mutableStateOf("") }
|
||||||
|
var cardName by remember { mutableStateOf("") }
|
||||||
|
var cardNum by remember { mutableStateOf("") }
|
||||||
|
var srokM by remember { mutableStateOf("") }
|
||||||
|
var srokY by remember { mutableStateOf("") }
|
||||||
|
var cvc by remember { mutableStateOf("") }
|
||||||
|
var sumChangStr by remember { mutableStateOf("10")}
|
||||||
|
var sumChang by remember { mutableStateOf(sumChangStr.toInt()) }
|
||||||
|
var sumSpons by remember { mutableStateOf(0)}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth().padding(bottom = 16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Спонсор бегуна",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Пожалуйста выберите бегуна, которого вы хотели бы спонсировать и сумму, которую вы хотели бы спонсировать. Спасибо за вашу поддержку бегунов и их благотворительных учреждений.",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.2f))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier.weight(1f),) {
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "Информация о спонсоре",
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "Ваше имя:",
|
||||||
|
value = fio,
|
||||||
|
onValueChange = { fio = it },
|
||||||
|
placeholder = "Ваше имя",
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithDropdown(
|
||||||
|
label = "Бегун:",
|
||||||
|
options = runnersNames,
|
||||||
|
selectedOption = runner,
|
||||||
|
onOptionSelected = { runner = it },
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
labelWidth = labelWidth
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "Карта:",
|
||||||
|
value = cardName,
|
||||||
|
onValueChange = { cardName = it },
|
||||||
|
placeholder = "Владелец карты",
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "Номер карты#:",
|
||||||
|
value = cardNum,
|
||||||
|
onValueChange = { cardNum = it },
|
||||||
|
placeholder = "...",
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Срок действия:",
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
color = Color.Black,
|
||||||
|
modifier = Modifier.weight(labelWidth)
|
||||||
|
)
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = srokM,
|
||||||
|
onValueChange = { srokM = it },
|
||||||
|
placeholder = { Text("MM", fontSize = fontSizeSecond) },
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
color = Color.Black
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.weight((1f - labelWidth) / 2)
|
||||||
|
.padding(end = 4.dp),
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = srokY,
|
||||||
|
onValueChange = { srokY = it },
|
||||||
|
placeholder = { Text("YY", fontSize = fontSizeSecond) },
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
color = Color.Black
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.weight((1f - labelWidth) / 2)
|
||||||
|
.padding(start = 4.dp),
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "CVC:",
|
||||||
|
value = cvc,
|
||||||
|
onValueChange = { cvc = it },
|
||||||
|
placeholder = "...",
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(modifier = Modifier.weight(1f),) {
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "Благотворительность",
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithDropdown(
|
||||||
|
label = "",
|
||||||
|
options = fondsNames,
|
||||||
|
selectedOption = selectedFondName,
|
||||||
|
onOptionSelected = { selectedFondName = it },
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
labelWidth = 0.5f
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.5f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "Сумма пожертвования",
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "$" + sumSpons.toString(),
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFourth,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(0.2f)
|
||||||
|
.aspectRatio(1f),
|
||||||
|
onClick = {
|
||||||
|
sumSpons -= sumChang
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(8.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
Text("-", fontSize = fontSizeSecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = sumChangStr,
|
||||||
|
onValueChange = {
|
||||||
|
sumChangStr = it
|
||||||
|
sumChang = it.toIntOrNull() ?: 0
|
||||||
|
},
|
||||||
|
placeholder = { Text("...", fontSize = fontSizeSecond) },
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
color = Color.Black,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(0.6f)
|
||||||
|
.padding(horizontal = 4.dp),
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(0.2f)
|
||||||
|
.aspectRatio(1f),
|
||||||
|
onClick = {
|
||||||
|
sumSpons += sumChang
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(8.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
Text("+", fontSize = fontSizeSecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.5f))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val selectedFond = fonds.find { it.name == selectedFondName }
|
||||||
|
if (selectedFond != null) {
|
||||||
|
val result = viewModel.topUpBalance(selectedFond.id, sumSpons)
|
||||||
|
if (result){
|
||||||
|
navigator.push(ConfirmSponsorScreen(timerViewModel, sumSpons.toString(), runner, selectedFondName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text("Заплатить", fontSize = fontSizeThird)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text("Отмена", fontSize = fontSizeThird)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ForSponsorTopBar() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSizeButton = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeText = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Назад",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(24.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "MARATHON SKILLS 2016",
|
||||||
|
style = MaterialTheme.typography.h6,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
textAlign = TextAlign.Left,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = fontSizeText,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ForSposnorBottomBar(timerViewModel: TimerViewModel) {
|
||||||
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 50).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(8.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = remainingTime,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,215 @@
|
|||||||
|
package org.example.project.ui.Screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
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.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Scaffold
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import org.example.project.ViewModel.InfoButton
|
||||||
|
import org.example.project.ViewModel.TimerViewModel
|
||||||
|
|
||||||
|
|
||||||
|
class InfoRunnerScreen(private val timerViewModel: TimerViewModel, private val idRunner: Int) : Screen {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = { InfoRunnerTopBar() },
|
||||||
|
bottomBar = { InfoRunnerBottomBar(timerViewModel = timerViewModel) }
|
||||||
|
) { paddingValues ->
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(paddingValues)
|
||||||
|
) {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
.padding(horizontal = 100.dp)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 25).sp
|
||||||
|
val fontSizeButton = (maxWidth.value / 40).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
.fillMaxSize(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Подробная информация",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSize,
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(end = 8.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
InfoButton("Регистрация на марафон", fontSizeButton, {navigator.push(RegMaraphonScreen(timerViewModel, idRunner))})
|
||||||
|
InfoButton("Редактирование профиля", fontSizeButton, {})
|
||||||
|
InfoButton("Контакты", fontSizeButton, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(start = 8.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
InfoButton("Мои результаты", fontSizeButton, {})
|
||||||
|
InfoButton("Мои спонсоры", fontSizeButton, {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun InfoRunnerTopBar() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSizeButton = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeText = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Назад",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(24.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "MARATHON SKILLS 2016",
|
||||||
|
style = MaterialTheme.typography.h6,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
textAlign = TextAlign.Left,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = fontSizeText,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(64.dp))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Logout",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun InfoRunnerBottomBar(timerViewModel: TimerViewModel) {
|
||||||
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 50).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(8.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = remainingTime,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,258 @@
|
|||||||
|
package org.example.project.ui.Screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Scaffold
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import org.example.project.ViewModel.FieldWithLabel
|
||||||
|
import org.example.project.ViewModel.TimerViewModel
|
||||||
|
import org.example.project.ViewModel.UserViewModel
|
||||||
|
|
||||||
|
class LoginScreen(private val timerViewModel: TimerViewModel) : Screen {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = { LoginTopBar() },
|
||||||
|
bottomBar = { LoginBottomBar(timerViewModel = timerViewModel) }
|
||||||
|
) { paddingValues ->
|
||||||
|
|
||||||
|
val viewModel = UserViewModel()
|
||||||
|
val users = viewModel.getUsers()
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.padding(paddingValues)
|
||||||
|
) {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
.padding(horizontal = 100.dp)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 25).sp
|
||||||
|
val fontSizeFirst = (maxWidth.value / 20).sp
|
||||||
|
val fontSizeSecond = (maxWidth.value / 35).sp
|
||||||
|
val labelWidth = 0.25f
|
||||||
|
var email by remember { mutableStateOf("") }
|
||||||
|
var password by remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
Spacer(Modifier.weight(0.25f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Форма авторизации",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.25f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Пожалуйста, авторизуйтесь в системе, используя\n ваш адрес электронной почты и пароль",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.25f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "Email:",
|
||||||
|
value = email,
|
||||||
|
onValueChange = { email = it },
|
||||||
|
placeholder = "Enter your email address",
|
||||||
|
fontSize = fontSize,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.25f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "Password:",
|
||||||
|
value = password,
|
||||||
|
onValueChange = { password = it },
|
||||||
|
placeholder = "Enter your password",
|
||||||
|
fontSize = fontSize,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.25f))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val user = users.find { it.email == email }
|
||||||
|
if (user != null && user.password == password) {
|
||||||
|
val userId = viewModel.getUserIdByEmail(user.email)
|
||||||
|
navigator.push(InfoRunnerScreen(timerViewModel, userId))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
"Login",
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.25f))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
"Cancel",
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun LoginTopBar() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSizeButton = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeText = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Назад",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(24.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "MARATHON SKILLS 2016",
|
||||||
|
style = MaterialTheme.typography.h6,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
textAlign = TextAlign.Left,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = fontSizeText,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(64.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun LoginBottomBar(timerViewModel: TimerViewModel) {
|
||||||
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 50).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(8.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = remainingTime,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,6 @@ import androidx.compose.ui.unit.sp
|
|||||||
import cafe.adriel.voyager.core.screen.Screen
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
|
|
||||||
class MainScreen : Screen {
|
class MainScreen : Screen {
|
||||||
|
|
||||||
@ -26,10 +25,6 @@ class MainScreen : Screen {
|
|||||||
val navigator = LocalNavigator.currentOrThrow
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
val timerViewModel = TimerViewModel()
|
val timerViewModel = TimerViewModel()
|
||||||
|
|
||||||
val buttonSize = Modifier
|
|
||||||
.width(400.dp)
|
|
||||||
.height(80.dp)
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { MainWindowTopBar() },
|
topBar = { MainWindowTopBar() },
|
||||||
bottomBar = { MainWindowBottomBar(timerViewModel) }
|
bottomBar = { MainWindowBottomBar(timerViewModel) }
|
||||||
@ -37,65 +32,73 @@ class MainScreen : Screen {
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(paddingValues)
|
.padding(paddingValues)
|
||||||
.fillMaxSize()
|
|
||||||
) {
|
) {
|
||||||
Column(
|
BoxWithConstraints(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.align(Alignment.Center)
|
.align(Alignment.Center)
|
||||||
.padding(horizontal = 30.dp),
|
.padding(horizontal = 100.dp)
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
) {
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.weight(0.25f))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = { navigator.push(RunnerScreen(timerViewModel)) },
|
onClick = { navigator.push(RunnerScreen(timerViewModel)) },
|
||||||
modifier = buttonSize,
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
backgroundColor = Color.LightGray,
|
backgroundColor = Color.LightGray,
|
||||||
contentColor = Color.Black
|
contentColor = Color.Black
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(15.dp)
|
shape = RoundedCornerShape(15.dp)
|
||||||
) {
|
) {
|
||||||
Text("Я хочу стать бегуном",
|
Text("Я хочу стать бегуном", fontSize = fontSize)
|
||||||
fontSize = 16.sp
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = { },
|
onClick = { navigator.push(ForSponsorScreen(timerViewModel))},
|
||||||
modifier = buttonSize,
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
backgroundColor = Color.LightGray,
|
backgroundColor = Color.LightGray,
|
||||||
contentColor = Color.Black
|
contentColor = Color.Black
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(15.dp)
|
shape = RoundedCornerShape(15.dp)
|
||||||
) {
|
) {
|
||||||
Text("Я хочу стать спонсором бегуна",
|
Text("Я хочу стать спонсором бегуна", fontSize = fontSize)
|
||||||
fontSize = 16.sp
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = { navigator.push(MoreInfoScreen(timerViewModel)) },
|
onClick = { navigator.push(MoreInfoScreen(timerViewModel)) },
|
||||||
modifier = buttonSize,
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
backgroundColor = Color.LightGray,
|
backgroundColor = Color.LightGray,
|
||||||
contentColor = Color.Black
|
contentColor = Color.Black
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(15.dp)
|
shape = RoundedCornerShape(15.dp)
|
||||||
) {
|
) {
|
||||||
Text(text = "Я хочу узнать больше о событии",
|
Text("Я хочу узнать больше о событии", fontSize = fontSize)
|
||||||
fontSize = 16.sp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.5f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = { },
|
onClick = { navigator.push(LoginScreen(timerViewModel)) },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.BottomEnd)
|
.align(Alignment.BottomEnd)
|
||||||
.height(65.dp)
|
.height(65.dp)
|
||||||
@ -106,7 +109,7 @@ class MainScreen : Screen {
|
|||||||
),
|
),
|
||||||
shape = RoundedCornerShape(15.dp)
|
shape = RoundedCornerShape(15.dp)
|
||||||
) {
|
) {
|
||||||
Text(text = "Login", color = Color.Black)
|
Text("Login")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,6 +117,14 @@ class MainScreen : Screen {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun MainWindowTopBar() {
|
private fun MainWindowTopBar() {
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -123,7 +134,7 @@ class MainScreen : Screen {
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "MARATHON SKILLS 2016",
|
text = "MARATHON SKILLS 2016",
|
||||||
fontSize = MaterialTheme.typography.h4.fontSize,
|
fontSize = fontSize,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = Color.White
|
color = Color.White
|
||||||
)
|
)
|
||||||
@ -133,17 +144,26 @@ class MainScreen : Screen {
|
|||||||
Text(
|
Text(
|
||||||
text = "Москва, Россия\nсреда 21 октября 2016",
|
text = "Москва, Россия\nсреда 21 октября 2016",
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontSize = MaterialTheme.typography.subtitle1.fontSize,
|
fontSize = fontSize,
|
||||||
fontStyle = FontStyle.Italic,
|
fontStyle = FontStyle.Italic,
|
||||||
color = Color.LightGray
|
color = Color.LightGray
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun MainWindowBottomBar(timerViewModel: TimerViewModel) {
|
private fun MainWindowBottomBar(timerViewModel: TimerViewModel) {
|
||||||
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 50).sp
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -152,7 +172,10 @@ class MainScreen : Screen {
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Text(text = remainingTime,
|
Text(text = remainingTime,
|
||||||
color = Color.White)
|
color = Color.White,
|
||||||
|
fontSize = fontSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@ package org.example.project.ui.Screens
|
|||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
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.BoxWithConstraints
|
||||||
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.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.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.layout.wrapContentWidth
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
@ -23,7 +23,6 @@ import androidx.compose.runtime.collectAsState
|
|||||||
import androidx.compose.ui.Alignment
|
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.text.font.FontStyle
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
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
|
||||||
@ -31,6 +30,7 @@ import androidx.compose.ui.unit.sp
|
|||||||
import cafe.adriel.voyager.core.screen.Screen
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import org.example.project.ViewModel.InfoButton
|
||||||
import org.example.project.ViewModel.TimerViewModel
|
import org.example.project.ViewModel.TimerViewModel
|
||||||
|
|
||||||
|
|
||||||
@ -38,20 +38,26 @@ class MoreInfoScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
val buttonSize = Modifier
|
|
||||||
.width(300.dp)
|
|
||||||
.height(80.dp)
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { InfoTopBar() },
|
topBar = { InfoTopBar() },
|
||||||
bottomBar = { InfoBottomBar(timerViewModel = timerViewModel) }
|
bottomBar = { InfoBottomBar(timerViewModel = timerViewModel) }
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(paddingValues)
|
.padding(paddingValues)
|
||||||
.fillMaxSize()
|
|
||||||
) {
|
) {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
.padding(horizontal = 100.dp)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 25).sp
|
||||||
|
val fontSizeButton = (maxWidth.value / 40).sp
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
@ -63,7 +69,7 @@ class MoreInfoScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
text = "Подробная информация",
|
text = "Подробная информация",
|
||||||
color = Color.DarkGray,
|
color = Color.DarkGray,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontSize = MaterialTheme.typography.h5.fontSize,
|
fontSize = fontSize,
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
@ -80,91 +86,21 @@ class MoreInfoScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Button(
|
InfoButton("Marathon Skills 2016", fontSizeButton, {navigator.push(AboutMarathonScreen(timerViewModel))})
|
||||||
onClick = { },
|
InfoButton("Предыдущие результаты", fontSizeButton, {})
|
||||||
modifier = buttonSize,
|
InfoButton("BMI калькулятор", fontSizeButton, {})
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
backgroundColor = Color.LightGray,
|
|
||||||
contentColor = Color.Black
|
|
||||||
),
|
|
||||||
shape = RoundedCornerShape(15.dp)
|
|
||||||
) {
|
|
||||||
Text(text = "Marathon Skills 2016", fontSize = 16.sp,
|
|
||||||
fontStyle = FontStyle.Italic
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(
|
|
||||||
onClick = { },
|
|
||||||
modifier = buttonSize,
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
backgroundColor = Color.LightGray,
|
|
||||||
contentColor = Color.Black
|
|
||||||
),
|
|
||||||
shape = RoundedCornerShape(15.dp)
|
|
||||||
) {
|
|
||||||
Text(text = "Предыдущие\nрезультаты", fontSize = 16.sp,
|
|
||||||
fontStyle = FontStyle.Italic)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(
|
|
||||||
onClick = { },
|
|
||||||
modifier = buttonSize,
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
backgroundColor = Color.LightGray,
|
|
||||||
contentColor = Color.Black
|
|
||||||
),
|
|
||||||
shape = RoundedCornerShape(15.dp)
|
|
||||||
) {
|
|
||||||
Text(text = "BMI калькулятор", fontSize = 16.sp,
|
|
||||||
fontStyle = FontStyle.Italic)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.padding(end = 8.dp),
|
.padding(start = 8.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Button(
|
InfoButton("Насколько долгий марафон", fontSizeButton, {})
|
||||||
onClick = { },
|
InfoButton("Список\nблаготворительных организаций", fontSizeButton, {})
|
||||||
modifier = buttonSize,
|
InfoButton("BMR калькулятор", fontSizeButton, {})
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
backgroundColor = Color.LightGray,
|
|
||||||
contentColor = Color.Black
|
|
||||||
),
|
|
||||||
shape = RoundedCornerShape(15.dp)
|
|
||||||
) {
|
|
||||||
Text(text = "Насколько долгий\nмарафон", fontSize = 16.sp,
|
|
||||||
fontStyle = FontStyle.Italic)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(
|
|
||||||
onClick = { },
|
|
||||||
modifier = buttonSize,
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
backgroundColor = Color.LightGray,
|
|
||||||
contentColor = Color.Black
|
|
||||||
),
|
|
||||||
shape = RoundedCornerShape(15.dp)
|
|
||||||
) {
|
|
||||||
Text(text = "Список\nблаготворительных\nорганизаций", fontSize = 16.sp,
|
|
||||||
fontStyle = FontStyle.Italic)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(
|
|
||||||
onClick = { },
|
|
||||||
modifier = buttonSize,
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
backgroundColor = Color.LightGray,
|
|
||||||
contentColor = Color.Black
|
|
||||||
),
|
|
||||||
shape = RoundedCornerShape(15.dp)
|
|
||||||
) {
|
|
||||||
Text(text = "BMR калькулятор", fontSize = 16.sp,
|
|
||||||
fontStyle = FontStyle.Italic)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,6 +113,15 @@ class MoreInfoScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
private fun InfoTopBar() {
|
private fun InfoTopBar() {
|
||||||
val navigator = LocalNavigator.currentOrThrow
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSizeButton = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeText = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -198,8 +143,10 @@ class MoreInfoScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
.wrapContentWidth()
|
.wrapContentWidth()
|
||||||
|
|
||||||
) {
|
) {
|
||||||
Text(text = "Назад",
|
Text(
|
||||||
|
text = "Назад",
|
||||||
color = Color.Black,
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,17 +158,25 @@ class MoreInfoScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
textAlign = TextAlign.Left,
|
textAlign = TextAlign.Left,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = MaterialTheme.typography.h4.fontSize,
|
fontSize = fontSizeText,
|
||||||
color = Color.White
|
color = Color.White
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(64.dp))
|
Spacer(modifier = Modifier.width(64.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun InfoBottomBar(timerViewModel: TimerViewModel) {
|
private fun InfoBottomBar(timerViewModel: TimerViewModel) {
|
||||||
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 50).sp
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -230,8 +185,13 @@ class MoreInfoScreen(private val timerViewModel: TimerViewModel) : Screen {
|
|||||||
.padding(8.dp),
|
.padding(8.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Text(text = remainingTime,
|
Text(
|
||||||
color = Color.White)
|
text = remainingTime,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,422 @@
|
|||||||
|
package org.example.project.ui.Screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.Checkbox
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.RadioButton
|
||||||
|
import androidx.compose.material.Scaffold
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import org.example.project.ViewModel.FieldWithDropdown
|
||||||
|
import org.example.project.ViewModel.FieldWithLabelInt
|
||||||
|
import org.example.project.ViewModel.TimerViewModel
|
||||||
|
import org.example.project.ViewModel.UserViewModel
|
||||||
|
|
||||||
|
class RegMaraphonScreen(private val timerViewModel: TimerViewModel, private val userId: Int) : Screen {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
val viewModel = UserViewModel()
|
||||||
|
val fonds = viewModel.getFond()
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = { RegMaraphonTopBar() },
|
||||||
|
bottomBar = { RegMaraphonBottomBar(timerViewModel = timerViewModel) }
|
||||||
|
) { paddingValues ->
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.padding(paddingValues)
|
||||||
|
) {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
.padding(horizontal = 100.dp)
|
||||||
|
) {
|
||||||
|
val fontSizeFirst = (maxWidth.value / 30).sp
|
||||||
|
val fontSizeSecond = (maxWidth.value / 40).sp
|
||||||
|
val fontSizeThird = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeFourth = (maxWidth.value / 10).sp
|
||||||
|
var finalSum by remember { mutableStateOf(0) }
|
||||||
|
var previousAddonPrice by remember { mutableStateOf(0) }
|
||||||
|
var checked1 by remember { mutableStateOf(false) }
|
||||||
|
var checked2 by remember { mutableStateOf(false) }
|
||||||
|
var checked3 by remember { mutableStateOf(false) }
|
||||||
|
val options = listOf(
|
||||||
|
"Вариант А($0): Номер бегуна + RFID браслет",
|
||||||
|
"Вариант B($20): вариант A + бейсболка + бутылка воды",
|
||||||
|
"Вариант C($45): Вариант B + футболка + сувенирный буклет"
|
||||||
|
)
|
||||||
|
var fondsNames = fonds.map { it.name }
|
||||||
|
var selectedOption by remember { mutableStateOf(options[0]) }
|
||||||
|
var vznos by remember { mutableStateOf("")}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth().padding(bottom = 16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Регистрация на марафон",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Пожалуйста, заполните всю информацию, чтобы зарегестрироваться на Skills Marathon 2016 проводимом в Москве. Russia. С вами свяжутся после регистрации для уточнения оплаты и другой информации.",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.2f))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier.weight(1f), ) {
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Вид марафона",
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Checkbox(
|
||||||
|
checked = checked1,
|
||||||
|
onCheckedChange = { isChecked ->
|
||||||
|
checked1 = isChecked
|
||||||
|
if (isChecked) {
|
||||||
|
finalSum += 145
|
||||||
|
} else {
|
||||||
|
finalSum -= 145
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
Text(text = "42km Полный марафон($145)", fontSize = fontSizeSecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Checkbox(
|
||||||
|
checked = checked2,
|
||||||
|
onCheckedChange = { isChecked ->
|
||||||
|
checked2 = isChecked
|
||||||
|
if (isChecked) {
|
||||||
|
finalSum += 75
|
||||||
|
} else {
|
||||||
|
finalSum -= 75
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
Text(text = "21km Поулмарафон($75)", fontSize = fontSizeSecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Checkbox(
|
||||||
|
checked = checked3,
|
||||||
|
onCheckedChange = { isChecked ->
|
||||||
|
checked3 = isChecked
|
||||||
|
if (isChecked) {
|
||||||
|
finalSum += 20
|
||||||
|
} else {
|
||||||
|
finalSum -= 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
Text(text = "5km Малая дистанция($20)", fontSize = fontSizeSecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Детали спонсорства",
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier
|
||||||
|
)
|
||||||
|
|
||||||
|
FieldWithDropdown(
|
||||||
|
label = "Взнос:",
|
||||||
|
options = fondsNames,
|
||||||
|
selectedOption = vznos,
|
||||||
|
onOptionSelected = { vznos = it },
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
labelWidth = 0.5f
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithLabelInt(
|
||||||
|
label = "Сумма взноса:",
|
||||||
|
value = finalSum,
|
||||||
|
onValueChange = { finalSum = it },
|
||||||
|
placeholder = "$$$",
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
labelWidth = 0.5f,
|
||||||
|
enabled = false
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val selectedFond = fonds.find { it.name == vznos }
|
||||||
|
if (selectedFond != null && selectedFond.balance > finalSum) {
|
||||||
|
val result = viewModel.withdrawalBalance(selectedFond.id, finalSum)
|
||||||
|
val result2 = viewModel.updateUserActive(userId)
|
||||||
|
if (result && result2){
|
||||||
|
navigator.push(ConfirmRunnerScreen(timerViewModel, userId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text("Регистрация", fontSize = fontSizeThird)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(InfoRunnerScreen(timerViewModel, userId)) },
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text("Отмена", fontSize = fontSizeThird)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "Варианты комплектов",
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
options.forEach { text ->
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
RadioButton(
|
||||||
|
selected = (text == selectedOption),
|
||||||
|
onClick = {
|
||||||
|
val newAddonPrice = when (text) {
|
||||||
|
options[0] -> 0
|
||||||
|
options[1] -> 20
|
||||||
|
options[2] -> 45
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
finalSum = finalSum - previousAddonPrice + newAddonPrice
|
||||||
|
|
||||||
|
previousAddonPrice = newAddonPrice
|
||||||
|
selectedOption = text
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.weight(0.01f))
|
||||||
|
Text(text = text, fontSize = fontSizeSecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "Регистрационный взнос",
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Text(
|
||||||
|
text = "$" + finalSum.toString(),
|
||||||
|
color = Color.LightGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFourth,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RegMaraphonTopBar() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSizeButton = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeText = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(InfoRunnerScreen(timerViewModel, userId)) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Назад",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(24.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "MARATHON SKILLS 2016",
|
||||||
|
style = MaterialTheme.typography.h6,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
textAlign = TextAlign.Left,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = fontSizeText,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(64.dp))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Logout",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RegMaraphonBottomBar(timerViewModel: TimerViewModel) {
|
||||||
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 50).sp
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(8.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = remainingTime,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,540 @@
|
|||||||
|
package org.example.project.ui.Screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
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.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.Icon
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.OutlinedTextField
|
||||||
|
import androidx.compose.material.Scaffold
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.DateRange
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import org.example.project.Models.User
|
||||||
|
import org.example.project.ViewModel.DatePickerField
|
||||||
|
import org.example.project.ViewModel.FieldWithDropdown
|
||||||
|
import org.example.project.ViewModel.FieldWithLabel
|
||||||
|
import org.example.project.ViewModel.GetPath
|
||||||
|
import org.example.project.ViewModel.ImageFromPath
|
||||||
|
import org.example.project.ViewModel.TimerViewModel
|
||||||
|
import org.example.project.ViewModel.UserViewModel
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.format.DateTimeParseException
|
||||||
|
|
||||||
|
class RegRunnerScreen(
|
||||||
|
private val timerViewModel: TimerViewModel,
|
||||||
|
) : Screen {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
val viewModel = UserViewModel()
|
||||||
|
var users = viewModel.getUsers()
|
||||||
|
var email by remember { mutableStateOf("") }
|
||||||
|
var password by remember { mutableStateOf("") }
|
||||||
|
var secondPassword by remember { mutableStateOf("") }
|
||||||
|
var name by remember { mutableStateOf("") }
|
||||||
|
var surname by remember { mutableStateOf("") }
|
||||||
|
var gender by remember { mutableStateOf("") }
|
||||||
|
var country by remember { mutableStateOf("") }
|
||||||
|
var photoPath by remember { mutableStateOf("") }
|
||||||
|
var openPicker by remember { mutableStateOf(false) }
|
||||||
|
if (openPicker) {
|
||||||
|
GetPath { selected ->
|
||||||
|
photoPath = selected
|
||||||
|
openPicker = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var showDatePicker by remember { mutableStateOf(false) }
|
||||||
|
var dateBirthday by remember { mutableStateOf("") }
|
||||||
|
if (showDatePicker) {
|
||||||
|
DatePickerField(
|
||||||
|
onDateSelected = {
|
||||||
|
dateBirthday = it
|
||||||
|
},
|
||||||
|
trigger = true,
|
||||||
|
onDismissRequest = { showDatePicker = false }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = { RegRunnerTopBar() },
|
||||||
|
bottomBar = {
|
||||||
|
BottomSection(
|
||||||
|
timerViewModel,
|
||||||
|
email, password, secondPassword, name, surname, gender, photoPath, dateBirthday, country
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { paddingValues ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.padding(paddingValues).fillMaxSize()
|
||||||
|
) {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
.padding(horizontal = 10.dp)
|
||||||
|
) {
|
||||||
|
val fontSize = (maxWidth.value / 60).sp
|
||||||
|
val fontSizeFirst = (maxWidth.value / 30).sp
|
||||||
|
val fontSizeSecond = (maxWidth.value / 40).sp
|
||||||
|
val labelWidth = 0.5f
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth().padding(bottom = 16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Регистрация бегуна",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeFirst,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Пожалуйста, заполните всю информацию, чтобы зарегестрироваться в качестве участника",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSizeSecond,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(0.2f))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier.weight(0.8f)) {
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "Email:",
|
||||||
|
value = email,
|
||||||
|
onValueChange = { email = it
|
||||||
|
println(email)},
|
||||||
|
placeholder = "Email",
|
||||||
|
fontSize = fontSize,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "Пароль:",
|
||||||
|
value = password,
|
||||||
|
onValueChange = { password = it },
|
||||||
|
placeholder = "Пароль",
|
||||||
|
fontSize = fontSize,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "Повторите пароль:",
|
||||||
|
value = secondPassword,
|
||||||
|
onValueChange = { secondPassword = it },
|
||||||
|
placeholder = "Повторите пароль",
|
||||||
|
fontSize = fontSize,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "Имя:",
|
||||||
|
value = name,
|
||||||
|
onValueChange = { name = it },
|
||||||
|
placeholder = "Имя",
|
||||||
|
fontSize = fontSize,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithLabel(
|
||||||
|
label = "Фамилия:",
|
||||||
|
value = surname,
|
||||||
|
onValueChange = { surname = it },
|
||||||
|
placeholder = "Фамилия",
|
||||||
|
fontSize = fontSize,
|
||||||
|
labelWidth = labelWidth,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
|
|
||||||
|
FieldWithDropdown(
|
||||||
|
label = "Пол:",
|
||||||
|
options = listOf("Мужской", "Остальное"),
|
||||||
|
selectedOption = gender,
|
||||||
|
onOptionSelected = { gender = it },
|
||||||
|
fontSize = fontSize,
|
||||||
|
labelWidth = labelWidth
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
|
ImageFromPath(
|
||||||
|
path = photoPath,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(0.4f)
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.border(1.dp, Color.Gray, RoundedCornerShape(8.dp)).align(Alignment.End)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.05f))
|
||||||
|
|
||||||
|
Column(modifier = Modifier.weight(0.3f)) {
|
||||||
|
Text(
|
||||||
|
text = "Фото файл:",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
fontSize = fontSize,
|
||||||
|
modifier = Modifier
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = photoPath,
|
||||||
|
onValueChange = {photoPath = it},
|
||||||
|
placeholder = {
|
||||||
|
Text(
|
||||||
|
text = "Photo_logo.jpg",
|
||||||
|
fontSize = fontSize,
|
||||||
|
color = Color.LightGray
|
||||||
|
)
|
||||||
|
},
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(
|
||||||
|
fontSize = fontSize,
|
||||||
|
color = Color.Black
|
||||||
|
),
|
||||||
|
enabled = true,
|
||||||
|
colors = androidx.compose.material.TextFieldDefaults.outlinedTextFieldColors(
|
||||||
|
backgroundColor = Color.White,
|
||||||
|
cursorColor = Color.Black,
|
||||||
|
textColor = Color.Black,
|
||||||
|
placeholderColor = Color.LightGray,
|
||||||
|
focusedBorderColor = Color(0xFFCCCCCC),
|
||||||
|
unfocusedBorderColor = Color(0xFFCCCCCC),
|
||||||
|
disabledBorderColor = Color(0xFFCCCCCC)
|
||||||
|
),
|
||||||
|
modifier = Modifier.weight(0.6f).wrapContentWidth().fillMaxWidth()
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.05f))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { openPicker = true},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(0.5f),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
"Просмотр",
|
||||||
|
fontSize = fontSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.05f))
|
||||||
|
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier.weight(labelWidth)) {
|
||||||
|
Text(
|
||||||
|
text = "Дата рождения",
|
||||||
|
color = Color.DarkGray,
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
fontSize = fontSize,
|
||||||
|
modifier = Modifier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = dateBirthday,
|
||||||
|
onValueChange = {dateBirthday = it},
|
||||||
|
placeholder = {
|
||||||
|
Text(
|
||||||
|
text = "...",
|
||||||
|
fontSize = fontSize,
|
||||||
|
color = Color.LightGray
|
||||||
|
)
|
||||||
|
},
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(
|
||||||
|
fontSize = fontSize,
|
||||||
|
color = Color.Black
|
||||||
|
),
|
||||||
|
enabled = true,
|
||||||
|
colors = androidx.compose.material.TextFieldDefaults.outlinedTextFieldColors(
|
||||||
|
backgroundColor = Color.White,
|
||||||
|
cursorColor = Color.Black,
|
||||||
|
textColor = Color.Black,
|
||||||
|
placeholderColor = Color.LightGray,
|
||||||
|
focusedBorderColor = Color(0xFFCCCCCC),
|
||||||
|
unfocusedBorderColor = Color(0xFFCCCCCC),
|
||||||
|
disabledBorderColor = Color(0xFFCCCCCC)
|
||||||
|
),
|
||||||
|
modifier = Modifier.weight(0.9f).wrapContentWidth()
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(0.05f))
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(0.5f)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.LightGray)
|
||||||
|
.clickable { showDatePicker = true }
|
||||||
|
.padding(vertical = 8.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.DateRange,
|
||||||
|
contentDescription = "Выбрать дату",
|
||||||
|
tint = Color.Black,
|
||||||
|
modifier = Modifier.size(24.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.weight(0.05f))
|
||||||
|
|
||||||
|
FieldWithDropdown(
|
||||||
|
label = "Страна:",
|
||||||
|
options = listOf("Russia", "Other"),
|
||||||
|
selectedOption = country,
|
||||||
|
onOptionSelected = { country = it },
|
||||||
|
fontSize = fontSize,
|
||||||
|
labelWidth = labelWidth
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RegRunnerTopBar() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Box {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center)
|
||||||
|
) {
|
||||||
|
val fontSizeButton = (maxWidth.value / 50).sp
|
||||||
|
val fontSizeText = (maxWidth.value / 25).sp
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
elevation = null,
|
||||||
|
shape = RoundedCornerShape(15.dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Назад",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = fontSizeButton
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(24.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "MARATHON SKILLS 2016",
|
||||||
|
style = MaterialTheme.typography.h6,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
textAlign = TextAlign.Left,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = fontSizeText,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(64.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RegRunnerBottomBar(timerViewModel: TimerViewModel) {
|
||||||
|
val remainingTime = timerViewModel.remainingTime.collectAsState().value
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.DarkGray)
|
||||||
|
.padding(8.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = remainingTime,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun BottomSection(
|
||||||
|
timerViewModel: TimerViewModel,
|
||||||
|
email: String,
|
||||||
|
password: String,
|
||||||
|
secondPassword: String,
|
||||||
|
name: String,
|
||||||
|
surname: String,
|
||||||
|
gender: String,
|
||||||
|
photoPath: String,
|
||||||
|
dateBirthday: String,
|
||||||
|
country: String
|
||||||
|
){
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.White)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val viewModel = UserViewModel()
|
||||||
|
var users = viewModel.getUsers()
|
||||||
|
val nextId = (users.maxByOrNull { it.id }?.id ?: 0) + 1
|
||||||
|
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
|
||||||
|
val birthdayDate = if (dateBirthday.isNotEmpty()) {
|
||||||
|
try {
|
||||||
|
LocalDate.parse(dateBirthday, formatter)
|
||||||
|
} catch (e: DateTimeParseException) {
|
||||||
|
LocalDate.now()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LocalDate.now()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondPassword == password) {
|
||||||
|
val result = viewModel.regUser(
|
||||||
|
User(
|
||||||
|
id = nextId,
|
||||||
|
email = email,
|
||||||
|
password = password,
|
||||||
|
name = name,
|
||||||
|
surname = surname,
|
||||||
|
gender = gender,
|
||||||
|
photopath = photoPath,
|
||||||
|
birthday = birthdayDate,
|
||||||
|
country = country,
|
||||||
|
active = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if (result){
|
||||||
|
navigator.push(InfoRunnerScreen(timerViewModel, nextId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text("Регистрация")
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { navigator.push(MainScreen()) },
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
backgroundColor = Color.LightGray,
|
||||||
|
contentColor = Color.Black
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
) {
|
||||||
|
Text("Отмена")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RegRunnerBottomBar(timerViewModel = timerViewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
composeApp/src/desktopMain/kotlin/Tables/Connect.kt
Normal file
17
composeApp/src/desktopMain/kotlin/Tables/Connect.kt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package org.example.project.Tables
|
||||||
|
|
||||||
|
import org.example.project.Models.User
|
||||||
|
import org.jetbrains.exposed.sql.Database
|
||||||
|
import org.jetbrains.exposed.sql.SchemaUtils
|
||||||
|
import org.jetbrains.exposed.sql.Table
|
||||||
|
import org.jetbrains.exposed.sql.selectAll
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
fun connectToDatabase() {
|
||||||
|
Database.connect(
|
||||||
|
"jdbc:postgresql://localhost:5447/multidb",
|
||||||
|
driver = "org.postgresql.Driver",
|
||||||
|
user = "multidb",
|
||||||
|
password = "multidb"
|
||||||
|
)
|
||||||
|
}
|
13
composeApp/src/desktopMain/kotlin/Tables/Fonds.kt
Normal file
13
composeApp/src/desktopMain/kotlin/Tables/Fonds.kt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package org.example.project.Tables
|
||||||
|
|
||||||
|
import org.example.project.Tables.Users.autoIncrement
|
||||||
|
import org.jetbrains.exposed.sql.Table
|
||||||
|
import org.jetbrains.exposed.sql.javatime.date
|
||||||
|
|
||||||
|
object Fonds : Table() {
|
||||||
|
val id = integer("id").autoIncrement()
|
||||||
|
val name = varchar("name", 255)
|
||||||
|
val balance = integer("balance")
|
||||||
|
|
||||||
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
}
|
18
composeApp/src/desktopMain/kotlin/Tables/Users.kt
Normal file
18
composeApp/src/desktopMain/kotlin/Tables/Users.kt
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package org.example.project.Tables
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.sql.Table
|
||||||
|
import org.jetbrains.exposed.sql.javatime.date
|
||||||
|
|
||||||
|
object Users : Table() {
|
||||||
|
val id = integer("id").autoIncrement()
|
||||||
|
val email = varchar("email", 255)
|
||||||
|
val password = varchar("password", 255)
|
||||||
|
val name = varchar("name", 255)
|
||||||
|
val surname = varchar("surname", 255)
|
||||||
|
val gender = varchar("gender", 255)
|
||||||
|
val photopath = varchar("photopath", 255)
|
||||||
|
val birthday = date("birthday")
|
||||||
|
val country = varchar("country", 255)
|
||||||
|
val active = bool("active").default(false)
|
||||||
|
override val primaryKey = PrimaryKey(id)
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import javax.swing.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun DatePickerField(
|
||||||
|
onDateSelected: (String) -> Unit,
|
||||||
|
trigger: Boolean,
|
||||||
|
onDismissRequest: () -> Unit
|
||||||
|
) {
|
||||||
|
if (trigger) {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
val dialog = JDialog()
|
||||||
|
dialog.title = "Выбор даты"
|
||||||
|
val model = SpinnerDateModel()
|
||||||
|
val spinner = JSpinner(model)
|
||||||
|
val panel = JPanel()
|
||||||
|
val button = JButton("OK")
|
||||||
|
panel.add(spinner)
|
||||||
|
panel.add(button)
|
||||||
|
dialog.contentPane = panel
|
||||||
|
dialog.setSize(200, 100)
|
||||||
|
|
||||||
|
button.addActionListener {
|
||||||
|
val date = model.date
|
||||||
|
val formatted = SimpleDateFormat("dd.MM.yyyy").format(date)
|
||||||
|
onDateSelected(formatted)
|
||||||
|
dialog.dispose()
|
||||||
|
onDismissRequest()
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.isVisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
composeApp/src/desktopMain/kotlin/ViewModel/GetPath.kt
Normal file
29
composeApp/src/desktopMain/kotlin/ViewModel/GetPath.kt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.io.File
|
||||||
|
import javax.swing.JFileChooser
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun GetPath(onPathSelected: (String) -> Unit) {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
val selectedPath = withContext(Dispatchers.IO) {
|
||||||
|
val chooser = JFileChooser()
|
||||||
|
chooser.dialogTitle = "Выберите изображение"
|
||||||
|
chooser.fileSelectionMode = JFileChooser.FILES_ONLY
|
||||||
|
|
||||||
|
val result = chooser.showOpenDialog(null)
|
||||||
|
if (result == JFileChooser.APPROVE_OPTION) {
|
||||||
|
val file: File = chooser.selectedFile
|
||||||
|
file.absolutePath
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onPathSelected(selectedPath)
|
||||||
|
}
|
||||||
|
}
|
33
composeApp/src/desktopMain/kotlin/ViewModel/IconPrinter.kt
Normal file
33
composeApp/src/desktopMain/kotlin/ViewModel/IconPrinter.kt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||||
|
import androidx.compose.ui.graphics.toComposeImageBitmap
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import org.jetbrains.skia.Image
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun IconPrinter(resourceName: String, modifier: Modifier) {
|
||||||
|
val imageBitmap = try {
|
||||||
|
val path = "drawable/${resourceName}.jpg"
|
||||||
|
val stream = Thread.currentThread().contextClassLoader.getResourceAsStream(path)
|
||||||
|
if (stream != null) {
|
||||||
|
Image.makeFromEncoded(stream.readAllBytes()).toComposeImageBitmap()
|
||||||
|
} else null
|
||||||
|
} catch (e: IOException) {
|
||||||
|
println("Ошибка загрузки иконки: ${e.message}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageBitmap != null) {
|
||||||
|
Image(
|
||||||
|
painter = BitmapPainter(imageBitmap),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = modifier,
|
||||||
|
contentScale = ContentScale.FillBounds
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
45
composeApp/src/desktopMain/kotlin/ViewModel/ImageFromPath.kt
Normal file
45
composeApp/src/desktopMain/kotlin/ViewModel/ImageFromPath.kt
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
|
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||||
|
import androidx.compose.ui.graphics.toComposeImageBitmap
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import org.jetbrains.skia.Image
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.Files
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun ImageFromPath(path: String, modifier: Modifier) {
|
||||||
|
val imageBitmap: ImageBitmap? = try {
|
||||||
|
if (path.isBlank()) {
|
||||||
|
val resourceStream = Thread.currentThread().contextClassLoader.getResourceAsStream("drawable/defPhoto.png")
|
||||||
|
val bytes = resourceStream.readAllBytes()
|
||||||
|
Image.makeFromEncoded(bytes).toComposeImageBitmap()
|
||||||
|
} else {
|
||||||
|
val file = File(path)
|
||||||
|
if (file.exists()) {
|
||||||
|
val bytes = Files.readAllBytes(file.toPath())
|
||||||
|
Image.makeFromEncoded(bytes).toComposeImageBitmap()
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Ошибка загрузки изображения: ${e.message}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageBitmap != null) {
|
||||||
|
Image(
|
||||||
|
painter = BitmapPainter(imageBitmap),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = modifier,
|
||||||
|
contentScale = ContentScale.Crop
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Box(modifier = modifier.fillMaxSize())
|
||||||
|
}
|
||||||
|
}
|
128
composeApp/src/desktopMain/kotlin/ViewModel/UserRepository.kt
Normal file
128
composeApp/src/desktopMain/kotlin/ViewModel/UserRepository.kt
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
package org.example.project.ViewModel
|
||||||
|
|
||||||
|
import org.example.project.Models.Fond
|
||||||
|
import org.example.project.Models.User
|
||||||
|
import org.example.project.Tables.Fonds
|
||||||
|
import org.example.project.Tables.Users
|
||||||
|
import org.example.project.Tables.connectToDatabase
|
||||||
|
import org.jetbrains.exposed.sql.SchemaUtils
|
||||||
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder
|
||||||
|
import org.jetbrains.exposed.sql.insert
|
||||||
|
import org.jetbrains.exposed.sql.selectAll
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.sql.update
|
||||||
|
|
||||||
|
actual class UserRepository {
|
||||||
|
actual fun fetchUsers(): List<User> {
|
||||||
|
connectToDatabase()
|
||||||
|
|
||||||
|
return transaction {
|
||||||
|
Users.selectAll().map {
|
||||||
|
User(
|
||||||
|
id = it[Users.id],
|
||||||
|
email = it[Users.email],
|
||||||
|
password = it[Users.password],
|
||||||
|
name = it[Users.name],
|
||||||
|
surname = it[Users.surname],
|
||||||
|
gender = it[Users.gender],
|
||||||
|
photopath = it[Users.photopath],
|
||||||
|
birthday = it[Users.birthday],
|
||||||
|
country = it[Users.country],
|
||||||
|
active = it[Users.active]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual fun regUser(user: User): Boolean{
|
||||||
|
connectToDatabase()
|
||||||
|
|
||||||
|
return try {
|
||||||
|
transaction {
|
||||||
|
Users.insert {
|
||||||
|
it[id] = user.id
|
||||||
|
it[email] = user.email
|
||||||
|
it[password] = user.password
|
||||||
|
it[name] = user.name
|
||||||
|
it[surname] = user.surname
|
||||||
|
it[gender] = user.gender
|
||||||
|
it[photopath] = user.photopath
|
||||||
|
it[birthday] = user.birthday
|
||||||
|
it[country] = user.country
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Ошибка при регистрации: ${e.message}")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual fun fetchFonds(): List<Fond>{
|
||||||
|
connectToDatabase()
|
||||||
|
|
||||||
|
return transaction {
|
||||||
|
Fonds.selectAll().map {
|
||||||
|
Fond(
|
||||||
|
id = it[Fonds.id],
|
||||||
|
name = it[Fonds.name],
|
||||||
|
balance = it[Fonds.balance]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual fun withdrawalBalance(idFond: Int, dedSum: Int): Boolean{
|
||||||
|
connectToDatabase()
|
||||||
|
|
||||||
|
return try {
|
||||||
|
transaction {
|
||||||
|
Fonds.update({Fonds.id eq idFond}){
|
||||||
|
with(SqlExpressionBuilder) {
|
||||||
|
it.update(balance, balance - dedSum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} catch (e: Exception){
|
||||||
|
println("Ошибка при снятии: ${e.message}")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual fun getUserIdByEmail(email: String): Int {
|
||||||
|
connectToDatabase()
|
||||||
|
|
||||||
|
return transaction {
|
||||||
|
Users.selectAll().where { Users.email eq email }.single()[Users.id]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual fun updateUserActive(idUser: Int): Boolean{
|
||||||
|
connectToDatabase()
|
||||||
|
|
||||||
|
return try {
|
||||||
|
transaction {
|
||||||
|
Users.update({Users.id eq idUser}){
|
||||||
|
it[active] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} catch (e: Exception){
|
||||||
|
println("Ошибка при обновлении: ${e.message}")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual fun topUpBalance(idFond: Int, sum: Int): Boolean{
|
||||||
|
connectToDatabase()
|
||||||
|
|
||||||
|
return try {
|
||||||
|
transaction {
|
||||||
|
Fonds.update({Fonds.id eq idFond}){
|
||||||
|
with(SqlExpressionBuilder) {
|
||||||
|
it.update(balance, balance + sum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} catch (e: Exception){
|
||||||
|
println("Ошибка при пополнении: ${e.message}")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import androidx.compose.ui.window.Window
|
|||||||
import org.example.project.App
|
import org.example.project.App
|
||||||
|
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
|
|
||||||
Window(
|
Window(
|
||||||
onCloseRequest = ::exitApplication,
|
onCloseRequest = ::exitApplication,
|
||||||
title = "Marathon Skills 2016"
|
title = "Marathon Skills 2016"
|
||||||
|
Loading…
Reference in New Issue
Block a user