diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardDefaults.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardDefaults.kt new file mode 100644 index 000000000..e2f973ad9 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardDefaults.kt @@ -0,0 +1,44 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.takeOrElse + +@Immutable +data class ContactCardColors( + val waveBackground: Color, + val background: Color, +) + +object ContactCardDefaults { + @Composable + fun colors( + waveBackground: Color = Color.Unspecified, + background: Color = Color.Unspecified, + ): ContactCardColors { + val defaultWave = MaterialTheme.colorScheme.surfaceContainerLowest + val defaultBackground = MaterialTheme.colorScheme.primaryContainer + return ContactCardColors( + waveBackground = waveBackground.takeOrElse { defaultWave }, + background = background.takeOrElse { defaultBackground }, + ) + } +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardTopBarState.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardTopBarState.kt new file mode 100644 index 000000000..526b3b58d --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardTopBarState.kt @@ -0,0 +1,23 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard + +sealed interface ContactCardTopBarState { + data class Editor(val onCancel: () -> Unit, val onSave: () -> Unit) : ContactCardTopBarState + data class Preview(val onClose: () -> Unit, val onMore: () -> Unit) : ContactCardTopBarState + data class Default(val onBack: () -> Unit) : ContactCardTopBarState +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/BottomSheetAction.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/BottomSheetAction.kt new file mode 100644 index 000000000..b8b235469 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/BottomSheetAction.kt @@ -0,0 +1,92 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Edit +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.core.ui.compose.margin.Margin + +@Composable +internal fun BottomSheetAction( + icon: ImageVector, + label: String, + onClick: () -> Unit, +) { + TextButton( + onClick = onClick, + shape = RectangleShape, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = Margin.Mini), + contentPadding = PaddingValues(Margin.Small), + colors = ButtonDefaults.textButtonColors( + contentColor = MaterialTheme.colorScheme.onSurface, + ) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier.size(24.dp), + ) + Spacer(Modifier.width(Margin.Medium)) + Text( + text = label, + style = MaterialTheme.typography.bodyLarge, + ) + } + } +} + +@Preview(name = "BottomSheetAction") +@Composable +private fun BottomSheetActionPreview() { + MaterialTheme { + Surface { + BottomSheetAction( + icon = Icons.Default.Edit, + label = "Edit", + onClick = {}, + ) + } + } +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactCardConstants.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactCardConstants.kt new file mode 100644 index 000000000..a6bc9d667 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactCardConstants.kt @@ -0,0 +1,21 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.ui.unit.dp + +internal val CardCornerRadius = 12.dp diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactCardTopBar.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactCardTopBar.kt new file mode 100644 index 000000000..1efc7e028 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactCardTopBar.kt @@ -0,0 +1,54 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.foundation.layout.RowScope +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import com.infomaniak.core.ui.compose.contactcard.R + +@Composable +@OptIn(ExperimentalMaterial3Api::class) +internal fun ContactCardTopBar( + navigationIcon: @Composable () -> Unit = {}, + actions: @Composable RowScope.() -> Unit = {}, + containerColor: Color = Color.Transparent, +) { + CenterAlignedTopAppBar( + title = { + Text( + text = stringResource(R.string.contactCardTitle), + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onSurface, + ) + }, + navigationIcon = navigationIcon, + actions = actions, + colors = TopAppBarDefaults.centerAlignedTopAppBarColors( + containerColor = containerColor, + titleContentColor = MaterialTheme.colorScheme.onSurface, + navigationIconContentColor = MaterialTheme.colorScheme.primary, + actionIconContentColor = MaterialTheme.colorScheme.primary, + ), + ) +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactInfoRows.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactInfoRows.kt new file mode 100644 index 000000000..534f3f937 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactInfoRows.kt @@ -0,0 +1,90 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import com.infomaniak.core.auth.models.user.Card +import com.infomaniak.core.auth.models.user.CardLinkType +import com.infomaniak.core.ui.compose.contactcard.R +import com.infomaniak.core.ui.compose.margin.Margin + +@Composable +internal fun ContactInfoRows(card: Card, modifier: Modifier = Modifier) { + val rows = buildList { + card.company?.takeIf { it.isNotBlank() }?.let { add(stringResource(R.string.company) to it) } + card.phone.takeIf { it.isNotBlank() }?.let { add(stringResource(R.string.phone) to it) } + card.links.orEmpty().firstOrNull { it.type == CardLinkType.Website && it.url.isNotBlank() }?.let { + add(stringResource(R.string.webSite) to it.url) + } + } + Column(modifier = modifier) { + rows.forEachIndexed { index, (label, value) -> + if (index > 0) { + HorizontalDivider( + thickness = 0.5.dp, + color = MaterialTheme.colorScheme.outlineVariant, + ) + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = Margin.Small), + horizontalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = label, + color = MaterialTheme.colorScheme.onSurfaceVariant, + style = MaterialTheme.typography.bodyMedium, + ) + Text( + text = value, + color = MaterialTheme.colorScheme.primary, + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.SemiBold, + ) + } + } + } +} + +@Preview(name = "ContactInfoRows") +@Composable +private fun ContactInfoRowsPreview( + @PreviewParameter(ContactPreviewProvider::class) contactData: PreviewContactData, +) { + MaterialTheme { + Surface { + ContactInfoRows(card = contactData.card) + } + } +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/DefaultContactCardDialog.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/DefaultContactCardDialog.kt new file mode 100644 index 000000000..60c482b54 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/DefaultContactCardDialog.kt @@ -0,0 +1,82 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.infomaniak.core.ui.compose.contactcard.R +import com.infomaniak.core.common.R as RCore + +@Composable +internal fun DefaultContactCardDialog( + titleRes: Int, + descriptionRes: Int, + confirmButtonRes: Int, + onConfirm: () -> Unit, + onDismiss: () -> Unit, + dismissButtonRes: Int? = null, +) { + AlertDialog( + onDismissRequest = onDismiss, + confirmButton = { + TextButton(onClick = onConfirm) { + Text(text = stringResource(confirmButtonRes)) + } + }, + dismissButton = dismissButtonRes?.let { + { + TextButton(onClick = onDismiss) { + Text(text = stringResource(it)) + } + } + }, + title = { Text(text = stringResource(titleRes)) }, + text = { Text(text = stringResource(descriptionRes)) }, + ) +} + +@Composable +internal fun DefaultValidationErrorDialog( + onDismiss: () -> Unit, + onConfirm: () -> Unit, +) { + DefaultContactCardDialog( + titleRes = R.string.alertTitle, + descriptionRes = R.string.alertDescription, + confirmButtonRes = android.R.string.ok, + onConfirm = onConfirm, + onDismiss = onDismiss, + ) +} + +@Composable +internal fun DefaultDeleteConfirmationDialog( + onDismiss: () -> Unit, + onConfirm: () -> Unit, +) { + DefaultContactCardDialog( + titleRes = R.string.deleteAlertTitle, + descriptionRes = R.string.deleteAlertDescription, + confirmButtonRes = R.string.deleteButton, + onConfirm = onConfirm, + onDismiss = onDismiss, + dismissButtonRes = RCore.string.buttonCancel, + ) +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/EditorField.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/EditorField.kt new file mode 100644 index 000000000..064501db5 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/EditorField.kt @@ -0,0 +1,74 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.tooling.preview.Preview + +@Composable +internal fun EditorField( + value: String, + placeholder: String, + onValueChange: (String) -> Unit, + modifier: Modifier = Modifier.fillMaxWidth(), + keyboardType: KeyboardType = KeyboardType.Text, +) { + TextField( + value = value, + onValueChange = onValueChange, + modifier = modifier, + placeholder = { + Text(text = placeholder) + }, + singleLine = true, + keyboardOptions = KeyboardOptions(keyboardType = keyboardType), + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.Transparent, + unfocusedContainerColor = Color.Transparent, + disabledContainerColor = Color.Transparent, + errorContainerColor = Color.Transparent, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + errorIndicatorColor = Color.Transparent, + ), + ) +} + +@Preview(name = "EditorField") +@Composable +private fun EditorFieldPreview() { + MaterialTheme { + Surface { + EditorField( + value = "", + placeholder = "Placeholder", + onValueChange = {}, + ) + } + } +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/EditorTopBar.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/EditorTopBar.kt new file mode 100644 index 000000000..5689bf7d5 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/EditorTopBar.kt @@ -0,0 +1,64 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.infomaniak.core.common.R as RCore + +@Composable +internal fun EditorTopBar( + onCancel: () -> Unit, + onSave: () -> Unit, +) { + ContactCardTopBar( + navigationIcon = { + TextButton(onClick = onCancel) { + Text( + text = stringResource(RCore.string.buttonCancel), + color = MaterialTheme.colorScheme.primary, + ) + } + }, + actions = { + TextButton(onClick = onSave) { + Text( + text = stringResource(RCore.string.buttonSave), + color = MaterialTheme.colorScheme.primary, + ) + } + }, + ) +} + +@Preview(name = "EditorTopBar") +@Composable +private fun EditorTopBarPreview() { + MaterialTheme { + Surface { + EditorTopBar( + onCancel = {}, + onSave = {}, + ) + } + } +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/FieldDivider.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/FieldDivider.kt new file mode 100644 index 000000000..20b31cfc6 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/FieldDivider.kt @@ -0,0 +1,44 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.infomaniak.core.ui.compose.margin.Margin + +@Composable +internal fun FieldDivider() { + HorizontalDivider( + modifier = Modifier.padding(horizontal = Margin.Medium), + color = MaterialTheme.colorScheme.outlineVariant, + ) +} + +@Preview(name = "FieldDivider") +@Composable +private fun FieldDividerPreview() { + MaterialTheme { + Surface { + FieldDivider() + } + } +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/LoadingContent.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/LoadingContent.kt new file mode 100644 index 000000000..2a8f7d1ad --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/LoadingContent.kt @@ -0,0 +1,44 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview + +@Composable +internal fun LoadingContent() { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + CircularProgressIndicator() + } +} + +@Preview(name = "LoadingContent") +@Composable +private fun LoadingContentPreview() { + MaterialTheme { + Surface { + LoadingContent() + } + } +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewData.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewData.kt new file mode 100644 index 000000000..bfac309b8 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewData.kt @@ -0,0 +1,65 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import com.infomaniak.core.auth.models.user.Card +import com.infomaniak.core.auth.models.user.CardLink +import com.infomaniak.core.auth.models.user.CardLinkType +import com.infomaniak.core.auth.models.user.User +import com.infomaniak.core.auth.models.user.preferences.OrganizationPreference +import com.infomaniak.core.auth.models.user.preferences.Preferences + +public data class PreviewContactData( + val user: User, + val card: Card, +) + +public class ContactPreviewProvider : PreviewParameterProvider { + override val values: Sequence = sequenceOf( + PreviewContactData( + user = User( + id = 42, + displayName = "Alice Doe", + firstname = "Alice", + lastname = "Doe", + email = "alice.doe@example.com", + avatar = "https://example.com/avatar.png", + card = null, + login = "alice.doe", + isStaff = false, + preferences = Preferences( + security = null, + organizationPreference = OrganizationPreference(currentOrganizationId = 0), + ), + ), + card = Card( + firstName = "Alice", + lastName = "Doe", + email = "alice.doe@example.com", + phone = "+41 79 123 45 67", + company = "Infomaniak", + avatarUrl = "https://example.com/avatar.png", + links = listOf( + CardLink(CardLinkType.LinkedIn, "https://linkedin.com/in/alicedoe"), + CardLink(CardLinkType.Website, "https://example.com"), + CardLink(CardLinkType.Other, "https://blog.example.com"), + ), + ), + ) + ) +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewTopBar.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewTopBar.kt new file mode 100644 index 000000000..f04b24fd4 --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewTopBar.kt @@ -0,0 +1,70 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.infomaniak.core.ui.compose.contactcard.R +import com.infomaniak.core.common.R as RCore + +@Composable +internal fun PreviewTopBar( + onClose: () -> Unit, + onMore: () -> Unit, +) { + ContactCardTopBar( + navigationIcon = { + IconButton(onClick = onClose) { + Icon( + imageVector = Icons.Filled.Close, + contentDescription = stringResource(RCore.string.buttonClose), + tint = MaterialTheme.colorScheme.primary, + ) + } + }, + actions = { + IconButton(onClick = onMore) { + Icon( + imageVector = Icons.Filled.MoreVert, + contentDescription = stringResource(R.string.buttonMore), + tint = MaterialTheme.colorScheme.primary, + ) + } + }, + ) +} + +@Preview(name = "PreviewTopBar") +@Composable +private fun PreviewTopBarPreview() { + MaterialTheme { + Surface { + PreviewTopBar( + onClose = {}, + onMore = {}, + ) + } + } +} diff --git a/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/SectionCard.kt b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/SectionCard.kt new file mode 100644 index 000000000..46fb5322a --- /dev/null +++ b/Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/SectionCard.kt @@ -0,0 +1,69 @@ +/* + * Infomaniak Core - Android + * Copyright (C) 2026 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.core.ui.compose.contactcard.component + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.infomaniak.core.ui.compose.margin.Margin + +@Composable +internal fun SectionCard( + title: String, + content: @Composable () -> Unit, +) { + Column(modifier = Modifier.fillMaxWidth()) { + Text( + text = title, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding( + start = Margin.Medium + Margin.Mini, + end = Margin.Medium, + bottom = Margin.Mini, + ), + ) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = Margin.Medium), + color = MaterialTheme.colorScheme.surface, + shape = RoundedCornerShape(CardCornerRadius), + ) { + Column(modifier = Modifier.fillMaxWidth()) { content() } + } + } +} + +@Preview(name = "SectionCard") +@Composable +private fun SectionCardPreview() { + MaterialTheme { + Surface { + SectionCard(title = "Section Title") { + Text("Content") + } + } + } +}