Skip to content

Commit

Permalink
Edured-83: implement add role/institution from the personal informati…
Browse files Browse the repository at this point in the history
…on screen.
  • Loading branch information
Iulia Stana committed Apr 14, 2023
1 parent 2a7b538 commit 942f87f
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ private fun AccountLinkedContent(
withBackIcon = false
) {
Column(
modifier = Modifier.verticalScroll(rememberScrollState())
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
) {
if (errorData != null) {
AlertDialogWithSingleButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,21 @@ class PersonalInfoRepository(private val eduIdApi: EduIdApi) {
Timber.e(e, "Failed to retrieve institution name")
null
}

suspend fun getStartLinkAccount(): String? = try {
val response = eduIdApi.getStartLinkAccount()
if (response.isSuccessful) {
response.body()?.url
} else {
Timber.w(
"Failed to retrieve start link account URL: [${response.code()}/${response.message()}]${
response.errorBody()?.string()
}"
)
null
}
} catch (e: Exception) {
Timber.e(e, "Failed to retrieve start link account URL")
null
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package nl.eduid.screens.personalinfo

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand All @@ -17,19 +18,25 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment.Companion.CenterStart
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import nl.eduid.ErrorData
import nl.eduid.R
import nl.eduid.screens.firsttimedialog.LinkAccountContract
import nl.eduid.ui.AlertDialogWithSingleButton
import nl.eduid.ui.EduIdTopAppBar
import nl.eduid.ui.InfoTab
Expand All @@ -43,11 +50,30 @@ fun PersonalInfoScreen(
viewModel: PersonalInfoViewModel,
onEmailClicked: () -> Unit,
onManageAccountClicked: (dateString: String) -> Unit,
goToAccountLinked: () -> Unit = {},
goBack: () -> Unit,
) = EduIdTopAppBar(
onBackClicked = goBack,
) {
val uiState by viewModel.uiState.observeAsState(UiState())
var isGettingLinkUrl by rememberSaveable { mutableStateOf(false) }
var isLinkingStarted by rememberSaveable { mutableStateOf(false) }
val launcher =
rememberLauncherForActivityResult(contract = LinkAccountContract(), onResult = { _ ->
if (isLinkingStarted) {
isLinkingStarted = false
goToAccountLinked()
}
})

if (isGettingLinkUrl && uiState.haveValidLinkIntent()) {
LaunchedEffect(key1 = viewModel) {
isGettingLinkUrl = false
launcher.launch(uiState.linkUrl)
isLinkingStarted = true
}
}

PersonalInfoScreenContent(
personalInfo = uiState.personalInfo,
isLoading = uiState.isLoading,
Expand All @@ -56,6 +82,10 @@ fun PersonalInfoScreen(
onEmailClicked = onEmailClicked,
removeConnection = { index -> viewModel.removeConnection(index) },
onManageAccountClicked = onManageAccountClicked,
addLinkToAccount = {
isGettingLinkUrl = true
viewModel.requestLinkUrl()
},
)
}

Expand All @@ -68,10 +98,10 @@ fun PersonalInfoScreenContent(
onEmailClicked: () -> Unit = {},
removeConnection: (Int) -> Unit = {},
onManageAccountClicked: (dateString: String) -> Unit = {},
addLinkToAccount: () -> Unit = {},
) = Column(
verticalArrangement = Arrangement.Bottom,
modifier = Modifier
.verticalScroll(rememberScrollState())
modifier = Modifier.verticalScroll(rememberScrollState())
) {
if (errorData != null) {
AlertDialogWithSingleButton(
Expand All @@ -86,9 +116,7 @@ fun PersonalInfoScreenContent(
Text(
style = MaterialTheme.typography.titleLarge.copy(
textAlign = TextAlign.Start, color = ButtonGreen
),
text = stringResource(R.string.personal_info_title),
modifier = Modifier.fillMaxWidth()
), text = stringResource(R.string.personal_info_title), modifier = Modifier.fillMaxWidth()
)
Spacer(Modifier.height(12.dp))
Text(
Expand Down Expand Up @@ -151,6 +179,38 @@ fun PersonalInfoScreenContent(
)
}

Spacer(Modifier.height(12.dp))
OutlinedButton(
onClick = addLinkToAccount,
shape = RoundedCornerShape(CornerSize(6.dp)),
modifier = Modifier
.fillMaxWidth()
.sizeIn(minHeight = 72.dp)
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = stringResource(R.string.personalinfo_add_role_institution),
style = MaterialTheme.typography.bodyLarge.copy(
textAlign = TextAlign.Start,
color = ButtonTextGrey,
fontWeight = FontWeight.Bold,
)
)
Text(
text = stringResource(R.string.personalinfo_add_via),
style = MaterialTheme.typography.bodyMedium.copy(
textAlign = TextAlign.Start,
color = ButtonTextGrey,
fontWeight = FontWeight.Light,
fontStyle = FontStyle.Italic
)
)
}
Image(
painter = painterResource(R.drawable.ic_plus),
contentDescription = "",
)
}
Spacer(Modifier.height(42.dp))
OutlinedButton(
onClick = { onManageAccountClicked(personalInfo.dateCreated.getDateTimeString("EEEE, dd MMMM yyyy 'at' HH:MM")) },
Expand All @@ -163,8 +223,7 @@ fun PersonalInfoScreenContent(
painter = painterResource(R.drawable.cog_icon),
alignment = CenterStart,
contentDescription = "",
modifier = Modifier
.padding(end = 48.dp)
modifier = Modifier.padding(start = 24.dp, end = 24.dp)
)
Text(
text = stringResource(R.string.personalinfo_manage_your_account),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package nl.eduid.screens.personalinfo

import android.content.Intent
import android.net.Uri
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import nl.eduid.ErrorData
import nl.eduid.di.model.UserDetails
import timber.log.Timber
import javax.inject.Inject

@HiltViewModel
Expand Down Expand Up @@ -82,6 +85,46 @@ class PersonalInfoViewModel @Inject constructor(private val repository: Personal
)
}

fun requestLinkUrl() = viewModelScope.launch {
val currentUiState = uiState.value ?: UiState()
uiState.postValue(currentUiState.copy(isLoading = true, linkUrl = null))
try {
val response = repository.getStartLinkAccount()
if (response != null) {
uiState.postValue(
currentUiState.copy(
linkUrl = createLaunchIntent(response), isLoading = false
)
)
} else {
uiState.postValue(
currentUiState.copy(
isLoading = false, errorData = ErrorData(
"Failed to get link URL",
"Could not retrieve URL to link your current account"
)
)
)
}
} catch (e: Exception) {
Timber.e(e, "Failed to get link account for current user")
uiState.postValue(
currentUiState.copy(
isLoading = false, errorData = ErrorData(
"Failed to get link URL",
"Could not retrieve URL to link your current account"
)
)
)
}
}

private fun createLaunchIntent(url: String): Intent {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(url)
return intent
}

private fun convertToUiData(userDetails: UserDetails): PersonalInfo {
val dateCreated = userDetails.created
val linkedAccounts = userDetails.linkedAccounts
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/kotlin/nl/eduid/screens/personalinfo/UiState.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package nl.eduid.screens.personalinfo

import android.content.Intent
import nl.eduid.ErrorData

data class UiState(
val personalInfo: PersonalInfo = PersonalInfo(),
val linkUrl: Intent? = null,
val isLoading: Boolean = false,
val errorData: ErrorData? = null,
)
) {
fun haveValidLinkIntent() = !isLoading && errorData == null && linkUrl != null
}
File renamed without changes.
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@
<string name="infotab_at">At %s</string>
<string name="infotab_role_institution">Role &amp; institution</string>
<string name="personalinfo_manage_your_account">Manage your account</string>
<string name="personalinfo_add_role_institution">Add role &amp; institution</string>
<string name="personalinfo_add_via">Proceed to add this via SURFConext</string>
<string name="infotab_delete_login_details">Delete login details *</string>

<string name="delete_service_confirm_title">Delete service</string>
Expand Down

0 comments on commit 942f87f

Please sign in to comment.