Skip to content

Commit

Permalink
Submit Fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ferdiallen committed May 2, 2023
1 parent 5fa950b commit f02aa2c
Show file tree
Hide file tree
Showing 18 changed files with 187 additions and 57 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ android {
minSdk = 24
targetSdk = 33
versionCode = 1
versionName = "0.55-alpha"
versionName = "0.6-alpha"
buildConfigField("String", "BASE_URL", baseUrlKey)
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand Down Expand Up @@ -118,7 +118,7 @@ dependencies {
implementation("androidx.media3:media3-ui:$media3_version")

//Ktor
val ktorVersion = "2.2.4"
val ktorVersion = "2.3.0"
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-android:$ktorVersion")
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
Expand Down
12 changes: 10 additions & 2 deletions app/src/main/java/com/example/nineintelligence/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ import androidx.navigation.compose.rememberNavController
import com.example.nineintelligence.core.AuthPrefs
import com.example.nineintelligence.domain.util.ExamType
import com.example.nineintelligence.navigation.RootNavigation
import com.example.nineintelligence.presentation.discuss.DiscussionScreen
import com.example.nineintelligence.presentation.dummy.SubmitTest
import com.example.nineintelligence.presentation.enter.LoginForm
import com.example.nineintelligence.presentation.enter.RegisterScreen
import com.example.nineintelligence.presentation.exam.ExamScreen
import com.example.nineintelligence.presentation.home.HomeScreen
import com.example.nineintelligence.presentation.profile.ProfileScreen
import com.example.nineintelligence.ui.theme.NineIntelligenceTheme
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import org.koin.android.ext.android.get

@UnstableApi
Expand All @@ -39,8 +42,8 @@ class MainActivity : ComponentActivity() {
/*MainReadingSubject(
modifier = Modifier.padding(horizontal = 12.dp)
)*/
/*RootNavigation()*/
RegisterScreen(controller = rememberNavController())
RootNavigation()
/*RegisterScreen(controller = rememberNavController())*/
/*ProfileScreen(
Modifier
.fillMaxSize()
Expand Down Expand Up @@ -69,6 +72,11 @@ class MainActivity : ComponentActivity() {
typeOf = ExamType.TAKE_EXAMS, slugName = "tryout-testing-1", time = 60
)*/
/*BankSoal(controller = rememberNavController(), modifier = Modifier.fillMaxSize())*/
/*HomeScreen(
systemUi = rememberSystemUiController(),
rootController = rememberNavController()
)*/
/* DiscussionScreen(typeOf = "", controller = rememberNavController())*/
}
}
}
Expand Down
45 changes: 38 additions & 7 deletions app/src/main/java/com/example/nineintelligence/core/AuthPrefs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,23 @@ class AuthPrefs(

private companion object {
const val AUTH_KEY = "auth_token"
const val TIMER_KEY = "token_time"
const val SAVED_USERNAME = "username"
const val SAVED_PASSWORD = "password"
val AUTH_KEY_PREF = stringPreferencesKey(AUTH_KEY)
val TIMER_KEY_PREF = stringPreferencesKey(TIMER_KEY)
val USER_PREF = stringPreferencesKey(SAVED_USERNAME)
val PASSWORD_PREF = stringPreferencesKey(SAVED_PASSWORD)
}

suspend fun saveToken(key: String, definedTime: String) {
suspend fun saveToken(key: String) {
store.edit { authKey ->
authKey[AUTH_KEY_PREF] = key
authKey[TIMER_KEY_PREF] = definedTime
}
}

suspend fun rememberUser(name: String, password: String) {
store.edit { userPrefs ->
userPrefs[USER_PREF] = name
userPrefs[PASSWORD_PREF] = password
}
}

Expand All @@ -34,15 +42,38 @@ class AuthPrefs(
}.first()
}

suspend fun readTime(): String? {
suspend fun readTokenNonBlocking(): String? {
return store.data.map {
it[TIMER_KEY_PREF]
it[AUTH_KEY_PREF]
}.first()
}

suspend fun isRememberSaved(userName: (String) -> Unit, password: (String) -> Unit): Boolean {
val savedUser = store.data.map {
listOf(
it[USER_PREF],
it[PASSWORD_PREF]
).takeWhile { out ->
out != null
}
}.first()
if (savedUser.isNotEmpty()) {
userName(savedUser[0] ?: "")
password(savedUser[1] ?: "")
}
return savedUser.isNotEmpty()
}

suspend fun clearData() {
store.edit {
it.clear()
it.remove(AUTH_KEY_PREF)
}
}

suspend fun deleteSavedUser() {
store.edit {
it.remove(USER_PREF)
it.remove(PASSWORD_PREF)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ val appModule = module {
HomeViewModel(get(), get())
}
viewModel {
TryOutInformationViewModel(get(), get())
TryOutInformationViewModel(get(), get(), get())
}

single<GetBankSoalList> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import kotlinx.serialization.Serializable

@Serializable
data class StartTryoutResponse(
@SerialName("to_id") val tryoutId: Int? = null,
@SerialName("user_answers") val userAnswer: List<UserAnswerData>? = emptyList(),
@SerialName("user_id") val userId: String? = null,
@SerialName("soal_struct") val soalStruct: String? = null,
@SerialName("draft_id") val draftId: Int? = null,
@SerialName("duration") val duration: Int? = null,
@SerialName("user_id") val userId: String? = null,
@SerialName("to_id") val tryoutId: Int? = null,
@SerialName("user_answers") val userAnswer: List<UserAnswerData> = emptyList()
@SerialName("duration") val duration: String? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import kotlinx.serialization.Serializable

@Serializable
data class SubmitModel(
@SerialName("user_answers") val userAnswers: List<UserAnswerData>
@SerialName("user_answers") val userAnswers: List<UserAnswerData> = emptyList()
)
@Serializable
data class UserAnswerData(
@SerialName("soal_id") val id: Int,
@SerialName("answer") val answer: String
@SerialName("soal_id") val id: Int = 0,
@SerialName("answer") val answer: String = ""
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@ import com.example.nineintelligence.domain.models.StartTryoutResponse
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.bearerAuth
import io.ktor.client.request.get
import io.ktor.client.request.post
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json

class StartTryoutImpl(
private val http: HttpClient,
private val authPrefs: AuthPrefs
) : StartTryout {
override suspend fun startTryout(slugname: String): StartTryoutResponse {
return http.post("${BuildConfig.BASE_URL}tryouts/$slugname/start") {
bearerAuth(authPrefs.readToken() ?: return@post)
}.body()
val res =
Json.decodeFromString<StartTryoutResponse>(http.post("${BuildConfig.BASE_URL}tryouts/$slugname/start") {
bearerAuth(authPrefs.readToken() ?: return@post)
}.body())
return res
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class SubmitAnswerImpl(
) : SubmitAnswer {
override suspend fun submitAnswer(answer: SubmitModel, slugName: String): String {
val res = http.post("${BuildConfig.BASE_URL}tryouts/$slugName/submit") {
bearerAuth(prefs.readToken() ?: return@post)
bearerAuth(prefs.readTokenNonBlocking() ?: return@post)
contentType(ContentType.Application.Json)
setBody(answer)
}.body<String>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ class StartTryoutUseCase(
return try {
val res = tryout.startTryout(slugname)
Resource.Success(res)
} catch (e: Exception) {
}/* catch (e: Exception) {
println(e.message)
Resource.Error(e.message)
} catch (e: IOException) {
}*/ catch (e: IOException) {
println(e.message)
Resource.Error(e.message)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ fun DiscussionScreen(
controller.popBackStack()
}
)

if (shouldShowPlaylistSelector) {
MenuListDialog(onDismiss = {
shouldShowPlaylistSelector = false
Expand Down Expand Up @@ -172,9 +171,10 @@ private fun MainScreen(

color = MainBlueColor
)
SideEffect {
LaunchedEffect(key1 = Unit, block = {
playSelectedVideo(videoList[it], context, player = playerExo)
}
})

DisposableEffect(key1 = true, effect = {
onDispose {
playerExo.release()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.example.nineintelligence.presentation.enter

import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.nineintelligence.core.AuthPrefs
Expand All @@ -10,6 +12,7 @@ import com.example.nineintelligence.domain.util.Resource
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

Expand All @@ -21,24 +24,55 @@ class EnterViewModel(
private val _currentPassword = MutableStateFlow("")
private val _isCheckedRememberMe = MutableStateFlow(false)
private val _loginState = mutableStateOf(LoginState())
var isLoadingLogin by mutableStateOf(false)
private set
val loginState: State<LoginState> = _loginState
val currentEmail = _currentEmail.asStateFlow()
val currentPassword = _currentPassword.asStateFlow()
val isCheckedRememberMe = _isCheckedRememberMe.asStateFlow()

init {
viewModelScope.launch(Dispatchers.IO) {
_isCheckedRememberMe.update {
store.isRememberSaved(userName = { username ->
_currentEmail.update {
username
}
}, password = { password ->
_currentPassword.update {
password
}
})
}
}
}

fun onEmailChange(text: String) = _currentEmail.update { text }
fun onPasswordChange(text: String) = _currentPassword.update { text }
fun onCheckedChange(data: Boolean) = _isCheckedRememberMe.update { data }
fun onCheckedChange(data: Boolean) {
viewModelScope.launch(Dispatchers.IO) {
if (!data && store.isRememberSaved(userName = {}, password = {})) {
store.deleteSavedUser()
}
}
_isCheckedRememberMe.update { data }
}

fun loginUser(username: String, password: String) = viewModelScope.launch(Dispatchers.IO) {
isLoadingLogin = true
login.getUserAuth(username, password).let { out ->
when (out) {
is Resource.Success -> {
store.saveToken(out.data?.token ?: return@launch, "")
isLoadingLogin = false
if (isCheckedRememberMe.first()) {
store.rememberUser(username, password)
}
store.saveToken(out.data?.token ?: return@launch)
_loginState.value = LoginState(false, out.data.token, "")
}

is Resource.Error -> {
isLoadingLogin = false
_loginState.value = LoginState(false, null, out.errorMessages ?: "")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.util.Patterns
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
Expand All @@ -24,6 +25,7 @@ import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.CheckboxDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
Expand Down Expand Up @@ -52,6 +54,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
import com.example.nineintelligence.R
Expand All @@ -67,8 +70,7 @@ import org.koin.androidx.compose.koinViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LoginForm(
viewModel: EnterViewModel = koinViewModel(),
controller: NavController
viewModel: EnterViewModel = koinViewModel(), controller: NavController
) {
val email by viewModel.currentEmail.collectAsStateWithLifecycle()
val password by viewModel.currentPassword.collectAsStateWithLifecycle()
Expand Down Expand Up @@ -163,12 +165,13 @@ fun LoginForm(
fontFamily = font,
fontSize = 14.sp
)
}, isError = if (hasFocusedEmail) isErrorEmailAddress else false,
},
isError = if (hasFocusedEmail) isErrorEmailAddress else false,
singleLine = true,
supportingText = {
if(hasFocusedEmail && isErrorEmailAddress) {
CustomText(text = "Invalid Email Address")
}
if (hasFocusedEmail && isErrorEmailAddress) {
CustomText(text = "Invalid Email Address")
}
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email)
)
Expand Down Expand Up @@ -204,8 +207,7 @@ fun LoginForm(
}) {
Icon(
imageVector = if (passwordVisibility) Icons.Filled.VisibilityOff
else Icons.Filled.Visibility,
contentDescription = null
else Icons.Filled.Visibility, contentDescription = null
)
}
},
Expand Down Expand Up @@ -254,7 +256,16 @@ fun LoginForm(
}
}
}
Box(
modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center
) {
if(viewModel.isLoadingLogin){
Dialog(onDismissRequest = { }) {
CircularProgressIndicator(color = MainYellowColor)
}

}
}
}

}
Loading

0 comments on commit f02aa2c

Please sign in to comment.