From 44c1737f8ec312ef0dec0bf8a1bb7802596d3a45 Mon Sep 17 00:00:00 2001 From: AbdallahMehiz Date: Sun, 21 Jul 2024 02:39:49 +0100 Subject: [PATCH] feat: login screen VEEEEEEEEEERY basic it doesn't even have persistency this'll be added in a few commits I'll be adding localization first --- .../mehiz/abdallah/progres/api/ProgresApi.kt | 7 - composeApp/build.gradle.kts | 12 +- .../androidMain/kotlin/Platform.android.kt | 7 - .../drawable/progres_dark.webp | Bin 0 -> 86004 bytes composeApp/src/commonMain/kotlin/App.kt | 35 +-- composeApp/src/commonMain/kotlin/Greeting.kt | 7 - composeApp/src/commonMain/kotlin/Platform.kt | 5 - .../di/{initKodein.kt => InitKodein.kt} | 4 +- .../kotlin/presentation/WheelPicker.kt | 249 +++++++++++++++ .../commonMain/kotlin/ui/home/HomeScreen.kt | 18 ++ .../kotlin/ui/onboarding/LoginScreen.kt | 285 ++++++++++++++++++ .../src/iosMain/kotlin/MainViewController.kt | 1 - .../abdallah/progres/data/ProgresDatabase.kt | 4 - {api => domain/api}/.gitignore | 0 {api => domain/api}/build.gradle.kts | 1 + .../abdallah/progres/api/ApiModule.android.kt | 7 + .../mehiz/abdallah/progres/api/ApiModule.kt | 32 ++ .../mehiz/abdallah/progres/api/Endpoints.kt | 15 + .../mehiz/abdallah/progres/api/ProgresApi.kt | 19 ++ .../mehiz/abdallah/progres/api/Requests.kt | 72 +++++ .../abdallah/progres/api/dto/UserAuth.kt | 18 ++ .../abdallah/progres/api/ApiModule.native.kt | 5 + domain/build.gradle.kts | 9 + {data => domain/data}/.gitignore | 0 {data => domain/data}/build.gradle.kts | 0 .../abdallah/progres/domain/AccountUseCase.kt | 11 + .../abdallah/progres/domain/DomainModule.kt | 12 + gradle/libs.versions.toml | 7 + settings.gradle.kts | 4 +- 29 files changed, 780 insertions(+), 66 deletions(-) delete mode 100755 api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ProgresApi.kt delete mode 100755 composeApp/src/androidMain/kotlin/Platform.android.kt create mode 100755 composeApp/src/commonMain/composeResources/drawable/progres_dark.webp delete mode 100755 composeApp/src/commonMain/kotlin/Greeting.kt delete mode 100755 composeApp/src/commonMain/kotlin/Platform.kt rename composeApp/src/commonMain/kotlin/di/{initKodein.kt => InitKodein.kt} (54%) create mode 100755 composeApp/src/commonMain/kotlin/presentation/WheelPicker.kt create mode 100755 composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt create mode 100755 composeApp/src/commonMain/kotlin/ui/onboarding/LoginScreen.kt delete mode 100755 data/src/commonMain/kotlin/mehiz/abdallah/progres/data/ProgresDatabase.kt rename {api => domain/api}/.gitignore (100%) rename {api => domain/api}/build.gradle.kts (95%) create mode 100755 domain/api/src/androidMain/kotlin/mehiz/abdallah/progres/api/ApiModule.android.kt create mode 100755 domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ApiModule.kt create mode 100755 domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/Endpoints.kt create mode 100755 domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ProgresApi.kt create mode 100755 domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/Requests.kt create mode 100755 domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/dto/UserAuth.kt create mode 100755 domain/api/src/nativeMain/kotlin/mehiz/abdallah/progres/api/ApiModule.native.kt rename {data => domain/data}/.gitignore (100%) rename {data => domain/data}/build.gradle.kts (100%) create mode 100755 domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/AccountUseCase.kt create mode 100755 domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/DomainModule.kt diff --git a/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ProgresApi.kt b/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ProgresApi.kt deleted file mode 100755 index 3f9b8c9..0000000 --- a/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ProgresApi.kt +++ /dev/null @@ -1,7 +0,0 @@ -package mehiz.abdallah.progres.api - -import io.ktor.client.HttpClient - -class ProgresApi( - private val client: HttpClient -) diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index f84b70c..c12e4a8 100755 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -28,21 +28,27 @@ kotlin { } sourceSets { - androidMain.dependencies { implementation(compose.preview) implementation(libs.androidx.activity.compose) } commonMain.dependencies { + implementation(project(":domain")) + + implementation(compose.ui) implementation(compose.runtime) + implementation(compose.material3) implementation(compose.foundation) - implementation(compose.material) - implementation(compose.ui) implementation(compose.components.resources) + implementation(compose.materialIconsExtended) implementation(compose.components.uiToolingPreview) + implementation(libs.immutable.collections) + implementation(libs.kotlinx.datetime) + api(libs.bundles.kodein) api(libs.bundles.datastore) + implementation(libs.bundles.voyager) } } } diff --git a/composeApp/src/androidMain/kotlin/Platform.android.kt b/composeApp/src/androidMain/kotlin/Platform.android.kt deleted file mode 100755 index 0a87ecf..0000000 --- a/composeApp/src/androidMain/kotlin/Platform.android.kt +++ /dev/null @@ -1,7 +0,0 @@ -import android.os.Build - -class AndroidPlatform : Platform { - override val name: String = "Android ${Build.VERSION.SDK_INT}" -} - -actual fun getPlatform(): Platform = AndroidPlatform() diff --git a/composeApp/src/commonMain/composeResources/drawable/progres_dark.webp b/composeApp/src/commonMain/composeResources/drawable/progres_dark.webp new file mode 100755 index 0000000000000000000000000000000000000000..19f9f17e846fa241320af0d69e760955d4fd81bc GIT binary patch literal 86004 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 o0000000000000000000*SV=|>0000@O#mtY000O80000006_eU#{d8T literal 0 HcmV?d00001 diff --git a/composeApp/src/commonMain/kotlin/App.kt b/composeApp/src/commonMain/kotlin/App.kt index da08ad5..5249e10 100755 --- a/composeApp/src/commonMain/kotlin/App.kt +++ b/composeApp/src/commonMain/kotlin/App.kt @@ -1,38 +1,15 @@ -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material.Button -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import org.jetbrains.compose.resources.painterResource +import cafe.adriel.voyager.navigator.Navigator import org.jetbrains.compose.ui.tooling.preview.Preview -import progres.composeapp.generated.resources.Res -import progres.composeapp.generated.resources.compose_multiplatform +import ui.onboarding.LoginScreen @Composable @Preview fun App() { MaterialTheme { - var showContent by remember { mutableStateOf(false) } - Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Button(onClick = { showContent = !showContent }) { - Text("Click me!") - } - AnimatedVisibility(showContent) { - val greeting = remember { Greeting().greet() } - Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Image(painterResource(Res.drawable.compose_multiplatform), null) - Text("Compose: $greeting") - } - } - } + Navigator( + screen = LoginScreen + ) } } diff --git a/composeApp/src/commonMain/kotlin/Greeting.kt b/composeApp/src/commonMain/kotlin/Greeting.kt deleted file mode 100755 index 5f8462d..0000000 --- a/composeApp/src/commonMain/kotlin/Greeting.kt +++ /dev/null @@ -1,7 +0,0 @@ -class Greeting { - private val platform = getPlatform() - - fun greet(): String { - return "Hello, ${platform.name}!" - } -} diff --git a/composeApp/src/commonMain/kotlin/Platform.kt b/composeApp/src/commonMain/kotlin/Platform.kt deleted file mode 100755 index 6992e78..0000000 --- a/composeApp/src/commonMain/kotlin/Platform.kt +++ /dev/null @@ -1,5 +0,0 @@ -interface Platform { - val name: String -} - -expect fun getPlatform(): Platform diff --git a/composeApp/src/commonMain/kotlin/di/initKodein.kt b/composeApp/src/commonMain/kotlin/di/InitKodein.kt similarity index 54% rename from composeApp/src/commonMain/kotlin/di/initKodein.kt rename to composeApp/src/commonMain/kotlin/di/InitKodein.kt index e07327c..44376c5 100755 --- a/composeApp/src/commonMain/kotlin/di/initKodein.kt +++ b/composeApp/src/commonMain/kotlin/di/InitKodein.kt @@ -1,5 +1,6 @@ package di +import mehiz.abdallah.progres.domain.DomainModule import org.kodein.di.DI fun initKodein( @@ -7,7 +8,8 @@ fun initKodein( ): DI { return DI.from( listOf( - PreferencesModule(datastorePath) + PreferencesModule(datastorePath), + DomainModule ) ) } diff --git a/composeApp/src/commonMain/kotlin/presentation/WheelPicker.kt b/composeApp/src/commonMain/kotlin/presentation/WheelPicker.kt new file mode 100755 index 0000000..eab6192 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/presentation/WheelPicker.kt @@ -0,0 +1,249 @@ +package presentation + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyItemScope +import androidx.compose.foundation.lazy.LazyListItemInfo +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.hapticfeedback.HapticFeedbackType +import androidx.compose.ui.platform.LocalHapticFeedback +import androidx.compose.ui.text.TextRange +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.DpSize +import androidx.compose.ui.unit.dp +import kotlinx.collections.immutable.ImmutableList +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map +import kotlin.math.absoluteValue + +@Composable +fun WheelNumberPicker( + items: ImmutableList, + modifier: Modifier = Modifier, + startIndex: Int = 0, + size: DpSize = DpSize(128.dp, 128.dp), + onSelectionChanged: (index: Int) -> Unit = {}, + backgroundContent: (@Composable (size: DpSize) -> Unit)? = { + WheelPickerDefaults.Background(size = it) + }, +) { + WheelPicker( + modifier = modifier, + startIndex = startIndex, + items = items, + size = size, + onSelectionChanged = onSelectionChanged, + manualInputType = KeyboardType.Number, + backgroundContent = backgroundContent, + ) { + WheelPickerDefaults.Item(text = "$it") + } +} + +@Composable +fun WheelTextPicker( + items: ImmutableList, + modifier: Modifier = Modifier, + startIndex: Int = 0, + size: DpSize = DpSize(128.dp, 128.dp), + onSelectionChanged: (index: Int) -> Unit = {}, + backgroundContent: (@Composable (size: DpSize) -> Unit)? = { + WheelPickerDefaults.Background(size = it) + }, +) { + WheelPicker( + modifier = modifier, + startIndex = startIndex, + items = items, + size = size, + onSelectionChanged = onSelectionChanged, + backgroundContent = backgroundContent, + ) { + WheelPickerDefaults.Item(text = it) + } +} + +@OptIn(ExperimentalFoundationApi::class) +@Composable +private fun WheelPicker( + items: ImmutableList, + modifier: Modifier = Modifier, + startIndex: Int = 0, + size: DpSize = DpSize(128.dp, 128.dp), + onSelectionChanged: (index: Int) -> Unit = {}, + manualInputType: KeyboardType? = null, + backgroundContent: (@Composable (size: DpSize) -> Unit)? = { + WheelPickerDefaults.Background(size = it) + }, + itemContent: @Composable LazyItemScope.(item: T) -> Unit, +) { + val haptic = LocalHapticFeedback.current + val lazyListState = rememberLazyListState(startIndex) + + var internalIndex by remember { mutableIntStateOf(startIndex) } + val internalOnSelectionChanged: (Int) -> Unit = { + internalIndex = it + onSelectionChanged(it) + } + + LaunchedEffect(lazyListState, onSelectionChanged) { + snapshotFlow { lazyListState.firstVisibleItemScrollOffset } + .map { calculateSnappedItemIndex(lazyListState) } + .distinctUntilChanged() + .collectLatest { + haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) + internalOnSelectionChanged(it) + } + } + + Box( + modifier = modifier + .height(size.height) + .width(size.width), + contentAlignment = Alignment.Center, + ) { + backgroundContent?.invoke(size) + + var showManualInput by remember { mutableStateOf(false) } + if (showManualInput) { + var value by remember { + val currentString = items[internalIndex].toString() + mutableStateOf(TextFieldValue(text = currentString, selection = TextRange(currentString.length))) + } + + val scope = rememberCoroutineScope() + BasicTextField( + modifier = Modifier + .align(Alignment.Center), + value = value, + onValueChange = { value = it }, + singleLine = true, + keyboardOptions = KeyboardOptions( + keyboardType = manualInputType!!, + imeAction = ImeAction.Done, + ), + textStyle = MaterialTheme.typography.titleMedium + + TextStyle( + color = MaterialTheme.colorScheme.onSurface, + textAlign = TextAlign.Center, + ), + cursorBrush = SolidColor(MaterialTheme.colorScheme.primary), + ) + } else { + LazyColumn( + modifier = Modifier, + state = lazyListState, + contentPadding = PaddingValues(vertical = size.height / RowCount * ((RowCount - 1) / 2)), + flingBehavior = rememberSnapFlingBehavior(lazyListState = lazyListState), + ) { + itemsIndexed(items) { index, item -> + Box( + modifier = Modifier + .height(size.height / RowCount) + .width(size.width) + .alpha( + calculateAnimatedAlpha( + lazyListState = lazyListState, + index = index, + ), + ), + contentAlignment = Alignment.Center, + ) { + itemContent(item) + } + } + } + } + } +} + +private fun LazyListState.snapOffsetForItem(itemInfo: LazyListItemInfo): Int { + val startScrollOffset = 0 + val endScrollOffset = layoutInfo.let { it.viewportEndOffset - it.afterContentPadding } + return startScrollOffset + (endScrollOffset - startScrollOffset - itemInfo.size) / 2 +} + +private fun LazyListState.distanceToSnapForIndex(index: Int): Int { + val itemInfo = layoutInfo.visibleItemsInfo.firstOrNull { it.index == index } + if (itemInfo != null) { + return itemInfo.offset - snapOffsetForItem(itemInfo) + } + return 0 +} + +private fun calculateAnimatedAlpha( + lazyListState: LazyListState, + index: Int, +): Float { + val distanceToIndexSnap = lazyListState.distanceToSnapForIndex(index).absoluteValue + val viewPortHeight = lazyListState.layoutInfo.viewportSize.height.toFloat() + val singleViewPortHeight = viewPortHeight / RowCount + return if (distanceToIndexSnap in 0..singleViewPortHeight.toInt()) { + 1.2f - (distanceToIndexSnap / singleViewPortHeight) + } else { + 0.2f + } +} + +private fun calculateSnappedItemIndex(lazyListState: LazyListState): Int { + return lazyListState.layoutInfo.visibleItemsInfo + .maxBy { calculateAnimatedAlpha(lazyListState, it.index) } + .index +} + +object WheelPickerDefaults { + @Composable + fun Background(size: DpSize) { + androidx.compose.material3.Surface( + modifier = Modifier + .size(size.width, size.height / RowCount), + shape = RoundedCornerShape(24.dp), + color = MaterialTheme.colorScheme.primary.copy(alpha = 0.2f), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary), + content = {}, + ) + } + + @Composable + fun Item(text: String) { + Text( + text = text, + style = MaterialTheme.typography.titleMedium, + maxLines = 1, + ) + } +} + +private const val RowCount = 3 diff --git a/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt new file mode 100755 index 0000000..ffeaa2f --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt @@ -0,0 +1,18 @@ +package ui.home + +import androidx.compose.foundation.layout.Box +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import cafe.adriel.voyager.core.screen.Screen + +object HomeScreen: Screen { + @Composable + override fun Content() { + Box( + contentAlignment = Alignment.Center + ) { + Text("Home Screen") + } + } +} diff --git a/composeApp/src/commonMain/kotlin/ui/onboarding/LoginScreen.kt b/composeApp/src/commonMain/kotlin/ui/onboarding/LoginScreen.kt new file mode 100755 index 0000000..01d5a61 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ui/onboarding/LoginScreen.kt @@ -0,0 +1,285 @@ +package ui.onboarding + +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.DateRange +import androidx.compose.material.icons.outlined.Key +import androidx.compose.material.icons.outlined.Person +import androidx.compose.material.icons.outlined.Translate +import androidx.compose.material.icons.outlined.Visibility +import androidx.compose.material.icons.outlined.VisibilityOff +import androidx.compose.material3.AlertDialogDefaults +import androidx.compose.material3.BasicAlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +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.text.input.KeyboardType +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.unit.dp +import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.currentOrThrow +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO +import kotlinx.coroutines.launch +import kotlinx.datetime.Clock +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime +import mehiz.abdallah.progres.domain.AccountUseCase +import org.jetbrains.compose.resources.painterResource +import org.kodein.di.compose.localDI +import org.kodein.di.instance +import presentation.WheelNumberPicker +import progres.composeapp.generated.resources.Res +import progres.composeapp.generated.resources.progres_dark +import ui.home.HomeScreen + +object LoginScreen : Screen { + + @Composable + override fun Content() { + val accountUseCase by localDI().instance() + + LoginScreen( + onLoginPressed = { id, password -> accountUseCase.login(id, password) }, + ) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun LoginScreen( + onLoginPressed: suspend (String, String) -> Unit, +) { + Scaffold( + modifier = Modifier.fillMaxSize(), + topBar = { + TopAppBar( + title = {}, + actions = { + var showLanguageDropDown by remember { mutableStateOf(false) } + IconButton( + onClick = { showLanguageDropDown = true }, + ) { + Icon( + Icons.Outlined.Translate, + "change language", + ) + } + DropdownMenu(expanded = showLanguageDropDown, onDismissRequest = { showLanguageDropDown = false }) { + Text("Arabic") + Text("English") + Text("French") + } + }, + ) + }, + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxWidth() + .padding(paddingValues) + .padding(horizontal = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + Image( + painter = painterResource(Res.drawable.progres_dark), + null, + ) + var id by remember { mutableStateOf("") } + var year by rememberSaveable { + mutableStateOf(Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).year.toString()) + } + val yearsRange = 1970..year.toInt() + var showYearPickerAlert by remember { mutableStateOf(false) } + if (showYearPickerAlert) { + val onDismissRequest: () -> Unit = { showYearPickerAlert = false } + YearPickerAlert( + value = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).year, + onValueChanged = { + year = it.toString() + onDismissRequest() + }, + range = yearsRange, + onDismissRequest = onDismissRequest, + ) + } + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + OutlinedTextField( + value = year, + onValueChange = { year = it }, + label = { Text("year") }, + leadingIcon = { + IconButton( + onClick = { showYearPickerAlert = true }, + ) { + Icon( + Icons.Outlined.DateRange, + "open date picker", + ) + } + }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + singleLine = true, + modifier = Modifier.weight(2f), + ) + OutlinedTextField( + value = id, + onValueChange = { id = it }, + label = { Text("ID Number") }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + singleLine = true, + leadingIcon = { Icon(Icons.Outlined.Person, null) }, + modifier = Modifier.weight(3f), + ) + } + var password by rememberSaveable { mutableStateOf("") } + var isPasswordVisible by remember { mutableStateOf(false) } + OutlinedTextField( + value = password, + onValueChange = { password = it }, + label = { Text("Password") }, + leadingIcon = { Icon(Icons.Outlined.Key, null) }, + trailingIcon = { + IconButton( + onClick = { + isPasswordVisible = !isPasswordVisible + }, + ) { + Icon( + if (isPasswordVisible) Icons.Outlined.Visibility else Icons.Outlined.VisibilityOff, + "toggle password visibility", + ) + } + }, + visualTransformation = if (isPasswordVisible) VisualTransformation.None else PasswordVisualTransformation(), + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), + singleLine = true, + modifier = Modifier.fillMaxWidth(), + ) + var isLoadingIndicatorShown by remember { mutableStateOf(false) } + val navigator = LocalNavigator.currentOrThrow + val scope = rememberCoroutineScope() + Button( + onClick = { + isLoadingIndicatorShown = true + scope.launch(Dispatchers.IO) { + try { + onLoginPressed(year + id, password) + navigator.replaceAll(HomeScreen) + } catch (e: Exception) { + isLoadingIndicatorShown = false + } + } + }, + modifier = Modifier.fillMaxWidth(), + ) { + Row( + modifier = Modifier.animateContentSize(), + verticalAlignment = Alignment.CenterVertically, + ) { + if (isLoadingIndicatorShown) { + CircularProgressIndicator( + modifier = Modifier.size(24.dp), + color = MaterialTheme.colorScheme.onPrimary, + strokeWidth = 2.dp, + ) + } else { + Text("Login") + } + } + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun YearPickerAlert( + value: Int, + onValueChanged: (Int) -> Unit, + range: IntRange, + onDismissRequest: () -> Unit, +) { + var index by remember { + mutableStateOf( + runCatching { range.indexOf(value) }.getOrNull() ?: range.indexOf(range.last), + ) + } + BasicAlertDialog( + onDismissRequest = onDismissRequest, + ) { + Surface( + modifier = Modifier.fillMaxWidth(), + color = MaterialTheme.colorScheme.surface, + shape = AlertDialogDefaults.shape, + tonalElevation = AlertDialogDefaults.TonalElevation, + ) { + Column( + modifier = Modifier + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + Text( + "Select year", + style = MaterialTheme.typography.headlineSmall, + modifier = Modifier.padding(horizontal = 16.dp), + ) + WheelNumberPicker( + startIndex = index, + items = range.toImmutableList(), + onSelectionChanged = { index = it }, + modifier = Modifier.align(Alignment.CenterHorizontally), + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + ) { + TextButton( + onClick = onDismissRequest, + ) { + Text("Cancel") + } + TextButton( + onClick = { onValueChanged(range.elementAt(index)) }, + ) { + Text("Ok") + } + } + } + } + } +} diff --git a/composeApp/src/iosMain/kotlin/MainViewController.kt b/composeApp/src/iosMain/kotlin/MainViewController.kt index b79211d..0b0e963 100755 --- a/composeApp/src/iosMain/kotlin/MainViewController.kt +++ b/composeApp/src/iosMain/kotlin/MainViewController.kt @@ -6,7 +6,6 @@ import platform.Foundation.NSDocumentDirectory import platform.Foundation.NSFileManager import platform.Foundation.NSUserDomainMask import platform.UIKit.UIViewController -import preferences.DataStoreFileName fun MainViewController(): UIViewController { val di = initKodein(preferencesStorePath()) diff --git a/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/ProgresDatabase.kt b/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/ProgresDatabase.kt deleted file mode 100755 index 704b081..0000000 --- a/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/ProgresDatabase.kt +++ /dev/null @@ -1,4 +0,0 @@ -package mehiz.abdallah.progres.data - -class ProgresDatabase { -} diff --git a/api/.gitignore b/domain/api/.gitignore similarity index 100% rename from api/.gitignore rename to domain/api/.gitignore diff --git a/api/build.gradle.kts b/domain/api/build.gradle.kts similarity index 95% rename from api/build.gradle.kts rename to domain/api/build.gradle.kts index 85f46df..7a4e33b 100755 --- a/api/build.gradle.kts +++ b/domain/api/build.gradle.kts @@ -24,6 +24,7 @@ kotlin { sourceSets { commonMain.dependencies { implementation(libs.bundles.ktor) + implementation(libs.kodein.core) } androidMain.dependencies { implementation(libs.ktor.client.okhttp) diff --git a/domain/api/src/androidMain/kotlin/mehiz/abdallah/progres/api/ApiModule.android.kt b/domain/api/src/androidMain/kotlin/mehiz/abdallah/progres/api/ApiModule.android.kt new file mode 100755 index 0000000..30b0e4f --- /dev/null +++ b/domain/api/src/androidMain/kotlin/mehiz/abdallah/progres/api/ApiModule.android.kt @@ -0,0 +1,7 @@ +package mehiz.abdallah.progres.api + +import io.ktor.client.engine.HttpClientEngine +import io.ktor.client.engine.okhttp.OkHttpConfig +import io.ktor.client.engine.okhttp.OkHttpEngine + +actual val engine: HttpClientEngine = OkHttpEngine(OkHttpConfig()) diff --git a/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ApiModule.kt b/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ApiModule.kt new file mode 100755 index 0000000..c5f0ddc --- /dev/null +++ b/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ApiModule.kt @@ -0,0 +1,32 @@ +package mehiz.abdallah.progres.api + +import io.ktor.client.HttpClient +import io.ktor.client.engine.HttpClientEngine +import io.ktor.client.plugins.contentnegotiation.ContentNegotiation +import io.ktor.client.plugins.logging.LogLevel +import io.ktor.client.plugins.logging.Logging +import io.ktor.serialization.kotlinx.json.json +import kotlinx.serialization.json.Json +import org.kodein.di.DI.Module +import org.kodein.di.bindSingleton + +expect val engine: HttpClientEngine + +val ApiModule = Module("ApiModule") { + bindSingleton { + ProgresApi( + HttpClient(engine) { + install(Logging) { + level = LogLevel.INFO + } + install(ContentNegotiation) { + json( + Json { + ignoreUnknownKeys = true + }, + ) + } + }, + ) + } +} diff --git a/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/Endpoints.kt b/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/Endpoints.kt new file mode 100755 index 0000000..3ff6b41 --- /dev/null +++ b/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/Endpoints.kt @@ -0,0 +1,15 @@ +package mehiz.abdallah.progres.api + +internal const val BASE_URL = "https://progres.mesrs.dz" + +enum class Endpoints(private val endpoint: String) { + Login("/api/authentication/v1/") + ; + + // Wanted to use String.format() but that is only for jvm :pain: + fun buildUrl(vararg params: String): String { + var url = "$BASE_URL$endpoint" + params.forEach { url = url.replaceFirst("%s", it) } + return url + } +} diff --git a/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ProgresApi.kt b/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ProgresApi.kt new file mode 100755 index 0000000..4d20750 --- /dev/null +++ b/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/ProgresApi.kt @@ -0,0 +1,19 @@ +package mehiz.abdallah.progres.api + +import io.ktor.client.HttpClient +import io.ktor.client.call.body +import io.ktor.client.request.request +import mehiz.abdallah.progres.api.dto.UserAuth + +class ProgresApi( + private val client: HttpClient, +) { + suspend fun login(id: String, password: String): UserAuth { + return client.request( + POST( + Endpoints.Login.buildUrl(), + body = """{"username": "$id", "password": "$password"}""", + ), + ).body() + } +} diff --git a/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/Requests.kt b/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/Requests.kt new file mode 100755 index 0000000..fbce54e --- /dev/null +++ b/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/Requests.kt @@ -0,0 +1,72 @@ +package mehiz.abdallah.progres.api + +import io.ktor.client.request.HttpRequestBuilder +import io.ktor.client.request.setBody +import io.ktor.http.ContentType +import io.ktor.http.Headers +import io.ktor.http.HttpMethod +import io.ktor.http.contentType +import io.ktor.http.set +import io.ktor.http.takeFrom + +@Suppress("FunctionNaming") +internal fun GET( + url: String, + headers: Headers = Headers.Empty, +): HttpRequestBuilder { + return HttpRequestBuilder() + .apply { + this.method = HttpMethod.Get + this.url.set { takeFrom(url) } + this.headers.appendAll(headers) + } +} + +@Suppress("FunctionNaming") +internal fun POST( + url: String, + body: String, + headers: Headers = Headers.Empty, + contentType: ContentType = ContentType.Application.Json, +): HttpRequestBuilder { + return HttpRequestBuilder() + .apply { + this.method = HttpMethod.Post + this.url.set { takeFrom(url) } + this.headers.appendAll(headers) + this.setBody(body) + contentType(contentType) + } +} + +@Suppress("FunctionNaming") +internal fun PUT( + url: String, + body: String, + headers: Headers = Headers.Empty, + contentType: ContentType = ContentType.Application.Json, +): HttpRequestBuilder { + return HttpRequestBuilder().apply { + this.method = HttpMethod.Put + this.url.set { takeFrom(url) } + this.headers.appendAll(headers) + this.setBody(body) + contentType(contentType) + } +} + +@Suppress("FunctionNaming") +internal fun DELETE( + url: String, + body: String, + headers: Headers = Headers.Empty, + contentType: ContentType = ContentType.Application.Json, +): HttpRequestBuilder { + return HttpRequestBuilder().apply { + this.method = HttpMethod.Delete + this.url.set { takeFrom(url) } + this.headers.appendAll(headers) + this.setBody(body) + contentType(contentType) + } +} diff --git a/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/dto/UserAuth.kt b/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/dto/UserAuth.kt new file mode 100755 index 0000000..37f8585 --- /dev/null +++ b/domain/api/src/commonMain/kotlin/mehiz/abdallah/progres/api/dto/UserAuth.kt @@ -0,0 +1,18 @@ +package mehiz.abdallah.progres.api.dto + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class UserAuth( + var expirationDate: String, + var token: String, + var userId: Long, + var uuid: String, + @SerialName("idIndividu") + var individualId: Long = 0, + @SerialName("etablissementId") + var establishmentId: Int, + var userName: String, +) + diff --git a/domain/api/src/nativeMain/kotlin/mehiz/abdallah/progres/api/ApiModule.native.kt b/domain/api/src/nativeMain/kotlin/mehiz/abdallah/progres/api/ApiModule.native.kt new file mode 100755 index 0000000..e6ce4d7 --- /dev/null +++ b/domain/api/src/nativeMain/kotlin/mehiz/abdallah/progres/api/ApiModule.native.kt @@ -0,0 +1,5 @@ +package mehiz.abdallah.progres.api + +import io.ktor.client.engine.HttpClientEngine + +actual val engine: HttpClientEngine = TODO() diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index ff255ec..9c92caf 100755 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -19,6 +19,15 @@ kotlin { iosX64() iosArm64() iosSimulatorArm64() + + sourceSets { + commonMain.dependencies { + implementation(project(":domain:api")) + implementation(project(":domain:data")) + + api(libs.kodein.core) + } + } } java { diff --git a/data/.gitignore b/domain/data/.gitignore similarity index 100% rename from data/.gitignore rename to domain/data/.gitignore diff --git a/data/build.gradle.kts b/domain/data/build.gradle.kts similarity index 100% rename from data/build.gradle.kts rename to domain/data/build.gradle.kts diff --git a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/AccountUseCase.kt b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/AccountUseCase.kt new file mode 100755 index 0000000..dd4f3b0 --- /dev/null +++ b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/AccountUseCase.kt @@ -0,0 +1,11 @@ +package mehiz.abdallah.progres.domain + +import mehiz.abdallah.progres.api.ProgresApi + +class AccountUseCase( + private val api: ProgresApi +) { + suspend fun login(id: String, password: String) { + api.login(id, password) + } +} diff --git a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/DomainModule.kt b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/DomainModule.kt new file mode 100755 index 0000000..eab80eb --- /dev/null +++ b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/DomainModule.kt @@ -0,0 +1,12 @@ +package mehiz.abdallah.progres.domain + +import mehiz.abdallah.progres.api.ApiModule +import org.kodein.di.DI.Module +import org.kodein.di.bindSingleton +import org.kodein.di.instance + +val DomainModule: Module = Module("DomainModule") { + import(ApiModule) + + bindSingleton { AccountUseCase(instance()) } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a8319ab..1bbedbb 100755 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,6 +18,7 @@ jetbrainsKotlinJvm = "1.9.0" ktor = "2.3.12" datastore = "1.1.1" kodein = "7.22.0" +voyager = "1.1.0-beta02" [libraries] kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } @@ -30,6 +31,8 @@ androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version androidx-material = { group = "com.google.android.material", name = "material", version.ref = "androidx-material" } androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" } androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" } +immutable-collections = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version = "0.3.7" } +kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version = "0.6.0" } ktor-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } ktor-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" } @@ -44,10 +47,14 @@ datastore-preferences = { module = "androidx.datastore:datastore-preferences", v kodein-core = { module = "org.kodein.di:kodein-di", version.ref = "kodein" } kodein-compose = { module = "org.kodein.di:kodein-di-framework-compose", version.ref = "kodein" } +voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" } +voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" } + [bundles] ktor = ["ktor-core", "ktor-logging", "ktor-content-negotiation", "ktor-serialization-kotlinx-json"] kodein = ["kodein-core", "kodein-compose"] datastore = ["datastore-core", "datastore-preferences"] +voyager = ["voyager-navigator", "voyager-transitions"] [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } diff --git a/settings.gradle.kts b/settings.gradle.kts index a682cd8..e9e355d 100755 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -30,5 +30,5 @@ dependencyResolutionManagement { include(":composeApp") include(":domain") -include(":data") -include(":api") +include(":domain:data") +include(":domain:api")