diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6df302c..ae26265 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,9 +14,10 @@ android:supportsRtl="false" android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> + + android:theme="@style/AppTheme.SplashTheme"> @@ -31,38 +32,34 @@ android:name=".ui.drinkdetails.DrinkDetailsActivity" android:configChanges="orientation|keyboardHidden" android:parentActivityName=".ui.main.MainActivity" - android:screenOrientation="portrait" /> + android:screenOrientation="portrait" + android:theme="@style/AppTheme.TranslucentStatus" /> - + android:screenOrientation="portrait" /> - + android:screenOrientation="portrait" /> + android:name=".ui.previousOrders.PreviousOrdersActivity" + android:screenOrientation="portrait" + android:parentActivityName=".ui.profile.ProfileActivity"/> + diff --git a/app/src/main/java/com/marknkamau/justjava/data/models/Library.kt b/app/src/main/java/com/marknkamau/justjava/data/models/Library.kt deleted file mode 100644 index c0c9371..0000000 --- a/app/src/main/java/com/marknkamau/justjava/data/models/Library.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.marknkamau.justjava.data.models - -/** - * Created by MarkNjunge. - * mark.kamau@outlook.com - * https://github.com/MarkNjunge - */ - -data class Library(val name: String, val author: String, val license: Int, val link: String) { - companion object { - const val MIT = 1 - const val APACHE2 = 2 - } - - val licenseText: String - get() = when (license) { - MIT -> "MIT" - APACHE2 -> "Apache-2.0" - else -> "Unknown" - } -} \ No newline at end of file diff --git a/app/src/main/java/com/marknkamau/justjava/di/Modules.kt b/app/src/main/java/com/marknkamau/justjava/di/Modules.kt index fde5b16..24161c5 100644 --- a/app/src/main/java/com/marknkamau/justjava/di/Modules.kt +++ b/app/src/main/java/com/marknkamau/justjava/di/Modules.kt @@ -7,16 +7,16 @@ import com.marknkamau.justjava.data.local.PreferencesRepository import com.marknkamau.justjava.data.local.PreferencesRepositoryImpl import com.marknkamau.justjava.ui.cart.CartPresenter import com.marknkamau.justjava.ui.cart.CartView -import com.marknkamau.justjava.ui.checkout.CheckoutPresenter -import com.marknkamau.justjava.ui.checkout.CheckoutView import com.marknkamau.justjava.ui.drinkdetails.DrinkDetailsPresenter import com.marknkamau.justjava.ui.drinkdetails.DrinkDetailsView import com.marknkamau.justjava.ui.login.LogInPresenter import com.marknkamau.justjava.ui.login.LogInView import com.marknkamau.justjava.ui.main.MainPresenter import com.marknkamau.justjava.ui.main.MainView -import com.marknkamau.justjava.ui.previousOrder.PreviousOrderPresenter -import com.marknkamau.justjava.ui.previousOrder.PreviousOrderView +import com.marknkamau.justjava.ui.viewOrder.ViewOrderPresenter +import com.marknkamau.justjava.ui.viewOrder.ViewOrderView +import com.marknkamau.justjava.ui.previousOrders.PreviousOrdersPresenter +import com.marknkamau.justjava.ui.previousOrders.PreviousOrdersView import com.marknkamau.justjava.ui.profile.ProfilePresenter import com.marknkamau.justjava.ui.profile.ProfileView import com.marknkamau.justjava.ui.signup.SignUpPresenter @@ -35,8 +35,8 @@ val appModule = module { factory { (view: SignUpView) -> SignUpPresenter(view, get(), get(), get(), Dispatchers.Main) } factory { (view: MainView) -> MainPresenter(view, Dispatchers.Main) } factory { (view: DrinkDetailsView) -> DrinkDetailsPresenter(view, get(), Dispatchers.Main) } - factory { (view: CartView) -> CartPresenter(view, get(), Dispatchers.Main) } - factory { (view: CheckoutView) -> CheckoutPresenter(view, get(), get(), get(), get(), Dispatchers.Main) } - factory { (view: PreviousOrderView) -> PreviousOrderPresenter(view, get(), get(), get(), Dispatchers.Main) } + factory { (view: CartView) -> CartPresenter(view, get(), get(), get(), get(), Dispatchers.Main) } + factory { (view: ViewOrderView) -> ViewOrderPresenter(view, get(), get(), get(), Dispatchers.Main) } factory { (view: ProfileView) -> ProfilePresenter(view, get(), get(), get(), get(), Dispatchers.Main) } + factory { (view: PreviousOrdersView) -> PreviousOrdersPresenter(view, get(), get(), Dispatchers.Main) } } \ No newline at end of file diff --git a/app/src/main/java/com/marknkamau/justjava/ui/BaseActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/BaseActivity.kt index 42ea165..242247c 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/BaseActivity.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/BaseActivity.kt @@ -1,18 +1,15 @@ package com.marknkamau.justjava.ui import android.content.Intent - -import androidx.appcompat.app.AppCompatActivity import android.view.Menu import android.view.MenuItem import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity import com.marknjunge.core.auth.AuthService -import com.marknkamau.justjava.JustJavaApp import com.marknkamau.justjava.R import com.marknkamau.justjava.data.local.PreferencesRepository import com.marknkamau.justjava.ui.about.AboutActivity import com.marknkamau.justjava.ui.cart.CartActivity -import com.marknkamau.justjava.ui.checkout.CheckoutActivity import com.marknkamau.justjava.ui.login.LogInActivity import com.marknkamau.justjava.ui.profile.ProfileActivity import org.koin.android.ext.android.inject @@ -30,22 +27,14 @@ abstract class BaseActivity : AppCompatActivity() { override fun onPrepareOptionsMenu(menu: Menu?): Boolean { super.onPrepareOptionsMenu(menu) - if (this is CartActivity || this is CheckoutActivity) { + if (this is CartActivity) { menu?.findItem(R.id.menu_cart)?.isVisible = false } if (this is ProfileActivity) { menu?.findItem(R.id.menu_profile)?.isVisible = false } - if (authService.isSignedIn()) { - menu?.findItem(R.id.menu_login)?.isVisible = false -// menu?.findItem(R.id.menu_profile)?.isVisible = true - menu?.findItem(R.id.menu_logout)?.isVisible = true - } else { - menu?.findItem(R.id.menu_login)?.isVisible = true -// menu?.findItem(R.id.menu_profile)?.isVisible = false - menu?.findItem(R.id.menu_logout)?.isVisible = false - } + menu?.findItem(R.id.menu_logout)?.isVisible = authService.isSignedIn() return true } @@ -55,10 +44,6 @@ abstract class BaseActivity : AppCompatActivity() { startActivity(Intent(this, CartActivity::class.java)) return true } - R.id.menu_login -> { - startActivity(Intent(this, LogInActivity::class.java)) - return true - } R.id.menu_profile -> { if (authService.isSignedIn()) { startActivity(Intent(this, ProfileActivity::class.java)) @@ -71,9 +56,10 @@ abstract class BaseActivity : AppCompatActivity() { invalidateOptionsMenu() preferencesRepository.clearUserDetails() authService.logOut() - // If this is ProfileActivity + // If this is ProfileActivity, leave it (this as? ProfileActivity)?.finish() Toast.makeText(this, "Logged out", Toast.LENGTH_SHORT).show() + onLoggedOut() return true } R.id.menu_about -> { @@ -84,4 +70,6 @@ abstract class BaseActivity : AppCompatActivity() { } } + open fun onLoggedOut(){} + } diff --git a/app/src/main/java/com/marknkamau/justjava/ui/about/AboutActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/about/AboutActivity.kt index 88c8807..8c6b7da 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/about/AboutActivity.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/about/AboutActivity.kt @@ -1,43 +1,33 @@ package com.marknkamau.justjava.ui.about +import android.annotation.SuppressLint import android.content.Intent import android.net.Uri import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity import android.view.View +import androidx.appcompat.app.AppCompatActivity import com.marknkamau.justjava.BuildConfig import com.marknkamau.justjava.R -import com.marknkamau.justjava.ui.libraries.LibrariesActivity import kotlinx.android.synthetic.main.activity_about.* -class AboutActivity : AppCompatActivity(), View.OnClickListener { +class AboutActivity : AppCompatActivity() { + @SuppressLint("SetTextI18n") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_about) - tvVersion.text = "v${BuildConfig.VERSION_NAME}" - - tvSource.setOnClickListener(this) - imgBack.setOnClickListener(this) - imgMail.setOnClickListener(this) - imgLinkedin.setOnClickListener(this) - imgGithub.setOnClickListener(this) - imgWebsite.setOnClickListener(this) - tvPrivacyPolicy.setOnClickListener(this) - tvLibraries.setOnClickListener { startActivity(Intent(this, LibrariesActivity::class.java)) } - } - - override fun onClick(view: View) { - when (view) { - tvSource -> openUrl("https://github.com/MarkNjunge/JustJava-Android") - imgBack -> finish() - imgMail -> sendEmail() - imgLinkedin -> openUrl("https://linkedin.com/in/marknjunge") - imgGithub -> openUrl("https://github.com/MarkNjunge") - imgWebsite -> openUrl("https://marknjunge.com") - tvPrivacyPolicy -> openUrl("https://marknjunge.com/justjava/privacy") - } + imgBackAbout.setOnClickListener { finish() } + tvAppVersionAbout.text = "v${BuildConfig.VERSION_NAME} ${if (BuildConfig.BUILD_TYPE == "debug") "(debug)" else ""}" + tvSourceCodeAbout.setOnClickListener { openUrl("https://github.com/MarkNjunge/JustJava-Android") } + imgEmailAbout.setOnClickListener { sendEmail() } + imgLinkedInAbout.setOnClickListener { openUrl("https://linkedin.com/in/marknjunge") } + imgWebsiteAbout.setOnClickListener { openUrl("https://marknjunge.com") } + imgGithubAbout.setOnClickListener { openUrl("https://github.com/MarkNjunge") } + tvPrivacyPolicyAbout.setOnClickListener { openUrl("https://marknjunge.com/justjava/privacy") } + + // See https://github.com/google/play-services-plugins/pull/62 + tvLicensesAbout.visibility = View.GONE } private fun openUrl(url: String) = startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) diff --git a/app/src/main/java/com/marknkamau/justjava/ui/cart/CartActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/cart/CartActivity.kt index 6e89f37..716364a 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/cart/CartActivity.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/cart/CartActivity.kt @@ -1,30 +1,46 @@ package com.marknkamau.justjava.ui.cart +import android.annotation.SuppressLint import android.content.Intent import android.os.Bundle import android.view.View -import android.widget.LinearLayout import android.widget.Toast -import androidx.recyclerview.widget.DividerItemDecoration +import androidx.appcompat.app.AlertDialog +import androidx.core.app.TaskStackBuilder import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.transition.TransitionManager +import com.marknjunge.core.model.Order +import com.marknjunge.core.model.UserDetails import com.marknkamau.justjava.R -import com.marknkamau.justjava.data.local.CartDao import com.marknkamau.justjava.data.models.CartItem import com.marknkamau.justjava.ui.BaseActivity -import com.marknkamau.justjava.ui.checkout.CheckoutActivity +import com.marknkamau.justjava.ui.login.LogInActivity +import com.marknkamau.justjava.ui.main.MainActivity +import com.marknkamau.justjava.ui.signup.SignUpActivity +import com.marknkamau.justjava.ui.viewOrder.ViewOrderActivity +import com.marknkamau.justjava.utils.BaseRecyclerViewAdapter +import com.marknkamau.justjava.utils.DividerItemDecorator +import com.marknkamau.justjava.utils.onTextChanged +import com.marknkamau.justjava.utils.trimmedText import kotlinx.android.synthetic.main.activity_cart.* -import kotlinx.coroutines.Dispatchers +import kotlinx.android.synthetic.main.content_toolbar.* +import kotlinx.android.synthetic.main.item_order_item.view.* import org.koin.android.ext.android.inject import org.koin.core.parameter.parametersOf class CartActivity : BaseActivity(), CartView { + private val presenter: CartPresenter by inject { parametersOf(this) } - private lateinit var adapter: CartAdapter + private lateinit var adapter: BaseRecyclerViewAdapter + private var payMpesa = true + @SuppressLint("SetTextI18n") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_cart) + setSupportActionBar(toolbar) + supportActionBar?.title = getString(R.string.cart) presenter.loadItems() @@ -39,43 +55,137 @@ class CartActivity : BaseActivity(), CartView { } } - adapter = CartAdapter(this) { cartItem -> - editCartDialog.arguments = Bundle().apply { - putParcelable(EditCartDialog.CART_ITEM, cartItem) + adapter = BaseRecyclerViewAdapter(R.layout.item_order_item) { cartItem -> + tvItemNameItem.text = cartItem.itemName + tvItemQtyItem.text = "${cartItem.itemQty}x" + tvItemPriceItem.text = context.getString(R.string.price_listing, cartItem.itemPrice) + + val toppings = mutableListOf() + + if (cartItem.itemCinnamon) toppings.add("Cinnamon") + if (cartItem.itemChoc) toppings.add("Chocolate") + if (cartItem.itemMarshmallow) toppings.add("Marshmallows") + + if (toppings.isNotEmpty()) { + tvToppingsItem.visibility = View.VISIBLE + tvToppingsItem.text = toppings.joinToString(", ") + } else { + tvToppingsItem.visibility = View.GONE + } + orderItemRootLayout.setOnClickListener { + editCartDialog.arguments = Bundle().apply { + putParcelable(EditCartDialog.CART_ITEM, cartItem) + } + editCartDialog.show(supportFragmentManager, "edit_cart_dialog") } - editCartDialog.show(supportFragmentManager, "edit_cart_dialog") } + rvCart.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) - rvCart.addItemDecoration(DividerItemDecoration(this, LinearLayout.VERTICAL)) + val dividerItemDecorator = DividerItemDecorator(getDrawable(R.drawable.custom_item_divider)!!) + rvCart.addItemDecoration(dividerItemDecorator) rvCart.adapter = adapter + tvPaymentMethodCart.text = "M-Pesa" + + etAddressCart.onTextChanged { tilAddressCart.error = null } + btnClearCart.setOnClickListener { presenter.clearCart() } - btnCheckout.setOnClickListener { - startActivity(Intent(this@CartActivity, CheckoutActivity::class.java)) + btnChangePaymentMethodCart.setOnClickListener { + AlertDialog.Builder(this) + .setTitle(R.string.payment_method) + .setItems(arrayOf("M-Pesa", "Cash on Delivery")) { _, which -> + if (which == 0) { + payMpesa = true + tvPaymentMethodCart.text = "M-Pesa" + } else { + payMpesa = false + tvPaymentMethodCart.text = "Cash on Delivery" + } + } + .create() + .show() + + } + + btnLoginCart.setOnClickListener { startActivity(Intent(this, LogInActivity::class.java)) } + btnSignUpCart.setOnClickListener { startActivity(Intent(this, SignUpActivity::class.java)) } + + btnPlaceOrder.setOnClickListener { + if (etAddressCart.trimmedText.isEmpty()) { + etAddressCart.error = getString(R.string.required) + return@setOnClickListener + } + presenter.placeOrder(etAddressCart.trimmedText, etCommentsCart.trimmedText, payMpesa) } } + override fun onResume() { + super.onResume() + presenter.getSignInStatus() + } + override fun onDestroy() { super.onDestroy() presenter.cancel() } + override fun onLoggedOut() { + setDisplayToLoggedOut() + } + + override fun setDisplayToLoggedIn(userDetails: UserDetails) { + TransitionManager.beginDelayedTransition(cartActivityRootLayout) + layoutCartSignedIn.visibility = View.VISIBLE + layoutCartSignedOut.visibility = View.GONE + etAddressCart.setText(userDetails.address) + } + + override fun setDisplayToLoggedOut() { + TransitionManager.beginDelayedTransition(cartActivityRootLayout) + layoutCartSignedIn.visibility = View.GONE + layoutCartSignedOut.visibility = View.VISIBLE + } + override fun displayCart(orderItems: MutableList) { - tvNoItems.visibility = View.GONE + TransitionManager.beginDelayedTransition(cartActivityRootLayout) + layoutCartContent.visibility = View.VISIBLE + layoutCartEmpty.visibility = View.GONE adapter.setItems(orderItems) - btnCheckout.isEnabled = true } - override fun displayCartTotal(totalCost: Int) { - tvCartTotal.text = getString(R.string.price_listing, totalCost) + override fun displayEmptyCart() { + TransitionManager.beginDelayedTransition(cartActivityRootLayout) + layoutCartContent.visibility = View.GONE + layoutCartEmpty.visibility = View.VISIBLE } - override fun displayEmptyCart() { - tvNoItems.visibility = View.VISIBLE - groupCartNotEmpty.visibility = View.GONE + override fun displayCartTotal(total: Int) { + tvTotalCart.text = getString(R.string.price_listing, total) + } + + override fun showLoadingBar() { + btnPlaceOrder.isEnabled = false + pbLoadingCart.visibility = View.VISIBLE + } + + override fun hideLoadingBar() { + btnPlaceOrder.isEnabled = true + pbLoadingCart.visibility = View.GONE + } + + override fun finishActivity(order: Order) { + val i = Intent(this, ViewOrderActivity::class.java) + i.putExtra(ViewOrderActivity.ORDER_KEY, order) + + TaskStackBuilder.create(this) + .addNextIntentWithParentStack(Intent(this, MainActivity::class.java)) + .addNextIntentWithParentStack(i) + .startActivities() + + finish() } override fun displayMessage(message: String?) = Toast.makeText(this, message, Toast.LENGTH_SHORT).show() diff --git a/app/src/main/java/com/marknkamau/justjava/ui/cart/CartAdapter.kt b/app/src/main/java/com/marknkamau/justjava/ui/cart/CartAdapter.kt deleted file mode 100644 index aff4164..0000000 --- a/app/src/main/java/com/marknkamau/justjava/ui/cart/CartAdapter.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.marknkamau.justjava.ui.cart - -import android.content.Context -import androidx.recyclerview.widget.RecyclerView -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup - -import com.marknkamau.justjava.R -import com.marknkamau.justjava.data.models.CartItem - -import kotlinx.android.synthetic.main.item_cart.view.* - -class CartAdapter(private val context: Context, private val onEditClick: (CartItem) -> Unit) : androidx.recyclerview.widget.RecyclerView.Adapter() { - private val items by lazy { mutableListOf() } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.item_cart)) - - override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position], context, onEditClick) - - override fun getItemCount() = items.size - - fun setItems(items: MutableList) { - this.items.clear() - this.items.addAll(items) - notifyDataSetChanged() - } - - class ViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) { - fun bind(item: CartItem, context: Context, onEditClick: (CartItem) -> Unit) { - itemView.tvItemName.text = item.itemName - itemView.tvItemQty.text = context.getString(R.string.quantity_listing, item.itemQty) - itemView.tvItemPrice.text = context.getString(R.string.price_listing, item.itemPrice) - - val toppings = mutableListOf() - - if (item.itemCinnamon) - toppings.add("Cinnamon") - - if (item.itemChoc) - toppings.add("Chocolate") - - if (item.itemMarshmallow) - toppings.add("Marshmallows") - - if (toppings.isNotEmpty()) { - itemView.tvToppings.text = toppings.toString().replace("[", "").replace("]", "") - itemView.tvToppings.visibility = View.VISIBLE - } else { - itemView.tvToppings.visibility = View.GONE - } - - itemView.setOnClickListener { onEditClick(item) } - } - } - - private fun ViewGroup.inflate(layoutRes: Int): View { - return LayoutInflater.from(context).inflate(layoutRes, this, false) - } -} diff --git a/app/src/main/java/com/marknkamau/justjava/ui/cart/CartPresenter.kt b/app/src/main/java/com/marknkamau/justjava/ui/cart/CartPresenter.kt index d997975..b6b210d 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/cart/CartPresenter.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/cart/CartPresenter.kt @@ -1,18 +1,35 @@ package com.marknkamau.justjava.ui.cart import android.annotation.SuppressLint +import com.marknjunge.core.auth.AuthService +import com.marknjunge.core.data.firebase.OrderService +import com.marknjunge.core.model.Order +import com.marknjunge.core.model.OrderItem import com.marknkamau.justjava.data.local.CartDao +import com.marknkamau.justjava.data.local.PreferencesRepository import com.marknkamau.justjava.data.models.CartItem import com.marknkamau.justjava.ui.BasePresenter import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.launch import timber.log.Timber +import java.util.* internal class CartPresenter(private val view: CartView, + private val auth: AuthService, + private val preferences: PreferencesRepository, private val cart: CartDao, + private val orderService: OrderService, mainDispatcher: CoroutineDispatcher ) : BasePresenter(mainDispatcher) { + fun getSignInStatus() { + if (auth.isSignedIn()) { + view.setDisplayToLoggedIn(preferences.getUserDetails()) + } else { + view.setDisplayToLoggedOut() + } + } + fun loadItems() { uiScope.launch { try { @@ -56,6 +73,35 @@ internal class CartPresenter(private val view: CartView, loadItems() } } + + fun placeOrder(address: String, comments: String, payMpesa: Boolean) { + view.showLoadingBar() + + uiScope.launch { + + try { + val (order, orderItems) = createOrderObject(address, comments, payMpesa) + orderService.placeNewOrder(order, orderItems) + + cart.deleteAll() + view.hideLoadingBar() + view.displayMessage("Order placed") + view.finishActivity(order) + } catch (e: Exception) { + view.hideLoadingBar() + view.displayMessage(e.message) + } + } + } + + private suspend fun createOrderObject(address: String, comments: String, payMpesa: Boolean): Pair> { + val orderId = UUID.randomUUID().toString().replace("-", "").subSequence(0, 10).toString().toUpperCase() + val paymentMethod = if (payMpesa) "mpesa" else "cash" + + val orderItems = cart.getAll().map { it.toOrderItem() } + val total = orderItems.fold(0, { acc, orderItem -> acc + orderItem.itemPrice }) + return Pair(Order(orderId, auth.getCurrentUser().userId, orderItems.size, total, address, comments, paymentMethod = paymentMethod),orderItems) + } } diff --git a/app/src/main/java/com/marknkamau/justjava/ui/cart/CartView.kt b/app/src/main/java/com/marknkamau/justjava/ui/cart/CartView.kt index 9f21131..021e011 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/cart/CartView.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/cart/CartView.kt @@ -1,10 +1,17 @@ package com.marknkamau.justjava.ui.cart +import com.marknjunge.core.model.Order +import com.marknjunge.core.model.UserDetails import com.marknkamau.justjava.data.models.CartItem import com.marknkamau.justjava.ui.BaseView internal interface CartView : BaseView{ + fun setDisplayToLoggedIn(userDetails: UserDetails) + fun setDisplayToLoggedOut() fun displayCart(orderItems: MutableList) fun displayEmptyCart() - fun displayCartTotal(totalCost: Int) + fun displayCartTotal(total: Int) + fun showLoadingBar() + fun hideLoadingBar() + fun finishActivity(order: Order) } diff --git a/app/src/main/java/com/marknkamau/justjava/ui/cart/EditCartDialog.kt b/app/src/main/java/com/marknkamau/justjava/ui/cart/EditCartDialog.kt index 081f411..225f5cc 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/cart/EditCartDialog.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/cart/EditCartDialog.kt @@ -49,8 +49,8 @@ class EditCartDialog : DialogFragment(), View.OnClickListener { tvDrinkName = view.findViewById(R.id.tvDrinkName) as TextView tvQuantity = view.findViewById(R.id.tvQuantity) as TextView - cbCinnamon = view.findViewById(R.id.cbCinnamon) as CheckBox - cbChocolate = view.findViewById(R.id.cbChocolate) as CheckBox + cbCinnamon = view.findViewById(R.id.cbCinnamonDetail) as CheckBox + cbChocolate = view.findViewById(R.id.cbChocolateDetail) as CheckBox cbMarshmallows = view.findViewById(R.id.cbMarshmallows) as CheckBox imgMinusQty = view.findViewById(R.id.imgMinusQty) as ImageView imgAddQty = view.findViewById(R.id.imgAddQty) as ImageView diff --git a/app/src/main/java/com/marknkamau/justjava/ui/checkout/CheckoutActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/checkout/CheckoutActivity.kt deleted file mode 100644 index 18642e3..0000000 --- a/app/src/main/java/com/marknkamau/justjava/ui/checkout/CheckoutActivity.kt +++ /dev/null @@ -1,140 +0,0 @@ -package com.marknkamau.justjava.ui.checkout - -import android.content.Context -import android.content.Intent -import android.net.ConnectivityManager -import android.os.Bundle -import androidx.core.app.TaskStackBuilder -import android.text.TextUtils -import android.view.View -import android.widget.RadioButton -import android.widget.Toast -import com.marknkamau.justjava.R -import com.marknjunge.core.model.Order -import com.marknjunge.core.model.UserDetails -import com.marknkamau.justjava.ui.BaseActivity -import com.marknkamau.justjava.ui.login.LogInActivity -import com.marknkamau.justjava.ui.main.MainActivity -import com.marknkamau.justjava.ui.previousOrder.PreviousOrderActivity -import com.marknkamau.justjava.utils.trimmedText -import kotlinx.android.synthetic.main.activity_checkout.* -import org.koin.android.ext.android.inject -import org.koin.core.parameter.parametersOf -import java.util.* - -class CheckoutActivity : BaseActivity(), CheckoutView { - private lateinit var name: String - private lateinit var phone: String - private lateinit var address: String - private lateinit var comments: String - - private val presenter: CheckoutPresenter by inject { parametersOf(this) } - - private var payCash = true - private val orderId = UUID.randomUUID().toString().replace("-", "").subSequence(0, 10).toString() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_checkout) - supportActionBar?.title = "Checkout" - - rgPayment.setOnCheckedChangeListener { _, checkedId -> - val text = findViewById(checkedId).text - payCash = text == getString(R.string.cash_on_delivery) - } - - btnPlaceOrder.setOnClickListener { - if (canConnectToInternet()) { - placeOder() - } else { - Toast.makeText(this, getString(R.string.check_your_internet_connection), Toast.LENGTH_SHORT).show() - } - } - - } - - override fun onResume() { - super.onResume() - presenter.getSignInStatus() - } - - override fun onDestroy() { - super.onDestroy() - presenter.cancel() - } - - private fun placeOder() { - if (validateInput()) { - presenter.placeOrder(orderId, address, comments, payCash) - } - } - - override fun setDisplayToLoggedIn(userDetails: UserDetails) { - etName.setText(userDetails.name) - etPhone.setText(userDetails.phone) - etDeliveryAddress.setText(userDetails.address) - } - - override fun invalidateMenu() { - invalidateOptionsMenu() - } - - override fun setDisplayToLoggedOut() { - startActivity(Intent(this, LogInActivity::class.java)) - finish() - } - - override fun showUploadBar() { - pbSavingProfile.visibility = View.VISIBLE - btnPlaceOrder.isEnabled = false - } - - override fun hideUploadBar() { - pbSavingProfile.visibility = View.INVISIBLE - btnPlaceOrder.isEnabled = true - } - - override fun finishActivity(order: Order) { - val i = Intent(this, PreviousOrderActivity::class.java) - i.putExtra(PreviousOrderActivity.ORDER_KEY, order) - - TaskStackBuilder.create(this) - .addNextIntentWithParentStack(Intent(this, MainActivity::class.java)) - .addNextIntentWithParentStack(i) - .startActivities() - - finish() - } - - override fun displayMessage(message: String?) { - Toast.makeText(this, message, Toast.LENGTH_SHORT).show() - } - - private fun validateInput(): Boolean { - name = etName.trimmedText - phone = etPhone.trimmedText - address = etDeliveryAddress.trimmedText - comments = etComments.trimmedText - - var returnValue = true - if (TextUtils.isEmpty(name)) { - etName.error = getString(R.string.required) - returnValue = false - } - if (TextUtils.isEmpty(phone)) { - etPhone.error = getString(R.string.required) - returnValue = false - } - if (TextUtils.isEmpty(address)) { - etDeliveryAddress.error = getString(R.string.required) - returnValue = false - } - return returnValue - } - - private fun canConnectToInternet(): Boolean { - val connectivityManager = applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - val activeNetwork = connectivityManager.activeNetworkInfo - return activeNetwork != null && activeNetwork.isConnected - } -} diff --git a/app/src/main/java/com/marknkamau/justjava/ui/checkout/CheckoutPresenter.kt b/app/src/main/java/com/marknkamau/justjava/ui/checkout/CheckoutPresenter.kt deleted file mode 100644 index 9c18449..0000000 --- a/app/src/main/java/com/marknkamau/justjava/ui/checkout/CheckoutPresenter.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.marknkamau.justjava.ui.checkout - -import com.marknjunge.core.auth.AuthService -import com.marknjunge.core.data.firebase.OrderService -import com.marknkamau.justjava.data.local.CartDao -import com.marknkamau.justjava.data.local.PreferencesRepository -import com.marknjunge.core.model.OrderItem -import com.marknjunge.core.model.Order -import com.marknkamau.justjava.data.models.CartItem -import com.marknkamau.justjava.ui.BasePresenter -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.launch - -internal class CheckoutPresenter(private val view: CheckoutView, - private val auth: AuthService, - private val preferences: PreferencesRepository, - private val orderService: OrderService, - private val cart: CartDao, - mainDispatcher: CoroutineDispatcher -) : BasePresenter(mainDispatcher) { - - fun getSignInStatus() { - if (auth.isSignedIn()) { - view.setDisplayToLoggedIn(preferences.getUserDetails()) - } else { - view.setDisplayToLoggedOut() - } - } - - fun placeOrder(orderId: String, address: String, comments: String, payCash: Boolean) { - val paymentMethod = if (payCash) "cash" else "mpesa" - val order = Order(orderId, auth.getCurrentUser().userId, 0, 0, address, comments, paymentMethod = paymentMethod) - view.showUploadBar() - - uiScope.launch { - val items = cart.getAll() - placeOrderInternal(items, order) - } - } - - private fun placeOrderInternal(items: MutableList, order: Order) { - val itemsCount = items.size - var total = 0 - items.forEach { item -> total += item.itemPrice } - - order.itemsCount = itemsCount - order.totalPrice = total - - val orderItems = mutableListOf() - items.forEach { - orderItems.add(it.toOrderItem()) - } - - uiScope.launch { - try { - orderService.placeNewOrder(order, orderItems) - - cart.deleteAll() - view.hideUploadBar() - view.displayMessage("Order placed") - view.finishActivity(order) - } catch (e: Exception) { - view.hideUploadBar() - view.displayMessage(e.message) - } - } - } -} diff --git a/app/src/main/java/com/marknkamau/justjava/ui/checkout/CheckoutView.kt b/app/src/main/java/com/marknkamau/justjava/ui/checkout/CheckoutView.kt deleted file mode 100644 index 89f5aac..0000000 --- a/app/src/main/java/com/marknkamau/justjava/ui/checkout/CheckoutView.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.marknkamau.justjava.ui.checkout - -import com.marknjunge.core.model.Order -import com.marknjunge.core.model.UserDetails -import com.marknkamau.justjava.ui.BaseView - -interface CheckoutView : BaseView { - fun invalidateMenu() - fun setDisplayToLoggedIn(userDetails: UserDetails) - fun setDisplayToLoggedOut() - fun showUploadBar() - fun hideUploadBar() - fun finishActivity(order: Order) -} diff --git a/app/src/main/java/com/marknkamau/justjava/ui/drinkdetails/DrinkDetailsActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/drinkdetails/DrinkDetailsActivity.kt index a8a0e41..3f319f1 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/drinkdetails/DrinkDetailsActivity.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/drinkdetails/DrinkDetailsActivity.kt @@ -1,26 +1,41 @@ package com.marknkamau.justjava.ui.drinkdetails +import android.animation.AnimatorSet +import android.animation.ObjectAnimator +import android.animation.PropertyValuesHolder +import android.app.Activity +import android.content.Context +import android.content.Intent import android.os.Bundle +import android.util.TypedValue import android.view.View import android.widget.Toast - -import com.marknkamau.justjava.R +import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityOptionsCompat +import androidx.core.util.Pair +import com.marknjunge.core.data.local.DrinksProvider import com.marknjunge.core.model.CoffeeDrink -import com.marknkamau.justjava.data.local.CartDao +import com.marknkamau.justjava.R import com.marknkamau.justjava.data.models.CartItem -import com.marknkamau.justjava.ui.BaseActivity import com.squareup.picasso.Picasso - import kotlinx.android.synthetic.main.activity_drink_details.* import kotlinx.android.synthetic.main.content_drink_details.* -import kotlinx.coroutines.Dispatchers import org.koin.android.ext.android.inject import org.koin.core.parameter.parametersOf -class DrinkDetailsActivity : BaseActivity(), DrinkDetailsView, View.OnClickListener { +class DrinkDetailsActivity : AppCompatActivity(), DrinkDetailsView { companion object { - const val DRINK_KEY = "drink_key" + private const val DRINK_KEY = "drink_key" + + fun start(context: Context, drink: CoffeeDrink, vararg sharedElements: Pair) { + val intent = Intent(context, DrinkDetailsActivity::class.java) + intent.putExtra(DRINK_KEY, drink) + + val options = ActivityOptionsCompat.makeSceneTransitionAnimation(context as Activity, *sharedElements) + + context.startActivity(intent, options.toBundle()) + } } private lateinit var drink: CoffeeDrink @@ -33,24 +48,24 @@ class DrinkDetailsActivity : BaseActivity(), DrinkDetailsView, View.OnClickListe drink = intent.extras!!.getParcelable(DRINK_KEY) as CoffeeDrink - tvDrinkName.text = drink.drinkName - tvDrinkContents.text = drink.drinkContents - tvDrinkDescription.text = drink.drinkDescription - tvDrinkPrice.text = resources.getString(R.string.price_listing, drink.drinkPrice.toInt()) - tvSubtotal.text = resources.getString(R.string.price_listing, drink.drinkPrice.toInt()) - - val drinkImage = "file:///android_asset/" + drink.drinkImage - val picasso = Picasso.with(this) - picasso.load(drinkImage).noFade().into(imgDrinkImage) - quantity = 1 - imgMinusQty.setOnClickListener(this) - imgAddQty.setOnClickListener(this) - btnAddToCart.setOnClickListener(this) - cbChocolate.setOnClickListener(this) - cbCinnamon.setOnClickListener(this) - cbMarshmallow.setOnClickListener(this) + tvDrinkNameDetail.text = drink.drinkName + tvDrinkContentsDetail.text = drink.drinkContents + tvDrinkDescriptionDetail.text = drink.drinkDescription + tvDrinkPriceDetail.text = resources.getString(R.string.price_listing, drink.drinkPrice.toInt()) + tvSubtotalDetail.text = resources.getString(R.string.price_listing, drink.drinkPrice.toInt()) + tvQuantityDetail.text = quantity.toString() + val drinkImage = "file:///android_asset/" + drink.drinkImage + Picasso.get().load(drinkImage).noFade().into(imgDrinkImageDetail) + + imgBackDetail.setOnClickListener { finish() } + imgMinusQtyDetail.setOnClickListener { minusQty() } + imgAddQtyDetail.setOnClickListener { addQty() } + btnAddToCart.setOnClickListener { addToCart() } + cbChocolateDetail.setOnClickListener { updateSubtotal() } + cbCinnamonDetail.setOnClickListener { updateSubtotal() } + cbMarshmallowDetail.setOnClickListener { updateSubtotal() } } override fun onDestroy() { @@ -58,17 +73,6 @@ class DrinkDetailsActivity : BaseActivity(), DrinkDetailsView, View.OnClickListe presenter.cancel() } - override fun onClick(view: View) { - when (view) { - imgMinusQty -> minusQty() - imgAddQty -> addQty() - btnAddToCart -> addToCart() - cbCinnamon -> updateSubtotal() - cbChocolate -> updateSubtotal() - cbMarshmallow -> updateSubtotal() - } - } - override fun displayMessage(message: String?) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } @@ -81,9 +85,9 @@ class DrinkDetailsActivity : BaseActivity(), DrinkDetailsView, View.OnClickListe val itemRm = CartItem(0, drink.drinkName, quantity, - cbCinnamon.isChecked, - cbChocolate.isChecked, - cbMarshmallow.isChecked, + cbCinnamonDetail.isChecked, + cbChocolateDetail.isChecked, + cbMarshmallowDetail.isChecked, updateSubtotal() ) @@ -91,32 +95,23 @@ class DrinkDetailsActivity : BaseActivity(), DrinkDetailsView, View.OnClickListe } private fun minusQty() { - if (quantity > 1) { - quantity -= 1 - } - tvQuantity.text = quantity.toString() + if (quantity == 1) return + + quantity -= 1 updateSubtotal() + tvQuantityDetail.text = quantity.toString() } private fun addQty() { quantity += 1 - tvQuantity.text = quantity.toString() updateSubtotal() + tvQuantityDetail.text = quantity.toString() } private fun updateSubtotal(): Int { - var base = Integer.parseInt(drink.drinkPrice) - base *= quantity - if (cbCinnamon.isChecked) { - base += quantity * 100 - } - if (cbChocolate.isChecked) { - base += quantity * 100 - } - if (cbMarshmallow.isChecked) { - base += quantity * 100 - } - tvSubtotal.text = resources.getString(R.string.price_listing, base) - return base + val total = DrinksProvider.calculateTotal(drink, quantity, cbCinnamonDetail.isChecked, cbChocolateDetail.isChecked, cbMarshmallowDetail.isChecked) + tvSubtotalDetail.text = resources.getString(R.string.price_listing, total) + return total } + } diff --git a/app/src/main/java/com/marknkamau/justjava/ui/libraries/LibrariesActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/libraries/LibrariesActivity.kt deleted file mode 100644 index 0a32220..0000000 --- a/app/src/main/java/com/marknkamau/justjava/ui/libraries/LibrariesActivity.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.marknkamau.justjava.ui.libraries - -import android.content.Intent -import android.net.Uri -import androidx.appcompat.app.AppCompatActivity -import android.os.Bundle -import android.widget.LinearLayout -import androidx.recyclerview.widget.RecyclerView -import com.marknkamau.justjava.R -import com.marknkamau.justjava.data.models.Library -import kotlinx.android.synthetic.main.activity_libraries.* - -class LibrariesActivity : AppCompatActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_libraries) - - val libraries = mutableListOf( - Library("Retrofit", "Square", Library.APACHE2, "http://square.github.io/retrofit/"), - Library("Gson", "Google", Library.APACHE2, "https://github.com/google/gson"), - Library("RxJava", "ReactiveX", Library.APACHE2, "https://github.com/ReactiveX/RxJava"), - Library("RxAndroid", "ReactiveX", Library.APACHE2, "https://github.com/ReactiveX/RxAndroid"), - Library("RxKotlin", "ReactiveX", Library.APACHE2, "https://github.com/ReactiveX/RxKotlin"), - Library("Picasso", "Square", Library.APACHE2, "http://square.github.io/picasso/"), - Library("Timber", "Jake Wharton", Library.APACHE2, "https://github.com/JakeWharton/timber"), - Library("Mockito", "Mockito", Library.MIT, "https://github.com/mockito/mockito"), - Library("Mockito-Kotlin", "Niek Haarman", Library.MIT, "https://github.com/nhaarman/mockito-kotlin") - ).sortedBy { it.name } - - rvLibraries.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this, RecyclerView.VERTICAL, false) - rvLibraries.addItemDecoration(androidx.recyclerview.widget.DividerItemDecoration(this, LinearLayout.VERTICAL)) - rvLibraries.adapter = LibrariesAdapter(libraries) { library -> - openUrl(library.link) - } - } - - private fun openUrl(url: String) = startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) -} diff --git a/app/src/main/java/com/marknkamau/justjava/ui/libraries/LibrariesAdapter.kt b/app/src/main/java/com/marknkamau/justjava/ui/libraries/LibrariesAdapter.kt deleted file mode 100644 index 90eb6e1..0000000 --- a/app/src/main/java/com/marknkamau/justjava/ui/libraries/LibrariesAdapter.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.marknkamau.justjava.ui.libraries - -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.marknkamau.justjava.R -import com.marknkamau.justjava.data.models.Library -import kotlinx.android.synthetic.main.item_library.view.* -import java.util.* - -/** - * Created by MarkNjunge. - * mark.kamau@outlook.com - * https://github.com/MarkNjunge - */ - -class LibrariesAdapter(private val data: List, private val onClick: (Library) -> Unit) : androidx.recyclerview.widget.RecyclerView.Adapter() { - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_library, parent, false)) - - override fun getItemCount() = data.size - - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - holder.bind(data[position], onClick) - } - - class ViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) { - fun bind(library: Library, onClick: (Library) -> Unit) { - with(itemView) { - tvName.text = library.name - tvAuthor.text = library.author - tvLicense.text = library.licenseText - - rootLayout.setOnClickListener { onClick(library) } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/marknkamau/justjava/ui/login/LogInActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/login/LogInActivity.kt index b1a750f..de4ac78 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/login/LogInActivity.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/login/LogInActivity.kt @@ -8,12 +8,14 @@ import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.marknkamau.justjava.R import com.marknkamau.justjava.ui.signup.SignUpActivity +import com.marknkamau.justjava.utils.hideKeyboard +import com.marknkamau.justjava.utils.onTextChanged import com.marknkamau.justjava.utils.trimmedText import kotlinx.android.synthetic.main.activity_log_in.* import org.koin.android.ext.android.inject import org.koin.core.parameter.parametersOf -class LogInActivity : AppCompatActivity(), LogInView, View.OnClickListener { +class LogInActivity : AppCompatActivity(), LogInView { private lateinit var email: String private val presenter: LogInPresenter by inject { parametersOf(this) } @@ -23,9 +25,19 @@ class LogInActivity : AppCompatActivity(), LogInView, View.OnClickListener { presenter.checkSignInStatus() - btnLogin.setOnClickListener(this) - tvForgotPass.setOnClickListener(this) - btnSignUp.setOnClickListener(this) + btnLoginLogin.setOnClickListener { signIn() } + tvForgotPassLogin.setOnClickListener { resetUserPassword() } + btnSignUpLogin.setOnClickListener { + startActivity(Intent(this@LogInActivity, SignUpActivity::class.java)) + finish() + } + + etEmailLogin.onTextChanged { + tilEmailLogin.error = null + } + etPasswordLogin.onTextChanged { + tilPasswordLogin.error = null + } } override fun onResume() { @@ -38,50 +50,40 @@ class LogInActivity : AppCompatActivity(), LogInView, View.OnClickListener { presenter.cancel() } - override fun onClick(view: View) { - when (view) { - btnLogin -> signIn() - tvForgotPass -> resetUserPassword() - btnSignUp -> { - startActivity(Intent(this@LogInActivity, SignUpActivity::class.java)) - } - } - } - override fun closeActivity() { finish() } override fun signIn() { if (validateFields()) { + hideKeyboard() disableButtons() - presenter.signIn(etEmail.text.toString().trim { it <= ' ' }, etPassword.text.toString().trim { it <= ' ' }) + presenter.signIn(etEmailLogin.trimmedText, etPasswordLogin.trimmedText) } } override fun resetUserPassword() { - disableButtons() - email = etEmail.trimmedText + email = etEmailLogin.trimmedText if (TextUtils.isEmpty(email)) { - etEmail.error = "Enter your email address" - enableButtons() + tilEmailLogin.error = "Enter your email address" } else { + disableButtons() presenter.resetUserPassword(email) } } override fun displayMessage(message: String?) { enableButtons() - dismissDialog() + dismissLoading() Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } - override fun showDialog() { + override fun showLoading() { pbLoading.visibility = View.VISIBLE } - override fun dismissDialog() { + override fun dismissLoading() { pbLoading.visibility = View.GONE } @@ -90,31 +92,30 @@ class LogInActivity : AppCompatActivity(), LogInView, View.OnClickListener { } private fun disableButtons() { - btnLogin.isEnabled = false - btnSignUp.isEnabled = false - tvForgotPass.isEnabled = false + btnLoginLogin.isEnabled = false + btnSignUpLogin.isEnabled = false + tvForgotPassLogin.isEnabled = false } private fun enableButtons() { - btnLogin.isEnabled = true - btnSignUp.isEnabled = true - tvForgotPass.isEnabled = true + btnLoginLogin.isEnabled = true + btnSignUpLogin.isEnabled = true + tvForgotPassLogin.isEnabled = true } private fun validateFields(): Boolean { - email = etEmail.trimmedText - val password = etPassword.trimmedText + var isValid = true - if (TextUtils.isEmpty(email)) { - etEmail.error = "Required" - return false + if (etEmailLogin.trimmedText.isEmpty()) { + tilEmailLogin.error = "Required" + isValid = false } - if (TextUtils.isEmpty(password)) { - etPassword.error = "Required" - return false + if (etPasswordLogin.trimmedText.isEmpty()) { + tilPasswordLogin.error = "Required" + isValid = false } - return true + return isValid } } diff --git a/app/src/main/java/com/marknkamau/justjava/ui/login/LogInPresenter.kt b/app/src/main/java/com/marknkamau/justjava/ui/login/LogInPresenter.kt index 3debc80..e9331c5 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/login/LogInPresenter.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/login/LogInPresenter.kt @@ -22,7 +22,7 @@ internal class LogInPresenter(private val view: LogInView, } fun signIn(email: String, password: String) { - view.showDialog() + view.showLoading() uiScope.launch { try { val uid = auth.signIn(email, password) @@ -41,7 +41,7 @@ internal class LogInPresenter(private val view: LogInView, val userDetails = userService.getUserDetails(id) preferences.saveUserDetails(userDetails) - view.dismissDialog() + view.dismissLoading() view.displayMessage("Sign in successful") view.finishSignIn() } catch (e: Exception) { diff --git a/app/src/main/java/com/marknkamau/justjava/ui/login/LogInView.kt b/app/src/main/java/com/marknkamau/justjava/ui/login/LogInView.kt index 96ab629..071954b 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/login/LogInView.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/login/LogInView.kt @@ -5,7 +5,7 @@ interface LogInView { fun signIn() fun resetUserPassword() fun displayMessage(message: String?) - fun showDialog() - fun dismissDialog() + fun showLoading() + fun dismissLoading() fun finishSignIn() } diff --git a/app/src/main/java/com/marknkamau/justjava/ui/main/CatalogAdapter.kt b/app/src/main/java/com/marknkamau/justjava/ui/main/CatalogAdapter.kt deleted file mode 100644 index 1741c97..0000000 --- a/app/src/main/java/com/marknkamau/justjava/ui/main/CatalogAdapter.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.marknkamau.justjava.ui.main - -import android.content.Context -import androidx.recyclerview.widget.RecyclerView -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.marknkamau.justjava.R -import com.marknjunge.core.model.CoffeeDrink -import com.squareup.picasso.Picasso -import kotlinx.android.synthetic.main.item_catalog.view.* - -class CatalogAdapter(private val context: Context, private val onClick: (CoffeeDrink) -> Unit) : androidx.recyclerview.widget.RecyclerView.Adapter() { - - private val items by lazy { mutableListOf() } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.item_catalog)) - - override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position], context, onClick) - - override fun getItemCount() = items.size - - fun setItems(items: MutableList) { - this.items.clear() - this.items.addAll(items) - notifyDataSetChanged() - } - - class ViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) { - fun bind(drink: CoffeeDrink, context: Context, onClick: (CoffeeDrink) -> Unit) { - itemView.tvItemName.text = drink.drinkName - itemView.tvShortDesc.text = drink.drinkContents - itemView.tvDrinkName.text = context.resources.getString(R.string.price_listing, drink.drinkPrice.toInt()) - - val drinkImage = "file:///android_asset/" + drink.drinkImage - Picasso.with(context).load(drinkImage).placeholder(R.drawable.plain_brown).into(itemView.imgDrinkImage) - - itemView.catalogItem.setOnClickListener { - onClick(drink) - } - } - } - - private fun ViewGroup.inflate(layoutRes: Int): View { - return LayoutInflater.from(context).inflate(layoutRes, this, false) - } -} diff --git a/app/src/main/java/com/marknkamau/justjava/ui/main/MainActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/main/MainActivity.kt index a2eb088..f25f2f1 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/main/MainActivity.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/main/MainActivity.kt @@ -1,33 +1,52 @@ package com.marknkamau.justjava.ui.main -import android.content.Intent import android.os.Bundle +import androidx.core.util.Pair +import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.marknkamau.justjava.R import com.marknjunge.core.model.CoffeeDrink +import com.marknkamau.justjava.R import com.marknkamau.justjava.ui.BaseActivity import com.marknkamau.justjava.ui.drinkdetails.DrinkDetailsActivity - +import com.marknkamau.justjava.utils.BaseRecyclerViewAdapter +import com.squareup.picasso.Picasso import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.content_toolbar.* +import kotlinx.android.synthetic.main.item_catalog.view.* import org.koin.android.ext.android.inject import org.koin.core.parameter.parametersOf class MainActivity : BaseActivity(), MainView { private val presenter: MainPresenter by inject { parametersOf(this) } - private lateinit var catalogAdapter: CatalogAdapter + private lateinit var catalogAdapter: BaseRecyclerViewAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - - catalogAdapter = CatalogAdapter(this) { coffeeDrink -> - val i = Intent(this, DrinkDetailsActivity::class.java) - i.putExtra(DrinkDetailsActivity.DRINK_KEY, coffeeDrink) - startActivity(i) + setSupportActionBar(toolbar) + + catalogAdapter = BaseRecyclerViewAdapter(R.layout.item_catalog) { drink -> + tvDrinkNameCatalog.text = drink.drinkName + tvDrinkContentsCatalog.text = drink.drinkContents + tvDrinkPriceCatalog.text = context.resources.getString(R.string.price_listing, drink.drinkPrice.toInt()) + + val drinkImage = "file:///android_asset/" + drink.drinkImage + Picasso.get().load(drinkImage).placeholder(R.drawable.plain_brown).into(imgDrinkImageCatalog) + + catalogItem.setOnClickListener { + DrinkDetailsActivity.start( + this@MainActivity, + drink, + Pair(imgDrinkImageCatalog, "drinkImage") + ) + } } rvCatalog.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) + val dividerItemDecoration = DividerItemDecoration(this, RecyclerView.VERTICAL) + dividerItemDecoration.setDrawable(getDrawable(R.drawable.custom_item_divider)!!) + rvCatalog.addItemDecoration(dividerItemDecoration) rvCatalog.adapter = catalogAdapter presenter.getCatalogItems() diff --git a/app/src/main/java/com/marknkamau/justjava/ui/previousOrder/OrderItemsAdapter.kt b/app/src/main/java/com/marknkamau/justjava/ui/previousOrder/OrderItemsAdapter.kt deleted file mode 100644 index ed80c0b..0000000 --- a/app/src/main/java/com/marknkamau/justjava/ui/previousOrder/OrderItemsAdapter.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.marknkamau.justjava.ui.previousOrder - -/** - * Created by Mark Njung'e. - * mark.kamau@outlook.com - * https://github.com/MarkNjunge - */ - -import androidx.recyclerview.widget.RecyclerView -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.marknkamau.justjava.R -import com.marknjunge.core.model.OrderItem -import kotlinx.android.synthetic.main.item_order_item.view.* - -class OrderItemsAdapter : androidx.recyclerview.widget.RecyclerView.Adapter() { - private val items by lazy { mutableListOf() } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.item_order_item)) - - override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position]) - - override fun getItemCount() = items.size - - fun setItems(items: List) { - this.items.clear() - this.items.addAll(items) - notifyDataSetChanged() - } - - class ViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) { - fun bind(item: OrderItem) { - itemView.run { - tvItemName.text = item.itemName - tvItemQuantity.text = "x ${item.itemQty}" - tvChocolate.visibility = if (item.itemChoc) View.VISIBLE else View.GONE - tvCinnamon.visibility = if (item.itemCinnamon) View.VISIBLE else View.GONE - tvMarshmallows.visibility = if (item.itemMarshmallow) View.VISIBLE else View.GONE - } - } - } - - private fun ViewGroup.inflate(layoutRes: Int): View { - return LayoutInflater.from(context).inflate(layoutRes, this, false) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/marknkamau/justjava/ui/previousOrders/PreviousOrdersActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/previousOrders/PreviousOrdersActivity.kt new file mode 100644 index 0000000..f202b1d --- /dev/null +++ b/app/src/main/java/com/marknkamau/justjava/ui/previousOrders/PreviousOrdersActivity.kt @@ -0,0 +1,68 @@ +package com.marknkamau.justjava.ui.previousOrders + +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.view.View +import android.widget.Toast +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.marknjunge.core.model.Order +import com.marknkamau.justjava.R +import com.marknkamau.justjava.ui.viewOrder.ViewOrderActivity +import com.marknkamau.justjava.utils.BaseRecyclerViewAdapter +import com.marknkamau.justjava.utils.DividerItemDecorator +import com.marknkamau.justjava.utils.formatForApp +import kotlinx.android.synthetic.main.activity_previous_orders.* +import kotlinx.android.synthetic.main.content_toolbar.* +import kotlinx.android.synthetic.main.item_previous_order.view.* +import org.koin.android.ext.android.inject +import org.koin.core.parameter.parametersOf + +class PreviousOrdersActivity : AppCompatActivity(), PreviousOrdersView { + + private lateinit var previousOrdersAdapter: BaseRecyclerViewAdapter + private val presenter: PreviousOrdersPresenter by inject { parametersOf(this) } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_previous_orders) + setSupportActionBar(toolbar) + supportActionBar?.title = getString(R.string.previous_orders) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + + previousOrdersAdapter = BaseRecyclerViewAdapter(R.layout.item_previous_order) { order -> + tvOrderTimeItem.text = order.date.formatForApp() + tvOrderStatusItem.text = order.status.name.toLowerCase().capitalize() + tvOrderQtyItem.text = order.itemsCount.toString() + tvOrderCountItem.text = resources.getQuantityString(R.plurals.order_info, order.itemsCount) + tvOrderTotalItem.text = resources.getString(R.string.price_listing, order.totalPrice) + + previousOrderItemRootLayout.setOnClickListener { + ViewOrderActivity.start(this@PreviousOrdersActivity, order) + } + } + + rvPreviousOrdersActivity.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) + rvPreviousOrdersActivity.addItemDecoration(DividerItemDecorator(getDrawable(R.drawable.custom_item_divider)!!)) + rvPreviousOrdersActivity.adapter = previousOrdersAdapter + + presenter.getPreviousOrders() + } + + override fun displayMessage(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } + + override fun displayNoOrders() { + pbLoadingOrdersPreviousActivity.visibility = View.GONE + contentNoOrdersPreviousActivity.visibility = View.VISIBLE + rvPreviousOrdersActivity.visibility = View.GONE + } + + override fun displayOrders(orders: List) { + pbLoadingOrdersPreviousActivity.visibility = View.GONE + contentNoOrdersPreviousActivity.visibility = View.GONE + rvPreviousOrdersActivity.visibility = View.VISIBLE + previousOrdersAdapter.setItems(orders) + } +} diff --git a/app/src/main/java/com/marknkamau/justjava/ui/previousOrders/PreviousOrdersPresenter.kt b/app/src/main/java/com/marknkamau/justjava/ui/previousOrders/PreviousOrdersPresenter.kt new file mode 100644 index 0000000..c83cc62 --- /dev/null +++ b/app/src/main/java/com/marknkamau/justjava/ui/previousOrders/PreviousOrdersPresenter.kt @@ -0,0 +1,31 @@ +package com.marknkamau.justjava.ui.previousOrders + +import com.marknjunge.core.auth.AuthService +import com.marknjunge.core.data.firebase.OrderService +import com.marknkamau.justjava.ui.BasePresenter +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.launch + +class PreviousOrdersPresenter(private val view: PreviousOrdersView, + private val authenticationService: AuthService, + private val orderService: OrderService, + mainDispatcher: CoroutineDispatcher +): BasePresenter(mainDispatcher){ + + fun getPreviousOrders() { + uiScope.launch { + try { + val previousOrders = orderService.getPreviousOrders(authenticationService.getCurrentUser().userId) + if (previousOrders.isEmpty()) { + view.displayNoOrders() + } else { + val sorted = previousOrders.sortedBy { it.date }.reversed().toMutableList() + view.displayOrders(sorted) + } + } catch (e: Exception) { + view.displayMessage(e.message ?: "Error getting previous orders") + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/marknkamau/justjava/ui/previousOrders/PreviousOrdersView.kt b/app/src/main/java/com/marknkamau/justjava/ui/previousOrders/PreviousOrdersView.kt new file mode 100644 index 0000000..ba1b9c4 --- /dev/null +++ b/app/src/main/java/com/marknkamau/justjava/ui/previousOrders/PreviousOrdersView.kt @@ -0,0 +1,9 @@ +package com.marknkamau.justjava.ui.previousOrders + +import com.marknjunge.core.model.Order + +interface PreviousOrdersView { + fun displayMessage(message: String) + fun displayNoOrders() + fun displayOrders(orders: List) +} \ No newline at end of file diff --git a/app/src/main/java/com/marknkamau/justjava/ui/profile/PreviousOrderAdapter.kt b/app/src/main/java/com/marknkamau/justjava/ui/profile/PreviousOrderAdapter.kt deleted file mode 100644 index 4b204e1..0000000 --- a/app/src/main/java/com/marknkamau/justjava/ui/profile/PreviousOrderAdapter.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.marknkamau.justjava.ui.profile - -import android.annotation.SuppressLint -import android.content.Context -import androidx.recyclerview.widget.RecyclerView -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.marknkamau.justjava.R -import com.marknjunge.core.model.Order -import com.marknkamau.justjava.utils.formatForApp -import kotlinx.android.synthetic.main.item_previous_order.view.* - -class PreviousOrderAdapter(private val context: Context, private val onClick: (order: Order) -> Unit) : androidx.recyclerview.widget.RecyclerView.Adapter() { - private val items by lazy { mutableListOf() } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(R.layout.item_previous_order)) - - override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position], context, onClick) - - override fun getItemCount() = items.size - - fun setItems(items: MutableList) { - this.items.clear() - this.items.addAll(items) - notifyDataSetChanged() - } - - class ViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) { - - @SuppressLint("SetTextI18n") - fun bind(order: Order, context: Context, onClick: (order: Order) -> Unit) { - itemView.tvTimestamp.text = order.date.formatForApp() - itemView.tvStatus.text = order.status.name.toLowerCase().capitalize() - itemView.tvAddress.text = order.deliveryAddress - itemView.tvOrderInfo.text = context.resources.getQuantityString(R.plurals.order_info, order.itemsCount, order.itemsCount, order.totalPrice) - - itemView.rootLayout.setOnClickListener { - onClick(order) - } - } - } - - - private fun ViewGroup.inflate(layoutRes: Int): View { - return LayoutInflater.from(context).inflate(layoutRes, this, false) - } -} diff --git a/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfileActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfileActivity.kt index 6dcb86d..9664701 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfileActivity.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfileActivity.kt @@ -1,47 +1,59 @@ package com.marknkamau.justjava.ui.profile +import android.content.Intent import android.os.Bundle -import android.text.TextUtils import android.view.View -import android.widget.LinearLayout import android.widget.Toast +import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView - -import com.marknkamau.justjava.R import com.marknjunge.core.model.Order import com.marknjunge.core.model.UserDetails +import com.marknkamau.justjava.R import com.marknkamau.justjava.ui.BaseActivity -import com.marknkamau.justjava.ui.previousOrder.PreviousOrderActivity - -import com.marknkamau.justjava.utils.trimmedText +import com.marknkamau.justjava.ui.viewOrder.ViewOrderActivity +import com.marknkamau.justjava.ui.previousOrders.PreviousOrdersActivity +import com.marknkamau.justjava.utils.* import kotlinx.android.synthetic.main.activity_profile.* +import kotlinx.android.synthetic.main.content_toolbar.* +import kotlinx.android.synthetic.main.item_previous_order.view.* import org.koin.android.ext.android.inject import org.koin.core.parameter.parametersOf class ProfileActivity : BaseActivity(), ProfileView { - private var name: String? = null - private var phone: String? = null - private var address: String? = null - private lateinit var adapter: PreviousOrderAdapter + private lateinit var previousOrdersAdapter: BaseRecyclerViewAdapter private val presenter: ProfilePresenter by inject { parametersOf(this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_profile) - - adapter = PreviousOrderAdapter(this) { order -> - PreviousOrderActivity.start(this, order) + setSupportActionBar(toolbar) + + previousOrdersAdapter = BaseRecyclerViewAdapter(R.layout.item_previous_order) { order -> + tvOrderTimeItem.text = order.date.formatForApp() + tvOrderStatusItem.text = order.status.name.toLowerCase().capitalize() + tvOrderQtyItem.text = order.itemsCount.toString() + tvOrderCountItem.text = resources.getQuantityString(R.plurals.order_info, order.itemsCount) + tvOrderTotalItem.text = resources.getString(R.string.price_listing, order.totalPrice) + + previousOrderItemRootLayout.setOnClickListener { + ViewOrderActivity.start(this@ProfileActivity, order) + } } - rvPreviousOrders.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this, RecyclerView.VERTICAL, false) - rvPreviousOrders.addItemDecoration(androidx.recyclerview.widget.DividerItemDecoration(this, LinearLayout.VERTICAL)) - rvPreviousOrders.adapter = adapter + rvPreviousOrdersProfile.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) + rvPreviousOrdersProfile.addItemDecoration(DividerItemDecorator(getDrawable(R.drawable.custom_item_divider)!!)) + rvPreviousOrdersProfile.adapter = previousOrdersAdapter presenter.getUserDetails() presenter.getPreviousOrders() btnUpdateProfile.setOnClickListener { saveChanges() } + tvSeeMoreProfile.setOnClickListener { startActivity(Intent(this, PreviousOrdersActivity::class.java)) } + + etNameProfile.onTextChanged { tilNameProfile.error = null } + etPhoneProfile.onTextChanged { tilPhoneProfile.error = null } + etAddressProfile.onTextChanged { tilAddressProfile.error = null } } override fun onDestroy() { @@ -49,56 +61,63 @@ class ProfileActivity : BaseActivity(), ProfileView { presenter.cancel() } - override fun showOrdersProgressBar() { - pbLoadingOrders.visibility = View.VISIBLE - } - - override fun hideOrdersProgressBar() { - pbLoadingOrders.visibility = View.GONE - } - override fun showProfileProgressBar() { - pbUpdatingProject.visibility = View.VISIBLE + pbUpdatingProfile.visibility = View.VISIBLE } override fun hideProfileProgressBar() { - pbUpdatingProject.visibility = View.GONE + pbUpdatingProfile.visibility = View.GONE } override fun displayNoPreviousOrders() { - tvNoOrders.visibility = View.VISIBLE - rvPreviousOrders.visibility = View.GONE + pbLoadingOrdersProfile.visibility = View.GONE + contentNoOrdersProfile.visibility = View.VISIBLE + rvPreviousOrdersProfile.visibility = View.GONE } override fun displayPreviousOrders(orderList: MutableList) { - adapter.setItems(orderList) + pbLoadingOrdersProfile.visibility = View.GONE + contentNoOrdersProfile.visibility = View.GONE + rvPreviousOrdersProfile.visibility = View.VISIBLE + tvSeeMoreProfile.visibility = View.VISIBLE + previousOrdersAdapter.setItems(orderList) } - override fun displayMessage(message: String?) { + override fun displayMessage(message: String) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } private fun saveChanges() { if (fieldsOk()) { - presenter.updateUserDetails(name!!, phone!!, address!!) + hideKeyboard() + presenter.updateUserDetails(etNameProfile.trimmedText, etPhoneProfile.trimmedText, etAddressProfile.trimmedText) } } private fun fieldsOk(): Boolean { - name = etName.trimmedText - phone = etPhone.trimmedText - address = etDeliveryAddress.trimmedText + var isValid = true + + if (etNameProfile.trimmedText.isEmpty()) { + isValid = false + tilNameProfile.error = getString(R.string.required) + } - if (TextUtils.isEmpty(name) || TextUtils.isEmpty(phone) || TextUtils.isEmpty(address)) { - Toast.makeText(this, "All fields are required", Toast.LENGTH_SHORT).show() - return false + if (etPhoneProfile.trimmedText.isEmpty()) { + isValid = false + tilPhoneProfile.error = getString(R.string.required) } - return true + + if (etAddressProfile.trimmedText.isEmpty()) { + isValid = false + tilAddressProfile.error = getString(R.string.required) + } + + return isValid } override fun displayUserDetails(userDetails: UserDetails) { - etName.setText(userDetails.name) - etPhone.setText(userDetails.phone) - etDeliveryAddress.setText(userDetails.address) + etNameProfile.setText(userDetails.name) + etPhoneProfile.setText(userDetails.phone) + etAddressProfile.setText(userDetails.address) } } \ No newline at end of file diff --git a/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfilePresenter.kt b/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfilePresenter.kt index 56847dd..86b70df 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfilePresenter.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfilePresenter.kt @@ -26,20 +26,17 @@ internal class ProfilePresenter(private val view: ProfileView, } fun getPreviousOrders() { - view.showOrdersProgressBar() uiScope.launch { try { val previousOrders = orderService.getPreviousOrders(authenticationService.getCurrentUser().userId) - view.hideOrdersProgressBar() if (previousOrders.isEmpty()) { view.displayNoPreviousOrders() } else { - val sorted = previousOrders.sortedBy { it.date }.reversed().toMutableList() + val sorted = previousOrders.sortedBy { it.date }.reversed().take(3).toMutableList() view.displayPreviousOrders(sorted) } } catch (e: Exception) { - view.hideOrdersProgressBar() - view.displayMessage(e.message) + view.displayMessage(e.message ?: "Error getting previous orders") } } } @@ -58,7 +55,7 @@ internal class ProfilePresenter(private val view: ProfileView, } catch (e: Exception) { Timber.e(e) view.hideProfileProgressBar() - view.displayMessage(e.message) + view.displayMessage(e.message ?: "Error upating profile") } } } diff --git a/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfileView.kt b/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfileView.kt index d01c6d2..f53eaae 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfileView.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/profile/ProfileView.kt @@ -5,11 +5,9 @@ import com.marknjunge.core.model.UserDetails internal interface ProfileView { fun displayUserDetails(userDetails: UserDetails) - fun showOrdersProgressBar() - fun hideOrdersProgressBar() fun showProfileProgressBar() fun hideProfileProgressBar() fun displayNoPreviousOrders() fun displayPreviousOrders(orderList: MutableList) - fun displayMessage(message: String?) + fun displayMessage(message: String) } diff --git a/app/src/main/java/com/marknkamau/justjava/ui/signup/SignUpActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/signup/SignUpActivity.kt index f9139c3..d43d9c6 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/signup/SignUpActivity.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/signup/SignUpActivity.kt @@ -1,32 +1,38 @@ package com.marknkamau.justjava.ui.signup +import android.content.Intent import android.os.Bundle import android.util.Patterns import android.view.View import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.marknkamau.justjava.R +import com.marknkamau.justjava.ui.login.LogInActivity +import com.marknkamau.justjava.utils.onTextChanged import com.marknkamau.justjava.utils.trimmedText import kotlinx.android.synthetic.main.activity_sign_up.* import org.koin.android.ext.android.inject import org.koin.core.parameter.parametersOf import java.util.regex.Pattern -class SignUpActivity : AppCompatActivity(), SignUpView, View.OnClickListener { - private lateinit var name: String - private lateinit var phone: String - private lateinit var email: String - private lateinit var address: String - private lateinit var password: String - +class SignUpActivity : AppCompatActivity(), SignUpView { private val presenter: SignUpPresenter by inject { parametersOf(this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_sign_up) - btnSignup.setOnClickListener(this) - tvLogin.setOnClickListener(this) + btnSignupSignUp.setOnClickListener { createUser() } + btnLoginSignUp.setOnClickListener { + startActivity(Intent(this@SignUpActivity, LogInActivity::class.java)) + finish() + } + + etEmailAddressSignUp.onTextChanged { tilEmailAddressSignUp.error = null } + etPasswordSignUp.onTextChanged { tilPasswordSignUp.error = null } + etNameSignUp.onTextChanged { tilNameSignUp.error = null } + etPhoneSignUp.onTextChanged { tilPhoneSignUp.error = null } + etDeliveryAddressSignUp.onTextChanged { tilDeliveryAddressSignUp.error = null } } override fun onDestroy() { @@ -34,25 +40,16 @@ class SignUpActivity : AppCompatActivity(), SignUpView, View.OnClickListener { presenter.cancel() } - override fun onClick(view: View) { - when (view) { - btnSignup -> createUser() - tvLogin -> { - finish() - } - } - } - override fun enableUserInteraction() { - btnSignup.setBackgroundResource(R.drawable.large_button) - btnSignup.isEnabled = true - pbLoading.visibility = View.GONE + btnSignupSignUp.isEnabled = true + btnLoginSignUp.isEnabled = true + pbLoadingSignUp.visibility = View.GONE } override fun disableUserInteraction() { - pbLoading.visibility = View.VISIBLE - btnSignup.setBackgroundResource(R.drawable.large_button_disabled) - btnSignup.isEnabled = false + btnSignupSignUp.isEnabled = false + btnLoginSignUp.isEnabled = false + pbLoadingSignUp.visibility = View.VISIBLE } override fun displayMessage(message: String) { @@ -62,41 +59,51 @@ class SignUpActivity : AppCompatActivity(), SignUpView, View.OnClickListener { override fun finishActivity() = finish() private fun createUser() { - if (fieldsOk()) { - presenter.createUser(email, password, name, phone, address) + if (isValid()) { + presenter.createUser(etEmailAddressSignUp.trimmedText, etPasswordSignUp.trimmedText, etNameSignUp.trimmedText, etPhoneSignUp.trimmedText, etDeliveryAddressSignUp.trimmedText) } } - private fun fieldsOk(): Boolean { - email = etEmailAddress.trimmedText - password = etPassword.trimmedText - - name = etName.trimmedText - phone = etPhone.trimmedText - address = etDeliveryAddress.trimmedText - - val pattern1 = Pattern.compile("^([a-zA-Z0-9_.-])+@justjava.com+") - val matcher1 = pattern1.matcher(email) + private fun isValid(): Boolean { + var isValid = true + + val justJavaEmailPattern = Pattern.compile("^([a-zA-Z0-9_.-])+@justjava.com+") + val justJavaEmailMatcher = justJavaEmailPattern.matcher(etEmailAddressSignUp.trimmedText) + + if (etEmailAddressSignUp.trimmedText.isEmpty()) { + tilEmailAddressSignUp.error = getString(R.string.required) + isValid = false + } else if (justJavaEmailMatcher.matches()) { + tilEmailAddressSignUp.error = "Can not use @justjava.com" + isValid = false + } else if (!Patterns.EMAIL_ADDRESS.matcher(etEmailAddressSignUp.trimmedText).matches()) { + tilEmailAddressSignUp.error = "Incorrect email" + isValid = false + } - if (matcher1.matches()) { - etEmailAddress.error = "Can not use @justjava.com" - return false + if (etPasswordSignUp.trimmedText.isEmpty()) { + tilPasswordSignUp.error = getString(R.string.required) + isValid = false + } else if (etPasswordSignUp.trimmedText.length < 6) { + tilPasswordSignUp.error = "At least 6 characters" + isValid = false } - if (email.isEmpty() || password.isEmpty() - || name.isEmpty() || phone.isEmpty() || address.isEmpty()) { - Toast.makeText(this, "All fields are required", Toast.LENGTH_SHORT).show() - return false + + if (etNameSignUp.trimmedText.isEmpty()) { + tilNameSignUp.error = getString(R.string.required) + isValid = false } - if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) { - Toast.makeText(this, "Invalid email", Toast.LENGTH_SHORT).show() - etEmailAddress.error = "Incorrect format" - return false + + if (etPhoneSignUp.trimmedText.isEmpty()) { + tilPhoneSignUp.error = getString(R.string.required) + isValid = false } - if (password.length < 6) { - Toast.makeText(this, "Password must be at least 6 characters", Toast.LENGTH_LONG).show() - etPassword.error = "At least 6 characters" - return false + + if (etDeliveryAddressSignUp.trimmedText.isEmpty()) { + tilDeliveryAddressSignUp.error = getString(R.string.required) + isValid = false } - return true + + return isValid } } diff --git a/app/src/main/java/com/marknkamau/justjava/ui/previousOrder/PreviousOrderActivity.kt b/app/src/main/java/com/marknkamau/justjava/ui/viewOrder/ViewOrderActivity.kt similarity index 58% rename from app/src/main/java/com/marknkamau/justjava/ui/previousOrder/PreviousOrderActivity.kt rename to app/src/main/java/com/marknkamau/justjava/ui/viewOrder/ViewOrderActivity.kt index 8a459fb..9a27e3f 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/previousOrder/PreviousOrderActivity.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/viewOrder/ViewOrderActivity.kt @@ -1,4 +1,4 @@ -package com.marknkamau.justjava.ui.previousOrder +package com.marknkamau.justjava.ui.viewOrder import android.content.BroadcastReceiver import android.content.Context @@ -11,53 +11,75 @@ import androidx.appcompat.app.AlertDialog import android.view.View import android.widget.LinearLayout import android.widget.Toast +import androidx.recyclerview.widget.RecyclerView import com.marknkamau.justjava.R import com.marknkamau.justjava.data.local.PreferencesRepository import com.marknjunge.core.model.Order import com.marknjunge.core.model.OrderItem import com.marknkamau.justjava.data.network.MyFirebaseMessagingService +import com.marknkamau.justjava.utils.BaseRecyclerViewAdapter import com.marknkamau.justjava.utils.formatForApp -import kotlinx.android.synthetic.main.activity_previous_order.* -import kotlinx.android.synthetic.main.include_order_details.* +import kotlinx.android.synthetic.main.activity_view_order.* +import kotlinx.android.synthetic.main.content_toolbar.* +import kotlinx.android.synthetic.main.item_order_item.view.* import org.koin.android.ext.android.inject import org.koin.core.parameter.parametersOf import timber.log.Timber -class PreviousOrderActivity : AppCompatActivity(), PreviousOrderView { +class ViewOrderActivity : AppCompatActivity(), ViewOrderView { companion object { const val ORDER_KEY = "order_key" fun start(context: Context, order: Order) { - val i = Intent(context, PreviousOrderActivity::class.java) + val i = Intent(context, ViewOrderActivity::class.java) i.putExtra(ORDER_KEY, order) context.startActivity(i) } } - private lateinit var orderItemsAdapter: OrderItemsAdapter + private lateinit var orderItemsAdapter: BaseRecyclerViewAdapter private lateinit var broadcastReceiver: BroadcastReceiver private lateinit var order: Order private val preferencesRepository: PreferencesRepository by inject() private val broadcastManager by lazy { LocalBroadcastManager.getInstance(this) } - private val presenter: PreviousOrderPresenter by inject { parametersOf(this) } + private val presenter: ViewOrderPresenter by inject { parametersOf(this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_previous_order) + setContentView(R.layout.activity_view_order) + setSupportActionBar(toolbar) + supportActionBar?.title = "Order" + supportActionBar?.setDisplayHomeAsUpEnabled(true) order = intent.getParcelableExtra(ORDER_KEY) updateViews(order) - orderItemsAdapter = OrderItemsAdapter() - rvOrderItems.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this, LinearLayout.VERTICAL, false) - rvOrderItems.adapter = orderItemsAdapter + orderItemsAdapter = BaseRecyclerViewAdapter(R.layout.item_order_item){orderItem -> + tvItemNameItem.text = orderItem.itemName + tvItemQtyItem.text = "${orderItem.itemQty}x" + tvItemPriceItem.text = context.getString(R.string.price_listing, orderItem.itemPrice) + val toppings = mutableListOf() - presenter.getOrderItems(order.orderId) + if (orderItem.itemCinnamon) toppings.add("Cinnamon") + if (orderItem.itemChoc) toppings.add("Chocolate") + if (orderItem.itemMarshmallow) toppings.add("Marshmallows") + + if (toppings.isNotEmpty()) { + tvToppingsItem.visibility = View.VISIBLE + tvToppingsItem.text = toppings.joinToString(", ") + } else { + tvToppingsItem.visibility = View.GONE + } + } + + rvOrderItemsOrder.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this, RecyclerView.VERTICAL, false) + rvOrderItemsOrder.adapter = orderItemsAdapter + presenter.getOrderItems(order.orderId) } override fun onStart() { @@ -70,8 +92,8 @@ class PreviousOrderActivity : AppCompatActivity(), PreviousOrderView { Timber.d("Payment received for order $orderId") if (order.orderId == orderId) { Timber.d("The current order has been paid for!") - btnPay.visibility = View.GONE - tvPaymentStatus.text = "Paid" + btnPayOrder.visibility = View.GONE + tvPaymentStatusOrder .text = "Paid" displayMessage("Payment received!") } } @@ -93,7 +115,8 @@ class PreviousOrderActivity : AppCompatActivity(), PreviousOrderView { } override fun displayOrderItems(orderItems: List) { - cardOrderItems.visibility = View.VISIBLE + pbLoadingOrderItemsOrder.visibility = View.GONE + rvOrderItemsOrder.visibility = View.VISIBLE orderItemsAdapter.setItems(orderItems) } @@ -107,26 +130,26 @@ class PreviousOrderActivity : AppCompatActivity(), PreviousOrderView { } private fun updateViews(order: Order) { - tvOrderId.text = order.orderId - tvOrderStatus.text = order.status.name.toLowerCase().capitalize() - tvOrderDate.text = order.date.formatForApp() - tvDeliveryAddress.text = order.deliveryAddress - tvTotalPrice.text = getString(R.string.ksh, order.totalPrice) + tvOrderIdOrder.text = order.orderId + tvOrderStatusOrder.text = order.status.name.toLowerCase().capitalize() + tvOrderDateOrder.text = order.date.formatForApp() + tvOrderAddressOrder.text = order.deliveryAddress + tvOrderTotalOrder .text = getString(R.string.ksh, order.totalPrice) if (order.additionalComments.isEmpty()) { - tvComments.visibility = View.GONE - tvCommentsLabel.visibility = View.GONE + tvOrderCommentsOrder.visibility = View.GONE + tvCommentsLabelOrder.visibility = View.GONE } else { - tvComments.text = order.additionalComments + tvOrderCommentsOrder.text = order.additionalComments } - tvPaymentMethod.text = order.paymentMethod.capitalize() - tvPaymentStatus.text = order.paymentStatus.capitalize() + tvPaymentMethodOrder.text = order.paymentMethod.capitalize() + tvPaymentStatusOrder.text = order.paymentStatus.capitalize() if (order.paymentMethod != "mpesa" || order.paymentStatus == "paid") { - btnPay.visibility = View.GONE + btnPayOrder.visibility = View.GONE } - btnPay.setOnClickListener { + btnPayOrder.setOnClickListener { val phoneNumber = preferencesRepository.getUserDetails().phone val dialog = AlertDialog.Builder(this) .setMessage("Are you sure you want to pay Ksh. 1 using $phoneNumber?\nThe money will be automatically refunded by Safaricom the following day.") diff --git a/app/src/main/java/com/marknkamau/justjava/ui/previousOrder/PreviousOrderPresenter.kt b/app/src/main/java/com/marknkamau/justjava/ui/viewOrder/ViewOrderPresenter.kt similarity index 81% rename from app/src/main/java/com/marknkamau/justjava/ui/previousOrder/PreviousOrderPresenter.kt rename to app/src/main/java/com/marknkamau/justjava/ui/viewOrder/ViewOrderPresenter.kt index 3f8c7b0..d2d7455 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/previousOrder/PreviousOrderPresenter.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/viewOrder/ViewOrderPresenter.kt @@ -1,4 +1,4 @@ -package com.marknkamau.justjava.ui.previousOrder +package com.marknkamau.justjava.ui.viewOrder import com.google.firebase.iid.FirebaseInstanceId import com.marknjunge.core.mpesa.MpesaInteractor @@ -15,11 +15,11 @@ import timber.log.Timber * https://github.com/MarkNjunge */ -class PreviousOrderPresenter(private val view: PreviousOrderView, - private val orderService: OrderService, - private val mpesaInteractor: MpesaInteractor, - private val authService: AuthService, - mainDispatcher: CoroutineDispatcher +class ViewOrderPresenter(private val view: ViewOrderView, + private val orderService: OrderService, + private val mpesaInteractor: MpesaInteractor, + private val authService: AuthService, + mainDispatcher: CoroutineDispatcher ) : BasePresenter(mainDispatcher) { fun getOrderDetails(orderId: String) { diff --git a/app/src/main/java/com/marknkamau/justjava/ui/previousOrder/PreviousOrderView.kt b/app/src/main/java/com/marknkamau/justjava/ui/viewOrder/ViewOrderView.kt similarity index 77% rename from app/src/main/java/com/marknkamau/justjava/ui/previousOrder/PreviousOrderView.kt rename to app/src/main/java/com/marknkamau/justjava/ui/viewOrder/ViewOrderView.kt index de98fca..6b3fbe5 100644 --- a/app/src/main/java/com/marknkamau/justjava/ui/previousOrder/PreviousOrderView.kt +++ b/app/src/main/java/com/marknkamau/justjava/ui/viewOrder/ViewOrderView.kt @@ -1,4 +1,4 @@ -package com.marknkamau.justjava.ui.previousOrder +package com.marknkamau.justjava.ui.viewOrder import com.marknjunge.core.model.Order import com.marknjunge.core.model.OrderItem @@ -10,7 +10,7 @@ import com.marknkamau.justjava.ui.BaseView * https://github.com/MarkNjunge */ -interface PreviousOrderView : BaseView { +interface ViewOrderView : BaseView { fun displayOrder(order: Order) fun displayOrderItems(orderItems: List) } \ No newline at end of file diff --git a/app/src/main/java/com/marknkamau/justjava/utils/BaseReyclerviewAdapter.kt b/app/src/main/java/com/marknkamau/justjava/utils/BaseReyclerviewAdapter.kt new file mode 100644 index 0000000..1eb1022 --- /dev/null +++ b/app/src/main/java/com/marknkamau/justjava/utils/BaseReyclerviewAdapter.kt @@ -0,0 +1,37 @@ +package com.marknkamau.justjava.utils + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView + +open class BaseRecyclerViewAdapter( + @LayoutRes + private val layoutRes: Int, + private val bind: View.(item: T) -> Unit +) : RecyclerView.Adapter.ViewHolder>() { + private val items by lazy { mutableListOf() } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(parent.inflate(layoutRes)) + + override fun getItemCount() = items.size + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(items[position]) + } + + fun setItems(newItems: List) { + items.clear() + items.addAll(newItems) + notifyDataSetChanged() + } + + inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + fun bind(item: T) = bind(itemView, item) + } + + private fun ViewGroup.inflate(layoutRes: Int): View { + return LayoutInflater.from(context).inflate(layoutRes, this, false) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/marknkamau/justjava/utils/DividerItemDecorator.kt b/app/src/main/java/com/marknkamau/justjava/utils/DividerItemDecorator.kt new file mode 100644 index 0000000..5eea497 --- /dev/null +++ b/app/src/main/java/com/marknkamau/justjava/utils/DividerItemDecorator.kt @@ -0,0 +1,25 @@ +package com.marknkamau.justjava.utils + +import android.graphics.Canvas +import android.graphics.drawable.Drawable +import androidx.recyclerview.widget.RecyclerView + +class DividerItemDecorator(private val mDivider: Drawable) : RecyclerView.ItemDecoration() { + override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) { + val dividerLeft = parent.paddingLeft + val dividerRight = parent.width - parent.paddingRight + + val childCount = parent.childCount + for (i in 0..childCount - 2) { + val child = parent.getChildAt(i) + + val params = child.layoutParams as RecyclerView.LayoutParams + + val dividerTop = child.bottom + params.bottomMargin + val dividerBottom = dividerTop + mDivider.intrinsicHeight + + mDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom) + mDivider.draw(canvas) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/marknkamau/justjava/utils/EditTextExtensions.kt b/app/src/main/java/com/marknkamau/justjava/utils/EditTextExtensions.kt new file mode 100644 index 0000000..b62207e --- /dev/null +++ b/app/src/main/java/com/marknkamau/justjava/utils/EditTextExtensions.kt @@ -0,0 +1,24 @@ +package com.marknkamau.justjava.utils + +import android.text.Editable +import android.text.TextWatcher +import android.widget.EditText + +fun EditText.onTextChanged(onChange: () -> Unit) { + this.addTextChangedListener(object : TextWatcher { + override fun afterTextChanged(s: Editable?) { + // Do nothing + } + + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { + // Do nothing + } + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + onChange() + } + }) +} + +val EditText.trimmedText: String + get() = this.text.trim().toString() diff --git a/app/src/main/java/com/marknkamau/justjava/utils/KeyboardUtils.kt b/app/src/main/java/com/marknkamau/justjava/utils/KeyboardUtils.kt new file mode 100644 index 0000000..b11e29b --- /dev/null +++ b/app/src/main/java/com/marknkamau/justjava/utils/KeyboardUtils.kt @@ -0,0 +1,17 @@ +package com.marknkamau.justjava.utils + +import android.content.Context +import android.view.inputmethod.InputMethodManager +import androidx.appcompat.app.AppCompatActivity + +fun AppCompatActivity.hideKeyboard() { + this.currentFocus?.let { + val manager = this.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + manager.hideSoftInputFromWindow(it.windowToken, 0) + } +} + +fun AppCompatActivity.showKeyboard() { + val manager = this.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + manager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0) +} diff --git a/app/src/main/java/com/marknkamau/justjava/utils/RandomUtils.kt b/app/src/main/java/com/marknkamau/justjava/utils/RandomUtils.kt deleted file mode 100644 index 5429bb3..0000000 --- a/app/src/main/java/com/marknkamau/justjava/utils/RandomUtils.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.marknkamau.justjava.utils - -import android.widget.EditText - -val EditText.trimmedText: String - get() = this.text.trim().toString() diff --git a/app/src/main/res/drawable-mdpi/ic_github_mark.xml b/app/src/main/res/drawable-mdpi/ic_github_mark.xml deleted file mode 100644 index 014d4b5..0000000 --- a/app/src/main/res/drawable-mdpi/ic_github_mark.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - diff --git a/app/src/main/res/drawable-mdpi/ic_linkedin_tm.xml b/app/src/main/res/drawable-mdpi/ic_linkedin_tm.xml deleted file mode 100644 index 4490649..0000000 --- a/app/src/main/res/drawable-mdpi/ic_linkedin_tm.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable-mdpi/ic_mail.xml b/app/src/main/res/drawable-mdpi/ic_mail.xml deleted file mode 100644 index 5b0b46c..0000000 --- a/app/src/main/res/drawable-mdpi/ic_mail.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/custom_item_divider.xml b/app/src/main/res/drawable/custom_item_divider.xml new file mode 100644 index 0000000..4016c66 --- /dev/null +++ b/app/src/main/res/drawable/custom_item_divider.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml index 0258249..ec3d105 100644 --- a/app/src/main/res/drawable/ic_add.xml +++ b/app/src/main/res/drawable/ic_add.xml @@ -1,9 +1,14 @@ - + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + diff --git a/app/src/main/res/drawable/ic_add_circle.xml b/app/src/main/res/drawable/ic_add_circle.xml deleted file mode 100644 index 900f227..0000000 --- a/app/src/main/res/drawable/ic_add_circle.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_cart.xml b/app/src/main/res/drawable/ic_cart.xml index 38955dc..6069a54 100644 --- a/app/src/main/res/drawable/ic_cart.xml +++ b/app/src/main/res/drawable/ic_cart.xml @@ -1,5 +1,14 @@ - - + + + diff --git a/app/src/main/res/drawable/ic_cart_light.xml b/app/src/main/res/drawable/ic_cart_light.xml new file mode 100644 index 0000000..6618d0f --- /dev/null +++ b/app/src/main/res/drawable/ic_cart_light.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml index 39e64d6..5658026 100644 --- a/app/src/main/res/drawable/ic_delete.xml +++ b/app/src/main/res/drawable/ic_delete.xml @@ -1,9 +1,14 @@ - + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + diff --git a/app/src/main/res/drawable/ic_github_mark.xml b/app/src/main/res/drawable/ic_github_mark.xml new file mode 100644 index 0000000..eb5be6c --- /dev/null +++ b/app/src/main/res/drawable/ic_github_mark.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xhdpi/ic_just_java_logo_black.xml b/app/src/main/res/drawable/ic_just_java_logo_black.xml similarity index 100% rename from app/src/main/res/drawable-xhdpi/ic_just_java_logo_black.xml rename to app/src/main/res/drawable/ic_just_java_logo_black.xml diff --git a/app/src/main/res/drawable/ic_linkedin.xml b/app/src/main/res/drawable/ic_linkedin.xml new file mode 100644 index 0000000..e3c70a2 --- /dev/null +++ b/app/src/main/res/drawable/ic_linkedin.xml @@ -0,0 +1,24 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_mail.xml b/app/src/main/res/drawable/ic_mail.xml new file mode 100644 index 0000000..476ccdd --- /dev/null +++ b/app/src/main/res/drawable/ic_mail.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_minus.xml b/app/src/main/res/drawable/ic_minus.xml new file mode 100644 index 0000000..a1ba00d --- /dev/null +++ b/app/src/main/res/drawable/ic_minus.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_minus_circle.xml b/app/src/main/res/drawable/ic_minus_circle.xml deleted file mode 100644 index 9af9456..0000000 --- a/app/src/main/res/drawable/ic_minus_circle.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_profile.xml b/app/src/main/res/drawable/ic_profile.xml index ba54ffd..6d2597f 100644 --- a/app/src/main/res/drawable/ic_profile.xml +++ b/app/src/main/res/drawable/ic_profile.xml @@ -1,9 +1,19 @@ - + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + + diff --git a/app/src/main/res/drawable/ic_profile_light.xml b/app/src/main/res/drawable/ic_profile_light.xml new file mode 100644 index 0000000..f79e682 --- /dev/null +++ b/app/src/main/res/drawable/ic_profile_light.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_remove.xml b/app/src/main/res/drawable/ic_remove.xml deleted file mode 100644 index a541177..0000000 --- a/app/src/main/res/drawable/ic_remove.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_visibility.xml b/app/src/main/res/drawable/ic_visibility.xml index 9a4b28c..ded970b 100644 --- a/app/src/main/res/drawable/ic_visibility.xml +++ b/app/src/main/res/drawable/ic_visibility.xml @@ -1,9 +1,14 @@ - + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + diff --git a/app/src/main/res/drawable/ic_website.xml b/app/src/main/res/drawable/ic_website.xml index 8324aee..475f7b4 100644 --- a/app/src/main/res/drawable/ic_website.xml +++ b/app/src/main/res/drawable/ic_website.xml @@ -1,5 +1,14 @@ - - + + + diff --git a/app/src/main/res/drawable/il_empty_cart.xml b/app/src/main/res/drawable/il_empty_cart.xml new file mode 100644 index 0000000..da4f26e --- /dev/null +++ b/app/src/main/res/drawable/il_empty_cart.xml @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/il_no_orders.xml b/app/src/main/res/drawable/il_no_orders.xml new file mode 100644 index 0000000..df32b02 --- /dev/null +++ b/app/src/main/res/drawable/il_no_orders.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xhdpi/plain_brown.xml b/app/src/main/res/drawable/plain_brown.xml similarity index 100% rename from app/src/main/res/drawable-xhdpi/plain_brown.xml rename to app/src/main/res/drawable/plain_brown.xml diff --git a/app/src/main/res/drawable-xhdpi/topping_on.xml b/app/src/main/res/drawable/topping_on.xml similarity index 100% rename from app/src/main/res/drawable-xhdpi/topping_on.xml rename to app/src/main/res/drawable/topping_on.xml diff --git a/app/src/main/res/font/bree_serif.xml b/app/src/main/res/font/bree_serif.xml new file mode 100644 index 0000000..feec39b --- /dev/null +++ b/app/src/main/res/font/bree_serif.xml @@ -0,0 +1,7 @@ + + + diff --git a/app/src/main/res/font/arimo.xml b/app/src/main/res/font/lato.xml similarity index 89% rename from app/src/main/res/font/arimo.xml rename to app/src/main/res/font/lato.xml index 109cd02..015fa0c 100644 --- a/app/src/main/res/font/arimo.xml +++ b/app/src/main/res/font/lato.xml @@ -2,6 +2,6 @@ diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 5211936..d07eb10 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -1,233 +1,252 @@ - - + android:layout_height="wrap_content" + tools:context="com.marknkamau.justjava.ui.about.AboutActivity"> + android:layout_height="match_parent" + android:background="@color/colorPrimaryDark"> - - + android:textColor="#FFFFFF" + android:textSize="24sp" + app:layout_constraintBottom_toTopOf="@+id/tvSourceCodeAbout" + app:layout_constraintStart_toEndOf="@+id/imageView3" + app:layout_constraintTop_toTopOf="@+id/imageView3" + app:layout_constraintVertical_chainStyle="packed" /> + android:textColor="@color/colorPrimaryLight" + app:layout_constraintBaseline_toBaselineOf="@+id/textView5" + app:layout_constraintStart_toEndOf="@+id/textView5" + tools:text="1.6.0 (debug)" /> - - - - - - - - - - - - - - - - - - - - + android:text="@string/source_code" + android:textColor="#ffffff" + app:layout_constraintBottom_toBottomOf="@+id/imageView3" + app:layout_constraintStart_toEndOf="@+id/imageView3" + app:layout_constraintTop_toBottomOf="@+id/textView5" /> - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_cart.xml b/app/src/main/res/layout/activity_cart.xml index 8c9dd82..8a47be7 100644 --- a/app/src/main/res/layout/activity_cart.xml +++ b/app/src/main/res/layout/activity_cart.xml @@ -1,101 +1,266 @@ - - - - - - - + + + + - - - - - - - - - - - - + android:layout_weight="1" + android:gravity="center" + android:orientation="vertical" + android:visibility="gone" + tools:visibility="visible"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_checkout.xml b/app/src/main/res/layout/activity_checkout.xml deleted file mode 100644 index a381234..0000000 --- a/app/src/main/res/layout/activity_checkout.xml +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_drink_details.xml b/app/src/main/res/layout/activity_drink_details.xml index ea90224..8937900 100644 --- a/app/src/main/res/layout/activity_drink_details.xml +++ b/app/src/main/res/layout/activity_drink_details.xml @@ -1,80 +1,41 @@ - + android:layout_height="wrap_content"> - + android:layout_height="wrap_content" + android:orientation="vertical" + tools:context="com.marknkamau.justjava.ui.drinkdetails.DrinkDetailsActivity"> - + android:contentDescription="@string/drink_image_content_desc" + android:scaleType="centerCrop" + android:transitionName="drinkImage" + tools:srcCompat="@tools:sample/backgrounds/scenic[0]" /> - + - - - - - - - - - - - - + - + + + diff --git a/app/src/main/res/layout/activity_log_in.xml b/app/src/main/res/layout/activity_log_in.xml index b6aebf2..14ebd1b 100644 --- a/app/src/main/res/layout/activity_log_in.xml +++ b/app/src/main/res/layout/activity_log_in.xml @@ -16,7 +16,7 @@ android:focusableInTouchMode="true"> + app:layout_constraintTop_toBottomOf="@+id/tilPasswordLogin" /> + app:layout_constraintLeft_toLeftOf="@+id/btnLoginLogin" + app:layout_constraintRight_toRightOf="@+id/btnLoginLogin" + app:layout_constraintTop_toBottomOf="@+id/btnLoginLogin" /> + app:layout_constraintGuide_percent="0.4" /> - + + - + android:layout_weight="1" + tools:itemCount="8" + tools:listitem="@layout/item_catalog" /> + + diff --git a/app/src/main/res/layout/activity_previous_order.xml b/app/src/main/res/layout/activity_previous_order.xml deleted file mode 100644 index cdcd667..0000000 --- a/app/src/main/res/layout/activity_previous_order.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/activity_previous_orders.xml b/app/src/main/res/layout/activity_previous_orders.xml new file mode 100644 index 0000000..c0a5167 --- /dev/null +++ b/app/src/main/res/layout/activity_previous_orders.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_profile.xml b/app/src/main/res/layout/activity_profile.xml index 57ddd42..42ca05e 100644 --- a/app/src/main/res/layout/activity_profile.xml +++ b/app/src/main/res/layout/activity_profile.xml @@ -1,201 +1,175 @@ - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - \ No newline at end of file + android:layout_gravity="center" + android:text="@string/you_do_not_have_any_previous_orders" /> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_sign_up.xml b/app/src/main/res/layout/activity_sign_up.xml index 2d457e1..6afa7c3 100644 --- a/app/src/main/res/layout/activity_sign_up.xml +++ b/app/src/main/res/layout/activity_sign_up.xml @@ -20,9 +20,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" - android:layout_marginTop="8dp" + android:layout_marginTop="16dp" android:layout_marginEnd="8dp" - android:fontFamily="@font/arimo" + android:fontFamily="@font/bree_serif" android:text="@string/app_name" android:textColor="@android:color/white" android:textSize="48sp" @@ -43,12 +43,12 @@ app:layout_constraintTop_toBottomOf="@+id/textView14" /> + app:layout_constraintTop_toBottomOf="@+id/tilPasswordSignUp"> + app:layout_constraintTop_toBottomOf="@+id/tilNameSignUp"> + app:layout_constraintTop_toBottomOf="@+id/tilPhoneSignUp"> - - + app:layout_constraintTop_toBottomOf="@+id/tilDeliveryAddressSignUp" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_view_order.xml b/app/src/main/res/layout/activity_view_order.xml new file mode 100644 index 0000000..298eafd --- /dev/null +++ b/app/src/main/res/layout/activity_view_order.xml @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_drink_details.xml b/app/src/main/res/layout/content_drink_details.xml index d36d321..c44f5d7 100644 --- a/app/src/main/res/layout/content_drink_details.xml +++ b/app/src/main/res/layout/content_drink_details.xml @@ -6,200 +6,209 @@ android:layout_height="wrap_content"> + tools:text="Ksh. 100" /> + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/tvDrinkNameDetail" + tools:text="Our beans are deeply roasted, out shots hand pulled. Taste the finest, freshly ground espresso shot in town." /> - - - - + app:layout_constraintTop_toBottomOf="@+id/tvDrinkDescriptionDetail" + tools:text="Just a shot of espresso" /> - + android:background="@color/colorTextTertiary" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/tvDrinkContentsDetail" /> + + + app:layout_constraintTop_toBottomOf="@+id/textView29" /> - + android:layout_marginStart="16dp" + android:layout_marginTop="8dp" + android:text="@string/chocolate_curls_ksh_xx" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/cbCinnamonDetail" /> - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/cbChocolateDetail" /> - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/cbMarshmallowDetail" /> - + app:layout_constraintTop_toBottomOf="@+id/view3" /> - + + + app:layout_constraintTop_toBottomOf="@+id/textView25" + app:srcCompat="@drawable/ic_minus" /> - + + + + + app:layout_constraintTop_toBottomOf="@+id/view4" /> - + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/view4" + tools:text="Ksh 200" /> + +