diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ee6b882
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+# Order Tracking UI
+You can create you custom shape to develop such type UIs.
+
+# Screenshot
+
+
+# Video
+https://github.com/KaushalVasava/ComposeUI/assets/49050597/412e1e1f-45cb-4bad-a368-259ef343b656
diff --git a/app/src/main/java/com/kaushalvasava/app/composeui/screen/AuthenticationScreen.kt b/app/src/main/java/com/kaushalvasava/app/composeui/screen/AuthenticationScreen.kt
new file mode 100644
index 0000000..eb38a20
--- /dev/null
+++ b/app/src/main/java/com/kaushalvasava/app/composeui/screen/AuthenticationScreen.kt
@@ -0,0 +1,394 @@
+package com.kaushalvasava.app.composeui.screen
+
+import android.widget.Toast
+import androidx.compose.animation.AnimatedContent
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ExperimentalLayoutApi
+import androidx.compose.foundation.layout.FlowRow
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+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.rememberScrollState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+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.draw.clip
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.draw.rotate
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.input.ImeAction
+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.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.navigation.NavController
+import androidx.navigation.compose.rememberNavController
+import com.kaushalvasava.app.composeui.R
+import com.kaushalvasava.app.composeui.ui.navigation.NavigationItem
+import com.kaushalvasava.app.composeui.util.ValidUtil.isValidEmail
+import com.kaushalvasava.app.composeui.util.ValidUtil.isValidName
+import com.kaushalvasava.app.composeui.util.ValidUtil.isValidPasswordFormat
+
+@Preview(showBackground = false)
+@Composable
+fun AuthenticationScreen(navController: NavController = rememberNavController()) {
+
+ var isNewUser by rememberSaveable {
+ mutableStateOf(true)
+ }
+ val backgroundColor = MaterialTheme.colorScheme.background
+ Column(
+ modifier = Modifier
+ .verticalScroll(rememberScrollState())
+ .fillMaxSize()
+ .drawBehind {
+ drawRect(
+ Brush.linearGradient(
+ colors = listOf(
+ Color.Blue,
+ backgroundColor,
+ Color.Blue,
+ )
+ )
+ )
+ }
+ ) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 24.dp),
+ horizontalArrangement = Arrangement.Center,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Text(
+ if (isNewUser) {
+ "Don't have an account?"
+ } else {
+ "Already have an account?"
+ },
+ style = MaterialTheme.typography.bodyMedium,
+ color = Color.White
+ )
+ Spacer(modifier = Modifier.width(8.dp))
+ Button(
+ onClick = {
+ isNewUser = !isNewUser
+ }, colors = ButtonDefaults.buttonColors(
+ containerColor = backgroundColor.copy(0.3f),
+ contentColor = Color.White
+ ),
+ shape = RoundedCornerShape(8.dp)
+ ) {
+ AnimatedContent(targetState = isNewUser, label = "") {
+ Text(
+ if (it) {
+ "Sign up"
+ } else {
+ "Sign in"
+ }
+ )
+ }
+ }
+ }
+ Image(
+ painter = painterResource(id = R.drawable.s_2),
+ contentScale = ContentScale.Crop,
+ contentDescription = "logo",
+ modifier = Modifier
+ .size(200.dp, 150.dp)
+ .rotate(-20f)
+ .clip(RoundedCornerShape(16.dp))
+ .align(Alignment.CenterHorizontally)
+
+ )
+ Text(
+ "Unique",
+ style = MaterialTheme.typography.displayLarge,
+ modifier = Modifier.align(Alignment.CenterHorizontally)
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ HorizontalDivider(
+ modifier = Modifier
+ .padding(horizontal = 32.dp)
+ .clip(RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp)),
+ thickness = 12.dp, color = MaterialTheme.colorScheme.background.copy(0.5f)
+ )
+ InfoCard(modifier = Modifier, isNewUser = { isNewUser }) {
+ navController.navigate(NavigationItem.PRODUCTS)
+ }
+ }
+}
+
+@OptIn(ExperimentalLayoutApi::class)
+@Composable
+fun InfoCard(
+ modifier: Modifier = Modifier,
+ isNewUser: () -> Boolean,
+ onSubmitClick: () -> Unit,
+) {
+ val context = LocalContext.current
+ var email by rememberSaveable {
+ mutableStateOf("")
+ }
+ var name by rememberSaveable {
+ mutableStateOf("")
+ }
+ var isPwdVisible by rememberSaveable {
+ mutableStateOf(false)
+ }
+ val maxChar = 10
+ var password by rememberSaveable {
+ mutableStateOf("")
+ }
+
+ val isValid by remember {
+ derivedStateOf {
+ isValidEmail(email) && isValidPasswordFormat(password)
+ && (if (isNewUser()) isValidName(name) else true)
+ }
+ }
+ val msg =
+ "Password is Wrong!\n" +
+ "Please enter at least 1 digit, 1 upper case and lowercase letter, 1 special character, no white spaces, at least 8 character"
+
+ Column(
+ modifier
+ .fillMaxWidth()
+ .clip(RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp))
+ .background(MaterialTheme.colorScheme.background)
+ .padding(16.dp),
+ verticalArrangement = Arrangement.spacedBy(16.dp),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ AnimatedContent(targetState = isNewUser(), label = "") {
+ Text(
+ if (it) "Let's make life stylish" else "Welcome Back",
+ fontWeight = FontWeight.Bold,
+ fontSize = 32.sp
+ )
+ }
+ Text(
+ "Enter your details below",
+ style = MaterialTheme.typography.bodyMedium,
+ fontWeight = FontWeight.Light
+ )
+ AnimatedContent(targetState = isNewUser(), label = "flowRow") {
+ FlowRow(
+ Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ verticalArrangement = Arrangement.spacedBy(16.dp)
+ ) {
+ if (it) {
+ OutlinedTextField(
+ value = name,
+ onValueChange = {
+ name = it
+ },
+ modifier = Modifier.weight(1f),
+ shape = RoundedCornerShape(12.dp),
+ textStyle = TextStyle(fontSize = 16.sp),
+ placeholder = {
+ Text("Enter name", color = Color.Gray)
+ },
+ supportingText = {
+ if (!isValidName(name) && name.isNotEmpty()) {
+ Text(
+ modifier = Modifier.fillMaxWidth(),
+ text = "Name is wrong!",
+ color = MaterialTheme.colorScheme.error
+ )
+ }
+ },
+ isError = name.isNotEmpty() && !isValidName(name),
+ keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next)
+ )
+ }
+ OutlinedTextField(
+ value = email,
+ onValueChange = {
+ email = it
+ },
+ modifier = Modifier.weight(1f),
+ textStyle = TextStyle(fontSize = 16.sp),
+ placeholder = {
+ Text("Enter email", color = Color.Gray)
+ },
+ shape = RoundedCornerShape(12.dp),
+ supportingText = {
+ if (!isValidEmail(email) && email.isNotEmpty()) {
+ Text(
+ modifier = Modifier.fillMaxWidth(),
+ text = "Email is wrong!",
+ color = MaterialTheme.colorScheme.error
+ )
+ }
+ },
+ isError = email.isNotEmpty() && !isValidEmail(email),
+ keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next)
+ )
+ OutlinedTextField(
+ value = password,
+ onValueChange = {
+ if (it.length <= maxChar) password = it
+ },
+ modifier = Modifier.weight(1f),
+ shape = RoundedCornerShape(12.dp),
+ visualTransformation =
+ if (isPwdVisible)
+ VisualTransformation.None
+ else
+ PasswordVisualTransformation(),
+ trailingIcon = {
+ IconButton(
+ onClick = {
+ isPwdVisible = !isPwdVisible
+ }
+ ) {
+ Icon(
+ if (isPwdVisible)
+ painterResource(id = R.drawable.ic_visibility_off)
+ else
+ painterResource(id = R.drawable.ic_visibility),
+ contentDescription = null
+ )
+ }
+ },
+ supportingText = {
+ if (!isValidPasswordFormat(password) && password.isNotEmpty()) {
+ Text(
+ modifier = Modifier.fillMaxWidth(),
+ text = msg,
+ color = MaterialTheme.colorScheme.error
+ )
+ }
+ },
+ textStyle = TextStyle(fontSize = 16.sp),
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password,
+ imeAction = ImeAction.Done),
+ placeholder = {
+ Text("Enter password", color = Color.Gray)
+ },
+ isError = password.isNotEmpty() && !isValidPasswordFormat(password),
+ )
+ }
+ }
+ Button(
+ onClick = {
+ if (isValid) {
+ onSubmitClick()
+ } else {
+ Toast.makeText(context, "Please enter all valid details", Toast.LENGTH_SHORT)
+ .show()
+ }
+ },
+ modifier = Modifier
+ .fillMaxWidth()
+ .clip(RoundedCornerShape(12.dp))
+ .drawBehind {
+ drawRect(
+ Brush.linearGradient(
+ colors = listOf(
+ Color.Blue,
+ Color.Magenta
+ )
+ )
+ )
+ },
+ colors = ButtonDefaults.buttonColors(
+ containerColor = Color.Transparent,
+ contentColor = Color.White
+ ),
+ shape = RoundedCornerShape(12.dp)
+ ) {
+ Text(
+ if (isNewUser()) "Sign up" else "Sign in",
+ modifier = Modifier.padding(vertical = 8.dp)
+ )
+ }
+ AnimatedVisibility(!isNewUser()) {
+ TextButton(onClick = {
+ //forgot password
+ }) {
+ Text("Forgot your password?")
+ }
+ }
+ Row(
+ Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceAround,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ HorizontalDivider(Modifier.weight(1f))
+ AnimatedContent(targetState = isNewUser(), label = "dg") {
+ Text(
+ if (it) {
+ "Or sign up with"
+ } else {
+ "Or sign in with"
+ },
+ modifier = Modifier.weight(1f),
+ textAlign = TextAlign.Center
+ )
+ }
+ HorizontalDivider(Modifier.weight(1f))
+ }
+ Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
+ OutlinedButton(onClick = { /*TODO*/ }, shape = RoundedCornerShape(8.dp)) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_google),
+ contentDescription = "google",
+ modifier = Modifier.size(ButtonDefaults.IconSize),
+ tint = Color.Unspecified
+ )
+ Spacer(modifier = Modifier.width(16.dp))
+ Text(text = "Google")
+ }
+ OutlinedButton(onClick = { /*TODO*/ }, shape = RoundedCornerShape(8.dp)) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_facebook),
+ contentDescription = "Facebook",
+ modifier = Modifier.size(ButtonDefaults.IconSize),
+ tint = Color.Unspecified
+ )
+ Spacer(modifier = Modifier.width(16.dp))
+ Text(text = "Facebook")
+ }
+ }
+ Spacer(Modifier.weight(1f))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kaushalvasava/app/composeui/screen/OrderScreen.kt b/app/src/main/java/com/kaushalvasava/app/composeui/screen/OrderScreen.kt
new file mode 100644
index 0000000..8244eeb
--- /dev/null
+++ b/app/src/main/java/com/kaushalvasava/app/composeui/screen/OrderScreen.kt
@@ -0,0 +1,112 @@
+package com.kaushalvasava.app.composeui.screen
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Column
+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.lazy.LazyColumn
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.rounded.ArrowBack
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.ModalBottomSheet
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.rememberModalBottomSheetState
+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.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.navigation.NavController
+import androidx.navigation.compose.rememberNavController
+import com.kaushalvasava.app.composeui.R
+import kotlinx.coroutines.launch
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Preview(showBackground = false)
+@Composable
+fun OrderScreen(navController: NavController = rememberNavController()) {
+
+ var isBottomSheet by remember {
+ mutableStateOf(false)
+ }
+
+ val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
+ val coroutineScope = rememberCoroutineScope()
+
+ if (isBottomSheet) {
+ ModalBottomSheet(
+ sheetState = bottomSheetState,
+ onDismissRequest = {
+ coroutineScope.launch {
+ isBottomSheet = false
+ bottomSheetState.hide()
+ }
+ }) {
+ OrderTrackingScreen()
+ }
+ }
+ Scaffold(
+ topBar = {
+ TopAppBar(title = { Text("Orders") }, navigationIcon = {
+ IconButton(onClick = { }) {
+ Icon(Icons.Rounded.ArrowBack, null)
+ }
+ })
+ },
+ ) {
+ LazyColumn(Modifier.padding(it)) {
+ items(8) {
+ OrderItem {
+ coroutineScope.launch {
+ isBottomSheet = true
+ bottomSheetState.show()
+ }
+// navController.navigate(NavigationItem.ORDER_TRACKING)
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun OrderItem(onClick: () -> Unit) {
+ Row(
+ Modifier
+ .fillMaxWidth()
+ .clickable {
+ onClick()
+ }
+ .padding(8.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Image(
+ painter = painterResource(id = R.drawable.s_3),
+ contentDescription = null,
+ modifier = Modifier.size(80.dp)
+ )
+ Spacer(modifier = Modifier.width(8.dp))
+ Column {
+ Text("Shoes Green", style = MaterialTheme.typography.titleMedium)
+ Text("Items: 3", style = MaterialTheme.typography.bodyMedium)
+ Text("Quantity: 1", style = MaterialTheme.typography.bodyMedium)
+ Text("Price: Rs. 1200", style = MaterialTheme.typography.bodyMedium)
+ Text("Delivery Status: Pending", style = MaterialTheme.typography.bodyMedium)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kaushalvasava/app/composeui/screen/OrderTrackingScreen.kt b/app/src/main/java/com/kaushalvasava/app/composeui/screen/OrderTrackingScreen.kt
new file mode 100644
index 0000000..dab8f29
--- /dev/null
+++ b/app/src/main/java/com/kaushalvasava/app/composeui/screen/OrderTrackingScreen.kt
@@ -0,0 +1,235 @@
+package com.kaushalvasava.app.composeui.screen
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+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.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.rounded.Person
+import androidx.compose.material.icons.rounded.Phone
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+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.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 androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Outline
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.kaushalvasava.app.composeui.R
+import kotlin.math.roundToInt
+
+@Preview(showBackground = true)
+@Composable
+fun OrderTrackingScreen() {
+ var isDelivered by remember {
+ mutableStateOf(false)
+ }
+ Column(
+ verticalArrangement = Arrangement.spacedBy(8.dp),
+ modifier = Modifier.padding(horizontal = 8.dp)
+ ) {
+ Row(
+ Modifier
+ .fillMaxWidth()
+ .padding(vertical = 8.dp),
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Image(
+ painter = painterResource(id = R.drawable.s_3),
+ contentDescription = null,
+ modifier = Modifier.size(60.dp)
+ )
+ Column {
+ Text("Shoes S2 - Green", fontWeight = FontWeight.Bold)
+ Text("Quantity: 1", fontSize = 14.sp)
+ }
+ }
+ OrderTrackingCard {
+ isDelivered
+ }
+ Text(
+ "Related Information",
+ style = MaterialTheme.typography.titleLarge,
+ fontWeight = FontWeight.Bold
+ )
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Image(
+ Icons.Rounded.Person,
+ contentDescription = "",
+ modifier = Modifier
+ .clip(CircleShape)
+ .background(Color.Green.copy(0.2f))
+ .size(50.dp)
+ )
+ Spacer(modifier = Modifier.width(8.dp))
+ Column {
+ Text("Kaushal V.")
+ Text("Courrier")
+ }
+ Spacer(modifier = Modifier.weight(1f))
+ IconButton(
+ onClick = {
+ //do call to driver
+ },
+ modifier = Modifier
+ .clip(CircleShape)
+ .background(Color.Green.copy(0.2f))
+ ) {
+ Icon(Icons.Rounded.Phone, contentDescription = "call")
+ }
+ }
+ Button(
+ onClick = {
+ isDelivered = !isDelivered
+ },
+ modifier = Modifier
+ .padding(bottom = 16.dp)
+ .fillMaxWidth()
+ .clip(RoundedCornerShape(16.dp))
+ .drawBehind {
+ drawRect(
+ Brush.linearGradient(
+ listOf(Color.Blue, Color.Green)
+ )
+ )
+ }
+ .align(Alignment.CenterHorizontally),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = Color.Transparent,
+ contentColor = Color.White
+ ),
+ shape = RoundedCornerShape(16.dp)
+ ) {
+ Text(
+ "Pay Now Rs. 1200",
+ style = MaterialTheme.typography.bodyLarge,
+ fontWeight = FontWeight.SemiBold
+ )
+ }
+ }
+}
+
+@Preview(showBackground = false)
+@Composable
+fun OrderTrackingCard(modifier: Modifier = Modifier, isDelivered: () -> Boolean = { false }) {
+ Card(
+ modifier,
+ colors = CardDefaults.cardColors(
+ containerColor = Color.Green.copy(0.2f)
+ )
+ ) {
+ Column(Modifier.padding(8.dp)) {
+ Row(Modifier.fillMaxWidth()) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_location),
+ contentDescription = "null"
+ )
+ Column(Modifier.weight(1f)) {
+ Text("Pickup Point", fontWeight = FontWeight.Bold, fontSize = 16.sp)
+ Text(
+ "Shop no.16 K Store, Zadeshwar ",
+ maxLines = 2,
+ overflow = TextOverflow.Ellipsis,
+ fontWeight = FontWeight.Light,
+ fontSize = 14.sp
+ )
+ }
+ Column(horizontalAlignment = Alignment.End) {
+ Text("Order Time", fontWeight = FontWeight.Bold, fontSize = 16.sp)
+ Text("12 pm", fontWeight = FontWeight.Light, fontSize = 14.sp)
+ }
+ }
+ Box(
+ Modifier
+ .width(4.dp)
+ .height(80.dp)
+ .background(
+ color = if (isDelivered()) {
+ Color(0xFF16AB1D)
+ } else
+ Color.Gray,
+ shape = DottedShape(step = 15.dp)
+ )
+ )
+ Row(Modifier.fillMaxWidth()) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_location),
+ contentDescription = "null"
+ )
+ Column {
+ Text("Delivery Point", fontWeight = FontWeight.Bold, fontSize = 16.sp)
+ Text("Zadeshwar no.2", fontWeight = FontWeight.Light, fontSize = 14.sp)
+ }
+ Spacer(Modifier.weight(1f))
+ Column(horizontalAlignment = Alignment.End) {
+ Text("Delivery Time", fontWeight = FontWeight.Bold, fontSize = 16.sp)
+ Text("3 pm", fontWeight = FontWeight.Light, fontSize = 14.sp)
+ }
+ }
+ }
+ }
+}
+
+
+private data class DottedShape(
+ val step: Dp,
+) : Shape {
+ override fun createOutline(
+ size: Size,
+ layoutDirection: LayoutDirection,
+ density: Density,
+ ) = Outline.Generic(Path().apply {
+ val stepPx = with(density) { step.toPx() }
+ val stepsCount = (size.height / stepPx).roundToInt()
+ val actualStep = size.height / stepsCount
+ val dotSize = Size(width = size.width, height = actualStep / 2)
+ for (i in 0 until stepsCount) {
+ addRect(
+ Rect(
+ offset = Offset(y = i * actualStep, x = 30f),
+ size = dotSize
+ )
+ )
+ }
+ close()
+ })
+}
diff --git a/app/src/main/java/com/kaushalvasava/app/composeui/screen/ProductDetailScreen.kt b/app/src/main/java/com/kaushalvasava/app/composeui/screen/ProductDetailScreen.kt
index f58c451..4e9d90e 100644
--- a/app/src/main/java/com/kaushalvasava/app/composeui/screen/ProductDetailScreen.kt
+++ b/app/src/main/java/com/kaushalvasava/app/composeui/screen/ProductDetailScreen.kt
@@ -61,6 +61,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
+import com.kaushalvasava.app.composeui.ui.navigation.NavigationItem
import kotlinx.coroutines.delay
@Preview
@@ -373,7 +374,9 @@ fun ProductDetailScreen(
colors = ButtonDefaults.buttonColors(
containerColor = Color.Blue
),
- onClick = {}
+ onClick = {
+ navController.navigate(NavigationItem.ORDERS)
+ }
) {
Icon(Icons.Rounded.ShoppingCart, contentDescription = null, tint = Color.White)
Text("Add to Cart")
diff --git a/app/src/main/java/com/kaushalvasava/app/composeui/ui/navigation/AppNavHost.kt b/app/src/main/java/com/kaushalvasava/app/composeui/ui/navigation/AppNavHost.kt
index 0f37c05..528e499 100644
--- a/app/src/main/java/com/kaushalvasava/app/composeui/ui/navigation/AppNavHost.kt
+++ b/app/src/main/java/com/kaushalvasava/app/composeui/ui/navigation/AppNavHost.kt
@@ -9,6 +9,9 @@ import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
+import com.kaushalvasava.app.composeui.screen.AuthenticationScreen
+import com.kaushalvasava.app.composeui.screen.OrderScreen
+import com.kaushalvasava.app.composeui.screen.OrderTrackingScreen
import com.kaushalvasava.app.composeui.screen.ProductDetailScreen
import com.kaushalvasava.app.composeui.screen.ProductsScreen
@@ -16,7 +19,7 @@ import com.kaushalvasava.app.composeui.screen.ProductsScreen
fun AppNavHost(
modifier: Modifier = Modifier,
navController: NavHostController,
- startDestination: String = NavigationItem.PRODUCTS,
+ startDestination: String = NavigationItem.ORDERS,
) {
NavHost(
modifier = modifier,
@@ -47,6 +50,9 @@ fun AppNavHost(
)
}
) {
+ composable(NavigationItem.AUTHENTICATION) {
+ AuthenticationScreen(navController)
+ }
composable(NavigationItem.PRODUCTS) {
ProductsScreen(navController)
}
@@ -59,5 +65,11 @@ fun AppNavHost(
if (productId != null)
ProductDetailScreen(productId = productId, navController = navController)
}
+ composable(NavigationItem.ORDERS) {
+ OrderScreen(navController)
+ }
+ composable(NavigationItem.ORDER_TRACKING) {
+ OrderTrackingScreen()
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/kaushalvasava/app/composeui/ui/navigation/NavigationItem.kt b/app/src/main/java/com/kaushalvasava/app/composeui/ui/navigation/NavigationItem.kt
index 6f75455..302f233 100644
--- a/app/src/main/java/com/kaushalvasava/app/composeui/ui/navigation/NavigationItem.kt
+++ b/app/src/main/java/com/kaushalvasava/app/composeui/ui/navigation/NavigationItem.kt
@@ -3,4 +3,7 @@ package com.kaushalvasava.app.composeui.ui.navigation
object NavigationItem {
const val PRODUCTS = "products"
const val PRODUCT_DETAILS = "product_details"
+ const val AUTHENTICATION = "authentication"
+ const val ORDERS = "orders"
+ const val ORDER_TRACKING = "order_tracking"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/kaushalvasava/app/composeui/util/ValidUtil.kt b/app/src/main/java/com/kaushalvasava/app/composeui/util/ValidUtil.kt
new file mode 100644
index 0000000..135e703
--- /dev/null
+++ b/app/src/main/java/com/kaushalvasava/app/composeui/util/ValidUtil.kt
@@ -0,0 +1,34 @@
+package com.kaushalvasava.app.composeui.util
+
+import android.util.Patterns
+import java.util.regex.Pattern
+
+object ValidUtil {
+
+ fun isValidEmail(email: String): Boolean {
+ val pattern: Pattern = Patterns.EMAIL_ADDRESS
+ return pattern.matcher(email).matches()
+ }
+
+ fun isValidName(name: String): Boolean {
+ val pattern: Pattern =
+ Pattern.compile("^([a-zA-Z]{2,}\\s[a-zA-Z]+'?-?[a-zA-Z]{2,}\\s?([a-zA-Z]+)?)")
+ return pattern.matcher(name).matches()
+ }
+
+
+ fun isValidPasswordFormat(password: String): Boolean {
+ val passwordREGEX = Pattern.compile(
+ "^" +
+ "(?=.*[0-9])" + //at least 1 digit
+ "(?=.*[a-z])" + //at least 1 lower case letter
+ "(?=.*[A-Z])" + //at least 1 upper case letter
+ "(?=.*[a-zA-Z])" + //any letter
+ "(?=.*[@#$%^&+=])" + //at least 1 special character
+ "(?=\\S+$)" + //no white spaces
+ ".{10,}" + //at least 8 characters
+ "$"
+ )
+ return passwordREGEX.matcher(password).matches()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_facebook.xml b/app/src/main/res/drawable/ic_facebook.xml
new file mode 100644
index 0000000..b60ee8a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_facebook.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_google.xml b/app/src/main/res/drawable/ic_google.xml
new file mode 100644
index 0000000..61448dd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_google.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_location.xml b/app/src/main/res/drawable/ic_location.xml
new file mode 100644
index 0000000..7eb4ae9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_location.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_visibility.xml b/app/src/main/res/drawable/ic_visibility.xml
new file mode 100644
index 0000000..f843e29
--- /dev/null
+++ b/app/src/main/res/drawable/ic_visibility.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_visibility_off.xml b/app/src/main/res/drawable/ic_visibility_off.xml
new file mode 100644
index 0000000..5993ca3
--- /dev/null
+++ b/app/src/main/res/drawable/ic_visibility_off.xml
@@ -0,0 +1,5 @@
+
+
+
+
+