Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ANDROAPP-5578-mobile-ui-Create-InputQrCode-component #84

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions common/src/commonMain/kotlin/org/hisp/dhis/common/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import org.hisp.dhis.common.screens.InputPercentageScreen
import org.hisp.dhis.common.screens.InputPhoneNumberScreen
import org.hisp.dhis.common.screens.InputPositiveIntegerOrZeroScreen
import org.hisp.dhis.common.screens.InputPositiveIntegerScreen
import org.hisp.dhis.common.screens.InputQRCodeScreen
import org.hisp.dhis.common.screens.InputRadioButtonScreen
import org.hisp.dhis.common.screens.InputScreen
import org.hisp.dhis.common.screens.InputSequentialScreen
Expand All @@ -56,7 +57,6 @@ import org.hisp.dhis.common.screens.LegendDescriptionScreen
import org.hisp.dhis.common.screens.LegendScreen
import org.hisp.dhis.common.screens.MetadataAvatarScreen
import org.hisp.dhis.common.screens.ProgressScreen
import org.hisp.dhis.common.screens.QrCodeBlockScreen
import org.hisp.dhis.common.screens.RadioButtonScreen
import org.hisp.dhis.common.screens.SectionScreen
import org.hisp.dhis.common.screens.SupportingTextScreen
Expand All @@ -74,7 +74,7 @@ fun App() {

@Composable
fun Main() {
val currentScreen = remember { mutableStateOf(Components.FORM_SHELLS) }
val currentScreen = remember { mutableStateOf(Components.INPUT_QR_CODE) }
var expanded by remember { mutableStateOf(false) }

Column(
Expand Down Expand Up @@ -154,7 +154,7 @@ fun Main() {
Components.INPUT_RADIO_BUTTON -> InputRadioButtonScreen()
Components.INPUT_MATRIX -> InputMatrixScreen()
Components.INPUT_SEQUENTIAL -> InputSequentialScreen()
Components.QR_CODE_BLOCK -> QrCodeBlockScreen()
Components.INPUT_QR_CODE -> InputQRCodeScreen()
Components.INPUT_CHECK_BOX -> InputCheckBoxScreen()
Components.BARCODE_BLOCK -> BarcodeBlockScreen()
Components.INPUT_YES_ONLY_SWITCH -> InputYesOnlySwitchScreen()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ enum class Components(val label: String) {
SWITCH("Switch"),
INPUT_MATRIX("Input Matrix"),
INPUT_SEQUENTIAL("Input Sequential"),
QR_CODE_BLOCK("QR Code Block"),
INPUT_QR_CODE("Input QR code"),
INPUT_CHECK_BOX("Input Check Box"),
BARCODE_BLOCK("Barcode Block"),
AGE_FIELD("Age Field"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package org.hisp.dhis.common.screens

import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.FileDownload
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.QrCodeScanner
import androidx.compose.material.icons.outlined.Share
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import org.hisp.dhis.mobile.ui.designsystem.component.BottomSheetShell
import org.hisp.dhis.mobile.ui.designsystem.component.ColumnComponentContainer
import org.hisp.dhis.mobile.ui.designsystem.component.Description
import org.hisp.dhis.mobile.ui.designsystem.component.InputQRCode
import org.hisp.dhis.mobile.ui.designsystem.component.InputShellState
import org.hisp.dhis.mobile.ui.designsystem.component.QrCodeBlock
import org.hisp.dhis.mobile.ui.designsystem.component.SupportingTextData
import org.hisp.dhis.mobile.ui.designsystem.component.SupportingTextState
import org.hisp.dhis.mobile.ui.designsystem.resource.provideStringResource
import org.hisp.dhis.mobile.ui.designsystem.theme.Shape
import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing
import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor
import org.hisp.dhis.mobile.ui.designsystem.theme.TextColor

@Composable
fun InputQRCodeScreen() {
ColumnComponentContainer {
var inputValue1 by rememberSaveable { mutableStateOf("889026a1-d01e-4d34-8209-81e8ed5c614b") }
var showEnabledQRBottomSheet by rememberSaveable { mutableStateOf(false) }

Description("Default Input QR code", textColor = TextColor.OnSurfaceVariant)
InputQRCode(
"label",
state = InputShellState.UNFOCUSED,
onQRButtonClicked = {
showEnabledQRBottomSheet = !showEnabledQRBottomSheet
},
inputText = inputValue1,
onValueChanged = {
if (it != null) {
inputValue1 = it
}
},

)

if (showEnabledQRBottomSheet) {
BottomSheetShell(
modifier = Modifier.testTag("LEGEND_BOTTOM_SHEET"),
title = provideStringResource("qr_code"),
icon = {
Icon(
imageVector = Icons.Outlined.Info,
contentDescription = "Button",
tint = SurfaceColor.Primary,
)
},
content = {
Row(horizontalArrangement = Arrangement.Center) {
QrCodeBlock(data = inputValue1)
}
},
buttonBlock = {
Row(
Modifier
.fillMaxSize()
.horizontalScroll(rememberScrollState()),
horizontalArrangement = Arrangement.Center,
) {
Button(
onClick = {},
modifier = Modifier
.padding(top = Spacing.Spacing4)
.width(Spacing.Spacing80)
.weight(1f),
shape = Shape.Full,
enabled = true,
colors = ButtonDefaults.buttonColors(Color.Transparent, TextColor.OnSurfaceVariant, Color.Transparent, TextColor.OnDisabledSurface),
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Icon(
imageVector = Icons.Outlined.Share,
contentDescription = "Carousel Button",
)

Spacer(Modifier.size(Spacing.Spacing8))
Text("Share", style = MaterialTheme.typography.labelSmall, textAlign = TextAlign.Center, maxLines = 2, overflow = TextOverflow.Ellipsis)
}
}
Button(
onClick = {},
modifier = Modifier
.padding(top = Spacing.Spacing4)
.width(Spacing.Spacing80)
.weight(1f),
shape = Shape.Full,
enabled = true,
colors = ButtonDefaults.buttonColors(Color.Transparent, TextColor.OnSurfaceVariant, Color.Transparent, TextColor.OnDisabledSurface),
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Icon(
imageVector = Icons.Outlined.QrCodeScanner,
contentDescription = "Carousel Button",
)

Spacer(Modifier.size(Spacing.Spacing8))
Text("Scan", style = MaterialTheme.typography.labelSmall, textAlign = TextAlign.Center, maxLines = 2, overflow = TextOverflow.Ellipsis)
}
}

Button(
onClick = {},
modifier = Modifier
.padding(top = Spacing.Spacing4)
.width(Spacing.Spacing80)
.weight(1f),
shape = Shape.Full,
enabled = true,
colors = ButtonDefaults.buttonColors(Color.Transparent, TextColor.OnSurfaceVariant, Color.Transparent, TextColor.OnDisabledSurface),
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Icon(
imageVector = Icons.Outlined.FileDownload,
contentDescription = "Carousel Button",
)

Spacer(Modifier.size(Spacing.Spacing8))
Text("Download", style = MaterialTheme.typography.labelSmall, textAlign = TextAlign.Center, maxLines = 2, overflow = TextOverflow.Ellipsis)
}
}
}
},
) {
showEnabledQRBottomSheet = false
}
}

var inputValue2 by rememberSaveable { mutableStateOf("") }
Description("Required field Input QR code", textColor = TextColor.OnSurfaceVariant)
InputQRCode(
"label",
state = InputShellState.ERROR,
onQRButtonClicked = {
},
inputText = inputValue2,
onValueChanged = {
if (it != null) {
inputValue2 = it
}
},
isRequiredField = true,
supportingText = listOf(SupportingTextData("Required", SupportingTextState.ERROR)),
)
Spacer(Modifier.size(Spacing.Spacing18))

Spacer(Modifier.size(Spacing.Spacing18))
var inputValue by rememberSaveable { mutableStateOf("") }
Description("Disabled Input QR code", textColor = TextColor.OnSurfaceVariant)
InputQRCode(
"label",
state = InputShellState.DISABLED,
onQRButtonClicked = {
},
inputText = inputValue,
onValueChanged = {
if (it != null) {
inputValue = it
}
},
)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ fun BottomSheetShell(
modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxHeight(1f),
horizontalAlignment = Alignment.CenterHorizontally,
) {
content?.let {
it.invoke()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.hisp.dhis.mobile.ui.designsystem.component

import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.QrCode2
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.input.ImeAction

/**
* DHIS2 Input QR Code. Wraps DHIS · [BasicTextInput].
* @param title controls the text to be shown for the title
* @param state Manages the InputShell state
* @param onQRButtonClicked gives access to the action button event
* @param supportingText is a list of SupportingTextData that
* manages all the messages to be shown
* @param legendData manages the legendComponent
* @param inputText manages the value of the text in the input field
* @param isRequiredField controls whether the field is mandatory or not
* @param onNextClicked gives access to the imeAction event
* @param onValueChanged gives access to the onValueChanged event
* @param onFocusChanged gives access to the onFocusChanged returns true if
* item is focused
* @param imeAction controls the imeAction button to be shown
* @param modifier allows a modifier to be passed externally
*/
@Composable
fun InputQRCode(
title: String,
state: InputShellState = InputShellState.UNFOCUSED,
onQRButtonClicked: () -> Unit,
supportingText: List<SupportingTextData>? = null,
legendData: LegendData? = null,
inputText: String? = null,
isRequiredField: Boolean = false,
onNextClicked: (() -> Unit)? = null,
onValueChanged: ((String?) -> Unit)? = null,
onFocusChanged: ((Boolean) -> Unit)? = null,
imeAction: ImeAction = ImeAction.Next,
modifier: Modifier = Modifier,
) {
BasicTextInput(
title = title,
state = state,
supportingText = supportingText,
legendData = legendData,
inputText = inputText,
isRequiredField = isRequiredField,
onNextClicked = onNextClicked,
onValueChanged = onValueChanged,
keyboardOptions = KeyboardOptions(imeAction = imeAction),
modifier = modifier,
testTag = "QR_CODE",
onFocusChanged = onFocusChanged,
actionButton = {
SquareIconButton(
modifier = Modifier.testTag("INPUT_QR_CODE_BUTTON"),
enabled = true,
icon = {
Icon(
imageVector = Icons.Outlined.QrCode2,
contentDescription = null,
)
},
onClick = onQRButtonClicked,
)
},
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="enter_phone_number">Enter phone number</string>
<string name="qr_code">QR code</string>
</resources>
Loading
Loading