diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index cc9f46b..a659271 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -18,9 +18,38 @@ kotlin { } jvm("desktop") - + 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") + + // Exposed + PostgreSQL +// implementation("org.jetbrains.exposed:exposed-core:$exposedVersion") +// implementation("org.jetbrains.exposed:exposed-dao:$exposedVersion") +// implementation("org.jetbrains.exposed:exposed-jdbc:$exposedVersion") + 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") + // or + implementation("org.jetbrains.exposed:exposed-java-time:$exposedVersion") + // or + 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") + } + } val commonMain by getting { resources.srcDir("src/commonMain/composeResources") @@ -31,6 +60,23 @@ kotlin { implementation(libs.androidx.activity.compose) implementation(libs.androidx.lifecycle.viewmodel) 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") + // or + implementation("org.jetbrains.exposed:exposed-java-time:$exposedVersion") + // or + 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") } commonMain.dependencies { val voyagerVersion = "1.1.0-beta02" @@ -49,17 +95,22 @@ kotlin { 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) - implementation("io.ktor:ktor-client-okhttp:2.3.2") - } +// desktopMain.dependencies { +// implementation(compose.desktop.currentOs) +// implementation(libs.kotlinx.coroutines.swing) +// implementation("io.ktor:ktor-client-okhttp:2.3.2") +// implementation("org.jetbrains.exposed:exposed-core:$exposedVersion") +// implementation("org.jetbrains.exposed:exposed-dao:$exposedVersion") +// implementation("org.jetbrains.exposed:exposed-jdbc:$exposedVersion") +// implementation("org.postgresql:postgresql:42.7.3") +// } } } @@ -89,6 +140,9 @@ android { targetCompatibility = JavaVersion.VERSION_11 } } +dependencies { + implementation(project(":composeApp")) +} compose.desktop { application { diff --git a/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/IconPrinter.kt b/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/IconPrinter.kt new file mode 100644 index 0000000..6714df7 --- /dev/null +++ b/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/IconPrinter.kt @@ -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 // fallback + } + + Image( + painter = painterResource(id = resId), + contentDescription = null, + modifier = modifier, + contentScale = ContentScale.FillBounds + ) +} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/UserRepository.kt b/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/UserRepository.kt new file mode 100644 index 0000000..fee7d8a --- /dev/null +++ b/composeApp/src/androidMain/kotlin/org/example/project/ViewModel/UserRepository.kt @@ -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 { + 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 { + 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 + } +} \ No newline at end of file diff --git a/composeApp/src/androidMain/res/drawable/map.jpg b/composeApp/src/androidMain/res/drawable/map.jpg new file mode 100644 index 0000000..dc4ae80 Binary files /dev/null and b/composeApp/src/androidMain/res/drawable/map.jpg differ diff --git a/composeApp/src/commonMain/composeResources/drawable/map.jpg b/composeApp/src/commonMain/composeResources/drawable/map.jpg new file mode 100644 index 0000000..dc4ae80 Binary files /dev/null and b/composeApp/src/commonMain/composeResources/drawable/map.jpg differ diff --git a/composeApp/src/commonMain/kotlin/org/example/project/Models/Fond.kt b/composeApp/src/commonMain/kotlin/org/example/project/Models/Fond.kt new file mode 100644 index 0000000..c89892b --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/Models/Fond.kt @@ -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 +) \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/Models/User.kt b/composeApp/src/commonMain/kotlin/org/example/project/Models/User.kt new file mode 100644 index 0000000..7c0c847 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/Models/User.kt @@ -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 +) diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/IconPrinter.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/IconPrinter.kt new file mode 100644 index 0000000..1ab6505 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/IconPrinter.kt @@ -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) \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/InfoButton.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/InfoButton.kt new file mode 100644 index 0000000..3d57283 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/InfoButton.kt @@ -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) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/RegRunnerViewModel.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/RegRunnerViewModel.kt new file mode 100644 index 0000000..80de433 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/RegRunnerViewModel.kt @@ -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("") +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/UserRepository.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/UserRepository.kt new file mode 100644 index 0000000..396d726 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/UserRepository.kt @@ -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 + fun regUser(user: User): Boolean + fun fetchFonds(): List + fun withdrawalBalance(idFond: Int, dedSum: Int): Boolean + fun getUserIdByEmail(email: String): Int + fun updateUserActive(idUser: Int): Boolean + fun topUpBalance(idFond: Int, sum: Int): Boolean +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/UserViewModel.kt b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/UserViewModel.kt new file mode 100644 index 0000000..3719460 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ViewModel/UserViewModel.kt @@ -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 { + return userRepository.fetchUsers() + } + + fun regUser(user: User): Boolean { + return userRepository.regUser(user) + } + + fun getFond(): List{ + 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) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/AboutMarathon.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/AboutMarathon.kt new file mode 100644 index 0000000..bcd5de3 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/AboutMarathon.kt @@ -0,0 +1,353 @@ +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 +// .weight(3f) + .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() + ) + } + +// Spacer(modifier = Modifier.weight(0.05f)) + + 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() + ) + } + } + +// Spacer(modifier = Modifier.weight(0.05f)) + + 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() + ) + } + } + +// Spacer(modifier = Modifier.weight(0.1f)) + } + + 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 + ) + } + } + } + } +} diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmRunner.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmRunner.kt index a51a8df..9fae2ea 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmRunner.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ConfirmRunner.kt @@ -33,7 +33,7 @@ import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import org.example.project.ViewModel.TimerViewModel -class ConfirmRunnerScreen(private val timerViewModel: TimerViewModel) : +class ConfirmRunnerScreen(private val timerViewModel: TimerViewModel, private val idRunner: Int) : Screen { @Composable @@ -89,7 +89,7 @@ class ConfirmRunnerScreen(private val timerViewModel: TimerViewModel) : Spacer(modifier = Modifier.weight(0.2f)) Button( - onClick = { navigator.push(InfoRunnerScreen(timerViewModel)) }, + onClick = { navigator.push(InfoRunnerScreen(timerViewModel, idRunner)) }, modifier = Modifier .fillMaxWidth() .height(48.dp), diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForRunner.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForRunner.kt index ae77492..86e0988 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForRunner.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForRunner.kt @@ -28,6 +28,9 @@ 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 androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewmodel.compose.viewModel +import org.example.project.ViewModel.RegRunnerViewModel import org.example.project.ViewModel.TimerViewModel class RunnerScreen(private val timerViewModel: TimerViewModel) : Screen { @@ -80,7 +83,11 @@ class RunnerScreen(private val timerViewModel: TimerViewModel) : Screen { Spacer(modifier = Modifier.weight(0.25f)) Button( - onClick = { navigator.push(RegRunnerScreen(timerViewModel)) }, +// onClick = { navigator.push(RegRunnerScreen(timerViewModel)) }, + onClick = { + val regRunnerViewModel = RegRunnerViewModel() + navigator.push(RegRunnerScreen(timerViewModel)) + }, modifier = Modifier .fillMaxWidth() .weight(1f), diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForSponsor.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForSponsor.kt index f9ab453..1f08982 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForSponsor.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/ForSponsor.kt @@ -1,6 +1,7 @@ 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 @@ -17,12 +18,15 @@ 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.DropdownMenu +import androidx.compose.material.DropdownMenuItem 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.ArrowDropDown import androidx.compose.material.icons.filled.DateRange import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -44,12 +48,16 @@ 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() }, @@ -71,12 +79,10 @@ class ForSponsorScreen(private val timerViewModel: TimerViewModel) : Screen { 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("") } - val runners = listOf( - "bob", - "bobby", - "baby" - ) var runner by remember { mutableStateOf("") } var cardName by remember { mutableStateOf("") } var cardNum by remember { mutableStateOf("") } @@ -86,6 +92,7 @@ class ForSponsorScreen(private val timerViewModel: TimerViewModel) : Screen { var sumChangStr by remember { mutableStateOf("10")} var sumChang by remember { mutableStateOf(sumChangStr.toInt()) } var sumSpons by remember { mutableStateOf(0)} + var expanded by remember { mutableStateOf(false) } Column( modifier = Modifier @@ -144,7 +151,7 @@ class ForSponsorScreen(private val timerViewModel: TimerViewModel) : Screen { FieldWithDropdown( label = "Бегун:", - options = runners, + options = runnersNames, selectedOption = runner, onOptionSelected = { runner = it }, fontSize = fontSizeSecond, @@ -242,15 +249,14 @@ class ForSponsorScreen(private val timerViewModel: TimerViewModel) : Screen { Spacer(modifier = Modifier.weight(0.1f)) - Box(modifier = Modifier.fillMaxWidth()) { - Text( - text = "blagot...", - color = Color.Black, - textAlign = TextAlign.Center, - fontSize = fontSizeSecond, - modifier = Modifier.align(Alignment.Center) - ) - } + FieldWithDropdown( + label = "", + options = fondsNames, + selectedOption = selectedFondName, + onOptionSelected = { selectedFondName = it }, + fontSize = fontSizeSecond, + labelWidth = 0.5f + ) Spacer(modifier = Modifier.weight(0.5f)) @@ -343,7 +349,16 @@ class ForSponsorScreen(private val timerViewModel: TimerViewModel) : Screen { .padding(horizontal = 16.dp, vertical = 8.dp) ) { Button( - onClick = { navigator.push(ConfirmSponsorScreen(timerViewModel, sumSpons.toString(), runner, "blagodat..."))}, +// onClick = { navigator.push(ConfirmSponsorScreen(timerViewModel, sumSpons.toString(), runner, "blagodat..."))}, + 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, @@ -399,7 +414,7 @@ class ForSponsorScreen(private val timerViewModel: TimerViewModel) : Screen { ) { Button( - onClick = { }, + onClick = { navigator.push(MainScreen()) }, colors = ButtonDefaults.buttonColors( backgroundColor = Color.LightGray, contentColor = Color.Black diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/InfoRunner.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/InfoRunner.kt index 92aa58a..2ad40cd 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/InfoRunner.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/InfoRunner.kt @@ -33,10 +33,11 @@ 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) : Screen { +class InfoRunnerScreen(private val timerViewModel: TimerViewModel, private val idRunner: Int) : Screen { @Composable override fun Content() { @@ -88,9 +89,9 @@ class InfoRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { verticalArrangement = Arrangement.spacedBy(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - InfoButton("Регистрация на марафон", fontSizeButton) - InfoButton("Редактирование профиля", fontSizeButton) - InfoButton("Контакты", fontSizeButton) + InfoButton("Регистрация на марафон", fontSizeButton, {navigator.push(RegMaraphonScreen(timerViewModel, idRunner))}) + InfoButton("Редактирование профиля", fontSizeButton, {}) + InfoButton("Контакты", fontSizeButton, {}) } Column( @@ -100,8 +101,8 @@ class InfoRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { verticalArrangement = Arrangement.spacedBy(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - InfoButton("Мои результаты", fontSizeButton) - InfoButton("Мои спонсоры", fontSizeButton) + InfoButton("Мои результаты", fontSizeButton, {}) + InfoButton("Мои спонсоры", fontSizeButton, {}) } } } @@ -110,23 +111,6 @@ class InfoRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { } } - @Composable - private fun InfoButton(text: String, fontSize: TextUnit) { - Button( - 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) - } - } - @Composable private fun InfoRunnerTopBar() { val navigator = LocalNavigator.currentOrThrow diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/Login.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/Login.kt index 4c78cb1..23ead60 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/Login.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/Login.kt @@ -35,11 +35,13 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.min import androidx.compose.ui.unit.sp +import androidx.lifecycle.ViewModel 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 { @@ -52,6 +54,9 @@ class LoginScreen(private val timerViewModel: TimerViewModel) : Screen { bottomBar = { LoginBottomBar(timerViewModel = timerViewModel) } ) { paddingValues -> + val viewModel = UserViewModel() + val users = viewModel.getUsers() + Box( modifier = Modifier.padding(paddingValues) ) { @@ -122,7 +127,14 @@ class LoginScreen(private val timerViewModel: TimerViewModel) : Screen { horizontalArrangement = Arrangement.Center ) { Button( - onClick = { navigator.push(InfoRunnerScreen(timerViewModel))}, +// onClick = { navigator.push(InfoRunnerScreen(timerViewModel))}, + 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), diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MainScreen.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MainScreen.kt index 27db258..92b8d1f 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MainScreen.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MainScreen.kt @@ -98,31 +98,6 @@ class MainScreen : Screen { } } -// BoxWithConstraints( -// modifier = Modifier -// .align(Alignment.BottomEnd) -// .padding(end = 16.dp, bottom = 20.dp) -// ) { -// val buttonWidth = (maxWidth.value / 6).dp -// val buttonHeight = (buttonWidth.value / 3).dp -// val fontSize = (maxWidth.value / 50).sp -// -// Button( -// onClick = { }, -// modifier = Modifier -// .width(buttonWidth) -// .height(buttonHeight), -// colors = ButtonDefaults.buttonColors( -// backgroundColor = Color.LightGray, -// contentColor = Color.Black -// ), -// shape = RoundedCornerShape(15.dp) -// ) { -// Text("Login", fontSize = fontSize) -// } -// } - - //доделать кнопку login Button( onClick = { navigator.push(LoginScreen(timerViewModel)) }, modifier = Modifier diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MoreInfo.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MoreInfo.kt index b87093b..8855cad 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MoreInfo.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/MoreInfo.kt @@ -33,6 +33,7 @@ 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 @@ -88,9 +89,9 @@ class MoreInfoScreen(private val timerViewModel: TimerViewModel) : Screen { verticalArrangement = Arrangement.spacedBy(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - InfoButton("Marathon Skills 2016", fontSizeButton) - InfoButton("Предыдущие результаты", fontSizeButton) - InfoButton("BMI калькулятор", fontSizeButton) + InfoButton("Marathon Skills 2016", fontSizeButton, {navigator.push(AboutMarathonScreen(timerViewModel))}) + InfoButton("Предыдущие результаты", fontSizeButton, {}) + InfoButton("BMI калькулятор", fontSizeButton, {}) } Column( @@ -100,9 +101,9 @@ class MoreInfoScreen(private val timerViewModel: TimerViewModel) : Screen { verticalArrangement = Arrangement.spacedBy(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - InfoButton("Насколько долгий марафон", fontSizeButton) - InfoButton("Список\nблаготворительных организаций", fontSizeButton) - InfoButton("BMR калькулятор", fontSizeButton) + InfoButton("Насколько долгий марафон", fontSizeButton, {}) + InfoButton("Список\nблаготворительных организаций", fontSizeButton, {}) + InfoButton("BMR калькулятор", fontSizeButton, {}) } } } @@ -111,23 +112,6 @@ class MoreInfoScreen(private val timerViewModel: TimerViewModel) : Screen { } } - @Composable - private fun InfoButton(text: String, fontSize: TextUnit) { - Button( - 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) - } - } - @Composable private fun InfoTopBar() { val navigator = LocalNavigator.currentOrThrow diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegMaraphon.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegMaraphon.kt index ffe27c4..ae0eb35 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegMaraphon.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegMaraphon.kt @@ -39,12 +39,15 @@ import org.example.project.ViewModel.FieldWithDropdown import org.example.project.ViewModel.FieldWithLabel import org.example.project.ViewModel.FieldWithLabelInt import org.example.project.ViewModel.TimerViewModel +import org.example.project.ViewModel.UserViewModel -class RegMaraphonScreen(private val timerViewModel: TimerViewModel) : Screen { +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() }, @@ -75,10 +78,11 @@ class RegMaraphonScreen(private val timerViewModel: TimerViewModel) : Screen { "Вариант B($20): вариант A + бейсболка + бутылка воды", "Вариант C($45): Вариант B + футболка + сувенирный буклет" ) - var blagi = listOf( - "Что-то", - "Ещё что-то" - ) +// var blagi = listOf( +// "Что-то", +// "Ещё что-то" +// ) + var fondsNames = fonds.map { it.name } var selectedOption by remember { mutableStateOf(options[0]) } var vznos by remember { mutableStateOf("")} var sumVznos by remember { mutableStateOf(0)} @@ -181,7 +185,7 @@ class RegMaraphonScreen(private val timerViewModel: TimerViewModel) : Screen { FieldWithDropdown( label = "Взнос:", - options = blagi, + options = fondsNames, selectedOption = vznos, onOptionSelected = { vznos = it }, fontSize = fontSizeSecond, @@ -192,11 +196,12 @@ class RegMaraphonScreen(private val timerViewModel: TimerViewModel) : Screen { FieldWithLabelInt( label = "Сумма взноса:", - value = sumVznos, - onValueChange = { sumVznos = it }, + value = finalSum, + onValueChange = { finalSum = it }, placeholder = "$$$", fontSize = fontSizeSecond, labelWidth = 0.5f, + enabled = false ) Spacer(modifier = Modifier.weight(0.1f)) @@ -209,7 +214,16 @@ class RegMaraphonScreen(private val timerViewModel: TimerViewModel) : Screen { .padding(horizontal = 16.dp, vertical = 8.dp) ) { Button( - onClick = { navigator.push(ConfirmRunnerScreen(timerViewModel))}, + 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, @@ -223,7 +237,7 @@ class RegMaraphonScreen(private val timerViewModel: TimerViewModel) : Screen { Spacer(modifier = Modifier.weight(0.1f)) Button( - onClick = { navigator.push(MainScreen()) }, + onClick = { navigator.push(InfoRunnerScreen(timerViewModel, userId)) }, modifier = Modifier.weight(1f), colors = ButtonDefaults.buttonColors( backgroundColor = Color.LightGray, @@ -329,7 +343,7 @@ class RegMaraphonScreen(private val timerViewModel: TimerViewModel) : Screen { ) { Button( - onClick = { }, + onClick = { navigator.push(InfoRunnerScreen(timerViewModel, userId)) }, colors = ButtonDefaults.buttonColors( backgroundColor = Color.LightGray, contentColor = Color.Black diff --git a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegRunner.kt b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegRunner.kt index 52dfe42..27a0422 100644 --- a/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegRunner.kt +++ b/composeApp/src/commonMain/kotlin/org/example/project/ui/Screens/RegRunner.kt @@ -1,8 +1,6 @@ package org.example.project.ui.Screens import androidx.compose.foundation.background -import androidx.compose.foundation.Image -import androidx.compose.ui.res.painterResource import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -13,27 +11,19 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults -import androidx.compose.material.DropdownMenu -import androidx.compose.material.DropdownMenuItem import androidx.compose.material.Icon -import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme import androidx.compose.material.OutlinedTextField import androidx.compose.material.Scaffold import androidx.compose.material.Text -import androidx.compose.material.TextField -import androidx.compose.material.contentColorFor import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowDropDown import androidx.compose.material.icons.filled.DateRange import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -47,29 +37,68 @@ 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.TextUnit 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 { +class RegRunnerScreen( + private val timerViewModel: TimerViewModel, +) : Screen { @Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow + val viewModel = UserViewModel() + var users = viewModel.getUsers() + val nextId = (users.maxByOrNull { it.id }?.id ?: 0) + 1 + 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 = timerViewModel) } + bottomBar = { + BottomSection( + timerViewModel, + email, password, secondPassword, name, surname, gender, photoPath, dateBirthday, country + ) + } ) { paddingValues -> Box( modifier = Modifier.padding(paddingValues).fillMaxSize() @@ -84,32 +113,6 @@ class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { val fontSizeFirst = (maxWidth.value / 30).sp val fontSizeSecond = (maxWidth.value / 40).sp val labelWidth = 0.5f - 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 } - ) - } Column( modifier = Modifier @@ -146,7 +149,8 @@ class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { FieldWithLabel( label = "Email:", value = email, - onValueChange = { email = it }, + onValueChange = { email = it + println(email)}, placeholder = "Email", fontSize = fontSize, labelWidth = labelWidth, @@ -355,6 +359,8 @@ class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { fontSize = fontSize, labelWidth = labelWidth ) + + Spacer(modifier = Modifier.width(16.dp)) } } } @@ -364,7 +370,6 @@ class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { } } - @Composable private fun RegRunnerTopBar() { val navigator = LocalNavigator.currentOrThrow @@ -444,24 +449,68 @@ class RegRunnerScreen(private val timerViewModel: TimerViewModel) : Screen { } @Composable - private fun BottomSection( - timerViewModel: TimerViewModel - ) { + 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, vertical = 8.dp) + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) ) { Button( - onClick = { navigator.push(RegMaraphonScreen(timerViewModel)) }, + 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, diff --git a/composeApp/src/desktopMain/kotlin/org/example/project/Server.kt b/composeApp/src/desktopMain/kotlin/org/example/project/Server.kt new file mode 100644 index 0000000..6e7df22 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/org/example/project/Server.kt @@ -0,0 +1,40 @@ +//package org.example.project +// +//import io.ktor.application.* +//import io.ktor.features.ContentNegotiation +//import io.ktor.http.HttpStatusCode +//import io.ktor.response.respond +//import io.ktor.routing.get +//import io.ktor.routing.routing +//import io.ktor.server.engine.embeddedServer +//import io.ktor.server.netty.Netty +//import io.ktor.server.plugins.statuspages.StatusPages +//import io.ktor.serialization.kotlinx.json +//import org.jetbrains.exposed.sql.Database +//import org.jetbrains.exposed.sql.selectAll +//import org.jetbrains.exposed.sql.transactions.transaction +//import org.example.project.Tables.Users +// +//fun startServer() { +// embeddedServer(Netty, port = 8080) { +// install(ContentNegotiation) { +// json() +// } +// +// install(StatusPages) { +// exception { cause -> +// call.respond(HttpStatusCode.InternalServerError, cause.localizedMessage) +// } +// } +// +// routing { +// get("/users") { +// Database.connect("jdbc:postgresql://localhost:5432/yourdb", driver = "org.postgresql.Driver", user = "user", password = "password") +// val users = transaction { +// Users.selectAll().map { it[Users.email] } +// } +// call.respond(users) +// } +// } +// }.start(wait = true) +//} \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/org/example/project/Tables/Connect.kt b/composeApp/src/desktopMain/kotlin/org/example/project/Tables/Connect.kt new file mode 100644 index 0000000..90f0397 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/org/example/project/Tables/Connect.kt @@ -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:5432/postgres", + driver = "org.postgresql.Driver", + user = "postgres", + password = "5432" + ) +} diff --git a/composeApp/src/desktopMain/kotlin/org/example/project/Tables/Fonds.kt b/composeApp/src/desktopMain/kotlin/org/example/project/Tables/Fonds.kt new file mode 100644 index 0000000..2b2b8b4 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/org/example/project/Tables/Fonds.kt @@ -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) +} \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/org/example/project/Tables/Users.kt b/composeApp/src/desktopMain/kotlin/org/example/project/Tables/Users.kt new file mode 100644 index 0000000..d2a3490 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/org/example/project/Tables/Users.kt @@ -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) +} diff --git a/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/IconPrinter.kt b/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/IconPrinter.kt new file mode 100644 index 0000000..99d1cf5 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/IconPrinter.kt @@ -0,0 +1,34 @@ +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.Fit + contentScale = ContentScale.FillBounds + ) + } +} \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/UserRepository.kt b/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/UserRepository.kt new file mode 100644 index 0000000..04bc18f --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/org/example/project/ViewModel/UserRepository.kt @@ -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 { + 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{ + 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 + } + } +} \ No newline at end of file