diff --git a/app/src/main/java/com/ouday/cryptowalletsample/MainActivity.kt b/app/src/main/java/com/ouday/cryptowalletsample/MainActivity.kt index d062038..a22f2f9 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/MainActivity.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/MainActivity.kt @@ -11,7 +11,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier import com.ouday.cryptowalletsample.home.ui.view.MainScreen -import com.ouday.cryptowalletsample.ui.theme.CryptoWalletSampleTheme +import com.ouday.cryptowalletsample.ui.theme.AppTheme import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -19,7 +19,7 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - CryptoWalletSampleTheme { + AppTheme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background diff --git a/app/src/main/java/com/ouday/cryptowalletsample/bills/ui/view/BillsScreen.kt b/app/src/main/java/com/ouday/cryptowalletsample/bills/ui/view/BillsScreen.kt index 25da161..beba846 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/bills/ui/view/BillsScreen.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/bills/ui/view/BillsScreen.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -33,12 +34,10 @@ import com.ouday.cryptowalletsample.bills.ui.viewmodel.BillViewModel import com.ouday.cryptowalletsample.common.FlowState import com.ouday.cryptowalletsample.common.HandleFlowState import com.ouday.cryptowalletsample.home.components.BillOptionItem -import com.ouday.cryptowalletsample.ui.theme.Colors import com.ouday.cryptowalletsample.ui.theme.MaterialCornerRadius import com.ouday.cryptowalletsample.ui.theme.Size import com.ouday.cryptowalletsample.ui.theme.Space import com.ouday.cryptowalletsample.ui.theme.Typography -import com.ouday.cryptowalletsample.ui.theme.success @Composable fun BillsScreen(modifier: Modifier = Modifier, viewModel: BillViewModel = hiltViewModel()) { @@ -88,7 +87,7 @@ fun BillDetails(history: History, modifier: Modifier = Modifier) { .fillMaxWidth() .padding(horizontal = Space.spaceSmall, vertical = Space.spaceSmall) .clip(RoundedCornerShape(MaterialCornerRadius.radiusMedium)) - .background(Colors.primaryVariant) + .background(MaterialTheme.colorScheme.surfaceVariant) .padding(Space.spaceMedium), verticalAlignment = Alignment.CenterVertically, ) { @@ -103,7 +102,7 @@ fun BillDetails(history: History, modifier: Modifier = Modifier) { style = Typography.body1, maxLines = 1, overflow = TextOverflow.Ellipsis, - color = Colors.onSurface + color = MaterialTheme.colorScheme.onSurface ) Text( text = stringResource( @@ -113,7 +112,7 @@ fun BillDetails(history: History, modifier: Modifier = Modifier) { style = Typography.body1, maxLines = 1, overflow = TextOverflow.Ellipsis, - color = Colors.onSurface + color = MaterialTheme.colorScheme.onSurface ) } Box( @@ -121,12 +120,12 @@ fun BillDetails(history: History, modifier: Modifier = Modifier) { .width(Size.size3XLarge) .size(Space.spaceLarge) .clip(CircleShape) - .background(if (history.paid) Colors.success else Colors.error), + .background(if (history.paid) MaterialTheme.colorScheme.secondary else MaterialTheme.colorScheme.error), contentAlignment = Alignment.Center ) { Text( text = if (history.paid) stringResource(R.string.paid) else stringResource(R.string.not_paid), - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onSurface, style = Typography.caption, maxLines = 1, overflow = TextOverflow.Ellipsis diff --git a/app/src/main/java/com/ouday/cryptowalletsample/common/FlowStateUtils.kt b/app/src/main/java/com/ouday/cryptowalletsample/common/FlowStateUtils.kt index 5b345cc..df24232 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/common/FlowStateUtils.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/common/FlowStateUtils.kt @@ -20,6 +20,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Error import androidx.compose.material3.Button 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 @@ -31,7 +32,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.ouday.cryptowalletsample.ui.theme.Colors @Composable fun HandleFlowState( @@ -117,14 +117,14 @@ fun ErrorContent(errorMessage: String, onRetry: () -> Unit) { verticalArrangement = Arrangement.Center ) { // Error icon or image (optional) - Icon(Icons.Filled.Error, contentDescription = "Error", tint = Colors.error) + Icon(Icons.Filled.Error, contentDescription = "Error", tint = MaterialTheme.colorScheme.error) Spacer(modifier = Modifier.height(16.dp)) // Error message text Text( text = errorMessage, - color = Colors.error, + color = MaterialTheme.colorScheme.error, style = typography.body1, textAlign = TextAlign.Center ) diff --git a/app/src/main/java/com/ouday/cryptowalletsample/home/components/BillOptionsComposable.kt b/app/src/main/java/com/ouday/cryptowalletsample/home/components/BillOptionsComposable.kt index fcb6aef..c66b9fb 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/home/components/BillOptionsComposable.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/home/components/BillOptionsComposable.kt @@ -1,10 +1,20 @@ package com.ouday.cryptowalletsample.home.components import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -12,16 +22,20 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.res.stringResource -import com.ouday.cryptowalletsample.R -import com.ouday.cryptowalletsample.bills.data.model.Bill -import com.ouday.cryptowalletsample.ui.theme.* +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import coil.compose.rememberAsyncImagePainter import coil.decode.SvgDecoder import coil.imageLoader import coil.request.ImageRequest +import com.ouday.cryptowalletsample.R +import com.ouday.cryptowalletsample.bills.data.model.Bill +import com.ouday.cryptowalletsample.bills.data.model.History import com.ouday.cryptowalletsample.common.getImageUrl +import com.ouday.cryptowalletsample.ui.theme.Size +import com.ouday.cryptowalletsample.ui.theme.Space +import com.ouday.cryptowalletsample.ui.theme.Typography @Composable fun BillOptionItem( @@ -44,14 +58,14 @@ fun BillOptionItem( Column( modifier = Modifier - .width(Size.size2XMax) - .height(Size.sizeMax) + .width(Size.size2XLarge) + .height(Size.size3XLarge) ) { Box( modifier = Modifier .clip(RoundedCornerShape(Size.sizeSmall)) .fillMaxWidth() - .background(Colors.primary.copy(alpha = if (isSelected) 0.8f else 0.2f)) + .background(MaterialTheme.colorScheme.primary.copy(alpha = if (isSelected) 0.8f else 0.2f)) .wrapContentHeight() ) { IconButton(onClick = { onBillClicked(bill) }) { @@ -60,9 +74,9 @@ fun BillOptionItem( painter = painter, contentDescription = stringResource(id = R.string.bill_option_description, bill.billName), modifier = Modifier - .size(Size.sizeLarge) + .size(Size.size2XLarge) .padding(Space.space2XSmall), - tint = if (isSelected) Colors.background else Colors.onSurface + tint = if (isSelected) MaterialTheme.colorScheme.background else MaterialTheme.colorScheme.onBackground ) } } @@ -73,7 +87,38 @@ fun BillOptionItem( .fillMaxWidth() .fillMaxHeight(), textAlign = TextAlign.Center, - style = Typography.caption.copy(fontSize = Typography.caption.fontSize) + style = Typography.overline, + maxLines = 1 + ) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewBillOptionItem() { + // Sample Bill data for the preview + val sampleBill = Bill( + id = 1, + billName = "Sample Bill", + icon = "https://example.com/sample_icon.svg", + history = listOf( + History(date = "2023-12-17", amount = 100.0, paid = true) + ) + ) + + // Preview of BillOptionItem in both selected and unselected states + Column { + BillOptionItem( + bill = sampleBill, + isSelected = true, + onBillClicked = {} + ) + Spacer(modifier = Modifier.height(Space.spaceMedium)) + BillOptionItem( + bill = sampleBill, + isSelected = false, + onBillClicked = {} ) } } + diff --git a/app/src/main/java/com/ouday/cryptowalletsample/home/components/BottomNavigationBar.kt b/app/src/main/java/com/ouday/cryptowalletsample/home/components/BottomNavigationBar.kt index f6b7a62..5c68227 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/home/components/BottomNavigationBar.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/home/components/BottomNavigationBar.kt @@ -3,6 +3,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Home @@ -10,6 +11,7 @@ import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Wallet import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItemDefaults @@ -21,22 +23,33 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.ouday.cryptowalletsample.ui.theme.Colors +import com.ouday.cryptowalletsample.R +import com.ouday.cryptowalletsample.ui.theme.* @Composable fun BottomNavigationBar( items: List, - currentRoute: String, onItemSelected: (BottomNavItem) -> Unit ) { - Box(modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 24.dp, top = 8.dp)) { + Box( + modifier = Modifier + .padding( + start = Space.spaceLarge, + end = Space.spaceLarge, + bottom = Space.spaceXLarge, + top = Space.spaceSmall + ) + ) { NavigationBar( modifier = Modifier .fillMaxWidth() - .height(50.dp) - .background(Colors.surface, RoundedCornerShape(30.dp)), + .height(Space.space2XLarge) + .background( + MaterialTheme.colorScheme.primary.copy(alpha = 0.2f), + RoundedCornerShape(MaterialCornerRadius.radiusMedium) + ), containerColor = Color.Transparent ) { var selectedItem by remember { mutableStateOf(BottomNavItem.Home) } @@ -46,7 +59,7 @@ fun BottomNavigationBar( icon = { Icon( imageVector = item.icon, - contentDescription = item.label + contentDescription = stringResource(id = item.labelRes) ) }, @@ -56,11 +69,11 @@ fun BottomNavigationBar( onItemSelected(item) }, colors = NavigationBarItemDefaults.colors( - indicatorColor = Color(0xFFFF0000), - unselectedIconColor = Color(0xFF10720D), - unselectedTextColor = Color(0xFF1870DD), - selectedIconColor = Color(0xFF14DA7C), - selectedTextColor = Color(0xFFD6DD18), + indicatorColor = MaterialTheme.colorScheme.primary, + unselectedIconColor = MaterialTheme.colorScheme.onSurface, + unselectedTextColor = MaterialTheme.colorScheme.onSurface, + selectedIconColor = MaterialTheme.colorScheme.onSecondaryContainer, + selectedTextColor = MaterialTheme.colorScheme.secondary, ), alwaysShowLabel = true ) @@ -71,17 +84,26 @@ fun BottomNavigationBar( @Preview(showBackground = true) @Composable -fun BottomNavigationBarPreview() { +fun PreviewBottomNavigationBar() { + // Sample items for the bottom navigation bar + val items = listOf( + BottomNavItem.Home, + BottomNavItem.Search, + BottomNavItem.Wallet, + BottomNavItem.Profile + ) + BottomNavigationBar( - listOf(BottomNavItem.Home), - "home", - {} + items = items ) + // This can be dynamic based on the current route in your actual app + { /* Handle item selection */ } } -sealed class BottomNavItem(val route: String, val icon: ImageVector, val label: String) { - object Home : BottomNavItem("home", Icons.Filled.Home, "Home") - object Search : BottomNavItem("Search", Icons.Filled.Search, "Search") - object Wallet : BottomNavItem("Wallet", Icons.Filled.Wallet, "Wallet") - object Profile : BottomNavItem("Profile", Icons.Filled.Person, "Profile") -} + +sealed class BottomNavItem(val route: String, val icon: ImageVector, val labelRes: Int) { + object Home : BottomNavItem("home", Icons.Filled.Home, R.string.nav_home) + object Search : BottomNavItem("search", Icons.Filled.Search, R.string.nav_search) + object Wallet : BottomNavItem("wallet", Icons.Filled.Wallet, R.string.nav_wallet) + object Profile : BottomNavItem("profile", Icons.Filled.Person, R.string.nav_profile) +} \ No newline at end of file diff --git a/app/src/main/java/com/ouday/cryptowalletsample/home/components/CreditCardComposable.kt b/app/src/main/java/com/ouday/cryptowalletsample/home/components/CreditCardComposable.kt index a59e982..52fb789 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/home/components/CreditCardComposable.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/home/components/CreditCardComposable.kt @@ -7,16 +7,17 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview import androidx.constraintlayout.compose.ConstraintLayout import com.ouday.cryptowalletsample.R import com.ouday.cryptowalletsample.creditcards.data.model.CreditCardInfo -import com.ouday.cryptowalletsample.ui.theme.Colors import com.ouday.cryptowalletsample.ui.theme.MaterialCornerRadius import com.ouday.cryptowalletsample.ui.theme.Size import com.ouday.cryptowalletsample.ui.theme.Space @@ -28,7 +29,7 @@ fun CreditCardComposable(cardInfo: CreditCardInfo, modifier: Modifier = Modifier modifier = modifier .height(Size.sizeXMax) .clip(RoundedCornerShape(MaterialCornerRadius.radiusMedium)) - .background(Colors.surface) + .background(MaterialTheme.colorScheme.secondary) .padding(Space.spaceMedium) ) { ConstraintLayout( @@ -38,67 +39,88 @@ fun CreditCardComposable(cardInfo: CreditCardInfo, modifier: Modifier = Modifier Text( text = cardInfo.cardType, - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onPrimary, style = Typography.h6, modifier = Modifier.constrainAs(cardType) { - top.linkTo(parent.top, margin = Space.spaceMedium) - start.linkTo(parent.start, margin = Space.spaceMedium) + top.linkTo(parent.top) + start.linkTo(parent.start) } ) Text( text = cardInfo.cardNumber, // Masked number for privacy - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onPrimary, style = Typography.h6, modifier = Modifier.constrainAs(cardNumber) { - top.linkTo(cardType.bottom, margin = Space.spaceSmall) + top.linkTo(cardType.bottom) end.linkTo(parent.end, margin = Space.spaceMedium) } ) Text( text = stringResource(R.string.due_date, cardInfo.dueDate), - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onPrimary, style = Typography.subtitle1, modifier = Modifier.constrainAs(dueDate) { - top.linkTo(cardNumber.bottom, margin = Space.spaceSmall) - start.linkTo(parent.start, margin = Space.spaceMedium) + top.linkTo(cardNumber.bottom) + start.linkTo(parent.start) } ) Text( text = cardInfo.amountDue, - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onPrimary, style = Typography.h4.copy(fontWeight = FontWeight.Bold), modifier = Modifier.constrainAs(amount) { - top.linkTo(dueDate.bottom, margin = Space.spaceSmall) - start.linkTo(parent.start, margin = Space.spaceMedium) + top.linkTo(paymentStatus.bottom) + start.linkTo(parent.start) } ) Button( - onClick = { /* Handle the payment action */ }, - modifier = Modifier.constrainAs(payButton) { - bottom.linkTo(parent.bottom, margin = Space.spaceMedium) - end.linkTo(parent.end, margin = Space.spaceMedium) + onClick = { /*TODO Handle on card clicked */ }, + modifier = Modifier + .constrainAs(payButton) { + bottom.linkTo(parent.bottom) + end.linkTo(parent.end) } ) { Text( text = stringResource(R.string.pay), style = Typography.button, - color = Colors.onSurface + color = MaterialTheme.colorScheme.onPrimary ) } Text( text = cardInfo.paymentStatus, - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onPrimary, style = Typography.overline, - modifier = Modifier.constrainAs(paymentStatus) { - start.linkTo(parent.start, margin = Space.spaceMedium) - bottom.linkTo(payButton.top, margin = Space.spaceSmall) + modifier = Modifier + .constrainAs(paymentStatus) { + start.linkTo(parent.start) + bottom.linkTo(payButton.top) } ) } } -} \ No newline at end of file +} + +@Preview(showBackground = true) +@Composable +fun PreviewCreditCardComposable() { + // Sample CreditCardInfo data for the preview + val sampleCreditCardInfo = CreditCardInfo( + cardType = "Visa", + cardNumber = "**** **** **** 1234", + dueDate = "12/25/2023", + amountDue = "$1,200.00", + paymentStatus = "Pending" + ) + + // Preview of CreditCardComposable + CreditCardComposable( + cardInfo = sampleCreditCardInfo, + modifier = Modifier.padding(Space.spaceMedium) + ) +} diff --git a/app/src/main/java/com/ouday/cryptowalletsample/home/components/HomeHeaderComposable.kt b/app/src/main/java/com/ouday/cryptowalletsample/home/components/HomeHeaderComposable.kt index a3c5992..8e18c62 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/home/components/HomeHeaderComposable.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/home/components/HomeHeaderComposable.kt @@ -2,17 +2,20 @@ package com.ouday.cryptowalletsample.home.components import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview import androidx.constraintlayout.compose.ConstraintLayout import com.ouday.cryptowalletsample.R import com.ouday.cryptowalletsample.ui.theme.Size import com.ouday.cryptowalletsample.ui.theme.Space -import com.ouday.cryptowalletsample.ui.theme.Colors import com.ouday.cryptowalletsample.ui.theme.Typography @Composable @@ -47,12 +50,14 @@ fun HomeHeaderComposable(username: String, modifier: Modifier = Modifier) { @Composable fun ProfileImage(modifier: Modifier) { - Box(modifier = modifier.padding( - top = Space.spaceMedium, - bottom = Space.spaceMedium, - start = Space.spaceMedium, - end = Space.space2XSmall - )) { + Box( + modifier = modifier.padding( + top = Space.spaceMedium, + bottom = Space.spaceMedium, + start = Space.spaceMedium, + end = Space.space2XSmall + ) + ) { Image( painter = painterResource(id = R.drawable.victory), contentDescription = "Profile Image", @@ -67,7 +72,7 @@ fun UsernameText(username: String, modifier: Modifier) { Text( text = username, modifier = modifier.padding(start = Space.spaceMedium), - style = Typography.h5.copy(color = Colors.primary) + style = Typography.h5.copy(color = MaterialTheme.colorScheme.primary) ) } @@ -87,4 +92,46 @@ fun SearchIcon(modifier: Modifier) { contentDescription = "Search", modifier = modifier.padding(Space.spaceMedium) ) -} \ No newline at end of file +} + + +@Preview(showBackground = true) +@Composable +fun PreviewHomeHeaderComposable() { + HomeHeaderComposable( + username = "JohnDoe", + modifier = Modifier.fillMaxWidth() + ) +} + +@Preview(showBackground = true) +@Composable +fun PreviewProfileImage() { + ProfileImage(modifier = Modifier.wrapContentSize()) +} + +@Preview(showBackground = true) +@Composable +fun PreviewUsernameText() { + UsernameText( + username = "JohnDoe", + modifier = Modifier + ) +} + +@Preview(showBackground = true) +@Composable +fun PreviewNotificationIcon() { + NotificationIcon( + modifier = Modifier.wrapContentSize() + ) +} + +@Preview(showBackground = true) +@Composable +fun PreviewSearchIcon() { + SearchIcon( + modifier = Modifier.wrapContentSize() + ) +} + diff --git a/app/src/main/java/com/ouday/cryptowalletsample/home/components/LoanCardComposable.kt b/app/src/main/java/com/ouday/cryptowalletsample/home/components/LoanCardComposable.kt index 6675fec..4f30cf3 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/home/components/LoanCardComposable.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/home/components/LoanCardComposable.kt @@ -5,13 +5,17 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.LinearProgressIndicator +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.ConstraintLayoutScope import androidx.constraintlayout.compose.ConstrainedLayoutReference @@ -34,7 +38,10 @@ fun LoanCardComposable( CardImageBox( imageResourceId = R.drawable.ic_car, - imageContentDescription = stringResource(R.string.image_content_description, content.imageContentDescription), + imageContentDescription = stringResource( + R.string.image_content_description, + content.imageContentDescription + ), imageBoxRef = imageBox ) @@ -84,7 +91,7 @@ fun ConstraintLayoutScope.CardImageBox( ) { Box( modifier = Modifier - .size(Size.sizeLarge) + .size(Size.size2XLarge) .background(Color.White, RoundedCornerShape(MaterialCornerRadius.radiusSmall)) .constrainAs(imageBoxRef) { top.linkTo(parent.top) @@ -95,7 +102,7 @@ fun ConstraintLayoutScope.CardImageBox( painter = painterResource(id = imageResourceId), contentDescription = imageContentDescription, modifier = Modifier - .size(Size.sizeMedium) + .size(Size.sizeXLarge) .align(Alignment.Center) ) } @@ -109,7 +116,7 @@ fun ConstraintLayoutScope.CardPriceText( Text( text = priceText, style = Typography.h6, - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onSurface, modifier = Modifier.constrainAs(priceRef) { top.linkTo(parent.top) end.linkTo(parent.end) @@ -126,7 +133,7 @@ fun ConstraintLayoutScope.CardModelText( Text( text = modelText, style = Typography.subtitle1, - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onSurface, modifier = Modifier.constrainAs(modelRef) { top.linkTo(imageBoxRef.bottom, margin = Space.spaceSmall) start.linkTo(parent.start) @@ -143,14 +150,14 @@ fun ConstraintLayoutScope.CardProgressIndicator( LinearProgressIndicator( progress = progressFraction, backgroundColor = Color.LightGray, - color = Colors.success, + color = MaterialTheme.colorScheme.secondary, modifier = Modifier - .fillMaxWidth() + .wrapContentWidth() .height(Size.sizeXSmall) .constrainAs(progressRef) { top.linkTo(modelRef.bottom, margin = Space.spaceSmall) - start.linkTo(parent.start) - end.linkTo(parent.end) + start.linkTo(parent.start, margin = Space.spaceMedium) + end.linkTo(progressRef.end, margin = Space.spaceSmall) } ) } @@ -164,7 +171,7 @@ fun ConstraintLayoutScope.CardNextBillingText( Text( text = nextText, style = Typography.caption, - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onSurface, modifier = Modifier.constrainAs(nextBillingRef) { top.linkTo(priceRef.bottom, margin = Space.space2XSmall) end.linkTo(parent.end) @@ -181,7 +188,7 @@ fun ConstraintLayoutScope.CardBillingDateText( Text( text = billingDateText, style = Typography.body1, - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onSurface, modifier = Modifier.constrainAs(billingDateRef) { top.linkTo(nextBillingRef.bottom, margin = Space.space2XSmall) end.linkTo(parent.end) @@ -198,11 +205,132 @@ fun ConstraintLayoutScope.CardProgressText( Text( text = progressText, style = Typography.caption, - color = Colors.onSurface, + color = MaterialTheme.colorScheme.onSurface, modifier = Modifier.constrainAs(progressTextRef) { top.linkTo(progressRef.top) bottom.linkTo(progressRef.bottom) - end.linkTo(progressRef.end) + end.linkTo(parent.end) } ) } + +@Preview(showBackground = true) +@Composable +fun PreviewLoanCardComposable() { + // Sample Subscription data for the preview + val sampleSubscription = Subscription( + priceText = "$1,500", + modelText = "Car Loan", + nextText = "Next Billing: 01/15/2024", + billingDateText = "Billing Date: 01/15/2023", + progressText = "60% Paid", + progressFraction = 0.6, + imageContentDescription = "Car Image", + imageResourceId = "sample_car_image_resource" // Replace with actual resource ID + ) + + LoanCardComposable( + content = sampleSubscription, + modifier = Modifier + .width(Size.size2XMax) + .height(Size.sizeMax) + .clip(RoundedCornerShape(Size.sizeSmall)) + .background(MaterialTheme.colorScheme.surfaceVariant) + .padding(Size.sizeMedium) + ) +} + +@Preview(showBackground = true) +@Composable +fun PreviewCardImageBox() { + ConstraintLayout { + val imageBoxRef = createRef() + CardImageBox( + imageResourceId = R.drawable.ic_car, + imageContentDescription = "Sample Image", + imageBoxRef = imageBoxRef + ) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewCardPriceText() { + ConstraintLayout { + val priceRef = createRef() + CardPriceText( + priceText = "$999", + priceRef = priceRef + ) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewCardModelText() { + ConstraintLayout { + val modelRef = createRef() + val imageBoxRef = createRef() + CardModelText( + modelText = "Car Model X", + modelRef = modelRef, + imageBoxRef = imageBoxRef + ) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewCardProgressIndicator() { + ConstraintLayout { + val progressRef = createRef() + val modelRef = createRef() + CardProgressIndicator( + progressFraction = 0.5f, + progressRef = progressRef, + modelRef = modelRef + ) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewCardNextBillingText() { + ConstraintLayout { + val nextBillingRef = createRef() + val priceRef = createRef() + CardNextBillingText( + nextText = "Next Billing: 10/10/2023", + nextBillingRef = nextBillingRef, + priceRef = priceRef + ) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewCardBillingDateText() { + ConstraintLayout { + val billingDateRef = createRef() + val nextBillingRef = createRef() + CardBillingDateText( + billingDateText = "Billing Date: 09/10/2023", + billingDateRef = billingDateRef, + nextBillingRef = nextBillingRef + ) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewCardProgressText() { + ConstraintLayout { + val progressTextRef = createRef() + val progressRef = createRef() + CardProgressText( + progressText = "Progress: 50%", + progressTextRef = progressTextRef, + progressRef = progressRef + ) + } +} diff --git a/app/src/main/java/com/ouday/cryptowalletsample/home/ui/view/HomeScreen.kt b/app/src/main/java/com/ouday/cryptowalletsample/home/ui/view/HomeScreen.kt index 49d9581..0369aad 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/home/ui/view/HomeScreen.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/home/ui/view/HomeScreen.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -41,7 +42,7 @@ fun HomeScreen(modifier: Modifier = Modifier, viewModel: HomeViewModel = hiltVie text = stringResource(id = R.string.bill_payments), style = Typography.subtitle1, modifier = Modifier.padding(start = Space.spaceLarge), - color = Colors.onSurface + color = MaterialTheme.colorScheme.onBackground ) Spacer(modifier = Modifier.height(Space.spaceSmall)) BillOptionsComposable(viewModel = viewModel) @@ -50,7 +51,7 @@ fun HomeScreen(modifier: Modifier = Modifier, viewModel: HomeViewModel = hiltVie text = stringResource(id = R.string.active_loans), style = Typography.subtitle1, modifier = Modifier.padding(start = Space.spaceLarge), - color = Colors.onSurface + color = MaterialTheme.colorScheme.onBackground ) Spacer(modifier = Modifier.height(Space.spaceSmall)) Subscriptions(viewModel = viewModel) @@ -79,7 +80,7 @@ fun Subscriptions(viewModel: HomeViewModel = hiltViewModel()) { .width(Size.size2XMax) .height(Size.sizeMax) .clip(RoundedCornerShape(Size.sizeSmall)) - .background(Colors.primary.copy(alpha = 0.2f)) + .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.2f)) .padding(Size.sizeMedium) ) } @@ -162,8 +163,8 @@ fun CreditCardsPager(creditCards: List) { HorizontalPagerIndicator( pagerState = pagerState, modifier = Modifier.align(Alignment.CenterHorizontally), - activeColor = Colors.primary, - inactiveColor = Colors.primary.copy(alpha = 0.6f) + activeColor = MaterialTheme.colorScheme.primary, + inactiveColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.6f) ) } } diff --git a/app/src/main/java/com/ouday/cryptowalletsample/home/ui/view/MainScreen.kt b/app/src/main/java/com/ouday/cryptowalletsample/home/ui/view/MainScreen.kt index ad1bbe3..805b371 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/home/ui/view/MainScreen.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/home/ui/view/MainScreen.kt @@ -28,8 +28,7 @@ fun MainScreen(modifier: Modifier = Modifier) { BottomNavItem.Search, BottomNavItem.Wallet, BottomNavItem.Profile, - ), - "home" + ) ) { selectedItem -> navController.navigate(selectedItem.route) } @@ -41,7 +40,7 @@ fun MainScreen(modifier: Modifier = Modifier) { .padding(innerPadding) ) { HomeHeaderComposable( - "Ouday", + "Welcome Back!", modifier = Modifier .fillMaxWidth() .wrapContentHeight() diff --git a/app/src/main/java/com/ouday/cryptowalletsample/subscriptions/ui/view/SubscriptionScreen.kt b/app/src/main/java/com/ouday/cryptowalletsample/subscriptions/ui/view/SubscriptionScreen.kt index 10fe647..0973842 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/subscriptions/ui/view/SubscriptionScreen.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/subscriptions/ui/view/SubscriptionScreen.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -50,7 +51,7 @@ fun SubscriptionsList(subscriptions: List, modifier: Modifier = Mo .fillMaxWidth() .height(Size.sizeMax) .clip(RoundedCornerShape(Size.sizeSmall)) - .background(Colors.primary.copy(alpha = 0.2f)) + .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.2f)) .padding(Size.sizeMedium) ) } diff --git a/app/src/main/java/com/ouday/cryptowalletsample/ui/theme/Color.kt b/app/src/main/java/com/ouday/cryptowalletsample/ui/theme/Color.kt new file mode 100644 index 0000000..152c43d --- /dev/null +++ b/app/src/main/java/com/ouday/cryptowalletsample/ui/theme/Color.kt @@ -0,0 +1,67 @@ +package com.ouday.cryptowalletsample.ui.theme +import androidx.compose.ui.graphics.Color + +val md_theme_light_primary = Color(0xFF8800EB) +val md_theme_light_onPrimary = Color(0xFFFFFFFF) +val md_theme_light_primaryContainer = Color(0xFFF0DBFF) +val md_theme_light_onPrimaryContainer = Color(0xFF2C0051) +val md_theme_light_secondary = Color(0xFF655A6F) +val md_theme_light_onSecondary = Color(0xFFFFFFFF) +val md_theme_light_secondaryContainer = Color(0xFFEDDDF6) +val md_theme_light_onSecondaryContainer = Color(0xFF21182A) +val md_theme_light_tertiary = Color(0xFF805158) +val md_theme_light_onTertiary = Color(0xFFFFFFFF) +val md_theme_light_tertiaryContainer = Color(0xFFFFD9DD) +val md_theme_light_onTertiaryContainer = Color(0xFF321017) +val md_theme_light_error = Color(0xFFBA1A1A) +val md_theme_light_errorContainer = Color(0xFFFFDAD6) +val md_theme_light_onError = Color(0xFFFFFFFF) +val md_theme_light_onErrorContainer = Color(0xFF410002) +val md_theme_light_background = Color(0xFFFFFBFF) +val md_theme_light_onBackground = Color(0xFF1D1B1E) +val md_theme_light_surface = Color(0xFFFFFBFF) +val md_theme_light_onSurface = Color(0xFF1D1B1E) +val md_theme_light_surfaceVariant = Color(0xFFE9DFEB) +val md_theme_light_onSurfaceVariant = Color(0xFF4A454E) +val md_theme_light_outline = Color(0xFF7B757E) +val md_theme_light_inverseOnSurface = Color(0xFFF5EFF4) +val md_theme_light_inverseSurface = Color(0xFF322F33) +val md_theme_light_inversePrimary = Color(0xFFDCB8FF) +val md_theme_light_shadow = Color(0xFF000000) +val md_theme_light_surfaceTint = Color(0xFF8800EB) +val md_theme_light_outlineVariant = Color(0xFFCCC4CE) +val md_theme_light_scrim = Color(0xFF000000) + +val md_theme_dark_primary = Color(0xFFDCB8FF) +val md_theme_dark_onPrimary = Color(0xFF480081) +val md_theme_dark_primaryContainer = Color(0xFF6700B5) +val md_theme_dark_onPrimaryContainer = Color(0xFFF0DBFF) +val md_theme_dark_secondary = Color(0xFFD0C1DA) +val md_theme_dark_onSecondary = Color(0xFF362C3F) +val md_theme_dark_secondaryContainer = Color(0xFF4D4357) +val md_theme_dark_onSecondaryContainer = Color(0xFFEDDDF6) +val md_theme_dark_tertiary = Color(0xFFF3B7BE) +val md_theme_dark_onTertiary = Color(0xFF4B252B) +val md_theme_dark_tertiaryContainer = Color(0xFF653A41) +val md_theme_dark_onTertiaryContainer = Color(0xFFFFD9DD) +val md_theme_dark_error = Color(0xFFFFB4AB) +val md_theme_dark_errorContainer = Color(0xFF93000A) +val md_theme_dark_onError = Color(0xFF690005) +val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) +val md_theme_dark_background = Color(0xFF1D1B1E) +val md_theme_dark_onBackground = Color(0xFFE7E1E5) +val md_theme_dark_surface = Color(0xFF1D1B1E) +val md_theme_dark_onSurface = Color(0xFFE7E1E5) +val md_theme_dark_surfaceVariant = Color(0xFF4A454E) +val md_theme_dark_onSurfaceVariant = Color(0xFFCCC4CE) +val md_theme_dark_outline = Color(0xFF968E98) +val md_theme_dark_inverseOnSurface = Color(0xFF1D1B1E) +val md_theme_dark_inverseSurface = Color(0xFFE7E1E5) +val md_theme_dark_inversePrimary = Color(0xFF8800EB) +val md_theme_dark_shadow = Color(0xFF000000) +val md_theme_dark_surfaceTint = Color(0xFFDCB8FF) +val md_theme_dark_outlineVariant = Color(0xFF4A454E) +val md_theme_dark_scrim = Color(0xFF000000) + + +val seed = Color(0xFF8800EB) diff --git a/app/src/main/java/com/ouday/cryptowalletsample/ui/theme/Theme.kt b/app/src/main/java/com/ouday/cryptowalletsample/ui/theme/Theme.kt new file mode 100644 index 0000000..bead15c --- /dev/null +++ b/app/src/main/java/com/ouday/cryptowalletsample/ui/theme/Theme.kt @@ -0,0 +1,90 @@ +package com.ouday.cryptowalletsample.ui.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.runtime.Composable + + +private val LightColors = lightColorScheme( + primary = md_theme_light_primary, + onPrimary = md_theme_light_onPrimary, + primaryContainer = md_theme_light_primaryContainer, + onPrimaryContainer = md_theme_light_onPrimaryContainer, + secondary = md_theme_light_secondary, + onSecondary = md_theme_light_onSecondary, + secondaryContainer = md_theme_light_secondaryContainer, + onSecondaryContainer = md_theme_light_onSecondaryContainer, + tertiary = md_theme_light_tertiary, + onTertiary = md_theme_light_onTertiary, + tertiaryContainer = md_theme_light_tertiaryContainer, + onTertiaryContainer = md_theme_light_onTertiaryContainer, + error = md_theme_light_error, + onError = md_theme_light_onError, + errorContainer = md_theme_light_errorContainer, + onErrorContainer = md_theme_light_onErrorContainer, + outline = md_theme_light_outline, + background = md_theme_light_background, + onBackground = md_theme_light_onBackground, + surface = md_theme_light_surface, + onSurface = md_theme_light_onSurface, + surfaceVariant = md_theme_light_surfaceVariant, + onSurfaceVariant = md_theme_light_onSurfaceVariant, + inverseSurface = md_theme_light_inverseSurface, + inverseOnSurface = md_theme_light_inverseOnSurface, + inversePrimary = md_theme_light_inversePrimary, + surfaceTint = md_theme_light_surfaceTint, + outlineVariant = md_theme_light_outlineVariant, + scrim = md_theme_light_scrim, +) + + +private val DarkColors = darkColorScheme( + primary = md_theme_dark_primary, + onPrimary = md_theme_dark_onPrimary, + primaryContainer = md_theme_dark_primaryContainer, + onPrimaryContainer = md_theme_dark_onPrimaryContainer, + secondary = md_theme_dark_secondary, + onSecondary = md_theme_dark_onSecondary, + secondaryContainer = md_theme_dark_secondaryContainer, + onSecondaryContainer = md_theme_dark_onSecondaryContainer, + tertiary = md_theme_dark_tertiary, + onTertiary = md_theme_dark_onTertiary, + tertiaryContainer = md_theme_dark_tertiaryContainer, + onTertiaryContainer = md_theme_dark_onTertiaryContainer, + error = md_theme_dark_error, + onError = md_theme_dark_onError, + errorContainer = md_theme_dark_errorContainer, + onErrorContainer = md_theme_dark_onErrorContainer, + outline = md_theme_dark_outline, + background = md_theme_dark_background, + onBackground = md_theme_dark_onBackground, + surface = md_theme_dark_surface, + onSurface = md_theme_dark_onSurface, + surfaceVariant = md_theme_dark_surfaceVariant, + onSurfaceVariant = md_theme_dark_onSurfaceVariant, + inverseSurface = md_theme_dark_inverseSurface, + inverseOnSurface = md_theme_dark_inverseOnSurface, + inversePrimary = md_theme_dark_inversePrimary, + surfaceTint = md_theme_dark_surfaceTint, + outlineVariant = md_theme_dark_outlineVariant, + scrim = md_theme_dark_scrim, +) + +@Composable +fun AppTheme( + useDarkTheme: Boolean = isSystemInDarkTheme(), + content: @Composable() () -> Unit +) { + val colors = if (!useDarkTheme) { + LightColors + } else { + DarkColors + } + + MaterialTheme( + colorScheme = colors, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/ouday/cryptowalletsample/ui/theme/CryptoWalletSampleTheme.kt b/app/src/main/java/com/ouday/cryptowalletsample/ui/theme/ThemeConstants.kt similarity index 53% rename from app/src/main/java/com/ouday/cryptowalletsample/ui/theme/CryptoWalletSampleTheme.kt rename to app/src/main/java/com/ouday/cryptowalletsample/ui/theme/ThemeConstants.kt index 2f81929..5316086 100644 --- a/app/src/main/java/com/ouday/cryptowalletsample/ui/theme/CryptoWalletSampleTheme.kt +++ b/app/src/main/java/com/ouday/cryptowalletsample/ui/theme/ThemeConstants.kt @@ -1,24 +1,7 @@ package com.ouday.cryptowalletsample.ui.theme -import androidx.compose.material.Colors -import androidx.compose.material.MaterialTheme -import androidx.compose.material.lightColors -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -val Colors.success: Color - get() = Color(0xFF4CAF50) // Example: Changed to Material Green - -val Colors = lightColors( - primary = Color(0xFF6200EE), // Example: Changed to Material Deep Purple - primaryVariant = Color(0xFF3700B3), // Example: Changed to a darker shade of Deep Purple - secondary = Color(0xFF03DAC6), // Example: Changed to Material Teal - surface = Color(0xFF121212), // Example: Changed to a dark surface color - onSurface = Color(0xFFFFFFFF), // Example: Changed to White for contrast on dark surface - onBackground = Color(0xFF000000) // Example: Black for background -) - object Size { val sizeXSmall = 4.dp val sizeSmall = 8.dp @@ -60,10 +43,3 @@ object MaterialElevation { val elevationLevel3 = 6.dp // For medium components val elevationLevel4 = 8.dp // For large components } - -@Composable -fun CryptoWalletSampleTheme(content: @Composable () -> Unit) { - MaterialTheme(colors = Colors, typography = Typography) { - content() - } -} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c320c89..60d933c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,5 +10,8 @@ Active Loans %1$s bill option %1$s image - + Home + Search + Wallet + Profile \ No newline at end of file