commit cb005b3837fab6b722870a476bac2fb01c08ec33 Author: Enrique Blasco Date: Mon May 4 13:15:24 2020 +0200 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..603b1407 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 00000000..dfebefaf --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Gestor Almacén \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..88ea3aa1 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,122 @@ + + + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+ + +
+
\ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 00000000..5cd135a0 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..37a75096 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 00000000..7f68460d --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 00000000..69d19b48 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,75 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' + + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.3" + + defaultConfig { + applicationId "es.verdnatura" + minSdkVersion 21 + targetSdkVersion 29 + versionCode 1 + versionName "5.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + dataBinding { + enabled = true + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + debugImplementation fileTree(dir: 'libs/debug', include: ['*.jar']) + releaseImplementation fileTree(dir: 'libs/release', include: ['*.jar']) + + // Kotlin and Android + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.core:core-ktx:1.2.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'com.google.android.material:material:1.0.0' + implementation 'com.squareup.retrofit2:retrofit:2.0.2' + implementation 'com.squareup.retrofit2:converter-gson:2.0.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.3.0' + implementation "com.airbnb.android:lottie:$lottieVersion" + + + // Architecture components + implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle" + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + + // Koin for DI + implementation "org.koin:koin-core:$koin" + implementation "org.koin:koin-android:$koin" + implementation "org.koin:koin-androidx-scope:$koin" + implementation "org.koin:koin-androidx-viewmodel:$koin" + + + // Image libraries + implementation "io.coil-kt:coil:$coil" + implementation "com.github.bumptech.glide:glide:$glide" + implementation "com.github.bumptech.glide:okhttp3-integration:$glide" + kapt "com.github.bumptech.glide:compiler:$glide" +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 00000000..f1b42451 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/es/verdnatura/ExampleInstrumentedTest.kt b/app/src/androidTest/java/es/verdnatura/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..6a6e2eb3 --- /dev/null +++ b/app/src/androidTest/java/es/verdnatura/ExampleInstrumentedTest.kt @@ -0,0 +1,22 @@ +package es.verdnatura + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("es.verdnatura", appContext.packageName) + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..23ef7ad1 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/MobileApplication.kt b/app/src/main/java/es/verdnatura/MobileApplication.kt new file mode 100644 index 00000000..20f831ea --- /dev/null +++ b/app/src/main/java/es/verdnatura/MobileApplication.kt @@ -0,0 +1,20 @@ +package es.verdnatura + +import android.app.Application +import es.verdnatura.di.viewModelModule +import org.koin.android.ext.koin.androidContext +import org.koin.core.context.loadKoinModules +import org.koin.core.context.startKoin + +class MobileApplication: Application() { + override fun onCreate() { + super.onCreate() + + startKoin { androidContext(this@MobileApplication) + val moduleList = listOf(viewModelModule) + loadKoinModules(moduleList) + } + + + } +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/di/viewModelModule.kt b/app/src/main/java/es/verdnatura/di/viewModelModule.kt new file mode 100644 index 00000000..d428eebd --- /dev/null +++ b/app/src/main/java/es/verdnatura/di/viewModelModule.kt @@ -0,0 +1,24 @@ +package es.verdnatura.di + +import es.verdnatura.presentation.view.feature.ajustes.fragment.AjustesViewModel +import es.verdnatura.presentation.view.feature.login.fragment.LoginViewModel +import es.verdnatura.presentation.view.feature.pasillero.fragment.PasilleroViewModel +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.dsl.module + +val viewModelModule = module{ + // Login + viewModel { + LoginViewModel() + } + + // Pasilleros + viewModel { + PasilleroViewModel() + } + + // Ajustes + viewModel { + AjustesViewModel() + } +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/domain/ApiSalixUtils.kt b/app/src/main/java/es/verdnatura/domain/ApiSalixUtils.kt new file mode 100644 index 00000000..d9a70a43 --- /dev/null +++ b/app/src/main/java/es/verdnatura/domain/ApiSalixUtils.kt @@ -0,0 +1,16 @@ +package es.verdnatura.domain + +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +class ApiSalixUtils { + companion object { + //const val BASE_URL:String = "http://192.168.1.108:8000/" + const val BASE_URL:String = "https://salix.verdnatura.es/api/" + fun getApiService():SalixService{ + val salixRetrofit = Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory( + GsonConverterFactory.create()).build() + return salixRetrofit.create(SalixService::class.java) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/domain/ApiUtils.kt b/app/src/main/java/es/verdnatura/domain/ApiUtils.kt new file mode 100644 index 00000000..9317c858 --- /dev/null +++ b/app/src/main/java/es/verdnatura/domain/ApiUtils.kt @@ -0,0 +1,16 @@ +package es.verdnatura.domain + +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +class ApiUtils { + companion object { + const val BASE_URL:String = "http://192.168.1.108:8000/" + //const val BASE_URL:String = "https://app.verdnatura.es/" + fun getApiService():VerdnaturaService{ + val retrofit = Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory( + GsonConverterFactory.create()).build() + return retrofit.create(VerdnaturaService::class.java) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/domain/Extensions.kt b/app/src/main/java/es/verdnatura/domain/Extensions.kt new file mode 100644 index 00000000..7281e0f1 --- /dev/null +++ b/app/src/main/java/es/verdnatura/domain/Extensions.kt @@ -0,0 +1,12 @@ +package es.verdnatura.domain + +import android.content.Context +import android.widget.Toast + +fun Any.toast(context: Context, duration: Int = Toast.LENGTH_SHORT): Toast { + return Toast.makeText(context, this.toString(), duration).apply { show() } +} + +fun T?.notNull(f: (it: T) -> Unit) { + if (this != null) f(this) +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/domain/GetAjustesUserCase.kt b/app/src/main/java/es/verdnatura/domain/GetAjustesUserCase.kt new file mode 100644 index 00000000..0759d1dc --- /dev/null +++ b/app/src/main/java/es/verdnatura/domain/GetAjustesUserCase.kt @@ -0,0 +1,13 @@ +package es.verdnatura.domain + +import es.verdnatura.presentation.view.feature.ajustes.model.SectorItemVO +import retrofit2.Call + +class GetAjustesUserCase : RestClient() { + + fun getSectors(usuario:String,password:String) : Call> { + return restClient!!.getSectors("json","1",usuario,password,"application/json")!! + } + + +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/domain/GetLoginUserCase.kt b/app/src/main/java/es/verdnatura/domain/GetLoginUserCase.kt new file mode 100644 index 00000000..51ff3898 --- /dev/null +++ b/app/src/main/java/es/verdnatura/domain/GetLoginUserCase.kt @@ -0,0 +1,26 @@ +package es.verdnatura.domain + +import es.verdnatura.presentation.view.feature.login.model.LoginSalixVO +import retrofit2.Call + +class GetLoginUserCase() : RestClient() { + + fun login(usuario:String,password:String) : Call{ + val params:ArrayList = ArrayList(); + params.add(usuario) + params.add(password) + return restClient!!.login("json","1",usuario,password,"application/json",params)!! + } + + fun salixLogin(usuario:String,password:String) : Call{ + + return salixClient!!.login("application/json", LoginSalixVO(usuario,password))!! + } + + fun checkVersion(usuario:String,password:String,version:String) : Call { + val params:ArrayList = ArrayList(); + params.add(version) + return restClient!!.version("json","1",usuario,password,"application/json",params)!! + } + +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/domain/RestClient.kt b/app/src/main/java/es/verdnatura/domain/RestClient.kt new file mode 100644 index 00000000..1c95a2f8 --- /dev/null +++ b/app/src/main/java/es/verdnatura/domain/RestClient.kt @@ -0,0 +1,13 @@ +package es.verdnatura.domain + +open class RestClient { + var restClient:VerdnaturaService? = null + var salixClient:SalixService? = null + + init { + restClient = ApiUtils.getApiService() + salixClient = ApiSalixUtils.getApiService() + } + + +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/domain/SalixService.kt b/app/src/main/java/es/verdnatura/domain/SalixService.kt new file mode 100644 index 00000000..02938f32 --- /dev/null +++ b/app/src/main/java/es/verdnatura/domain/SalixService.kt @@ -0,0 +1,15 @@ +package es.verdnatura.domain + +import es.verdnatura.presentation.view.feature.login.model.LoginSalixVO +import retrofit2.Call +import retrofit2.http.Body +import retrofit2.http.Header +import retrofit2.http.POST + +interface SalixService { + + @POST("Accounts/login") + fun login(@Header("Content-Type") content_type: String, + @Body params: LoginSalixVO): + Call +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/domain/VerdnaturaService.kt b/app/src/main/java/es/verdnatura/domain/VerdnaturaService.kt new file mode 100644 index 00000000..f850ca25 --- /dev/null +++ b/app/src/main/java/es/verdnatura/domain/VerdnaturaService.kt @@ -0,0 +1,38 @@ +package es.verdnatura.domain + + +import es.verdnatura.presentation.view.feature.ajustes.model.SectorItemVO +import retrofit2.Call +import retrofit2.http.Body +import retrofit2.http.Header +import retrofit2.http.POST + +interface VerdnaturaService { + + @POST("security/login") + fun login(@Header("aplicacion") aplicacion: String, + @Header("version") version: String, + @Header("user") user: String, + @Header("pass") pass: String, + @Header("Content-Type") content_type: String, + @Body params: List): + Call + + @POST("almacenv2/version") + fun version(@Header("aplicacion") aplicacion: String, + @Header("version") version: String, + @Header("user") user: String, + @Header("pass") pass: String, + @Header("Content-Type") content_type: String, + @Body params: List): + Call + + @POST("almacenv2/sector_get") + fun getSectors(@Header("aplicacion") aplicacion: String, + @Header("version") version: String, + @Header("user") user: String, + @Header("pass") pass: String, + @Header("Content-Type") content_type: String): + Call> + +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/base/BR.kt b/app/src/main/java/es/verdnatura/presentation/base/BR.kt new file mode 100644 index 00000000..295f0e87 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/base/BR.kt @@ -0,0 +1,27 @@ +package es.verdnatura.presentation.base + +object BR { + const val _all = 0 + const val focused = 1 + const val rating = 2 + const val resumePosition = 3 + const val favorite = 4 + const val selected = 5 + const val toolBarItem = 6 + const val item = 7 + const val loadingInfo = 8 + const val color = 9 + const val icon = 10 + const val episode = 11 + const val title = 12 + const val content = 13 + const val onOptionsItemSelected = 14 + const val vpsActionListener = 15 + const val numberEpisodes = 16 + const val seasonColor = 17 + const val viewModel = 18 + const val action = 19 + const val liveProgram = 20 + const val loadingEpisodes = 21 + const val ratio = 22 +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/base/BaseActivity.kt b/app/src/main/java/es/verdnatura/presentation/base/BaseActivity.kt new file mode 100644 index 00000000..2298d325 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/base/BaseActivity.kt @@ -0,0 +1,33 @@ +package es.verdnatura.presentation.base + +import android.os.Bundle +import androidx.annotation.LayoutRes +import androidx.appcompat.app.AppCompatActivity +import androidx.databinding.DataBindingUtil +import androidx.databinding.ViewDataBinding + +abstract class BaseActivity : AppCompatActivity() { + + + protected lateinit var binding: T + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(getLayoutId()) + initDataBinding() + init() + } + + @LayoutRes + abstract fun getLayoutId(): Int + open fun addBindingVariables() {} + abstract fun init() + + + private fun initDataBinding() { + binding = DataBindingUtil.setContentView(this, getLayoutId()) + binding.lifecycleOwner = this + addBindingVariables() + } +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/base/BaseFragment.kt b/app/src/main/java/es/verdnatura/presentation/base/BaseFragment.kt new file mode 100644 index 00000000..4771a70b --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/base/BaseFragment.kt @@ -0,0 +1,61 @@ +package es.verdnatura.presentation.base + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.LayoutRes +import androidx.databinding.DataBindingUtil +import androidx.databinding.ViewDataBinding +import androidx.fragment.app.Fragment +import org.koin.androidx.viewmodel.ext.android.viewModel +import kotlin.reflect.KClass + +abstract class BaseFragment(viewModelClass: KClass) : + Fragment() { + + + protected val PREFS_USER = "es.verdnatura.user.prefs" + protected val USERFK = "userFk" + protected val USER = "user" + protected val PASSWORD = "password" + protected val TOKEN = "token" + protected val SECTORDESCRIP = "sectordescrip" + protected val SECTORFK = "sectorFk" + protected val WAREHOUSEFK = "warehouseFk" + protected val viewModel: V by viewModel(viewModelClass) + protected lateinit var binding: T + + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? = inflater.inflate(getLayoutId(), container, false) + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + initDataBinding() + getBundleArguments() + observeViewModel() + + init() + } + + @LayoutRes + abstract fun getLayoutId(): Int + open fun init() {} + open fun observeViewModel() {} + open fun getBundleArguments() {} + open fun addBindingVariables() {} + + + private fun initDataBinding() { + binding = DataBindingUtil.bind(view!!)!! + binding.lifecycleOwner = viewLifecycleOwner + binding.setVariable(BR.viewModel, this@BaseFragment.viewModel) + lifecycle.addObserver(this@BaseFragment.viewModel) + addBindingVariables() + } +} diff --git a/app/src/main/java/es/verdnatura/presentation/base/BaseViewModel.kt b/app/src/main/java/es/verdnatura/presentation/base/BaseViewModel.kt new file mode 100644 index 00000000..b39bd015 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/base/BaseViewModel.kt @@ -0,0 +1,6 @@ +package es.verdnatura.presentation.base + +import androidx.lifecycle.LifecycleObserver +import androidx.lifecycle.ViewModel + +abstract class BaseViewModel : ViewModel(), LifecycleObserver \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/common/Event.kt b/app/src/main/java/es/verdnatura/presentation/common/Event.kt new file mode 100644 index 00000000..f0714d4f --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/common/Event.kt @@ -0,0 +1,24 @@ +package es.verdnatura.presentation.common + +open class Event(private val content: T) { + + var hasBeenHandled = false + private set // Allow external read but not write + + /** + * Returns the content and prevents its use again. + */ + fun getContentIfNotHandled(): T? { + return if (hasBeenHandled) { + null + } else { + hasBeenHandled = true + content + } + } + + /** + * Returns the content, even if it's already been handled. + */ + fun peekContent(): T = content +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/common/UICallbacks.kt b/app/src/main/java/es/verdnatura/presentation/common/UICallbacks.kt new file mode 100644 index 00000000..090dd41e --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/common/UICallbacks.kt @@ -0,0 +1,12 @@ +package es.verdnatura.presentation.common + +import es.verdnatura.presentation.view.feature.ajustes.model.AjustesItemVO +import es.verdnatura.presentation.view.feature.pasillero.model.PasillerosItemVO + +interface OnPasillerosItemClickListener { + fun onPasillerosItemClickListener(item: PasillerosItemVO) +} + +interface OnAjustesItemClickListener { + fun onAjustesItemClickListener(item: AjustesItemVO) +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/common/UIExtensions.kt b/app/src/main/java/es/verdnatura/presentation/common/UIExtensions.kt new file mode 100644 index 00000000..dadaf35c --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/common/UIExtensions.kt @@ -0,0 +1,80 @@ +package es.verdnatura.presentation.common + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentTransaction +import com.bumptech.glide.Glide + + +inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> FragmentTransaction) = + beginTransaction().func().commit() + + +fun Context.openActivity(it: Class, extras: Bundle.() -> Unit = {}) { + val intent = Intent(this, it) + intent.putExtras(Bundle().apply(extras)) + startActivity(intent) +} + +fun FragmentActivity.replaceFragment( + fragment: Fragment, + frameId: Int, + tag: String, + addToBackStack: Boolean = false +) { + supportFragmentManager.inTransaction { + replace(frameId, fragment, tag) + if (addToBackStack) addToBackStack(tag) + setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) + } +} + +fun FragmentActivity.addFragment( + fragment: Fragment, + frameId: Int, + tag: String = "", + addToBackStack: Boolean = false +) { + supportFragmentManager.inTransaction { + add(frameId, fragment, tag) + if (addToBackStack) addToBackStack(tag) + setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) + } +} + +fun View.setDimensions(width: Int, height: Int) { + val layoutParams = this.layoutParams + layoutParams?.width = width + layoutParams?.height = height + this.layoutParams = layoutParams +} +fun View.setMargins(left: Int, top: Int, right: Int, bottom: Int) { + val mlp = this.layoutParams as ViewGroup.MarginLayoutParams + mlp.setMargins(left, top, right, bottom) +} + +fun ImageView.loadUrl(url: String) { +// load(url) + Glide.with(context).load(url).into(this) +// Glide.with(context) +// .asBitmap() +// .load(url) +// .into(object : CustomTarget() { +// +// override fun onLoadCleared(placeholder: Drawable?) {} +// +// override fun onResourceReady(resource: Bitmap, transition: Transition?) { +// setImageBitmap(resource) +// } +// }) +} + +inline val T.TAG: String + get() = T::class.java.canonicalName ?: T::class.simpleName ?: T::class.java.simpleName \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/view/component/CustomDialog.kt b/app/src/main/java/es/verdnatura/presentation/view/component/CustomDialog.kt new file mode 100644 index 00000000..39bf05ef --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/component/CustomDialog.kt @@ -0,0 +1,42 @@ +package es.verdnatura.presentation.view.component + +import android.app.Dialog +import android.content.Context +import android.view.View +import es.verdnatura.R +import kotlinx.android.synthetic.main.component_custom_dialog.* + +class CustomDialog(context: Context) : Dialog(context, R.style.DialogTheme) { + + init { + setContentView(R.layout.component_custom_dialog) + } + + + fun setTitle(title: String): CustomDialog { + custom_dialog_title.visibility = View.VISIBLE + custom_dialog_title.text = title + return this + } + + fun setDescription(description: String): CustomDialog { + custom_dialog_description.visibility = View.VISIBLE + custom_dialog_description.text = description + return this + } + + fun setOkButton(text: String, onButtonClicked: () -> Unit): CustomDialog { + custom_dialog_button_ok.visibility = View.VISIBLE + custom_dialog_button_ok.text = text + custom_dialog_button_ok.setOnClickListener { onButtonClicked() } + return this + } + + fun setKoButton(text: String, onButtonClicked: () -> Unit): CustomDialog { + custom_dialog_button_ko.visibility = View.VISIBLE + custom_dialog_button_ko.text = text + custom_dialog_button_ko.setOnClickListener { onButtonClicked() } + return this + } + +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/adapter/AjustesAdapter.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/adapter/AjustesAdapter.kt new file mode 100644 index 00000000..0b90bf37 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/adapter/AjustesAdapter.kt @@ -0,0 +1,41 @@ +package es.verdnatura.presentation.view.feature.ajustes.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import es.verdnatura.databinding.ItemAjustesRowBinding +import es.verdnatura.presentation.common.OnAjustesItemClickListener +import es.verdnatura.presentation.view.feature.ajustes.model.AjustesItemVO + +class AjustesAdapter ( + private val items: List, + private val onAjustesItemClickListener: OnAjustesItemClickListener +): RecyclerView.Adapter () { + + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AjustesItemHolder { + return AjustesItemHolder( + ItemAjustesRowBinding.inflate(LayoutInflater.from(parent.context),parent,false) + ) + } + + override fun getItemCount() =items.size + + override fun onBindViewHolder(holder: AjustesItemHolder, position: Int) { + holder.bind(items[position]) + holder.binding.root.setOnClickListener { + onAjustesItemClickListener.onAjustesItemClickListener(items[position]) + } + } + + + class AjustesItemHolder( + val binding: ItemAjustesRowBinding + ) : RecyclerView.ViewHolder(binding.root){ + fun bind(item: AjustesItemVO) { + binding.apply { + this.item = item + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/fragment/AjustesFragment.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/fragment/AjustesFragment.kt new file mode 100644 index 00000000..09851c9b --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/fragment/AjustesFragment.kt @@ -0,0 +1,127 @@ +package es.verdnatura.presentation.view.feature.ajustes.fragment + +import android.app.AlertDialog +import android.content.DialogInterface +import android.content.SharedPreferences +import android.view.View +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.LinearLayoutManager +import es.verdnatura.R +import es.verdnatura.databinding.FragmentAjustesBinding +import es.verdnatura.domain.notNull +import es.verdnatura.presentation.base.BaseFragment +import es.verdnatura.presentation.common.OnAjustesItemClickListener +import es.verdnatura.presentation.view.component.CustomDialog +import es.verdnatura.presentation.view.feature.ajustes.adapter.AjustesAdapter +import es.verdnatura.presentation.view.feature.ajustes.model.AjustesItemVO +import es.verdnatura.presentation.view.feature.ajustes.model.SectorItemVO +import es.verdnatura.presentation.view.feature.ajustes.model.SectorListVO +import kotlinx.android.synthetic.main.fragment_ajustes.* + +class AjustesFragment : BaseFragment(AjustesViewModel::class) { + + private var user:String? = "" + private var password:String? = "" + private lateinit var customDialog: CustomDialog + private var sectorListVO:List = listOf() + private var prefs: SharedPreferences? = null + private var ajustesAdapter: AjustesAdapter? = null + + companion object { + fun newInstance() = AjustesFragment() + } + override fun getLayoutId(): Int = R.layout.fragment_ajustes + + override fun init() { + prefs = activity!!.getSharedPreferences(PREFS_USER,0) + customDialog = CustomDialog(requireContext()) + viewModel.inititializeDefaultAjusts(prefs!!.getString(SECTORDESCRIP,"Sin sector").toString(),prefs!!.getInt(SECTORFK,0),prefs!!.getInt(WAREHOUSEFK,0)) + user_text.setText(prefs!!.getString(USERFK,"")) + val versionName = activity!!.packageManager.getPackageInfo(activity!!.packageName,0).versionName + item_version.setText(versionName) + user = prefs!!.getString(USER,"") + password = prefs!!.getString(PASSWORD,"") + super.init() + } + + override fun observeViewModel() { + with(viewModel){ + ajustesAdapter = AjustesAdapter(ajustesitem,object: OnAjustesItemClickListener{ + override fun onAjustesItemClickListener(item: AjustesItemVO) { + if (item.id == 0){ + splash_progress.visibility = View.VISIBLE + viewModel.getSectors(user!!,password!!) + } else if (item.id == 1){ + activity!!.onBackPressed() + } + } + }) + ajustess_items.adapter = ajustesAdapter + ajustess_items.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) + + loadSectorList.observe(viewLifecycleOwner, Observer { event -> + event.getContentIfNotHandled().notNull { + splash_progress.visibility = View.INVISIBLE + if (it.list != null && it.list.size > 0 && it.list.get(0).isError){ + customDialog.setTitle("Error").setDescription(it.list.get(0).errorMessage).setOkButton("Cerrar"){ + customDialog.hide() + }.show() + }else{ + + if (it.list != null && it.list.size > 0){ + val listSectores : ArrayList = ArrayList() + it.list.forEach { + listSectores.add(it.description) + } + val array = arrayOfNulls(listSectores.size) + sectorListVO = it.list + showDialogSector(listSectores.toArray(array)) + + }else{ + customDialog.setTitle("Sectores").setDescription("No existes sectores.").setOkButton("Cerrar"){ + customDialog.hide() + }.show() + } + + } + } + }) + } + super.observeViewModel() + } + + private fun showDialogSector(array:Array){ + val builder = AlertDialog.Builder(this.context) + + + builder.setTitle("Selecciona un sector") + builder.setItems(array) { _, which -> + val selected = array[which] + sectorListVO.forEach { + if (it.description.equals(selected)){ + val editor = prefs!!.edit() + editor.putString(SECTORDESCRIP,it.description) + editor.putInt(SECTORFK,it.id) + it.warehouseFk?.let { it1 -> editor.putInt(WAREHOUSEFK, it1) } + editor.apply() + + viewModel.ajustesitem.get(0).sectorFk = it.id + viewModel.ajustesitem.get(0).warehouse = it.warehouseFk + viewModel.ajustesitem.get(0).selected = it.description + ajustesAdapter!!.notifyDataSetChanged() + + return@forEach + } + } + + + } + + val dialog = builder.create() + dialog.show() + } + + + + +} diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/fragment/AjustesViewModel.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/fragment/AjustesViewModel.kt new file mode 100644 index 00000000..b8a79a86 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/fragment/AjustesViewModel.kt @@ -0,0 +1,81 @@ +package es.verdnatura.presentation.view.feature.ajustes.fragment + + +import android.content.SharedPreferences +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.Transformations +import es.verdnatura.domain.GetAjustesUserCase +import es.verdnatura.presentation.base.BaseViewModel +import es.verdnatura.presentation.common.Event +import es.verdnatura.presentation.view.feature.ajustes.model.AjustesItemVO +import es.verdnatura.presentation.view.feature.ajustes.model.SectorItemVO +import es.verdnatura.presentation.view.feature.ajustes.model.SectorListVO +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + + +class AjustesViewModel : BaseViewModel() { + + private val getAjustesUserCase:GetAjustesUserCase = GetAjustesUserCase() + val version : String = "5.0.0"; + + private val _ajustesitem by lazy { ArrayList() } + val ajustesitem: List + get() = _ajustesitem + + private val _sectorList by lazy { MutableLiveData() } + val sectorList: LiveData + get() = _sectorList + + + val loadSectorList = Transformations.map(_sectorList) {Event(it)} + + + + + fun inititializeDefaultAjusts(sectorDescrip: String,sectorFk : Int, warehouseFk : Int) { + _ajustesitem.add( + AjustesItemVO(0, + "Sector", + sectorDescrip, + sectorFk, + warehouseFk) + ) + + _ajustesitem.add( + AjustesItemVO(1, + "Cerrar Sesión", + "", + 0, + 0) + ) + + } + + fun getSectors(user:String,password:String){ + getAjustesUserCase.getSectors(user,password).enqueue(object : Callback>{ + override fun onFailure(call: Call>, t: Throwable) { + val listError:ArrayList = ArrayList() + listError.add(SectorItemVO(0,"",0,true,t.message!!)) + _sectorList.value = SectorListVO(listError) + } + + override fun onResponse( + call: Call>, + response: Response> + ) { + if (response.body() != null){ + _sectorList.value = response.body()?.let { SectorListVO(it) } + }else{ + val listError:ArrayList = ArrayList() + listError.add(SectorItemVO(0,"",0,true,"Error en la llamada sector_get")) + _sectorList.value = SectorListVO(listError) + } + } + + }) + } + +} diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/model/AjustesItemVO.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/model/AjustesItemVO.kt new file mode 100644 index 00000000..2b293657 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/ajustes/model/AjustesItemVO.kt @@ -0,0 +1,21 @@ +package es.verdnatura.presentation.view.feature.ajustes.model + +class AjustesItemVO ( + var id: Int, + var title: String = "", + var selected: String = "", + var sectorFk : Int?, + var warehouse: Int? +) + +class SectorItemVO ( + var id: Int, + var description:String = "", + val warehouseFk:Int?, + val isError : Boolean = false, + var errorMessage : String = "" +) + +class SectorListVO ( + var list: List = listOf() +) \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/login/activity/LoginActivity.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/login/activity/LoginActivity.kt new file mode 100644 index 00000000..27f05577 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/login/activity/LoginActivity.kt @@ -0,0 +1,19 @@ +package es.verdnatura.presentation.view.feature.login.activity + +import es.verdnatura.R +import es.verdnatura.databinding.ActivityLoginBinding +import es.verdnatura.presentation.base.BaseActivity +import es.verdnatura.presentation.common.TAG +import es.verdnatura.presentation.common.addFragment +import es.verdnatura.presentation.view.feature.login.fragment.LoginFragment + +class LoginActivity : BaseActivity() { + + override fun getLayoutId(): Int = R.layout.activity_login + + override fun init() { + addFragment(LoginFragment.newInstance(),R.id.main_frame_layout,LoginFragment.TAG) + } + + +} diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/login/fragment/LoginFragment.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/login/fragment/LoginFragment.kt new file mode 100644 index 00000000..a2badb4e --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/login/fragment/LoginFragment.kt @@ -0,0 +1,130 @@ +package es.verdnatura.presentation.view.feature.login.fragment + + +import android.content.Intent +import android.content.SharedPreferences +import android.net.Uri +import android.view.View +import androidx.lifecycle.Observer +import es.verdnatura.R +import es.verdnatura.databinding.FragmentLoginBinding +import es.verdnatura.presentation.base.BaseFragment +import es.verdnatura.presentation.view.component.CustomDialog +import es.verdnatura.presentation.view.feature.login.model.LoginItemVO +import es.verdnatura.presentation.view.feature.main.activity.MainActivity +import kotlinx.android.synthetic.main.fragment_login.* + +class LoginFragment : BaseFragment (LoginViewModel::class) { + + private lateinit var customDialog: CustomDialog + companion object { + fun newInstance() = LoginFragment() + } + + override fun getLayoutId(): Int = R.layout.fragment_login + + override fun init() { + customDialog = CustomDialog(requireContext()) + checkUser() + button_login.setOnClickListener(View.OnClickListener { + splash_progress.visibility = View.VISIBLE + viewModel.login(edittext_username.text.toString(),edittext_password.text.toString()) + }) + } + + private fun checkUser(){ + val prefs: SharedPreferences = activity!!.getSharedPreferences(PREFS_USER,0) + edittext_username.setText(prefs.getString(USER,"")) + edittext_password.setText(prefs.getString(PASSWORD,"")) + if (edittext_password.text.toString().isNotEmpty()){ + switch_remember.isChecked = true + } + } + + override fun observeViewModel() { + with(viewModel){ + loginitem.observe(viewLifecycleOwner, Observer { + splash_progress.visibility = View.INVISIBLE + if (it.isError){ + customDialog.setTitle("Error").setDescription(it.errorMessage).setOkButton("Cerrar"){ + customDialog.hide() + }.show() + }else{ + splash_progress.visibility = View.VISIBLE + saveUserFkPref(it) + if (switch_remember.isChecked) { + saveUserAccesPref(edittext_username.text.toString(),edittext_password.text.toString()) + }else{ + saveUserAccesPref("","") + } + loginSalix(user = edittext_username.text.toString(),password = edittext_password.text.toString()) + } + + }) + loginsalixitem.observe(viewLifecycleOwner, Observer { + splash_progress.visibility = View.INVISIBLE + if (it.isError){ + saveTokenPref("") + customDialog.setTitle("Error").setDescription(it.errorMessage+". Puedes continuar pero algunas funcionalidades no estarán disponibles.").setOkButton("Entendido"){ + customDialog.hide() + getVersion() + }.show() + }else{ + saveTokenPref(it.token) + getVersion() + } + }) + + version.observe(viewLifecycleOwner, Observer { + splash_progress.visibility = View.INVISIBLE + if (it){ + goToMain() + }else{ + customDialog.setTitle("Error").setDescription("Existe una versión nueva, es recomendable actualizar.").setOkButton("Actualizar"){ + val openURL = Intent(Intent.ACTION_VIEW) + openURL.data = Uri.parse("https://app.verdnatura.es/bin/vn-pickingV2.apk") + startActivity(openURL) + }.setKoButton("Omitir"){ + customDialog.hide() + goToMain() + }.show() + } + }) + } + super.observeViewModel() + } + + private fun saveTokenPref(token:String){ + val prefs: SharedPreferences = activity!!.getSharedPreferences(PREFS_USER,0) + val editor = prefs.edit() + editor.putString(TOKEN,token) + editor.apply() + } + + private fun saveUserFkPref(loginitem : LoginItemVO){ + val prefs: SharedPreferences = activity!!.getSharedPreferences(PREFS_USER,0) + val editor = prefs.edit() + editor.putString(USERFK,loginitem.id) + editor.apply() + } + + private fun saveUserAccesPref(user:String,password:String){ + val prefs: SharedPreferences = activity!!.getSharedPreferences(PREFS_USER,0) + val editor = prefs.edit() + editor.putString(USER,user) + editor.putString(PASSWORD,password) + editor.apply() + } + + private fun goToMain(){ + val intent = Intent(activity,MainActivity::class.java) + startActivity(intent) + } + + private fun getVersion(){ + val versionName = activity!!.packageManager.getPackageInfo(activity!!.packageName,0).versionName + splash_progress.visibility = View.VISIBLE + viewModel.checkVersion(user = edittext_username.text.toString(),password = edittext_password.text.toString(),version = versionName) + } + +} diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/login/fragment/LoginViewModel.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/login/fragment/LoginViewModel.kt new file mode 100644 index 00000000..e7ee2363 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/login/fragment/LoginViewModel.kt @@ -0,0 +1,92 @@ +package es.verdnatura.presentation.view.feature.login.fragment + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import es.verdnatura.domain.GetLoginUserCase +import es.verdnatura.presentation.base.BaseViewModel +import es.verdnatura.presentation.view.feature.login.model.LoginItemVO +import es.verdnatura.presentation.view.feature.login.model.LoginSalixVO +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class LoginViewModel() : BaseViewModel() { + + private val getLoginUserCase: GetLoginUserCase = GetLoginUserCase() + + + private val _loginitem by lazy { MutableLiveData ()} + val loginitem : LiveData + get() = _loginitem + + private val _loginsalixitem by lazy { MutableLiveData ()} + val loginsalixitem : LiveData + get() = _loginsalixitem + + + private val _version by lazy { MutableLiveData ()} + val version : LiveData + get() = _version + + + fun login(user:String,password:String){ + getLoginUserCase.login(user,password).enqueue(object : Callback{ + override fun onResponse(call: Call, response: Response) { + + var loginItemVO:LoginItemVO? + if (response.raw().code() == 555){ + loginItemVO = LoginItemVO(id = "0",isError = true, errorMessage = "Usuario o contraseña incorrectos") + }else if (!response.body().isNullOrEmpty()){ + loginItemVO = response.body()?.let { LoginItemVO(id = it) } + }else{ + loginItemVO = LoginItemVO(id = "0",isError = true,errorMessage = "Error desconocido") + } + + _loginitem.value = loginItemVO!! + } + + override fun onFailure(call: Call, t: Throwable) { + val loginItemVO : LoginItemVO? = LoginItemVO(id = "0",isError = true, errorMessage = t.message!!) + _loginitem.value = loginItemVO + } + }) + } + + fun loginSalix(user:String,password:String){ + getLoginUserCase.salixLogin(user,password).enqueue(object : Callback{ + override fun onResponse(call: Call, response: Response) { + + var loginSalixVO:LoginSalixVO? + if(response.body() != null){ + loginSalixVO = response.body()?.token?.let { LoginSalixVO(user,password, it,isError = false,errorMessage = "") } + }else{ + loginSalixVO = LoginSalixVO(user,password,isError = true,errorMessage = "Error al conectar con salix") + } + + _loginsalixitem.value = loginSalixVO + } + + override fun onFailure(call: Call, t: Throwable) { + val loginSalixVO = LoginSalixVO(user,password, "",isError = true,errorMessage = t.message!!) + _loginsalixitem.value = loginSalixVO + } + }) + } + + fun checkVersion(user:String,password:String,version:String){ + getLoginUserCase.checkVersion(user,password,version).enqueue(object : Callback{ + override fun onResponse(call: Call, response: Response) { + if (response.body() != null){ + _version.value = response.body() + }else{ + _version.value = true + } + } + + override fun onFailure(call: Call, t: Throwable) { + _version.value = true + } + }) + } + +} diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/login/model/LoginItemVO.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/login/model/LoginItemVO.kt new file mode 100644 index 00000000..04d4e85d --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/login/model/LoginItemVO.kt @@ -0,0 +1,15 @@ +package es.verdnatura.presentation.view.feature.login.model + +class LoginItemVO ( + val id:String = "", + var isError:Boolean = false, + var errorMessage:String = "" +) + +class LoginSalixVO ( + val user:String = "", + val password:String = "", + val token:String = "", + var isError:Boolean = false, + var errorMessage:String = "" +) \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/main/activity/MainActivity.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/main/activity/MainActivity.kt new file mode 100644 index 00000000..c582ebd5 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/main/activity/MainActivity.kt @@ -0,0 +1,132 @@ +package es.verdnatura.presentation.view.feature.main.activity + +import android.util.Log +import android.view.Menu +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import es.verdnatura.R +import es.verdnatura.databinding.ActivityMainBinding +import es.verdnatura.domain.toast +import es.verdnatura.presentation.base.BaseActivity +import es.verdnatura.presentation.common.OnPasillerosItemClickListener +import es.verdnatura.presentation.common.TAG +import es.verdnatura.presentation.common.addFragment +import es.verdnatura.presentation.view.component.CustomDialog +import es.verdnatura.presentation.view.feature.ajustes.fragment.AjustesFragment +import es.verdnatura.presentation.view.feature.main.model.ItemMenuVO +import es.verdnatura.presentation.view.feature.pasillero.fragment.PasilleroFragment +import es.verdnatura.presentation.view.feature.pasillero.model.PasillerosItemVO +import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch + + +class MainActivity : BaseActivity() , OnPasillerosItemClickListener { + + private var lastBottomMenuItemSelected: ItemMenuVO? = null + private lateinit var customDialog: CustomDialog + + override fun getLayoutId(): Int = R.layout.activity_main + + override fun init() { + customDialog = CustomDialog(this) + setBottomMenu() + addFragment(PasilleroFragment.newInstance(),R.id.main_frame_layout, PasilleroFragment.TAG) + } + + private fun openFragment(fragment: Fragment) { + val transaction = supportFragmentManager.beginTransaction() + transaction.replace(R.id.main_frame_layout, fragment) + transaction.addToBackStack(null) + transaction.commit() + } + + private fun setBottomMenu(){ + val bottomMenu = main_bottom_navigation + bottomMenu.itemIconTintList = null + GlobalScope.launch(Dispatchers.Main){ + val bottomMenuItems : ArrayList = ArrayList() + + bottomMenuItems.add(ItemMenuVO(0,title = "Pasilleros",defaultImage = ContextCompat.getDrawable( + applicationContext,R.drawable.ic_device_hub_black_24dp),selectedImage = ContextCompat.getDrawable( + applicationContext,R.drawable.ic_device_hub_black_24dp_selected))) + + bottomMenuItems.add(ItemMenuVO(1,title = "Sacadores",defaultImage = ContextCompat.getDrawable( + applicationContext,R.drawable.ic_local_florist_black_24dp),selectedImage = ContextCompat.getDrawable( + applicationContext,R.drawable.ic_local_florist_black_24dp_selected))) + + bottomMenuItems.add(ItemMenuVO(2,title = "Controladores",defaultImage = ContextCompat.getDrawable( + applicationContext,R.drawable.ic_verified_user_black_24dp),selectedImage = ContextCompat.getDrawable( + applicationContext,R.drawable.ic_verified_user_black_24dp_selected))) + + bottomMenuItems.add(ItemMenuVO(3,title = "Ajustes",defaultImage = ContextCompat.getDrawable( + applicationContext,R.drawable.ic_build_black_24dp),selectedImage = ContextCompat.getDrawable( + applicationContext,R.drawable.ic_build_black_24dp_selected))) + + // Add al items to menu view + bottomMenuItems.forEach { + bottomMenu.menu.add(Menu.NONE, it.id, Menu.NONE, it.title).icon = it.defaultImage + } + + // Select first item by default + val firstItem = bottomMenuItems.first() + bottomMenu.selectedItemId = firstItem.id + bottomMenu.menu.findItem(firstItem.id).icon = firstItem.selectedImage + lastBottomMenuItemSelected = firstItem + + bottomMenu.setOnNavigationItemSelectedListener { menuItem -> + // Get selected item from itemList and apply ui changes to menu view + val selectedItemMenu = bottomMenuItems.find { menuItem.itemId == it.id } + menuItem.icon = selectedItemMenu?.selectedImage + + // Get last selected item and disable it + bottomMenu.menu.findItem(lastBottomMenuItemSelected?.id!!).icon = + lastBottomMenuItemSelected?.defaultImage + lastBottomMenuItemSelected = selectedItemMenu + + when (selectedItemMenu?.title) { + "Pasilleros" -> { + addFragment(PasilleroFragment.newInstance(),R.id.main_frame_layout, PasilleroFragment.TAG) + true + } + "Sacadores" -> { + selectedItemMenu.title.toast(this@MainActivity) + true + } + "Controladores" -> { + selectedItemMenu.title.toast(this@MainActivity) + true + } + "Ajustes" -> { + addFragment(AjustesFragment.newInstance(),R.id.main_frame_layout, AjustesFragment.TAG) + true + } + + + else -> false + } + + true + } + bottomMenu.setOnNavigationItemReselectedListener { + + } + } + } + + override fun onPasillerosItemClickListener(item: PasillerosItemVO) { + Log.i("Item: ",item.title) + } + + + override fun onBackPressed() { + customDialog.setTitle("Error").setDescription("¿Estás seguro de cerrar la sesión?").setOkButton("Salir"){ + customDialog.hide() + finish() + }.setKoButton("Cancelar") { + customDialog.hide() + }.show() + } + +} diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/main/model/ItemMenuVO.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/main/model/ItemMenuVO.kt new file mode 100644 index 00000000..9de1fb60 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/main/model/ItemMenuVO.kt @@ -0,0 +1,10 @@ +package es.verdnatura.presentation.view.feature.main.model + +import android.graphics.drawable.Drawable + +data class ItemMenuVO( + val id: Int, + val title: String, + val defaultImage: Drawable?, + val selectedImage: Drawable? +) \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/adapter/PasillerosAdapter.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/adapter/PasillerosAdapter.kt new file mode 100644 index 00000000..fe4d0830 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/adapter/PasillerosAdapter.kt @@ -0,0 +1,43 @@ +package es.verdnatura.presentation.view.feature.pasillero.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import es.verdnatura.databinding.ItemPasillerosMainMenuBinding +import es.verdnatura.presentation.common.OnPasillerosItemClickListener +import es.verdnatura.presentation.view.feature.pasillero.model.PasillerosItemVO + +class PasillerosAdapter ( + private val items: List, + private val onPasillerosItemClickListener: OnPasillerosItemClickListener +): RecyclerView.Adapter () { + + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PasillerosItemHolder { + return PasillerosItemHolder( + ItemPasillerosMainMenuBinding.inflate(LayoutInflater.from(parent.context),parent,false) + ) + } + + override fun getItemCount() =items.size + + override fun onBindViewHolder(holder: PasillerosItemHolder, position: Int) { + holder.bind(items[position]) + holder.binding.root.setOnClickListener { + onPasillerosItemClickListener.onPasillerosItemClickListener(items[position]) + } + + } + + + class PasillerosItemHolder( + val binding: ItemPasillerosMainMenuBinding + ) : RecyclerView.ViewHolder(binding.root){ + fun bind(item: PasillerosItemVO) { + binding.apply { + this.item = item + itemImage.setImageResource(item.iconResource) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/fragment/PasilleroFragment.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/fragment/PasilleroFragment.kt new file mode 100644 index 00000000..afd23b69 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/fragment/PasilleroFragment.kt @@ -0,0 +1,42 @@ +package es.verdnatura.presentation.view.feature.pasillero.fragment + +import android.content.Context +import androidx.recyclerview.widget.LinearLayoutManager +import es.verdnatura.R +import es.verdnatura.databinding.FragmentPasilleroBinding +import es.verdnatura.presentation.base.BaseFragment +import es.verdnatura.presentation.common.OnPasillerosItemClickListener +import es.verdnatura.presentation.view.feature.pasillero.adapter.PasillerosAdapter +import kotlinx.android.synthetic.main.fragment_pasillero.* + +class PasilleroFragment : BaseFragment(PasilleroViewModel::class){ + + private var pasillerosItemClickListener: OnPasillerosItemClickListener? = null + + companion object { + fun newInstance() = PasilleroFragment() + } + + override fun onAttach(context: Context) { + super.onAttach(context) + if (context is OnPasillerosItemClickListener) pasillerosItemClickListener = context + } + + override fun getLayoutId(): Int = R.layout.fragment_pasillero + + override fun init() { + viewModel.inititializeDefaultData() + super.init() + } + + + + override fun observeViewModel() { + with(viewModel){ + pasilleros_items.adapter = PasillerosAdapter(pasillerositem,pasillerosItemClickListener!!) + pasilleros_items.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) + } + super.observeViewModel() + } + +} diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/fragment/PasilleroViewModel.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/fragment/PasilleroViewModel.kt new file mode 100644 index 00000000..fe24e933 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/fragment/PasilleroViewModel.kt @@ -0,0 +1,47 @@ +package es.verdnatura.presentation.view.feature.pasillero.fragment + + +import es.verdnatura.R +import es.verdnatura.presentation.base.BaseViewModel +import es.verdnatura.presentation.view.feature.pasillero.model.PasillerosItemVO + +class PasilleroViewModel : BaseViewModel() { + private val _pasillerositem by lazy { ArrayList() } + val pasillerositem: List + get() = _pasillerositem + + + fun inititializeDefaultData() { + _pasillerositem.add( + PasillerosItemVO(0, + R.drawable.ic_loyalty_black_24dp, + "Consultar artículo") + ) + + _pasillerositem.add( + PasillerosItemVO(1, + R.drawable.ic_dashboard_black_24dp, + "Ubicador") + ) + + _pasillerositem.add( + PasillerosItemVO(2, + R.drawable.ic_visibility_black_24dp, + "Buscar item") + ) + + _pasillerositem.add( + PasillerosItemVO(3, + R.drawable.ic_spa_black_24dp, + "Inventario") + ) + + _pasillerositem.add( + PasillerosItemVO(4, + R.drawable.ic_move_to_inbox_black_24dp, + "Faltas") + ) + + + } +} diff --git a/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/model/PasillerosItemVO.kt b/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/model/PasillerosItemVO.kt new file mode 100644 index 00000000..e16e17b0 --- /dev/null +++ b/app/src/main/java/es/verdnatura/presentation/view/feature/pasillero/model/PasillerosItemVO.kt @@ -0,0 +1,7 @@ +package es.verdnatura.presentation.view.feature.pasillero.model + +class PasillerosItemVO ( + var id: Int, + var iconResource: Int, + val title: String = "" +) \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 00000000..2b068d11 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/selector_bottombar_text.xml b/app/src/main/res/drawable-v24/selector_bottombar_text.xml new file mode 100644 index 00000000..b6b2e8a2 --- /dev/null +++ b/app/src/main/res/drawable-v24/selector_bottombar_text.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/background_login.jpg b/app/src/main/res/drawable/background_login.jpg new file mode 100644 index 00000000..1222ac69 Binary files /dev/null and b/app/src/main/res/drawable/background_login.jpg differ diff --git a/app/src/main/res/drawable/background_oval_checked.xml b/app/src/main/res/drawable/background_oval_checked.xml new file mode 100644 index 00000000..de8667d9 --- /dev/null +++ b/app/src/main/res/drawable/background_oval_checked.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_oval_unchecked.xml b/app/src/main/res/drawable/background_oval_unchecked.xml new file mode 100644 index 00000000..6bc2ac95 --- /dev/null +++ b/app/src/main/res/drawable/background_oval_unchecked.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_parental.xml b/app/src/main/res/drawable/border_parental.xml new file mode 100644 index 00000000..055fb3d9 --- /dev/null +++ b/app/src/main/res/drawable/border_parental.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/btn_ios_like.xml b/app/src/main/res/drawable/btn_ios_like.xml new file mode 100644 index 00000000..82e322aa --- /dev/null +++ b/app/src/main/res/drawable/btn_ios_like.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/btn_orange.xml b/app/src/main/res/drawable/btn_orange.xml new file mode 100644 index 00000000..015136be --- /dev/null +++ b/app/src/main/res/drawable/btn_orange.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/app/src/main/res/drawable/btn_white_transparent.xml b/app/src/main/res/drawable/btn_white_transparent.xml new file mode 100644 index 00000000..04580960 --- /dev/null +++ b/app/src/main/res/drawable/btn_white_transparent.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/component_progress.xml b/app/src/main/res/drawable/component_progress.xml new file mode 100644 index 00000000..4323faee --- /dev/null +++ b/app/src/main/res/drawable/component_progress.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drawable_white_circle.xml b/app/src/main/res/drawable/drawable_white_circle.xml new file mode 100644 index 00000000..65768015 --- /dev/null +++ b/app/src/main/res/drawable/drawable_white_circle.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_arrow_drop_down_black_24dp.xml b/app/src/main/res/drawable/ic_arrow_drop_down_black_24dp.xml new file mode 100644 index 00000000..1d53945f --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_drop_down_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_build_black_24dp.xml b/app/src/main/res/drawable/ic_build_black_24dp.xml new file mode 100644 index 00000000..1962aea6 --- /dev/null +++ b/app/src/main/res/drawable/ic_build_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_build_black_24dp_selected.xml b/app/src/main/res/drawable/ic_build_black_24dp_selected.xml new file mode 100644 index 00000000..a634102d --- /dev/null +++ b/app/src/main/res/drawable/ic_build_black_24dp_selected.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_chevron_right_black_24dp.xml b/app/src/main/res/drawable/ic_chevron_right_black_24dp.xml new file mode 100644 index 00000000..6c1fb088 --- /dev/null +++ b/app/src/main/res/drawable/ic_chevron_right_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_dashboard_black_24dp.xml b/app/src/main/res/drawable/ic_dashboard_black_24dp.xml new file mode 100644 index 00000000..4e11f689 --- /dev/null +++ b/app/src/main/res/drawable/ic_dashboard_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_device_hub_black_24dp.xml b/app/src/main/res/drawable/ic_device_hub_black_24dp.xml new file mode 100644 index 00000000..0123debb --- /dev/null +++ b/app/src/main/res/drawable/ic_device_hub_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_device_hub_black_24dp_selected.xml b/app/src/main/res/drawable/ic_device_hub_black_24dp_selected.xml new file mode 100644 index 00000000..10d6fe4b --- /dev/null +++ b/app/src/main/res/drawable/ic_device_hub_black_24dp_selected.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..07d5da9c --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_local_florist_black_24dp.xml b/app/src/main/res/drawable/ic_local_florist_black_24dp.xml new file mode 100644 index 00000000..c2854d8d --- /dev/null +++ b/app/src/main/res/drawable/ic_local_florist_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_local_florist_black_24dp_selected.xml b/app/src/main/res/drawable/ic_local_florist_black_24dp_selected.xml new file mode 100644 index 00000000..635695a2 --- /dev/null +++ b/app/src/main/res/drawable/ic_local_florist_black_24dp_selected.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_loyalty_black_24dp.xml b/app/src/main/res/drawable/ic_loyalty_black_24dp.xml new file mode 100644 index 00000000..6e54d2d5 --- /dev/null +++ b/app/src/main/res/drawable/ic_loyalty_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_move_to_inbox_black_24dp.xml b/app/src/main/res/drawable/ic_move_to_inbox_black_24dp.xml new file mode 100644 index 00000000..84240c0f --- /dev/null +++ b/app/src/main/res/drawable/ic_move_to_inbox_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_spa_black_24dp.xml b/app/src/main/res/drawable/ic_spa_black_24dp.xml new file mode 100644 index 00000000..f1dcc9bf --- /dev/null +++ b/app/src/main/res/drawable/ic_spa_black_24dp.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/main/res/drawable/ic_verified_user_black_24dp.xml b/app/src/main/res/drawable/ic_verified_user_black_24dp.xml new file mode 100644 index 00000000..36793b4e --- /dev/null +++ b/app/src/main/res/drawable/ic_verified_user_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_verified_user_black_24dp_selected.xml b/app/src/main/res/drawable/ic_verified_user_black_24dp_selected.xml new file mode 100644 index 00000000..ef5e9321 --- /dev/null +++ b/app/src/main/res/drawable/ic_verified_user_black_24dp_selected.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_visibility_black_24dp.xml b/app/src/main/res/drawable/ic_visibility_black_24dp.xml new file mode 100644 index 00000000..518f0381 --- /dev/null +++ b/app/src/main/res/drawable/ic_visibility_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 00000000..7264870f --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..ccd5820f --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/component_custom_dialog.xml b/app/src/main/res/layout/component_custom_dialog.xml new file mode 100644 index 00000000..6e328c83 --- /dev/null +++ b/app/src/main/res/layout/component_custom_dialog.xml @@ -0,0 +1,61 @@ + + + + + + + + + +