diff --git a/common/src/commonMain/kotlin/org/hisp/dhis/common/App.kt b/common/src/commonMain/kotlin/org/hisp/dhis/common/App.kt index da09ea305..338d00780 100644 --- a/common/src/commonMain/kotlin/org/hisp/dhis/common/App.kt +++ b/common/src/commonMain/kotlin/org/hisp/dhis/common/App.kt @@ -46,6 +46,7 @@ import org.hisp.dhis.common.screens.InputTextScreen import org.hisp.dhis.common.screens.LegendDescriptionScreen import org.hisp.dhis.common.screens.LegendScreen 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 @@ -139,6 +140,7 @@ fun Main() { Components.BADGES -> BadgesScreen() Components.SWITCH -> SwitchScreen() Components.INPUT_RADIO_BUTTON -> InputRadioButtonScreen() + Components.QR_CODE_BLOCK -> QrCodeBlockScreen() } } } diff --git a/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/Components.kt b/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/Components.kt index bacc51319..91422e763 100644 --- a/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/Components.kt +++ b/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/Components.kt @@ -30,4 +30,5 @@ enum class Components(val label: String) { ICON_CARDS("Icon Cards"), INPUT_RADIO_BUTTON("Input Radio Button"), SWITCH("Switch"), + QR_CODE_BLOCK("QR Code Block"), } diff --git a/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/QrCodeBlockScreen.kt b/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/QrCodeBlockScreen.kt new file mode 100644 index 000000000..68a0547bb --- /dev/null +++ b/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/QrCodeBlockScreen.kt @@ -0,0 +1,23 @@ +package org.hisp.dhis.common.screens + +import androidx.compose.material3.Divider +import androidx.compose.runtime.Composable +import org.hisp.dhis.mobile.ui.designsystem.component.ColumnComponentContainer +import org.hisp.dhis.mobile.ui.designsystem.component.QrCodeBlock +import org.hisp.dhis.mobile.ui.designsystem.component.RowComponentContainer + +@Composable +fun QrCodeBlockScreen() { + ColumnComponentContainer { + QrCodeBlock(data = "QR code value") + Divider() + QrCodeBlock(data = "889026a1-d01e-4d34-8209-81e8ed5c614b") + Divider() + QrCodeBlock(data = "l;kw1jheoi1u23iop1") + Divider() + RowComponentContainer { + QrCodeBlock(data = "563ce8df-8e0b-420c-a63c-fe000b1d1f11") + QrCodeBlock(data = "378c472d-bb05-4174-9fe5-f6dbf8f5de36") + } + } +} diff --git a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/QrCodeBlock.kt b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/QrCodeBlock.kt new file mode 100644 index 000000000..d2f9db057 --- /dev/null +++ b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/QrCodeBlock.kt @@ -0,0 +1,64 @@ +package org.hisp.dhis.mobile.ui.designsystem.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredWidthIn +import androidx.compose.foundation.layout.size +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import org.hisp.dhis.mobile.ui.designsystem.component.internal.qr.rememberQrCodeGenerator +import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing +import org.hisp.dhis.mobile.ui.designsystem.theme.TextColor + +/** + * Container to render QR code image and text for given + * data + * + * @param data: Data to render QR code and text for + */ +@Composable +fun QrCodeBlock( + data: String, + modifier: Modifier = Modifier, + qrCodeSize: Dp = 240.dp, +) { + if (data.isNotBlank()) { + Column( + modifier = modifier.padding(vertical = Spacing.Spacing16) + .requiredWidthIn(max = qrCodeSize) + .testTag("QR_CODE_BLOCK_CONTAINER"), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + val qrCode by rememberQrCodeGenerator(data) + + Box(Modifier.size(qrCodeSize)) { + qrCode?.let { bitmap -> + Image( + bitmap = bitmap, + contentDescription = null, + modifier = Modifier.matchParentSize(), + contentScale = ContentScale.FillBounds, + ) + } + } + + Text( + text = data, + style = MaterialTheme.typography.titleMedium, + color = TextColor.OnSurface, + textAlign = TextAlign.Center, + ) + } + } +} diff --git a/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/QrCodeBlockTest.kt b/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/QrCodeBlockTest.kt new file mode 100644 index 000000000..508f3d2da --- /dev/null +++ b/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/QrCodeBlockTest.kt @@ -0,0 +1,30 @@ +package org.hisp.dhis.mobile.ui.designsystem.component + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag +import org.junit.Rule +import org.junit.Test + +class QrCodeBlockTest { + + @get:Rule + val rule = createComposeRule() + + @Test + fun shouldNotRenderQrCodeBlockIfDataIsEmpty() { + rule.setContent { + QrCodeBlock(data = "") + } + + rule.onNodeWithTag("QR_CODE_BLOCK_CONTAINER").assertDoesNotExist() + } + + @Test + fun shouldRenderQrCodeBlockIfDataExists() { + rule.setContent { + QrCodeBlock(data = "1b8ea3ff-f0da-4101-b2a6-d51a3b228d67") + } + + rule.onNodeWithTag("QR_CODE_BLOCK_CONTAINER").assertExists() + } +}