diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index ba3a483..744370f 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -14,6 +14,9 @@
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 36a4c12..33f6faa 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
+ kotlin("plugin.serialization") version "2.0.21"
}
android {
@@ -45,6 +46,12 @@ dependencies {
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
+ implementation(libs.retrofit)
+ implementation (libs.converter.kotlinx.serialization)
+ implementation(libs.kotlinx.serialization.json)
+ implementation (libs.androidx.navigation.compose)
+ implementation(libs.androidx.lifecycle.viewmodel.compose)
+
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f4bc553..d1d611f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,7 +1,7 @@
-
+
{ RegistrationScreen(onNavigateToAuthorization = {
+ navController.navigate(route = Authorization)
+ }) }
+ composable { AuthorizeScreen({ userId ->
+ navController.navigate(route = Clicker(userId = userId))
+ }) }
+ composable{ navBackStackEntry ->
+ val clicker: Clicker = navBackStackEntry.toRoute()
+ ClickerScreen(clicker.userId, {navController.navigate(route = Score)})
+ }
+ composable { ScoreScreen({navController.navigate(route = Clicker)}) }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/appforkids/data/AppForKidsApi.kt b/app/src/main/java/com/example/appforkids/data/AppForKidsApi.kt
new file mode 100644
index 0000000..c7e4698
--- /dev/null
+++ b/app/src/main/java/com/example/appforkids/data/AppForKidsApi.kt
@@ -0,0 +1,24 @@
+package com.example.appforkids.data
+
+import com.example.appforkids.data.Models.Requests.AuthorizeUserRequest
+import com.example.appforkids.data.Models.Requests.RegisterUserRequest
+import com.example.appforkids.data.Models.Response.UserResponse
+import retrofit2.http.Body
+import retrofit2.http.GET
+import retrofit2.http.POST
+import retrofit2.http.PUT
+import retrofit2.http.Path
+
+interface AppForKidsApi {
+ @GET("/user")
+ suspend fun getUsers():List
+
+ @PUT("/user/{user_id}/clicks")
+ suspend fun registerClick(@Path("user_id") idUser:Int)
+
+ @POST("/authorize/auth")
+ suspend fun authorizeUser(@Body authorizeUserRequest: AuthorizeUserRequest):UserResponse?
+
+ @POST("/authorize/register")
+ suspend fun registerUser(@Body registerUserRequest: RegisterUserRequest):UserResponse?
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/appforkids/data/Models/Requests/AuthorizeUserRequest.kt b/app/src/main/java/com/example/appforkids/data/Models/Requests/AuthorizeUserRequest.kt
new file mode 100644
index 0000000..2a2c3cb
--- /dev/null
+++ b/app/src/main/java/com/example/appforkids/data/Models/Requests/AuthorizeUserRequest.kt
@@ -0,0 +1,6 @@
+package com.example.appforkids.data.Models.Requests
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class AuthorizeUserRequest(val login:String, val password: String)
diff --git a/app/src/main/java/com/example/appforkids/data/Models/Requests/RegisterUserRequest.kt b/app/src/main/java/com/example/appforkids/data/Models/Requests/RegisterUserRequest.kt
new file mode 100644
index 0000000..2406e6c
--- /dev/null
+++ b/app/src/main/java/com/example/appforkids/data/Models/Requests/RegisterUserRequest.kt
@@ -0,0 +1,6 @@
+package com.example.appforkids.data.Models.Requests
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class RegisterUserRequest(val login:String, val password:String, var url:String?=null)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/appforkids/data/Models/Response/UserResponse.kt b/app/src/main/java/com/example/appforkids/data/Models/Response/UserResponse.kt
new file mode 100644
index 0000000..9c5d125
--- /dev/null
+++ b/app/src/main/java/com/example/appforkids/data/Models/Response/UserResponse.kt
@@ -0,0 +1,11 @@
+package com.example.appforkids.data.Models.Response
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class UserResponse(
+ val id:Int,
+ val nickname: String,
+ val password: String,
+ val clicks:Int,
+ var url:String? = null )
diff --git a/app/src/main/java/com/example/appforkids/data/Retrofit.kt b/app/src/main/java/com/example/appforkids/data/Retrofit.kt
new file mode 100644
index 0000000..69ad2ed
--- /dev/null
+++ b/app/src/main/java/com/example/appforkids/data/Retrofit.kt
@@ -0,0 +1,19 @@
+package com.example.appforkids.data
+
+import kotlinx.serialization.json.Json
+import okhttp3.MediaType
+import retrofit2.Retrofit
+import retrofit2.converter.kotlinx.serialization.asConverterFactory
+
+object HttpClient {
+ const val URL = "http://192.168.0.108:8080"
+ private val retrofit: Retrofit by lazy {
+ Retrofit.Builder()
+ .baseUrl(URL)
+ .addConverterFactory(Json.asConverterFactory(MediaType.get("application/json; charset=UTF8")))
+ .build()
+ }
+ val retrofitInstance by lazy {
+ retrofit.create(AppForKidsApi::class.java)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/appforkids/screen/authorize/AuthorizeScreen.kt b/app/src/main/java/com/example/appforkids/screen/authorize/AuthorizeScreen.kt
index 13dd4a0..3433757 100644
--- a/app/src/main/java/com/example/appforkids/screen/authorize/AuthorizeScreen.kt
+++ b/app/src/main/java/com/example/appforkids/screen/authorize/AuthorizeScreen.kt
@@ -7,6 +7,8 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -15,33 +17,43 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.lifecycle.viewmodel.compose.viewModel
+import com.example.appforkids.data.Models.Response.UserResponse
import com.example.appforkids.screen.common.CommonButton
import com.example.appforkids.screen.common.CommonTextFieldWithLabel
+import kotlinx.coroutines.flow.asStateFlow
@Preview
@Composable
-fun AuthorizeScreen() {
+fun AuthorizeScreen(onNavigateToClickerScreen: (Int) -> Unit) {
+ val authorizeViewModel:AuthorizeViewModel = viewModel()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
- modifier = Modifier.fillMaxSize().padding(5.dp),
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(5.dp),
) {
- var login by remember { mutableStateOf("") }
+ if(authorizeViewModel.isSignIn) {
+ onNavigateToClickerScreen(authorizeViewModel.userId)
+ authorizeViewModel.isSignIn = false;
+ }
CommonTextFieldWithLabel(
- value = login,
- onValueChange = { login = it},
+ value = authorizeViewModel.login,
+ onValueChange = { authorizeViewModel.login = it},
label = "Введите никнейм"
)
- var password by remember { mutableStateOf("") }
CommonTextFieldWithLabel(
- value = password,
- onValueChange = { password = it},
+ value = authorizeViewModel.password,
+ onValueChange = {authorizeViewModel.password = it},
label = "Введите пароль"
)
CommonButton(
- text = "Зарегистрироваться",
- onClick = {}
+ text = "Войти",
+ onClick = {
+ authorizeViewModel.authorize()
+ }
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/appforkids/screen/authorize/AuthorizeViewModel.kt b/app/src/main/java/com/example/appforkids/screen/authorize/AuthorizeViewModel.kt
new file mode 100644
index 0000000..1fca3c9
--- /dev/null
+++ b/app/src/main/java/com/example/appforkids/screen/authorize/AuthorizeViewModel.kt
@@ -0,0 +1,31 @@
+package com.example.appforkids.screen.authorize
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.viewModelScope
+import androidx.lifecycle.viewmodel.viewModelFactory
+import com.example.appforkids.data.HttpClient
+import com.example.appforkids.data.Models.Requests.AuthorizeUserRequest
+import com.example.appforkids.data.Models.Response.UserResponse
+import kotlinx.coroutines.launch
+
+class AuthorizeViewModel(): ViewModel() {
+ var login by mutableStateOf("")
+ var password by mutableStateOf("")
+ var isSignIn by mutableStateOf(false)
+ var userId by mutableIntStateOf(-1)
+ fun authorize(){
+ val authorizeUserRequest = AuthorizeUserRequest(login = login, password = password)
+ viewModelScope.launch {
+ var user = HttpClient.retrofitInstance.authorizeUser(authorizeUserRequest)
+ if (user != null) {
+ isSignIn = true
+ userId = user.id
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/appforkids/screen/common/CommonComponents.kt b/app/src/main/java/com/example/appforkids/screen/common/CommonComponents.kt
index 12be35e..310549f 100644
--- a/app/src/main/java/com/example/appforkids/screen/common/CommonComponents.kt
+++ b/app/src/main/java/com/example/appforkids/screen/common/CommonComponents.kt
@@ -12,13 +12,15 @@ import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
-@Preview
@Composable
fun CommonButton(onClick: () -> Unit, text: String){
Button(onClick = onClick,
modifier = Modifier
- .fillMaxWidth()
- .height(40.dp)) {
+ .padding(vertical = 10.dp)
+ .fillMaxWidth()
+ .height(40.dp)
+
+ ) {
Text(text = text)
}
}
diff --git a/app/src/main/java/com/example/appforkids/screen/main/ClickerScreen.kt b/app/src/main/java/com/example/appforkids/screen/main/ClickerScreen.kt
index 1437339..eb82b5a 100644
--- a/app/src/main/java/com/example/appforkids/screen/main/ClickerScreen.kt
+++ b/app/src/main/java/com/example/appforkids/screen/main/ClickerScreen.kt
@@ -24,9 +24,11 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.example.appforkids.R
+import com.example.appforkids.data.Models.Response.UserResponse
+import com.example.appforkids.screen.common.CommonButton
@Composable
-fun ClickerScreen(){
+fun ClickerScreen(userId: Int, OnRouteToRating: () -> Unit){
var countClick by remember { mutableIntStateOf(0) }
Column(
horizontalAlignment = Alignment.CenterHorizontally,
@@ -43,5 +45,6 @@ fun ClickerScreen(){
.border(border = BorderStroke(1.dp, Color.Gray))
)
Text(text = countClick.toString())
+ CommonButton(onClick = {OnRouteToRating()}, text = "Открыть рейтинг")
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/appforkids/screen/reigistration/RegistrationScreen.kt b/app/src/main/java/com/example/appforkids/screen/reigistration/RegistrationScreen.kt
index 1af410b..a5cfb2c 100644
--- a/app/src/main/java/com/example/appforkids/screen/reigistration/RegistrationScreen.kt
+++ b/app/src/main/java/com/example/appforkids/screen/reigistration/RegistrationScreen.kt
@@ -4,44 +4,51 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
-import androidx.compose.material3.Text
-import androidx.compose.material3.TextField
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.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.appforkids.screen.common.CommonButton
import com.example.appforkids.screen.common.CommonTextFieldWithLabel
@Preview
@Composable
-fun RegistrationScreen() {
+fun RegistrationScreen(onNavigateToAuthorization: () -> Unit) {
+ val registrationViewModel: RegistrationViewModel = viewModel(factory = RegistrationViewModel.Factory)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize().padding(5.dp),
) {
- var login by remember { mutableStateOf("") }
+ val registerState by registrationViewModel.registrationState.collectAsState()
+
CommonTextFieldWithLabel(
- value = login,
- onValueChange = { login = it},
+ value = registerState.login,
+ onValueChange = { registrationViewModel.setLogin(it)},
label = "Введите никнейм"
)
- var password by remember { mutableStateOf("") }
CommonTextFieldWithLabel(
- value = password,
- onValueChange = { password = it},
+ value = registerState.password,
+ onValueChange = {registrationViewModel.setPassword(it)},
label = "Введите пароль"
)
CommonButton(
- text = "Войти",
- onClick = {}
+ text = "Зарегестрироваться",
+ onClick = {
+ registrationViewModel.registerUser()
+ onNavigateToAuthorization()
+ }
+ )
+ CommonButton(
+ text = "Авторизоваться",
+ onClick = {
+ onNavigateToAuthorization()
+ }
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/appforkids/screen/reigistration/RegistrationState.kt b/app/src/main/java/com/example/appforkids/screen/reigistration/RegistrationState.kt
new file mode 100644
index 0000000..33dfab3
--- /dev/null
+++ b/app/src/main/java/com/example/appforkids/screen/reigistration/RegistrationState.kt
@@ -0,0 +1,3 @@
+package com.example.appforkids.screen.reigistration
+
+data class RegistrationState(var login: String = "", var password: String = "")
diff --git a/app/src/main/java/com/example/appforkids/screen/reigistration/RegistrationViewModel.kt b/app/src/main/java/com/example/appforkids/screen/reigistration/RegistrationViewModel.kt
new file mode 100644
index 0000000..3768261
--- /dev/null
+++ b/app/src/main/java/com/example/appforkids/screen/reigistration/RegistrationViewModel.kt
@@ -0,0 +1,42 @@
+package com.example.appforkids.screen.reigistration
+
+import androidx.lifecycle.AbstractSavedStateViewModelFactory
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.viewModelScope
+import androidx.lifecycle.viewmodel.initializer
+import androidx.lifecycle.viewmodel.viewModelFactory
+import com.example.appforkids.data.AppForKidsApi
+import com.example.appforkids.data.HttpClient
+import com.example.appforkids.data.Models.Requests.RegisterUserRequest
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.launch
+
+class RegistrationViewModel(val appForKidsApi: AppForKidsApi):ViewModel() {
+ val registrationState = MutableStateFlow(RegistrationState())
+
+ fun registerUser(){
+ val userRequest = RegisterUserRequest(login = registrationState.value.login, password = registrationState.value.password)
+
+ viewModelScope.launch {
+ appForKidsApi.registerUser(userRequest)
+ }
+ }
+ fun setLogin(login: String){
+ viewModelScope.launch {
+ registrationState.emit(registrationState.value.copy(login = login))
+ }
+ }
+ fun setPassword(password: String){
+ viewModelScope.launch {
+ registrationState.emit(registrationState.value.copy(password = password))
+ }
+ }
+ companion object {
+ val Factory:ViewModelProvider.Factory = viewModelFactory {
+ initializer {
+ RegistrationViewModel(HttpClient.retrofitInstance)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/appforkids/screen/score/ScoreScreen.kt b/app/src/main/java/com/example/appforkids/screen/score/ScoreScreen.kt
new file mode 100644
index 0000000..601a984
--- /dev/null
+++ b/app/src/main/java/com/example/appforkids/screen/score/ScoreScreen.kt
@@ -0,0 +1,40 @@
+package com.example.appforkids.screen.score
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.viewmodel.compose.viewModel
+import com.example.appforkids.screen.common.CommonButton
+import com.example.appforkids.screen.common.CommonTextFieldWithLabel
+
+@Composable
+fun ScoreScreen(onNavigateToClickerScreen: () -> Unit) {
+ val registrationViewModel: ScoreViewModel = viewModel()
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.Center,
+ modifier = Modifier.fillMaxSize().padding(5.dp),
+
+ ) {
+ val registerState by registrationViewModel.registrationState.collectAsState()
+
+ registerState.forEach {
+ Text(text = "${it.nickname} ${it.clicks}")
+ }
+ CommonButton(
+ text = "Вернуться",
+ onClick = {
+ onNavigateToClickerScreen()
+ }
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/appforkids/screen/score/ScoreViewModel.kt b/app/src/main/java/com/example/appforkids/screen/score/ScoreViewModel.kt
new file mode 100644
index 0000000..76ca6cc
--- /dev/null
+++ b/app/src/main/java/com/example/appforkids/screen/score/ScoreViewModel.kt
@@ -0,0 +1,24 @@
+package com.example.appforkids.screen.score
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.viewModelScope
+import androidx.lifecycle.viewmodel.initializer
+import androidx.lifecycle.viewmodel.viewModelFactory
+import com.example.appforkids.data.AppForKidsApi
+import com.example.appforkids.data.HttpClient
+import com.example.appforkids.data.Models.Requests.RegisterUserRequest
+import com.example.appforkids.data.Models.Response.UserResponse
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.launch
+import okhttp3.Response
+
+class ScoreViewModel():ViewModel() {
+ val registrationState = MutableStateFlow>(emptyList())
+
+ init {
+ viewModelScope.launch {
+ registrationState.emit(HttpClient.retrofitInstance.getUsers())
+ }
+ }
+}
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a5581cd..8ce8d49 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,16 +1,25 @@
[versions]
agp = "8.7.2"
+converterGson = "2.11.0"
+converterKotlinxSerialization = "2.11.0"
kotlin = "2.0.0"
coreKtx = "1.10.1"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
+kotlinxSerializationJson = "1.7.3"
lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.8.0"
composeBom = "2024.04.01"
+navigationCompose = "2.8.5"
+retrofit2KotlinxSerializationConverter = "1.0.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" }
+androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
+converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" }
+converter-kotlinx-serialization = { module = "com.squareup.retrofit2:converter-kotlinx-serialization", version.ref = "converterKotlinxSerialization" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
@@ -24,6 +33,9 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
+kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
+retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "converterGson" }
+retrofit2-kotlinx-serialization-converter = { module = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter", version.ref = "retrofit2KotlinxSerializationConverter" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }