AA-14 | Mukunda | adding preliminary offer screen changes + integrating with application apis

This commit is contained in:
Mukunda
2019-11-14 10:22:14 +05:30
parent 445fbed377
commit 846e0745d6
59 changed files with 1764 additions and 314 deletions

View File

@@ -6,14 +6,16 @@ apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
def version_retrofit = '2.6.2'
def version_kotlin_coroutines = '1.3.2'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.navi.medici.android_customer_app"
applicationId "com.navi.medici.androidCustomerApp"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
@@ -46,8 +48,8 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.android.support:cardview-v7:29.0.2'
implementation 'com.android.support:design:29.0.2'
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'com.navi.medici.utils:amortization:1.1-SNAPSHOT'
}

View File

@@ -0,0 +1,83 @@
package com.navi.medici.androidCustomerApp.adapters
import android.content.Context
import android.graphics.Typeface
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.navi.medici.androidCustomerApp.databinding.EmiScheduleCardBinding
import com.navi.medici.androidCustomerApp.models.EmiSchedule
import java.text.SimpleDateFormat
import java.util.*
class EmiScheduleAdapter(private val context: Context) :
RecyclerView.Adapter<EmiScheduleAdapter.EmiScheduleViewHolder>() {
private val emiScheduleList = mutableListOf<EmiSchedule>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EmiScheduleViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = EmiScheduleCardBinding.inflate(layoutInflater, parent, false)
return EmiScheduleViewHolder(view)
}
fun setLoans(emiScheduleList: List<EmiSchedule>) {
this.emiScheduleList.clear()
this.emiScheduleList.addAll(emiScheduleList)
notifyDataSetChanged()
}
override fun getItemCount() = emiScheduleList.count()
override fun onBindViewHolder(holder: EmiScheduleViewHolder, position: Int) {
val emiSchedule = emiScheduleList[position]
holder.binding.apply {
when {
position == 0 -> {
emiNoTxt.text = "No."
emiAmountTxt.text = "EMI Amount"
emiDueDateTxt.text = "Due Date"
emiNoTxt.typeface = Typeface.DEFAULT_BOLD
emiAmountTxt.typeface = Typeface.DEFAULT_BOLD
emiDueDateTxt.typeface = Typeface.DEFAULT_BOLD
}
else -> {
emiNoTxt.text = position.toString()
emiAmountTxt.text =
emiSchedule.emi?.symbol.toString() + " " + emiSchedule.emi?.amount.toString()
emiDueDateTxt.text = convertDueDate("2019-11-13T12:23:36.087+0000")
}
}
}
}
fun convertDueDate(dueDate: String): String {
val tz = TimeZone.getTimeZone("UTC")
val df =
SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ") // Quoted "Z" to indicate UTC, no timezone offset
df.setTimeZone(tz)
val parsedDate = df.parse(dueDate)
var cal = Calendar.getInstance()
cal.time = parsedDate
val format2 =
SimpleDateFormat("dd'" + getDayNumberSuffix(cal.get(Calendar.DAY_OF_MONTH)) + "' MMM yyyy")
return format2.format(parsedDate)
}
private fun getDayNumberSuffix(day: Int): String {
if (day >= 11 && day <= 13) {
return "th"
}
when (day % 10) {
1 -> return "st"
2 -> return "nd"
3 -> return "rd"
else -> return "th"
}
}
class EmiScheduleViewHolder(val binding: EmiScheduleCardBinding) :
RecyclerView.ViewHolder(binding.root)
}

View File

@@ -29,7 +29,7 @@ class LoanDetailsTabAdapter(fm: FragmentManager) :
return when (position) {
0 -> "Loan Details"
else -> {
"EMI Schedule"
"EMI Schedule"
}
}
}

View File

@@ -0,0 +1,55 @@
package com.navi.medici.androidCustomerApp.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import com.navi.medici.androidCustomerApp.R
import com.navi.medici.androidCustomerApp.models.LoanReason
class LoanReasonAdapter(val context: Context, var loanReasonList: List<LoanReason>) :
BaseAdapter() {
val mInflater: LayoutInflater = LayoutInflater.from(context)
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view: View
val vh: ItemRowHolder
if (convertView == null) {
view = mInflater.inflate(R.layout.loan_reason, parent, false)
vh = ItemRowHolder(view)
view?.tag = vh
} else {
view = convertView
vh = view.tag as ItemRowHolder
}
// setting adapter item height programatically.
vh.label.text = loanReasonList.get(position).reason
return view
}
override fun getCount(): Int {
return loanReasonList.size
}
override fun getItem(position: Int): Any {
return loanReasonList.get(position)
}
override fun getItemId(position: Int): Long {
return loanReasonList.get(position).id.toLong()
}
private class ItemRowHolder(row: View?) {
val label: TextView
init {
this.label = row?.findViewById(R.id.loan_reason_txt) as TextView
}
}
}

View File

@@ -1,29 +1,44 @@
package com.navi.medici.androidCustomerApp.api
import com.navi.medici.androidCustomerApp.common.RetrofitService
import com.navi.medici.androidCustomerApp.bottomNavigation.loanApplication.models.OfferResponse
import com.navi.medici.androidCustomerApp.loan_application.models.OfferSelected
import com.navi.medici.androidCustomerApp.loan_application.models.OfferAcceptResponse
import com.navi.medici.androidCustomerApp.models.ApplicationSummary
import com.navi.medici.androidCustomerApp.models.OfferResponse
import com.navi.medici.androidCustomerApp.models.OfferSelected
import com.navi.medici.androidCustomerApp.models.response.CreateApplicationResponse
import com.navi.medici.androidCustomerApp.models.response.OfferAcceptResponse
import retrofit2.Response
import retrofit2.http.*
private const val BASE_URL = "https://loan-origination-service.np.navi-tech.in"
//private const val BASE_URL = "http://192.168.31.220:3020"
interface LoanApplicationApi {
@PUT("/los/apply-loan")
suspend fun acceptOffer(
@Body offerData: OfferSelected?
): Response<OfferAcceptResponse>
@PUT("/los/application")
suspend fun createApplication(
@Body offerData: OfferSelected?
): Response<CreateApplicationResponse>
@GET("/los/offers")
suspend fun fetchOffer(
@Query("person_id") personId: String?
): Response<OfferResponse>
@GET("/los/application/summary")
suspend fun fetchApplicationSummary(
@Query("application_id") applicationId: String?
): Response<ApplicationSummary>
companion object {
operator fun invoke(): LoanApplicationApi {
return RetrofitService.build(BASE_URL).create(
LoanApplicationApi::class.java)
LoanApplicationApi::class.java
)
}
}
}

View File

@@ -8,6 +8,7 @@ import retrofit2.http.Body
import retrofit2.http.POST
private const val BASE_URL = "https://auth-service.np.navi-tech.in"
//private const val BASE_URL = "http://192.168.31.220:3020"
interface LoginApi {
@POST("/auth/otps/generate")

View File

@@ -7,6 +7,7 @@ import retrofit2.http.GET
import retrofit2.http.Query
private const val BASE_URL = "https://loan-accounts-service.np.navi-tech.in"
//private const val BASE_URL = "http://192.168.31.220:3020"
interface MyLoansApi {
@GET("/v1/loan-account-service/loan-accounts")

View File

@@ -8,6 +8,7 @@ import retrofit2.http.Body
import retrofit2.http.POST
private const val BASE_URL = "https://auth-service.np.navi-tech.in"
//private const val BASE_URL = "http://192.168.31.220:3020"
interface OtpApi {
@POST("/auth/tokens")

View File

@@ -8,7 +8,7 @@ import retrofit2.http.Body
import retrofit2.http.PUT
private const val BASE_URL = "https://auth-service.np.navi-tech.in"
//private const val BASE_URL = "http://192.168.31.220:3020"
interface RegisterApi {
@PUT("/auth/app-installations/register")
suspend fun checkDevice(@Body registerRequest: RegisterRequest): Response<RegisterResponse>

View File

@@ -0,0 +1,8 @@
package com.navi.medici.androidCustomerApp.models
data class ApplicationSummary(
var applicationId: String? = "",
var installments: List<EmiSchedule>,
var loanApplicationDetails: LoanApplicationDetail
) {
}

View File

@@ -0,0 +1,4 @@
package com.navi.medici.androidCustomerApp.models
data class EmiSchedule(val emi: Money?, val numberOfMonthsRemaining: Int, val dueDate: String) {
}

View File

@@ -1,9 +1,7 @@
package com.navi.medici.androidCustomerApp.models
import com.navi.medici.androidCustomerApp.bottomNavigation.loanApplication.models.response.Money
class LoanAmount(
val min: Money?,
val max: Money?
val min: Money,
val max: Money
) {
}

View File

@@ -0,0 +1,15 @@
package com.navi.medici.androidCustomerApp.models
import java.math.BigDecimal
data class LoanApplicationDetail(
val id: Int,
val loanAmount: Money,
val reason: String,
val tenure: TenureDetails,
val rateOfInterest: BigDecimal,
val personId: String,
val offerId: String,
val tenureValue: Int,
val customerId: Int
)

View File

@@ -0,0 +1,4 @@
package com.navi.medici.androidCustomerApp.models
data class LoanReason(val id: Int, val reason: String) {
}

View File

@@ -1,8 +1,14 @@
package com.navi.medici.androidCustomerApp.bottomNavigation.loanApplication.models.response
package com.navi.medici.androidCustomerApp.models
import java.math.BigDecimal
data class Money(
val currency: String?,
val symbol: String?,
val amount: Int
val amount: BigDecimal
) {
fun getDisplayStr(): String {
return "$symbol. $amount"
}
}

View File

@@ -1,13 +1,15 @@
package com.navi.medici.androidCustomerApp.bottomNavigation.loanApplication.models
package com.navi.medici.androidCustomerApp.models
import com.navi.medici.androidCustomerApp.models.LoanAmount
import com.navi.medici.androidCustomerApp.models.OfferTenure
import java.math.BigDecimal
data class OfferResponse(
var schemeId: String? = "",
var personId: String? = "",
var loanAmount: LoanAmount?,
var loanAmount: LoanAmount,
var tenure: OfferTenure?,
var rateOfInterest: Double
var rateOfInterest: BigDecimal,
var loanReasons: List<LoanReason>
) {
}

View File

@@ -1,13 +1,14 @@
package com.navi.medici.androidCustomerApp.loan_application.models
package com.navi.medici.androidCustomerApp.models
import com.navi.medici.androidCustomerApp.bottomNavigation.loanApplication.models.response.Money
import java.math.BigDecimal
data class OfferSelected(
var personId: String? = "",
var offerId: String? = "",
var loanAmount: Money?,
var tenure: TenureDetails?,
var rateOfInterest: Double? = 0.0
var rateOfInterest: BigDecimal? = BigDecimal(0),
var selectionReasonId: Long?
) {
}

View File

@@ -1,7 +1,5 @@
package com.navi.medici.androidCustomerApp.models
import com.navi.medici.androidCustomerApp.loan_application.models.TenureDetails
class OfferTenure(
val min: TenureDetails?,
val max: TenureDetails?

View File

@@ -1,7 +1,10 @@
package com.navi.medici.androidCustomerApp.loan_application.models
package com.navi.medici.androidCustomerApp.models
data class TenureDetails(
val value: Int = 0,
val unit: String = ""
) {
fun getDisplayStr(): String {
return "$value $unit"
}
}

View File

@@ -0,0 +1,20 @@
package com.navi.medici.androidCustomerApp.models
enum class TenureUnit(val unit: String) {
MONTH("months"),
DAYS("days"),
HOURS("hrs");
// TODO: update it to a map
companion object {
fun getTenureUnitByValue(unit: String): TenureUnit {
return when (unit) {
"months" -> MONTH
"days" -> DAYS
"hrs" -> HOURS
else -> MONTH
}
}
}
}

View File

@@ -0,0 +1,4 @@
package com.navi.medici.androidCustomerApp.models.response
data class CreateApplicationResponse(val applicationId: String?) {
}

View File

@@ -1,4 +1,4 @@
package com.navi.medici.androidCustomerApp.loan_application.models
package com.navi.medici.androidCustomerApp.models.response
data class OfferAcceptResponse(
val customerId: String? = ""

View File

@@ -1,38 +1,52 @@
package com.navi.medici.androidCustomerApp.preferences
import android.app.Activity
import android.content.Context
import android.content.SharedPreferences
object PreferenceManager {
val PREFS_FILENAME = "com.navi.medici.android_customer_app.preferences"
fun getStringPreference(context: Context, preference: PreferenceNames): String? {
val sharedPref: SharedPreferences =
context.getSharedPreferences(PREFS_FILENAME, Context.MODE_PRIVATE)
return sharedPref.getString(preference.name, "")
fun getPersonId(context: Context): String? {
return PreferenceWrapper.getStringPreference(
context,
PreferenceNames.PERSON_ID
)
}
fun setStringPreference(context: Context, preference: PreferenceNames, value: String?) {
val sharedPref: SharedPreferences =
context.getSharedPreferences(PREFS_FILENAME, Context.MODE_PRIVATE)
val editor = sharedPref.edit()
editor.putString(preference.name, value)
editor.apply()
fun getCustomerId(context: Context): String? {
return PreferenceWrapper.getStringPreference(
context,
PreferenceNames.CUSTOMER_ID
)
}
fun getIntPreference(context: Context, preference: PreferenceNames): Int {
val sharedPref: SharedPreferences =
context.getSharedPreferences(PREFS_FILENAME, Context.MODE_PRIVATE)
return sharedPref.getInt(preference.name, 0)
fun getApplicationId(context: Context): String? {
return PreferenceWrapper.getStringPreference(
context,
PreferenceNames.CUSTOMER_ID
)
}
fun setIntPreference(context: Context, preference: PreferenceNames, value: Int) {
val sharedPref: SharedPreferences =
context.getSharedPreferences(PREFS_FILENAME, Context.MODE_PRIVATE)
val editor = sharedPref.edit()
editor.putInt(preference.name, value)
editor.apply()
fun saveCustomerId(customerId: String?, activity: Activity) {
PreferenceWrapper.setStringPreference(
activity,
PreferenceNames.CUSTOMER_ID,
customerId
)
}
fun savePersonId(personId: String?, activity: Activity) {
PreferenceWrapper.setStringPreference(
activity,
PreferenceNames.PERSON_ID,
personId
)
}
fun saveApplicationId(applicationId: String?, activity: Activity) {
PreferenceWrapper.setStringPreference(
activity,
PreferenceNames.APPLICATION_ID,
applicationId
)
}
fun getBooleanPreference(

View File

@@ -7,5 +7,6 @@ enum class PreferenceNames {
APPROVED_AMOUT,
IMEI,
PHONE_NUMBER,
NOT_FIRST_TIME_USER
NOT_FIRST_TIME_USER,
APPLICATION_ID
}

View File

@@ -0,0 +1,37 @@
package com.navi.medici.androidCustomerApp.preferences
import android.content.Context
import android.content.SharedPreferences
object PreferenceWrapper {
val PREFS_FILENAME = "com.navi.medici.androidCustomerApp.preferences"
fun getStringPreference(context: Context, preference: PreferenceNames): String? {
val sharedPref: SharedPreferences =
context.getSharedPreferences(PREFS_FILENAME, Context.MODE_PRIVATE)
return sharedPref.getString(preference.name, "")
}
fun setStringPreference(context: Context, preference: PreferenceNames, value: String?) {
val sharedPref: SharedPreferences =
context.getSharedPreferences(PREFS_FILENAME, Context.MODE_PRIVATE)
val editor = sharedPref.edit()
editor.putString(preference.name, value)
editor.apply()
}
fun getIntPreference(context: Context, preference: PreferenceNames): Int {
val sharedPref: SharedPreferences =
context.getSharedPreferences(PREFS_FILENAME, Context.MODE_PRIVATE)
return sharedPref.getInt(preference.name, 0)
}
fun setIntPreference(context: Context, preference: PreferenceNames, value: Int) {
val sharedPref: SharedPreferences =
context.getSharedPreferences(PREFS_FILENAME, Context.MODE_PRIVATE)
val editor = sharedPref.edit()
editor.putInt(preference.name, value)
editor.apply()
}
}

View File

@@ -1,9 +1,11 @@
package com.navi.medici.androidCustomerApp.loan_application
import com.navi.medici.androidCustomerApp.api.LoanApplicationApi
import com.navi.medici.androidCustomerApp.loan_application.models.OfferSelected
import com.navi.medici.androidCustomerApp.models.OfferSelected
class LoanApplicationRepository(private val loanApplicationApi: LoanApplicationApi) {
suspend fun offerAccept(offerAcceptInput: OfferSelected?) = suspend { loanApplicationApi.acceptOffer(offerAcceptInput) }.invoke()
suspend fun createApplication(offerAcceptInput: OfferSelected?) = suspend { loanApplicationApi.createApplication(offerAcceptInput) }.invoke()
suspend fun fetchOffer(personId: String?) = suspend { loanApplicationApi.fetchOffer(personId) }.invoke()
suspend fun fetchApplicationSummary(applicationId: String?) = suspend { loanApplicationApi.fetchApplicationSummary(applicationId) }.invoke()
}

View File

@@ -8,6 +8,7 @@ import com.navi.medici.androidCustomerApp.R
import com.navi.medici.androidCustomerApp.ui.fragments.OfferAcceptFragment
import com.navi.medici.androidCustomerApp.ui.fragments.MyLoansFragment
import com.navi.medici.androidCustomerApp.databinding.ActivityBottomNavigationBinding
import com.navi.medici.androidCustomerApp.ui.fragments.PreliminaryOfferFragment
class BottomNavigationActivity : FragmentActivity() {
@@ -21,12 +22,14 @@ class BottomNavigationActivity : FragmentActivity() {
navigateToPage(it.itemId)
}
var tagId = intent.getStringExtra("TAG_ID");
if(tagId != null && tagId.equals(MyLoansFragment.TAG)) {
binding.bottomNavigationView.selectedItemId = R.id.my_loans
} else {
binding.bottomNavigationView.selectedItemId = R.id.home
var tagId = intent.getStringExtra("TAG_ID")
binding.bottomNavigationView.selectedItemId = when (tagId) {
MyLoansFragment.TAG -> R.id.my_loans
OfferAcceptFragment.TAG -> R.id.offer_accept
PreliminaryOfferFragment.TAG -> R.id.preliminary_offer
else -> R.id.home
}
}
private fun navigateToPage(itemId: Int): Boolean {
@@ -46,16 +49,18 @@ class BottomNavigationActivity : FragmentActivity() {
private fun getFragment(itemId: Int): Fragment {
return when (itemId) {
R.id.home -> OfferAcceptFragment()
R.id.home -> PreliminaryOfferFragment()
R.id.my_loans -> MyLoansFragment()
R.id.preliminary_offer -> PreliminaryOfferFragment()
else -> OfferAcceptFragment()
}
}
private fun getFragmentTag(itemId: Int): String {
return when (itemId) {
R.id.home -> MyLoansFragment.TAG
R.id.home -> PreliminaryOfferFragment.TAG
R.id.my_loans -> OfferAcceptFragment.TAG
R.id.preliminary_offer -> PreliminaryOfferFragment.TAG
else -> MyLoansFragment.TAG
}
}

View File

@@ -11,6 +11,7 @@ import com.navi.medici.androidCustomerApp.R
import com.navi.medici.androidCustomerApp.databinding.ActivityLoginBinding
import com.navi.medici.androidCustomerApp.preferences.PreferenceManager
import com.navi.medici.androidCustomerApp.preferences.PreferenceNames
import com.navi.medici.androidCustomerApp.preferences.PreferenceWrapper
import com.navi.medici.androidCustomerApp.utils.showServiceNotAvailableToast
import com.navi.medici.androidCustomerApp.viewModels.LoginViewModel
@@ -27,7 +28,7 @@ class LoginActivity : AppCompatActivity() {
loginViewModel.otpTokenAndPhone.observe(this, loggedInObserver())
binding.phoneEdit.addTextChangedListener {
PreferenceManager.getStringPreference(
PreferenceWrapper.getStringPreference(
this,
PreferenceNames.IMEI
)?.let { imei ->
@@ -41,7 +42,7 @@ class LoginActivity : AppCompatActivity() {
private fun loggedInObserver(): Observer<Pair<String, String>> {
return Observer { otpTokenAndPhone ->
PreferenceManager.setStringPreference(
PreferenceWrapper.setStringPreference(
this,
PreferenceNames.PHONE_NUMBER,
otpTokenAndPhone.second

View File

@@ -1,6 +1,5 @@
package com.navi.medici.androidCustomerApp.ui.activities
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
@@ -13,6 +12,7 @@ import com.navi.medici.androidCustomerApp.R
import com.navi.medici.androidCustomerApp.databinding.ActivityOtpBinding
import com.navi.medici.androidCustomerApp.preferences.PreferenceManager
import com.navi.medici.androidCustomerApp.preferences.PreferenceNames
import com.navi.medici.androidCustomerApp.preferences.PreferenceWrapper
import com.navi.medici.androidCustomerApp.viewModels.OtpViewModel
class OtpActivity : AppCompatActivity() {
@@ -25,7 +25,7 @@ class OtpActivity : AppCompatActivity() {
binding = DataBindingUtil.setContentView(this, R.layout.activity_otp)
otpViewModel = ViewModelProviders.of(this).get(OtpViewModel::class.java)
val phoneNumber = PreferenceManager.getStringPreference(
val phoneNumber = PreferenceWrapper.getStringPreference(
this,
PreferenceNames.PHONE_NUMBER
)
@@ -53,7 +53,7 @@ class OtpActivity : AppCompatActivity() {
private fun verifiedOtpObserver(): Observer<Boolean> {
return Observer {
if (it) {
savePersonId(otpViewModel.personId, this)
PreferenceManager.savePersonId(otpViewModel.personId, this)
val intent = Intent(this, UploadPanActivity::class.java)
startActivity(intent)
} else {
@@ -61,12 +61,4 @@ class OtpActivity : AppCompatActivity() {
}
}
}
private fun savePersonId(personId: String?, activity: Activity) {
PreferenceManager.setStringPreference(
activity,
PreferenceNames.PERSON_ID,
personId
)
}
}

View File

@@ -17,6 +17,7 @@ import androidx.lifecycle.ViewModelProviders
import com.navi.medici.androidCustomerApp.R
import com.navi.medici.androidCustomerApp.preferences.PreferenceManager
import com.navi.medici.androidCustomerApp.preferences.PreferenceNames
import com.navi.medici.androidCustomerApp.preferences.PreferenceWrapper
import com.navi.medici.androidCustomerApp.utils.showServiceNotAvailableToast
import com.navi.medici.androidCustomerApp.viewModels.SplashScreenViewModel
@@ -72,7 +73,7 @@ class SplashScreenActivity : AppCompatActivity() {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getImei().let {
splashScreenViewModel.checkDevice(it)
PreferenceManager.setStringPreference(
PreferenceWrapper.setStringPreference(
this,
PreferenceNames.IMEI,
it

View File

@@ -1,7 +1,46 @@
package com.navi.medici.androidCustomerApp.ui.fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import com.navi.medici.androidCustomerApp.R
import com.navi.medici.androidCustomerApp.adapters.EmiScheduleAdapter
import com.navi.medici.androidCustomerApp.databinding.EmiScheduleFragmentBinding
import com.navi.medici.androidCustomerApp.viewModels.OfferAcceptViewModel
class EmiScheduleFragment : Fragment() {
private lateinit var binding: EmiScheduleFragmentBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val activity = activity as FragmentActivity
val viewModel =
ViewModelProviders.of(activity).get(OfferAcceptViewModel::class.java)
binding = DataBindingUtil.inflate(
inflater,
R.layout.emi_schedule_fragment,
container,
false
)
viewModel.applicationSummary.observe(this, Observer { summary ->
val emiScheduleAdapter = EmiScheduleAdapter(activity)
emiScheduleAdapter.setLoans(summary.installments)
binding.emiScheduleRecyclerView.layoutManager = LinearLayoutManager(activity)
binding.emiScheduleRecyclerView.adapter = emiScheduleAdapter
})
return binding.root
}
}

View File

@@ -32,10 +32,16 @@ class LoanDetailsFragment : Fragment() {
false
)
viewModel.offerSelected.observe(this, Observer { offer ->
binding.totalAmount.setText(offer.loanAmount?.symbol.toString() + ". " + offer.loanAmount?.amount.toString())
viewModel.applicationSummary.observe(this, Observer { summary ->
binding.loanAmountTxt.setText(summary.loanApplicationDetails.loanAmount.symbol + " " + summary.loanApplicationDetails.loanAmount.amount.toInt().toString())
binding.interestTxt.setText(summary.loanApplicationDetails.rateOfInterest.toString() + "%")
binding.emiTxt.setText(summary.installments[0].emi?.amount?.toInt().toString())
})
// viewModel.offerSelected.observe(this, Observer { offer ->
// binding.totalAmount.setText(offer.loanAmount?.symbol.toString() + ". " + offer.loanAmount?.loanAmount.toString())
// })
return binding.root
}
}

View File

@@ -1,6 +1,5 @@
package com.navi.medici.androidCustomerApp.ui.fragments
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -12,11 +11,10 @@ import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import com.navi.medici.androidCustomerApp.R
import com.navi.medici.androidCustomerApp.adapters.MyLoansAdapter
import com.navi.medici.androidCustomerApp.models.response.MyLoansResponse
import com.navi.medici.androidCustomerApp.viewModels.MyLoansViewModel
import com.navi.medici.androidCustomerApp.databinding.MyLoansFragmentBinding
import com.navi.medici.androidCustomerApp.models.response.MyLoansResponse
import com.navi.medici.androidCustomerApp.preferences.PreferenceManager
import com.navi.medici.androidCustomerApp.preferences.PreferenceNames
import com.navi.medici.androidCustomerApp.viewModels.MyLoansViewModel
class MyLoansFragment : Fragment() {
private lateinit var viewModel: MyLoansViewModel
@@ -58,17 +56,11 @@ class MyLoansFragment : Fragment() {
)
)
viewModel.fetchMyLoans(getCustomerId(it))
viewModel.fetchMyLoans(PreferenceManager.getCustomerId(it))
}
return binding.root
}
private fun getCustomerId(context: Context): String? {
return PreferenceManager.getStringPreference(
context,
PreferenceNames.CUSTOMER_ID
)
}
private fun myLoansObserver(
myActiveLoansAdapter: MyLoansAdapter,

View File

@@ -1,11 +1,12 @@
package com.navi.medici.androidCustomerApp.ui.fragments
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
@@ -21,6 +22,7 @@ import com.navi.medici.androidCustomerApp.preferences.PreferenceNames
import com.navi.medici.androidCustomerApp.ui.activities.BottomNavigationActivity
import com.navi.medici.androidCustomerApp.viewModels.OfferAcceptViewModel
class OfferAcceptFragment : Fragment() {
private lateinit var viewModel: OfferAcceptViewModel
private lateinit var binding: OfferAcceptFragmentBinding
@@ -50,13 +52,15 @@ class OfferAcceptFragment : Fragment() {
binding.offerAcceptViewpager.adapter = fragmentAdapter
binding.tabLayout.setupWithViewPager(binding.offerAcceptViewpager)
val activity = activity as FragmentActivity
viewModel = ViewModelProviders.of(activity).get(OfferAcceptViewModel::class.java)
viewModel.fetchOffers(getPersonId(activity))
animateLoanApproval()
viewModel.fetchApplication(PreferenceManager.getApplicationId(activity))
binding.acceptOfferBtn.setOnClickListener {
if (binding.checkbox.isChecked) {
viewModel.onSubmitOfferAccept()
viewModel.onSubmitOfferAccept(PreferenceManager.getPersonId(activity))
} else {
var errorMessage = Toast.makeText(
activity,
@@ -69,7 +73,7 @@ class OfferAcceptFragment : Fragment() {
viewModel.customerId.observe(this, Observer { customerId ->
if (customerId.isNotEmpty()) {
saveCustomerId(customerId, activity)
PreferenceManager.saveCustomerId(customerId, activity)
openMyLoansPage()
}
})
@@ -82,19 +86,22 @@ class OfferAcceptFragment : Fragment() {
startActivity(intent)
}
private fun saveCustomerId(customerId: String?, activity: Activity) {
PreferenceManager.setStringPreference(
activity,
PreferenceNames.CUSTOMER_ID,
customerId
)
fun animateLoanApproval() {
binding.fireworkImage11.startAnimation(buildAnimation(200))
binding.fireworkImage12.startAnimation(buildAnimation(400))
binding.fireworkImage13.startAnimation(buildAnimation(600))
binding.fireworkImage21.startAnimation(buildAnimation(200))
binding.fireworkImage22.startAnimation(buildAnimation(400))
binding.fireworkImage23.startAnimation(buildAnimation(600))
}
private fun getPersonId(activity: Activity): String? {
return PreferenceManager.getStringPreference(
activity,
PreferenceNames.PERSON_ID
)
fun buildAnimation(startOffet: Long): Animation {
val aniSlide =
AnimationUtils.loadAnimation(context, R.anim.zoom_in)
aniSlide.startOffset = startOffet
aniSlide.duration = 2000
return aniSlide
}
companion object {

View File

@@ -0,0 +1,197 @@
package com.navi.medici.androidCustomerApp.ui.fragments
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.SeekBar
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.navi.medici.androidCustomerApp.R
import com.navi.medici.androidCustomerApp.adapters.LoanReasonAdapter
import com.navi.medici.androidCustomerApp.databinding.PreliminaryOfferFragmentBinding
import com.navi.medici.androidCustomerApp.models.Money
import com.navi.medici.androidCustomerApp.models.TenureDetails
import com.navi.medici.androidCustomerApp.models.TenureUnit
import com.navi.medici.androidCustomerApp.preferences.PreferenceManager
import com.navi.medici.androidCustomerApp.ui.activities.BottomNavigationActivity
import com.navi.medici.androidCustomerApp.viewModels.PreliminaryOfferViewModel
import kotlinx.android.synthetic.main.amount_dialog.view.amount_edt
import kotlinx.android.synthetic.main.amount_dialog.view.ok_btn
import kotlinx.android.synthetic.main.tenure_dialog.view.*
class PreliminaryOfferFragment : Fragment() {
private lateinit var binding: PreliminaryOfferFragmentBinding
private lateinit var viewModel: PreliminaryOfferViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(
inflater,
R.layout.preliminary_offer_fragment,
container,
false
)
val activity = activity as FragmentActivity
viewModel = ViewModelProviders.of(activity).get(PreliminaryOfferViewModel::class.java)
binding.viewModel = viewModel
binding.executePendingBindings()
//TODO: fetches the existing offers.Remove this post fetch offer screen is built
viewModel.fetchOffers(PreferenceManager.getPersonId(activity))
viewModel.offerResponse.observe(this, Observer { offer ->
binding.amountSlider.max = viewModel.scaleToAmountMap.size - 1
binding.tenureSlider.max = viewModel.scaleToTenureMap.size - 1
var loanAmount = viewModel.offerResponse.value?.loanAmount
var loanTenure = viewModel.offerResponse.value?.tenure
binding.minAmountTxt.setText(loanAmount?.min?.getDisplayStr())
binding.maxAmountTxt.setText(loanAmount?.max?.getDisplayStr())
binding.minTenureTxt.setText(loanTenure?.min?.getDisplayStr())
binding.maxTenureTxt.setText(loanTenure?.max?.getDisplayStr())
binding.tenureSlider.progress = binding.tenureSlider.max / 2
binding.amountSlider.progress = binding.amountSlider.max / 2
binding.reasonSpinner.adapter = LoanReasonAdapter(activity, offer.loanReasons)
})
binding.amountSlider.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
var amount = viewModel.scaleToAmountMap.get(seekBar.progress)
updateAmount(amount)
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
}
})
binding.tenureSlider.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
var tenureDetails = viewModel.scaleToTenureMap.get(seekBar.progress)
updateTenure(tenureDetails)
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
}
})
viewModel.applicationId.observe(this, Observer { applicationId ->
PreferenceManager.saveApplicationId(applicationId, activity)
openOfferAcceptFragment()
})
binding.loanSelectedAmountTxt.setOnClickListener {
showAmountDialog()
}
binding.tenureSelectedTxt.setOnClickListener {
showTenureDialog()
}
binding.acceptOfferBtn.setOnClickListener {
viewModel.onSubmitApplicationCreate(
PreferenceManager.getPersonId(activity),
binding.reasonSpinner.selectedItemId
)
}
return binding.root
}
fun updateAmount(amount: Money?) {
viewModel.setSelectedLoanAmount(amount)
// binding.loanSelectedAmountTxt.setText(amount?.currency + " " + amount?.amount)
}
fun updateTenure(tenureDetails: TenureDetails?) {
viewModel.setSelectedTenureDetails(tenureDetails)
// binding.tenureSelectedTxt.setText(tenureDetails?.value.toString() + " " + tenureDetails?.unit)
}
fun showAmountDialog() {
val dialogBuilder = AlertDialog.Builder(context)
val inflater = this.layoutInflater
val dialogView = inflater.inflate(R.layout.amount_dialog, null)
dialogBuilder.setView(dialogView)
val alertDialog = dialogBuilder.create()
dialogView.ok_btn.setOnClickListener {
if (dialogView.amount_edt.text.toString().isNotEmpty()) {
var amount = dialogView.amount_edt.text.toString().toBigDecimal()
var maxAmount = viewModel.getLoanAmount()?.max
maxAmount?.let {
if (amount > maxAmount.amount) {
amount = maxAmount.amount
}
}
updateAmount(Money(maxAmount?.currency, maxAmount?.symbol, amount))
}
alertDialog.dismiss()
}
alertDialog.show()
}
fun showTenureDialog() {
val dialogBuilder = AlertDialog.Builder(context)
val inflater = this.layoutInflater
val dialogView = inflater.inflate(R.layout.tenure_dialog, null)
dialogBuilder.setView(dialogView)
var tenureTypes = arrayOf(TenureUnit.DAYS.unit, TenureUnit.MONTH.unit)
val mainActivity = activity as Activity
val arrayAdapter =
ArrayAdapter(mainActivity, android.R.layout.simple_list_item_1, tenureTypes)
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
dialogView.tenure_type_spinner!!.setAdapter(arrayAdapter)
val alertDialog = dialogBuilder.create()
dialogView.ok_btn.setOnClickListener {
if (dialogView.tenure_edt.text.toString().isNotEmpty()) {
var tenure = dialogView.tenure_edt.text.toString().toInt()
var tenureType = dialogView.tenure_type_spinner.selectedItem.toString()
var maxTenure = viewModel.getTenure()?.max
maxTenure?.let {
if (tenure > maxTenure.value && tenureType.equals(maxTenure.unit)) {
tenure = maxTenure.value
}
}
updateTenure(TenureDetails(tenure, tenureType))
}
alertDialog.dismiss()
}
alertDialog.show()
}
private fun openOfferAcceptFragment() {
val intent = Intent(activity, BottomNavigationActivity::class.java)
intent.putExtra("TAG_ID", OfferAcceptFragment.TAG)
startActivity(intent)
}
companion object {
const val TAG = "PRELIMINORY_OFFER_FRAGMENT"
}
}

View File

@@ -0,0 +1,23 @@
package com.navi.medici.androidCustomerApp.utils
import com.navi.medici.androidCustomerApp.models.TenureDetails
import com.navi.medici.androidCustomerApp.models.TenureUnit
import com.navi.medici.utils.amortization.EmiCalculator
import org.joda.money.BigMoney
import org.joda.money.CurrencyUnit
import java.math.BigDecimal
class EmiCalculator() {
fun calculateEmi(amount: BigDecimal, interestRate: BigDecimal, tenure: TenureDetails): BigDecimal {
val loanTenureInMonths: Int
if (tenure.unit.equals(TenureUnit.DAYS.unit)) {
loanTenureInMonths = 1
} else {
loanTenureInMonths = tenure.value
}
var principalAmount = BigMoney.of(CurrencyUnit.of("INR"), BigDecimal(amount.toDouble()))
val emiValue = EmiCalculator(principalAmount, interestRate, loanTenureInMonths).calculate()
return emiValue.amount
}
}

View File

@@ -0,0 +1,22 @@
package com.navi.medici.androidCustomerApp.utils
import com.navi.medici.androidCustomerApp.models.*
import java.math.BigDecimal
class MockResponseBuilder {
fun buildSampleOfferResponse(): OfferResponse? {
var offerTenure = OfferTenure(TenureDetails(1, "day"), TenureDetails(6, "months"))
var loanReasons =
arrayListOf(LoanReason(1, "home construction"), LoanReason(1, "personal emergency"))
var offerResponseVal: OfferResponse? = OfferResponse(
"1",
"123",
LoanAmount(Money("Rs", "Rs", 500.toBigDecimal()), Money("Rs", "Rs", 25000.toBigDecimal())),
offerTenure,
BigDecimal(12.5),
loanReasons
)
return offerResponseVal
}
}

View File

@@ -0,0 +1,41 @@
package com.navi.medici.androidCustomerApp.utils
import com.navi.medici.androidCustomerApp.models.*
import java.math.BigDecimal
class StepFunctionCalculator {
val STEP_FUNCTION_AMOUNT = 500
fun buildTenureStepFunction(offerResponse: OfferResponse?): MutableList<TenureDetails> {
var stepFunctionVals = ArrayList<TenureDetails>()
for (tenureVal in 1 until 30) {
stepFunctionVals.add(TenureDetails(tenureVal, TenureUnit.DAYS.unit))
}
var minMonth: Int = 12
offerResponse?.tenure?.max?.let {
if (it.unit.equals(TenureUnit.MONTH.unit)) {
minMonth = it.value
}
}
for (tenureVal in 1 until minMonth + 1) {
stepFunctionVals.add(TenureDetails(tenureVal, TenureUnit.MONTH.unit))
}
return stepFunctionVals
}
fun buildScaleToAmountMap(loanAmount: LoanAmount) : MutableList<Money>{
var minAmount = loanAmount.min.amount
var stepFunctionVals = ArrayList<Money>()
var index = 0
while (minAmount <= loanAmount.max.amount) {
stepFunctionVals.add(Money(loanAmount.max.currency, loanAmount.max.symbol, minAmount))
minAmount += BigDecimal(STEP_FUNCTION_AMOUNT)
index++
}
return stepFunctionVals
}
}

View File

@@ -4,9 +4,9 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.navi.medici.androidCustomerApp.api.LoanApplicationApi
import com.navi.medici.androidCustomerApp.bottomNavigation.loanApplication.models.OfferResponse
import com.navi.medici.androidCustomerApp.loan_application.LoanApplicationRepository
import com.navi.medici.androidCustomerApp.loan_application.models.OfferSelected
import com.navi.medici.androidCustomerApp.models.ApplicationSummary
import com.navi.medici.androidCustomerApp.models.OfferSelected
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -17,40 +17,60 @@ class OfferAcceptViewModel : ViewModel() {
val customerId: LiveData<String>
get() = _customerId
var offerSelected = MutableLiveData<OfferSelected>();
private val offerAcceptRepository = LoanApplicationRepository(LoanApplicationApi())
private val coroutineScope = CoroutineScope(Dispatchers.Main)
fun onSubmitOfferAccept() {
coroutineScope.launch {
offerSelected.value?.let {
val response = offerAcceptRepository.offerAccept(offerSelected.value)
if (response.isSuccessful) {
_customerId.value = response.body()?.customerId
Timber.i("Offer Accept response ${response.body().toString()}")
}
}
}
}
val applicationSummary = MutableLiveData<ApplicationSummary>()
fun fetchOffers(personId: String?) {
fun onSubmitOfferAccept(personId: String?) {
coroutineScope.launch {
val response = offerAcceptRepository.fetchOffer(personId)
if (response.isSuccessful) {
selectOffer(response.body(), personId)
Timber.i("OfferSelected response ${response.body().toString()}")
}
}
}
private fun selectOffer(offerResponse: OfferResponse?, personId: String?) {
offerSelected.value =
OfferSelected(
var applicationDetail = applicationSummary.value?.loanApplicationDetails
// TODO: updateit to send only the application id
var offerSelected = OfferSelected(
personId,
offerResponse?.schemeId,
offerResponse?.loanAmount?.max,
offerResponse?.tenure?.max,
offerResponse?.rateOfInterest
applicationDetail?.offerId,
applicationDetail?.loanAmount,
applicationDetail?.tenure,
applicationDetail?.rateOfInterest,
1
)
val response = offerAcceptRepository.offerAccept(offerSelected)
if (response.isSuccessful) {
_customerId.value = response.body()?.customerId
Timber.i("Offer Accept response $response.body().toString()")
}
}
}
fun fetchApplication(applicationId: String?) {
coroutineScope.launch {
val response = offerAcceptRepository.fetchApplicationSummary(applicationId)
if (response.isSuccessful) {
applicationSummary.value = response.body()
Timber.i("OfferSelected response $response.body().toString()")
}
}
}
// fun fetchOffers(personId: String?) {
// coroutineScope.launch {
// val response = offerAcceptRepository.fetchOffer(personId)
// if (response.isSuccessful) {
// selectOffer(response.body(), personId)
// Log.i("OfferSelected response", response.body().toString())
// }
// }
// }
// private fun selectOffer(offerResponse: OfferResponse?, personId: String?) {
// offerSelected.value =
// OfferSelected(
// personId,
// offerResponse?.schemeId,
// offerResponse?.loanAmount?.max,
// offerResponse?.tenure?.max,
// offerResponse?.rateOfInterest
// )
// }
}

View File

@@ -0,0 +1,130 @@
package com.navi.medici.androidCustomerApp.viewModels
import android.util.Log
import android.widget.SeekBar
import androidx.databinding.ObservableField
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.navi.medici.androidCustomerApp.api.LoanApplicationApi
import com.navi.medici.androidCustomerApp.loan_application.LoanApplicationRepository
import com.navi.medici.androidCustomerApp.models.*
import com.navi.medici.androidCustomerApp.utils.EmiCalculator
import com.navi.medici.androidCustomerApp.utils.MockResponseBuilder
import com.navi.medici.androidCustomerApp.utils.StepFunctionCalculator
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.math.BigDecimal
class PreliminaryOfferViewModel : ViewModel() {
var scaleToTenureMap = HashMap<Int, TenureDetails>()
var scaleToAmountMap = HashMap<Int, Money>()
private val _applicationId = MutableLiveData<String>()
val applicationId: LiveData<String>
get() = _applicationId
private val offerAcceptRepository = LoanApplicationRepository(LoanApplicationApi())
private val coroutineScope = CoroutineScope(Dispatchers.Main)
var offerResponse = MutableLiveData<OfferResponse>();
var selectedLoanAmount = ObservableField<Money?>()
var selectedTenureDetails = ObservableField<TenureDetails?>()
var emiValue = ObservableField<String>()
fun fetchOffers(personId: String?) {
coroutineScope.launch {
val response = offerAcceptRepository.fetchOffer(personId)
if (response.isSuccessful) {
var offerResponseVal = response.body()
buildAmountTenureMap(offerResponseVal)
offerResponse.value = offerResponseVal
Log.i("OfferSelected response", offerResponseVal.toString())
}
}
}
fun onSubmitApplicationCreate(
personId: String?,
selectionReasonId: Long?
) {
coroutineScope.launch {
var offerSelected = OfferSelected(
personId,
offerResponse.value?.schemeId,
selectedLoanAmount.get(),
selectedTenureDetails.get(),
offerResponse.value?.rateOfInterest,
selectionReasonId
)
val response = offerAcceptRepository.createApplication(offerSelected)
if (response.isSuccessful) {
_applicationId.value = response.body()?.applicationId
Log.i("CreateAplctn response", response.body().toString())
}
}
}
fun getLoanAmount(): LoanAmount? {
return offerResponse.value?.loanAmount
}
fun getTenure(): OfferTenure? {
return offerResponse.value?.tenure
}
fun setSelectedLoanAmount(amount: Money?) {
selectedLoanAmount.set(amount)
updateEma()
}
fun setSelectedTenureDetails(tenureDetails: TenureDetails?) {
selectedTenureDetails.set(tenureDetails)
updateEma()
}
fun updateEma() {
var amount = selectedLoanAmount.get()
var tenureDetails = selectedTenureDetails.get()
amount?.let {
tenureDetails?.let {
calculateEmi(
amount?.amount,
tenureDetails
)
}
}
}
fun buildAmountTenureMap(offerResponse: OfferResponse?) {
offerResponse?.let {
var tenureStepValue = StepFunctionCalculator().buildTenureStepFunction(offerResponse)
for (index in 0 until tenureStepValue.size) {
scaleToTenureMap.put(index, tenureStepValue.get(index))
}
var amountsStepValue =
StepFunctionCalculator().buildScaleToAmountMap(offerResponse.loanAmount)
for (index in 0 until amountsStepValue.size) {
scaleToAmountMap.put(index, amountsStepValue.get(index))
}
}
}
private fun calculateEmi(amount: BigDecimal, tenure: TenureDetails) {
offerResponse.value?.let {
emiValue.set(
getLoanAmount()?.max?.symbol + " " + EmiCalculator().calculateEmi(
amount,
it.rateOfInterest,
tenure
).toLong()
)
}
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXScale="0.2"
android:fromYScale="0.2"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" >
</scale>
</set>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<stroke android:width="5dp" android:color="#D9D9D9"/>
<corners android:radius="5dp" />
</shape>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="@color/colorBlueSeekbar"/>
<size
android:width="25dp"
android:height="25dp"/>
</shape>
</item>
</layer-list>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<stroke android:width="5dp" android:color="@color/colorBlueSeekbar"/>
<corners android:radius="5dp" />
</shape>

View File

@@ -0,0 +1,10 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@android:id/background"
android:drawable="@drawable/border_shadow"/>
<item android:id="@android:id/progress">
<clip android:drawable="@drawable/seekbar_progress" />
</item>
</layer-list>

View File

@@ -8,6 +8,17 @@
android:layout_height="match_parent"
tools:context=".ui.activities.BottomNavigationActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:padding="1dp"
app:layout_constraintTop_toTopOf="parent"
app:subtitleTextColor="#f5fbff"
app:titleTextColor="#fff" />
<LinearLayout
android:id="@+id/content_view"
android:layout_width="match_parent"
@@ -16,7 +27,7 @@
app:layout_constraintBottom_toTopOf="@+id/bottom_navigation_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toBottomOf="@id/toolbar" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation_view"

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="30dp"
android:orientation="vertical">
<TextView
android:id="@+id/enter_amount_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Enter Amount"
android:inputType="textPersonName"
android:textSize="18sp"
app:layout_constraintTop_toTopOf="parent" />
<RelativeLayout
android:id="@+id/enter_amount_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/enter_amount_txt">
<TextView
android:id="@+id/rs_txt"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Rs."
android:textColor="@color/colorBlueTxt"
android:textSize="18sp" />
<EditText
android:id="@+id/amount_edt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/rs_txt"
android:hint="Amount"
android:inputType="number"
android:textColor="@color/colorBlueTxt"
android:textSize="30sp" />
</RelativeLayout>
<Button
android:id="@+id/ok_btn"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginRight="20dp"
android:text="OK"
android:textColor="@color/colorWhite"
android:textSize="16sp"
app:layout_constraintRight_toRightOf="@id/enter_amount_layout"
app:layout_constraintTop_toBottomOf="@id/enter_amount_layout" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<TextView
android:id="@+id/emi_no_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1.2"
android:paddingLeft="10dp"
android:text="1"
android:textSize="16sp" />
<TextView
android:id="@+id/emi_amount_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:paddingLeft="10dp"
android:text="Rs.0"
android:textAlignment="textStart"
android:textSize="16sp"
/>
<TextView
android:id="@+id/emi_due_date_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:layout_weight="0.8"
android:text="Rs.0"
android:textSize="16sp" />
</LinearLayout>
</layout>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/emi_schedule_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true" />
</layout>

View File

@@ -3,53 +3,93 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp">
android:layout_height="100dp"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textAlignment="center"
android:gravity="center"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:baselineAligned="false"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
<TextView
android:id="@+id/loan_amount_title_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1.2">
android:layout_weight="0.6"
android:text="Loan Amount"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/txt_total_amount_to_be_repaid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Total Amount to be Repaid"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
<TextView
android:id="@+id/loan_amount_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_gravity="center"
android:layout_weight="0.8">
<TextView
android:id="@+id/total_amount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:text=""
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
android:layout_weight="0.8"
android:text="Rs.0"
android:textAlignment="center"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/linearLayout1"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<TextView
android:id="@+id/interest_title_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:text="Interest"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/interest_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:text="17.5%"
android:textAlignment="center"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/linearLayout2"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<TextView
android:id="@+id/emi_title_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:text="EMI"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/emi_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:text="Rs. 0"
android:textAlignment="center"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</RelativeLayout>
</layout>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/loan_reason_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textSize="16sp"
android:gravity="left"
android:text="Residential"
android:textColor="@android:color/black" />
</LinearLayout>

View File

@@ -3,174 +3,250 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10sp"
android:gravity="center"
tools:context="com.navi.medici.androidCustomerApp.loan_application.OfferAcceptActivity">
android:gravity="center">
<ImageView
android:id="@+id/firework_image1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:adjustViewBounds="true"
android:src="@drawable/firework"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="@+id/tick_mark_image"
app:layout_constraintEnd_toStartOf="@+id/guideline_1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/tick_mark_image" />
<ImageView
android:id="@+id/tick_mark_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:adjustViewBounds="true"
android:src="@drawable/tick_mark"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toEndOf="@id/guideline_2"
app:layout_constraintStart_toStartOf="@id/guideline_1"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/firework_image2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:adjustViewBounds="true"
android:src="@drawable/firework"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="@+id/tick_mark_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/guideline_2"
app:layout_constraintTop_toTopOf="@+id/tick_mark_image" />
<TextView
android:id="@+id/congratulations_label_text"
style="@style/largeCustomFontStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/congratulations"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tick_mark_image" />
<TextView
android:id="@+id/loan_approved_label_text"
style="@style/paragraphCustomFontStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/your_loan_got_approved"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/congratulations_label_text" />
<androidx.cardview.widget.CardView
android:id="@+id/loan_details_card"
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollview_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:elevation="8dp"
android:orientation="horizontal"
app:cardCornerRadius="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/loan_approved_label_text">
android:layout_height="match_parent"
android:layout_marginBottom="100dp">
<RelativeLayout
android:id="@+id/relativeLayout1"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="match_parent"
android:layout_margin="10sp"
android:gravity="center">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
<RelativeLayout
android:id="@+id/firework_layout1"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
app:layout_constraintRight_toLeftOf="@+id/tick_mark_image"
android:layout_marginRight="20dp"
app:layout_constraintTop_toTopOf="parent" >
<ImageView
android:id="@+id/firework_image1_1"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginRight="5dp"
android:src="@drawable/firework" />
<ImageView
android:id="@+id/firework_image1_2"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="20dp"
android:layout_toRightOf="@id/firework_image1_1"
android:src="@drawable/firework" />
<ImageView
android:id="@+id/firework_image1_3"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:layout_below="@id/firework_image1_1"
android:src="@drawable/firework"
app:layout_constraintTop_toTopOf="parent" />
</RelativeLayout>
<ImageView
android:id="@+id/tick_mark_image"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginTop="16dp"
android:src="@drawable/tick_mark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<RelativeLayout
android:id="@+id/firework_layout2"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
app:layout_constraintLeft_toRightOf="@+id/tick_mark_image"
android:layout_marginLeft="20dp"
app:layout_constraintTop_toTopOf="parent" >
<ImageView
android:id="@+id/firework_image2_1"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginRight="5dp"
android:layout_toRightOf="@id/firework_image2_2"
android:src="@drawable/firework" />
<ImageView
android:id="@+id/firework_image2_2"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="20dp"
android:layout_marginRight="5dp"
android:src="@drawable/firework" />
<ImageView
android:id="@+id/firework_image2_3"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:layout_below="@id/firework_image2_1"
android:layout_toRightOf="@id/firework_image2_2"
android:src="@drawable/firework"
app:layout_constraintTop_toTopOf="parent" />
</RelativeLayout>
<TextView
android:id="@+id/congratulations_label_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Congratulations"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/loan_approved_label_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tick_mark_image"
app:layout_constraintVertical_bias="0.592" />
<TextView
android:id="@+id/loan_approved_label_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Your loan got approved"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/congratulations_label_text" />
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/loan_details_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorWhite"
app:tabIndicatorColor="@color/colorRed" />
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginTop="25dp"
android:layout_marginRight="10dp"
android:elevation="10dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/loan_approved_label_text"
card_view:cardCornerRadius="4dp"
tools:layout_editor_absoluteX="1dp">
<androidx.viewpager.widget.ViewPager
android:id="@+id/offer_accept_viewpager"
<RelativeLayout
android:id="@+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"></com.google.android.material.tabs.TabLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/offer_accept_viewpager"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_below="@+id/tab_layout"
tools:layout_editor_absoluteX="8dp" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_below="@+id/tab_layout" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/loan_details_card"
app:layout_constraintVertical_bias="0.103">
<TextView
android:id="@+id/invite_friends_text"
style="@style/paragraphCustomFontStyle"
android:layout_width="0dp"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Invite friends to vouch for you to get discount" />
<Button
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_marginLeft="5dp"
android:background="#494968"
android:text="Invite"
android:textColor="@color/colorWhite"
android:textSize="14sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:id="@+id/checkbox_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="@string/invite_friends"
android:textColor="@android:color/black"
android:textSize="14sp"
app:layout_constraintEnd_toStartOf="@+id/button"
app:layout_constraintStart_toStartOf="@+id/loan_details_card"
app:layout_constraintTop_toBottomOf="@+id/loan_details_card" />
android:layout_marginStart="16dp"
android:clickable="true"
app:layout_constraintBottom_toTopOf="@id/accept_offer_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/colorGray"
android:minWidth="0dp"
android:minHeight="0dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:text="@string/invite"
android:textColor="@color/colorWhite"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="@+id/invite_friends_text"
app:layout_constraintEnd_toEndOf="@+id/loan_details_card"
app:layout_constraintTop_toTopOf="@+id/invite_friends_text" />
<CheckBox
android:id="@+id/checkbox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/i_accept_text"
android:textColor="@color/colorGray"
app:layout_constraintEnd_toEndOf="@+id/loan_details_card"
app:layout_constraintStart_toStartOf="@+id/loan_details_card"
app:layout_constraintTop_toBottomOf="@+id/invite_friends_text" />
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10sp"
android:text="I accept that I have seen the loan details and EMI schedule" />
</LinearLayout>
<Button
android:id="@+id/accept_offer_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/accept_and_proceed"
android:background="@color/colorRed"
android:paddingLeft="30dp"
android:paddingRight="30dp"
android:text="Accept and Proceed"
android:textAllCaps="false"
android:textColor="@color/colorWhite"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/checkbox" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.3" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.7" />
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -0,0 +1,317 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- <androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:background="@color/colorWhite">-->
<!-- -->
<data>
<import type="android.view.View"/>
<variable
name="viewModel"
type="com.navi.medici.androidCustomerApp.viewModels.PreliminaryOfferViewModel" />
</data>
<ScrollView
android:id="@+id/scrollview_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorWhite">
<TextView
android:id="@+id/select_loan_amount_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Select Loan amount and tenure"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent" />
<androidx.cardview.widget.CardView
android:id="@+id/amount_tenure_card_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/select_loan_amount_txt"
android:layout_margin="16dp"
app:cardElevation="8dp"
app:layout_constraintTop_toBottomOf="@id/select_loan_amount_txt">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorWhite">
<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/select_amount_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/borrow_amount_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="I'd like to borrow upto"
android:textSize="16sp" />
<TextView
android:id="@+id/loan_selected_amount_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/borrow_amount_txt"
android:layout_marginLeft="20dp"
android:layout_marginTop="10dp"
android:text="@{viewModel.selectedLoanAmount.displayStr}"
android:clickable="true"
android:textColor="@color/colorBlueSeekbar"
android:textSize="20sp"
android:textStyle="bold" />
<SeekBar
android:id="@+id/amount_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/loan_selected_amount_txt"
android:layout_marginTop="5dp"
android:progress="56"
android:progressDrawable="@drawable/seekbar_style"
android:splitTrack="false"
android:thumb="@drawable/custom_thumb" />
<TextView
android:id="@+id/min_amount_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/amount_slider"
android:layout_marginLeft="20dp"
android:text="Rs. 0"
android:textColor="@color/colorBlueSeekbar"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/max_amount_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/amount_slider"
android:layout_alignParentRight="true"
android:layout_marginRight="20dp"
android:text="Rs. 0"
android:textColor="@color/colorBlueSeekbar"
android:textSize="16sp"
android:textStyle="bold" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/select_tenure_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/select_amount_layout"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/select_tenure_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="Select the tenure of the loan"
android:textSize="16sp" />
<TextView
android:id="@+id/tenure_selected_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/select_tenure_txt"
android:layout_marginLeft="20dp"
android:layout_marginTop="10dp"
android:text="@{viewModel.selectedTenureDetails.displayStr}"
android:textColor="@color/colorBlueSeekbar"
android:textSize="20sp"
android:textStyle="bold" />
<SeekBar
android:id="@+id/tenure_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tenure_selected_txt"
android:layout_marginTop="5dp"
android:progress="56"
android:progressDrawable="@drawable/seekbar_style"
android:splitTrack="false"
android:thumb="@drawable/custom_thumb" />
<TextView
android:id="@+id/min_tenure_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tenure_slider"
android:layout_marginLeft="20dp"
android:text="24 hrs"
android:textColor="@color/colorBlueSeekbar"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/max_tenure_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tenure_slider"
android:layout_alignParentRight="true"
android:layout_marginRight="20dp"
android:text="24 months"
android:textColor="@color/colorBlueSeekbar"
android:textSize="16sp"
android:textStyle="bold" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/select_reason_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/select_tenure_layout"
android:layout_marginTop="20dp"
android:paddingBottom="20dp">
<TextView
android:id="@+id/reason_for_loan_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="Reason for loan"
android:textSize="16sp"
android:textStyle="bold" />
<Spinner
android:id="@+id/reason_spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/reason_for_loan_txt"
android:layout_alignLeft="@id/reason_for_loan_txt"
android:entries="@array/reason_list" />
</RelativeLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/tentative_loan_offer_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="20dp"
android:text="Tentative Loan Offer"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/amount_tenure_card_layout" />
<androidx.cardview.widget.CardView
android:id="@+id/tentative_loan_offer_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:cardElevation="8dp"
app:layout_constraintTop_toBottomOf="@id/tentative_loan_offer_txt">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@color/colorWhite">
<LinearLayout
android:id="@+id/interest_rate_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:gravity="center"
android:orientation="horizontal"
android:textAlignment="center">
<TextView
android:id="@+id/interest_rate_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:text="Interest Rate"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/interest_rate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1.2"
android:text="16.5%"
android:textAlignment="textEnd"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/interest_rate_layout"
android:baselineAligned="false"
android:gravity="center"
android:orientation="horizontal"
android:textAlignment="center">
<TextView
android:id="@+id/emi_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:text="EMI"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/emi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1.2"
android:text="@{viewModel.emiValue}"
android:textAlignment="textEnd"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
<Button
android:id="@+id/accept_offer_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="10dp"
android:background="@color/colorRed"
android:paddingLeft="30dp"
android:paddingRight="30dp"
android:text="Accept and Proceed"
android:textAllCaps="false"
android:textColor="@color/colorWhite"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@id/tentative_loan_offer_layout"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<!-- </androidx.constraintlayout.widget.ConstraintLayout>-->
</layout>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="30dp"
android:orientation="vertical">
<TextView
android:id="@+id/enter_amount_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Enter Amount"
android:inputType="textPersonName"
android:textSize="18sp"
app:layout_constraintTop_toTopOf="parent" />
<RelativeLayout
android:id="@+id/enter_amount_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/enter_amount_txt">
<EditText
android:id="@+id/tenure_edt"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:hint="0"
android:inputType="number"
android:textColor="@color/colorBlueTxt"
android:textSize="30sp" />
<Spinner
android:id="@+id/tenure_type_spinner"
android:layout_width="200dp"
android:layout_marginLeft="20dp"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/tenure_edt"
android:layout_alignBottom="@id/tenure_edt"
android:layout_alignTop="@id/tenure_edt"
android:textColor="@color/colorBlueTxt"
android:textSize="30sp" />
</RelativeLayout>
<Button
android:id="@+id/ok_btn"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginRight="20dp"
android:text="OK"
android:textColor="@color/colorWhite"
android:textSize="16sp"
app:layout_constraintRight_toRightOf="@id/enter_amount_layout"
app:layout_constraintTop_toBottomOf="@id/enter_amount_layout" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -13,6 +13,18 @@
android:title="@string/my_loans"
android:icon="@drawable/my_loans_icon"
app:showAsAction="withText" />
<item
android:id="@+id/preliminary_offer"
android:visible="false"
android:title="@string/my_loans"
android:icon="@drawable/my_loans_icon"
app:showAsAction="withText" />
<item
android:id="@+id/offer_accept"
android:visible="false"
android:title="@string/my_loans"
android:icon="@drawable/my_loans_icon"
app:showAsAction="withText" />
<item
android:id="@+id/profile"
android:enabled="true"

View File

@@ -8,4 +8,6 @@
<color name="colorGray">#B3000000</color>
<color name="colorDeepBlueGray">#4B4968</color>
<color name="colorLinkButton">#ABC0EE</color>
<color name="colorBlueSeekbar">#3a8ee7</color>
<color name="colorBlueTxt">#3a8ee7</color>
</resources>

View File

@@ -53,4 +53,9 @@
<string name="ask_your_friend_sub_heading">Ask your friends to vouch for you and get discounts on EMI</string>
<string name="get_started">Get Started</string>
<string name="skip_tutorial">Skip Tutorial</string>
<string-array name="reason_list">
<item>Home Loan</item>
<item>Person loan</item>
</string-array>
</resources>

View File

@@ -5,7 +5,6 @@ buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
@@ -19,7 +18,14 @@ allprojects {
repositories {
google()
jcenter()
mavenCentral()
maven {
credentials {
username 'nexus-user'
password 'nexus-user'
}
url "https://nexus.np.navi-tech.in/repository/maven-snapshots"
}
}
}

View File

@@ -19,3 +19,4 @@ android.useAndroidX=true
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.jetifier.blacklist=amortization-1.1-SNAPSHOT.jar