[
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n/.idea/navEditor.xml\n/.idea/assetWizardSettings.xml\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n.cxx\nlocal.properties\n"
  },
  {
    "path": ".idea/.gitignore",
    "content": ""
  },
  {
    "path": ".idea/.name",
    "content": "Shopping App"
  },
  {
    "path": ".idea/codeStyles/Project.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <JetCodeStyleSettings>\n      <option name=\"CODE_STYLE_DEFAULTS\" value=\"KOTLIN_OFFICIAL\" />\n    </JetCodeStyleSettings>\n    <codeStyleSettings language=\"XML\">\n      <option name=\"FORCE_REARRANGE_MODE\" value=\"1\" />\n      <indentOptions>\n        <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      </indentOptions>\n      <arrangement>\n        <rules>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>xmlns:android</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>xmlns:.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*:id</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*:name</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>name</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>style</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>ANDROID_ATTRIBUTE_ORDER</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>.*</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n        </rules>\n      </arrangement>\n    </codeStyleSettings>\n    <codeStyleSettings language=\"kotlin\">\n      <option name=\"CODE_STYLE_DEFAULTS\" value=\"KOTLIN_OFFICIAL\" />\n      <indentOptions>\n        <option name=\"USE_TAB_CHARACTER\" value=\"true\" />\n      </indentOptions>\n    </codeStyleSettings>\n  </code_scheme>\n</component>"
  },
  {
    "path": ".idea/codeStyles/codeStyleConfig.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <state>\n    <option name=\"USE_PER_PROJECT_SETTINGS\" value=\"true\" />\n  </state>\n</component>"
  },
  {
    "path": ".idea/compiler.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <bytecodeTargetLevel target=\"11\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleMigrationSettings\" migrationVersion=\"1\" />\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <option name=\"testRunner\" value=\"PLATFORM\" />\n        <option name=\"distributionType\" value=\"DEFAULT_WRAPPED\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"gradleJvm\" value=\"1.8\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n            <option value=\"$PROJECT_DIR$/app\" />\n          </set>\n        </option>\n        <option name=\"resolveModulePerSourceSet\" value=\"false\" />\n        <option name=\"useQualifiedModuleNames\" value=\"true\" />\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/jarRepositories.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RemoteRepositoriesConfiguration\">\n    <remote-repository>\n      <option name=\"id\" value=\"central\" />\n      <option name=\"name\" value=\"Maven Central repository\" />\n      <option name=\"url\" value=\"https://repo1.maven.org/maven2\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"jboss.community\" />\n      <option name=\"name\" value=\"JBoss Community repository\" />\n      <option name=\"url\" value=\"https://repository.jboss.org/nexus/content/repositories/public/\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"BintrayJCenter\" />\n      <option name=\"name\" value=\"BintrayJCenter\" />\n      <option name=\"url\" value=\"https://jcenter.bintray.com/\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"Google\" />\n      <option name=\"name\" value=\"Google\" />\n      <option name=\"url\" value=\"https://dl.google.com/dl/android/maven2/\" />\n    </remote-repository>\n  </component>\n</project>"
  },
  {
    "path": ".idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_11\" default=\"true\" project-jdk-name=\"1.8\" project-jdk-type=\"JavaSDK\">\n    <output url=\"file://$PROJECT_DIR$/build/classes\" />\n  </component>\n  <component name=\"ProjectType\">\n    <option name=\"id\" value=\"Android\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/render.experimental.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RenderSettings\">\n    <option name=\"showDecorations\" value=\"true\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/runConfigurations.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <option name=\"ignoredProducers\">\n      <set>\n        <option value=\"com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer\" />\n      </set>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 Vishal Gaur\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Shopping Android App\nAn e-commerce android application written in Kotlin where users can sell and buy products. \n\n\n## Overview\nThe application contains list of products such as shoes, slippers on which user can click to view its details and then, add them to cart. User can like and dislike the product as well. Also, User can sell products, if he/she signed up as a Seller.\nSome other features are as following:\n- Login / Signup with OTP Verification.\n- Recyclerview with variable span size to show products.\n- Search Bar and filtering\n- Product detail screen with image carousel and custom Radio Buttons.\n- Add/Edit Product for Sellers\n- See all orders placed.\n- Increase/Decrease quantity of product in cart.\n- Place Order.\n- Modify status of order for Seller.\n- Add/Edit Address\n- Tested using Espresso. Written unit, instrumentation and UI tests.\n\n## Some Screenshots\n\n|             Splash Screen            |             Application Home              |           Product Detail            |\n| :----------------------------------: | :---------------------------------------: | :----------------------------------:|\n| ![](snapshots/shopping-launcher.png) | ![](snapshots/shopping-home-customer.png) | ![](snapshots/shopping-product.png) |\n\n|                 Signup              |                Login              |        OTP Verification         |\n| :---------------------------------: | :-------------------------------: | :------------------------------:|\n| ![](snapshots/shopping-sign-up.png) | ![](snapshots/shopping-login.png) | ![](snapshots/shopping-otp.png) |\n\n|           Shopping Cart          |             Address Selection              |             Payment Method             |               Order Success               |\n| :------------------------------: | :----------------------------------------: | :-------------------------------------:| :---------------------------------------: |\n| ![](snapshots/shopping-cart.png) | ![](snapshots/shopping-select-address.png) | ![](snapshots/shopping-choose-pay.png) | ![](snapshots/shopping-order-success.png) |\n\n|               Add Product               |             All Orders             |                Order Detail              |               Sign Out               |\n| :-------------------------------------: | :--------------------------------: | :---------------------------------------:| :----------------------------------: |\n| ![](snapshots/shopping-add-product.png) | ![](snapshots/shopping-orders.png) | ![](snapshots/shopping-order-detail.png) | ![](snapshots/shopping-sign-out.png) |\n\n## Project Setup\n\n### Clone and install\n\nClone this repository and import into Android Studio\n```\ngit clone https://github.com/i-vishi/shopping-android-app.git\n```\n\n### Configuration\n- The project requires Firebase. So follow the steps given [here (Add Firebase to Android Project)](https://firebase.google.com/docs/android/setup) to add firebase to your android project.\n- Download the firebase config file `google-services.json`\n- Move the config file to `(app)` module of the project.\n- Also, add Cloud Firestore for storing users, products, orders and addresses data. Follow instructions [here (Add Cloud Firestore to your app)](https://firebase.google.com/docs/firestore/quickstart) to add Cloud Firestore to your app.\n- There need to be two collections - `users` for Users data and `products` for Products Data.\n- This project also, requires OTP based authentication. So, you just need to enable Phone Number sign-in in your firebase project. Follow instructions [here (Enable Phone Number sign-in)](https://firebase.google.com/docs/auth/android/phone-auth) to enable Phone Number sign-in. \n- Do not forget to enable app verification for your firebase project. Follow instructions [here (Enable app verification)](https://firebase.google.com/docs/auth/android/phone-auth#enable-app-verification) to enable app verification. Add both SHA-1 and SHA-256 fingerprints.\n\nTried everything but still not able to explore the app due to OTP errors? Don't worry, you can by-pass the OTP screen and explore the app.\n- Go to `app/src/main/java/com/vishalgaur/shoppingapp/Utils.kt` file.\n- Change the return value for function `shouldBypassOTPValidation()` to `true`.\n- You are good to go now. Just run the app and explore.\n- And take your time to setup the OTP verification. :wink:\n\n\n## Star History\n\n<a href=\"https://star-history.com/#i-vishi/shopping-android-app&Date\">\n <picture>\n   <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=i-vishi/shopping-android-app&type=Date&theme=dark\" />\n   <source media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=i-vishi/shopping-android-app&type=Date\" />\n   <img alt=\"Star History Chart\" src=\"https://api.star-history.com/svg?repos=i-vishi/shopping-android-app&type=Date\" />\n </picture>\n</a>\n\n\n## Built With\n- Kotlin\n- Firebase\n- Room\n- Material\n- Glide\n\n\n---\n\n<p align=\"center\"> Made with :blue_heart: by <a href=\"https://github.com/i-vishi\">Vishal Gaur</a></p>\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n\n/google-services.json\n"
  },
  {
    "path": "app/build.gradle",
    "content": "plugins {\n    id 'com.android.application'\n    id 'kotlin-android'\n    id 'kotlin-kapt'\n    id 'com.google.gms.google-services'\n    id 'kotlin-parcelize'\n}\n\nandroid {\n    compileSdkVersion 30\n    buildToolsVersion \"30.0.3\"\n\n    defaultConfig {\n        applicationId \"com.vishalgaur.shoppingapp\"\n        minSdkVersion 23\n        targetSdkVersion 30\n        versionCode 1\n        versionName \"1.0\"\n\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n    }\n\n    buildFeatures {\n        viewBinding true\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    kotlinOptions {\n        jvmTarget = '1.8'\n    }\n\n    packagingOptions {\n        exclude 'META-INF/AL2.0'\n        exclude 'META-INF/LGPL2.1'\n    }\n}\n\ndependencies {\n\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version\"\n\n    // Source: https://github.com/Kotlin/kotlinx.coroutines/tree/master/integration/kotlinx-coroutines-play-services\n    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.4.1'\n\n    implementation 'androidx.core:core-ktx:1.3.2'\n    implementation 'androidx.appcompat:appcompat:1.2.0'\n    implementation 'com.google.android.material:material:1.3.0'\n    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'\n    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'\n    implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'\n\n    // RecyclerView - beta with ConcatAdapter (previously MergeAdapter)\n    implementation \"androidx.recyclerview:recyclerview:1.2.0\"\n\n    // Room\n    implementation \"androidx.room:room-runtime:$room_version\"\n    implementation \"androidx.room:room-ktx:$room_version\"\n    implementation 'androidx.legacy:legacy-support-v4:1.0.0'\n    kapt \"androidx.room:room-compiler:$room_version\"\n\n    // ViewModel and LiveData\n    implementation \"androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version\"\n    implementation 'com.google.firebase:firebase-analytics'\n    implementation 'com.google.firebase:firebase-auth-ktx'\n\n    // Glide\n    implementation \"com.github.bumptech.glide:glide:$glide_version\"\n\n    //Firebase\n    implementation platform('com.google.firebase:firebase-bom:27.0.0')\n    implementation 'com.google.firebase:firebase-firestore-ktx'\n    implementation 'com.google.firebase:firebase-storage-ktx'\n\n    // Testing\n    testImplementation 'junit:junit:4.13.2'\n    androidTestImplementation 'androidx.test.ext:junit:1.1.2'\n    androidTestImplementation \"androidx.test.ext:junit-ktx:1.1.2\"\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'\n\n    // AndroidJUnitRunner and JUnit Rules\n    androidTestImplementation 'androidx.test:runner:1.3.0'\n    androidTestImplementation 'androidx.test:rules:1.3.0'\n\n    // espresso for intents\n    androidTestImplementation 'androidx.test.espresso:espresso-intents:3.3.0'\n\n    //espresso for recyclerview\n    androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0'\n\n    // AndroidX Test - JVM testing\n    testImplementation \"androidx.test.ext:junit-ktx:1.1.2\"\n    testImplementation \"androidx.arch.core:core-testing:2.1.0\"\n    testImplementation \"androidx.test:core-ktx:1.3.0\"\n\n    testImplementation \"org.robolectric:robolectric:4.3.1\"\n\n    androidTestImplementation \"androidx.arch.core:core-testing:2.1.0\"\n\n\n    // testing coroutines\n    androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.3'\n\n    //fragment testing\n    debugImplementation \"androidx.fragment:fragment-testing:1.3.3\"\n\n    //navigation testing\n    androidTestImplementation \"androidx.navigation:navigation-testing:2.3.5\"\n}"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/AppDatabaseTest.kt",
    "content": "package com.vishalgaur.shoppingapp\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.room.Room\nimport androidx.test.espresso.matcher.ViewMatchers.assertThat\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.local.ProductsDao\nimport com.vishalgaur.shoppingapp.data.source.local.ShoppingAppDatabase\nimport com.vishalgaur.shoppingapp.data.source.local.UserDao\nimport kotlinx.coroutines.runBlocking\nimport org.hamcrest.Matchers.*\nimport org.junit.After\nimport org.junit.Assert.assertEquals\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\nclass AppDatabaseTest {\n\tprivate val pro1 = Product(\n\t\t\"pro-owner1-shoe-101\",\n\t\t\"Shoe Name 101\",\n\t\t\"owner1\",\n\t\t\"some description\",\n\t\t\"Shoes\",\n\t\t250.0,\n\t\t300.0,\n\t\tlistOf(5, 6, 7, 8),\n\t\tlistOf(\"Red\", \"Blue\"),\n\t\tlistOf(\"http://image-ref-uri/shoe-101-01.jpg\", \"http://image-ref-uri/-shoe-101-02.jpg\"),\n\t\t2.5\n\t)\n\tprivate val pro2 = Product(\n\t\t\"pro-owner1-slipper-101\",\n\t\t\"Slipper Name 101\",\n\t\t\"owner1\",\n\t\t\"some description\",\n\t\t\"Slippers\",\n\t\t50.0,\n\t\t80.0,\n\t\tlistOf(6, 7, 8),\n\t\tlistOf(\"Black\", \"Blue\"),\n\t\tlistOf(\n\t\t\t\"http://image-ref-uri/-slipper-101-01.jpg\",\n\t\t\t\"http://image-ref-uri/-slipper-101-02.jpg\"\n\t\t),\n\t\t4.0\n\t)\n\n\tprivate lateinit var userDao: UserDao\n\tprivate lateinit var productsDao: ProductsDao\n\tprivate lateinit var appDb: ShoppingAppDatabase\n\n\t@get:Rule\n\tvar instantTaskExecutorRule = InstantTaskExecutorRule()\n\n\t@Before\n\tfun createDb() {\n\t\tval context = InstrumentationRegistry.getInstrumentation().targetContext\n\n\t\tappDb =\n\t\t\tRoom.inMemoryDatabaseBuilder(context, ShoppingAppDatabase::class.java)\n\t\t\t\t.allowMainThreadQueries()\n\t\t\t\t.build()\n\n\t\tuserDao = appDb.userDao()\n\t\tproductsDao = appDb.productsDao()\n\t}\n\n\t@After\n\tfun closeDb() {\n\t\tappDb.clearAllTables()\n\t\tappDb.close()\n\t}\n\n\t@Test\n\tfun insertAndGetUser() {\n\t\tval user = UserData(\n\t\t\t\"sdjm43892yfh948ehod\",\n\t\t\t\"Vishal\",\n\t\t\t\"+919999988888\",\n\t\t\t\"vishal@somemail.com\",\n\t\t\t\"dh94328hd\",\n\t\t\tArrayList(),\n\t\t\tArrayList(),\n\t\t\tArrayList()\n\t\t)\n\t\trunBlocking {\n\t\t\tuserDao.insert(user)\n\t\t\tval result = userDao.getById(\"sdjm43892yfh948ehod\")\n\t\t\tassertThat(result?.userId, `is`(user.userId))\n\t\t}\n\n\t}\n\n\t@Test\n\tfun noData_returnsNull() {\n\t\trunBlocking {\n\t\t\tval result = userDao.getById(\"1232\")\n\t\t\tassertThat(result, `is`(nullValue()))\n\t\t}\n\t}\n\n\t@Test\n\tfun insertClearUser_returnsNull() {\n\t\tval user = UserData(\n\t\t\t\"sdjm43892yfh948ehod\",\n\t\t\t\"Vishal\",\n\t\t\t\"+919999988888\",\n\t\t\t\"vishal@somemail.com\",\n\t\t\t\"dh94328hd\",\n\t\t\temptyList(),\n\t\t\temptyList(),\n\t\t\temptyList()\n\t\t)\n\t\trunBlocking {\n\t\t\tuserDao.insert(user)\n\t\t\tuserDao.clear()\n\t\t\tval result = userDao.getById(\"sdjm43892yfh948ehod\")\n\t\t\tassertThat(result, `is`(nullValue()))\n\t\t}\n\t}\n\n\t@Test\n\tfun insertAndGetProduct() {\n\t\trunBlocking {\n\t\t\tproductsDao.insert(pro1)\n\t\t\tval result = productsDao.getProductById(pro1.productId)\n\t\t\tassertEquals(pro1, result)\n\t\t}\n\t}\n\n\t@Test\n\tfun insertClearProduct_returnsNull() = runBlocking {\n\t\tproductsDao.insert(pro1)\n\t\tproductsDao.deleteAllProducts()\n\t\tval result = productsDao.getAllProducts()\n\t\tassertEquals(0, result.size)\n\t}\n\n\t@Test\n\tfun deleteProductById() = runBlocking {\n\t\tproductsDao.insert(pro2)\n\t\tproductsDao.deleteProductById(pro2.productId)\n\t\tval result = productsDao.getProductById(pro2.productId)\n\t\tassertThat(result, `is`(nullValue()))\n\t}\n\n\t@Test\n\tfun noProducts_returnsEmptyList() = runBlocking {\n\t\tval result = productsDao.getAllProducts()\n\t\tassertThat(result.size, `is`(0))\n\t}\n\n\t@Test\n\tfun deleteAllProducts_returnsEmptyList() = runBlocking {\n\t\tproductsDao.insert(pro2)\n\t\tproductsDao.deleteAllProducts()\n\t\tval result = productsDao.getAllProducts()\n\t\tassertThat(result.size, `is`(0))\n\t}\n\n\t@Test\n\tfun getProductsByOwner_returnsData() = runBlocking {\n\t\tproductsDao.insert(pro2)\n\t\tval result = productsDao.getProductsByOwnerId(pro2.owner)\n\t\tassertThat(result.size, `is`(1))\n\t}\n\n\t@Test\n\tfun insertMultipleProducts() = runBlocking {\n\t\tproductsDao.insertListOfProducts(listOf(pro1, pro2))\n\t\tval result = productsDao.getAllProducts()\n\t\tassertThat(result.size, `is`(2))\n\t}\n\n\t@Test\n\tfun observeProducts_returnsLiveData() = runBlocking {\n\t\tval initialRes = productsDao.observeProducts()\n\t\tproductsDao.insert(pro1)\n\t\tval newValue = productsDao.observeProducts().getOrAwaitValue()\n\n\t\tassertThat(initialRes.value, not(newValue))\n\t\tassertThat(initialRes.value, `is`(nullValue()))\n\t\tassertThat(newValue.size, `is`(1))\n\t}\n\n\t@Test\n\tfun observeProductsByOwner_returnsLiveData() = runBlocking {\n\t\tval initialRes = productsDao.observeProductsByOwner(pro1.owner)\n\t\tproductsDao.insert(pro1)\n\t\tval newValue = productsDao.observeProductsByOwner(pro1.owner).getOrAwaitValue()\n\n\t\tassertThat(initialRes.value, not(newValue))\n\t\tassertThat(initialRes.value, `is`(nullValue()))\n\t\tassertThat(newValue.size, `is`(1))\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/ClickClickableSpan.kt",
    "content": "package com.vishalgaur.shoppingapp\n\nimport android.text.SpannableString\nimport android.text.style.ClickableSpan\nimport android.view.View\nimport android.widget.TextView\nimport androidx.test.espresso.NoMatchingViewException\nimport androidx.test.espresso.UiController\nimport androidx.test.espresso.ViewAction\nimport org.hamcrest.Matcher\nimport org.hamcrest.Matchers\n\n\ninternal fun clickClickableSpan(textToClick: CharSequence): ViewAction {\n\treturn object : ViewAction {\n\n\t\toverride fun getConstraints(): Matcher<View> {\n\t\t\treturn Matchers.instanceOf(TextView::class.java)\n\t\t}\n\n\t\toverride fun getDescription(): String {\n\t\t\treturn \"clicking on a ClickableSpan\"\n\t\t}\n\n\t\toverride fun perform(uiController: UiController, view: View) {\n\t\t\tval textView = view as TextView\n\t\t\tval spannableString = textView.text as SpannableString\n\n\t\t\tif (spannableString.isEmpty()) {\n\t\t\t\t// TextView is empty, nothing to do\n\t\t\t\tthrow NoMatchingViewException.Builder()\n\t\t\t\t\t.includeViewHierarchy(true)\n\t\t\t\t\t.withRootView(textView)\n\t\t\t\t\t.build()\n\t\t\t}\n\n\t\t\t// Get the links inside the TextView and check if we find textToClick\n\t\t\tval spans =\n\t\t\t\tspannableString.getSpans(0, spannableString.length, ClickableSpan::class.java)\n\t\t\tif (spans.isNotEmpty()) {\n\t\t\t\tvar spanCandidate: ClickableSpan\n\t\t\t\tfor (span: ClickableSpan in spans) {\n\t\t\t\t\tspanCandidate = span\n\t\t\t\t\tval start = spannableString.getSpanStart(spanCandidate)\n\t\t\t\t\tval end = spannableString.getSpanEnd(spanCandidate)\n\t\t\t\t\tval sequence = spannableString.subSequence(start, end)\n\t\t\t\t\tif (textToClick.toString() == sequence.toString()) {\n\t\t\t\t\t\tspan.onClick(textView)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// textToClick not found in TextView\n\t\t\tthrow NoMatchingViewException.Builder()\n\t\t\t\t.includeViewHierarchy(true)\n\t\t\t\t.withRootView(textView)\n\t\t\t\t.build()\n\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/ExampleInstrumentedTest.kt",
    "content": "package com.vishalgaur.shoppingapp\n\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.platform.app.InstrumentationRegistry\nimport org.junit.Assert.assertEquals\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\n@RunWith(AndroidJUnit4::class)\nclass ExampleInstrumentedTest {\n\t@Test\n\tfun useAppContext() {\n\t\t// Context of the app under test.\n\t\tval appContext = InstrumentationRegistry.getInstrumentation().targetContext\n\t\tassertEquals(\"com.vishalgaur.shoppingapp\", appContext.packageName)\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/LiveDataTestUtil.kt",
    "content": "package com.vishalgaur.shoppingapp\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.Observer\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.TimeoutException\n\n/* Copyright 2019 Google LLC.\n   SPDX-License-Identifier: Apache-2.0 */\nfun <T> LiveData<T>.getOrAwaitValue(\n\ttime: Long = 2,\n\ttimeUnit: TimeUnit = TimeUnit.SECONDS\n): T {\n\tvar data: T? = null\n\tval latch = CountDownLatch(1)\n\tval observer = object : Observer<T> {\n\t\toverride fun onChanged(o: T?) {\n\t\t\tdata = o\n\t\t\tlatch.countDown()\n\t\t\tthis@getOrAwaitValue.removeObserver(this)\n\t\t}\n\t}\n\n\tthis.observeForever(observer)\n\n\t// Don't wait indefinitely if the LiveData is not set.\n\tif (!latch.await(time, timeUnit)) {\n\t\tthrow TimeoutException(\"LiveData value was never set.\")\n\t}\n\n\t@Suppress(\"UNCHECKED_CAST\")\n\treturn data as T\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/MainCoroutineRule.kt",
    "content": "package com.vishalgaur.shoppingapp\n\nimport kotlinx.coroutines.CoroutineDispatcher\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.TestCoroutineScope\nimport kotlinx.coroutines.test.resetMain\nimport kotlinx.coroutines.test.setMain\nimport org.junit.rules.TestWatcher\nimport org.junit.runner.Description\nimport kotlin.coroutines.ContinuationInterceptor\n\n@ExperimentalCoroutinesApi\nclass MainCoroutineRule : TestWatcher(), TestCoroutineScope by TestCoroutineScope() {\n\n\toverride fun starting(description: Description?) {\n\t\tsuper.starting(description)\n\t\tDispatchers.setMain(this.coroutineContext[ContinuationInterceptor] as CoroutineDispatcher)\n\t}\n\n\toverride fun finished(description: Description?) {\n\t\tsuper.finished(description)\n\t\tDispatchers.resetMain()\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/RecyclerViewMatcherUtils.kt",
    "content": "package com.vishalgaur.shoppingapp\n\nimport android.view.View\nimport androidx.recyclerview.widget.RecyclerView\nimport androidx.test.espresso.NoMatchingViewException\nimport androidx.test.espresso.ViewAction\nimport androidx.test.espresso.ViewAssertion\nimport androidx.test.espresso.matcher.BoundedMatcher\nimport androidx.test.espresso.matcher.ViewMatchers.assertThat\nimport org.hamcrest.Description\nimport org.hamcrest.Matcher\nimport org.hamcrest.Matchers.`is`\n\n\nfun atPosition(position: Int, itemMatcher: Matcher<View?>): Matcher<View?> {\n\treturn object : BoundedMatcher<View?, RecyclerView>(RecyclerView::class.java) {\n\t\toverride fun describeTo(description: Description) {\n\t\t\tdescription.appendText(\"has item at position $position: \")\n\t\t\titemMatcher.describeTo(description)\n\t\t}\n\n\t\toverride fun matchesSafely(view: RecyclerView): Boolean {\n\t\t\tval viewHolder = view.findViewHolderForAdapterPosition(position)\n\t\t\t\t?: // has no item on such position\n\t\t\t\treturn false\n\t\t\treturn itemMatcher.matches(viewHolder.itemView)\n\t\t}\n\t}\n}\n\nabstract class RecyclerViewItemAction: ViewAction {\n\toverride fun getConstraints(): Matcher<View>? {\n\t\treturn null\n\t}\n\n\toverride fun getDescription(): String {\n\t\treturn \"Action on a specific Button\"\n\t}\n}\n\nclass RecyclerViewItemCountAssertion(private val expectedCount: Int) : ViewAssertion {\n\toverride fun check(view: View, noViewFoundException: NoMatchingViewException?) {\n\t\tif (noViewFoundException != null) {\n\t\t\tthrow noViewFoundException\n\t\t}\n\t\tval recyclerView = view as RecyclerView\n\t\tval adapter = recyclerView.adapter\n\t\tassertThat(adapter!!.itemCount, `is`(expectedCount))\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/data/source/FakeAuthRepository.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source\n\nimport android.content.Context\nimport androidx.lifecycle.MutableLiveData\nimport com.google.firebase.auth.FirebaseAuth\nimport com.google.firebase.auth.PhoneAuthCredential\nimport com.google.firebase.auth.ktx.auth\nimport com.google.firebase.ktx.Firebase\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepoInterface\nimport com.vishalgaur.shoppingapp.data.utils.EmailMobileData\nimport com.vishalgaur.shoppingapp.data.utils.SignUpErrors\nimport com.vishalgaur.shoppingapp.data.utils.UserType\n\nclass FakeAuthRepository(private val sessionManager: ShoppingAppSessionManager) :\n\tAuthRepoInterface {\n\n\tprivate var emailMobileData = EmailMobileData()\n\tprivate var uData: UserData? = null\n\n\toverride suspend fun refreshData() {\n\t\t// no implementation\n\t}\n\n\toverride suspend fun signUp(userData: UserData) {\n\t\tuData = userData\n\t\tsessionManager.createLoginSession(\n\t\t\tuserData.userId,\n\t\t\tuserData.name,\n\t\t\tuserData.mobile,\n\t\t\tfalse,\n\t\t\tuserData.userType == UserType.SELLER.name\n\t\t)\n\t}\n\n\toverride fun login(userData: UserData, rememberMe: Boolean) {\n\t\tuData = userData\n\t\tsessionManager.createLoginSession(\n\t\t\tuserData.userId,\n\t\t\tuserData.name,\n\t\t\tuserData.mobile,\n\t\t\trememberMe,\n\t\t\tuserData.userType == UserType.SELLER.name\n\t\t)\n\t}\n\n\toverride suspend fun checkEmailAndMobile(\n\t\temail: String,\n\t\tmobile: String,\n\t\tcontext: Context\n\t): SignUpErrors {\n\t\t// no implementation\n\t\treturn SignUpErrors.NONE\n\t}\n\n\toverride suspend fun checkLogin(mobile: String, password: String): UserData? {\n\t\tuData?.let {\n\t\t\tif (it.mobile == mobile && it.password == password) {\n\t\t\t\treturn it\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n\n\toverride suspend fun signOut() {\n\t\tuData = null\n\t\tsessionManager.logoutFromSession()\n\t}\n\n\toverride suspend fun hardRefreshUserData() {\n\t\t// no implementation\n\t}\n\n\toverride suspend fun insertProductToLikes(productId: String, userId: String): Result<Boolean> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval likes = it.likes.toMutableList()\n\t\t\t\tlikes.add(productId)\n\t\t\t\tit.likes = likes\n\t\t\t\treturn Result.Success(true)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun removeProductFromLikes(\n\t\tproductId: String,\n\t\tuserId: String\n\t): Result<Boolean> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval likes = it.likes.toMutableList()\n\t\t\t\tlikes.remove(productId)\n\t\t\t\tit.likes = likes\n\t\t\t\treturn Result.Success(true)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun insertAddress(\n\t\tnewAddress: UserData.Address,\n\t\tuserId: String\n\t): Result<Boolean> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval addresses = it.addresses.toMutableList()\n\t\t\t\taddresses.add(newAddress)\n\t\t\t\tit.addresses = addresses\n\t\t\t\treturn Result.Success(true)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun updateAddress(\n\t\tnewAddress: UserData.Address,\n\t\tuserId: String\n\t): Result<Boolean> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval addresses = it.addresses.toMutableList()\n\t\t\t\taddresses.add(newAddress)\n\t\t\t\tval pos =\n\t\t\t\t\tit.addresses.indexOfFirst { address -> address.addressId == newAddress.addressId }\n\t\t\t\tif (pos >= 0) {\n\t\t\t\t\taddresses[pos] = newAddress\n\t\t\t\t}\n\t\t\t\tit.addresses = addresses\n\t\t\t\treturn Result.Success(true)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun deleteAddressById(addressId: String, userId: String): Result<Boolean> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval addresses = it.addresses.toMutableList()\n\t\t\t\tval pos = it.addresses.indexOfFirst { address -> address.addressId == addressId }\n\t\t\t\tif (pos >= 0) {\n\t\t\t\t\taddresses.removeAt(pos)\n\t\t\t\t}\n\t\t\t\tit.addresses = addresses\n\t\t\t\treturn Result.Success(true)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun insertCartItemByUserId(\n\t\tcartItem: UserData.CartItem,\n\t\tuserId: String\n\t): Result<Boolean> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval cart = it.cart.toMutableList()\n\t\t\t\tcart.add(cartItem)\n\t\t\t\tit.cart = cart\n\t\t\t\treturn Result.Success(true)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun updateCartItemByUserId(\n\t\tcartItem: UserData.CartItem,\n\t\tuserId: String\n\t): Result<Boolean> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval cart = it.cart.toMutableList()\n\t\t\t\tval pos = it.cart.indexOfFirst { item -> item.itemId == cartItem.itemId }\n\t\t\t\tif (pos >= 0) {\n\t\t\t\t\tcart[pos] = cartItem\n\t\t\t\t}\n\t\t\t\tit.cart = cart\n\t\t\t\treturn Result.Success(true)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun deleteCartItemByUserId(itemId: String, userId: String): Result<Boolean> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval cart = it.cart.toMutableList()\n\t\t\t\tval pos = it.cart.indexOfFirst { item -> item.itemId == itemId }\n\t\t\t\tif (pos >= 0) {\n\t\t\t\t\tcart.removeAt(pos)\n\t\t\t\t}\n\t\t\t\tit.cart = cart\n\t\t\t\treturn Result.Success(true)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun getAddressesByUserId(userId: String): Result<List<UserData.Address>?> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\treturn Result.Success(it.addresses)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun getLikesByUserId(userId: String): Result<List<String>?> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\treturn Result.Success(it.likes)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun getUserData(userId: String): Result<UserData?> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\treturn Result.Success(it)\n\t\t\t}\n\t\t}\n\t\treturn Result.Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride fun getFirebaseAuth(): FirebaseAuth {\n\t\treturn Firebase.auth\n\t}\n\n\toverride fun signInWithPhoneAuthCredential(\n\t\tcredential: PhoneAuthCredential,\n\t\tisUserLoggedIn: MutableLiveData<Boolean>,\n\t\tcontext: Context\n\t) {\n\t\t// no implementation\n\t}\n\n\toverride fun isRememberMeOn(): Boolean {\n\t\t// no implementation\n\t\treturn true\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/data/source/FakeProductsDataSource.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source\n\nimport android.net.Uri\nimport androidx.core.net.toUri\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.Transformations\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\n\nclass FakeProductsDataSource(private var products: MutableList<Product>? = mutableListOf()) :\n\tProductDataSource {\n\tprivate val imagesStorage = mutableListOf<String>()\n\toverride fun observeProducts(): LiveData<Result<List<Product>>?> {\n\t\tproducts?.let { pros ->\n\t\t\tval res = MutableLiveData(pros)\n\t\t\treturn Transformations.map(res) {\n\t\t\t\tSuccess(it.toList())\n\t\t\t}\n\t\t}\n\t\treturn MutableLiveData(Error(Exception()))\n\t}\n\n\toverride fun observeProductsByOwner(ownerId: String): LiveData<Result<List<Product>>?> {\n\t\tproducts?.let { allPros ->\n\t\t\tval pros = allPros.filter { pr -> pr.owner == ownerId }\n\t\t\tval res = MutableLiveData(pros)\n\t\t\treturn Transformations.map(res) {\n\t\t\t\tSuccess(it.toList())\n\t\t\t}\n\t\t}\n\t\treturn MutableLiveData(Error(Exception()))\n\t}\n\n\toverride suspend fun getAllProducts(): Result<List<Product>> {\n\t\tproducts?.let {\n\t\t\treturn Success(it)\n\t\t}\n\t\treturn Error(Exception(\"Products Not Found\"))\n\t}\n\n\toverride suspend fun refreshProducts() {\n\t\t// No implementation\n\t}\n\n\toverride suspend fun getProductById(productId: String): Result<Product> {\n\t\tproducts?.let {\n\t\t\tval res = it.filter { product -> product.productId == productId }\n\t\t\treturn if (res.isNotEmpty()) {\n\t\t\t\tSuccess(res[0])\n\t\t\t} else {\n\t\t\t\tError(Exception(\"Product Not Found\"))\n\t\t\t}\n\t\t}\n\t\treturn Error(Exception(\"Product Not Found\"))\n\t}\n\n\toverride suspend fun insertProduct(newProduct: Product) {\n\t\tproducts?.add(newProduct)\n\t}\n\n\toverride suspend fun updateProduct(proData: Product) {\n\t\tproducts?.let {\n\t\t\tval pos = it.indexOfFirst { product -> proData.productId == product.productId }\n\t\t\tit[pos] = proData\n\t\t}\n\t}\n\n\toverride suspend fun deleteProduct(productId: String) {\n\t\tproducts?.let {\n\t\t\tval pos = it.indexOfFirst { product -> productId == product.productId }\n\t\t\tif (pos >= 0)\n\t\t\t\tit.removeAt(pos)\n\t\t\telse throw Exception(\"Product Not Found\")\n\t\t}\n\t}\n\n\toverride suspend fun getAllProductsByOwner(ownerId: String): Result<List<Product>> {\n\t\tval res = products?.filter { product ->\n\t\t\tproduct.owner == ownerId\n\t\t}\n\t\treturn if (res != null) {\n\t\t\tSuccess(res)\n\t\t} else {\n\t\t\tSuccess(emptyList())\n\t\t}\n\t}\n\n\toverride suspend fun deleteAllProducts() {\n\t\tproducts = mutableListOf()\n\t}\n\n\toverride suspend fun insertMultipleProducts(data: List<Product>) {\n\t\tproducts?.addAll(data)\n\t}\n\n\toverride suspend fun uploadImage(uri: Uri, fileName: String): Uri {\n\t\tval res = uri.toString() + fileName\n\t\tif (res.contains(\"invalidinvalidinvalid\")) {\n\t\t\tthrow Exception(\"Error uploading Images\")\n\t\t}\n\t\timagesStorage.add(res)\n\t\treturn res.toUri()\n\t}\n\n\toverride fun revertUpload(fileName: String) {\n\t\tval pos = imagesStorage.indexOfFirst { imageRef ->\n\t\t\timageRef.contains(fileName)\n\t\t}\n\t\tif (pos >= 0) {\n\t\t\timagesStorage.removeAt(pos)\n\t\t}\n\t}\n\n\toverride fun deleteImage(imgUrl: String) {\n\t\timagesStorage.remove(imgUrl)\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/data/source/FakeProductsRepository.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source\n\nimport android.net.Uri\nimport androidx.core.net.toUri\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.Transformations\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.source.repository.ProductsRepoInterface\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport kotlinx.coroutines.runBlocking\nimport java.util.*\nimport kotlin.collections.LinkedHashMap\n\nclass FakeProductsRepository : ProductsRepoInterface {\n\n\tvar productsServiceData: LinkedHashMap<String, Product> = LinkedHashMap()\n\tprivate val imagesStorage = mutableListOf<String>()\n\tprivate val observableProducts = MutableLiveData<Result<List<Product>>>()\n\n\toverride suspend fun refreshProducts(): StoreDataStatus {\n\t\tobservableProducts.value = Success(productsServiceData.values.toList())\n\t\treturn StoreDataStatus.DONE\n\t}\n\n\toverride fun observeProducts(): LiveData<Result<List<Product>>?> {\n\t\trunBlocking { refreshProducts() }\n\t\treturn observableProducts\n\t}\n\n\toverride fun observeProductsByOwner(ownerId: String): LiveData<Result<List<Product>>?> {\n\t\trunBlocking { refreshProducts() }\n\t\treturn Transformations.map(observableProducts) { products ->\n\t\t\twhen (products) {\n\t\t\t\tis Result.Loading -> Result.Loading\n\t\t\t\tis Error -> Error(products.exception)\n\t\t\t\tis Success -> {\n\t\t\t\t\tval pros = products.data.filter { it.owner == ownerId }\n\t\t\t\t\tSuccess(pros)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun getAllProductsByOwner(ownerId: String): Result<List<Product>> {\n\t\tproductsServiceData.values.let { pros ->\n\t\t\tval res = pros.filter { it.owner == ownerId }\n\t\t\treturn Success(res)\n\t\t}\n\t}\n\n\toverride suspend fun getProductById(productId: String, forceUpdate: Boolean): Result<Product> {\n\t\tproductsServiceData[productId]?.let {\n\t\t\treturn Success(it)\n\t\t}\n\t\treturn Error(Exception(\"Product Not Found!\"))\n\t}\n\n\toverride suspend fun insertProduct(newProduct: Product): Result<Boolean> {\n\t\tproductsServiceData[newProduct.productId] = newProduct\n\t\treturn Success(true)\n\t}\n\n\toverride suspend fun insertImages(imgList: List<Uri>): List<String> {\n\t\tval result = mutableListOf<String>()\n\t\timgList.forEach { uri ->\n\t\t\tval uniId = UUID.randomUUID().toString()\n\t\t\tval fileName = uniId + uri.lastPathSegment?.split(\"/\")?.last()\n\t\t\tval res = uri.toString() + fileName\n\t\t\timagesStorage.add(res)\n\t\t\tresult.add(res)\n\t\t}\n\t\treturn result\n\t}\n\n\toverride suspend fun updateProduct(product: Product): Result<Boolean> {\n\t\tproductsServiceData[product.productId] = product\n\t\treturn Success(true)\n\t}\n\n\toverride suspend fun updateImages(newList: List<Uri>, oldList: List<String>): List<String> {\n\t\tval urlList = mutableListOf<String>()\n\t\tnewList.forEach { uri ->\n\t\t\tif (!oldList.contains(uri.toString())) {\n\t\t\t\tval uniId = UUID.randomUUID().toString()\n\t\t\t\tval fileName = uniId + uri.lastPathSegment?.split(\"/\")?.last()\n\t\t\t\tval res = uri.toString() + fileName\n\t\t\t\timagesStorage.add(res)\n\t\t\t\turlList.add(res)\n\t\t\t} else {\n\t\t\t\turlList.add(uri.toString())\n\t\t\t}\n\t\t}\n\t\toldList.forEach { imgUrl ->\n\t\t\tif (!newList.contains(imgUrl.toUri())) {\n\t\t\t\timagesStorage.remove(imgUrl)\n\t\t\t}\n\t\t}\n\t\treturn urlList\n\t}\n\n\toverride suspend fun deleteProductById(productId: String): Result<Boolean> {\n\t\tproductsServiceData.remove(productId)\n\t\trefreshProducts()\n\t\treturn Success(true)\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/data/source/FakeUserDataSource.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source\n\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.EmailMobileData\n\nclass FakeUserDataSource(private var uData: UserData?) : UserDataSource {\n\n\tprivate var emailMobileData = EmailMobileData()\n\n\toverride suspend fun addUser(userData: UserData) {\n\t\tuData = userData\n\t}\n\n\toverride suspend fun getUserById(userId: String): Result<UserData?> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\treturn Success(it)\n\t\t\t}\n\t\t}\n\t\treturn Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun getEmailsAndMobiles(): EmailMobileData {\n\t\treturn emailMobileData\n\t}\n\n\toverride suspend fun getUserByMobileAndPassword(\n\t\tmobile: String,\n\t\tpassword: String\n\t): MutableList<UserData> {\n\t\tval res = mutableListOf<UserData>()\n\t\tuData?.let {\n\t\t\tif (it.mobile == mobile && it.password == password) {\n\t\t\t\tres.add(it)\n\t\t\t}\n\t\t}\n\t\treturn res\n\t}\n\n\toverride suspend fun clearUser() {\n\t\tuData = null\n\t}\n\n\toverride suspend fun getUserByMobile(phoneNumber: String): UserData? {\n\t\treturn super.getUserByMobile(phoneNumber)\n\t}\n\n\toverride fun updateEmailsAndMobiles(email: String, mobile: String) {\n\t\temailMobileData.emails.add(email)\n\t\temailMobileData.mobiles.add(mobile)\n\t}\n\n\toverride suspend fun likeProduct(productId: String, userId: String) {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval likes = it.likes.toMutableList()\n\t\t\t\tlikes.add(productId)\n\t\t\t\tit.likes = likes\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun dislikeProduct(productId: String, userId: String) {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval likes = it.likes.toMutableList()\n\t\t\t\tlikes.remove(productId)\n\t\t\t\tit.likes = likes\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun insertAddress(newAddress: UserData.Address, userId: String) {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval addresses = it.addresses.toMutableList()\n\t\t\t\taddresses.add(newAddress)\n\t\t\t\tit.addresses = addresses\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun updateAddress(newAddress: UserData.Address, userId: String) {\n\t\tuData?.let { data ->\n\t\t\tif (data.userId == userId) {\n\t\t\t\tval addresses = data.addresses.toMutableList()\n\t\t\t\tval pos = data.addresses.indexOfFirst { it.addressId == newAddress.addressId }\n\t\t\t\tif (pos >= 0) {\n\t\t\t\t\taddresses[pos] = newAddress\n\t\t\t\t}\n\t\t\t\tdata.addresses = addresses\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun deleteAddress(addressId: String, userId: String) {\n\t\tuData?.let { data ->\n\t\t\tif (data.userId == userId) {\n\t\t\t\tval addresses = data.addresses.toMutableList()\n\t\t\t\tval pos = data.addresses.indexOfFirst { it.addressId == addressId }\n\t\t\t\tif (pos >= 0) {\n\t\t\t\t\taddresses.removeAt(pos)\n\t\t\t\t}\n\t\t\t\tdata.addresses = addresses\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun insertCartItem(newItem: UserData.CartItem, userId: String) {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\tval cart = it.cart.toMutableList()\n\t\t\t\tcart.add(newItem)\n\t\t\t\tit.cart = cart\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun updateCartItem(item: UserData.CartItem, userId: String) {\n\t\tuData?.let { data ->\n\t\t\tif (data.userId == userId) {\n\t\t\t\tval cart = data.cart.toMutableList()\n\t\t\t\tval pos = data.cart.indexOfFirst { it.itemId == item.itemId }\n\t\t\t\tif (pos >= 0) {\n\t\t\t\t\tcart[pos] = item\n\t\t\t\t}\n\t\t\t\tdata.cart = cart\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun deleteCartItem(itemId: String, userId: String) {\n\t\tuData?.let { data ->\n\t\t\tif (data.userId == userId) {\n\t\t\t\tval cart = data.cart.toMutableList()\n\t\t\t\tval pos = data.cart.indexOfFirst { it.itemId == itemId }\n\t\t\t\tif (pos >= 0) {\n\t\t\t\t\tcart.removeAt(pos)\n\t\t\t\t}\n\t\t\t\tdata.cart = cart\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun getAddressesByUserId(userId: String): Result<List<UserData.Address>?> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\treturn Success(it.addresses)\n\t\t\t}\n\t\t}\n\t\treturn Error(Exception(\"User Not Found\"))\n\t}\n\n\toverride suspend fun getLikesByUserId(userId: String): Result<List<String>?> {\n\t\tuData?.let {\n\t\t\tif (it.userId == userId) {\n\t\t\t\treturn Success(it.likes)\n\t\t\t}\n\t\t}\n\t\treturn Error(Exception(\"User Not Found\"))\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/data/source/repository/AuthRepositoryTest.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.repository\n\nimport android.content.Context\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.espresso.matcher.ViewMatchers.assertThat\nimport androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread\nimport com.google.firebase.FirebaseApp\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.FakeUserDataSource\nimport com.vishalgaur.shoppingapp.data.utils.SignUpErrors\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.hamcrest.Matchers.`is`\nimport org.hamcrest.Matchers.nullValue\nimport org.junit.Assert.assertEquals\nimport org.junit.Before\nimport org.junit.Test\n\n@ExperimentalCoroutinesApi\nclass AuthRepositoryTest {\n\tprivate val userSeller = UserData(\n\t\t\"weoifhwenf29385\",\n\t\t\"Seller Name\",\n\t\t\"+919999990000\",\n\t\t\"somemail@mail.com\",\n\t\t\"12345\",\n\t\temptyList(),\n\t\temptyList(),\n\t\temptyList(),\n\t\t\"SELLER\",\n\t)\n\tprivate val userCustomer = UserData(\n\t\t\"dwoeihwjklvn48329752\",\n\t\t\"Customer Name\",\n\t\t\"+919090909090\",\n\t\t\"somemail1232@mail.com\",\n\t\t\"12345\",\n\t\temptyList(),\n\t\temptyList(),\n\t\temptyList(),\n\t\t\"CUSTOMER\",\n\t)\n\n\tprivate lateinit var context: Context\n\n\tprivate lateinit var userLocalDataSource: FakeUserDataSource\n\tprivate lateinit var authRemoteDataSource: FakeUserDataSource\n\tprivate lateinit var sessionManager: ShoppingAppSessionManager\n\n\t// class under test\n\tprivate lateinit var authRepository: AuthRepository\n\n\t@Before\n\tfun createRepository() {\n\t\tcontext = ApplicationProvider.getApplicationContext()\n\t\tFirebaseApp.initializeApp(ApplicationProvider.getApplicationContext())\n\t\tuserLocalDataSource = FakeUserDataSource(userSeller)\n\t\tauthRemoteDataSource = FakeUserDataSource(userCustomer)\n\t\tsessionManager = ShoppingAppSessionManager(ApplicationProvider.getApplicationContext())\n\n\t\tauthRepository = AuthRepository(\n\t\t\tuserLocalDataSource,\n\t\t\tauthRemoteDataSource,\n\t\t\tsessionManager\n\t\t)\n\t}\n\n\t@Test\n\tfun login_getUserDetailFromSession() = runBlockingTest {\n\t\tauthRepository.login(userSeller, true)\n\t\tval result = sessionManager.getUserDataFromSession()\n\n\t\tassertThat(result[\"userName\"], `is`(userSeller.name))\n\t\tassertThat(result[\"userId\"], `is`(userSeller.userId))\n\t\tassertThat(result[\"userMobile\"], `is`(userSeller.mobile))\n\t}\n\n\t@Test\n\tfun singUp_addsUserToSources() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\n\t\tval resultSession = sessionManager.getUserDataFromSession()\n\t\tassertThat(resultSession[\"userName\"], `is`(userCustomer.name))\n\t\tassertThat(resultSession[\"userId\"], `is`(userCustomer.userId))\n\t\tassertThat(resultSession[\"userMobile\"], `is`(userCustomer.mobile))\n\n\t\tval localRes = userLocalDataSource.getUserById(userCustomer.userId)\n\t\tassertThat(localRes, `is`(Success(userCustomer)))\n\n\t\tval remoteRes = authRemoteDataSource.getUserById(userCustomer.userId)\n\t\tassertThat(remoteRes, `is`(Success(userCustomer)))\n\t}\n\n\t@Test\n\tfun checkEmailAndMobile_existingEmail_returnsError() {\n\t\tauthRemoteDataSource.updateEmailsAndMobiles(\"mail123@mail.com\", \"+919999988888\")\n\t\trunOnUiThread {\n\t\t\trunBlockingTest {\n\t\t\t\tval result =\n\t\t\t\t\tauthRepository.checkEmailAndMobile(\"mail123@mail.com\", \"+919685\", context)\n\t\t\t\tassertThat(result, `is`(SignUpErrors.SERR))\n\t\t\t}\n\t\t}\n\t}\n\n\t@Test\n\tfun checkEmailAndMobile_existingMobile_returnsError() {\n\t\tauthRemoteDataSource.updateEmailsAndMobiles(\"mail123@mail.com\", \"+919999988888\")\n\t\trunOnUiThread {\n\t\t\trunBlockingTest {\n\t\t\t\tval result =\n\t\t\t\t\tauthRepository.checkEmailAndMobile(\"mail999@mail.com\", \"+919999988888\", context)\n\t\t\t\tassertThat(result, `is`(SignUpErrors.SERR))\n\t\t\t}\n\t\t}\n\t}\n\n\t@Test\n\tfun checkEmailAndMobile_existingMobileAndEmail_returnsError() {\n\t\tauthRemoteDataSource.updateEmailsAndMobiles(\"mail123@mail.com\", \"+919999988888\")\n\t\trunOnUiThread {\n\t\t\trunBlockingTest {\n\t\t\t\tval result =\n\t\t\t\t\tauthRepository.checkEmailAndMobile(\"mail123@mail.com\", \"+919999988888\", context)\n\t\t\t\tassertThat(result, `is`(SignUpErrors.SERR))\n\t\t\t}\n\t\t}\n\t}\n\n\t@Test\n\tfun checkEmailAndMobile_newData_returnsError() {\n\t\tauthRemoteDataSource.updateEmailsAndMobiles(\"mail123@mail.com\", \"+919999988888\")\n\t\trunOnUiThread {\n\t\t\trunBlockingTest {\n\t\t\t\tval result =\n\t\t\t\t\tauthRepository.checkEmailAndMobile(\n\t\t\t\t\t\t\"somemail123@mail.com\",\n\t\t\t\t\t\t\"+919999977777\",\n\t\t\t\t\t\tcontext\n\t\t\t\t\t)\n\t\t\t\tassertThat(result, `is`(SignUpErrors.NONE))\n\t\t\t}\n\t\t}\n\t}\n\n\t@Test\n\tfun checkLogin_existingUser_returnsData() = runBlockingTest {\n\t\tval result = authRepository.checkLogin(userCustomer.mobile, userCustomer.password)\n\t\tassertThat(result, `is`(userCustomer))\n\t}\n\n\t@Test\n\tfun checkLogin_newCredentials_returnsNull() = runBlockingTest {\n\t\tval result = authRepository.checkLogin(\"+919879879879\", \"sdygt4\")\n\t\tassertThat(result, `is`(nullValue()))\n\t}\n\n\t@Test\n\tfun signOut_clearsSessionAndData() = runBlockingTest {\n\t\tauthRepository.signOut()\n\n\t\tval sessionRes = sessionManager.isLoggedIn()\n\t\tval localRes = userLocalDataSource.getUserById(userSeller.userId)\n\n\t\tassertThat(sessionRes, `is`(false))\n\t\tif (localRes is Success)\n\t\t\tassert(false)\n\t\telse if (localRes is Error) {\n\t\t\tassertEquals(localRes.exception.message, \"User Not Found\")\n\t\t}\n\t}\n\n\t@Test\n\tfun getLikes_returnsLikes() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\t\tval res = authRepository.getLikesByUserId(userCustomer.userId)\n\t\tif (res is Success) {\n\t\t\tassertThat(res.data, `is`(userCustomer.likes))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun likeProduct() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\t\tauthRepository.insertProductToLikes(\"some-id\", userCustomer.userId)\n\t\tval res = authRepository.getLikesByUserId(userCustomer.userId)\n\t\tif (res is Success) {\n\t\t\tassertThat(res.data?.size, `is`(1))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun dislikeProduct() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\t\tauthRepository.insertProductToLikes(\"some-id\", userCustomer.userId)\n\t\tauthRepository.removeProductFromLikes(\"some-id\", userCustomer.userId)\n\t\tval res = authRepository.getLikesByUserId(userCustomer.userId)\n\t\tif (res is Success) {\n\t\t\tassertThat(res.data?.contains(\"some-id\"), `is`(false))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun getAddresses() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\t\tval res = authRepository.getAddressesByUserId(userCustomer.userId)\n\t\tif (res is Success) {\n\t\t\tassertThat(res.data, `is`(userCustomer.addresses))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun addAddress() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\t\tval address = UserData.Address(\n\t\t\t\"id123-add\",\n\t\t\t\"namefirst\",\n\t\t\t\"lname\",\n\t\t\t\"IN\",\n\t\t\t\"2341 weg\",\n\t\t\t\"\",\n\t\t\t\"kanopwe\",\n\t\t\t\"up\",\n\t\t\t\"209876\",\n\t\t\t\"+919999988888\"\n\t\t)\n\t\tauthRepository.insertAddress(address, userCustomer.userId)\n\t\tval res = authRepository.getAddressesByUserId(userCustomer.userId)\n\t\tif (res is Success) {\n\t\t\tassertThat(res.data?.size, `is`(1))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun removeAddress() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\t\tval address = UserData.Address(\n\t\t\t\"id123-add\",\n\t\t\t\"namefirst\",\n\t\t\t\"lname\",\n\t\t\t\"IN\",\n\t\t\t\"2341 weg\",\n\t\t\t\"\",\n\t\t\t\"kanopwe\",\n\t\t\t\"up\",\n\t\t\t\"209876\",\n\t\t\t\"+919999988888\"\n\t\t)\n\t\tauthRepository.insertAddress(address, userCustomer.userId)\n\t\tauthRepository.deleteAddressById(address.addressId, userCustomer.userId)\n\t\tval res = authRepository.getAddressesByUserId(userCustomer.userId)\n\t\tif (res is Success) {\n\t\t\tassertThat(res.data?.contains(address), `is`(false))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun updateAddress() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\t\tval address = UserData.Address(\n\t\t\t\"id123-add\",\n\t\t\t\"namefirst\",\n\t\t\t\"lname\",\n\t\t\t\"IN\",\n\t\t\t\"2341 weg\",\n\t\t\t\"\",\n\t\t\t\"kanopwe\",\n\t\t\t\"up\",\n\t\t\t\"209876\",\n\t\t\t\"+919999988888\"\n\t\t)\n\t\tval newAddress = UserData.Address(\n\t\t\t\"id123-add\",\n\t\t\t\"namefirst\",\n\t\t\t\"lname\",\n\t\t\t\"IN\",\n\t\t\t\"2341 wesfgeg\",\n\t\t\t\"vdfg, heth\",\n\t\t\t\"kanopwe\",\n\t\t\t\"up\",\n\t\t\t\"209876\",\n\t\t\t\"+919999988888\"\n\t\t)\n\t\tauthRepository.insertAddress(address, userCustomer.userId)\n\t\tauthRepository.updateAddress(newAddress, userCustomer.userId)\n\t\tval res = authRepository.getAddressesByUserId(userCustomer.userId)\n\t\tif (res is Success) {\n\t\t\tassertThat(res.data?.contains(newAddress), `is`(true))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun addItemToCart() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\t\tval item = UserData.CartItem(\n\t\t\t\"item-id-123\",\n\t\t\t\"pro-122\",\n\t\t\t\"owner-1213\",\n\t\t\t1,\n\t\t\t\"black\",\n\t\t\t7\n\t\t)\n\t\tauthRepository.insertCartItemByUserId(item, userCustomer.userId)\n\t\tval userRes = userLocalDataSource.getUserById(userCustomer.userId)\n\t\tif (userRes is Success) {\n\t\t\tval data = userRes.data\n\t\t\tif (data != null) {\n\t\t\t\tval cart = data.cart\n\t\t\t\tassertThat(cart.contains(item), `is`(true))\n\t\t\t} else {\n\t\t\t\tassert(false)\n\t\t\t}\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun removeItemFromCart() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\t\tval item = UserData.CartItem(\n\t\t\t\"item-id-123\",\n\t\t\t\"pro-122\",\n\t\t\t\"owner-1213\",\n\t\t\t1,\n\t\t\t\"black\",\n\t\t\t7\n\t\t)\n\t\tauthRepository.insertCartItemByUserId(item, userCustomer.userId)\n\t\tauthRepository.deleteCartItemByUserId(item.itemId, userCustomer.userId)\n\t\tval userRes = userLocalDataSource.getUserById(userCustomer.userId)\n\t\tif (userRes is Success) {\n\t\t\tval data = userRes.data\n\t\t\tif (data != null) {\n\t\t\t\tval cart = data.cart\n\t\t\t\tassertThat(cart.contains(item), `is`(false))\n\t\t\t} else {\n\t\t\t\tassert(false)\n\t\t\t}\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun updateItemInCart() = runBlockingTest {\n\t\tauthRepository.signUp(userCustomer)\n\t\tval item = UserData.CartItem(\n\t\t\t\"item-id-123\",\n\t\t\t\"pro-122\",\n\t\t\t\"owner-1213\",\n\t\t\t1,\n\t\t\t\"black\",\n\t\t\t7\n\t\t)\n\t\tval newItem = UserData.CartItem(\n\t\t\t\"item-id-123\",\n\t\t\t\"pro-122\",\n\t\t\t\"owner-1213\",\n\t\t\t5,\n\t\t\t\"black\",\n\t\t\t7\n\t\t)\n\t\tauthRepository.insertCartItemByUserId(item, userCustomer.userId)\n\t\tauthRepository.updateCartItemByUserId(newItem, userCustomer.userId)\n\t\tval userRes = userLocalDataSource.getUserById(userCustomer.userId)\n\t\tif (userRes is Success) {\n\t\t\tval data = userRes.data\n\t\t\tif (data != null) {\n\t\t\t\tval cart = data.cart\n\t\t\t\tassertThat(cart.contains(newItem), `is`(true))\n\t\t\t} else {\n\t\t\t\tassert(false)\n\t\t\t}\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/data/source/repository/ProductsRepositoryTest.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.repository\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.core.net.toUri\nimport androidx.test.espresso.matcher.ViewMatchers.assertThat\nimport com.vishalgaur.shoppingapp.ERR_UPLOAD\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.source.FakeProductsDataSource\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.getOrAwaitValue\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.hamcrest.Matchers.`is`\nimport org.hamcrest.Matchers.greaterThan\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertNotEquals\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\n\n@ExperimentalCoroutinesApi\nclass ProductsRepositoryTest {\n\tprivate val pro1 = Product(\n\t\t\"pro-owner1-shoe-101\",\n\t\t\"Shoe Name 101\",\n\t\t\"owner1\",\n\t\t\"some description\",\n\t\t\"Shoes\",\n\t\t250.0,\n\t\t300.0,\n\t\tlistOf(5, 6, 7, 8),\n\t\tlistOf(\"Red\", \"Blue\"),\n\t\tlistOf(\"http://image-ref-uri/shoe-101-01.jpg\", \"http://image-ref-uri/-shoe-101-02.jpg\"),\n\t\t2.5\n\t)\n\tprivate val pro2 = Product(\n\t\t\"pro-owner1-slipper-101\",\n\t\t\"Slipper Name 101\",\n\t\t\"owner1\",\n\t\t\"some description\",\n\t\t\"Slippers\",\n\t\t50.0,\n\t\t80.0,\n\t\tlistOf(6, 7, 8),\n\t\tlistOf(\"Black\", \"Blue\"),\n\t\tlistOf(\n\t\t\t\"http://image-ref-uri/-slipper-101-01.jpg\",\n\t\t\t\"http://image-ref-uri/-slipper-101-02.jpg\"\n\t\t),\n\t\t4.0\n\t)\n\tprivate val pro3 = Product(\n\t\t\"pro-owner1-shoe-102\",\n\t\t\"Shoe Name 102\",\n\t\t\"owner2\",\n\t\t\"some description\",\n\t\t\"Shoes\",\n\t\t450.0,\n\t\t600.0,\n\t\tlistOf(4, 5, 7, 8, 10),\n\t\tlistOf(\"Red\", \"Blue\", \"White\"),\n\t\tlistOf(\"http://image-ref-uri/-shoe-102-01.jpg\", \"http://image-ref-uri/-shoe-102-02.jpg\"),\n\t\t3.5\n\t)\n\n\tprivate lateinit var productsLocalDataSource: FakeProductsDataSource\n\tprivate lateinit var productsRemoteDataSource: FakeProductsDataSource\n\n\t// class under test\n\tprivate lateinit var productsRepository: ProductsRepository\n\n\t@get:Rule\n\tval instantTaskExecutorRule = InstantTaskExecutorRule()\n\n\t@Before\n\tfun createRepository() {\n\t\tproductsLocalDataSource = FakeProductsDataSource(mutableListOf())\n\t\tproductsRemoteDataSource = FakeProductsDataSource(mutableListOf(pro1, pro3))\n\n\t\tproductsRepository = ProductsRepository(productsRemoteDataSource, productsLocalDataSource)\n\t}\n\n\t@Test\n\tfun getProductsById_invalidId_returnsError() = runBlockingTest {\n\t\tval resultRes = productsRepository.getProductById(\"invalidId\", false)\n\t\tif (resultRes is Result.Success)\n\t\t\tassert(false)\n\t\telse if (resultRes is Result.Error) {\n\t\t\tassertEquals(resultRes.exception.message, \"Product Not Found\")\n\t\t}\n\t}\n\n\t@Test\n\tfun getProductsById_validId_returnsProduct() = runBlockingTest {\n\t\tproductsRepository.insertProduct(pro1)\n\t\tval resultRes = productsRepository.getProductById(pro1.productId, false)\n\t\tif (resultRes is Result.Success) {\n\t\t\tassertThat(resultRes.data, `is`(pro1))\n\t\t} else if (resultRes is Result.Error) {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun insertProduct_returnsSuccess() = runBlockingTest {\n\t\tval insertRes = productsRepository.insertProduct(pro1)\n\t\tif (insertRes is Result.Success) {\n\t\t\tassertThat(insertRes.data, `is`(true))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun insertImages_returnsSuccess() = runBlockingTest {\n\t\tval result = productsRepository.insertImages(pro1.images.map { it.toUri() })\n\t\tassertThat(result.size, `is`(pro1.images.size))\n\t}\n\n\t@Test\n\tfun insertImages_invalidImages_returnsError() = runBlockingTest {\n\t\tval result =\n\t\t\tproductsRepository.insertImages(listOf(\"http://image-ref-uri/dwoeiovnwi-invalidinvalidinvalid/weoifhowf\".toUri()))\n\t\tassertThat(result[0], `is`(ERR_UPLOAD))\n\t}\n\n\t@Test\n\tfun updateProduct_returnsSuccess() = runBlockingTest {\n\t\tproductsRepository.insertProduct(pro2)\n\t\tval updatedPro = pro2\n\t\tupdatedPro.availableSizes = listOf(5, 6, 10, 12)\n\t\tval insertRes = productsRepository.updateProduct(updatedPro)\n\t\tif (insertRes is Result.Success) {\n\t\t\tassertThat(insertRes.data, `is`(true))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun updateImages_returnsList() = runBlockingTest {\n\t\tval oldList = productsRepository.insertImages(pro1.images.map { it.toUri() })\n\t\tval result = productsRepository.updateImages(pro3.images.map { it.toUri() }, oldList)\n\t\tassertThat(result.size, `is`(pro3.images.size))\n\t}\n\n\t@Test\n\tfun updateImages_invalidImage_returnsError() = runBlockingTest {\n\t\tval oldList = productsRepository.insertImages(pro1.images.map { it.toUri() })\n\t\tval newList = oldList.toMutableList()\n\t\tnewList[0] = \"http://csifduoskjgn/invalidinvalidinvalid/wehoiw\"\n\t\tval result = productsRepository.updateImages(newList.map { it.toUri() }, oldList)\n\t\tassertThat(result[0], `is`(ERR_UPLOAD))\n\t}\n\n\t@Test\n\tfun deleteProductById_returnsSuccess() = runBlockingTest {\n\t\tproductsRepository.insertProduct(pro1)\n\t\tproductsRepository.insertProduct(pro2)\n\t\tval result = productsRepository.deleteProductById(pro1.productId)\n\t\tassert(result is Result.Success)\n\t}\n\n\t@Test\n\tfun deleteProductById_invalidId_returnsError() = runBlockingTest {\n\t\tproductsRepository.insertProduct(pro1)\n\t\tproductsRepository.insertProduct(pro2)\n\t\tval result = productsRepository.deleteProductById(pro3.productId)\n\t\tassert(result is Result.Error)\n\t}\n\n\t@Test\n\tfun refreshProducts_returnsSuccess() = runBlockingTest {\n\t\tval result = productsRepository.refreshProducts()\n\t\tassertThat(result, `is`(StoreDataStatus.DONE))\n\t}\n\n\t@Test\n\tfun observeProducts_noData_returnsNoData() = runBlockingTest {\n\t\tproductsLocalDataSource.deleteAllProducts()\n\t\tval result = productsRepository.observeProducts().getOrAwaitValue()\n\t\tif (result is Result.Success) {\n\t\t\tassertThat(result.data.size, `is`(0))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun observeProducts_hasData_returnsSuccessWithData() = runBlockingTest {\n\t\tval initialValue = productsRepository.observeProducts().getOrAwaitValue()\n\n\t\tval insertRes = async { productsRepository.insertProduct(pro3) }\n\t\tinsertRes.await()\n\t\tval refreshRes = async { productsRepository.refreshProducts() }\n\t\tassertThat(refreshRes.await(), `is`(StoreDataStatus.DONE))\n\n\t\tval newValue = productsRepository.observeProducts().getOrAwaitValue()\n\n\t\tassertNotEquals(initialValue.toString(), newValue.toString())\n\t\tif (initialValue is Result.Success) {\n\t\t\tassertThat(initialValue.data.size, `is`(0))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t\tif (newValue is Result.Success) {\n\t\t\tassertThat(newValue.data.size, `is`(greaterThan(0)))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun observeProductsByOwner_noData_returnsNoData() = runBlockingTest {\n\t\tproductsLocalDataSource.deleteAllProducts()\n\t\tval result = productsRepository.observeProductsByOwner(pro1.owner).getOrAwaitValue()\n\t\tif (result is Result.Success) {\n\t\t\tassertThat(result.data.size, `is`(0))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun observeProductsByOwner_hasData_returnsSuccessWithData() = runBlockingTest {\n\t\tval initialValue = productsRepository.observeProductsByOwner(pro3.owner).getOrAwaitValue()\n\n\t\tval insertRes = async { productsRepository.insertProduct(pro3) }\n\t\tinsertRes.await()\n\t\tval refreshRes = async { productsRepository.refreshProducts() }\n\t\tassertThat(refreshRes.await(), `is`(StoreDataStatus.DONE))\n\n\t\tval newValue = productsRepository.observeProductsByOwner(pro3.owner).getOrAwaitValue()\n\n\t\tassertNotEquals(initialValue.toString(), newValue.toString())\n\t\tif (initialValue is Result.Success) {\n\t\t\tassertThat(initialValue.data.size, `is`(0))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t\tif (newValue is Result.Success) {\n\t\t\tassertThat(newValue.data.size, `is`(greaterThan(0)))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun getAllProductsByOwner_noData_returnsNoData() = runBlockingTest {\n\t\tproductsLocalDataSource.deleteAllProducts()\n\t\tval result = productsRepository.getAllProductsByOwner(pro1.owner)\n\t\tif (result is Result.Success) {\n\t\t\tassertThat(result.data.size, `is`(0))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n\t@Test\n\tfun getAllProductsByOwner_hasData_returnsData() = runBlockingTest {\n\t\tproductsRepository.refreshProducts()\n\t\tval result = productsRepository.getAllProductsByOwner(pro1.owner)\n\t\tif (result is Result.Success) {\n\t\t\tassertThat(result.data.size, `is`(greaterThan(0)))\n\t\t} else {\n\t\t\tassert(false)\n\t\t}\n\t}\n\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/ui/home/HomeFragmentTest.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.view.View\nimport android.widget.ImageView\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.core.view.isVisible\nimport androidx.fragment.app.testing.FragmentScenario\nimport androidx.fragment.app.testing.launchFragmentInContainer\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.navigation.testing.TestNavHostController\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.espresso.Espresso.onView\nimport androidx.test.espresso.UiController\nimport androidx.test.espresso.action.ViewActions.click\nimport androidx.test.espresso.action.ViewActions.typeText\nimport androidx.test.espresso.assertion.ViewAssertions.matches\nimport androidx.test.espresso.contrib.RecyclerViewActions\nimport androidx.test.espresso.matcher.RootMatchers.isDialog\nimport androidx.test.espresso.matcher.ViewMatchers.*\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread\nimport com.vishalgaur.shoppingapp.*\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.FakeAuthRepository\nimport com.vishalgaur.shoppingapp.data.source.FakeProductsRepository\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepoInterface\nimport com.vishalgaur.shoppingapp.data.source.repository.ProductsRepoInterface\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.runBlocking\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.hamcrest.Matchers.`is`\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\n@ExperimentalCoroutinesApi\nclass HomeFragmentTest {\n\tprivate lateinit var homeScenario: FragmentScenario<HomeFragment>\n\tprivate lateinit var navController: NavController\n\tprivate lateinit var sessionManager: ShoppingAppSessionManager\n\tprivate lateinit var productsRepository: ProductsRepoInterface\n\tprivate lateinit var authRepository: AuthRepoInterface\n\tprivate val context = ApplicationProvider.getApplicationContext<ShoppingApplication>()\n\n\tprivate val userCustomer = UserData(\n\t\t\"sdjm43892yfh948ehod\",\n\t\t\"Vishal\",\n\t\t\"+919999988888\",\n\t\t\"vishal@somemail.com\",\n\t\t\"dh94328hd\",\n\t\tArrayList(),\n\t\tArrayList(),\n\t\tArrayList(),\n\t\t\"CUSTOMER\"\n\t)\n\tprivate val userSeller = UserData(\n\t\t\"user1234selller\",\n\t\t\"Some Name\",\n\t\t\"+919999988888\",\n\t\t\"somemail123seller@somemail.com\",\n\t\t\"1234\",\n\t\temptyList(),\n\t\temptyList(),\n\t\temptyList(),\n\t\t\"SELLER\"\n\t)\n\n\tprivate val pro1 = Product(\n\t\t\"pro-owner1-shoe-101\",\n\t\t\"Shoe Name 101\",\n\t\t\"user1234selller\",\n\t\t\"some description\",\n\t\t\"Shoes\",\n\t\t250.0,\n\t\t300.0,\n\t\tlistOf(5, 6, 7, 8),\n\t\tlistOf(\"Red\", \"Blue\"),\n\t\tlistOf(\"http://image-ref-uri/shoe-101-01.jpg\", \"http://image-ref-uri/-shoe-101-02.jpg\"),\n\t\t2.5\n\t)\n\tprivate val pro2 = Product(\n\t\t\"pro-owner1-slipper-101\",\n\t\t\"Slipper Name 101\",\n\t\t\"owner1\",\n\t\t\"some description\",\n\t\t\"Slippers\",\n\t\t50.0,\n\t\t80.0,\n\t\tlistOf(6, 7, 8),\n\t\tlistOf(\"Black\", \"Blue\"),\n\t\tlistOf(\n\t\t\t\"http://image-ref-uri/-slipper-101-01.jpg\",\n\t\t\t\"http://image-ref-uri/-slipper-101-02.jpg\"\n\t\t),\n\t\t4.0\n\t)\n\n\n\t@get:Rule\n\tvar instantTaskExecutorRule = InstantTaskExecutorRule()\n\n\t@Before\n\tfun setUp() {\n\t\tsessionManager = ShoppingAppSessionManager(context)\n\t\tauthRepository = FakeAuthRepository(sessionManager)\n\t\tproductsRepository = FakeProductsRepository()\n\t\tServiceLocator.productsRepository = productsRepository\n\t}\n\n\t@After\n\tfun cleanUp() = runBlockingTest {\n\t\tauthRepository.signOut()\n\t\tServiceLocator.resetRepository()\n\t}\n\n\t@Test\n\tfun userCustomer_hideFABandEditDeleteButtons() = runBlockingTest {\n\t\tinsertProducts()\n\t\tloginCustomer()\n\n\t\tonView(withId(R.id.home_fab_add_product)).check(matches(withEffectiveVisibility(Visibility.GONE)))\n\n\t\t//testing recyclerview items\n\t\tonView(withId(R.id.products_recycler_view))\n\t\t\t.perform(\n\t\t\t\tRecyclerViewActions.actionOnItemAtPosition<ProductAdapter.ItemViewHolder>(\n\t\t\t\t\t0,\n\t\t\t\t\tobject : RecyclerViewItemAction() {\n\t\t\t\t\t\toverride fun perform(uiController: UiController?, view: View) {\n\t\t\t\t\t\t\tval editButton: ImageView = view.findViewById(R.id.product_edit_button)\n\t\t\t\t\t\t\tval deleteButton: ImageView =\n\t\t\t\t\t\t\t\tview.findViewById(R.id.product_delete_button)\n\t\t\t\t\t\t\tassertThat(editButton.isVisible, `is`(false))\n\t\t\t\t\t\t\tassertThat(deleteButton.isVisible, `is`(false))\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t)\n\t}\n\n\t@Test\n\tfun userSeller_showFABandEditDeleteButtons() = runBlockingTest {\n\t\tinsertProducts()\n\t\tloginSeller()\n\n\t\tonView(withId(R.id.home_fab_add_product)).check(matches(withEffectiveVisibility(Visibility.VISIBLE)))\n\t\t//testing recyclerview items\n\t\tonView(withId(R.id.products_recycler_view))\n\t\t\t.perform(\n\t\t\t\tRecyclerViewActions.actionOnItemAtPosition<ProductAdapter.ItemViewHolder>(\n\t\t\t\t\t0,\n\t\t\t\t\tobject : RecyclerViewItemAction() {\n\t\t\t\t\t\toverride fun perform(uiController: UiController?, view: View) {\n\t\t\t\t\t\t\tval editButton: ImageView = view.findViewById(R.id.product_edit_button)\n\t\t\t\t\t\t\tval deleteButton: ImageView =\n\t\t\t\t\t\t\t\tview.findViewById(R.id.product_delete_button)\n\t\t\t\t\t\t\tassertThat(editButton.isVisible, `is`(true))\n\t\t\t\t\t\t\tassertThat(deleteButton.isVisible, `is`(true))\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t)\n\t}\n\n\t@Test\n\tfun onFABClick_openCategoryDialog() {\n\t\tloginSeller()\n\n\t\tonView(withId(R.id.home_fab_add_product)).perform(click())\n\t\tonView(withText(R.string.pro_cat_dialog_title)).inRoot(isDialog())\n\t\t\t.check(matches(isDisplayed()))\n\t}\n\n\t@Test\n\tfun onSelectCategory_openAddProductFragment() {\n\t\tloginSeller()\n\n\t\tonView(withId(R.id.home_fab_add_product)).perform(click())\n\t\tonView(withText(R.string.pro_cat_dialog_ok_btn)).inRoot(isDialog())\n\t\t\t.check(matches(isDisplayed())).perform(click())\n\n\t\tassertThat(navController.currentDestination?.id, `is`(R.id.addEditProductFragment))\n\t}\n\n\t@Test\n\tfun onFilterClick_openFilterDialog() = runBlockingTest{\n\t\tinsertProducts()\n\t\tloginCustomer()\n\t\tonView(withId(R.id.home_filter)).perform(click())\n\t\tonView(withText(\"Shoes\")).inRoot(isDialog())\n\t\t\t.perform(click())\n\t\tonView(withText(R.string.pro_cat_dialog_ok_btn)).inRoot(isDialog())\n\t\t\t.perform(click())\n\t\tonView(withId(R.id.products_recycler_view)).check(RecyclerViewItemCountAssertion(1))\n\n\t}\n\n\t@Test\n\tfun onFilter_filterResults() {\n\t\tloginCustomer()\n\t\tonView(withId(R.id.home_filter)).perform(click())\n\t\tonView(withText(R.string.pro_cat_dialog_title)).inRoot(isDialog())\n\t\t\t.check(matches(isDisplayed()))\n\t}\n\n\t@Test\n\tfun enterSearch_filtersResults() {\n\t\trunBlocking {\n\t\t\tinsertProducts()\n\t\t\tloginCustomer()\n\t\t\tonView(withId(R.id.home_search_edit_text)).perform(typeText(\"slipper\"))\n\t\t\tdelay(500)\n\t\t\tonView(withId(R.id.products_recycler_view)).check(RecyclerViewItemCountAssertion(1))\n\t\t}\n\t}\n\n\tprivate fun loginSeller() {\n\t\tauthRepository.login(userSeller, true)\n\t\tServiceLocator.authRepository = authRepository\n\t\tsetScenarioAndNav()\n\t}\n\n\tprivate fun loginCustomer() {\n\t\tauthRepository.login(userCustomer, true)\n\t\tServiceLocator.authRepository = authRepository\n\t\tsetScenarioAndNav()\n\t}\n\n\tprivate fun setScenarioAndNav() {\n\t\thomeScenario = launchFragmentInContainer(Bundle(), R.style.Theme_ShoppingApp)\n\t\tnavController = TestNavHostController(context)\n\t\trunOnUiThread {\n\t\t\tnavController.setGraph(R.navigation.home_nav_graph)\n\t\t\thomeScenario.onFragment {\n\t\t\t\tNavigation.setViewNavController(it.requireView(), navController)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate suspend fun insertProducts() {\n\t\tproductsRepository.insertProduct(pro1)\n\t\tproductsRepository.insertProduct(pro2)\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/ui/home/ProductDetailsFragmentTest.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.fragment.app.testing.FragmentScenario\nimport androidx.navigation.NavController\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport com.vishalgaur.shoppingapp.ServiceLocator\nimport com.vishalgaur.shoppingapp.ShoppingApplication\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.FakeAuthRepository\nimport com.vishalgaur.shoppingapp.data.source.FakeProductsRepository\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepoInterface\nimport com.vishalgaur.shoppingapp.data.source.repository.ProductsRepoInterface\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\n@ExperimentalCoroutinesApi\nclass ProductDetailsFragmentTest {\n\tprivate lateinit var productDetailScenario: FragmentScenario<ProductDetailsFragment>\n\tprivate lateinit var navController: NavController\n\tprivate lateinit var sessionManager: ShoppingAppSessionManager\n\tprivate lateinit var productsRepository: ProductsRepoInterface\n\tprivate lateinit var authRepository: AuthRepoInterface\n\tprivate val context = ApplicationProvider.getApplicationContext<ShoppingApplication>()\n\n\tprivate val pro1 = Product(\n\t\t\"pro-owner1-shoe-101\",\n\t\t\"Shoe Name 101\",\n\t\t\"user1234selller\",\n\t\t\"some description\",\n\t\t\"Shoes\",\n\t\t250.0,\n\t\t300.0,\n\t\tlistOf(5, 6, 7, 8),\n\t\tlistOf(\"Red\", \"Blue\"),\n\t\tlistOf(\"http://image-ref-uri/shoe-101-01.jpg\", \"http://image-ref-uri/-shoe-101-02.jpg\"),\n\t\t2.5\n\t)\n\n\tprivate val userCustomer = UserData(\n\t\t\"sdjm43892yfh948ehod\",\n\t\t\"Vishal\",\n\t\t\"+919999988888\",\n\t\t\"vishal@somemail.com\",\n\t\t\"dh94328hd\",\n\t\tArrayList(),\n\t\tArrayList(),\n\t\tArrayList(),\n\t\t\"CUSTOMER\"\n\t)\n\tprivate val userSeller = UserData(\n\t\t\"user1234selller\",\n\t\t\"Some Name\",\n\t\t\"+919999988888\",\n\t\t\"somemail123seller@somemail.com\",\n\t\t\"1234\",\n\t\temptyList(),\n\t\temptyList(),\n\t\temptyList(),\n\t\t\"SELLER\"\n\t)\n\n\t@get:Rule\n\tvar instantTaskExecutorRule = InstantTaskExecutorRule()\n\n\t@Before\n\tfun setUp() {\n\t\tsessionManager = ShoppingAppSessionManager(context)\n\t\tauthRepository = FakeAuthRepository(sessionManager)\n\t\tproductsRepository = FakeProductsRepository()\n\t\tServiceLocator.productsRepository = productsRepository\n\t}\n\n\t@After\n\tfun cleanUp() = runBlockingTest {\n\t\tauthRepository.signOut()\n\t\tServiceLocator.resetRepository()\n\t}\n\n\tprivate suspend fun insertProducts() {\n\t\tproductsRepository.insertProduct(pro1)\n\t}\n}\n"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/ui/loginSignup/LoginFragmentTest.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.loginSignup\n\nimport androidx.fragment.app.testing.FragmentScenario\nimport androidx.fragment.app.testing.launchFragmentInContainer\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.navigation.testing.TestNavHostController\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.espresso.Espresso.onView\nimport androidx.test.espresso.action.ViewActions.*\nimport androidx.test.espresso.assertion.ViewAssertions.matches\nimport androidx.test.espresso.intent.Intents\nimport androidx.test.espresso.intent.Intents.intended\nimport androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent\nimport androidx.test.espresso.matcher.ViewMatchers.*\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread\nimport androidx.test.platform.app.InstrumentationRegistry\nimport com.vishalgaur.shoppingapp.MOB_ERROR_TEXT\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.clickClickableSpan\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport org.hamcrest.Matchers.`is`\nimport org.junit.Assert\nimport org.junit.Before\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\nclass LoginFragmentTest {\n\tprivate lateinit var loginScenario: FragmentScenario<LoginFragment>\n\tprivate lateinit var navController: NavController\n\tprivate lateinit var sessionManager: ShoppingAppSessionManager\n\n\t@Before\n\tfun setUp() {\n\t\tsessionManager = ShoppingAppSessionManager(ApplicationProvider.getApplicationContext())\n\t\tsessionManager.logoutFromSession()\n\t\tloginScenario = launchFragmentInContainer(themeResId = R.style.Theme_ShoppingApp)\n\t\tnavController = TestNavHostController(ApplicationProvider.getApplicationContext())\n\n\t\trunOnUiThread {\n\t\t\tnavController.setGraph(R.navigation.signup_nav_graph)\n\t\t\tloginScenario.onFragment {\n\t\t\t\tNavigation.setViewNavController(it.requireView(), navController)\n\t\t\t}\n\t\t}\n\t}\n\n\t@Test\n\tfun useAppContext() {\n\t\tval context = InstrumentationRegistry.getInstrumentation().targetContext\n\t\tAssert.assertEquals(\"com.vishalgaur.shoppingapp\", context.packageName)\n\t}\n\n\t@Test\n\tfun userCanEnterMobile() {\n\t\tinsertInMobileEditText(\"8976527465\")\n\t}\n\n\t@Test\n\tfun userCanEnterPassword() {\n\t\tinsertInPwdEditText(\"dh239048fy\")\n\t}\n\n\t@Test\n\tfun userCanClickRemSwitch() {\n\t\tclickRememberSwitch()\n\t}\n\n\t@Test\n\tfun userCanClickSignUpText() {\n\t\tclickSignUpText()\n\t}\n\n\t@Test\n\tfun userCanClickForgotTextView() {\n\t\tclickForgotTextView()\n\t}\n\n\t@Test\n\tfun userCanClickLoginButton() {\n\t\tclickLoginButton()\n\t}\n\n\t@Test\n\tfun onSignUpClick_navigateToSignUpFragment() {\n\t\tclickSignUpText()\n\t\tassertThat(navController.currentDestination?.id, `is`(R.id.SignupFragment))\n\t}\n\n\t@Test\n\tfun onLogin_emptyForm_showsError() {\n\t\tclickLoginButton()\n\n\t\tonView(withId(R.id.login_error_text_view)).check(matches(isDisplayed()))\n\t}\n\n\t@Test\n\tfun onLogin_invalidMobile_showsError() {\n\t\tinsertInMobileEditText(\"  467856 \")\n\t\tinsertInPwdEditText(\"fd3g24\")\n\t\tclickLoginButton()\n\n\t\tonView(withId(R.id.login_mobile_edit_text)).check(matches(hasErrorText(`is`(MOB_ERROR_TEXT))))\n\t}\n\n\t@Test\n\tfun onLogin_validData_showsNoError() {\n\t\tIntents.init()\n\n\t\tinsertInMobileEditText(\"9966339966\")\n\t\tinsertInPwdEditText(\"1234\")\n\t\tclickLoginButton()\n\n\t\tintended(hasComponent(OtpActivity::class.java.name))\n\t}\n\n\tprivate fun insertInMobileEditText(phone: String) =\n\t\tonView(withId(R.id.login_mobile_edit_text)).perform(\n\t\t\tscrollTo(),\n\t\t\tclearText(),\n\t\t\ttypeText(phone)\n\t\t)\n\n\tprivate fun insertInPwdEditText(pwd: String) =\n\t\tonView(withId(R.id.login_password_edit_text)).perform(\n\t\t\tscrollTo(),\n\t\t\tclearText(),\n\t\t\ttypeText(pwd)\n\t\t)\n\n\tprivate fun clickRememberSwitch() =\n\t\tonView(withId(R.id.login_rem_switch))\n\t\t\t.perform(scrollTo(), click())\n\n\tprivate fun clickForgotTextView() =\n\t\tonView(withId(R.id.login_forgot_tv))\n\t\t\t.perform(scrollTo(), click())\n\n\tprivate fun clickLoginButton() =\n\t\tonView(withId(R.id.login_login_btn))\n\t\t\t.perform(scrollTo(), click())\n\n\tprivate fun clickSignUpText() =\n\t\tonView(withId(R.id.login_signup_text_view)).perform(\n\t\t\tscrollTo(),\n\t\t\tclickClickableSpan(\"Sign Up\")\n\t\t)\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/ui/loginSignup/SignupFragmentTest.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.loginSignup\n\nimport androidx.fragment.app.testing.FragmentScenario\nimport androidx.fragment.app.testing.launchFragmentInContainer\nimport androidx.navigation.NavController\nimport androidx.navigation.Navigation\nimport androidx.navigation.testing.TestNavHostController\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.espresso.Espresso.onView\nimport androidx.test.espresso.action.ViewActions.*\nimport androidx.test.espresso.assertion.ViewAssertions.matches\nimport androidx.test.espresso.intent.Intents\nimport androidx.test.espresso.intent.Intents.intended\nimport androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent\nimport androidx.test.espresso.matcher.ViewMatchers.*\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread\nimport androidx.test.platform.app.InstrumentationRegistry\nimport com.vishalgaur.shoppingapp.EMAIL_ERROR_TEXT\nimport com.vishalgaur.shoppingapp.MOB_ERROR_TEXT\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.clickClickableSpan\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport org.hamcrest.Matchers.`is`\nimport org.junit.Assert.assertEquals\nimport org.junit.Before\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\nclass SignupFragmentTest {\n\tprivate lateinit var signUpScenario: FragmentScenario<SignupFragment>\n\tprivate lateinit var navController: NavController\n\tprivate lateinit var sessionManager: ShoppingAppSessionManager\n\n\t@Before\n\tfun setUp() {\n\t\tsessionManager = ShoppingAppSessionManager(ApplicationProvider.getApplicationContext())\n\t\tsessionManager.logoutFromSession()\n\t\tsignUpScenario = launchFragmentInContainer(themeResId = R.style.Theme_ShoppingApp)\n\t\tnavController = TestNavHostController(ApplicationProvider.getApplicationContext())\n\n\t\trunOnUiThread {\n\t\t\tnavController.setGraph(R.navigation.signup_nav_graph)\n\t\t\tsignUpScenario.onFragment {\n\t\t\t\tNavigation.setViewNavController(it.requireView(), navController)\n\t\t\t}\n\t\t}\n\t}\n\n\t@Test\n\tfun useAppContext() {\n\t\tval context = InstrumentationRegistry.getInstrumentation().targetContext\n\t\tassertEquals(\"com.vishalgaur.shoppingapp\", context.packageName)\n\t}\n\n\t@Test\n\tfun userCanEnterName() {\n\t\tinsertInNameEditText(\"Vishal Gaur  \")\n\t}\n\n\t@Test\n\tfun userCanEnterMobile() {\n\t\tinsertInMobileEditText(\"8976527465\")\n\t}\n\n\t@Test\n\tfun userCanEnterEmail() {\n\t\tinsertInEmailEditText(\"  weuiyjkh@ujhyew.dciwe\")\n\t}\n\n\t@Test\n\tfun userCanEnterPassword() {\n\t\tinsertInPwdEditText(\"dh239048fy\")\n\t}\n\n\t@Test\n\tfun userCanEnterInCnfPassword() {\n\t\tinsertInCnfPwdEditText(\"con34uyf98\")\n\t}\n\n\t@Test\n\tfun userCanClickTermsSwitch() {\n\t\tclickTermsSwitch()\n\t}\n\n\t@Test\n\tfun userCanClickSellerSwitch() {\n\t\tclickSellerSwitch()\n\t}\n\n\t@Test\n\tfun userCanClickSignUp() {\n\t\tclickSignUpButton()\n\t}\n\n\t@Test\n\tfun userCanClickLogInText() {\n\t\tclickLoginText()\n\t}\n\n\t@Test\n\tfun onLoginClick_navigateToLoginFragment() {\n\t\tclickLoginText()\n\t\tassertEquals(navController.currentDestination?.id, R.id.LoginFragment)\n\t}\n\n\t@Test\n\tfun onSignUp_emptyForm_showsError() {\n\t\tclickSignUpButton()\n\n\t\tonView(withId(R.id.signup_error_text_view)).check(matches(isDisplayed()))\n\t}\n\n\t@Test\n\tfun onSignUp_invalidEmail_showsEmailError() {\n\t\tinsertInNameEditText(\"Vishal Gaur \")\n\t\tinsertInMobileEditText(\"8976527465  \")\n\t\tinsertInEmailEditText(\"  weuiyjyew.dciwe\")\n\t\tinsertInPwdEditText(\"dh239048fy\")\n\t\tinsertInCnfPwdEditText(\"dh239048fy\")\n\t\tclickTermsSwitch()\n\t\tclickSignUpButton()\n\n\t\tonView(withId(R.id.signup_email_edit_text)).check(matches(hasErrorText(`is`(EMAIL_ERROR_TEXT))))\n\t}\n\n\t@Test\n\tfun onSignUp_invalidMobile_showsMobileError() {\n\t\tinsertInNameEditText(\"Vishal Gaur \")\n\t\tinsertInMobileEditText(\"86527465  \")\n\t\tinsertInEmailEditText(\"  weuiyj@yew.dciwe\")\n\t\tinsertInPwdEditText(\"dh239048fy\")\n\t\tinsertInCnfPwdEditText(\"dh239048fy\")\n\t\tclickTermsSwitch()\n\t\tclickSignUpButton()\n\n\t\tonView(withId(R.id.signup_mobile_edit_text)).check(matches(hasErrorText(`is`(MOB_ERROR_TEXT))))\n\t}\n\n\t@Test\n\tfun onSignUp_notAcceptedTerms_showsError() {\n\t\tinsertInNameEditText(\"Vishal Gaur \")\n\t\tinsertInMobileEditText(\"8652744565  \")\n\t\tinsertInEmailEditText(\"  weuiyj@yew.dciwe\")\n\t\tinsertInPwdEditText(\"dh239048fy\")\n\t\tinsertInCnfPwdEditText(\"dh239048fy\")\n\t\tclickSignUpButton()\n\n\t\tonView(withId(R.id.signup_error_text_view)).check(matches(withText(\"Accept the Terms.\")))\n\t}\n\n\t@Test\n\tfun onSignUp_notSamePasswords_showsError() {\n\t\tinsertInNameEditText(\"Vishal Gaur \")\n\t\tinsertInMobileEditText(\"8652744565  \")\n\t\tinsertInEmailEditText(\"  weuiyj@yew.dciwe\")\n\t\tinsertInPwdEditText(\"dh2398fy\")\n\t\tinsertInCnfPwdEditText(\"dh239048fy\")\n\t\tclickTermsSwitch()\n\t\tclickSignUpButton()\n\n\t\tonView(withId(R.id.signup_error_text_view)).check(matches(withText(\"Both passwords are not same!\")))\n\t}\n\n\t@Test\n\tfun onSignUp_validForm_showsNoError() {\n\t\tIntents.init()\n\t\tinsertInNameEditText(\"Vishal Gaur \")\n\t\tinsertInMobileEditText(\"8652744565  \")\n\t\tinsertInEmailEditText(\"  weuiyj@yew.dciwe\")\n\t\tinsertInPwdEditText(\"dh2398fy\")\n\t\tinsertInCnfPwdEditText(\"dh2398fy\")\n\t\tclickTermsSwitch()\n\t\tclickSignUpButton()\n\n\t\tintended(hasComponent(OtpActivity::class.java.name))\n\t}\n\n\n\tprivate fun insertInNameEditText(name: String) =\n\t\tonView(withId(R.id.signup_name_edit_text)).perform(scrollTo(), clearText(), typeText(name))\n\n\tprivate fun insertInMobileEditText(phone: String) =\n\t\tonView(withId(R.id.signup_mobile_edit_text)).perform(\n\t\t\tscrollTo(),\n\t\t\tclearText(),\n\t\t\ttypeText(phone)\n\t\t)\n\n\tprivate fun insertInEmailEditText(email: String) =\n\t\tonView(withId(R.id.signup_email_edit_text)).perform(\n\t\t\tscrollTo(),\n\t\t\tclearText(),\n\t\t\ttypeText(email)\n\t\t)\n\n\tprivate fun insertInPwdEditText(pwd: String) =\n\t\tonView(withId(R.id.signup_password_edit_text)).perform(\n\t\t\tscrollTo(),\n\t\t\tclearText(),\n\t\t\ttypeText(pwd)\n\t\t)\n\n\tprivate fun insertInCnfPwdEditText(pwd2: String) =\n\t\tonView(withId(R.id.signup_cnf_password_edit_text)).perform(\n\t\t\tscrollTo(),\n\t\t\tclearText(),\n\t\t\ttypeText(pwd2)\n\t\t)\n\n\tprivate fun clickTermsSwitch() =\n\t\tonView(withId(R.id.signup_policy_switch)).perform(scrollTo(), click())\n\n\tprivate fun clickSellerSwitch() =\n\t\tonView(withId(R.id.signup_seller_switch)).perform(scrollTo(), click())\n\n\tprivate fun clickSignUpButton() =\n\t\tonView(withId(R.id.signup_signup_btn)).perform(scrollTo(), click())\n\n\tprivate fun clickLoginText() =\n\t\tonView(withId(R.id.signup_login_text_view)).perform(\n\t\t\tscrollTo(),\n\t\t\tclickClickableSpan(\"Log In\")\n\t\t)\n\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/viewModels/AddEditAddressViewModelTest.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.espresso.matcher.ViewMatchers.assertThat\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport com.vishalgaur.shoppingapp.ServiceLocator\nimport com.vishalgaur.shoppingapp.ShoppingApplication\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.FakeAuthRepository\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepoInterface\nimport com.vishalgaur.shoppingapp.getOrAwaitValue\nimport com.vishalgaur.shoppingapp.ui.AddAddressViewErrors\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.hamcrest.Matchers.*\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\n@ExperimentalCoroutinesApi\nclass AddEditAddressViewModelTest {\n\tprivate lateinit var addEditAddressViewModel: AddEditAddressViewModel\n\tprivate lateinit var authRepository: AuthRepoInterface\n\n\tval user = UserData(\n\t\t\"sdjm43892yfh948ehod\",\n\t\t\"Vishal\",\n\t\t\"+919999988888\",\n\t\t\"vishal@somemail.com\",\n\t\t\"dh94328hd\",\n\t\tArrayList(),\n\t\tArrayList(),\n\t\tArrayList()\n\t)\n\n\t@get:Rule\n\tvar instantTaskExecutorRule = InstantTaskExecutorRule()\n\n\t@Before\n\tfun setUp() {\n\t\tval context = ApplicationProvider.getApplicationContext<ShoppingApplication>()\n\t\tval sessionManager = ShoppingAppSessionManager(context)\n\t\tauthRepository = FakeAuthRepository(sessionManager)\n\t\tauthRepository.login(user, true)\n\t\tServiceLocator.authRepository = authRepository\n\t\taddEditAddressViewModel = AddEditAddressViewModel(context)\n\n\t}\n\n\t@After\n\tfun cleanUp() = runBlockingTest {\n\t\tServiceLocator.resetRepository()\n\t}\n\n\t@Test\n\tfun setIsEdit_setsValue() {\n\t\trunBlockingTest {\n\t\t\taddEditAddressViewModel.setIsEdit(false)\n\t\t\tval res = addEditAddressViewModel.isEdit.getOrAwaitValue()\n\t\t\tassertThat(res, `is`(false))\n\t\t}\n\t}\n\n\t@Test\n\tfun setAddressData_setsData() = runBlockingTest {\n\t\tval address = UserData.Address(\n\t\t\t\"add-id-121\",\n\t\t\t\"adg\",\n\t\t\t\"shgd\",\n\t\t\t\"IN\",\n\t\t\t\"sfhg45eyh\",\n\t\t\t\"\",\n\t\t\t\"kanpuit\",\n\t\t\t\"up\",\n\t\t\t\"309890\",\n\t\t\t\"9999988558\"\n\t\t)\n\t\tauthRepository.insertAddress(address, user.userId)\n\t\taddEditAddressViewModel.setAddressData(address.addressId)\n\t\tval result = addEditAddressViewModel.addressData.getOrAwaitValue()\n\t\tassertThat(result, `is`(address))\n\t}\n\n\t@Test\n\tfun submitAddress_emptyForm_returnsError() {\n\t\tval fname = \"adg\"\n\t\tval lname = \"\"\n\t\tval code = \"IN\"\n\t\tval streetAdd = \"sfhg45eyh\"\n\t\tval streetAdd2 = \"\"\n\t\tval city = \"\"\n\t\tval state = \"up\"\n\t\tval zip = \"309890\"\n\t\tval phone = \"9999988558\"\n\t\taddEditAddressViewModel.submitAddress(\n\t\t\tcode,\n\t\t\tfname,\n\t\t\tlname,\n\t\t\tstreetAdd,\n\t\t\tstreetAdd2,\n\t\t\tcity,\n\t\t\tstate,\n\t\t\tzip,\n\t\t\tphone\n\t\t)\n\t\tval result = addEditAddressViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result.size, `is`(greaterThan(0)))\n\t\tassertThat(result.contains(AddAddressViewErrors.ERR_CITY_EMPTY), `is`(true))\n\t}\n\n\t@Test\n\tfun submitAddress_invalidZipcode_returnsError() {\n\t\tval fname = \"adg\"\n\t\tval lname = \"serdg\"\n\t\tval code = \"IN\"\n\t\tval streetAdd = \"sfhg45eyh\"\n\t\tval streetAdd2 = \"\"\n\t\tval city = \"sfhg\"\n\t\tval state = \"up\"\n\t\tval zip = \"30990\"\n\t\tval phone = \"9999988558\"\n\t\taddEditAddressViewModel.submitAddress(\n\t\t\tcode,\n\t\t\tfname,\n\t\t\tlname,\n\t\t\tstreetAdd,\n\t\t\tstreetAdd2,\n\t\t\tcity,\n\t\t\tstate,\n\t\t\tzip,\n\t\t\tphone\n\t\t)\n\t\tval result = addEditAddressViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result.size, `is`(greaterThan(0)))\n\t\tassertThat(result.contains(AddAddressViewErrors.ERR_ZIP_INVALID), `is`(true))\n\t}\n\n\t@Test\n\tfun submitAddress_invalidPhone_returnsError() {\n\t\tval fname = \"adg\"\n\t\tval lname = \"serdg\"\n\t\tval code = \"IN\"\n\t\tval streetAdd = \"sfhg45eyh\"\n\t\tval streetAdd2 = \"\"\n\t\tval city = \"sfhg\"\n\t\tval state = \"up\"\n\t\tval zip = \"309903\"\n\t\tval phone = \"9999988efg558\"\n\t\taddEditAddressViewModel.submitAddress(\n\t\t\tcode,\n\t\t\tfname,\n\t\t\tlname,\n\t\t\tstreetAdd,\n\t\t\tstreetAdd2,\n\t\t\tcity,\n\t\t\tstate,\n\t\t\tzip,\n\t\t\tphone\n\t\t)\n\t\tval result = addEditAddressViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result.size, `is`(greaterThan(0)))\n\t\tassertThat(result.contains(AddAddressViewErrors.ERR_PHONE_INVALID), `is`(true))\n\t}\n\n\t@Test\n\tfun submitAddress_validData_returnsNoError() {\n\t\tval fname = \"adg\"\n\t\tval lname = \"serdg\"\n\t\tval code = \"IN\"\n\t\tval streetAdd = \"sfhg45eyh\"\n\t\tval streetAdd2 = \"\"\n\t\tval city = \"sfhg\"\n\t\tval state = \"up\"\n\t\tval zip = \"302203\"\n\t\tval phone = \"9879988558\"\n\t\taddEditAddressViewModel.submitAddress(\n\t\t\tcode,\n\t\t\tfname,\n\t\t\tlname,\n\t\t\tstreetAdd,\n\t\t\tstreetAdd2,\n\t\t\tcity,\n\t\t\tstate,\n\t\t\tzip,\n\t\t\tphone\n\t\t)\n\t\tval result = addEditAddressViewModel.errorStatus.getOrAwaitValue()\n\t\tassertThat(result.size, `is`(0))\n\n\t\tval resData = addEditAddressViewModel.newAddressData.getOrAwaitValue()\n\t\tassertThat(resData, `is`(notNullValue()))\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/viewModels/AddEditProductViewModelTest.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport android.net.Uri\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.core.net.toUri\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.espresso.matcher.ViewMatchers.assertThat\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.getOrAwaitValue\nimport com.vishalgaur.shoppingapp.ui.AddProductViewErrors\nimport org.hamcrest.Matchers.`is`\nimport org.hamcrest.Matchers.notNullValue\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\nclass AddEditProductViewModelTest {\n\tprivate lateinit var addEditProductViewModel: AddEditProductViewModel\n\tprivate lateinit var sessionManager: ShoppingAppSessionManager\n\n\tprivate val userSeller = UserData(\n\t\t\"user1234selller\",\n\t\t\"Some Name\",\n\t\t\"+919999988888\",\n\t\t\"somemail123seller@somemail.com\",\n\t\t\"1234\",\n\t\temptyList(),\n\t\temptyList(),\n\t\temptyList(),\n\t\t\"SELLER\"\n\t)\n\n\t@get:Rule\n\tvar instantTaskExecutorRule = InstantTaskExecutorRule()\n\n\t@Before\n\tfun setUp() {\n\t\tsessionManager = ShoppingAppSessionManager(ApplicationProvider.getApplicationContext())\n\t\tsessionManager.createLoginSession(\n\t\t\tuserSeller.userId,\n\t\t\tuserSeller.name,\n\t\t\tuserSeller.mobile,\n\t\t\tfalse,\n\t\t\ttrue\n\t\t)\n\t\taddEditProductViewModel =\n\t\t\tAddEditProductViewModel(ApplicationProvider.getApplicationContext())\n\t}\n\n\t@Test\n\tfun setCategory_Shoes() {\n\t\taddEditProductViewModel.setCategory(\"Shoes\")\n\t\tval result = addEditProductViewModel.selectedCategory.getOrAwaitValue()\n\t\tassertThat(result, `is`(\"Shoes\"))\n\t}\n\n\t@Test\n\tfun setIsEdit_true() {\n\t\taddEditProductViewModel.setIsEdit(true)\n\t\tval result = addEditProductViewModel.isEdit.getOrAwaitValue()\n\t\tassertThat(result, `is`(true))\n\t}\n\n\t@Test\n\tfun setIsEdit_false() {\n\t\taddEditProductViewModel.setIsEdit(false)\n\t\tval result = addEditProductViewModel.isEdit.getOrAwaitValue()\n\t\tassertThat(result, `is`(false))\n\t}\n\n\n\t@Test\n\tfun submitProduct_noData_returnsEmptyError() {\n\t\taddEditProductViewModel.setIsEdit(false)\n\t\tval name = \"\"\n\t\tval price = null\n\t\tval mrp = null\n\t\tval desc = \"\"\n\t\tval sizes = emptyList<Int>()\n\t\tval colors = emptyList<String>()\n\t\tval imgList = emptyList<Uri>()\n\n\t\taddEditProductViewModel.submitProduct(name, price, mrp, desc, sizes, colors, imgList)\n\t\tval result = addEditProductViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(AddProductViewErrors.EMPTY))\n\t}\n\n\t@Test\n\tfun submitProduct_invalidPrice_returnsPriceError() {\n\t\taddEditProductViewModel.setIsEdit(false)\n\t\tval name = \"vwsf\"\n\t\tval mrp = 125.0\n\t\tval price = 0.0\n\t\tval desc = \"crw rewg\"\n\t\tval sizes = listOf(5, 6)\n\t\tval colors = listOf(\"red\", \"blue\")\n\t\tval imgList = listOf(\"ffsd\".toUri(), \"sws\".toUri())\n\n\t\taddEditProductViewModel.submitProduct(name, price, mrp, desc, sizes, colors, imgList)\n\t\tval result = addEditProductViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(AddProductViewErrors.ERR_PRICE_0))\n\t}\n\n\t@Test\n\tfun submitProduct_allValid_returnsNoError() {\n\t\taddEditProductViewModel.setIsEdit(false)\n\t\taddEditProductViewModel.setCategory(\"Shoes\")\n\t\tval name = \"vwsf\"\n\t\tval mrp = 125.0\n\t\tval price = 100.0\n\t\tval desc = \"crw rewg\"\n\t\tval sizes = listOf(5, 6)\n\t\tval colors = listOf(\"red\", \"blue\")\n\t\tval imgList = listOf(\"ffsd\".toUri(), \"sws\".toUri())\n\n\t\taddEditProductViewModel.submitProduct(name, price, mrp, desc, sizes, colors, imgList)\n\t\tval result = addEditProductViewModel.errorStatus.getOrAwaitValue()\n\t\tval resultPro = addEditProductViewModel.newProductData.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(AddProductViewErrors.NONE))\n\t\tassertThat(resultPro, `is`(notNullValue()))\n\t\tassertThat(resultPro.name, `is`(\"vwsf\"))\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/viewModels/AuthViewModelTest.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.espresso.matcher.ViewMatchers.assertThat\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport com.vishalgaur.shoppingapp.getOrAwaitValue\nimport com.vishalgaur.shoppingapp.ui.LoginViewErrors\nimport com.vishalgaur.shoppingapp.ui.SignUpViewErrors\nimport org.hamcrest.Matchers.*\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\nclass AuthViewModelTest {\n\tprivate lateinit var authViewModel: AuthViewModel\n\n\t@get:Rule\n\tvar instantTaskExecutorRule = InstantTaskExecutorRule()\n\n\t@Before\n\tfun setUp() {\n\t\tauthViewModel = AuthViewModel(ApplicationProvider.getApplicationContext())\n\t}\n\n\t@Test\n\tfun signUpSubmitData_noData_returnsEmptyError() {\n\t\tval name = \"\"\n\t\tval mobile = \"\"\n\t\tval email = \"\"\n\t\tval pwd1 = \"\"\n\t\tval pwd2 = \"\"\n\t\tval isAccepted = false\n\t\tval isSeller = false\n\t\tauthViewModel.signUpSubmitData(name, mobile, email, pwd1, pwd2, isAccepted, isSeller)\n\t\tval result = authViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(SignUpViewErrors.ERR_EMPTY))\n\t\tassertThat(authViewModel.userData.value, `is`(nullValue()))\n\t}\n\n\t@Test\n\tfun signUpSubmitData_notAccepted_returnsNotAccError() {\n\t\tval name = \"uigbivs ihgfdsg\"\n\t\tval mobile = \"9988665555\"\n\t\tval email = \"owhfoi@oihw.cro\"\n\t\tval pwd1 = \"1234\"\n\t\tval pwd2 = \"1234\"\n\t\tval isAccepted = false\n\t\tval isSeller = false\n\t\tauthViewModel.signUpSubmitData(name, mobile, email, pwd1, pwd2, isAccepted, isSeller)\n\t\tval result = authViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(SignUpViewErrors.ERR_NOT_ACC))\n\t\tassertThat(authViewModel.userData.value, `is`(nullValue()))\n\t}\n\n\t@Test\n\tfun signUpSubmitData_pwdNotEq_returnsPwdError() {\n\t\tval name = \"uigbivs ihgfdsg\"\n\t\tval mobile = \"9988665555\"\n\t\tval email = \"owhfoi@oihw.cro\"\n\t\tval pwd1 = \"12345\"\n\t\tval pwd2 = \"1234\"\n\t\tval isAccepted = false\n\t\tval isSeller = false\n\t\tauthViewModel.signUpSubmitData(name, mobile, email, pwd1, pwd2, isAccepted, isSeller)\n\t\tval result = authViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(SignUpViewErrors.ERR_PWD12NS))\n\t\tassertThat(authViewModel.userData.value, `is`(nullValue()))\n\t}\n\n\t@Test\n\tfun signUpSubmitData_invalidEmail_returnsEmailError() {\n\t\tval name = \"uigbivs ihgfdsg\"\n\t\tval mobile = \"9988665555\"\n\t\tval email = \"owhfoi@oihwo\"\n\t\tval pwd1 = \"1234\"\n\t\tval pwd2 = \"1234\"\n\t\tval isAccepted = true\n\t\tval isSeller = false\n\t\tauthViewModel.signUpSubmitData(name, mobile, email, pwd1, pwd2, isAccepted, isSeller)\n\t\tval result = authViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(SignUpViewErrors.ERR_EMAIL))\n\t\tassertThat(authViewModel.userData.value, `is`(nullValue()))\n\t}\n\n\t@Test\n\tfun signUpSubmitData_invalidMobile_returnsMobError() {\n\t\tval name = \"uigbivs ihgfdsg\"\n\t\tval mobile = \"9988665fng55\"\n\t\tval email = \"owhfoi@oihw.coo\"\n\t\tval pwd1 = \"1234\"\n\t\tval pwd2 = \"1234\"\n\t\tval isAccepted = true\n\t\tval isSeller = false\n\t\tauthViewModel.signUpSubmitData(name, mobile, email, pwd1, pwd2, isAccepted, isSeller)\n\t\tval result = authViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(SignUpViewErrors.ERR_MOBILE))\n\t\tassertThat(authViewModel.userData.value, `is`(nullValue()))\n\t}\n\n\t@Test\n\tfun signUpSubmitData_invalidEmailMobile_returnsEmailMobError() {\n\t\tval name = \"uigbivs ihgfdsg\"\n\t\tval mobile = \"9988665fng55\"\n\t\tval email = \"owhfoi@oihwoo\"\n\t\tval pwd1 = \"1234\"\n\t\tval pwd2 = \"1234\"\n\t\tval isAccepted = true\n\t\tval isSeller = false\n\t\tauthViewModel.signUpSubmitData(name, mobile, email, pwd1, pwd2, isAccepted, isSeller)\n\t\tval result = authViewModel.errorStatus.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(SignUpViewErrors.ERR_EMAIL_MOBILE))\n\t\tassertThat(authViewModel.userData.value, `is`(nullValue()))\n\t}\n\n\t@Test\n\tfun signUpSubmitData_validData_returnsNoError() {\n\t\tval name = \"   uigbivs ihgfdsg\"\n\t\tval mobile = \"   9988665755\"\n\t\tval email = \"owhfoi@oihwoo.cwdo    \"\n\t\tval pwd1 = \"1234\"\n\t\tval pwd2 = \"1234\"\n\t\tval isAccepted = true\n\t\tval isSeller = false\n\t\tauthViewModel.signUpSubmitData(name, mobile, email, pwd1, pwd2, isAccepted, isSeller)\n\t\tval result = authViewModel.errorStatus.getOrAwaitValue()\n\t\tval dataRes = authViewModel.userData.getOrAwaitValue()\n\t\tassertThat(result, `is`(SignUpViewErrors.NONE))\n\t\tassertThat(dataRes, `is`(notNullValue()))\n\t\tassertThat(dataRes.name, `is`(\"uigbivs ihgfdsg\"))\n\t}\n\n\t@Test\n\tfun loginSubmitData_noData_returnsEmptyError() {\n\t\tval mobile = \"\"\n\t\tval pwd = \"\"\n\t\tauthViewModel.loginSubmitData(mobile, pwd)\n\t\tval result = authViewModel.errorStatusLoginFragment.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(LoginViewErrors.ERR_EMPTY))\n\t}\n\n\t@Test\n\tfun loginSubmitData_invalidMobile_returnsMobileError() {\n\t\tval mobile = \"9fwd988556699\"\n\t\tval pwd = \"123\"\n\t\tauthViewModel.loginSubmitData(mobile, pwd)\n\t\tval result = authViewModel.errorStatusLoginFragment.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(LoginViewErrors.ERR_MOBILE))\n\t}\n\n\t@Test\n\tfun loginSubmitData_validData_returnsNoError() {\n\t\tval mobile = \"9988556699\"\n\t\tval pwd = \"123\"\n\t\tauthViewModel.loginSubmitData(mobile, pwd)\n\t\tval result = authViewModel.errorStatusLoginFragment.getOrAwaitValue()\n\n\t\tassertThat(result, `is`(LoginViewErrors.NONE))\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/viewModels/HomeViewModelTest.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.espresso.matcher.ViewMatchers.assertThat\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport com.vishalgaur.shoppingapp.ServiceLocator\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.source.FakeAuthRepository\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepoInterface\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.getOrAwaitValue\nimport org.hamcrest.Matchers.`is`\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\nclass HomeViewModelTest {\n\tprivate lateinit var homeViewModel: HomeViewModel\n\tprivate lateinit var authRepository: AuthRepoInterface\n\n\t@get:Rule\n\tvar instantTaskExecutorRule = InstantTaskExecutorRule()\n\n\t@Before\n\tfun setUp() {\n\t\tval sessionManager = ShoppingAppSessionManager(ApplicationProvider.getApplicationContext())\n\t\tauthRepository = FakeAuthRepository(sessionManager)\n\t\tServiceLocator.authRepository = authRepository\n\t\thomeViewModel = HomeViewModel(ApplicationProvider.getApplicationContext())\n\t}\n\n\t@After\n\tfun cleanUp() {\n\t\tServiceLocator.resetRepository()\n\t}\n\n    @Test\n    fun setDataLoaded_setsValue() {\n        homeViewModel.setDataLoaded()\n        val result = homeViewModel.storeDataStatus.getOrAwaitValue()\n        assertThat(result, `is`(StoreDataStatus.DONE))\n    }\n\n\t@Test\n\tfun filterProducts_All() {\n\t\thomeViewModel.filterProducts(\"All\")\n\t\tval result =  homeViewModel.filterCategory.getOrAwaitValue()\n\t\tassertThat(result, `is`(\"All\"))\n\t}\n\n\t@Test\n\tfun filterProducts_Shoes() {\n\t\thomeViewModel.filterProducts(\"Shoes\")\n\t\tval result =  homeViewModel.filterCategory.getOrAwaitValue()\n\t\tassertThat(result, `is`(\"Shoes\"))\n\t}\n\n\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/viewModels/OrderViewModelTest.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.espresso.matcher.ViewMatchers.assertThat\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport com.vishalgaur.shoppingapp.ServiceLocator\nimport com.vishalgaur.shoppingapp.ShoppingApplication\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.FakeAuthRepository\nimport com.vishalgaur.shoppingapp.data.source.FakeProductsRepository\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepoInterface\nimport com.vishalgaur.shoppingapp.data.source.repository.ProductsRepoInterface\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.getOrAwaitValue\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.runBlocking\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.hamcrest.Matchers.*\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\n@ExperimentalCoroutinesApi\nclass OrderViewModelTest {\n\n\tprivate lateinit var orderViewModel: OrderViewModel\n\tprivate lateinit var productsRepository: ProductsRepoInterface\n\tprivate lateinit var authRepository: AuthRepoInterface\n\n\tval user = UserData(\n\t\t\"sdjm43892yfh948ehod\",\n\t\t\"Vishal\",\n\t\t\"+919999988888\",\n\t\t\"vishal@somemail.com\",\n\t\t\"dh94328hd\",\n\t\tArrayList(),\n\t\tArrayList(),\n\t\tArrayList()\n\t)\n\n\tval address = UserData.Address(\n\t\t\"add-id-121\",\n\t\t\"adg\",\n\t\t\"shgd\",\n\t\t\"IN\",\n\t\t\"sfhg45eyh\",\n\t\t\"\",\n\t\t\"kanpuit\",\n\t\t\"up\",\n\t\t\"309890\",\n\t\t\"9999988558\"\n\t)\n\n\tval item1 = UserData.CartItem(\n\t\t\"item2123\",\n\t\t\"pro123\",\n\t\t\"owner23\",\n\t\t1,\n\t\t\"Red\",\n\t\t10\n\t)\n\n\tval item2 = UserData.CartItem(\n\t\t\"item2123456347\",\n\t\t\"pro12345\",\n\t\t\"owner23\",\n\t\t1,\n\t\t\"Blue\",\n\t\t9\n\t)\n\n\t@get:Rule\n\tvar instantTaskExecutorRule = InstantTaskExecutorRule()\n\n\t@Before\n\tfun setUp() {\n\t\tproductsRepository = FakeProductsRepository()\n\t\tval context = ApplicationProvider.getApplicationContext<ShoppingApplication>()\n\t\tval sessionManager = ShoppingAppSessionManager(context)\n\t\tauthRepository = FakeAuthRepository(sessionManager)\n\t\tauthRepository.login(user, true)\n\t\tServiceLocator.productsRepository = productsRepository\n\t\tServiceLocator.authRepository = authRepository\n\n\t\torderViewModel = OrderViewModel(context)\n\t}\n\n\t@After\n\tfun cleanUp() = runBlockingTest {\n\t\tServiceLocator.resetRepository()\n\t}\n\n\t@Test\n\tfun getCartItems_loadsData() = runBlocking {\n\t\torderViewModel.getCartItems()\n\t\tdelay(200)\n\t\tval result = orderViewModel.dataStatus.getOrAwaitValue()\n\t\tassertThat(result, `is`(StoreDataStatus.DONE))\n\t}\n\n\t@Test\n\tfun getAddresses_noAddress_loadsData() = runBlocking {\n\t\torderViewModel.getUserAddresses()\n\t\tdelay(200)\n\t\tval result = orderViewModel.dataStatus.getOrAwaitValue()\n\t\tassertThat(result, `is`(StoreDataStatus.DONE))\n\t\tval resAdd = orderViewModel.userAddresses.getOrAwaitValue()\n\t\tassertThat(resAdd.size, `is`(0))\n\t}\n\n\t@Test\n\tfun getAddresses_hasAddress_loadsData() = runBlocking {\n\t\tauthRepository.insertAddress(address, user.userId)\n\t\tdelay(100)\n\t\torderViewModel.getUserAddresses()\n\t\tdelay(100)\n\t\tval result = orderViewModel.dataStatus.getOrAwaitValue()\n\t\tassertThat(result, `is`(StoreDataStatus.DONE))\n\t\tval resAdd = orderViewModel.userAddresses.getOrAwaitValue()\n\t\tassertThat(resAdd.size, `is`(1))\n\t}\n\n\t@Test\n\tfun deleteAddress_deletesAddress() = runBlocking{\n\t\tauthRepository.insertAddress(address, user.userId)\n\t\tdelay(100)\n\t\torderViewModel.getUserAddresses()\n\t\tdelay(100)\n\t\tval resAdd = orderViewModel.userAddresses.getOrAwaitValue()\n\t\tassertThat(resAdd.size, `is`(1))\n\n\t\torderViewModel.deleteAddress(address.addressId)\n\t\tdelay(100)\n\t\tval resAdd2 = orderViewModel.userAddresses.getOrAwaitValue()\n\t\tassertThat(resAdd2.size, `is`(0))\n\t}\n\n\t@Test\n\tfun getItemsPriceTotal_returnsTotal() {\n\t\trunBlocking {\n\t\t\tauthRepository.insertCartItemByUserId(item1, user.userId)\n\t\t\tdelay(100)\n\t\t\tval result = orderViewModel.getItemsPriceTotal()\n\t\t\tassertThat(result, `is`(0.0))\n\t\t}\n\t}\n\n\t@Test\n\tfun toggleLike() {\n\t\trunBlocking {\n\t\t\tval res1 = orderViewModel.userLikes.getOrAwaitValue()\n\t\t\torderViewModel.toggleLikeProduct(\"pro-if2r3\")\n\t\t\tdelay(100)\n\t\t\tval res2 = orderViewModel.userLikes.getOrAwaitValue()\n\t\t\tassertThat(res1.size, not(res2.size))\n\t\t}\n\t}\n\n\t@Test\n\tfun setQuantity_setsQuantity() = runBlocking {\n\t\tauthRepository.insertCartItemByUserId(item1, user.userId)\n\t\tdelay(100)\n\t\tval res1 = orderViewModel.cartItems.getOrAwaitValue().find { it.itemId == item1.itemId }\n\t\tval size1 = res1?.quantity ?: 0\n\t\torderViewModel.setQuantityOfItem(item1.itemId, 1)\n\t\tdelay(100)\n\t\tval res2 = orderViewModel.cartItems.getOrAwaitValue().find { it.itemId == item1.itemId }\n\t\tval size2 = res2?.quantity ?: 0\n\n\t\tassertThat(size1, `is`(1))\n\t\tassertThat(size2, `is`(2))\n\t}\n\n\t@Test\n\tfun deleteItemFromCart_deletesItem() = runBlocking {\n\t\tauthRepository.insertCartItemByUserId(item1, user.userId)\n\t\tdelay(100)\n\t\tval res1 = orderViewModel.cartItems.getOrAwaitValue().find { it.itemId == item1.itemId }\n\t\tassertThat(res1, `is`(notNullValue()))\n\n\t\torderViewModel.deleteItemFromCart(item1.itemId)\n\t\tdelay(100)\n\t\tval res2 = orderViewModel.cartItems.getOrAwaitValue().find { it.itemId == item1.itemId }\n\t\tassertThat(res2, `is`(nullValue()))\n\t}\n}"
  },
  {
    "path": "app/src/androidTest/java/com/vishalgaur/shoppingapp/viewModels/ProductViewModelTest.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.espresso.matcher.ViewMatchers.assertThat\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport com.vishalgaur.shoppingapp.ServiceLocator\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.FakeAuthRepository\nimport com.vishalgaur.shoppingapp.data.source.FakeProductsRepository\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepoInterface\nimport com.vishalgaur.shoppingapp.data.source.repository.ProductsRepoInterface\nimport com.vishalgaur.shoppingapp.getOrAwaitValue\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.runBlocking\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.hamcrest.Matchers.`is`\nimport org.hamcrest.Matchers.not\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\n@RunWith(AndroidJUnit4::class)\n@ExperimentalCoroutinesApi\nclass ProductViewModelTest {\n\tprivate lateinit var productViewModel: ProductViewModel\n\tprivate lateinit var productId: String\n\tprivate lateinit var productsRepository: ProductsRepoInterface\n\tprivate lateinit var authRepository: AuthRepoInterface\n\n\tval user = UserData(\n\t\t\"sdjm43892yfh948ehod\",\n\t\t\"Vishal\",\n\t\t\"+919999988888\",\n\t\t\"vishal@somemail.com\",\n\t\t\"dh94328hd\",\n\t\tArrayList(),\n\t\tArrayList(),\n\t\tArrayList()\n\t)\n\n\t@get:Rule\n\tvar instantTaskExecutorRule = InstantTaskExecutorRule()\n\n\t@Before\n\tfun setUp() {\n\t\tproductsRepository = FakeProductsRepository()\n\t\tval sessionManager = ShoppingAppSessionManager(ApplicationProvider.getApplicationContext())\n\t\tauthRepository = FakeAuthRepository(sessionManager)\n\t\tauthRepository.login(user, true)\n\t\tServiceLocator.productsRepository = productsRepository\n\t\tServiceLocator.authRepository = authRepository\n\t\tproductId = \"pro-shoes-wofwopjf-1\"\n\t\tproductViewModel = ProductViewModel(productId, ApplicationProvider.getApplicationContext())\n\t}\n\n\t@After\n\tfun cleanUp() = runBlockingTest {\n\t\tServiceLocator.resetRepository()\n\t}\n\n\t@Test\n\tfun toggleLikeProduct_false_true() {\n\t\tval result1 = productViewModel.isLiked.value\n\t\trunBlocking {\n\t\t\tproductViewModel.toggleLikeProduct()\n\t\t\tdelay(1000)\n\t\t\tval result2 = productViewModel.isLiked.getOrAwaitValue()\n\t\t\tassertThat(result1, not(result2))\n\t\t}\n\n\t}\n}"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.vishalgaur.shoppingapp\">\n\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <application\n        android:name=\".ShoppingApplication\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/Theme.ShoppingApp\">\n\n        <activity\n            android:name=\".ui.LaunchActivity\"\n            android:exported=\"true\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n\n        <activity\n            android:name=\".ui.loginSignup.LoginSignupActivity\" />\n\n        <activity\n            android:name=\".ui.home.MainActivity\"\n            android:exported=\"true\"\n            android:launchMode=\"singleTop\" />\n\n        <activity\n            android:name=\".ui.loginSignup.OtpActivity\" />\n\n        <meta-data\n            android:name=\"preloaded_fonts\"\n            android:resource=\"@array/preloaded_fonts\" />\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ServiceLocator.kt",
    "content": "package com.vishalgaur.shoppingapp\n\nimport android.content.Context\nimport androidx.annotation.VisibleForTesting\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.source.ProductDataSource\nimport com.vishalgaur.shoppingapp.data.source.UserDataSource\nimport com.vishalgaur.shoppingapp.data.source.local.ProductsLocalDataSource\nimport com.vishalgaur.shoppingapp.data.source.local.ShoppingAppDatabase\nimport com.vishalgaur.shoppingapp.data.source.local.UserLocalDataSource\nimport com.vishalgaur.shoppingapp.data.source.remote.AuthRemoteDataSource\nimport com.vishalgaur.shoppingapp.data.source.remote.ProductsRemoteDataSource\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepoInterface\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepository\nimport com.vishalgaur.shoppingapp.data.source.repository.ProductsRepoInterface\nimport com.vishalgaur.shoppingapp.data.source.repository.ProductsRepository\n\nobject ServiceLocator {\n\tprivate var database: ShoppingAppDatabase? = null\n\tprivate val lock = Any()\n\n\t@Volatile\n\tvar authRepository: AuthRepoInterface? = null\n\t\t@VisibleForTesting set\n\n\t@Volatile\n\tvar productsRepository: ProductsRepoInterface? = null\n\t\t@VisibleForTesting set\n\n\tfun provideAuthRepository(context: Context): AuthRepoInterface {\n\t\tsynchronized(this) {\n\t\t\treturn authRepository ?: createAuthRepository(context)\n\t\t}\n\t}\n\n\tfun provideProductsRepository(context: Context): ProductsRepoInterface {\n\t\tsynchronized(this) {\n\t\t\treturn productsRepository ?: createProductsRepository(context)\n\t\t}\n\t}\n\n\t@VisibleForTesting\n\tfun resetRepository() {\n\t\tsynchronized(lock) {\n\t\t\tdatabase?.apply {\n\t\t\t\tclearAllTables()\n\t\t\t\tclose()\n\t\t\t}\n\t\t\tdatabase = null\n\t\t\tauthRepository = null\n\t\t}\n\t}\n\n\tprivate fun createProductsRepository(context: Context): ProductsRepoInterface {\n\t\tval newRepo =\n\t\t\tProductsRepository(ProductsRemoteDataSource(), createProductsLocalDataSource(context))\n\t\tproductsRepository = newRepo\n\t\treturn newRepo\n\t}\n\n\tprivate fun createAuthRepository(context: Context): AuthRepoInterface {\n\t\tval appSession = ShoppingAppSessionManager(context.applicationContext)\n\t\tval newRepo =\n\t\t\tAuthRepository(createUserLocalDataSource(context), AuthRemoteDataSource(), appSession)\n\t\tauthRepository = newRepo\n\t\treturn newRepo\n\t}\n\n\tprivate fun createProductsLocalDataSource(context: Context): ProductDataSource {\n\t\tval database = database ?: ShoppingAppDatabase.getInstance(context.applicationContext)\n\t\treturn ProductsLocalDataSource(database.productsDao())\n\t}\n\n\tprivate fun createUserLocalDataSource(context: Context): UserDataSource {\n\t\tval database = database ?: ShoppingAppDatabase.getInstance(context.applicationContext)\n\t\treturn UserLocalDataSource(database.userDao())\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ShoppingApplication.kt",
    "content": "package com.vishalgaur.shoppingapp\n\nimport android.app.Application\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepoInterface\nimport com.vishalgaur.shoppingapp.data.source.repository.ProductsRepoInterface\n\nclass ShoppingApplication : Application() {\n\tval authRepository: AuthRepoInterface\n\t\tget() = ServiceLocator.provideAuthRepository(this)\n\n\tval productsRepository: ProductsRepoInterface\n\t\tget() = ServiceLocator.provideProductsRepository(this)\n\n\toverride fun onCreate() {\n\t\tsuper.onCreate()\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/Utils.kt",
    "content": "package com.vishalgaur.shoppingapp\n\nimport java.util.*\nimport java.util.regex.Pattern\nimport kotlin.math.roundToInt\n\nconst val MOB_ERROR_TEXT = \"Enter valid mobile number!\"\nconst val EMAIL_ERROR_TEXT = \"Enter valid email address!\"\nconst val ERR_INIT = \"ERROR\"\nconst val ERR_EMAIL = \"_EMAIL\"\nconst val ERR_MOBILE = \"_MOBILE\"\nconst val ERR_UPLOAD = \"UploadErrorException\"\n\ninternal fun isEmailValid(email: String): Boolean {\n\tval EMAIL_PATTERN = Pattern.compile(\n\t\t\"\\\\s*[a-zA-Z0-9\\\\+\\\\.\\\\_\\\\%\\\\-\\\\+]{1,256}\" +\n\t\t\t\t\"\\\\@\" +\n\t\t\t\t\"[a-zA-Z0-9][a-zA-Z0-9\\\\-]{0,64}\" +\n\t\t\t\t\"(\" +\n\t\t\t\t\"\\\\.\" +\n\t\t\t\t\"[a-zA-Z0-9][a-zA-Z0-9\\\\-]{0,25}\" +\n\t\t\t\t\")+\\\\s*\"\n\t)\n\treturn if (email.isEmpty()) {\n\t\tfalse\n\t} else {\n\t\tEMAIL_PATTERN.matcher(email).matches()\n\t}\n}\n\ninternal fun isPhoneValid(phone: String): Boolean {\n\tval PHONE_PATTERN = Pattern.compile(\"^\\\\s*[6-9]\\\\d{9}\\\\s*\\$\")\n\treturn if (phone.isEmpty()) {\n\t\tfalse\n\t} else {\n\t\tPHONE_PATTERN.matcher(phone).matches()\n\t}\n}\n\ninternal fun isZipCodeValid(zipCode: String): Boolean {\n\tval ZIPCODE_PATTERN = Pattern.compile(\"^\\\\s*[1-9]\\\\d{5}\\\\s*\\$\")\n\treturn if (zipCode.isEmpty()) {\n\t\tfalse\n\t} else {\n\t\tZIPCODE_PATTERN.matcher(zipCode).matches()\n\t}\n}\n\ninternal fun getRandomString(length: Int, uNum: String, endLength: Int): String {\n\tval allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')\n\tfun getStr(l: Int): String = (1..l).map { allowedChars.random() }.joinToString(\"\")\n\treturn getStr(length) + uNum + getStr(endLength)\n}\n\ninternal fun getProductId(ownerId: String, proCategory: String): String {\n\tval uniqueId = UUID.randomUUID().toString()\n\treturn \"pro-$proCategory-$ownerId-$uniqueId\"\n}\n\ninternal fun getOfferPercentage(costPrice: Double, sellingPrice: Double): Int {\n\tif (costPrice == 0.0 || sellingPrice == 0.0 || costPrice <= sellingPrice)\n\t\treturn 0\n\tval off = ((costPrice - sellingPrice) * 100) / costPrice\n\treturn off.roundToInt()\n}\n\ninternal fun getAddressId(userId: String): String {\n\tval uniqueId = UUID.randomUUID().toString()\n\treturn \"$userId-$uniqueId\"\n}\n\ninternal fun shouldBypassOTPValidation() : Boolean {\n\treturn false\n}\n"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/Product.kt",
    "content": "package com.vishalgaur.shoppingapp.data\n\nimport android.os.Parcelable\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey\nimport kotlinx.parcelize.Parcelize\n\n@Parcelize\n@Entity(tableName = \"products\")\ndata class Product @JvmOverloads constructor(\n\t@PrimaryKey\n\tvar productId: String = \"\",\n\tvar name: String = \"\",\n\tvar owner: String = \"\",\n\tvar description: String = \"\",\n\tvar category: String = \"\",\n\tvar price: Double = 0.0,\n\tvar mrp: Double = 0.0,\n\tvar availableSizes: List<Int> = ArrayList(),\n\tvar availableColors: List<String> = ArrayList(),\n\tvar images: List<String> = ArrayList(),\n\tvar rating: Double = 0.0\n) : Parcelable {\n\tfun toHashMap(): HashMap<String, Any> {\n\t\treturn hashMapOf(\n\t\t\t\"productId\" to productId,\n\t\t\t\"name\" to name,\n\t\t\t\"owner\" to owner,\n\t\t\t\"description\" to description,\n\t\t\t\"category\" to category,\n\t\t\t\"price\" to price,\n\t\t\t\"mrp\" to mrp,\n\t\t\t\"availableSizes\" to availableSizes,\n\t\t\t\"availableColors\" to availableColors,\n\t\t\t\"images\" to images,\n\t\t\t\"rating\" to rating\n\t\t)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/Result.kt",
    "content": "package com.vishalgaur.shoppingapp.data\n\nimport com.vishalgaur.shoppingapp.data.Result.Success\n\n/**\n * A generic class that holds a value with its loading status.\n * @param <T>\n */\nsealed class Result<out R> {\n\n\tdata class Success<out T>(val data: T) : Result<T>()\n\tdata class Error(val exception: Exception) : Result<Nothing>()\n\tobject Loading : Result<Nothing>()\n\n\toverride fun toString(): String {\n\t\treturn when (this) {\n\t\t\tis Success<*> -> \"Success[data=$data]\"\n\t\t\tis Error -> \"Error[exception=$exception]\"\n\t\t\tLoading -> \"Loading\"\n\t\t}\n\t}\n}\n\n/**\n * `true` if [Result] is of type [Success] & holds non-null [Success.data].\n */\nval Result<*>.succeeded\n\tget() = this is Success && data != null"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/ShoppingAppSessionManager.kt",
    "content": "package com.vishalgaur.shoppingapp.data\n\nimport android.content.Context\nimport android.content.SharedPreferences\n\nclass ShoppingAppSessionManager(context: Context) {\n\n\tvar userSession: SharedPreferences =\n\t\tcontext.getSharedPreferences(\"userSessionData\", Context.MODE_PRIVATE)\n\tvar editor: SharedPreferences.Editor = userSession.edit()\n\n\n\tfun createLoginSession(\n\t\tid: String,\n\t\tname: String,\n\t\tmobile: String,\n\t\tisRemOn: Boolean,\n\t\tisSeller: Boolean\n\t) {\n\t\teditor.putBoolean(IS_LOGIN, true)\n\t\teditor.putString(KEY_ID, id)\n\t\teditor.putString(KEY_NAME, name)\n\t\teditor.putString(KEY_MOBILE, mobile)\n\t\teditor.putBoolean(KEY_REMEMBER_ME, isRemOn)\n\t\teditor.putBoolean(KEY_IS_SELLER, isSeller)\n\n\t\teditor.commit()\n\t}\n\n\tfun isUserSeller(): Boolean = userSession.getBoolean(KEY_IS_SELLER, false)\n\n\tfun isRememberMeOn(): Boolean = userSession.getBoolean(KEY_REMEMBER_ME, false)\n\n\tfun getPhoneNumber(): String? = userSession.getString(KEY_MOBILE, null)\n\n\tfun getUserDataFromSession(): HashMap<String, String?> {\n\t\treturn hashMapOf(\n\t\t\tKEY_ID to userSession.getString(KEY_ID, null),\n\t\t\tKEY_NAME to userSession.getString(KEY_NAME, null),\n\t\t\tKEY_MOBILE to userSession.getString(KEY_MOBILE, null)\n\t\t)\n\t}\n\n\tfun getUserIdFromSession(): String? = userSession.getString(KEY_ID, null)\n\n\tfun isLoggedIn(): Boolean = userSession.getBoolean(IS_LOGIN, false)\n\n\tfun logoutFromSession() {\n\t\teditor.clear()\n\t\teditor.commit()\n\t}\n\n\tcompanion object {\n\t\tprivate const val IS_LOGIN = \"isLoggedIn\"\n\t\tprivate const val KEY_NAME = \"userName\"\n\t\tprivate const val KEY_MOBILE = \"userMobile\"\n\t\tprivate const val KEY_ID = \"userId\"\n\t\tprivate const val KEY_REMEMBER_ME = \"isRemOn\"\n\t\tprivate const val KEY_IS_SELLER = \"isSeller\"\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/UserData.kt",
    "content": "package com.vishalgaur.shoppingapp.data\n\nimport android.os.Parcelable\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey\nimport androidx.room.TypeConverters\nimport com.vishalgaur.shoppingapp.data.utils.ObjectListTypeConvertor\nimport com.vishalgaur.shoppingapp.data.utils.OrderStatus\nimport com.vishalgaur.shoppingapp.data.utils.UserType\nimport kotlinx.parcelize.Parcelize\nimport java.util.*\nimport kotlin.collections.ArrayList\n\n@Parcelize\n@Entity(tableName = \"users\")\ndata class UserData(\n\t@PrimaryKey\n\tvar userId: String = \"\",\n\tvar name: String = \"\",\n\tvar mobile: String = \"\",\n\tvar email: String = \"\",\n\tvar password: String = \"\",\n\tvar likes: List<String> = ArrayList(),\n\t@TypeConverters(ObjectListTypeConvertor::class)\n\tvar addresses: List<Address> = ArrayList(),\n\t@TypeConverters(ObjectListTypeConvertor::class)\n\tvar cart: List<CartItem> = ArrayList(),\n\t@TypeConverters(ObjectListTypeConvertor::class)\n\tvar orders: List<OrderItem> = ArrayList(),\n\tvar userType: String = UserType.CUSTOMER.name\n) : Parcelable {\n\tfun toHashMap(): HashMap<String, Any> {\n\t\treturn hashMapOf(\n\t\t\t\"userId\" to userId,\n\t\t\t\"name\" to name,\n\t\t\t\"email\" to email,\n\t\t\t\"mobile\" to mobile,\n\t\t\t\"password\" to password,\n\t\t\t\"likes\" to likes,\n\t\t\t\"addresses\" to addresses.map { it.toHashMap() },\n\t\t\t\"userType\" to userType\n\t\t)\n\t}\n\n\t@Parcelize\n\tdata class OrderItem(\n\t\tvar orderId: String = \"\",\n\t\tvar customerId: String = \"\",\n\t\tvar items: List<CartItem> = ArrayList(),\n\t\tvar itemsPrices: Map<String, Double> = mapOf(),\n\t\tvar deliveryAddress: Address = Address(),\n\t\tvar shippingCharges: Double = 0.0,\n\t\tvar paymentMethod: String = \"\",\n\t\tvar orderDate: Date = Date(),\n\t\tvar status: String = OrderStatus.CONFIRMED.name\n\t) : Parcelable {\n\t\tfun toHashMap(): HashMap<String, Any> {\n\t\t\treturn hashMapOf(\n\t\t\t\t\"orderId\" to orderId,\n\t\t\t\t\"customerId\" to customerId,\n\t\t\t\t\"items\" to items.map { it.toHashMap() },\n\t\t\t\t\"itemsPrices\" to itemsPrices,\n\t\t\t\t\"deliveryAddress\" to deliveryAddress.toHashMap(),\n\t\t\t\t\"shippingCharges\" to shippingCharges,\n\t\t\t\t\"paymentMethod\" to paymentMethod,\n\t\t\t\t\"orderDate\" to orderDate,\n\t\t\t\t\"status\" to status\n\t\t\t)\n\t\t}\n\t}\n\n\t@Parcelize\n\tdata class Address(\n\t\tvar addressId: String = \"\",\n\t\tvar fName: String = \"\",\n\t\tvar lName: String = \"\",\n\t\tvar countryISOCode: String = \"\",\n\t\tvar streetAddress: String = \"\",\n\t\tvar streetAddress2: String = \"\",\n\t\tvar city: String = \"\",\n\t\tvar state: String = \"\",\n\t\tvar zipCode: String = \"\",\n\t\tvar phoneNumber: String = \"\"\n\t) : Parcelable {\n\t\tfun toHashMap(): HashMap<String, String> {\n\t\t\treturn hashMapOf(\n\t\t\t\t\"addressId\" to addressId,\n\t\t\t\t\"fName\" to fName,\n\t\t\t\t\"lName\" to lName,\n\t\t\t\t\"countryISOCode\" to countryISOCode,\n\t\t\t\t\"streetAddress\" to streetAddress,\n\t\t\t\t\"streetAddress2\" to streetAddress2,\n\t\t\t\t\"city\" to city,\n\t\t\t\t\"state\" to state,\n\t\t\t\t\"zipCode\" to zipCode,\n\t\t\t\t\"phoneNumber\" to phoneNumber\n\t\t\t)\n\t\t}\n\t}\n\n\t@Parcelize\n\tdata class CartItem(\n\t\tvar itemId: String = \"\",\n\t\tvar productId: String = \"\",\n\t\tvar ownerId: String = \"\",\n\t\tvar quantity: Int = 0,\n\t\tvar color: String?,\n\t\tvar size: Int?\n\t) : Parcelable {\n\t\tconstructor() : this(\"\", \"\", \"\", 0, \"NA\", -1)\n\n\t\tfun toHashMap(): HashMap<String, Any> {\n\t\t\tval hashMap = hashMapOf<String, Any>()\n\t\t\thashMap[\"itemId\"] = itemId\n\t\t\thashMap[\"productId\"] = productId\n\t\t\thashMap[\"ownerId\"] = ownerId\n\t\t\thashMap[\"quantity\"] = quantity\n\t\t\tif (color != null)\n\t\t\t\thashMap[\"color\"] = color!!\n\t\t\tif (size != null)\n\t\t\t\thashMap[\"size\"] = size!!\n\t\t\treturn hashMap\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/ProductDataSource.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source\n\nimport android.net.Uri\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result\n\ninterface ProductDataSource {\n\n\tfun observeProducts(): LiveData<Result<List<Product>>?>\n\n\tsuspend fun getAllProducts(): Result<List<Product>>\n\n\tsuspend fun refreshProducts() {}\n\n\tsuspend fun getProductById(productId: String): Result<Product>\n\n\tsuspend fun insertProduct(newProduct: Product)\n\n\tsuspend fun updateProduct(proData: Product)\n\n\tfun observeProductsByOwner(ownerId: String): LiveData<Result<List<Product>>?> {\n\t\treturn MutableLiveData()\n\t}\n\n\tsuspend fun getAllProductsByOwner(ownerId: String): Result<List<Product>> {\n\t\treturn Result.Success(emptyList())\n\t}\n\n\tsuspend fun uploadImage(uri: Uri, fileName: String): Uri? {\n\t\treturn null\n\t}\n\n\tfun revertUpload(fileName: String) {}\n\tfun deleteImage(imgUrl: String) {}\n\tsuspend fun deleteProduct(productId: String)\n\tsuspend fun deleteAllProducts() {}\n\tsuspend fun insertMultipleProducts(data: List<Product>) {}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/UserDataSource.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source\n\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.EmailMobileData\n\ninterface UserDataSource {\n\tsuspend fun addUser(userData: UserData)\n\n\tsuspend fun getUserById(userId: String): Result<UserData?>\n\n\tfun updateEmailsAndMobiles(email: String, mobile: String) {}\n\n\tsuspend fun getEmailsAndMobiles(): EmailMobileData? {\n\t\treturn null\n\t}\n\n\tsuspend fun getUserByMobileAndPassword(\n\t\tmobile: String,\n\t\tpassword: String\n\t): MutableList<UserData> {\n\t\treturn mutableListOf()\n\t}\n\n\tsuspend fun likeProduct(productId: String, userId: String) {}\n\n\tsuspend fun dislikeProduct(productId: String, userId: String) {}\n\n\tsuspend fun insertAddress(newAddress: UserData.Address, userId: String) {}\n\n\tsuspend fun updateAddress(newAddress: UserData.Address, userId: String) {}\n\n\tsuspend fun deleteAddress(addressId: String, userId: String) {}\n\n\tsuspend fun insertCartItem(newItem: UserData.CartItem, userId: String) {}\n\n\tsuspend fun updateCartItem(item: UserData.CartItem, userId: String) {}\n\n\tsuspend fun deleteCartItem(itemId: String, userId: String) {}\n\n\tsuspend fun placeOrder(newOrder: UserData.OrderItem, userId: String) {}\n\n\tsuspend fun setStatusOfOrderByUserId(orderId: String, userId: String, status: String) {}\n\n\tsuspend fun clearUser() {}\n\n\tsuspend fun getUserByMobile(phoneNumber: String): UserData? {\n\t\treturn null\n\t}\n\n\tsuspend fun getOrdersByUserId(userId: String): Result<List<UserData.OrderItem>?>\n\n\tsuspend fun getAddressesByUserId(userId: String): Result<List<UserData.Address>?>\n\n\tsuspend fun getLikesByUserId(userId: String): Result<List<String>?>\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/local/ProductsDao.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.local\n\nimport androidx.lifecycle.LiveData\nimport androidx.room.Dao\nimport androidx.room.Insert\nimport androidx.room.OnConflictStrategy\nimport androidx.room.Query\nimport com.vishalgaur.shoppingapp.data.Product\n\n@Dao\ninterface ProductsDao {\n\t@Insert(onConflict = OnConflictStrategy.REPLACE)\n\tsuspend fun insert(product: Product)\n\n\t@Insert(onConflict = OnConflictStrategy.REPLACE)\n\tsuspend fun insertListOfProducts(products: List<Product>)\n\n\t@Query(\"SELECT * FROM products\")\n\tsuspend fun getAllProducts(): List<Product>\n\n\t@Query(\"SELECT * FROM products\")\n\tfun observeProducts(): LiveData<List<Product>>\n\n\t@Query(\"SELECT * FROM products WHERE owner = :ownerId\")\n\tfun observeProductsByOwner(ownerId: String): LiveData<List<Product>>\n\n\t@Query(\"SELECT * FROM products WHERE productId = :proId\")\n\tsuspend fun getProductById(proId: String): Product?\n\n\t@Query(\"SELECT * FROM products WHERE owner = :ownerId\")\n\tsuspend fun getProductsByOwnerId(ownerId: String): List<Product>\n\n\t@Query(\"DELETE FROM products WHERE productId = :proId\")\n\tsuspend fun deleteProductById(proId: String): Int\n\n\t@Query(\"DELETE FROM products\")\n\tsuspend fun deleteAllProducts()\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/local/ProductsLocalDataSource.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.local\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.Transformations\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.Result.*\nimport com.vishalgaur.shoppingapp.data.source.ProductDataSource\nimport kotlinx.coroutines.CoroutineDispatcher\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.withContext\n\nclass ProductsLocalDataSource internal constructor(\n\tprivate val productsDao: ProductsDao,\n\tprivate val ioDispatcher: CoroutineDispatcher = Dispatchers.IO\n) : ProductDataSource {\n\toverride fun observeProducts(): LiveData<Result<List<Product>>?> {\n\t\treturn try {\n\t\t\tTransformations.map(productsDao.observeProducts()) {\n\t\t\t\tSuccess(it)\n\t\t\t}\n\t\t} catch (e: Exception) {\n\t\t\tTransformations.map(MutableLiveData(e)) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride fun observeProductsByOwner(ownerId: String): LiveData<Result<List<Product>>?> {\n\t\treturn try {\n\t\t\tTransformations.map(productsDao.observeProductsByOwner(ownerId)) {\n\t\t\t\tSuccess(it)\n\t\t\t}\n\t\t} catch (e: Exception) {\n\t\t\tTransformations.map(MutableLiveData(e)) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun getAllProducts(): Result<List<Product>> = withContext(ioDispatcher) {\n\t\treturn@withContext try {\n\t\t\tSuccess(productsDao.getAllProducts())\n\t\t} catch (e: Exception) {\n\t\t\tError(e)\n\t\t}\n\t}\n\n\toverride suspend fun getAllProductsByOwner(ownerId: String): Result<List<Product>> =\n\t\twithContext(ioDispatcher) {\n\t\t\treturn@withContext try {\n\t\t\t\tSuccess(productsDao.getProductsByOwnerId(ownerId))\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\n\toverride suspend fun getProductById(productId: String): Result<Product> =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval product = productsDao.getProductById(productId)\n\t\t\t\tif (product != null) {\n\t\t\t\t\treturn@withContext Success(product)\n\t\t\t\t} else {\n\t\t\t\t\treturn@withContext Error(Exception(\"Product Not Found!\"))\n\t\t\t\t}\n\t\t\t} catch (e: Exception) {\n\t\t\t\treturn@withContext Error(e)\n\t\t\t}\n\t\t}\n\n\toverride suspend fun insertProduct(newProduct: Product) = withContext(ioDispatcher) {\n\t\tproductsDao.insert(newProduct)\n\t}\n\n\toverride suspend fun updateProduct(proData: Product) = withContext(ioDispatcher) {\n\t\tproductsDao.insert(proData)\n\t}\n\n\toverride suspend fun insertMultipleProducts(data: List<Product>) = withContext(ioDispatcher) {\n\t\tproductsDao.insertListOfProducts(data)\n\t}\n\n\toverride suspend fun deleteProduct(productId: String): Unit = withContext(ioDispatcher) {\n\t\tproductsDao.deleteProductById(productId)\n\t}\n\n\toverride suspend fun deleteAllProducts() = withContext(ioDispatcher) {\n\t\tproductsDao.deleteAllProducts()\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/local/ShoppingAppDatabase.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.local\n\nimport android.content.Context\nimport androidx.room.Database\nimport androidx.room.Room\nimport androidx.room.RoomDatabase\nimport androidx.room.TypeConverters\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.DateTypeConvertors\nimport com.vishalgaur.shoppingapp.data.utils.ListTypeConverter\nimport com.vishalgaur.shoppingapp.data.utils.ObjectListTypeConvertor\n\n@Database(entities = [UserData::class, Product::class], version = 2)\n@TypeConverters(ListTypeConverter::class, ObjectListTypeConvertor::class, DateTypeConvertors::class)\nabstract class ShoppingAppDatabase : RoomDatabase() {\n\tabstract fun userDao(): UserDao\n\tabstract fun productsDao(): ProductsDao\n\n\tcompanion object {\n\t\t@Volatile\n\t\tprivate var INSTANCE: ShoppingAppDatabase? = null\n\n\t\tfun getInstance(context: Context): ShoppingAppDatabase =\n\t\t\tINSTANCE ?: synchronized(this) {\n\t\t\t\tINSTANCE ?: buildDatabase(context).also { INSTANCE = it }\n\t\t\t}\n\n\t\tprivate fun buildDatabase(context: Context) =\n\t\t\tRoom.databaseBuilder(\n\t\t\t\tcontext.applicationContext,\n\t\t\t\tShoppingAppDatabase::class.java, \"ShoppingAppDb\"\n\t\t\t)\n\t\t\t\t.fallbackToDestructiveMigration()\n\t\t\t\t.allowMainThreadQueries()\n\t\t\t\t.build()\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/local/UserDao.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.local\n\nimport androidx.room.*\nimport com.vishalgaur.shoppingapp.data.UserData\n\n@Dao\ninterface UserDao {\n\t@Insert(onConflict = OnConflictStrategy.REPLACE)\n\tsuspend fun insert(uData: UserData)\n\n\t@Query(\"SELECT * FROM users WHERE userId = :userId\")\n\tsuspend fun getById(userId: String): UserData?\n\n\t@Query(\"SELECT * FROM users WHERE mobile = :mobile\")\n\tsuspend fun getByMobile(mobile: String): UserData?\n\n\t@Update(entity = UserData::class)\n\tsuspend fun updateUser(obj: UserData)\n\n\t@Query(\"DELETE FROM users\")\n\tsuspend fun clear()\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/local/UserLocalDataSource.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.local\n\nimport android.util.Log\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.Result.*\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.UserDataSource\nimport kotlinx.coroutines.CoroutineDispatcher\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.withContext\n\nclass UserLocalDataSource internal constructor(\n\tprivate val userDao: UserDao,\n\tprivate val ioDispatcher: CoroutineDispatcher = Dispatchers.IO\n) : UserDataSource {\n\n\toverride suspend fun addUser(userData: UserData) {\n\t\twithContext(ioDispatcher) {\n\t\t\tuserDao.clear()\n\t\t\tuserDao.insert(userData)\n\t\t}\n\t}\n\n\toverride suspend fun getUserById(userId: String): Result<UserData?> =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getById(userId)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\treturn@withContext Success(uData)\n\t\t\t\t} else {\n\t\t\t\t\treturn@withContext Error(Exception(\"User Not Found!\"))\n\t\t\t\t}\n\t\t\t} catch (e: Exception) {\n\t\t\t\treturn@withContext Error(e)\n\t\t\t}\n\t\t}\n\n\toverride suspend fun getUserByMobile(phoneNumber: String): UserData? =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getByMobile(phoneNumber)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\treturn@withContext uData\n\t\t\t\t} else {\n\t\t\t\t\treturn@withContext null\n\t\t\t\t}\n\t\t\t} catch (e: Exception) {\n\t\t\t\tLog.d(\"UserLocalSource\", \"onGetUser: Error Occurred, $e\")\n\t\t\t\treturn@withContext null\n\t\t\t}\n\t\t}\n\n\toverride suspend fun getOrdersByUserId(userId: String): Result<List<UserData.OrderItem>?> =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getById(userId)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\tval ordersList = uData.orders\n\t\t\t\t\treturn@withContext Success(ordersList)\n\t\t\t\t} else {\n\t\t\t\t\treturn@withContext Error(Exception(\"User Not Found\"))\n\t\t\t\t}\n\n\t\t\t} catch (e: Exception) {\n\t\t\t\tLog.d(\"UserLocalSource\", \"onGetOrders: Error Occurred, ${e.message}\")\n\t\t\t\treturn@withContext Error(e)\n\t\t\t}\n\t\t}\n\n\toverride suspend fun getAddressesByUserId(userId: String): Result<List<UserData.Address>?> =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getById(userId)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\tval addressList = uData.addresses\n\t\t\t\t\treturn@withContext Success(addressList)\n\t\t\t\t} else {\n\t\t\t\t\treturn@withContext Error(Exception(\"User Not Found\"))\n\t\t\t\t}\n\n\t\t\t} catch (e: Exception) {\n\t\t\t\tLog.d(\"UserLocalSource\", \"onGetAddress: Error Occurred, ${e.message}\")\n\t\t\t\treturn@withContext Error(e)\n\t\t\t}\n\t\t}\n\n\toverride suspend fun getLikesByUserId(userId: String): Result<List<String>?> =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getById(userId)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\tval likesList = uData.likes\n\t\t\t\t\treturn@withContext Success(likesList)\n\t\t\t\t} else {\n\t\t\t\t\treturn@withContext Error(Exception(\"User Not Found\"))\n\t\t\t\t}\n\n\t\t\t} catch (e: Exception) {\n\t\t\t\tLog.d(\"UserLocalSource\", \"onGetLikes: Error Occurred, ${e.message}\")\n\t\t\t\treturn@withContext Error(e)\n\t\t\t}\n\t\t}\n\n\toverride suspend fun dislikeProduct(productId: String, userId: String) =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getById(userId)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\tval likesList = uData.likes.toMutableList()\n\t\t\t\t\tlikesList.remove(productId)\n\t\t\t\t\tuData.likes = likesList\n\t\t\t\t\tuserDao.updateUser(uData)\n\t\t\t\t} else {\n\t\t\t\t\tthrow Exception(\"User Not Found\")\n\t\t\t\t}\n\t\t\t} catch (e: Exception) {\n\t\t\t\tLog.d(\"UserLocalSource\", \"onGetLikes: Error Occurred, ${e.message}\")\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\toverride suspend fun likeProduct(productId: String, userId: String) =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getById(userId)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\tval likesList = uData.likes.toMutableList()\n\t\t\t\t\tlikesList.add(productId)\n\t\t\t\t\tuData.likes = likesList\n\t\t\t\t\tuserDao.updateUser(uData)\n\t\t\t\t} else {\n\t\t\t\t\tthrow Exception(\"User Not Found\")\n\t\t\t\t}\n\t\t\t} catch (e: Exception) {\n\t\t\t\tLog.d(\"UserLocalSource\", \"onGetLikes: Error Occurred, ${e.message}\")\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\toverride suspend fun insertCartItem(newItem: UserData.CartItem, userId: String) =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getById(userId)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\tval cartItems = uData.cart.toMutableList()\n\t\t\t\t\tcartItems.add(newItem)\n\t\t\t\t\tuData.cart = cartItems\n\t\t\t\t\tuserDao.updateUser(uData)\n\t\t\t\t} else {\n\t\t\t\t\tthrow Exception(\"User Not Found\")\n\t\t\t\t}\n\t\t\t} catch (e: Exception) {\n\t\t\t\tLog.d(\"UserLocalSource\", \"onInsertCartItem: Error Occurred, ${e.message}\")\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\toverride suspend fun updateCartItem(item: UserData.CartItem, userId: String) =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getById(userId)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\tval cartItems = uData.cart.toMutableList()\n\t\t\t\t\tval pos = cartItems.indexOfFirst { it.itemId == item.itemId }\n\t\t\t\t\tif (pos >= 0) {\n\t\t\t\t\t\tcartItems[pos] = item\n\t\t\t\t\t}\n\t\t\t\t\tuData.cart = cartItems\n\t\t\t\t\tuserDao.updateUser(uData)\n\t\t\t\t} else {\n\t\t\t\t\tthrow Exception(\"User Not Found\")\n\t\t\t\t}\n\t\t\t} catch (e: Exception) {\n\t\t\t\tLog.d(\"UserLocalSource\", \"onInsertCartItem: Error Occurred, ${e.message}\")\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\toverride suspend fun deleteCartItem(itemId: String, userId: String) =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getById(userId)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\tval cartItems = uData.cart.toMutableList()\n\t\t\t\t\tval pos = cartItems.indexOfFirst { it.itemId == itemId }\n\t\t\t\t\tif (pos >= 0) {\n\t\t\t\t\t\tcartItems.removeAt(pos)\n\t\t\t\t\t}\n\t\t\t\t\tuData.cart = cartItems\n\t\t\t\t\tuserDao.updateUser(uData)\n\t\t\t\t} else {\n\t\t\t\t\tthrow Exception(\"User Not Found\")\n\t\t\t\t}\n\t\t\t} catch (e: Exception) {\n\t\t\t\tLog.d(\"UserLocalSource\", \"onInsertCartItem: Error Occurred, ${e.message}\")\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\toverride suspend fun setStatusOfOrderByUserId(orderId: String, userId: String, status: String) =\n\t\twithContext(ioDispatcher) {\n\t\t\ttry {\n\t\t\t\tval uData = userDao.getById(userId)\n\t\t\t\tif (uData != null) {\n\t\t\t\t\tval orders = uData.orders.toMutableList()\n\t\t\t\t\tval pos = orders.indexOfFirst { it.orderId == orderId }\n\t\t\t\t\tif (pos >= 0) {\n\t\t\t\t\t\torders[pos].status = status\n\t\t\t\t\t\tval custId = orders[pos].customerId\n\t\t\t\t\t\tval custData = userDao.getById(custId)\n\t\t\t\t\t\tif (custData != null) {\n\t\t\t\t\t\t\tval orderList = custData.orders.toMutableList()\n\t\t\t\t\t\t\tval idx = orderList.indexOfFirst { it.orderId == orderId }\n\t\t\t\t\t\t\tif (idx >= 0) {\n\t\t\t\t\t\t\t\torderList[idx].status = status\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcustData.orders = orderList\n\t\t\t\t\t\t\tuserDao.updateUser(custData)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tuData.orders = orders\n\t\t\t\t\tuserDao.updateUser(uData)\n\t\t\t\t} else {\n\t\t\t\t\tthrow Exception(\"User Not Found\")\n\t\t\t\t}\n\t\t\t} catch (e: Exception) {\n\t\t\t\tLog.d(\"UserLocalSource\", \"onInsertCartItem: Error Occurred, ${e.message}\")\n\t\t\t\tthrow e\n\t\t\t}\n\t\t}\n\n\toverride suspend fun clearUser() {\n\t\twithContext(ioDispatcher) {\n\t\t\tuserDao.clear()\n\t\t}\n\t}\n\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/remote/AuthRemoteDataSource.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.remote\n\nimport android.util.Log\nimport com.google.firebase.firestore.FieldValue\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.google.firebase.firestore.ktx.firestore\nimport com.google.firebase.ktx.Firebase\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.UserDataSource\nimport com.vishalgaur.shoppingapp.data.utils.EmailMobileData\nimport com.vishalgaur.shoppingapp.data.utils.OrderStatus\nimport kotlinx.coroutines.tasks.await\n\nclass AuthRemoteDataSource : UserDataSource {\n\tprivate val firebaseDb: FirebaseFirestore = Firebase.firestore\n\n\tprivate fun usersCollectionRef() = firebaseDb.collection(USERS_COLLECTION)\n\tprivate fun allEmailsMobilesRef() =\n\t\tfirebaseDb.collection(USERS_COLLECTION).document(EMAIL_MOBILE_DOC)\n\n\n\toverride suspend fun getUserById(userId: String): Result<UserData?> {\n\t\tval resRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\treturn if (!resRef.isEmpty) {\n\t\t\tSuccess(resRef.toObjects(UserData::class.java)[0])\n\t\t} else {\n\t\t\tError(Exception(\"User Not Found!\"))\n\t\t}\n\t}\n\n\n\toverride suspend fun addUser(userData: UserData) {\n\t\tusersCollectionRef().add(userData.toHashMap())\n\t\t\t.addOnSuccessListener {\n\t\t\t\tLog.d(TAG, \"Doc added\")\n\t\t\t}\n\t\t\t.addOnFailureListener { e ->\n\t\t\t\tLog.d(TAG, \"firestore error occurred: $e\")\n\t\t\t}\n\t}\n\n\toverride suspend fun getUserByMobile(phoneNumber: String): UserData =\n\t\tusersCollectionRef().whereEqualTo(USERS_MOBILE_FIELD, phoneNumber).get().await()\n\t\t\t.toObjects(UserData::class.java)[0]\n\n\toverride suspend fun getOrdersByUserId(userId: String): Result<List<UserData.OrderItem>?> {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\treturn if (!userRef.isEmpty) {\n\t\t\tval userData = userRef.documents[0].toObject(UserData::class.java)\n\t\t\tSuccess(userData!!.orders)\n\t\t} else {\n\t\t\tError(Exception(\"User Not Found!\"))\n\t\t}\n\t}\n\n\toverride suspend fun getAddressesByUserId(userId: String): Result<List<UserData.Address>?> {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\treturn if (!userRef.isEmpty) {\n\t\t\tval userData = userRef.documents[0].toObject(UserData::class.java)\n\t\t\tSuccess(userData!!.addresses)\n\t\t} else {\n\t\t\tError(Exception(\"User Not Found!\"))\n\t\t}\n\t}\n\n\toverride suspend fun getLikesByUserId(userId: String): Result<List<String>?> {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\treturn if (!userRef.isEmpty) {\n\t\t\tval userData = userRef.documents[0].toObject(UserData::class.java)\n\t\t\tSuccess(userData!!.likes)\n\t\t} else {\n\t\t\tError(Exception(\"User Not Found!\"))\n\t\t}\n\t}\n\n\toverride suspend fun getUserByMobileAndPassword(\n\t\tmobile: String,\n\t\tpassword: String\n\t): MutableList<UserData> =\n\t\tusersCollectionRef().whereEqualTo(USERS_MOBILE_FIELD, mobile)\n\t\t\t.whereEqualTo(USERS_PWD_FIELD, password).get().await().toObjects(UserData::class.java)\n\n\toverride suspend fun likeProduct(productId: String, userId: String) {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\tif (!userRef.isEmpty) {\n\t\t\tval docId = userRef.documents[0].id\n\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t.update(USERS_LIKES_FIELD, FieldValue.arrayUnion(productId))\n\t\t}\n\t}\n\n\toverride suspend fun dislikeProduct(productId: String, userId: String) {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\tif (!userRef.isEmpty) {\n\t\t\tval docId = userRef.documents[0].id\n\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t.update(USERS_LIKES_FIELD, FieldValue.arrayRemove(productId))\n\t\t}\n\t}\n\n\toverride suspend fun insertAddress(newAddress: UserData.Address, userId: String) {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\tif (!userRef.isEmpty) {\n\t\t\tval docId = userRef.documents[0].id\n\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t.update(USERS_ADDRESSES_FIELD, FieldValue.arrayUnion(newAddress.toHashMap()))\n\t\t}\n\t}\n\n\toverride suspend fun updateAddress(newAddress: UserData.Address, userId: String) {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\tif (!userRef.isEmpty) {\n\t\t\tval docId = userRef.documents[0].id\n\t\t\tval oldAddressList =\n\t\t\t\tuserRef.documents[0].toObject(UserData::class.java)?.addresses?.toMutableList()\n\t\t\tval idx = oldAddressList?.indexOfFirst { it.addressId == newAddress.addressId } ?: -1\n\t\t\tif (idx != -1) {\n\t\t\t\toldAddressList?.set(idx, newAddress)\n\t\t\t}\n\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t.update(USERS_ADDRESSES_FIELD, oldAddressList?.map { it.toHashMap() })\n\t\t}\n\t}\n\n\toverride suspend fun deleteAddress(addressId: String, userId: String) {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\tif (!userRef.isEmpty) {\n\t\t\tval docId = userRef.documents[0].id\n\t\t\tval oldAddressList =\n\t\t\t\tuserRef.documents[0].toObject(UserData::class.java)?.addresses?.toMutableList()\n\t\t\tval idx = oldAddressList?.indexOfFirst { it.addressId == addressId } ?: -1\n\t\t\tif (idx != -1) {\n\t\t\t\toldAddressList?.removeAt(idx)\n\t\t\t}\n\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t.update(USERS_ADDRESSES_FIELD, oldAddressList?.map { it.toHashMap() })\n\t\t}\n\t}\n\n\toverride suspend fun insertCartItem(newItem: UserData.CartItem, userId: String) {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\tif (!userRef.isEmpty) {\n\t\t\tval docId = userRef.documents[0].id\n\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t.update(USERS_CART_FIELD, FieldValue.arrayUnion(newItem.toHashMap()))\n\t\t}\n\t}\n\n\toverride suspend fun updateCartItem(item: UserData.CartItem, userId: String) {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\tif (!userRef.isEmpty) {\n\t\t\tval docId = userRef.documents[0].id\n\t\t\tval oldCart =\n\t\t\t\tuserRef.documents[0].toObject(UserData::class.java)?.cart?.toMutableList()\n\t\t\tval idx = oldCart?.indexOfFirst { it.itemId == item.itemId } ?: -1\n\t\t\tif (idx != -1) {\n\t\t\t\toldCart?.set(idx, item)\n\t\t\t}\n\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t.update(USERS_CART_FIELD, oldCart?.map { it.toHashMap() })\n\t\t}\n\t}\n\n\toverride suspend fun deleteCartItem(itemId: String, userId: String) {\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\tif (!userRef.isEmpty) {\n\t\t\tval docId = userRef.documents[0].id\n\t\t\tval oldCart =\n\t\t\t\tuserRef.documents[0].toObject(UserData::class.java)?.cart?.toMutableList()\n\t\t\tval idx = oldCart?.indexOfFirst { it.itemId == itemId } ?: -1\n\t\t\tif (idx != -1) {\n\t\t\t\toldCart?.removeAt(idx)\n\t\t\t}\n\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t.update(USERS_CART_FIELD, oldCart?.map { it.toHashMap() })\n\t\t}\n\t}\n\n\toverride suspend fun placeOrder(newOrder: UserData.OrderItem, userId: String) {\n\t\t// add order to customer and\n\t\t// specific items to their owners\n\t\t// empty customers cart\n\t\tval ownerProducts: MutableMap<String, MutableList<UserData.CartItem>> = mutableMapOf()\n\t\tfor (item in newOrder.items) {\n\t\t\tif (!ownerProducts.containsKey(item.ownerId)) {\n\t\t\t\townerProducts[item.ownerId] = mutableListOf()\n\t\t\t}\n\t\t\townerProducts[item.ownerId]?.add(item)\n\t\t}\n\t\townerProducts.forEach { (ownerId, items) ->\n\t\t\trun {\n\t\t\t\tval itemPrices = mutableMapOf<String, Double>()\n\t\t\t\titems.forEach { item ->\n\t\t\t\t\titemPrices[item.itemId] = newOrder.itemsPrices[item.itemId] ?: 0.0\n\t\t\t\t}\n\t\t\t\tval ownerOrder = UserData.OrderItem(\n\t\t\t\t\tnewOrder.orderId,\n\t\t\t\t\tuserId,\n\t\t\t\t\titems,\n\t\t\t\t\titemPrices,\n\t\t\t\t\tnewOrder.deliveryAddress,\n\t\t\t\t\tnewOrder.shippingCharges,\n\t\t\t\t\tnewOrder.paymentMethod,\n\t\t\t\t\tnewOrder.orderDate,\n\t\t\t\t\tOrderStatus.CONFIRMED.name\n\t\t\t\t)\n\t\t\t\tval ownerRef =\n\t\t\t\t\tusersCollectionRef().whereEqualTo(USERS_ID_FIELD, ownerId).get().await()\n\t\t\t\tif (!ownerRef.isEmpty) {\n\t\t\t\t\tval docId = ownerRef.documents[0].id\n\t\t\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t\t\t.update(USERS_ORDERS_FIELD, FieldValue.arrayUnion(ownerOrder.toHashMap()))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\tif (!userRef.isEmpty) {\n\t\t\tval docId = userRef.documents[0].id\n\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t.update(USERS_ORDERS_FIELD, FieldValue.arrayUnion(newOrder.toHashMap()))\n\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t.update(USERS_CART_FIELD, ArrayList<UserData.CartItem>())\n\t\t}\n\t}\n\n\toverride suspend fun setStatusOfOrderByUserId(orderId: String, userId: String, status: String) {\n\t\t// update on customer and owner\n\t\tval userRef = usersCollectionRef().whereEqualTo(USERS_ID_FIELD, userId).get().await()\n\t\tif (!userRef.isEmpty) {\n\t\t\tval docId = userRef.documents[0].id\n\t\t\tval ordersList =\n\t\t\t\tuserRef.documents[0].toObject(UserData::class.java)?.orders?.toMutableList()\n\t\t\tval idx = ordersList?.indexOfFirst { it.orderId == orderId } ?: -1\n\t\t\tif (idx != -1) {\n\t\t\t\tval orderData = ordersList?.get(idx)\n\t\t\t\tif (orderData != null) {\n\t\t\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t\t\t.update(USERS_ORDERS_FIELD, FieldValue.arrayRemove(orderData.toHashMap()))\n\t\t\t\t\torderData.status = status\n\t\t\t\t\tusersCollectionRef().document(docId)\n\t\t\t\t\t\t.update(USERS_ORDERS_FIELD, FieldValue.arrayUnion(orderData.toHashMap()))\n\n\t\t\t\t\t// updating customer status\n\t\t\t\t\tval custRef =\n\t\t\t\t\t\tusersCollectionRef().whereEqualTo(USERS_ID_FIELD, orderData.customerId)\n\t\t\t\t\t\t\t.get().await()\n\t\t\t\t\tif (!custRef.isEmpty) {\n\t\t\t\t\t\tval did = custRef.documents[0].id\n\t\t\t\t\t\tval orders =\n\t\t\t\t\t\t\tcustRef.documents[0].toObject(UserData::class.java)?.orders?.toMutableList()\n\t\t\t\t\t\tval pos = orders?.indexOfFirst { it.orderId == orderId } ?: -1\n\t\t\t\t\t\tif (pos != -1) {\n\t\t\t\t\t\t\tval order = orders?.get(pos)\n\t\t\t\t\t\t\tif (order != null) {\n\t\t\t\t\t\t\t\tusersCollectionRef().document(did).update(\n\t\t\t\t\t\t\t\t\tUSERS_ORDERS_FIELD,\n\t\t\t\t\t\t\t\t\tFieldValue.arrayRemove(order.toHashMap())\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\torder.status = status\n\t\t\t\t\t\t\t\tusersCollectionRef().document(did).update(\n\t\t\t\t\t\t\t\t\tUSERS_ORDERS_FIELD,\n\t\t\t\t\t\t\t\t\tFieldValue.arrayUnion(order.toHashMap())\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\toverride fun updateEmailsAndMobiles(email: String, mobile: String) {\n\t\tallEmailsMobilesRef().update(EMAIL_MOBILE_EMAIL_FIELD, FieldValue.arrayUnion(email))\n\t\tallEmailsMobilesRef().update(EMAIL_MOBILE_MOB_FIELD, FieldValue.arrayUnion(mobile))\n\t}\n\n\toverride suspend fun getEmailsAndMobiles() = allEmailsMobilesRef().get().await().toObject(\n\t\tEmailMobileData::class.java\n\t)\n\n\tcompanion object {\n\t\tprivate const val USERS_COLLECTION = \"users\"\n\t\tprivate const val USERS_ID_FIELD = \"userId\"\n\t\tprivate const val USERS_ADDRESSES_FIELD = \"addresses\"\n\t\tprivate const val USERS_LIKES_FIELD = \"likes\"\n\t\tprivate const val USERS_CART_FIELD = \"cart\"\n\t\tprivate const val USERS_ORDERS_FIELD = \"orders\"\n\t\tprivate const val USERS_MOBILE_FIELD = \"mobile\"\n\t\tprivate const val USERS_PWD_FIELD = \"password\"\n\t\tprivate const val EMAIL_MOBILE_DOC = \"emailAndMobiles\"\n\t\tprivate const val EMAIL_MOBILE_EMAIL_FIELD = \"emails\"\n\t\tprivate const val EMAIL_MOBILE_MOB_FIELD = \"mobiles\"\n\t\tprivate const val TAG = \"AuthRemoteDataSource\"\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/remote/ProductsRemoteDataSource.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.remote\n\nimport android.net.Uri\nimport android.util.Log\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.google.firebase.firestore.ktx.firestore\nimport com.google.firebase.ktx.Firebase\nimport com.google.firebase.storage.FirebaseStorage\nimport com.google.firebase.storage.ktx.storage\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.source.ProductDataSource\nimport kotlinx.coroutines.tasks.await\n\nclass ProductsRemoteDataSource : ProductDataSource {\n\tprivate val firebaseDb: FirebaseFirestore = Firebase.firestore\n\tprivate val firebaseStorage: FirebaseStorage = Firebase.storage\n\n\tprivate val observableProducts = MutableLiveData<Result<List<Product>>?>()\n\n\tprivate fun storageRef() = firebaseStorage.reference\n\tprivate fun productsCollectionRef() = firebaseDb.collection(PRODUCT_COLLECTION)\n\n\toverride suspend fun refreshProducts() {\n\t\tobservableProducts.value = getAllProducts()\n\t}\n\n\toverride fun observeProducts(): LiveData<Result<List<Product>>?> {\n\t\treturn observableProducts\n\t}\n\n\toverride suspend fun getAllProducts(): Result<List<Product>> {\n\t\tval resRef = productsCollectionRef().get().await()\n\t\treturn if (!resRef.isEmpty) {\n\t\t\tSuccess(resRef.toObjects(Product::class.java))\n\t\t} else {\n\t\t\tError(Exception(\"Error getting Products!\"))\n\t\t}\n\t}\n\n\toverride suspend fun insertProduct(newProduct: Product) {\n\t\tproductsCollectionRef().add(newProduct.toHashMap()).await()\n\t}\n\n\toverride suspend fun updateProduct(proData: Product) {\n\t\tval resRef =\n\t\t\tproductsCollectionRef().whereEqualTo(PRODUCT_ID_FIELD, proData.productId).get().await()\n\t\tif (!resRef.isEmpty) {\n\t\t\tval docId = resRef.documents[0].id\n\t\t\tproductsCollectionRef().document(docId).set(proData.toHashMap()).await()\n\t\t} else {\n\t\t\tLog.d(TAG, \"onUpdateProduct: product with id: $proData.productId not found!\")\n\t\t}\n\t}\n\n\toverride suspend fun getProductById(productId: String): Result<Product> {\n\t\tval resRef = productsCollectionRef().whereEqualTo(PRODUCT_ID_FIELD, productId).get().await()\n\t\treturn if (!resRef.isEmpty) {\n\t\t\tSuccess(resRef.toObjects(Product::class.java)[0])\n\t\t} else {\n\t\t\tError(Exception(\"Product with id: $productId Not Found!\"))\n\t\t}\n\t}\n\n\toverride suspend fun deleteProduct(productId: String) {\n\t\tLog.d(TAG, \"onDeleteProduct: delete product with Id: $productId initiated\")\n\t\tval resRef = productsCollectionRef().whereEqualTo(PRODUCT_ID_FIELD, productId).get().await()\n\t\tif (!resRef.isEmpty) {\n\t\t\tval product = resRef.documents[0].toObject(Product::class.java)\n\t\t\tval imgUrls = product?.images\n\n\t\t\t//deleting images first\n\t\t\timgUrls?.forEach { imgUrl ->\n\t\t\t\tdeleteImage(imgUrl)\n\t\t\t}\n\n\t\t\t//deleting doc containing product\n\t\t\tval docId = resRef.documents[0].id\n\t\t\tproductsCollectionRef().document(docId).delete().addOnSuccessListener {\n\t\t\t\tLog.d(TAG, \"onDelete: DocumentSnapshot successfully deleted!\")\n\t\t\t}.addOnFailureListener { e ->\n\t\t\t\tLog.w(TAG, \"onDelete: Error deleting document\", e)\n\t\t\t}\n\t\t} else {\n\t\t\tLog.d(TAG, \"onDeleteProduct: product with id: $productId not found!\")\n\t\t}\n\t}\n\n\toverride suspend fun uploadImage(uri: Uri, fileName: String): Uri? {\n\t\tval imgRef = storageRef().child(\"$SHOES_STORAGE_PATH/$fileName\")\n\t\tval uploadTask = imgRef.putFile(uri)\n\t\tval uriRef = uploadTask.continueWithTask { task ->\n\t\t\tif (!task.isSuccessful) {\n\t\t\t\ttask.exception?.let { throw it }\n\t\t\t}\n\t\t\timgRef.downloadUrl\n\t\t}\n\t\treturn uriRef.await()\n\t}\n\n\toverride fun deleteImage(imgUrl: String) {\n\t\tval ref = firebaseStorage.getReferenceFromUrl(imgUrl)\n\t\tref.delete().addOnSuccessListener {\n\t\t\tLog.d(TAG, \"onDelete: image deleted successfully!\")\n\t\t}.addOnFailureListener { e ->\n\t\t\tLog.d(TAG, \"onDelete: Error deleting image, error: $e\")\n\t\t}\n\t}\n\n\toverride fun revertUpload(fileName: String) {\n\t\tval imgRef = storageRef().child(\"${SHOES_STORAGE_PATH}/$fileName\")\n\t\timgRef.delete().addOnSuccessListener {\n\t\t\tLog.d(TAG, \"onRevert: File with name: $fileName deleted successfully!\")\n\t\t}.addOnFailureListener { e ->\n\t\t\tLog.d(TAG, \"onRevert: Error deleting file with name = $fileName, error: $e\")\n\t\t}\n\t}\n\n\tcompanion object {\n\t\tprivate const val PRODUCT_COLLECTION = \"products\"\n\t\tprivate const val PRODUCT_ID_FIELD = \"productId\"\n\t\tprivate const val SHOES_STORAGE_PATH = \"Shoes\"\n\t\tprivate const val TAG = \"ProductsRemoteSource\"\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/repository/AuthRepoInterface.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.repository\n\nimport android.content.Context\nimport androidx.lifecycle.MutableLiveData\nimport com.google.firebase.auth.FirebaseAuth\nimport com.google.firebase.auth.PhoneAuthCredential\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.SignUpErrors\n\ninterface AuthRepoInterface {\n\tsuspend fun refreshData()\n\tsuspend fun signUp(userData: UserData)\n\tfun login(userData: UserData, rememberMe: Boolean)\n\tsuspend fun checkEmailAndMobile(email: String, mobile: String, context: Context): SignUpErrors?\n\tsuspend fun checkLogin(mobile: String, password: String): UserData?\n\tsuspend fun signOut()\n\tsuspend fun hardRefreshUserData()\n\tsuspend fun insertProductToLikes(productId: String, userId: String): Result<Boolean>\n\tsuspend fun removeProductFromLikes(productId: String, userId: String): Result<Boolean>\n\tsuspend fun insertAddress(newAddress: UserData.Address, userId: String): Result<Boolean>\n\tsuspend fun updateAddress(newAddress: UserData.Address, userId: String): Result<Boolean>\n\tsuspend fun deleteAddressById(addressId: String, userId: String): Result<Boolean>\n\tsuspend fun insertCartItemByUserId(cartItem: UserData.CartItem, userId: String): Result<Boolean>\n\tsuspend fun updateCartItemByUserId(cartItem: UserData.CartItem, userId: String): Result<Boolean>\n\tsuspend fun deleteCartItemByUserId(itemId: String, userId: String): Result<Boolean>\n\tsuspend fun placeOrder(newOrder: UserData.OrderItem, userId: String): Result<Boolean>\n\tsuspend fun setStatusOfOrder(orderId: String, userId: String, status: String): Result<Boolean>\n\tsuspend fun getOrdersByUserId(userId: String): Result<List<UserData.OrderItem>?>\n\tsuspend fun getAddressesByUserId(userId: String): Result<List<UserData.Address>?>\n\tsuspend fun getLikesByUserId(userId: String): Result<List<String>?>\n\tsuspend fun getUserData(userId: String): Result<UserData?>\n\tfun getFirebaseAuth(): FirebaseAuth\n\tfun signInWithPhoneAuthCredential(\n\t\tcredential: PhoneAuthCredential,\n\t\tisUserLoggedIn: MutableLiveData<Boolean>,\n\t\tcontext: Context\n\t)\n\n\tfun isRememberMeOn(): Boolean\n}\n"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/repository/AuthRepository.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.repository\n\nimport android.content.Context\nimport android.util.Log\nimport android.widget.Toast\nimport androidx.lifecycle.MutableLiveData\nimport com.google.firebase.auth.FirebaseAuth\nimport com.google.firebase.auth.FirebaseAuthInvalidCredentialsException\nimport com.google.firebase.auth.PhoneAuthCredential\nimport com.google.firebase.auth.ktx.auth\nimport com.google.firebase.ktx.Firebase\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.UserDataSource\nimport com.vishalgaur.shoppingapp.data.utils.SignUpErrors\nimport com.vishalgaur.shoppingapp.data.utils.UserType\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.coroutineScope\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.supervisorScope\n\nclass AuthRepository(\n\tprivate val userLocalDataSource: UserDataSource,\n\tprivate val authRemoteDataSource: UserDataSource,\n\tprivate var sessionManager: ShoppingAppSessionManager\n) : AuthRepoInterface {\n\n\tprivate var firebaseAuth: FirebaseAuth = Firebase.auth\n\n\tcompanion object {\n\t\tprivate const val TAG = \"AuthRepository\"\n\t}\n\n\toverride fun getFirebaseAuth() = firebaseAuth\n\n\toverride fun isRememberMeOn() = sessionManager.isRememberMeOn()\n\n\toverride suspend fun refreshData() {\n\t\tLog.d(TAG, \"refreshing userdata\")\n\t\tif (sessionManager.isLoggedIn()) {\n\t\t\tupdateUserInLocalSource(sessionManager.getPhoneNumber())\n\t\t} else {\n\t\t\tsessionManager.logoutFromSession()\n\t\t\tdeleteUserFromLocalSource()\n\t\t}\n\t}\n\n\toverride suspend fun signUp(userData: UserData) {\n\t\tval isSeller = userData.userType == UserType.SELLER.name\n\t\tsessionManager.createLoginSession(\n\t\t\tuserData.userId,\n\t\t\tuserData.name,\n\t\t\tuserData.mobile,\n\t\t\tfalse,\n\t\t\tisSeller\n\t\t)\n\t\tLog.d(TAG, \"on SignUp: Updating user in Local Source\")\n\t\tuserLocalDataSource.addUser(userData)\n\t\tLog.d(TAG, \"on SignUp: Updating userdata on Remote Source\")\n\t\tauthRemoteDataSource.addUser(userData)\n\t\tauthRemoteDataSource.updateEmailsAndMobiles(userData.email, userData.mobile)\n\t}\n\n\toverride fun login(userData: UserData, rememberMe: Boolean) {\n\t\tval isSeller = userData.userType == UserType.SELLER.name\n\t\tsessionManager.createLoginSession(\n\t\t\tuserData.userId,\n\t\t\tuserData.name,\n\t\t\tuserData.mobile,\n\t\t\trememberMe,\n\t\t\tisSeller\n\t\t)\n\t}\n\n\toverride suspend fun checkEmailAndMobile(\n\t\temail: String,\n\t\tmobile: String,\n\t\tcontext: Context\n\t): SignUpErrors? {\n\t\tLog.d(TAG, \"on SignUp: Checking email and mobile\")\n\t\tvar sErr: SignUpErrors? = null\n\t\ttry {\n\t\t\tval queryResult = authRemoteDataSource.getEmailsAndMobiles()\n\t\t\tif (queryResult != null) {\n\t\t\t\tval mob = queryResult.mobiles.contains(mobile)\n\t\t\t\tval em = queryResult.emails.contains(email)\n\t\t\t\tif (!mob && !em) {\n\t\t\t\t\tsErr = SignUpErrors.NONE\n\t\t\t\t} else {\n\t\t\t\t\tsErr = SignUpErrors.SERR\n\t\t\t\t\twhen {\n\t\t\t\t\t\t!mob && em -> makeErrToast(\"Email is already registered!\", context)\n\t\t\t\t\t\tmob && !em -> makeErrToast(\"Mobile is already registered!\", context)\n\t\t\t\t\t\tmob && em -> makeErrToast(\n\t\t\t\t\t\t\t\"Email and mobile is already registered!\",\n\t\t\t\t\t\t\tcontext\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e: Exception) {\n\t\t\tmakeErrToast(\"Some Error Occurred\", context)\n\t\t}\n\t\treturn sErr\n\t}\n\n\toverride suspend fun checkLogin(mobile: String, password: String): UserData? {\n\t\tLog.d(TAG, \"on Login: checking mobile and password\")\n\t\tvar queryResult = mutableListOf<UserData>()\n\t\ttry {\n\t\t\tqueryResult = authRemoteDataSource.getUserByMobileAndPassword(mobile, password)\n\t\t} catch (e: Exception) {\n\t\t\t// No Handling\n\t\t}\n\t\treturn if (queryResult.size > 0) {\n\t\t\tqueryResult[0]\n\t\t} else {\n\t\t\tnull\n\t\t}\n\t}\n\n\toverride fun signInWithPhoneAuthCredential(\n\t\tcredential: PhoneAuthCredential,\n\t\tisUserLoggedIn: MutableLiveData<Boolean>, context: Context\n\t) {\n\t\ttry {\n\t\t\tfirebaseAuth.signInWithCredential(credential)\n\t\t\t\t.addOnCompleteListener { task ->\n\t\t\t\t\tif (task.isSuccessful) {\n\t\t\t\t\t\tLog.d(TAG, \"signInWithCredential:success\")\n\t\t\t\t\t\tval user = task.result?.user\n\t\t\t\t\t\tif (user != null) {\n\t\t\t\t\t\t\tisUserLoggedIn.postValue(true)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tLog.w(TAG, \"signInWithCredential:failure\", task.exception)\n\t\t\t\t\t\tif (task.exception is FirebaseAuthInvalidCredentialsException) {\n\t\t\t\t\t\t\tLog.d(TAG, \"createUserWithMobile:failure\", task.exception)\n\t\t\t\t\t\t\tisUserLoggedIn.postValue(false)\n\t\t\t\t\t\t\tmakeErrToast(\"Wrong OTP!\", context)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}.addOnFailureListener {\n\t\t\t\t\tLog.d(TAG, \"createUserWithMobile:failure\", it)\n\t\t\t\t\tisUserLoggedIn.postValue(false)\n\t\t\t\t\tmakeErrToast(\"Invalid Request!\", context)\n\t\t\t\t}\n\t\t} catch (e: Exception) {\n\t\t\tmakeErrToast(\"Some Error Occurred\", context)\n\t\t}\n\t}\n\n\toverride suspend fun signOut() {\n\t\tsessionManager.logoutFromSession()\n\t\tfirebaseAuth.signOut()\n\t\tuserLocalDataSource.clearUser()\n\t}\n\n\tprivate fun makeErrToast(text: String, context: Context) {\n\t\tToast.makeText(context, text, Toast.LENGTH_LONG).show()\n\t}\n\n\tprivate suspend fun deleteUserFromLocalSource() {\n\t\tuserLocalDataSource.clearUser()\n\t}\n\n\tprivate suspend fun updateUserInLocalSource(phoneNumber: String?) {\n\t\tcoroutineScope {\n\t\t\tlaunch {\n\t\t\t\tif (phoneNumber != null) {\n\t\t\t\t\tval getUser = userLocalDataSource.getUserByMobile(phoneNumber)\n\t\t\t\t\tif (getUser == null) {\n\t\t\t\t\t\tuserLocalDataSource.clearUser()\n\t\t\t\t\t\tval uData = authRemoteDataSource.getUserByMobile(phoneNumber)\n\t\t\t\t\t\tif (uData != null) {\n\t\t\t\t\t\t\tuserLocalDataSource.addUser(uData)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun hardRefreshUserData() {\n\t\tuserLocalDataSource.clearUser()\n\t\tval mobile = sessionManager.getPhoneNumber()\n\t\tif (mobile != null) {\n\t\t\tval uData = authRemoteDataSource.getUserByMobile(mobile)\n\t\t\tif (uData != null) {\n\t\t\t\tuserLocalDataSource.addUser(uData)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun insertProductToLikes(productId: String, userId: String): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onLikeProduct: adding product to remote source\")\n\t\t\t\tauthRemoteDataSource.likeProduct(productId, userId)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onLikeProduct: updating product to local source\")\n\t\t\t\tuserLocalDataSource.likeProduct(productId, userId)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tlocalRes.await()\n\t\t\t\tremoteRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun removeProductFromLikes(\n\t\tproductId: String,\n\t\tuserId: String\n\t): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onDislikeProduct: deleting product from remote source\")\n\t\t\t\tauthRemoteDataSource.dislikeProduct(productId, userId)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onDislikeProduct: updating product to local source\")\n\t\t\t\tuserLocalDataSource.dislikeProduct(productId, userId)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tlocalRes.await()\n\t\t\t\tremoteRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun insertAddress(\n\t\tnewAddress: UserData.Address,\n\t\tuserId: String\n\t): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onInsertAddress: adding address to remote source\")\n\t\t\t\tauthRemoteDataSource.insertAddress(newAddress, userId)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onInsertAddress: updating address to local source\")\n\t\t\t\tval userRes = authRemoteDataSource.getUserById(userId)\n\t\t\t\tif (userRes is Success) {\n\t\t\t\t\tuserLocalDataSource.clearUser()\n\t\t\t\t\tuserLocalDataSource.addUser(userRes.data!!)\n\t\t\t\t} else if (userRes is Error) {\n\t\t\t\t\tthrow userRes.exception\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tremoteRes.await()\n\t\t\t\tlocalRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun updateAddress(\n\t\tnewAddress: UserData.Address,\n\t\tuserId: String\n\t): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onUpdateAddress: updating address on remote source\")\n\t\t\t\tauthRemoteDataSource.updateAddress(newAddress, userId)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onUpdateAddress: updating address on local source\")\n\t\t\t\tval userRes =\n\t\t\t\t\tauthRemoteDataSource.getUserById(userId)\n\t\t\t\tif (userRes is Success) {\n\t\t\t\t\tuserLocalDataSource.clearUser()\n\t\t\t\t\tuserLocalDataSource.addUser(userRes.data!!)\n\t\t\t\t} else if (userRes is Error) {\n\t\t\t\t\tthrow userRes.exception\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tremoteRes.await()\n\t\t\t\tlocalRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun deleteAddressById(addressId: String, userId: String): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onDelete: deleting address from remote source\")\n\t\t\t\tauthRemoteDataSource.deleteAddress(addressId, userId)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onDelete: deleting address from local source\")\n\t\t\t\tval userRes =\n\t\t\t\t\tauthRemoteDataSource.getUserById(userId)\n\t\t\t\tif (userRes is Success) {\n\t\t\t\t\tuserLocalDataSource.clearUser()\n\t\t\t\t\tuserLocalDataSource.addUser(userRes.data!!)\n\t\t\t\t} else if (userRes is Error) {\n\t\t\t\t\tthrow userRes.exception\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tremoteRes.await()\n\t\t\t\tlocalRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun insertCartItemByUserId(\n\t\tcartItem: UserData.CartItem,\n\t\tuserId: String\n\t): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onInsertCartItem: adding item to remote source\")\n\t\t\t\tauthRemoteDataSource.insertCartItem(cartItem, userId)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onInsertCartItem: updating item to local source\")\n\t\t\t\tuserLocalDataSource.insertCartItem(cartItem, userId)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tlocalRes.await()\n\t\t\t\tremoteRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun updateCartItemByUserId(\n\t\tcartItem: UserData.CartItem,\n\t\tuserId: String\n\t): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onUpdateCartItem: updating cart item on remote source\")\n\t\t\t\tauthRemoteDataSource.updateCartItem(cartItem, userId)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onUpdateCartItem: updating cart item on local source\")\n\t\t\t\tuserLocalDataSource.updateCartItem(cartItem, userId)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tlocalRes.await()\n\t\t\t\tremoteRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun deleteCartItemByUserId(itemId: String, userId: String): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onDelete: deleting cart item from remote source\")\n\t\t\t\tauthRemoteDataSource.deleteCartItem(itemId, userId)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onDelete: deleting cart item from local source\")\n\t\t\t\tuserLocalDataSource.deleteCartItem(itemId, userId)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tlocalRes.await()\n\t\t\t\tremoteRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun placeOrder(newOrder: UserData.OrderItem, userId: String): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onPlaceOrder: adding item to remote source\")\n\t\t\t\tauthRemoteDataSource.placeOrder(newOrder, userId)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onPlaceOrder: adding item to local source\")\n\t\t\t\tval userRes = authRemoteDataSource.getUserById(userId)\n\t\t\t\tif (userRes is Success) {\n\t\t\t\t\tuserLocalDataSource.clearUser()\n\t\t\t\t\tuserLocalDataSource.addUser(userRes.data!!)\n\t\t\t\t} else if (userRes is Error) {\n\t\t\t\t\tthrow userRes.exception\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tremoteRes.await()\n\t\t\t\tlocalRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun setStatusOfOrder(\n\t\torderId: String,\n\t\tuserId: String,\n\t\tstatus: String\n\t): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onSetStatus: updating status on remote source\")\n\t\t\t\tauthRemoteDataSource.setStatusOfOrderByUserId(orderId, userId, status)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onSetStatus: updating status on local source\")\n\t\t\t\tuserLocalDataSource.setStatusOfOrderByUserId(orderId, userId, status)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tlocalRes.await()\n\t\t\t\tremoteRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun getOrdersByUserId(userId: String): Result<List<UserData.OrderItem>?> {\n\t\treturn userLocalDataSource.getOrdersByUserId(userId)\n\t}\n\n\toverride suspend fun getAddressesByUserId(userId: String): Result<List<UserData.Address>?> {\n\t\treturn userLocalDataSource.getAddressesByUserId(userId)\n\t}\n\n\toverride suspend fun getLikesByUserId(userId: String): Result<List<String>?> {\n\t\treturn userLocalDataSource.getLikesByUserId(userId)\n\t}\n\n\toverride suspend fun getUserData(userId: String): Result<UserData?> {\n\t\treturn userLocalDataSource.getUserById(userId)\n\t}\n\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/repository/ProductsRepoInterface.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.repository\n\nimport android.net.Uri\nimport androidx.lifecycle.LiveData\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\n\ninterface ProductsRepoInterface {\n\tsuspend fun refreshProducts(): StoreDataStatus?\n\tfun observeProducts(): LiveData<Result<List<Product>>?>\n\tfun observeProductsByOwner(ownerId: String): LiveData<Result<List<Product>>?>\n\tsuspend fun getAllProductsByOwner(ownerId: String): Result<List<Product>>\n\tsuspend fun getProductById(productId: String, forceUpdate: Boolean = false): Result<Product>\n\tsuspend fun insertProduct(newProduct: Product): Result<Boolean>\n\tsuspend fun insertImages(imgList: List<Uri>): List<String>\n\tsuspend fun updateProduct(product: Product): Result<Boolean>\n\tsuspend fun updateImages(newList: List<Uri>, oldList: List<String>): List<String>\n\tsuspend fun deleteProductById(productId: String): Result<Boolean>\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/source/repository/ProductsRepository.kt",
    "content": "package com.vishalgaur.shoppingapp.data.source.repository\n\nimport android.net.Uri\nimport android.util.Log\nimport androidx.core.net.toUri\nimport androidx.lifecycle.LiveData\nimport com.vishalgaur.shoppingapp.ERR_UPLOAD\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.Result.*\nimport com.vishalgaur.shoppingapp.data.source.ProductDataSource\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.supervisorScope\nimport java.util.*\n\nclass ProductsRepository(\n\tprivate val productsRemoteSource: ProductDataSource,\n\tprivate val productsLocalSource: ProductDataSource\n) : ProductsRepoInterface {\n\n\tcompanion object {\n\t\tprivate const val TAG = \"ProductsRepository\"\n\t}\n\n\toverride suspend fun refreshProducts(): StoreDataStatus? {\n\t\tLog.d(TAG, \"Updating Products in Room\")\n\t\treturn updateProductsFromRemoteSource()\n\t}\n\n\toverride fun observeProducts(): LiveData<Result<List<Product>>?> {\n\t\treturn productsLocalSource.observeProducts()\n\t}\n\n\toverride fun observeProductsByOwner(ownerId: String): LiveData<Result<List<Product>>?> {\n\t\treturn productsLocalSource.observeProductsByOwner(ownerId)\n\t}\n\n\toverride suspend fun getAllProductsByOwner(ownerId: String): Result<List<Product>> {\n\t\treturn productsLocalSource.getAllProductsByOwner(ownerId)\n\t}\n\n\toverride suspend fun getProductById(productId: String, forceUpdate: Boolean): Result<Product> {\n\t\tif (forceUpdate) {\n\t\t\tupdateProductFromRemoteSource(productId)\n\t\t}\n\t\treturn productsLocalSource.getProductById(productId)\n\t}\n\n\toverride suspend fun insertProduct(newProduct: Product): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onInsertProduct: adding product to local source\")\n\t\t\t\tproductsLocalSource.insertProduct(newProduct)\n\t\t\t}\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onInsertProduct: adding product to remote source\")\n\t\t\t\tproductsRemoteSource.insertProduct(newProduct)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tlocalRes.await()\n\t\t\t\tremoteRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun insertImages(imgList: List<Uri>): List<String> {\n\t\tvar urlList = mutableListOf<String>()\n\t\timgList.forEach label@{ uri ->\n\t\t\tval uniId = UUID.randomUUID().toString()\n\t\t\tval fileName = uniId + uri.lastPathSegment?.split(\"/\")?.last()\n\t\t\ttry {\n\t\t\t\tval downloadUrl = productsRemoteSource.uploadImage(uri, fileName)\n\t\t\t\turlList.add(downloadUrl.toString())\n\t\t\t} catch (e: Exception) {\n\t\t\t\tproductsRemoteSource.revertUpload(fileName)\n\t\t\t\tLog.d(TAG, \"exception: message = $e\")\n\t\t\t\turlList = mutableListOf()\n\t\t\t\turlList.add(ERR_UPLOAD)\n\t\t\t\treturn@label\n\t\t\t}\n\t\t}\n\t\treturn urlList\n\t}\n\n\toverride suspend fun updateProduct(product: Product): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onUpdate: updating product in remote source\")\n\t\t\t\tproductsRemoteSource.updateProduct(product)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onUpdate: updating product in local source\")\n\t\t\t\tproductsLocalSource.insertProduct(product)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tremoteRes.await()\n\t\t\t\tlocalRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride suspend fun updateImages(newList: List<Uri>, oldList: List<String>): List<String> {\n\t\tvar urlList = mutableListOf<String>()\n\t\tnewList.forEach label@{ uri ->\n\t\t\tif (!oldList.contains(uri.toString())) {\n\t\t\t\tval uniId = UUID.randomUUID().toString()\n\t\t\t\tval fileName = uniId + uri.lastPathSegment?.split(\"/\")?.last()\n\t\t\t\ttry {\n\t\t\t\t\tval downloadUrl = productsRemoteSource.uploadImage(uri, fileName)\n\t\t\t\t\turlList.add(downloadUrl.toString())\n\t\t\t\t} catch (e: Exception) {\n\t\t\t\t\tproductsRemoteSource.revertUpload(fileName)\n\t\t\t\t\tLog.d(TAG, \"exception: message = $e\")\n\t\t\t\t\turlList = mutableListOf()\n\t\t\t\t\turlList.add(ERR_UPLOAD)\n\t\t\t\t\treturn@label\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\turlList.add(uri.toString())\n\t\t\t}\n\t\t}\n\t\toldList.forEach { imgUrl ->\n\t\t\tif (!newList.contains(imgUrl.toUri())) {\n\t\t\t\tproductsRemoteSource.deleteImage(imgUrl)\n\t\t\t}\n\t\t}\n\t\treturn urlList\n\t}\n\n\toverride suspend fun deleteProductById(productId: String): Result<Boolean> {\n\t\treturn supervisorScope {\n\t\t\tval remoteRes = async {\n\t\t\t\tLog.d(TAG, \"onDelete: deleting product from remote source\")\n\t\t\t\tproductsRemoteSource.deleteProduct(productId)\n\t\t\t}\n\t\t\tval localRes = async {\n\t\t\t\tLog.d(TAG, \"onDelete: deleting product from local source\")\n\t\t\t\tproductsLocalSource.deleteProduct(productId)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tremoteRes.await()\n\t\t\t\tlocalRes.await()\n\t\t\t\tSuccess(true)\n\t\t\t} catch (e: Exception) {\n\t\t\t\tError(e)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate suspend fun updateProductsFromRemoteSource(): StoreDataStatus? {\n\t\tvar res: StoreDataStatus? = null\n\t\ttry {\n\t\t\tval remoteProducts = productsRemoteSource.getAllProducts()\n\t\t\tif (remoteProducts is Success) {\n\t\t\t\tLog.d(TAG, \"pro list = ${remoteProducts.data}\")\n\t\t\t\tproductsLocalSource.deleteAllProducts()\n\t\t\t\tproductsLocalSource.insertMultipleProducts(remoteProducts.data)\n\t\t\t\tres = StoreDataStatus.DONE\n\t\t\t} else {\n\t\t\t\tres = StoreDataStatus.ERROR\n\t\t\t\tif (remoteProducts is Error)\n\t\t\t\t\tthrow remoteProducts.exception\n\t\t\t}\n\t\t} catch (e: Exception) {\n\t\t\tLog.d(TAG, \"onUpdateProductsFromRemoteSource: Exception occurred, ${e.message}\")\n\t\t}\n\n\t\treturn res\n\t}\n\n\tprivate suspend fun updateProductFromRemoteSource(productId: String): StoreDataStatus? {\n\t\tvar res: StoreDataStatus? = null\n\t\ttry {\n\t\t\tval remoteProduct = productsRemoteSource.getProductById(productId)\n\t\t\tif (remoteProduct is Success) {\n\t\t\t\tproductsLocalSource.insertProduct(remoteProduct.data)\n\t\t\t\tres = StoreDataStatus.DONE\n\t\t\t} else {\n\t\t\t\tres = StoreDataStatus.ERROR\n\t\t\t\tif (remoteProduct is Error)\n\t\t\t\t\tthrow remoteProduct.exception\n\t\t\t}\n\t\t} catch (e: Exception) {\n\t\t\tLog.d(TAG, \"onUpdateProductFromRemoteSource: Exception occurred, ${e.message}\")\n\t\t}\n\t\treturn res\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/utils/DateTypeConvertors.kt",
    "content": "package com.vishalgaur.shoppingapp.data.utils\n\nimport androidx.room.TypeConverter\nimport java.util.*\n\nclass DateTypeConvertors {\n\t@TypeConverter\n\tfun toDate(dateLong: Long?): Date? {\n\t\treturn dateLong?.let { Date(it) }\n\t}\n\n\t@TypeConverter\n\tfun fromDate(date: Date?): Long? {\n\t\treturn date?.time\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/utils/EmailMobileData.kt",
    "content": "package com.vishalgaur.shoppingapp.data.utils\n\ndata class EmailMobileData(\n\tval emails: ArrayList<String> = ArrayList(),\n\tval mobiles: ArrayList<String> = ArrayList()\n)"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/utils/ListTypeConverter.kt",
    "content": "package com.vishalgaur.shoppingapp.data.utils\n\nimport androidx.room.TypeConverter\n\nclass ListTypeConverter {\n\t@TypeConverter\n\tfun fromStringToStringList(value: String): List<String> {\n\t\treturn value.split(\",\").map { it }\n\t}\n\n\t@TypeConverter\n\tfun fromStringListToString(value: List<String>): String {\n\t\treturn value.joinToString(separator = \",\")\n\t}\n\n\t@TypeConverter\n\tfun fromStringToIntegerList(value: String): List<Int> {\n\t\treturn value.split(\",\").map { it.toInt() }\n\t}\n\n\t@TypeConverter\n\tfun fromIntegerListToString(value: List<Int>): String {\n\t\treturn value.joinToString(separator = \",\")\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/utils/ObjectListTypeConvertor.kt",
    "content": "package com.vishalgaur.shoppingapp.data.utils\n\nimport androidx.room.TypeConverter\nimport com.google.common.reflect.TypeToken\nimport com.google.gson.Gson\nimport com.vishalgaur.shoppingapp.data.UserData\n\nclass ObjectListTypeConvertor {\n\t@TypeConverter\n\tfun stringToAddressObjectList(data: String?): List<UserData.Address> {\n\t\tif (data.isNullOrBlank()) {\n\t\t\treturn emptyList()\n\t\t}\n\t\tval listType = object : TypeToken<List<UserData.Address>>() {}.type\n\t\tval gson = Gson()\n\t\treturn gson.fromJson(data, listType)\n\t}\n\n\t@TypeConverter\n\tfun addressObjectListToString(addressList: List<UserData.Address>): String {\n\t\tif (addressList.isEmpty()) {\n\t\t\treturn \"\"\n\t\t}\n\t\tval gson = Gson()\n\t\tval listType = object : TypeToken<List<UserData.Address>>() {}.type\n\t\treturn gson.toJson(addressList, listType)\n\t}\n\n\t@TypeConverter\n\tfun stringToCartObjectList(data: String?): List<UserData.CartItem> {\n\t\tif (data.isNullOrBlank()) {\n\t\t\treturn emptyList()\n\t\t}\n\t\tval listType = object : TypeToken<List<UserData.CartItem>>() {}.type\n\t\tval gson = Gson()\n\t\treturn gson.fromJson(data, listType)\n\t}\n\n\t@TypeConverter\n\tfun cartObjectListToString(cartList: List<UserData.CartItem>): String {\n\t\tif (cartList.isEmpty()) {\n\t\t\treturn \"\"\n\t\t}\n\t\tval gson = Gson()\n\t\tval listType = object : TypeToken<List<UserData.CartItem>>() {}.type\n\t\treturn gson.toJson(cartList, listType)\n\t}\n\n\t@TypeConverter\n\tfun stringToOrderObjectList(data: String?): List<UserData.OrderItem> {\n\t\tif (data.isNullOrBlank()) {\n\t\t\treturn emptyList()\n\t\t}\n\t\tval listType = object : TypeToken<List<UserData.OrderItem>>() {}.type\n\t\tval gson = Gson()\n\t\treturn gson.fromJson(data, listType)\n\t}\n\n\t@TypeConverter\n\tfun orderObjectListToString(orderList: List<UserData.OrderItem>): String {\n\t\tif (orderList.isEmpty()) {\n\t\t\treturn \"\"\n\t\t}\n\t\tval gson = Gson()\n\t\tval listType = object : TypeToken<List<UserData.OrderItem>>() {}.type\n\t\treturn gson.toJson(orderList, listType)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/utils/ProductUtils.kt",
    "content": "package com.vishalgaur.shoppingapp.data.utils\n\nval ShoeSizes = mapOf(\n\t\"UK4\" to 4,\n\t\"UK5\" to 5,\n\t\"UK6\" to 6,\n\t\"UK7\" to 7,\n\t\"UK8\" to 8,\n\t\"UK9\" to 9,\n\t\"UK10\" to 10,\n\t\"UK11\" to 11,\n\t\"UK12\" to 12\n)\n\nval ShoeColors = mapOf(\n\t\"black\" to \"#000000\",\n\t\"white\" to \"#FFFFFF\",\n\t\"red\" to \"#FF0000\",\n\t\"green\" to \"#00FF00\",\n\t\"blue\" to \"#0000FF\",\n\t\"yellow\" to \"#FFFF00\",\n\t\"cyan\" to \"#00FFFF\",\n\t\"magenta\" to \"#FF00FF\"\n)\n\nval ProductCategories = arrayOf(\"Shoes\", \"Slippers\")"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/data/utils/Utils.kt",
    "content": "package com.vishalgaur.shoppingapp.data.utils\n\nimport java.util.*\n\nenum class SignUpErrors { NONE, SERR }\n\nenum class LogInErrors { NONE, LERR }\n\nenum class AddProductErrors { NONE, ERR_ADD, ERR_ADD_IMG, ADDING }\n\nenum class AddObjectStatus { DONE, ERR_ADD, ADDING }\n\nenum class UserType { CUSTOMER, SELLER }\n\nenum class OrderStatus { CONFIRMED, PACKAGING, PACKED, SHIPPING, SHIPPED, ARRIVING, DELIVERED }\n\nenum class StoreDataStatus { LOADING, ERROR, DONE }\n\nfun getISOCountriesMap(): Map<String, String> {\n\tval result = mutableMapOf<String, String>()\n\tval isoCountries = Locale.getISOCountries()\n\tval countriesList = isoCountries.map { isoCountry ->\n\t\tresult[isoCountry] = Locale(\"\", isoCountry).displayCountry\n\t}\n\treturn result\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/LaunchActivity.kt",
    "content": "package com.vishalgaur.shoppingapp.ui\n\nimport android.content.Intent\nimport android.os.Bundle\nimport android.os.Handler\nimport android.os.Looper\nimport androidx.appcompat.app.AppCompatActivity\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.ui.loginSignup.LoginSignupActivity\n\nclass LaunchActivity : AppCompatActivity() {\n\n\toverride fun onCreate(savedInstanceState: Bundle?) {\n\t\tsuper.onCreate(savedInstanceState)\n\t\tsetContentView(R.layout.activity_launch)\n\t\tsetLaunchScreenTimeOut()\n\t}\n\n\tprivate fun setLaunchScreenTimeOut() {\n\t\tLooper.myLooper()?.let {\n\t\t\tHandler(it).postDelayed({\n\t\t\t\tstartPreferredActivity()\n\t\t\t}, TIME_OUT)\n\t\t}\n\t}\n\n\tprivate fun startPreferredActivity() {\n\t\tval sessionManager = ShoppingAppSessionManager(this)\n\t\tif (sessionManager.isLoggedIn()) {\n\t\t\tlaunchHome(this)\n\t\t\tfinish()\n\t\t} else {\n\t\t\tval intent = Intent(this, LoginSignupActivity::class.java)\n\t\t\tstartActivity(intent)\n\t\t\tfinish()\n\t\t}\n\t}\n\n\tcompanion object {\n\t\tprivate const val TIME_OUT: Long = 1500\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/RecyclerViewPaddingItemDecoration.kt",
    "content": "package com.vishalgaur.shoppingapp.ui\n\nimport android.content.Context\nimport android.graphics.Rect\nimport android.view.View\nimport androidx.recyclerview.widget.RecyclerView\n\nclass RecyclerViewPaddingItemDecoration(private val context: Context) :\n\tRecyclerView.ItemDecoration() {\n\tprivate val paddingSpace = 16\n\n\toverride fun getItemOffsets(\n\t\toutRect: Rect,\n\t\tview: View,\n\t\tparent: RecyclerView,\n\t\tstate: RecyclerView.State\n\t) {\n\t\tsuper.getItemOffsets(outRect, view, parent, state)\n\t\toutRect.set(paddingSpace, paddingSpace, paddingSpace, paddingSpace)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/UiUtils.kt",
    "content": "package com.vishalgaur.shoppingapp.ui\n\nimport android.app.Activity\nimport android.content.Context\nimport android.content.Intent\nimport android.content.res.Resources\nimport android.graphics.Canvas\nimport android.graphics.Paint\nimport android.graphics.Rect\nimport android.view.View\nimport android.view.WindowManager\nimport android.view.inputmethod.InputMethodManager\nimport androidx.annotation.ColorInt\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport androidx.recyclerview.widget.RecyclerView\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.getISOCountriesMap\nimport com.vishalgaur.shoppingapp.ui.home.MainActivity\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\nimport kotlin.math.max\n\nenum class SignUpViewErrors { NONE, ERR_EMAIL, ERR_MOBILE, ERR_EMAIL_MOBILE, ERR_EMPTY, ERR_NOT_ACC, ERR_PWD12NS }\n\nenum class LoginViewErrors { NONE, ERR_EMPTY, ERR_MOBILE }\n\nenum class OTPStatus { NONE, CORRECT, WRONG, INVALID_REQ }\n\nenum class AddProductViewErrors { NONE, EMPTY, ERR_PRICE_0 }\n\nenum class AddAddressViewErrors { EMPTY, ERR_FNAME_EMPTY, ERR_LNAME_EMPTY, ERR_STR1_EMPTY, ERR_CITY_EMPTY, ERR_STATE_EMPTY, ERR_ZIP_EMPTY, ERR_ZIP_INVALID, ERR_PHONE_INVALID, ERR_PHONE_EMPTY }\n\nenum class AddItemErrors { ERROR_SIZE, ERROR_COLOR }\n\nclass MyOnFocusChangeListener : View.OnFocusChangeListener {\n\toverride fun onFocusChange(v: View?, hasFocus: Boolean) {\n\t\tif (v != null) {\n\t\t\tval inputManager =\n\t\t\t\tv.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager\n\t\t\tif (!hasFocus) {\n\n\t\t\t\tinputManager.hideSoftInputFromWindow(v.windowToken, 0)\n\t\t\t} else {\n\t\t\t\tinputManager.toggleSoftInputFromWindow(v.windowToken, 0, 0)\n\n\t\t\t}\n\t\t}\n\t}\n}\n\nfun <T> throttleLatest(\n\tintervalMs: Long = 300L,\n\tcoroutineScope: CoroutineScope,\n\tdestinationFunction: (T) -> Unit\n): (T) -> Unit {\n\tvar throttleJob: Job? = null\n\tvar latestParam: T\n\treturn { param: T ->\n\t\tlatestParam = param\n\t\tif (throttleJob?.isCompleted != false) {\n\t\t\tthrottleJob = coroutineScope.launch {\n\t\t\t\tdelay(intervalMs)\n\t\t\t\tlatestParam.let(destinationFunction)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfun <T> debounce(\n\twaitMs: Long = 300L,\n\tcoroutineScope: CoroutineScope,\n\tdestinationFunction: (T) -> Unit\n): (T) -> Unit {\n\tvar debounceJob: Job? = null\n\treturn { param: T ->\n\t\tdebounceJob?.cancel()\n\t\tdebounceJob = coroutineScope.launch {\n\t\t\tdelay(waitMs)\n\t\t\tdestinationFunction(param)\n\t\t}\n\t}\n}\n\nclass DotsIndicatorDecoration(\n\tprivate val radius: Float,\n\tprivate val indicatorItemPadding: Float,\n\tprivate val indicatorHeight: Int,\n\t@ColorInt private val colorInactive: Int,\n\t@ColorInt private val colorActive: Int\n) : RecyclerView.ItemDecoration() {\n\n\tprivate val inactivePaint = Paint()\n\tprivate val activePaint = Paint()\n\n\tinit {\n\t\tval width = Resources.getSystem().displayMetrics.density * 1\n\t\tinactivePaint.apply {\n\t\t\tstrokeCap = Paint.Cap.ROUND\n\t\t\tstrokeWidth = width\n\t\t\tstyle = Paint.Style.STROKE\n\t\t\tisAntiAlias = true\n\t\t\tcolor = colorInactive\n\t\t}\n\n\t\tactivePaint.apply {\n\t\t\tstrokeCap = Paint.Cap.ROUND\n\t\t\tstrokeWidth = width\n\t\t\tstyle = Paint.Style.FILL_AND_STROKE\n\t\t\tisAntiAlias = true\n\t\t\tcolor = colorActive\n\t\t}\n\t}\n\n\toverride fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {\n\t\tsuper.onDrawOver(c, parent, state)\n\n\t\tval adapter = parent.adapter ?: return\n\n\t\tval itemCount = adapter.itemCount\n\n\t\tval totalLength: Float = (radius * 2 * itemCount)\n\t\tval padBWItems = max(0, itemCount - 1) * indicatorItemPadding\n\t\tval indicatorTotalWidth = totalLength + padBWItems\n\t\tval indicatorStartX = (parent.width - indicatorTotalWidth) / 2F\n\n\t\tval indicatorPosY = parent.height - indicatorHeight / 2F\n\n\t\tdrawInactiveDots(c, indicatorStartX, indicatorPosY, itemCount)\n\n\t\tval activePos: Int =\n\t\t\t(parent.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()\n\t\tif (activePos == RecyclerView.NO_POSITION) {\n\t\t\treturn\n\t\t}\n\n\t\tval activeChild =\n\t\t\t(parent.layoutManager as LinearLayoutManager).findViewByPosition(activePos)\n\t\t\t\t?: return\n\n\t\tdrawActiveDot(c, indicatorStartX, indicatorPosY, activePos)\n\n\n\t}\n\n\tprivate fun drawInactiveDots(\n\t\tc: Canvas,\n\t\tindicatorStartX: Float,\n\t\tindicatorPosY: Float,\n\t\titemCount: Int\n\t) {\n\t\tval w = radius * 2 + indicatorItemPadding\n\t\tvar st = indicatorStartX + radius\n\t\tfor (i in 1..itemCount) {\n\t\t\tc.drawCircle(st, indicatorPosY, radius, inactivePaint)\n\t\t\tst += w\n\t\t}\n\t}\n\n\tprivate fun drawActiveDot(\n\t\tc: Canvas,\n\t\tindicatorStartX: Float,\n\t\tindicatorPosY: Float,\n\t\thighlightPos: Int\n\t) {\n\t\tval w = radius * 2 + indicatorItemPadding\n\t\tval highStart = indicatorStartX + radius + w * highlightPos\n\t\tc.drawCircle(highStart, indicatorPosY, radius, activePaint)\n\t}\n\n\toverride fun getItemOffsets(\n\t\toutRect: Rect,\n\t\tview: View,\n\t\tparent: RecyclerView,\n\t\tstate: RecyclerView.State\n\t) {\n\t\tsuper.getItemOffsets(outRect, view, parent, state)\n\t\toutRect.bottom = indicatorHeight\n\t}\n\n}\n\ninternal fun launchHome(context: Context) {\n\tval homeIntent = Intent(context, MainActivity::class.java)\n\thomeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)\n\t\t.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)\n\t\t.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)\n\tcontext.startActivity(homeIntent)\n}\n\ninternal fun getCompleteAddress(address: UserData.Address): String {\n\treturn if (address.streetAddress2.isBlank()) {\n\t\t\"${address.streetAddress}, ${address.city}, ${address.state} - ${address.zipCode}, ${getISOCountriesMap()[address.countryISOCode]}\"\n\t} else {\n\t\t\"${address.streetAddress}, ${address.streetAddress2}, ${address.city}, ${address.state} - ${address.zipCode}, ${getISOCountriesMap()[address.countryISOCode]}\"\n\t}\n}\n\ninternal fun disableClickOnWindow(activity: Activity) {\n\tactivity.window.setFlags(\n\t\tWindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,\n\t\tWindowManager.LayoutParams.FLAG_NOT_TOUCHABLE\n\t)\n}\n\ninternal fun enableClickOnWindow(activity: Activity) {\n\tactivity.window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/AccountFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.content.Intent\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport com.google.android.material.dialog.MaterialAlertDialogBuilder\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.databinding.FragmentAccountBinding\nimport com.vishalgaur.shoppingapp.ui.loginSignup.LoginSignupActivity\nimport com.vishalgaur.shoppingapp.viewModels.HomeViewModel\n\nprivate const val TAG = \"AccountFragment\"\n\nclass AccountFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentAccountBinding\n\tprivate val viewModel: HomeViewModel by activityViewModels()\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentAccountBinding.inflate(layoutInflater)\n\n\t\tsetViews()\n\t\treturn binding.root\n\t}\n\n\tprivate fun setViews() {\n\t\tbinding.accountTopAppBar.topAppBar.title = getString(R.string.account_fragment_title)\n\t\tbinding.accountProfileTv.setOnClickListener {\n\t\t\tLog.d(TAG, \"Profile Selected\")\n\t\t\tfindNavController().navigate(R.id.action_accountFragment_to_profileFragment)\n\t\t}\n\t\tbinding.accountOrdersTv.setOnClickListener {\n\t\t\tLog.d(TAG, \"Orders Selected\")\n\t\t\tfindNavController().navigate(R.id.action_accountFragment_to_ordersFragment)\n\t\t}\n\t\tbinding.accountAddressTv.setOnClickListener {\n\t\t\tLog.d(TAG, \"Address Selected\")\n\t\t\tfindNavController().navigate(R.id.action_accountFragment_to_addressFragment)\n\t\t}\n\t\tbinding.accountSignOutTv.setOnClickListener {\n\t\t\tLog.d(TAG, \"Sign Out Selected\")\n\t\t\tshowSignOutDialog()\n\t\t}\n\t}\n\n\tprivate fun showSignOutDialog() {\n\t\tcontext?.let {\n\t\t\tMaterialAlertDialogBuilder(it)\n\t\t\t\t.setTitle(getString(R.string.sign_out_dialog_title_text))\n\t\t\t\t.setMessage(getString(R.string.sign_out_dialog_message_text))\n\t\t\t\t.setNegativeButton(getString(R.string.pro_cat_dialog_cancel_btn)) { dialog, _ ->\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.setPositiveButton(getString(R.string.dialog_sign_out_btn_text)) { dialog, _ ->\n\t\t\t\t\tviewModel.signOut()\n\t\t\t\t\tnavigateToSignUpActivity()\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.show()\n\t\t}\n\t}\n\n\tprivate fun navigateToSignUpActivity() {\n\t\tval homeIntent = Intent(context, LoginSignupActivity::class.java)\n\t\thomeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)\n\t\t\t.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)\n\t\t\t.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)\n\t\tcontext?.startActivity(homeIntent)\n\t\trequireActivity().finish()\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/AddEditAddressFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.ArrayAdapter\nimport android.widget.AutoCompleteTextView\nimport android.widget.Toast\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.viewModels\nimport androidx.navigation.fragment.findNavController\nimport com.google.android.material.textfield.TextInputLayout\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.utils.AddObjectStatus\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.data.utils.getISOCountriesMap\nimport com.vishalgaur.shoppingapp.databinding.FragmentAddEditAddressBinding\nimport com.vishalgaur.shoppingapp.ui.AddAddressViewErrors\nimport com.vishalgaur.shoppingapp.ui.MyOnFocusChangeListener\nimport com.vishalgaur.shoppingapp.viewModels.AddEditAddressViewModel\nimport java.util.*\nimport kotlin.properties.Delegates\n\nprivate const val TAG = \"AddAddressFragment\"\n\nclass AddEditAddressFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentAddEditAddressBinding\n\tprivate val focusChangeListener = MyOnFocusChangeListener()\n\tprivate val viewModel by viewModels<AddEditAddressViewModel>()\n\n\tprivate var isEdit by Delegates.notNull<Boolean>()\n\tprivate lateinit var addressId: String\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentAddEditAddressBinding.inflate(layoutInflater)\n\n\t\tisEdit = arguments?.getBoolean(\"isEdit\") == true\n\t\taddressId = arguments?.getString(\"addressId\").toString()\n\n\t\tinitViewModel()\n\n\t\tsetViews()\n\n\t\tsetObservers()\n\t\treturn binding.root\n\t}\n\n\tprivate fun initViewModel() {\n\t\tviewModel.setIsEdit(isEdit)\n\t\tif (isEdit) {\n\t\t\tviewModel.setAddressData(addressId)\n\t\t}\n\t}\n\n\tprivate fun setViews() {\n\t\tif (!isEdit) {\n\t\t\tbinding.addAddressTopAppBar.topAppBar.title = \"Add Address\"\n\t\t} else {\n\t\t\tbinding.addAddressTopAppBar.topAppBar.title = \"Edit Address\"\n\t\t}\n\t\tbinding.addAddressTopAppBar.topAppBar.setNavigationOnClickListener {\n\t\t\tfindNavController().navigateUp()\n\t\t}\n\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\tbinding.addressFirstNameEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.addressLastNameEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.addressStreetAddEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.addressStreetAdd2EditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.addressCityEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.addressStateEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.addressZipcodeEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.addressPhoneEditText.onFocusChangeListener = focusChangeListener\n\t\tsetCountrySelectTextField()\n\n\t\tbinding.addAddressSaveBtn.setOnClickListener {\n\t\t\tonAddAddress()\n\t\t\tif (viewModel.errorStatus.value?.isEmpty() == true) {\n\t\t\t\tviewModel.addAddressStatus.observe(viewLifecycleOwner) { status ->\n\t\t\t\t\tif (status == AddObjectStatus.DONE) {\n\t\t\t\t\t\tmakeToast(\"Address Saved!\")\n\t\t\t\t\t\tfindNavController().navigateUp()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun setObservers() {\n\t\tviewModel.errorStatus.observe(viewLifecycleOwner) { errList ->\n\t\t\tif (errList.isEmpty()) {\n\t\t\t\tbinding.addAddressErrorTextView.visibility = View.GONE\n\t\t\t} else {\n\t\t\t\tmodifyErrors(errList)\n\t\t\t}\n\t\t}\n\n\t\tviewModel.dataStatus.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tStoreDataStatus.LOADING -> setLoaderState(View.VISIBLE)\n\t\t\t\tStoreDataStatus.ERROR -> {\n\t\t\t\t\tsetLoaderState()\n\t\t\t\t\tmakeToast(\"Error getting Data, Try Again!\")\n\t\t\t\t}\n\t\t\t\tStoreDataStatus.DONE -> {\n\t\t\t\t\tfillDataInViews()\n\t\t\t\t\tsetLoaderState()\n\t\t\t\t}\n\t\t\t\telse -> {\n\t\t\t\t\tsetLoaderState()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tviewModel.addAddressStatus.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tAddObjectStatus.DONE -> setLoaderState()\n\t\t\t\tAddObjectStatus.ERR_ADD -> {\n\t\t\t\t\tsetLoaderState()\n\t\t\t\t\tbinding.addAddressErrorTextView.visibility = View.VISIBLE\n\t\t\t\t\tbinding.addAddressErrorTextView.text =\n\t\t\t\t\t\tgetString(R.string.save_address_error_text)\n\t\t\t\t\tmakeToast(getString(R.string.save_address_error_text))\n\t\t\t\t}\n\t\t\t\tAddObjectStatus.ADDING -> {\n\t\t\t\t\tsetLoaderState(View.VISIBLE)\n\t\t\t\t}\n\t\t\t\telse -> setLoaderState()\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun fillDataInViews() {\n\t\tviewModel.addressData.value?.let { address ->\n\t\t\tbinding.addAddressTopAppBar.topAppBar.title = \"Edit Address\"\n\t\t\tval countryName = getISOCountriesMap()[address.countryISOCode]\n\t\t\tbinding.addressCountryEditText.setText(countryName, false)\n\t\t\tbinding.addressFirstNameEditText.setText(address.fName)\n\t\t\tbinding.addressLastNameEditText.setText(address.lName)\n\t\t\tbinding.addressStreetAddEditText.setText(address.streetAddress)\n\t\t\tbinding.addressStreetAdd2EditText.setText(address.streetAddress2)\n\t\t\tbinding.addressCityEditText.setText(address.city)\n\t\t\tbinding.addressStateEditText.setText(address.state)\n\t\t\tbinding.addressZipcodeEditText.setText(address.zipCode)\n\t\t\tbinding.addressPhoneEditText.setText(address.phoneNumber.substringAfter(\"+91\"))\n\t\t\tbinding.addAddressSaveBtn.setText(R.string.save_address_btn_text)\n\t\t}\n\t}\n\n\tprivate fun makeToast(errText: String) {\n\t\tToast.makeText(context, errText, Toast.LENGTH_LONG).show()\n\t}\n\n\tprivate fun setLoaderState(isVisible: Int = View.GONE) {\n\t\tbinding.loaderLayout.loaderFrameLayout.visibility = isVisible\n\t\tif (isVisible == View.GONE) {\n\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t} else {\n\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t}\n\t}\n\n\tprivate fun onAddAddress() {\n\t\tval countryName = binding.addressCountryEditText.text.toString()\n\t\tval firstName = binding.addressFirstNameEditText.text.toString()\n\t\tval lastName = binding.addressLastNameEditText.text.toString()\n\t\tval streetAdd = binding.addressStreetAddEditText.text.toString()\n\t\tval streetAdd2 = binding.addressStreetAdd2EditText.text.toString()\n\t\tval city = binding.addressCityEditText.text.toString()\n\t\tval state = binding.addressStateEditText.text.toString()\n\t\tval zipCode = binding.addressZipcodeEditText.text.toString()\n\t\tval phoneNumber = binding.addressPhoneEditText.text.toString()\n\n\t\tval countryCode =\n\t\t\tgetISOCountriesMap().keys.find { Locale(\"\", it).displayCountry == countryName }\n\n\t\tLog.d(TAG, \"onAddAddress: Add/Edit Address Initiated\")\n\t\tviewModel.submitAddress(\n\t\t\tcountryCode!!,\n\t\t\tfirstName,\n\t\t\tlastName,\n\t\t\tstreetAdd,\n\t\t\tstreetAdd2,\n\t\t\tcity,\n\t\t\tstate,\n\t\t\tzipCode,\n\t\t\tphoneNumber\n\t\t)\n\t}\n\n\tprivate fun setCountrySelectTextField() {\n\t\tval isoCountriesMap = getISOCountriesMap()\n\t\tval countries = isoCountriesMap.values.toSortedSet().toList()\n\t\tval defaultCountry = Locale.getDefault().displayCountry\n\t\tval countryAdapter = ArrayAdapter(requireContext(), R.layout.country_list_item, countries)\n\t\t(binding.addressCountryEditText as? AutoCompleteTextView)?.let {\n\t\t\tit.setText(defaultCountry, false)\n\t\t\tit.setAdapter(countryAdapter)\n\t\t}\n\t}\n\n\tprivate fun modifyErrors(errList: List<AddAddressViewErrors>) {\n\t\tbinding.fNameOutlinedTextField.error = null\n\t\tbinding.lNameOutlinedTextField.error = null\n\t\tbinding.streetAddOutlinedTextField.error = null\n\t\tbinding.cityOutlinedTextField.error = null\n\t\tbinding.stateOutlinedTextField.error = null\n\t\tbinding.zipCodeOutlinedTextField.error = null\n\t\tbinding.phoneOutlinedTextField.error = null\n\t\terrList.forEach { err ->\n\t\t\twhen (err) {\n\t\t\t\tAddAddressViewErrors.EMPTY -> setEditTextsError(true)\n\t\t\t\tAddAddressViewErrors.ERR_FNAME_EMPTY ->\n\t\t\t\t\tsetEditTextsError(true, binding.fNameOutlinedTextField)\n\t\t\t\tAddAddressViewErrors.ERR_LNAME_EMPTY ->\n\t\t\t\t\tsetEditTextsError(true, binding.lNameOutlinedTextField)\n\t\t\t\tAddAddressViewErrors.ERR_STR1_EMPTY ->\n\t\t\t\t\tsetEditTextsError(true, binding.streetAddOutlinedTextField)\n\t\t\t\tAddAddressViewErrors.ERR_CITY_EMPTY ->\n\t\t\t\t\tsetEditTextsError(true, binding.cityOutlinedTextField)\n\t\t\t\tAddAddressViewErrors.ERR_STATE_EMPTY ->\n\t\t\t\t\tsetEditTextsError(true, binding.stateOutlinedTextField)\n\t\t\t\tAddAddressViewErrors.ERR_ZIP_EMPTY ->\n\t\t\t\t\tsetEditTextsError(true, binding.zipCodeOutlinedTextField)\n\t\t\t\tAddAddressViewErrors.ERR_ZIP_INVALID ->\n\t\t\t\t\tsetEditTextsError(false, binding.zipCodeOutlinedTextField)\n\t\t\t\tAddAddressViewErrors.ERR_PHONE_INVALID ->\n\t\t\t\t\tsetEditTextsError(false, binding.phoneOutlinedTextField)\n\t\t\t\tAddAddressViewErrors.ERR_PHONE_EMPTY ->\n\t\t\t\t\tsetEditTextsError(true, binding.phoneOutlinedTextField)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun setEditTextsError(isEmpty: Boolean, editText: TextInputLayout? = null) {\n\t\tif (isEmpty) {\n\t\t\tbinding.addAddressErrorTextView.visibility = View.VISIBLE\n\t\t\tif (editText != null) {\n\t\t\t\teditText.error = \"Please Fill the Form\"\n\t\t\t\teditText.errorIconDrawable = null\n\t\t\t}\n\t\t} else {\n\t\t\tbinding.addAddressErrorTextView.visibility = View.GONE\n\t\t\teditText!!.error = \"Invalid!\"\n\t\t\teditText.errorIconDrawable = null\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/AddEditProductFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.content.res.ColorStateList\nimport android.graphics.Color\nimport android.net.Uri\nimport android.os.Bundle\nimport android.util.Log\nimport android.util.TypedValue\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.Toast\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.core.net.toUri\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.viewModels\nimport androidx.navigation.fragment.findNavController\nimport com.google.android.material.chip.Chip\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.utils.AddProductErrors\nimport com.vishalgaur.shoppingapp.data.utils.ShoeColors\nimport com.vishalgaur.shoppingapp.data.utils.ShoeSizes\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.databinding.FragmentAddEditProductBinding\nimport com.vishalgaur.shoppingapp.ui.AddProductViewErrors\nimport com.vishalgaur.shoppingapp.ui.MyOnFocusChangeListener\nimport com.vishalgaur.shoppingapp.viewModels.AddEditProductViewModel\nimport kotlin.properties.Delegates\n\nprivate const val TAG = \"AddProductFragment\"\n\nclass AddEditProductFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentAddEditProductBinding\n\tprivate val viewModel by viewModels<AddEditProductViewModel>()\n\tprivate val focusChangeListener = MyOnFocusChangeListener()\n\n\t// arguments\n\tprivate var isEdit by Delegates.notNull<Boolean>()\n\tprivate lateinit var catName: String\n\tprivate lateinit var productId: String\n\n\tprivate var sizeList = mutableSetOf<Int>()\n\tprivate var colorsList = mutableSetOf<String>()\n\tprivate var imgList = mutableListOf<Uri>()\n\n\tprivate val getImages =\n\t\tregisterForActivityResult(ActivityResultContracts.GetMultipleContents()) { result ->\n\t\t\timgList.addAll(result)\n\t\t\tif (imgList.size > 3) {\n\t\t\t\timgList = imgList.subList(0, 3)\n\t\t\t\tmakeToast(\"Maximum 3 images are allowed!\")\n\t\t\t}\n\t\t\tval adapter = context?.let { AddProductImagesAdapter(it, imgList) }\n\t\t\tbinding.addProImagesRv.adapter = adapter\n\t\t}\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater, container: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\t// Inflate the layout for this fragment\n\t\tbinding = FragmentAddEditProductBinding.inflate(layoutInflater)\n\n\t\tisEdit = arguments?.getBoolean(\"isEdit\") == true\n\t\tcatName = arguments?.getString(\"categoryName\").toString()\n\t\tproductId = arguments?.getString(\"productId\").toString()\n\n\t\tinitViewModel()\n\n\t\tsetViews()\n\n\t\tsetObservers()\n\t\treturn binding.root\n\t}\n\n\tprivate fun initViewModel() {\n\t\tLog.d(TAG, \"init view model, isedit = $isEdit\")\n\n\t\tviewModel.setIsEdit(isEdit)\n\t\tif (isEdit) {\n\t\t\tLog.d(TAG, \"init view model, isedit = true, $productId\")\n\t\t\tviewModel.setProductData(productId)\n\t\t} else {\n\t\t\tLog.d(TAG, \"init view model, isedit = false, $catName\")\n\t\t\tviewModel.setCategory(catName)\n\t\t}\n\t}\n\n\tprivate fun setObservers() {\n\t\tviewModel.errorStatus.observe(viewLifecycleOwner) { err ->\n\t\t\tmodifyErrors(err)\n\t\t}\n\t\tviewModel.dataStatus.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tStoreDataStatus.LOADING -> {\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t\t\t}\n\t\t\t\tStoreDataStatus.DONE -> {\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\tfillDataInAllViews()\n\t\t\t\t}\n\t\t\t\telse -> {\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\tmakeToast(\"Error getting Data, Try Again!\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tviewModel.addProductErrors.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tAddProductErrors.ADDING -> {\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t\t\t}\n\t\t\t\tAddProductErrors.ERR_ADD_IMG -> {\n\t\t\t\t\tsetAddProductErrors(getString(R.string.add_product_error_img_upload))\n\t\t\t\t}\n\t\t\t\tAddProductErrors.ERR_ADD -> {\n\t\t\t\t\tsetAddProductErrors(getString(R.string.add_product_insert_error))\n\t\t\t\t}\n\t\t\t\tAddProductErrors.NONE -> {\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun setAddProductErrors(errText: String) {\n\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\tbinding.addProErrorTextView.visibility = View.VISIBLE\n\t\tbinding.addProErrorTextView.text = errText\n\n\t}\n\n\tprivate fun fillDataInAllViews() {\n\t\tviewModel.productData.value?.let { product ->\n\t\t\tLog.d(TAG, \"fill data in views\")\n\t\t\tbinding.addProAppBar.topAppBar.title = \"Edit Product - ${product.name}\"\n\t\t\tbinding.proNameEditText.setText(product.name)\n\t\t\tbinding.proPriceEditText.setText(product.price.toString())\n\t\t\tbinding.proMrpEditText.setText(product.mrp.toString())\n\t\t\tbinding.proDescEditText.setText(product.description)\n\n\t\t\timgList = product.images.map { it.toUri() } as MutableList<Uri>\n\t\t\tval adapter = AddProductImagesAdapter(requireContext(), imgList)\n\t\t\tbinding.addProImagesRv.adapter = adapter\n\n\t\t\tsetShoeSizesChips(product.availableSizes)\n\t\t\tsetShoeColorsChips(product.availableColors)\n\n\t\t\tbinding.addProBtn.setText(R.string.edit_product_btn_text)\n\t\t}\n\n\t}\n\n\tprivate fun setViews() {\n\t\tLog.d(TAG, \"set views\")\n\n\t\tif (!isEdit) {\n\t\t\tbinding.addProAppBar.topAppBar.title =\n\t\t\t\t\"Add Product - ${viewModel.selectedCategory.value}\"\n\n\t\t\tval adapter = AddProductImagesAdapter(requireContext(), imgList)\n\t\t\tbinding.addProImagesRv.adapter = adapter\n\t\t}\n\t\tbinding.addProImagesBtn.setOnClickListener {\n\t\t\tgetImages.launch(\"image/*\")\n\t\t}\n\n\t\tbinding.addProAppBar.topAppBar.setNavigationOnClickListener {\n\t\t\tfindNavController().navigateUp()\n\t\t}\n\n\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\n\t\tsetShoeSizesChips()\n\t\tsetShoeColorsChips()\n\n\t\tbinding.addProErrorTextView.visibility = View.GONE\n\t\tbinding.proNameEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.proPriceEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.proMrpEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.proDescEditText.onFocusChangeListener = focusChangeListener\n\n\t\tbinding.addProBtn.setOnClickListener {\n\t\t\tonAddProduct()\n\t\t\tif (viewModel.errorStatus.value == AddProductViewErrors.NONE) {\n\t\t\t\tviewModel.addProductErrors.observe(viewLifecycleOwner) { err ->\n\t\t\t\t\tif (err == AddProductErrors.NONE) {\n\t\t\t\t\t\tfindNavController().navigate(R.id.action_addProductFragment_to_homeFragment)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun onAddProduct() {\n\t\tval name = binding.proNameEditText.text.toString()\n\t\tval price = binding.proPriceEditText.text.toString().toDoubleOrNull()\n\t\tval mrp = binding.proMrpEditText.text.toString().toDoubleOrNull()\n\t\tval desc = binding.proDescEditText.text.toString()\n\t\tLog.d(\n\t\t\tTAG,\n\t\t\t\"onAddProduct: Add product initiated, $name, $price, $mrp, $desc, $sizeList, $colorsList, $imgList\"\n\t\t)\n\t\tviewModel.submitProduct(\n\t\t\tname, price, mrp, desc, sizeList.toList(), colorsList.toList(), imgList\n\t\t)\n\t}\n\n\tprivate fun setShoeSizesChips(shoeList: List<Int>? = emptyList()) {\n\t\tbinding.addProSizeChipGroup.apply {\n\t\t\tremoveAllViews()\n\t\t\tfor ((_, v) in ShoeSizes) {\n\t\t\t\tval chip = Chip(context)\n\t\t\t\tchip.id = v\n\t\t\t\tchip.tag = v\n\n\t\t\t\tchip.text = \"$v\"\n\t\t\t\tchip.isCheckable = true\n\n\t\t\t\tif (shoeList?.contains(v) == true) {\n\t\t\t\t\tchip.isChecked = true\n\t\t\t\t\tsizeList.add(chip.tag.toString().toInt())\n\t\t\t\t}\n\n\t\t\t\tchip.setOnCheckedChangeListener { buttonView, isChecked ->\n\t\t\t\t\tval tag = buttonView.tag.toString().toInt()\n\t\t\t\t\tif (!isChecked) {\n\t\t\t\t\t\tsizeList.remove(tag)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsizeList.add(tag)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\taddView(chip)\n\t\t\t}\n\t\t\tinvalidate()\n\t\t}\n\t}\n\n\tprivate fun setShoeColorsChips(colorList: List<String>? = emptyList()) {\n\t\tbinding.addProColorChipGroup.apply {\n\t\t\tremoveAllViews()\n\t\t\tvar ind = 1\n\t\t\tfor ((k, v) in ShoeColors) {\n\t\t\t\tval chip = Chip(context)\n\t\t\t\tchip.id = ind\n\t\t\t\tchip.tag = k\n\n\t\t\t\tchip.chipStrokeColor = ColorStateList.valueOf(Color.BLACK)\n\t\t\t\tchip.chipStrokeWidth = TypedValue.applyDimension(\n\t\t\t\t\tTypedValue.COMPLEX_UNIT_DIP,\n\t\t\t\t\t1F,\n\t\t\t\t\tcontext.resources.displayMetrics\n\t\t\t\t)\n\t\t\t\tchip.chipBackgroundColor = ColorStateList.valueOf(Color.parseColor(v))\n\t\t\t\tchip.isCheckable = true\n\n\t\t\t\tif (colorList?.contains(k) == true) {\n\t\t\t\t\tchip.isChecked = true\n\t\t\t\t\tcolorsList.add(chip.tag.toString())\n\t\t\t\t}\n\n\t\t\t\tchip.setOnCheckedChangeListener { buttonView, isChecked ->\n\t\t\t\t\tval tag = buttonView.tag.toString()\n\t\t\t\t\tif (!isChecked) {\n\t\t\t\t\t\tcolorsList.remove(tag)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcolorsList.add(tag)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\taddView(chip)\n\t\t\t\tind++\n\t\t\t}\n\t\t\tinvalidate()\n\t\t}\n\t}\n\n\tprivate fun modifyErrors(err: AddProductViewErrors) {\n\t\twhen (err) {\n\t\t\tAddProductViewErrors.NONE -> binding.addProErrorTextView.visibility = View.GONE\n\t\t\tAddProductViewErrors.EMPTY -> {\n\t\t\t\tbinding.addProErrorTextView.visibility = View.VISIBLE\n\t\t\t\tbinding.addProErrorTextView.text = getString(R.string.add_product_error_string)\n\t\t\t}\n\t\t\tAddProductViewErrors.ERR_PRICE_0 -> {\n\t\t\t\tbinding.addProErrorTextView.visibility = View.VISIBLE\n\t\t\t\tbinding.addProErrorTextView.text = getString(R.string.add_pro_error_price_string)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun makeToast(text: String) {\n\t\tToast.makeText(context, text, Toast.LENGTH_LONG).show()\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/AddProductImagesAdapter.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.content.Context\nimport android.net.Uri\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.recyclerview.widget.RecyclerView\nimport com.bumptech.glide.Glide\nimport com.vishalgaur.shoppingapp.databinding.AddImagesItemBinding\n\nclass AddProductImagesAdapter(private val context: Context, images: List<Uri>) :\n\tRecyclerView.Adapter<AddProductImagesAdapter.ViewHolder>() {\n\n\tprivate var data: MutableList<Uri> = images as MutableList<Uri>\n\n\tinner class ViewHolder(private var binding: AddImagesItemBinding) :\n\t\tRecyclerView.ViewHolder(binding.root) {\n\t\tfun bind(imgUrl: Uri, pos: Int) {\n\t\t\tbinding.addImgCloseBtn.setOnClickListener {\n\t\t\t\tdeleteItem(pos)\n\t\t\t}\n\n\t\t\tif (imgUrl.toString().contains(\"https://\")) {\n\t\t\t\tGlide.with(context)\n\t\t\t\t\t.asBitmap()\n\t\t\t\t\t.load(imgUrl.buildUpon().scheme(\"https\").build())\n\t\t\t\t\t.into(binding.addImagesImageView)\n\t\t\t} else {\n\t\t\t\tbinding.addImagesImageView.setImageURI(imgUrl)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n\t\treturn ViewHolder(\n\t\t\tAddImagesItemBinding.inflate(\n\t\t\t\tLayoutInflater.from(parent.context),\n\t\t\t\tparent,\n\t\t\t\tfalse\n\t\t\t)\n\t\t)\n\t}\n\n\toverride fun onBindViewHolder(holder: ViewHolder, position: Int) {\n\t\tval imageUrl = data[position]\n\t\tholder.bind(imageUrl, position)\n\t}\n\n\toverride fun getItemCount(): Int = data.size\n\n\tfun deleteItem(index: Int) {\n\t\tdata.removeAt(index)\n\t\tnotifyDataSetChanged()\n\t}\n\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/AddressAdapter.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.content.Context\nimport android.util.Log\nimport android.util.TypedValue\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.recyclerview.widget.RecyclerView\nimport com.google.android.material.card.MaterialCardView\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.databinding.LayoutAddressCardBinding\nimport com.vishalgaur.shoppingapp.ui.getCompleteAddress\n\nprivate const val TAG = \"AddressAdapter\"\n\nclass AddressAdapter(\n\tprivate val context: Context,\n\taddresses: List<UserData.Address>,\n\tprivate val isSelect: Boolean\n) :\n\tRecyclerView.Adapter<AddressAdapter.ViewHolder>() {\n\n\tlateinit var onClickListener: OnClickListener\n\tvar data: List<UserData.Address> = addresses\n\n\tvar lastCheckedAddress: String? = null\n\tprivate var lastCheckedCard: MaterialCardView? = null\n\tvar selectedAddressPos = -1\n\n\tinner class ViewHolder(private var binding: LayoutAddressCardBinding) :\n\t\tRecyclerView.ViewHolder(binding.root) {\n\t\tfun bind(address: UserData.Address, position: Int) {\n\t\t\tbinding.addressCard.isChecked = position == selectedAddressPos\n\t\t\tbinding.addressPersonNameTv.text =\n\t\t\t\tcontext.getString(R.string.person_name, address.fName, address.lName)\n\t\t\tbinding.addressCompleteAddressTv.text = getCompleteAddress(address)\n\t\t\tbinding.addressMobileTv.text = address.phoneNumber\n\t\t\tif (isSelect) {\n\t\t\t\tbinding.addressCard.setOnClickListener {\n\t\t\t\t\tonCardClick(position, address.addressId, it as MaterialCardView)\n\t\t\t\t}\n\t\t\t}\n\t\t\tbinding.addressEditBtn.setOnClickListener {\n\t\t\t\tonClickListener.onEditClick(address.addressId)\n\t\t\t}\n\t\t\tbinding.addressDeleteBtn.setOnClickListener {\n\t\t\t\tonClickListener.onDeleteClick(address.addressId)\n\t\t\t\tnotifyDataSetChanged()\n\t\t\t}\n\t\t}\n\t}\n\n\toverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n\t\treturn ViewHolder(\n\t\t\tLayoutAddressCardBinding.inflate(\n\t\t\t\tLayoutInflater.from(parent.context),\n\t\t\t\tparent,\n\t\t\t\tfalse\n\t\t\t)\n\t\t)\n\t}\n\n\toverride fun onBindViewHolder(holder: ViewHolder, position: Int) {\n\t\tholder.bind(data[position], position)\n\t}\n\n\toverride fun getItemCount(): Int = data.size\n\n\tinterface OnClickListener {\n\t\tfun onEditClick(addressId: String)\n\t\tfun onDeleteClick(addressId: String)\n\t}\n\n\tprivate fun onCardClick(position: Int, addressTd: String, card: MaterialCardView) {\n\t\tif (addressTd != lastCheckedAddress) {\n\t\t\tcard.apply {\n\t\t\t\tstrokeColor = context.getColor(R.color.blue_accent_300)\n\t\t\t\tisChecked = true\n\t\t\t\tstrokeWidth = TypedValue.applyDimension(\n\t\t\t\t\tTypedValue.COMPLEX_UNIT_DIP,\n\t\t\t\t\t2F,\n\t\t\t\t\tresources.displayMetrics\n\t\t\t\t).toInt()\n\t\t\t}\n\t\t\tlastCheckedCard?.apply {\n\t\t\t\tstrokeColor = context.getColor(R.color.light_gray)\n\t\t\t\tisChecked = false\n\t\t\t\tstrokeWidth = TypedValue.applyDimension(\n\t\t\t\t\tTypedValue.COMPLEX_UNIT_DIP,\n\t\t\t\t\t1F,\n\t\t\t\t\tresources.displayMetrics\n\t\t\t\t).toInt()\n\t\t\t}\n\n\t\t\tlastCheckedAddress = addressTd\n\t\t\tlastCheckedCard = card\n\t\t\tselectedAddressPos = position\n\t\t\tLog.d(TAG, \"onCardClick: selected address = $addressTd\")\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/AddressFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.os.bundleOf\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport com.google.android.material.dialog.MaterialAlertDialogBuilder\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.databinding.FragmentAddressBinding\nimport com.vishalgaur.shoppingapp.viewModels.HomeViewModel\n\nprivate const val TAG = \"AddressFragment\"\n\nclass AddressFragment : Fragment() {\n\tprivate lateinit var binding: FragmentAddressBinding\n\tprivate lateinit var addressAdapter: AddressAdapter\n\tprivate val viewModel: HomeViewModel by activityViewModels()\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentAddressBinding.inflate(layoutInflater)\n\t\tsetViews()\n\t\tsetObservers()\n\t\treturn binding.root\n\t}\n\n\toverride fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n\t\tsuper.onViewCreated(view, savedInstanceState)\n\t\tviewModel.getUserAddresses()\n\t}\n\n\tprivate fun setViews() {\n\t\tbinding.addressAppBar.topAppBar.title = \"Address\"\n\t\tbinding.addressAppBar.topAppBar.setNavigationOnClickListener { findNavController().navigateUp() }\n\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\tbinding.addressAddBtn.visibility = View.GONE\n\t\tbinding.addressAddBtn.setOnClickListener {\n\t\t\tnavigateToAddEditAddress(false)\n\t\t}\n\t\tbinding.addressEmptyTextView.visibility = View.GONE\n\t\tif (context != null) {\n\t\t\tval addressList = viewModel.userAddresses.value ?: emptyList()\n\t\t\taddressAdapter = AddressAdapter(requireContext(), addressList, false)\n\t\t\taddressAdapter.onClickListener = object : AddressAdapter.OnClickListener {\n\t\t\t\toverride fun onEditClick(addressId: String) {\n\t\t\t\t\tLog.d(TAG, \"onEditAddress: initiated\")\n\t\t\t\t\tnavigateToAddEditAddress(true, addressId)\n\t\t\t\t}\n\n\t\t\t\toverride fun onDeleteClick(addressId: String) {\n\t\t\t\t\tLog.d(TAG, \"onDeleteAddress: initiated\")\n\t\t\t\t\tshowDeleteDialog(addressId)\n\t\t\t\t}\n\t\t\t}\n\t\t\tbinding.addressAddressesRecyclerView.adapter = addressAdapter\n\t\t}\n\t}\n\n\tprivate fun setObservers() {\n\t\tviewModel.dataStatus.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tStoreDataStatus.LOADING -> {\n\t\t\t\t\tbinding.addressEmptyTextView.visibility = View.GONE\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t\t\t}\n\t\t\t\telse -> {\n\t\t\t\t\tbinding.addressAddBtn.visibility = View.VISIBLE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (status != null && status != StoreDataStatus.LOADING) {\n\t\t\t\tviewModel.userAddresses.observe(viewLifecycleOwner) { addressList ->\n\t\t\t\t\tif (addressList.isNotEmpty()) {\n\t\t\t\t\t\taddressAdapter.data = addressList\n\t\t\t\t\t\tbinding.addressAddressesRecyclerView.adapter = addressAdapter\n\t\t\t\t\t\tbinding.addressAddressesRecyclerView.adapter?.notifyDataSetChanged()\n\t\t\t\t\t} else if (addressList.isEmpty()) {\n\t\t\t\t\t\tbinding.addressAddressesRecyclerView.visibility = View.GONE\n\t\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\t\tbinding.addressEmptyTextView.visibility = View.VISIBLE\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbinding.addressAddBtn.visibility = View.VISIBLE\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun showDeleteDialog(addressId: String) {\n\t\tcontext?.let {\n\t\t\tMaterialAlertDialogBuilder(it)\n\t\t\t\t.setTitle(getString(R.string.delete_dialog_title_text))\n\t\t\t\t.setMessage(getString(R.string.delete_address_message_text))\n\t\t\t\t.setNeutralButton(getString(R.string.pro_cat_dialog_cancel_btn)) { dialog, _ ->\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.setPositiveButton(getString(R.string.delete_dialog_delete_btn_text)) { dialog, _ ->\n\t\t\t\t\tviewModel.deleteAddress(addressId)\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.show()\n\t\t}\n\t}\n\n\tprivate fun navigateToAddEditAddress(isEdit: Boolean, addressId: String? = null) {\n\t\tfindNavController().navigate(\n\t\t\tR.id.action_addressFragment_to_addEditAddressFragment,\n\t\t\tbundleOf(\"isEdit\" to isEdit, \"addressId\" to addressId)\n\t\t)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/CartFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport androidx.recyclerview.widget.ConcatAdapter\nimport androidx.recyclerview.widget.RecyclerView\nimport com.google.android.material.dialog.MaterialAlertDialogBuilder\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.databinding.FragmentCartBinding\nimport com.vishalgaur.shoppingapp.databinding.LayoutCircularLoaderBinding\nimport com.vishalgaur.shoppingapp.databinding.LayoutPriceCardBinding\nimport com.vishalgaur.shoppingapp.viewModels.OrderViewModel\n\nprivate const val TAG = \"CartFragment\"\n\nclass CartFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentCartBinding\n\tprivate val orderViewModel: OrderViewModel by activityViewModels()\n\tprivate lateinit var itemsAdapter: CartItemAdapter\n\tprivate lateinit var concatAdapter: ConcatAdapter\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentCartBinding.inflate(layoutInflater)\n\n\t\tsetViews()\n\t\tsetObservers()\n\n\t\treturn binding.root\n\t}\n\n\toverride fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n\t\tsuper.onViewCreated(view, savedInstanceState)\n\t\torderViewModel.getUserLikes()\n\t\torderViewModel.getCartItems()\n\t}\n\n\tprivate fun setViews() {\n\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\tbinding.cartAppBar.topAppBar.title = getString(R.string.cart_fragment_label)\n\t\tbinding.cartEmptyTextView.visibility = View.GONE\n\t\tbinding.cartCheckOutBtn.setOnClickListener {\n\t\t\tnavigateToSelectAddress()\n\t\t}\n\t\tif (context != null) {\n\t\t\tsetItemsAdapter(orderViewModel.cartItems.value)\n\t\t\tconcatAdapter = ConcatAdapter(itemsAdapter, PriceCardAdapter())\n\t\t\tbinding.cartProductsRecyclerView.adapter = concatAdapter\n\t\t}\n\t}\n\n\tprivate fun setObservers() {\n\t\torderViewModel.dataStatus.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tStoreDataStatus.LOADING -> {\n\t\t\t\t\tbinding.cartProductsRecyclerView.visibility = View.GONE\n\t\t\t\t\tbinding.cartCheckOutBtn.visibility = View.GONE\n\t\t\t\t\tbinding.cartEmptyTextView.visibility = View.GONE\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t\t\t}\n\t\t\t\telse -> {\n\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\torderViewModel.dataStatus.observe(viewLifecycleOwner) { status ->\n\t\t\tif (status != null && status != StoreDataStatus.LOADING) {\n\t\t\t\torderViewModel.cartProducts.observe(viewLifecycleOwner) { itemList ->\n\t\t\t\t\tif (itemList.isNotEmpty()) {\n\t\t\t\t\t\tupdateAdapter()\n\t\t\t\t\t\tbinding.cartEmptyTextView.visibility = View.GONE\n\t\t\t\t\t\tbinding.cartProductsRecyclerView.visibility = View.VISIBLE\n\t\t\t\t\t\tbinding.cartCheckOutBtn.visibility = View.VISIBLE\n\t\t\t\t\t} else if (itemList.isEmpty()) {\n\t\t\t\t\t\tbinding.cartProductsRecyclerView.visibility = View.GONE\n\t\t\t\t\t\tbinding.cartCheckOutBtn.visibility = View.GONE\n\t\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\t\tbinding.cartEmptyTextView.visibility = View.VISIBLE\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\torderViewModel.cartItems.observe(viewLifecycleOwner) { items ->\n\t\t\tif (items.isNotEmpty()) {\n\t\t\t\tupdateAdapter()\n\t\t\t}\n\t\t}\n\t\torderViewModel.priceList.observe(viewLifecycleOwner) {\n\t\t\tif (it.isNotEmpty()) {\n\t\t\t\tupdateAdapter()\n\t\t\t}\n\t\t}\n\t\torderViewModel.userLikes.observe(viewLifecycleOwner) {\n\t\t\tif (it.isNotEmpty()) {\n\t\t\t\tupdateAdapter()\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun updateAdapter() {\n\t\tval items = orderViewModel.cartItems.value ?: emptyList()\n\t\tval likeList = orderViewModel.userLikes.value ?: emptyList()\n\t\tval prosList = orderViewModel.cartProducts.value ?: emptyList()\n\t\titemsAdapter.apply {\n\t\t\tdata = items\n\t\t\tproList = prosList\n\t\t\tlikesList = likeList\n\t\t}\n\t\tconcatAdapter = ConcatAdapter(itemsAdapter, PriceCardAdapter())\n\t\tbinding.cartProductsRecyclerView.adapter = concatAdapter\n\t\tbinding.cartProductsRecyclerView.adapter?.notifyDataSetChanged()\n\t}\n\n\tprivate fun setItemsAdapter(itemList: List<UserData.CartItem>?) {\n\t\tval items = itemList ?: emptyList()\n\t\tval likesList = orderViewModel.userLikes.value ?: emptyList()\n\t\tval proList = orderViewModel.cartProducts.value ?: emptyList()\n\t\titemsAdapter = CartItemAdapter(requireContext(), items, proList, likesList)\n\t\titemsAdapter.onClickListener = object : CartItemAdapter.OnClickListener {\n\t\t\toverride fun onLikeClick(productId: String) {\n\t\t\t\tLog.d(TAG, \"onToggle Like Clicked\")\n\t\t\t\torderViewModel.toggleLikeProduct(productId)\n\t\t\t}\n\n\t\t\toverride fun onDeleteClick(itemId: String, itemBinding: LayoutCircularLoaderBinding) {\n\t\t\t\tLog.d(TAG, \"onDelete: initiated\")\n\t\t\t\tshowDeleteDialog(itemId, itemBinding)\n\t\t\t}\n\n\t\t\toverride fun onPlusClick(itemId: String) {\n\t\t\t\tLog.d(TAG, \"onPlus: Increasing quantity\")\n\t\t\t\torderViewModel.setQuantityOfItem(itemId, 1)\n\t\t\t}\n\n\t\t\toverride fun onMinusClick(itemId: String, currQuantity: Int,itemBinding: LayoutCircularLoaderBinding) {\n\t\t\t\tLog.d(TAG, \"onMinus: decreasing quantity\")\n\t\t\t\tif (currQuantity == 1) {\n\t\t\t\t\tshowDeleteDialog(itemId, itemBinding)\n\t\t\t\t} else {\n\t\t\t\t\torderViewModel.setQuantityOfItem(itemId, -1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun navigateToSelectAddress() {\n\t\tfindNavController().navigate(R.id.action_cartFragment_to_selectAddressFragment)\n\t}\n\n\tprivate fun showDeleteDialog(itemId: String, itemBinding: LayoutCircularLoaderBinding) {\n\t\tcontext?.let {\n\t\t\tMaterialAlertDialogBuilder(it)\n\t\t\t\t.setTitle(getString(R.string.delete_dialog_title_text))\n\t\t\t\t.setMessage(getString(R.string.delete_cart_item_message_text))\n\t\t\t\t.setNegativeButton(getString(R.string.pro_cat_dialog_cancel_btn)) { dialog, _ ->\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t\titemBinding.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t}\n\t\t\t\t.setPositiveButton(getString(R.string.delete_dialog_delete_btn_text)) { dialog, _ ->\n\t\t\t\t\torderViewModel.deleteItemFromCart(itemId)\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}.setOnCancelListener {\n\t\t\t\t\titemBinding.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t}\n\t\t\t\t.show()\n\t\t}\n\t}\n\n\tinner class PriceCardAdapter : RecyclerView.Adapter<PriceCardAdapter.ViewHolder>() {\n\n\t\tinner class ViewHolder(private val priceCardBinding: LayoutPriceCardBinding) :\n\t\t\tRecyclerView.ViewHolder(priceCardBinding.root) {\n\t\t\tfun bind() {\n\t\t\t\tpriceCardBinding.priceItemsLabelTv.text = getString(\n\t\t\t\t\tR.string.price_card_items_string,\n\t\t\t\t\torderViewModel.getItemsCount().toString()\n\t\t\t\t)\n\t\t\t\tpriceCardBinding.priceItemsAmountTv.text =\n\t\t\t\t\tgetString(R.string.price_text, orderViewModel.getItemsPriceTotal().toString())\n\t\t\t\tpriceCardBinding.priceShippingAmountTv.text = getString(R.string.price_text, \"0\")\n\t\t\t\tpriceCardBinding.priceChargesAmountTv.text = getString(R.string.price_text, \"0\")\n\t\t\t\tpriceCardBinding.priceTotalAmountTv.text =\n\t\t\t\t\tgetString(R.string.price_text, orderViewModel.getItemsPriceTotal().toString())\n\t\t\t}\n\t\t}\n\n\t\toverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n\t\t\treturn ViewHolder(\n\t\t\t\tLayoutPriceCardBinding.inflate(\n\t\t\t\t\tLayoutInflater.from(parent.context),\n\t\t\t\t\tparent,\n\t\t\t\t\tfalse\n\t\t\t\t)\n\t\t\t)\n\t\t}\n\n\t\toverride fun onBindViewHolder(holder: ViewHolder, position: Int) {\n\t\t\tholder.bind()\n\t\t}\n\n\t\toverride fun getItemCount() = 1\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/CartItemAdapter.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.net.toUri\nimport androidx.recyclerview.widget.RecyclerView\nimport com.bumptech.glide.Glide\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.databinding.CartListItemBinding\nimport com.vishalgaur.shoppingapp.databinding.LayoutCircularLoaderBinding\n\nclass CartItemAdapter(\n\tprivate val context: Context, items: List<UserData.CartItem>,\n\tproducts: List<Product>, userLikes: List<String>\n) : RecyclerView.Adapter<CartItemAdapter.ViewHolder>() {\n\n\tlateinit var onClickListener: OnClickListener\n\tvar data: List<UserData.CartItem> = items\n\tvar proList: List<Product> = products\n\tvar likesList: List<String> = userLikes\n\n\tinner class ViewHolder(private val binding: CartListItemBinding) :\n\t\tRecyclerView.ViewHolder(binding.root) {\n\t\tfun bind(itemData: UserData.CartItem) {\n\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\tval proData = proList.find { it.productId == itemData.productId } ?: Product()\n\t\t\tbinding.cartProductTitleTv.text = proData.name\n\t\t\tbinding.cartProductPriceTv.text =\n\t\t\t\tcontext.getString(R.string.price_text, proData.price.toString())\n\t\t\tif (proData.images.isNotEmpty()) {\n\t\t\t\tval imgUrl = proData.images[0].toUri().buildUpon().scheme(\"https\").build()\n\t\t\t\tGlide.with(context)\n\t\t\t\t\t.asBitmap()\n\t\t\t\t\t.load(imgUrl)\n\t\t\t\t\t.into(binding.productImageView)\n\t\t\t\tbinding.productImageView.clipToOutline = true\n\t\t\t}\n\t\t\tbinding.cartProductQuantityTextView.text = itemData.quantity.toString()\n\n\t\t\tif (likesList.contains(proData.productId)) {\n\t\t\t\tbinding.cartProductLikeBtn.setImageResource(R.drawable.liked_heart_drawable)\n\t\t\t} else {\n\t\t\t\tbinding.cartProductLikeBtn.setImageResource(R.drawable.heart_icon_drawable)\n\t\t\t}\n\n\t\t\tbinding.cartProductLikeBtn.setOnClickListener {\n\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\tif (!likesList.contains(proData.productId)) {\n\t\t\t\t\tbinding.cartProductLikeBtn.setImageResource(R.drawable.liked_heart_drawable)\n\t\t\t\t} else {\n\t\t\t\t\tbinding.cartProductLikeBtn.setImageResource(R.drawable.heart_icon_drawable)\n\t\t\t\t}\n\t\t\t\tonClickListener.onLikeClick(proData.productId)\n\t\t\t}\n\t\t\tbinding.cartProductDeleteBtn.setOnClickListener {\n\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\tonClickListener.onDeleteClick(itemData.itemId, binding.loaderLayout)\n\t\t\t}\n\t\t\tbinding.cartProductPlusBtn.setOnClickListener {\n\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\tonClickListener.onPlusClick(itemData.itemId)\n\t\t\t}\n\t\t\tbinding.cartProductMinusBtn.setOnClickListener {\n\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\tonClickListener.onMinusClick(itemData.itemId, itemData.quantity, binding.loaderLayout)\n\t\t\t}\n\n\t\t}\n\t}\n\n\toverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n\t\treturn ViewHolder(\n\t\t\tCartListItemBinding.inflate(\n\t\t\t\tLayoutInflater.from(parent.context), parent, false\n\t\t\t)\n\t\t)\n\t}\n\n\toverride fun onBindViewHolder(holder: ViewHolder, position: Int) {\n\t\tholder.bind(data[position])\n\t}\n\n\toverride fun getItemCount() = data.size\n\n\tinterface OnClickListener {\n\t\tfun onLikeClick(productId: String)\n\t\tfun onDeleteClick(itemId: String, itemBinding: LayoutCircularLoaderBinding)\n\t\tfun onPlusClick(itemId: String)\n\t\tfun onMinusClick(itemId: String, currQuantity: Int, itemBinding: LayoutCircularLoaderBinding)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/FavoritesFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.os.bundleOf\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.databinding.FragmentFavoritesBinding\nimport com.vishalgaur.shoppingapp.ui.RecyclerViewPaddingItemDecoration\nimport com.vishalgaur.shoppingapp.viewModels.HomeViewModel\n\nprivate const val TAG = \"FavoritesFragment\"\n\nclass FavoritesFragment : Fragment() {\n\tprivate lateinit var binding: FragmentFavoritesBinding\n\tprivate val viewModel: HomeViewModel by activityViewModels()\n\tprivate lateinit var productsAdapter: LikedProductAdapter\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentFavoritesBinding.inflate(layoutInflater)\n\n\t\tsetViews()\n\t\tsetObservers()\n\t\treturn binding.root\n\t}\n\n\tprivate fun setViews() {\n\t\tviewModel.setDataLoading()\n\t\tviewModel.getLikedProducts()\n\t\tbinding.favTopAppBar.topAppBar.title = \"Favorite Products\"\n\t\tbinding.favTopAppBar.topAppBar.setNavigationOnClickListener {\n\t\t\tfindNavController().navigateUp()\n\t\t}\n\t\tbinding.favEmptyTextView.visibility = View.GONE\n\t\tif (context != null) {\n\t\t\tval proList = viewModel.likedProducts.value ?: emptyList()\n\t\t\tproductsAdapter = LikedProductAdapter(proList, requireContext())\n\t\t\tproductsAdapter.onClickListener = object : LikedProductAdapter.OnClickListener {\n\t\t\t\toverride fun onClick(productData: Product) {\n\t\t\t\t\tLog.d(TAG, \"Product: ${productData.productId} clicked\")\n\t\t\t\t\tfindNavController().navigate(\n\t\t\t\t\t\tR.id.action_favoritesFragment_to_productDetailsFragment,\n\t\t\t\t\t\tbundleOf(\"productId\" to productData.productId)\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\toverride fun onDeleteClick(productId: String) {\n\t\t\t\t\tviewModel.toggleLikeByProductId(productId)\n\t\t\t\t}\n\t\t\t}\n\t\t\tbinding.favProductsRecyclerView.apply {\n\t\t\t\tval itemDecoration = RecyclerViewPaddingItemDecoration(requireContext())\n\t\t\t\tif (itemDecorationCount == 0) {\n\t\t\t\t\taddItemDecoration(itemDecoration)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun setObservers() {\n\t\tviewModel.dataStatus.observe(viewLifecycleOwner) { status ->\n\t\t\tif (status == StoreDataStatus.LOADING) {\n\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t\t\tbinding.favEmptyTextView.visibility = View.GONE\n\t\t\t} else if (status != null) {\n\t\t\t\tviewModel.likedProducts.observe(viewLifecycleOwner) {\n\t\t\t\t\tif (it.isNotEmpty()) {\n\t\t\t\t\t\tproductsAdapter.data = viewModel.likedProducts.value!!\n\t\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\t\tproductsAdapter.data = it\n\t\t\t\t\t\tbinding.favProductsRecyclerView.adapter = productsAdapter\n\t\t\t\t\t\tbinding.favProductsRecyclerView.adapter?.apply {\n\t\t\t\t\t\t\tnotifyDataSetChanged()\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (it.isEmpty()) {\n\t\t\t\t\t\tbinding.favEmptyTextView.visibility = View.VISIBLE\n\t\t\t\t\t\tbinding.favProductsRecyclerView.visibility = View.GONE\n\t\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/HomeFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.ViewGroup\nimport android.view.inputmethod.EditorInfo\nimport android.view.inputmethod.InputMethodManager\nimport android.widget.CheckBox\nimport android.widget.ImageView\nimport androidx.core.os.bundleOf\nimport androidx.core.widget.doAfterTextChanged\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport androidx.recyclerview.widget.GridLayoutManager\nimport com.google.android.material.dialog.MaterialAlertDialogBuilder\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.utils.ProductCategories\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.databinding.FragmentHomeBinding\nimport com.vishalgaur.shoppingapp.ui.MyOnFocusChangeListener\nimport com.vishalgaur.shoppingapp.ui.RecyclerViewPaddingItemDecoration\nimport com.vishalgaur.shoppingapp.viewModels.HomeViewModel\nimport kotlinx.coroutines.*\n\n\nprivate const val TAG = \"HomeFragment\"\n\nclass HomeFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentHomeBinding\n\tprivate val viewModel: HomeViewModel by activityViewModels()\n\tprivate val focusChangeListener = MyOnFocusChangeListener()\n\tprivate lateinit var productAdapter: ProductAdapter\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater, container: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\t// Inflate the layout for this fragment\n\t\tbinding = FragmentHomeBinding.inflate(layoutInflater)\n\t\tsetViews()\n\t\tsetObservers()\n\t\treturn binding.root\n\t}\n\n\toverride fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n\t\tsuper.onViewCreated(view, savedInstanceState)\n\t\tviewModel.getUserLikes()\n\t}\n\n//\toverride fun onResume() {\n//\t\tsuper.onResume()\n//\t\tviewModel.getLikedProducts()\n//\t}\n\n\tprivate fun setViews() {\n\t\tsetHomeTopAppBar()\n\t\tif (context != null) {\n\t\t\tsetProductsAdapter(viewModel.products.value)\n\t\t\tbinding.productsRecyclerView.apply {\n\t\t\t\tval gridLayoutManager = GridLayoutManager(context, 2)\n\t\t\t\tgridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {\n\t\t\t\t\toverride fun getSpanSize(position: Int): Int {\n\t\t\t\t\t\treturn when (productAdapter.getItemViewType(position)) {\n\t\t\t\t\t\t\t2 -> 2 //ad\n\t\t\t\t\t\t\telse -> {\n\t\t\t\t\t\t\t\tval proCount = productAdapter.data.count { it is Product }\n\t\t\t\t\t\t\t\tval adCount = productAdapter.data.size - proCount\n\t\t\t\t\t\t\t\tval totalCount = proCount + (adCount * 2)\n\t\t\t\t\t\t\t\t// product, full for last item\n\t\t\t\t\t\t\t\tif (position + 1 == productAdapter.data.size && totalCount % 2 == 1) 2 else 1\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlayoutManager = gridLayoutManager\n\t\t\t\tadapter = productAdapter\n\t\t\t\tval itemDecoration = RecyclerViewPaddingItemDecoration(requireContext())\n\t\t\t\tif (itemDecorationCount == 0) {\n\t\t\t\t\taddItemDecoration(itemDecoration)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!viewModel.isUserASeller) {\n\t\t\tbinding.homeFabAddProduct.visibility = View.GONE\n\t\t}\n\t\tbinding.homeFabAddProduct.setOnClickListener {\n\t\t\tshowDialogWithItems(ProductCategories, 0, false)\n\t\t}\n\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t}\n\n\tprivate fun setObservers() {\n\t\tviewModel.storeDataStatus.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tStoreDataStatus.LOADING -> {\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t\t\t\tbinding.productsRecyclerView.visibility = View.GONE\n\t\t\t\t}\n\t\t\t\telse -> {\n\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (status != null && status != StoreDataStatus.LOADING) {\n\t\t\t\tviewModel.products.observe(viewLifecycleOwner) { productsList ->\n\t\t\t\t\tif (productsList.isNotEmpty()) {\n\t\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\t\tbinding.productsRecyclerView.visibility = View.VISIBLE\n\t\t\t\t\t\tbinding.productsRecyclerView.adapter?.apply {\n\t\t\t\t\t\t\tproductAdapter.data =\n\t\t\t\t\t\t\t\tgetMixedDataList(productsList, getAdsList())\n\t\t\t\t\t\t\tnotifyDataSetChanged()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tviewModel.allProducts.observe(viewLifecycleOwner) {\n\t\t\tif (it.isNotEmpty()) {\n\t\t\t\tviewModel.setDataLoaded()\n\t\t\t\tviewModel.filterProducts(\"All\")\n\t\t\t}\n\t\t}\n\t\tviewModel.userLikes.observe(viewLifecycleOwner) {\n\t\t\tif (it.isNotEmpty()) {\n\t\t\t\tbinding.productsRecyclerView.adapter?.apply {\n\t\t\t\t\tnotifyDataSetChanged()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun performSearch(query: String) {\n\t\tviewModel.filterBySearch(query)\n\t}\n\n\tprivate fun setAppBarItemClicks(menuItem: MenuItem): Boolean {\n\t\treturn when (menuItem.itemId) {\n\t\t\tR.id.home_filter -> {\n\t\t\t\tval extraFilters = arrayOf(\"All\", \"None\")\n\t\t\t\tval categoryList = ProductCategories.plus(extraFilters)\n\t\t\t\tval checkedItem = categoryList.indexOf(viewModel.filterCategory.value)\n\t\t\t\tshowDialogWithItems(categoryList, checkedItem, true)\n\t\t\t\ttrue\n\t\t\t}\n\t\t\tR.id.home_favorites -> {\n\t\t\t\t// show favorite products list\n\t\t\t\tfindNavController().navigate(R.id.action_homeFragment_to_favoritesFragment)\n\t\t\t\ttrue\n\t\t\t}\n\t\t\telse -> false\n\t\t}\n\t}\n\n\tprivate fun setHomeTopAppBar() {\n\t\tvar lastInput = \"\"\n\t\tval debounceJob: Job? = null\n\t\tval uiScope = CoroutineScope(Dispatchers.Main + SupervisorJob())\n\t\tbinding.homeTopAppBar.topAppBar.inflateMenu(R.menu.home_app_bar_menu)\n\t\tif (viewModel.isUserASeller) {\n\t\t\tbinding.homeTopAppBar.topAppBar.menu.removeItem(R.id.home_favorites)\n\t\t}\n\t\tbinding.homeTopAppBar.homeSearchEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.homeTopAppBar.homeSearchEditText.doAfterTextChanged { editable ->\n\t\t\tif (editable != null) {\n\t\t\t\tval newtInput = editable.toString()\n\t\t\t\tdebounceJob?.cancel()\n\t\t\t\tif (lastInput != newtInput) {\n\t\t\t\t\tlastInput = newtInput\n\t\t\t\t\tuiScope.launch {\n\t\t\t\t\t\tdelay(500)\n\t\t\t\t\t\tif (lastInput == newtInput) {\n\t\t\t\t\t\t\tperformSearch(newtInput)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbinding.homeTopAppBar.homeSearchEditText.setOnEditorActionListener { textView, actionId, _ ->\n\t\t\tif (actionId == EditorInfo.IME_ACTION_SEARCH) {\n\t\t\t\ttextView.clearFocus()\n\t\t\t\tval inputManager =\n\t\t\t\t\trequireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager\n\t\t\t\tinputManager.hideSoftInputFromWindow(textView.windowToken, 0)\n\t\t\t\tperformSearch(textView.text.toString())\n\t\t\t\ttrue\n\t\t\t} else {\n\t\t\t\tfalse\n\t\t\t}\n\t\t}\n\t\tbinding.homeTopAppBar.searchOutlinedTextLayout.setEndIconOnClickListener {\n\t\t\tit.clearFocus()\n\t\t\tbinding.homeTopAppBar.homeSearchEditText.setText(\"\")\n\t\t\tval inputManager =\n\t\t\t\trequireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager\n\t\t\tinputManager.hideSoftInputFromWindow(it.windowToken, 0)\n//\t\t\tviewModel.filterProducts(\"All\")\n\t\t}\n\t\tbinding.homeTopAppBar.topAppBar.setOnMenuItemClickListener { menuItem ->\n\t\t\tsetAppBarItemClicks(menuItem)\n\t\t}\n\t}\n\n\tprivate fun setProductsAdapter(productsList: List<Product>?) {\n\t\tval likesList = viewModel.userLikes.value ?: emptyList()\n\t\tproductAdapter = ProductAdapter(productsList ?: emptyList(), likesList, requireContext())\n\t\tproductAdapter.onClickListener = object : ProductAdapter.OnClickListener {\n\t\t\toverride fun onClick(productData: Product) {\n\t\t\t\tfindNavController().navigate(\n\t\t\t\t\tR.id.action_seeProduct,\n\t\t\t\t\tbundleOf(\"productId\" to productData.productId)\n\t\t\t\t)\n\t\t\t}\n\n\t\t\toverride fun onDeleteClick(productData: Product) {\n\t\t\t\tLog.d(TAG, \"onDeleteProduct: initiated for ${productData.productId}\")\n\t\t\t\tshowDeleteDialog(productData.name, productData.productId)\n\t\t\t}\n\n\t\t\toverride fun onEditClick(productId: String) {\n\t\t\t\tLog.d(TAG, \"onEditProduct: initiated for $productId\")\n\t\t\t\tnavigateToAddEditProductFragment(isEdit = true, productId = productId)\n\t\t\t}\n\n\t\t\toverride fun onLikeClick(productId: String) {\n\t\t\t\tLog.d(TAG, \"onToggleLike: initiated for $productId\")\n\t\t\t\tviewModel.toggleLikeByProductId(productId)\n\t\t\t}\n\n\t\t\toverride fun onAddToCartClick(productData: Product) {\n\t\t\t\tLog.d(TAG, \"onToggleCartAddition: initiated\")\n\t\t\t\tviewModel.toggleProductInCart(productData)\n\t\t\t}\n\t\t}\n\t\tproductAdapter.bindImageButtons = object : ProductAdapter.BindImageButtons {\n\t\t\t@SuppressLint(\"ResourceAsColor\")\n\t\t\toverride fun setLikeButton(productId: String, button: CheckBox) {\n\t\t\t\tbutton.isChecked = viewModel.isProductLiked(productId)\n\t\t\t}\n\n\t\t\toverride fun setCartButton(productId: String, imgView: ImageView) {\n\t\t\t\tif (viewModel.isProductInCart(productId)) {\n\t\t\t\t\timgView.setImageResource(R.drawable.ic_remove_shopping_cart_24)\n\t\t\t\t} else {\n\t\t\t\t\timgView.setImageResource(R.drawable.ic_add_shopping_cart_24)\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\n\tprivate fun showDeleteDialog(productName: String, productId: String) {\n\t\tcontext?.let {\n\t\t\tMaterialAlertDialogBuilder(it)\n\t\t\t\t.setTitle(getString(R.string.delete_dialog_title_text))\n\t\t\t\t.setMessage(getString(R.string.delete_dialog_message_text, productName))\n\t\t\t\t.setNegativeButton(getString(R.string.pro_cat_dialog_cancel_btn)) { dialog, _ ->\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.setPositiveButton(getString(R.string.delete_dialog_delete_btn_text)) { dialog, _ ->\n\t\t\t\t\tviewModel.deleteProduct(productId)\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.show()\n\t\t}\n\t}\n\n\tprivate fun showDialogWithItems(\n\t\tcategoryItems: Array<String>,\n\t\tcheckedOption: Int = 0,\n\t\tisFilter: Boolean\n\t) {\n\t\tvar checkedItem = checkedOption\n\t\tcontext?.let {\n\t\t\tMaterialAlertDialogBuilder(it)\n\t\t\t\t.setTitle(getString(R.string.pro_cat_dialog_title))\n\t\t\t\t.setSingleChoiceItems(categoryItems, checkedItem) { _, which ->\n\t\t\t\t\tcheckedItem = which\n\t\t\t\t}\n\t\t\t\t.setNegativeButton(getString(R.string.pro_cat_dialog_cancel_btn)) { dialog, _ ->\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.setPositiveButton(getString(R.string.pro_cat_dialog_ok_btn)) { dialog, _ ->\n\t\t\t\t\tif (checkedItem == -1) {\n\t\t\t\t\t\tdialog.cancel()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (isFilter) {\n\t\t\t\t\t\t\tviewModel.filterProducts(categoryItems[checkedItem])\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnavigateToAddEditProductFragment(\n\t\t\t\t\t\t\t\tisEdit = false,\n\t\t\t\t\t\t\t\tcatName = categoryItems[checkedItem]\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.show()\n\t\t}\n\t}\n\n\tprivate fun navigateToAddEditProductFragment(\n\t\tisEdit: Boolean,\n\t\tcatName: String? = null,\n\t\tproductId: String? = null\n\t) {\n\t\tfindNavController().navigate(\n\t\t\tR.id.action_goto_addProduct,\n\t\t\tbundleOf(\"isEdit\" to isEdit, \"categoryName\" to catName, \"productId\" to productId)\n\t\t)\n\t}\n\n\tprivate fun getMixedDataList(data: List<Product>, adsList: List<Int>): List<Any> {\n\t\tval itemsList = mutableListOf<Any>()\n\t\titemsList.addAll(data.sortedBy { it.productId })\n\t\tvar currPos = 0\n\t\tif (itemsList.size >= 4) {\n\t\t\tadsList.forEach label@{ ad ->\n\t\t\t\tif (itemsList.size > currPos + 1) {\n\t\t\t\t\titemsList.add(currPos, ad)\n\t\t\t\t} else {\n\t\t\t\t\treturn@label\n\t\t\t\t}\n\t\t\t\tcurrPos += 5\n\t\t\t}\n\t\t}\n\t\treturn itemsList\n\t}\n\n\tprivate fun getAdsList(): List<Int> {\n\t\treturn listOf(R.drawable.ad_ex_2, R.drawable.ad_ex_1, R.drawable.ad_ex_3)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/LikedProductAdapter.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.content.Context\nimport android.graphics.Paint\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.net.toUri\nimport androidx.recyclerview.widget.RecyclerView\nimport com.bumptech.glide.Glide\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.databinding.ProductsListItemBinding\nimport com.vishalgaur.shoppingapp.getOfferPercentage\n\nclass LikedProductAdapter(proList: List<Product>, private val context: Context) :\n\tRecyclerView.Adapter<LikedProductAdapter.ViewHolder>() {\n\n\tvar data = proList\n\tlateinit var onClickListener: OnClickListener\n\n\tinner class ViewHolder(private val binding: ProductsListItemBinding) :\n\t\tRecyclerView.ViewHolder(binding.root) {\n\t\tfun bind(productData: Product) {\n\t\t\tbinding.productCard.setOnClickListener {\n\t\t\t\tonClickListener.onClick(productData)\n\t\t\t}\n\t\t\tbinding.productNameTv.text = productData.name\n\t\t\tbinding.productPriceTv.text =\n\t\t\t\tcontext.getString(R.string.pro_details_price_value, productData.price.toString())\n\t\t\tbinding.productRatingBar.rating = productData.rating.toFloat()\n\t\t\tbinding.productActualPriceTv.apply {\n\t\t\t\tpaintFlags = Paint.STRIKE_THRU_TEXT_FLAG\n\t\t\t\ttext = context.getString(\n\t\t\t\t\tR.string.pro_details_actual_strike_value,\n\t\t\t\t\tproductData.mrp.toString()\n\t\t\t\t)\n\t\t\t}\n\t\t\tbinding.productOfferValueTv.text = context.getString(\n\t\t\t\tR.string.pro_offer_precent_text,\n\t\t\t\tgetOfferPercentage(productData.mrp, productData.price).toString()\n\t\t\t)\n\t\t\tif (productData.images.isNotEmpty()) {\n\t\t\t\tval imgUrl = productData.images[0].toUri().buildUpon().scheme(\"https\").build()\n\t\t\t\tGlide.with(context)\n\t\t\t\t\t.asBitmap()\n\t\t\t\t\t.load(imgUrl)\n\t\t\t\t\t.into(binding.productImageView)\n\t\t\t\tbinding.productImageView.clipToOutline = true\n\t\t\t}\n\n\t\t\t//hiding unnecessary button\n\t\t\tbinding.productAddToCartButton.visibility = View.GONE\n\t\t\tbinding.productDeleteButton.visibility = View.GONE\n\t\t\tbinding.productLikeCheckbox.visibility = View.GONE\n\n\t\t\t// setting edit button as delete button\n\t\t\tbinding.productEditButton.setImageResource(R.drawable.ic_delete_24)\n\t\t\tbinding.productEditButton.setOnClickListener {\n\t\t\t\tonClickListener.onDeleteClick(productData.productId)\n\t\t\t\tnotifyDataSetChanged()\n\t\t\t}\n\t\t}\n\t}\n\n\toverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n\t\treturn ViewHolder(\n\t\t\tProductsListItemBinding.inflate(\n\t\t\t\tLayoutInflater.from(parent.context),\n\t\t\t\tparent,\n\t\t\t\tfalse\n\t\t\t)\n\t\t)\n\t}\n\n\toverride fun onBindViewHolder(holder: ViewHolder, position: Int) {\n\t\tholder.bind(data[position])\n\t}\n\n\toverride fun getItemCount() = data.size\n\n\tinterface OnClickListener {\n\t\tfun onClick(productData: Product)\n\t\tfun onDeleteClick(productId: String)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/MainActivity.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.View\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.navigation.fragment.NavHostFragment\nimport androidx.navigation.ui.NavigationUI\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.databinding.ActivityMainBinding\n\nprivate const val TAG = \"MainActivity\"\n\nclass MainActivity : AppCompatActivity() {\n\n\tprivate lateinit var binding: ActivityMainBinding\n\n\toverride fun onCreate(savedInstanceState: Bundle?) {\n\t\tLog.d(TAG, \"onCreate starts\")\n\t\tsuper.onCreate(savedInstanceState)\n\t\tbinding = ActivityMainBinding.inflate(layoutInflater)\n\t\tsetContentView(binding.root)\n\n\t\t// Bottom Navigation\n\t\tsetUpNav()\n\t}\n\n\tprivate fun setUpNav() {\n\t\tval navFragment =\n\t\t\tsupportFragmentManager.findFragmentById(R.id.home_nav_host_fragment) as NavHostFragment\n\t\tNavigationUI.setupWithNavController(binding.homeBottomNavigation, navFragment.navController)\n\n\t\tnavFragment.navController.addOnDestinationChangedListener { _, destination, _ ->\n\t\t\twhen (destination.id) {\n\t\t\t\tR.id.homeFragment -> setBottomNavVisibility(View.VISIBLE)\n\t\t\t\tR.id.cartFragment -> setBottomNavVisibility(View.VISIBLE)\n\t\t\t\tR.id.accountFragment -> setBottomNavVisibility(View.VISIBLE)\n\t\t\t\tR.id.ordersFragment -> setBottomNavVisibility(View.VISIBLE)\n\t\t\t\tR.id.orderSuccessFragment -> setBottomNavVisibility(View.VISIBLE)\n\t\t\t\telse -> setBottomNavVisibility(View.GONE)\n\t\t\t}\n\t\t}\n\n\t\tval sessionManager = ShoppingAppSessionManager(this.applicationContext)\n\t\tif (sessionManager.isUserSeller()) {\n\t\t\tbinding.homeBottomNavigation.menu.removeItem(R.id.cartFragment)\n\t\t}else {\n\t\t\tbinding.homeBottomNavigation.menu.removeItem(R.id.ordersFragment)\n\t\t}\n\t}\n\n\tprivate fun setBottomNavVisibility(visibility: Int) {\n\t\tbinding.homeBottomNavigation.visibility = visibility\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/OrderDetailsFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport com.google.android.material.dialog.MaterialAlertDialogBuilder\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.OrderStatus\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.databinding.FragmentOrderDetailsBinding\nimport com.vishalgaur.shoppingapp.ui.getCompleteAddress\nimport com.vishalgaur.shoppingapp.viewModels.HomeViewModel\nimport java.time.Month\nimport java.util.*\n\nclass OrderDetailsFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentOrderDetailsBinding\n\tprivate val viewModel: HomeViewModel by activityViewModels()\n\tprivate lateinit var orderId: String\n\tprivate lateinit var productsAdapter: OrderProductsAdapter\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentOrderDetailsBinding.inflate(layoutInflater)\n\t\torderId = arguments?.getString(\"orderId\").toString()\n\t\tviewModel.getOrderDetailsByOrderId(orderId)\n\t\tsetViews()\n\t\tsetObservers()\n\t\treturn binding.root\n\t}\n\n\tprivate fun setViews() {\n\t\tbinding.orderDetailAppBar.topAppBar.title = getString(R.string.order_details_fragment_title)\n\t\tbinding.orderDetailAppBar.topAppBar.setNavigationOnClickListener { findNavController().navigateUp() }\n\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\tbinding.orderDetailsConstraintGroup.visibility = View.GONE\n\n\t\tif (context != null) {\n\t\t\tsetProductsAdapter(viewModel.selectedOrder.value?.items)\n\t\t\tbinding.orderDetailsProRecyclerView.adapter = productsAdapter\n\t\t}\n\t}\n\n\tprivate fun setObservers() {\n\t\tviewModel.storeDataStatus.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tStoreDataStatus.LOADING -> {\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t\t\t\tbinding.orderDetailsConstraintGroup.visibility = View.GONE\n\t\t\t\t}\n\t\t\t\telse -> {\n\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tviewModel.selectedOrder.observe(viewLifecycleOwner) { orderData ->\n\t\t\tif (orderData != null) {\n\t\t\t\tbinding.orderDetailsConstraintGroup.visibility = View.VISIBLE\n\t\t\t\tsetAllViews(orderData)\n\t\t\t\tval items = orderData.items\n\t\t\t\tval likeList = viewModel.userLikes.value ?: emptyList()\n\t\t\t\tval prosList = viewModel.orderProducts.value ?: emptyList()\n\t\t\t\tproductsAdapter.apply {\n\t\t\t\t\tdata = items\n\t\t\t\t\tproList = prosList\n\t\t\t\t\tlikesList = likeList\n\t\t\t\t}\n\t\t\t\tbinding.orderDetailsProRecyclerView.adapter = productsAdapter\n\t\t\t\tbinding.orderDetailsProRecyclerView.adapter?.notifyDataSetChanged()\n\t\t\t} else {\n\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t\t\tbinding.orderDetailsConstraintGroup.visibility = View.GONE\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun setAllViews(orderData: UserData.OrderItem) {\n\t\tLog.d(\"OrderDetail\", \"set all views called\")\n\t\tif (viewModel.isUserASeller) {\n\t\t\tbinding.orderChangeStatusBtn.visibility = View.VISIBLE\n\t\t\tbinding.orderChangeStatusBtn.setOnClickListener {\n\t\t\t\tval statusString = orderData.status.split(\" \")[0]\n\t\t\t\tval pos = OrderStatus.values().map { it.name }.indexOf(statusString)\n\t\t\t\tshowDialogWithItems(pos, orderData.orderId)\n\t\t\t}\n\t\t} else {\n\t\t\tbinding.orderChangeStatusBtn.visibility = View.GONE\n\t\t}\n\t\tval calendar = Calendar.getInstance()\n\t\tcalendar.time = orderData.orderDate\n\t\tbinding.orderDetailsShippingAddLayout.shipDateValueTv.text = getString(\n\t\t\tR.string.order_date_text,\n\t\t\tMonth.values()[(calendar.get(Calendar.MONTH))].name,\n\t\t\tcalendar.get(Calendar.DAY_OF_MONTH).toString(),\n\t\t\tcalendar.get(Calendar.YEAR).toString()\n\t\t)\n\t\tbinding.orderDetailsShippingAddLayout.shipAddValueTv.text =\n\t\t\tgetCompleteAddress(orderData.deliveryAddress)\n\t\tbinding.orderDetailsShippingAddLayout.shipCurrStatusValueTv.text = orderData.status\n\n\t\tsetPriceCard(orderData)\n\t}\n\n\tprivate fun setPriceCard(orderData: UserData.OrderItem) {\n\t\tbinding.orderDetailsPaymentLayout.priceItemsLabelTv.text = getString(\n\t\t\tR.string.price_card_items_string,\n\t\t\tgetItemsCount(orderData.items).toString()\n\t\t)\n\t\tval itemsPriceTotal = getItemsPriceTotal(orderData.itemsPrices, orderData.items)\n\t\tbinding.orderDetailsPaymentLayout.priceItemsAmountTv.text =\n\t\t\tgetString(\n\t\t\t\tR.string.price_text,\n\t\t\t\titemsPriceTotal.toString()\n\t\t\t)\n\t\tbinding.orderDetailsPaymentLayout.priceShippingAmountTv.text =\n\t\t\tgetString(R.string.price_text, \"0\")\n\t\tbinding.orderDetailsPaymentLayout.priceChargesAmountTv.text =\n\t\t\tgetString(R.string.price_text, \"0\")\n\t\tbinding.orderDetailsPaymentLayout.priceTotalAmountTv.text =\n\t\t\tgetString(R.string.price_text, (itemsPriceTotal + orderData.shippingCharges).toString())\n\t}\n\n\tprivate fun setProductsAdapter(itemsList: List<UserData.CartItem>?) {\n\t\tval items = itemsList ?: emptyList()\n\t\tval likesList = viewModel.userLikes.value ?: emptyList()\n\t\tval proList = viewModel.orderProducts.value ?: emptyList()\n\t\tproductsAdapter = OrderProductsAdapter(requireContext(), items, proList, likesList)\n\t}\n\n\tprivate fun showDialogWithItems(checkedOption: Int = 0, orderId: String) {\n\t\tval categoryItems: Array<String> = OrderStatus.values().map { it.name }.toTypedArray()\n\t\tvar checkedItem = checkedOption\n\t\tcontext?.let {\n\t\t\tMaterialAlertDialogBuilder(it)\n\t\t\t\t.setTitle(getString(R.string.status_dialog_title))\n\t\t\t\t.setSingleChoiceItems(categoryItems, checkedItem) { _, which ->\n\t\t\t\t\tcheckedItem = which\n\t\t\t\t}\n\t\t\t\t.setNegativeButton(getString(R.string.pro_cat_dialog_cancel_btn)) { dialog, _ ->\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.setPositiveButton(getString(R.string.pro_cat_dialog_ok_btn)) { dialog, _ ->\n\t\t\t\t\tif (checkedItem == -1) {\n\t\t\t\t\t\tdialog.cancel()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tviewModel.onSetStatusOfOrder(orderId, categoryItems[checkedItem])\n\t\t\t\t\t}\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.show()\n\t\t}\n\t}\n\n\tprivate fun getItemsCount(cartItems: List<UserData.CartItem>): Int {\n\t\tvar totalCount = 0\n\t\tcartItems.forEach {\n\t\t\ttotalCount += it.quantity\n\t\t}\n\t\treturn totalCount\n\t}\n\n\tprivate fun getItemsPriceTotal(\n\t\tpriceList: Map<String, Double>,\n\t\tcartItems: List<UserData.CartItem>\n\t): Double {\n\t\tvar totalPrice = 0.0\n\t\tpriceList.forEach { (itemId, price) ->\n\t\t\ttotalPrice += price * (cartItems.find { it.itemId == itemId }?.quantity ?: 1)\n\t\t}\n\t\treturn totalPrice\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/OrderProductsAdapter.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.net.toUri\nimport androidx.recyclerview.widget.RecyclerView\nimport com.bumptech.glide.Glide\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.databinding.CartListItemBinding\n\nclass OrderProductsAdapter(\n\tprivate val context: Context, items: List<UserData.CartItem>,\n\tproducts: List<Product>, userLikes: List<String>\n) : RecyclerView.Adapter<OrderProductsAdapter.ViewHolder>() {\n\n\tvar data: List<UserData.CartItem> = items\n\tvar proList: List<Product> = products\n\tvar likesList: List<String> = userLikes\n\n\tinner class ViewHolder(private val binding: CartListItemBinding) :\n\t\tRecyclerView.ViewHolder(binding.root) {\n\t\tfun bind(itemData: UserData.CartItem) {\n\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\tval proData = proList.find { it.productId == itemData.productId } ?: Product()\n\t\t\tbinding.cartProductTitleTv.text = proData.name\n\t\t\tbinding.cartProductPriceTv.text =\n\t\t\t\tcontext.getString(R.string.price_text, proData.price.toString())\n\t\t\tif (proData.images.isNotEmpty()) {\n\t\t\t\tval imgUrl = proData.images[0].toUri().buildUpon().scheme(\"https\").build()\n\t\t\t\tGlide.with(context)\n\t\t\t\t\t.asBitmap()\n\t\t\t\t\t.load(imgUrl)\n\t\t\t\t\t.into(binding.productImageView)\n\t\t\t\tbinding.productImageView.clipToOutline = true\n\t\t\t}\n\t\t\tbinding.cartProductDeleteBtn.visibility = View.GONE\n\t\t\tbinding.cartProductQuantityButtonsLayout.visibility = View.GONE\n\t\t\tbinding.cartProductLikeBtn.visibility = View.GONE\n\t\t}\n\t}\n\n\toverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n\t\treturn ViewHolder(\n\t\t\tCartListItemBinding.inflate(\n\t\t\t\tLayoutInflater.from(parent.context),\n\t\t\t\tparent,\n\t\t\t\tfalse\n\t\t\t)\n\t\t)\n\t}\n\n\toverride fun onBindViewHolder(holder: ViewHolder, position: Int) {\n\t\tholder.bind(data[position])\n\t}\n\n\toverride fun getItemCount() = data.size\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/OrderSuccessFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.os.CountDownTimer\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.databinding.FragmentOrderSuccessBinding\nimport com.vishalgaur.shoppingapp.viewModels.OrderViewModel\n\nclass OrderSuccessFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentOrderSuccessBinding\n\tprivate val orderViewModel: OrderViewModel by activityViewModels()\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentOrderSuccessBinding.inflate(layoutInflater)\n\n\t\tbinding.loaderLayout.loaderCard.visibility = View.VISIBLE\n\t\tbinding.loaderLayout.loadingMessage.text = getString(R.string.process_order_msg)\n\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\tbinding.orderConstraintGroup.visibility = View.GONE\n\t\tsetObservers()\n\t\treturn binding.root\n\t}\n\n\toverride fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n\t\tsuper.onViewCreated(view, savedInstanceState)\n\n\t\tbinding.backToHomeBtn.setOnClickListener {\n\t\t\tfindNavController().navigate(R.id.action_orderSuccessFragment_to_homeFragment)\n\t\t}\n\t}\n\n\tprivate fun setObservers() {\n\t\torderViewModel.orderStatus.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tStoreDataStatus.LOADING -> {\n\t\t\t\t\tbinding.loaderLayout.loaderCard.visibility = View.VISIBLE\n\t\t\t\t}\n\t\t\t\telse -> {\n\t\t\t\t\tbinding.orderConstraintGroup.visibility = View.VISIBLE\n\t\t\t\t\tbinding.loaderLayout.loaderCard.visibility = View.GONE\n\t\t\t\t\tbinding.redirectHomeTimerTv.text =\n\t\t\t\t\t\tgetString(R.string.redirect_home_timer_text, \"5\")\n\t\t\t\t\tcountDownTimer.start()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate val countDownTimer = object : CountDownTimer(5000, 1000) {\n\t\toverride fun onTick(millisUntilFinished: Long) {\n\t\t\tval sec = millisUntilFinished / 1000\n\t\t\tbinding.redirectHomeTimerTv.text =\n\t\t\t\tgetString(R.string.redirect_home_timer_text, sec.toString())\n\t\t}\n\n\t\toverride fun onFinish() {\n\t\t\tfindNavController().navigate(R.id.action_orderSuccessFragment_to_homeFragment)\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/OrdersAdapter.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.recyclerview.widget.RecyclerView\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.databinding.LayoutOrderSummaryCardBinding\nimport java.time.Month\nimport java.util.*\n\nclass OrdersAdapter(ordersList: List<UserData.OrderItem>, private val context: Context) :\n\tRecyclerView.Adapter<OrdersAdapter.ViewHolder>() {\n\n\tlateinit var onClickListener: OnClickListener\n\tvar data: List<UserData.OrderItem> = ordersList\n\n\tinner class ViewHolder(private val binding: LayoutOrderSummaryCardBinding) :\n\t\tRecyclerView.ViewHolder(binding.root) {\n\t\tfun bind(orderData: UserData.OrderItem) {\n\t\t\tbinding.orderSummaryCard.setOnClickListener { onClickListener.onCardClick(orderData.orderId) }\n\t\t\tbinding.orderSummaryIdTv.text = orderData.orderId\n\t\t\tval calendar = Calendar.getInstance()\n\t\t\tcalendar.time = orderData.orderDate\n\t\t\tbinding.orderSummaryDateTv.text =\n\t\t\t\tcontext.getString(\n\t\t\t\t\tR.string.order_date_text,\n\t\t\t\t\tMonth.values()[(calendar.get(Calendar.MONTH))].name,\n\t\t\t\t\tcalendar.get(Calendar.DAY_OF_MONTH).toString(),\n\t\t\t\t\tcalendar.get(Calendar.YEAR).toString()\n\t\t\t\t)\n\t\t\tbinding.orderSummaryStatusValueTv.text = orderData.status\n\t\t\tval totalItems = orderData.items.map { it.quantity }.sum()\n\t\t\tbinding.orderSummaryItemsCountTv.text =\n\t\t\t\tcontext.getString(R.string.order_items_count_text, totalItems.toString())\n\t\t\tvar totalAmount = 0.0\n\t\t\torderData.itemsPrices.forEach { (itemId, price) ->\n\t\t\t\ttotalAmount += price * (orderData.items.find { it.itemId == itemId }?.quantity ?: 1)\n\t\t\t}\n\t\t\tbinding.orderSummaryTotalAmountTv.text =\n\t\t\t\tcontext.getString(R.string.price_text, totalAmount.toString())\n\t\t}\n\t}\n\n\toverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n\t\treturn ViewHolder(\n\t\t\tLayoutOrderSummaryCardBinding.inflate(\n\t\t\t\tLayoutInflater.from(parent.context),\n\t\t\t\tparent,\n\t\t\t\tfalse\n\t\t\t)\n\t\t)\n\t}\n\n\toverride fun onBindViewHolder(holder: ViewHolder, position: Int) {\n\t\tholder.bind(data[position])\n\t}\n\n\toverride fun getItemCount() = data.size\n\n\tinterface OnClickListener {\n\t\tfun onCardClick(orderId: String)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/OrdersFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.os.bundleOf\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.databinding.FragmentOrdersBinding\nimport com.vishalgaur.shoppingapp.viewModels.HomeViewModel\n\nprivate const val TAG = \"OrdersFragment\"\n\nclass OrdersFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentOrdersBinding\n\tprivate lateinit var ordersAdapter: OrdersAdapter\n\tprivate val viewModel: HomeViewModel by activityViewModels()\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentOrdersBinding.inflate(layoutInflater)\n\n\t\tsetViews()\n\t\tsetObservers()\n\n\t\treturn binding.root\n\t}\n\n\toverride fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n\t\tsuper.onViewCreated(view, savedInstanceState)\n\t\tviewModel.getAllOrders()\n\t}\n\n\tprivate fun setViews() {\n\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\tbinding.ordersAppBar.topAppBar.title = getString(R.string.orders_fragment_title)\n\t\tbinding.ordersAppBar.topAppBar.setNavigationOnClickListener {\n\t\t\tfindNavController().navigateUp()\n\t\t}\n\t\tbinding.ordersEmptyTextView.visibility = View.GONE\n\t\tif (context != null) {\n\t\t\tordersAdapter = OrdersAdapter(emptyList(), requireContext())\n\t\t\tordersAdapter.onClickListener = object : OrdersAdapter.OnClickListener {\n\t\t\t\toverride fun onCardClick(orderId: String) {\n\t\t\t\t\tLog.d(TAG, \"onOrderSummaryClick: Getting order details\")\n\t\t\t\t\tfindNavController().navigate(\n\t\t\t\t\t\tR.id.action_ordersFragment_to_orderDetailsFragment,\n\t\t\t\t\t\tbundleOf(\"orderId\" to orderId)\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t\tbinding.orderAllOrdersRecyclerView.adapter = ordersAdapter\n\t\t}\n\t}\n\n\tprivate fun setObservers() {\n\t\tviewModel.storeDataStatus.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tStoreDataStatus.LOADING -> {\n\t\t\t\t\tbinding.orderAllOrdersRecyclerView.visibility = View.GONE\n\t\t\t\t\tbinding.ordersEmptyTextView.visibility = View.GONE\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t\t\t}\n\t\t\t\telse -> {\n\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (status != null && status != StoreDataStatus.LOADING) {\n\t\t\t\tviewModel.userOrders.observe(viewLifecycleOwner) { orders ->\n\t\t\t\t\tif (orders.isNotEmpty()) {\n\t\t\t\t\t\tordersAdapter.data = orders.sortedByDescending { it.orderDate }\n\t\t\t\t\t\tbinding.orderAllOrdersRecyclerView.adapter?.notifyDataSetChanged()\n\t\t\t\t\t\tbinding.orderAllOrdersRecyclerView.visibility = View.VISIBLE\n\t\t\t\t\t} else if (orders.isEmpty()) {\n\t\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\t\tbinding.ordersEmptyTextView.visibility = View.VISIBLE\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/PayByAdapter.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.annotation.SuppressLint\nimport android.util.Log\nimport android.util.TypedValue\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.recyclerview.widget.RecyclerView\nimport com.google.android.material.card.MaterialCardView\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.databinding.LayoutListItemBinding\n\nprivate const val TAG = \"PayByAdapter\"\n\nclass PayByAdapter(private val data: List<String>) :\n\tRecyclerView.Adapter<PayByAdapter.ViewHolder>() {\n\n\tvar lastCheckedMethod: String? = null\n\tprivate var lastCheckedCard: MaterialCardView? = null\n\tprivate var selectedMethodPos = -1\n\n\tinner class ViewHolder(binding: LayoutListItemBinding) :\n\t\tRecyclerView.ViewHolder(binding.root) {\n\t\tval textView = binding.itemTitleTextView\n\t\tval cardView = binding.itemCard\n\t}\n\n\toverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n\t\treturn ViewHolder(\n\t\t\tLayoutListItemBinding.inflate(\n\t\t\t\tLayoutInflater.from(parent.context),\n\t\t\t\tparent,\n\t\t\t\tfalse\n\t\t\t)\n\t\t)\n\t}\n\n\t@SuppressLint(\"ResourceAsColor\")\n\toverride fun onBindViewHolder(holder: ViewHolder, position: Int) {\n\t\tval title = data[position]\n\t\tholder.apply {\n\t\t\ttextView.text = title\n\t\t\tcardView.setOnClickListener {\n\t\t\t\tonCardClick(position, data[position], it as MaterialCardView)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride fun getItemCount() = data.size\n\n\tprivate fun onCardClick(position: Int, method: String, cardView: MaterialCardView) {\n\t\tif (method != lastCheckedMethod) {\n\t\t\tcardView.apply {\n\t\t\t\tstrokeColor = context.getColor(R.color.blue_accent_300)\n\t\t\t\tisChecked = true\n\t\t\t\tstrokeWidth = TypedValue.applyDimension(\n\t\t\t\t\tTypedValue.COMPLEX_UNIT_DIP,\n\t\t\t\t\t2F,\n\t\t\t\t\tresources.displayMetrics\n\t\t\t\t).toInt()\n\t\t\t}\n\n\t\t\tlastCheckedCard?.apply {\n\t\t\t\tstrokeColor = context.getColor(R.color.light_gray)\n\t\t\t\tisChecked = false\n\t\t\t\tstrokeWidth = TypedValue.applyDimension(\n\t\t\t\t\tTypedValue.COMPLEX_UNIT_DIP,\n\t\t\t\t\t1F,\n\t\t\t\t\tresources.displayMetrics\n\t\t\t\t).toInt()\n\t\t\t}\n\n\t\t\tlastCheckedCard = cardView\n\t\t\tlastCheckedMethod = method\n\t\t\tselectedMethodPos = position\n\t\t\tLog.d(TAG, \"onSelectMethod: Selected Method = $lastCheckedMethod\")\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/ProductAdapter.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.content.Context\nimport android.graphics.Paint\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.CheckBox\nimport android.widget.ImageView\nimport androidx.core.net.toUri\nimport androidx.recyclerview.widget.RecyclerView\nimport com.bumptech.glide.Glide\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.databinding.LayoutHomeAdBinding\nimport com.vishalgaur.shoppingapp.databinding.ProductsListItemBinding\nimport com.vishalgaur.shoppingapp.getOfferPercentage\n\nclass ProductAdapter(proList: List<Any>, userLikes: List<String>, private val context: Context) :\n\tRecyclerView.Adapter<RecyclerView.ViewHolder>() {\n\n\tvar data = proList\n\tvar likesList = userLikes\n\n\tlateinit var onClickListener: OnClickListener\n\tlateinit var bindImageButtons: BindImageButtons\n\tprivate val sessionManager = ShoppingAppSessionManager(context)\n\n\tinner class ItemViewHolder(binding: ProductsListItemBinding) :\n\t\tRecyclerView.ViewHolder(binding.root) {\n\t\tprivate val proName = binding.productNameTv\n\t\tprivate val proPrice = binding.productPriceTv\n\t\tprivate val productCard = binding.productCard\n\t\tprivate val productImage = binding.productImageView\n\t\tprivate val proDeleteButton = binding.productDeleteButton\n\t\tprivate val proEditBtn = binding.productEditButton\n\t\tprivate val proMrp = binding.productActualPriceTv\n\t\tprivate val proOffer = binding.productOfferValueTv\n\t\tprivate val proRatingBar = binding.productRatingBar\n\t\tprivate val proLikeButton = binding.productLikeCheckbox\n\t\tprivate val proCartButton = binding.productAddToCartButton\n\n\t\tfun bind(productData: Product) {\n\t\t\tproductCard.setOnClickListener {\n\t\t\t\tonClickListener.onClick(productData)\n\t\t\t}\n\t\t\tproName.text = productData.name\n\t\t\tproPrice.text =\n\t\t\t\tcontext.getString(R.string.pro_details_price_value, productData.price.toString())\n\t\t\tproRatingBar.rating = productData.rating.toFloat()\n\t\t\tproMrp.paintFlags = Paint.STRIKE_THRU_TEXT_FLAG\n\t\t\tproMrp.text =\n\t\t\t\tcontext.getString(\n\t\t\t\t\tR.string.pro_details_actual_strike_value,\n\t\t\t\t\tproductData.mrp.toString()\n\t\t\t\t)\n\t\t\tproOffer.text = context.getString(\n\t\t\t\tR.string.pro_offer_precent_text,\n\t\t\t\tgetOfferPercentage(productData.mrp, productData.price).toString()\n\t\t\t)\n\t\t\tif (productData.images.isNotEmpty()) {\n\t\t\t\tval imgUrl = productData.images[0].toUri().buildUpon().scheme(\"https\").build()\n\t\t\t\tGlide.with(context)\n\t\t\t\t\t.asBitmap()\n\t\t\t\t\t.load(imgUrl)\n\t\t\t\t\t.into(productImage)\n\n\t\t\t\tproductImage.clipToOutline = true\n\t\t\t}\n\n\t\t\tproLikeButton.isChecked = likesList.contains(productData.productId)\n\n\t\t\tif (sessionManager.isUserSeller()) {\n\t\t\t\tproLikeButton.visibility = View.GONE\n\t\t\t\tproCartButton.visibility = View.GONE\n\t\t\t\tproEditBtn.setOnClickListener {\n\t\t\t\t\tonClickListener.onEditClick(productData.productId)\n\t\t\t\t}\n\n\t\t\t\tproDeleteButton.setOnClickListener {\n\t\t\t\t\tonClickListener.onDeleteClick(productData)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tproEditBtn.visibility = View.GONE\n\t\t\t\tproDeleteButton.visibility = View.GONE\n\t\t\t\tbindImageButtons.setLikeButton(productData.productId, proLikeButton)\n\t\t\t\tbindImageButtons.setCartButton(productData.productId, proCartButton)\n\t\t\t\tproLikeButton.setOnCheckedChangeListener { _, _ ->\n\n\n\t\t\t\t}\n\t\t\t\tproLikeButton.setOnClickListener {\n\t\t\t\t\tonClickListener.onLikeClick(productData.productId)\n\t\t\t\t}\n\t\t\t\tproCartButton.setOnClickListener {\n\t\t\t\t\tonClickListener.onAddToCartClick(productData)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tinner class AdViewHolder(binding: LayoutHomeAdBinding) : RecyclerView.ViewHolder(binding.root) {\n\t\tval adImageView: ImageView = binding.adImageView\n\t}\n\n\toverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {\n\t\treturn when (viewType) {\n\t\t\tVIEW_TYPE_AD -> AdViewHolder(\n\t\t\t\tLayoutHomeAdBinding.inflate(\n\t\t\t\t\tLayoutInflater.from(parent.context),\n\t\t\t\t\tparent,\n\t\t\t\t\tfalse\n\t\t\t\t)\n\t\t\t)\n\t\t\telse -> ItemViewHolder(\n\t\t\t\tProductsListItemBinding.inflate(\n\t\t\t\t\tLayoutInflater.from(parent.context),\n\t\t\t\t\tparent,\n\t\t\t\t\tfalse\n\t\t\t\t)\n\t\t\t)\n\t\t}\n\t}\n\n\toverride fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {\n\t\twhen (val proData = data[position]) {\n\t\t\tis Int -> (holder as AdViewHolder).adImageView.setImageResource(proData)\n\t\t\tis Product -> (holder as ItemViewHolder).bind(proData)\n\t\t}\n\t}\n\n\toverride fun getItemCount(): Int = data.size\n\n\tcompanion object {\n\t\tconst val VIEW_TYPE_PRODUCT = 1\n\t\tconst val VIEW_TYPE_AD = 2\n\t}\n\n\toverride fun getItemViewType(position: Int): Int {\n\t\treturn when (data[position]) {\n\t\t\tis Int -> VIEW_TYPE_AD\n\t\t\tis Product -> VIEW_TYPE_PRODUCT\n\t\t\telse -> VIEW_TYPE_PRODUCT\n\t\t}\n\t}\n\n\tinterface BindImageButtons {\n\t\tfun setLikeButton(productId: String, button: CheckBox)\n\t\tfun setCartButton(productId: String, imgView: ImageView)\n\t}\n\n\tinterface OnClickListener {\n\t\tfun onClick(productData: Product)\n\t\tfun onDeleteClick(productData: Product)\n\t\tfun onEditClick(productId: String) {}\n\t\tfun onLikeClick(productId: String) {}\n\t\tfun onAddToCartClick(productData: Product) {}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/ProductDetailsFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.annotation.SuppressLint\nimport android.app.Application\nimport android.content.res.ColorStateList\nimport android.graphics.Color\nimport android.graphics.PorterDuff\nimport android.graphics.Typeface\nimport android.os.Bundle\nimport android.util.Log\nimport android.util.TypedValue\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.RadioButton\nimport android.widget.Toast\nimport androidx.core.content.ContextCompat\nimport androidx.core.content.res.ResourcesCompat\nimport androidx.core.view.setMargins\nimport androidx.fragment.app.Fragment\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.ViewModelProvider\nimport androidx.navigation.fragment.findNavController\nimport androidx.recyclerview.widget.PagerSnapHelper\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.utils.AddObjectStatus\nimport com.vishalgaur.shoppingapp.data.utils.ShoeColors\nimport com.vishalgaur.shoppingapp.data.utils.ShoeSizes\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.databinding.FragmentProductDetailsBinding\nimport com.vishalgaur.shoppingapp.ui.AddItemErrors\nimport com.vishalgaur.shoppingapp.ui.DotsIndicatorDecoration\nimport com.vishalgaur.shoppingapp.viewModels.ProductViewModel\n\nclass ProductDetailsFragment : Fragment() {\n\n\tinner class ProductViewModelFactory(\n\t\tprivate val productId: String,\n\t\tprivate val application: Application\n\t) : ViewModelProvider.Factory {\n\t\t@Suppress(\"UNCHECKED_CAST\")\n\t\toverride fun <T : ViewModel?> create(modelClass: Class<T>): T {\n\t\t\tif (modelClass.isAssignableFrom(ProductViewModel::class.java)) {\n\t\t\t\treturn ProductViewModel(productId, application) as T\n\t\t\t}\n\t\t\tthrow IllegalArgumentException(\"Unknown ViewModel Class\")\n\t\t}\n\t}\n\n\tprivate lateinit var binding: FragmentProductDetailsBinding\n\tprivate lateinit var viewModel: ProductViewModel\n\tprivate var selectedSize: Int? = null\n\tprivate var selectedColor: String? = null\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentProductDetailsBinding.inflate(layoutInflater)\n\t\tval productId = arguments?.getString(\"productId\")\n\n\t\tif (activity != null && productId != null) {\n\t\t\tval viewModelFactory = ProductViewModelFactory(productId, requireActivity().application)\n\t\t\tviewModel = ViewModelProvider(this, viewModelFactory).get(ProductViewModel::class.java)\n\t\t}\n\n\t\tif (viewModel.isSeller()) {\n\t\t\tbinding.proDetailsAddCartBtn.visibility = View.GONE\n\t\t} else {\n\t\t\tbinding.proDetailsAddCartBtn.visibility = View.VISIBLE\n\t\t\tbinding.proDetailsAddCartBtn.setOnClickListener {\n\t\t\t\tif (viewModel.isItemInCart.value == true) {\n\t\t\t\t\tnavigateToCartFragment()\n\t\t\t\t} else {\n\t\t\t\t\tonAddToCart()\n\t\t\t\t\tif (viewModel.errorStatus.value?.isEmpty() == true) {\n\t\t\t\t\t\tviewModel.addItemStatus.observe(viewLifecycleOwner) { status ->\n\t\t\t\t\t\t\tif (status == AddObjectStatus.DONE) {\n\t\t\t\t\t\t\t\tmakeToast(\"Product Added To Cart\")\n\t\t\t\t\t\t\t\tviewModel.checkIfInCart()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tbinding.loaderLayout.loaderFrameLayout.background =\n\t\t\tResourcesCompat.getDrawable(resources, R.color.white, null)\n\n\t\tbinding.layoutViewsGroup.visibility = View.GONE\n\t\tbinding.proDetailsAddCartBtn.visibility = View.GONE\n\t\tsetObservers()\n\t\treturn binding.root\n\t}\n\n\toverride fun onResume() {\n\t\tsuper.onResume()\n\t\tviewModel.setLike()\n\t\tviewModel.checkIfInCart()\n\t\tselectedSize = null\n\t\tselectedColor = null\n\t}\n\n\tprivate fun setObservers() {\n\t\tviewModel.dataStatus.observe(viewLifecycleOwner) {\n\t\t\twhen (it) {\n\t\t\t\tStoreDataStatus.DONE -> {\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\tbinding.proDetailsLayout.visibility = View.VISIBLE\n\t\t\t\t\tsetViews()\n\t\t\t\t}\n\t\t\t\telse -> {\n\t\t\t\t\tbinding.proDetailsLayout.visibility = View.GONE\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tviewModel.isLiked.observe(viewLifecycleOwner) {\n\t\t\tif (it == true) {\n\t\t\t\tbinding.proDetailsLikeBtn.setImageResource(R.drawable.liked_heart_drawable)\n\t\t\t} else {\n\t\t\t\tbinding.proDetailsLikeBtn.setImageResource(R.drawable.heart_icon_drawable)\n\t\t\t}\n\t\t}\n\t\tviewModel.isItemInCart.observe(viewLifecycleOwner) {\n\t\t\tif (it == true) {\n\t\t\t\tbinding.proDetailsAddCartBtn.text =\n\t\t\t\t\tgetString(R.string.pro_details_go_to_cart_btn_text)\n\t\t\t} else {\n\t\t\t\tbinding.proDetailsAddCartBtn.text =\n\t\t\t\t\tgetString(R.string.pro_details_add_to_cart_btn_text)\n\t\t\t}\n\t\t}\n\t\tviewModel.errorStatus.observe(viewLifecycleOwner) {\n\t\t\tif (it.isNotEmpty())\n\t\t\t\tmodifyErrors(it)\n\t\t}\n\t}\n\n\t@SuppressLint(\"ResourceAsColor\")\n\tprivate fun modifyErrors(errList: List<AddItemErrors>) {\n\t\tmakeToast(\"Please Select Size and Color.\")\n\t\tif (!errList.isNullOrEmpty()) {\n\t\t\terrList.forEach { err ->\n\t\t\t\twhen (err) {\n\t\t\t\t\tAddItemErrors.ERROR_SIZE -> {\n\t\t\t\t\t\tbinding.proDetailsSelectSizeLabel.setTextColor(R.color.red_600)\n\t\t\t\t\t}\n\t\t\t\t\tAddItemErrors.ERROR_COLOR -> {\n\t\t\t\t\t\tbinding.proDetailsSelectColorLabel.setTextColor(R.color.red_600)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun setViews() {\n\t\tbinding.layoutViewsGroup.visibility = View.VISIBLE\n\t\tbinding.proDetailsAddCartBtn.visibility = View.VISIBLE\n\t\tbinding.addProAppBar.topAppBar.title = viewModel.productData.value?.name\n\t\tbinding.addProAppBar.topAppBar.setNavigationOnClickListener {\n\t\t\tfindNavController().navigateUp()\n\t\t}\n\t\tbinding.addProAppBar.topAppBar.inflateMenu(R.menu.app_bar_menu)\n\t\tbinding.addProAppBar.topAppBar.overflowIcon?.setTint(\n\t\t\tContextCompat.getColor(\n\t\t\t\trequireContext(),\n\t\t\t\tR.color.gray\n\t\t\t)\n\t\t)\n\n\t\tsetImagesView()\n\n\t\tbinding.proDetailsTitleTv.text = viewModel.productData.value?.name ?: \"\"\n\t\tbinding.proDetailsLikeBtn.apply {\n\t\t\tsetOnClickListener {\n\t\t\t\tviewModel.toggleLikeProduct()\n\t\t\t}\n\t\t}\n\t\tbinding.proDetailsRatingBar.rating = (viewModel.productData.value?.rating ?: 0.0).toFloat()\n\t\tbinding.proDetailsPriceTv.text = resources.getString(\n\t\t\tR.string.pro_details_price_value,\n\t\t\tviewModel.productData.value?.price.toString()\n\t\t)\n\t\tsetShoeSizeButtons()\n\t\tsetShoeColorsButtons()\n\t\tbinding.proDetailsSpecificsText.text = viewModel.productData.value?.description ?: \"\"\n\t}\n\n\tprivate fun onAddToCart() {\n\t\tviewModel.addToCart(selectedSize, selectedColor)\n\t}\n\n\tprivate fun navigateToCartFragment() {\n\t\tfindNavController().navigate(R.id.action_productDetailsFragment_to_cartFragment)\n\t}\n\n\tprivate fun makeToast(text: String) {\n\t\tToast.makeText(context, text, Toast.LENGTH_LONG).show()\n\t}\n\n\tprivate fun setImagesView() {\n\t\tif (context != null) {\n\t\t\tbinding.proDetailsImagesRecyclerview.isNestedScrollingEnabled = false\n\t\t\tval adapter = ProductImagesAdapter(\n\t\t\t\trequireContext(),\n\t\t\t\tviewModel.productData.value?.images ?: emptyList()\n\t\t\t)\n\t\t\tbinding.proDetailsImagesRecyclerview.adapter = adapter\n\t\t\tval rad = resources.getDimension(R.dimen.radius)\n\t\t\tval dotsHeight = resources.getDimensionPixelSize(R.dimen.dots_height)\n\t\t\tval inactiveColor = ContextCompat.getColor(requireContext(), R.color.gray)\n\t\t\tval activeColor = ContextCompat.getColor(requireContext(), R.color.blue_accent_300)\n\t\t\tval itemDecoration =\n\t\t\t\tDotsIndicatorDecoration(rad, rad * 4, dotsHeight, inactiveColor, activeColor)\n\t\t\tbinding.proDetailsImagesRecyclerview.addItemDecoration(itemDecoration)\n\t\t\tPagerSnapHelper().attachToRecyclerView(binding.proDetailsImagesRecyclerview)\n\t\t}\n\t}\n\n\tprivate fun setShoeSizeButtons() {\n\t\tbinding.proDetailsSizesRadioGroup.apply {\n\t\t\tfor ((_, v) in ShoeSizes) {\n\t\t\t\tif (viewModel.productData.value?.availableSizes?.contains(v) == true) {\n\t\t\t\t\tval radioButton = RadioButton(context)\n\t\t\t\t\tradioButton.id = v\n\t\t\t\t\tradioButton.tag = v\n\t\t\t\t\tval param =\n\t\t\t\t\t\tbinding.proDetailsSizesRadioGroup.layoutParams as ViewGroup.MarginLayoutParams\n\t\t\t\t\tparam.setMargins(resources.getDimensionPixelSize(R.dimen.radio_margin_size))\n\t\t\t\t\tparam.width = ViewGroup.LayoutParams.WRAP_CONTENT\n\t\t\t\t\tparam.height = ViewGroup.LayoutParams.WRAP_CONTENT\n\t\t\t\t\tradioButton.layoutParams = param\n\t\t\t\t\tradioButton.background =\n\t\t\t\t\t\tContextCompat.getDrawable(context, R.drawable.radio_selector)\n\t\t\t\t\tradioButton.setButtonDrawable(R.color.transparent)\n\t\t\t\t\tradioButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14F)\n\t\t\t\t\tradioButton.setTextColor(Color.BLACK)\n\t\t\t\t\tradioButton.setTypeface(null, Typeface.BOLD)\n\t\t\t\t\tradioButton.textAlignment = View.TEXT_ALIGNMENT_CENTER\n\t\t\t\t\tradioButton.text = \"$v\"\n\t\t\t\t\tradioButton.setOnCheckedChangeListener { buttonView, isChecked ->\n\t\t\t\t\t\tval tag = buttonView.tag.toString().toInt()\n\t\t\t\t\t\tif (isChecked) {\n\t\t\t\t\t\t\tselectedSize = tag\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\taddView(radioButton)\n\t\t\t\t}\n\t\t\t}\n\t\t\tinvalidate()\n\t\t}\n\t}\n\n\tprivate fun setShoeColorsButtons() {\n\t\tbinding.proDetailsColorsRadioGroup.apply {\n\t\t\tvar ind = 1\n\t\t\tfor ((k, v) in ShoeColors) {\n\t\t\t\tif (viewModel.productData.value?.availableColors?.contains(k) == true) {\n\t\t\t\t\tval radioButton = RadioButton(context)\n\t\t\t\t\tradioButton.id = ind\n\t\t\t\t\tradioButton.tag = k\n\t\t\t\t\tval param =\n\t\t\t\t\t\tbinding.proDetailsColorsRadioGroup.layoutParams as ViewGroup.MarginLayoutParams\n\t\t\t\t\tparam.setMargins(resources.getDimensionPixelSize(R.dimen.radio_margin_size))\n\t\t\t\t\tparam.width = ViewGroup.LayoutParams.WRAP_CONTENT\n\t\t\t\t\tparam.height = ViewGroup.LayoutParams.WRAP_CONTENT\n\t\t\t\t\tradioButton.layoutParams = param\n\t\t\t\t\tradioButton.background =\n\t\t\t\t\t\tContextCompat.getDrawable(context, R.drawable.color_radio_selector)\n\t\t\t\t\tradioButton.setButtonDrawable(R.color.transparent)\n\t\t\t\t\tradioButton.backgroundTintList = ColorStateList.valueOf(Color.parseColor(v))\n\t\t\t\t\tif (k == \"white\") {\n\t\t\t\t\t\tradioButton.backgroundTintMode = PorterDuff.Mode.MULTIPLY\n\t\t\t\t\t} else {\n\t\t\t\t\t\tradioButton.backgroundTintMode = PorterDuff.Mode.ADD\n\t\t\t\t\t}\n\t\t\t\t\tradioButton.setOnCheckedChangeListener { buttonView, isChecked ->\n\t\t\t\t\t\tval tag = buttonView.tag.toString()\n\t\t\t\t\t\tif (isChecked) {\n\t\t\t\t\t\t\tselectedColor = tag\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\taddView(radioButton)\n\t\t\t\t\tind++\n\t\t\t\t}\n\t\t\t}\n\t\t\tinvalidate()\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/ProductImagesAdapter.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.core.net.toUri\nimport androidx.recyclerview.widget.RecyclerView\nimport com.bumptech.glide.Glide\nimport com.vishalgaur.shoppingapp.databinding.ImagesItemBinding\n\nclass ProductImagesAdapter(private val context: Context, private val images: List<String>) :\n\tRecyclerView.Adapter<ProductImagesAdapter.ViewHolder>() {\n\n\tclass ViewHolder(binding: ImagesItemBinding) : RecyclerView.ViewHolder(binding.root) {\n\t\tval imageView = binding.rcImageView\n\t}\n\n\toverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {\n\t\treturn ViewHolder(\n\t\t\tImagesItemBinding.inflate(\n\t\t\t\tLayoutInflater.from(parent.context),\n\t\t\t\tparent,\n\t\t\t\tfalse\n\t\t\t)\n\t\t)\n\t}\n\n\toverride fun onBindViewHolder(holder: ViewHolder, position: Int) {\n\t\tval imageUrl = images[position]\n\t\tval imgUrl = imageUrl.toUri().buildUpon().scheme(\"https\").build()\n\n\t\tGlide.with(context)\n\t\t\t.asBitmap()\n\t\t\t.load(imgUrl)\n\t\t\t.into(holder.imageView)\n\t}\n\n\toverride fun getItemCount(): Int = images.size\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/ProfileFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.databinding.FragmentProfileBinding\nimport com.vishalgaur.shoppingapp.viewModels.HomeViewModel\n\nclass ProfileFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentProfileBinding\n\tprivate val viewModel: HomeViewModel by activityViewModels()\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentProfileBinding.inflate(layoutInflater)\n\t\tbinding.profileTopAppBar.topAppBar.title = getString(R.string.account_profile_label)\n\t\tbinding.profileTopAppBar.topAppBar.setNavigationOnClickListener {\n\t\t\tfindNavController().navigateUp()\n\t\t}\n\t\treturn binding.root\n\t}\n\n\toverride fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n\t\tsuper.onViewCreated(view, savedInstanceState)\n\t\tviewModel.getUserData()\n\t\tsetViews()\n\t}\n\n\tprivate fun setViews() {\n\t\tviewModel.userData.observe(viewLifecycleOwner) {\n\t\t\tif (it != null) {\n\t\t\t\tbinding.profileNameTv.text = it.name\n\t\t\t\tbinding.profileEmailTv.text = it.email\n\t\t\t\tbinding.profileMobileTv.text = it.mobile\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/SelectAddressFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.os.bundleOf\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport com.google.android.material.dialog.MaterialAlertDialogBuilder\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.databinding.FragmentSelectAddressBinding\nimport com.vishalgaur.shoppingapp.viewModels.OrderViewModel\n\nprivate const val TAG = \"ShipToFragment\"\n\nclass SelectAddressFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentSelectAddressBinding\n\tprivate val orderViewModel: OrderViewModel by activityViewModels()\n\tprivate lateinit var addressAdapter: AddressAdapter\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentSelectAddressBinding.inflate(layoutInflater)\n\n\t\tsetViews()\n\t\tsetObservers()\n\n\t\treturn binding.root\n\t}\n\n\toverride fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n\t\tsuper.onViewCreated(view, savedInstanceState)\n\t\torderViewModel.getUserAddresses()\n\t}\n\n\tprivate fun setObservers() {\n\t\torderViewModel.dataStatus.observe(viewLifecycleOwner) { status ->\n\t\t\twhen (status) {\n\t\t\t\tStoreDataStatus.LOADING -> {\n\t\t\t\t\tbinding.addressEmptyTextView.visibility = View.GONE\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.VISIBLE\n\t\t\t\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\t\t\t}\n\t\t\t\telse -> {\n\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(status != null && status != StoreDataStatus.LOADING) {\n\t\t\t\torderViewModel.userAddresses.observe(viewLifecycleOwner) { addressList ->\n\t\t\t\t\tif (addressList.isNotEmpty()) {\n\t\t\t\t\t\taddressAdapter.data = addressList\n\t\t\t\t\t\tbinding.shipToAddressesRecyclerView.adapter = addressAdapter\n\t\t\t\t\t\tbinding.shipToAddressesRecyclerView.adapter?.notifyDataSetChanged()\n\t\t\t\t\t} else if (addressList.isEmpty()) {\n\t\t\t\t\t\tbinding.shipToAddressesRecyclerView.visibility = View.GONE\n\t\t\t\t\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\t\t\t\t\tbinding.loaderLayout.circularLoader.hideAnimationBehavior\n\t\t\t\t\t\tbinding.addressEmptyTextView.visibility = View.VISIBLE\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun setViews() {\n\t\tbinding.shipToAppBar.topAppBar.title = getString(R.string.ship_to_title)\n\t\tbinding.shipToAppBar.topAppBar.inflateMenu(R.menu.menu_with_add_only)\n\t\tbinding.shipToAppBar.topAppBar.setNavigationOnClickListener {\n\t\t\tfindNavController().navigateUp()\n\t\t}\n\t\tbinding.loaderLayout.loaderFrameLayout.visibility = View.GONE\n\t\tbinding.shipToErrorTextView.visibility = View.GONE\n\t\tbinding.addressEmptyTextView.visibility = View.GONE\n\t\tbinding.shipToAppBar.topAppBar.setOnMenuItemClickListener { menuItem ->\n\t\t\tif (menuItem.itemId == R.id.add_item) {\n\t\t\t\tnavigateToAddEditAddress(false)\n\t\t\t\ttrue\n\t\t\t} else {\n\t\t\t\tfalse\n\t\t\t}\n\t\t}\n\n\t\tif (context != null) {\n\t\t\taddressAdapter = AddressAdapter(\n\t\t\t\trequireContext(),\n\t\t\t\torderViewModel.userAddresses.value ?: emptyList(),\n\t\t\t\ttrue\n\t\t\t)\n\t\t\taddressAdapter.onClickListener = object : AddressAdapter.OnClickListener {\n\t\t\t\toverride fun onEditClick(addressId: String) {\n\t\t\t\t\tLog.d(TAG, \"onEditAddress: initiated\")\n\t\t\t\t\tnavigateToAddEditAddress(true, addressId)\n\t\t\t\t}\n\n\t\t\t\toverride fun onDeleteClick(addressId: String) {\n\t\t\t\t\tLog.d(TAG, \"onDeleteAddress: initiated\")\n\t\t\t\t\tshowDeleteDialog(addressId)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbinding.shipToAddressesRecyclerView.adapter = addressAdapter\n\t\t}\n\n\t\tbinding.shipToNextBtn.setOnClickListener {\n\t\t\tnavigateToPaymentFragment(addressAdapter.lastCheckedAddress)\n\t\t}\n\t}\n\n\tprivate fun showDeleteDialog(addressId: String) {\n\t\tcontext?.let {\n\t\t\tMaterialAlertDialogBuilder(it)\n\t\t\t\t.setTitle(getString(R.string.delete_dialog_title_text))\n\t\t\t\t.setMessage(getString(R.string.delete_address_message_text))\n\t\t\t\t.setNeutralButton(getString(R.string.pro_cat_dialog_cancel_btn)) { dialog, _ ->\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.setPositiveButton(getString(R.string.delete_dialog_delete_btn_text)) { dialog, _ ->\n\t\t\t\t\torderViewModel.deleteAddress(addressId)\n\t\t\t\t\tdialog.cancel()\n\t\t\t\t}\n\t\t\t\t.show()\n\t\t}\n\t}\n\n\tprivate fun navigateToPaymentFragment(addressId: String?) {\n\t\tif (addressId != null) {\n\t\t\torderViewModel.setSelectedAddress(addressId)\n\t\t\tLog.d(TAG, \"navigate to Payment\")\n\t\t\tbinding.shipToErrorTextView.visibility = View.GONE\n\t\t\tfindNavController().navigate(R.id.action_selectAddressFragment_to_selectPaymentFragment)\n\n\t\t} else {\n\t\t\tLog.d(TAG, \"error = select one address\")\n\t\t\tbinding.shipToErrorTextView.visibility = View.VISIBLE\n\t\t}\n\t}\n\n\tprivate fun navigateToAddEditAddress(isEdit: Boolean, addressId: String? = null) {\n\t\tfindNavController().navigate(\n\t\t\tR.id.action_selectAddressFragment_to_addEditAddressFragment,\n\t\t\tbundleOf(\"isEdit\" to isEdit, \"addressId\" to addressId)\n\t\t)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/home/SelectPaymentFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.home\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.databinding.FragmentSelectPaymentBinding\nimport com.vishalgaur.shoppingapp.viewModels.OrderViewModel\n\nprivate const val TAG = \"SelectMethodFragment\"\n\nclass SelectPaymentFragment : Fragment() {\n\n\tprivate lateinit var binding: FragmentSelectPaymentBinding\n\tprivate var methodsAdapter = PayByAdapter(getPaymentMethods())\n\tprivate val orderViewModel: OrderViewModel by activityViewModels()\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tbinding = FragmentSelectPaymentBinding.inflate(layoutInflater)\n\n\t\tsetViews()\n\t\treturn binding.root\n\t}\n\n\tprivate fun setViews() {\n\t\tbinding.payByAppBar.topAppBar.title = getString(R.string.pay_by_title)\n\t\tbinding.payByAppBar.topAppBar.setNavigationOnClickListener {\n\t\t\tfindNavController().navigateUp()\n\t\t}\n\t\tbinding.payByErrorTextView.visibility = View.GONE\n\t\tbinding.payByPaymentsRecyclerView.adapter = methodsAdapter\n\t\tbinding.payByNextBtn.text =\n\t\t\tgetString(R.string.pay_by_next_btn_text, orderViewModel.getItemsPriceTotal().toString())\n\t\tbinding.payByNextBtn.setOnClickListener {\n\t\t\tnavigateToOrderSuccess(methodsAdapter.lastCheckedMethod)\n\t\t}\n\t}\n\n\tprivate fun navigateToOrderSuccess(method: String?) {\n\t\tif (method != null) {\n\t\t\torderViewModel.setSelectedPaymentMethod(method)\n\t\t\tLog.d(TAG, \"navigate to order Success\")\n\t\t\tbinding.payByErrorTextView.visibility = View.GONE\n\t\t\torderViewModel.finalizeOrder()\n\t\t\t// save order\n\t\t\t// wait for save add observer\n\t\t\t// if success, navigate\n\t\t\tfindNavController().navigate(R.id.action_selectPaymentFragment_to_orderSuccessFragment)\n\t\t} else {\n\t\t\tLog.d(TAG, \"Error: Select a payment method!\")\n\t\t\tbinding.payByErrorTextView.visibility = View.VISIBLE\n\t\t}\n\t}\n\n\tprivate fun getPaymentMethods(): List<String> {\n\t\treturn listOf(\"UPI\", \"Debit Card\", \"Cash On Delivery\")\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/loginSignup/LoginFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.loginSignup\n\nimport android.text.SpannableString\nimport android.text.Spanned\nimport android.text.method.LinkMovementMethod\nimport android.text.style.ClickableSpan\nimport android.view.View\nimport androidx.core.os.bundleOf\nimport androidx.navigation.fragment.findNavController\nimport com.vishalgaur.shoppingapp.MOB_ERROR_TEXT\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.utils.LogInErrors\nimport com.vishalgaur.shoppingapp.databinding.FragmentLoginBinding\nimport com.vishalgaur.shoppingapp.ui.LoginViewErrors\n\nclass LoginFragment : LoginSignupBaseFragment<FragmentLoginBinding>() {\n\toverride fun setViewBinding(): FragmentLoginBinding {\n\t\treturn FragmentLoginBinding.inflate(layoutInflater)\n\t}\n\n\toverride fun observeView() {\n\t\tsuper.observeView()\n\n\t\tviewModel.errorStatusLoginFragment.observe(viewLifecycleOwner) { err ->\n\t\t\tmodifyErrors(err)\n\t\t}\n\n\t\tviewModel.loginErrorStatus.observe(viewLifecycleOwner) { err ->\n\t\t\twhen (err) {\n\t\t\t\tLogInErrors.LERR -> setErrorText(getString(R.string.login_error_text))\n\t\t\t\telse -> binding.loginErrorTextView.visibility = View.GONE\n\t\t\t}\n\t\t}\n\t}\n\n\toverride fun setUpViews() {\n\t\tsuper.setUpViews()\n\n\t\tbinding.loginErrorTextView.visibility = View.GONE\n\n\t\tbinding.loginMobileEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.loginPasswordEditText.onFocusChangeListener = focusChangeListener\n\n\t\tbinding.loginLoginBtn.setOnClickListener(object : OnClickListener {\n\t\t\toverride fun onClick(v: View?) {\n\t\t\t\tonLogin()\n\t\t\t\tif (viewModel.errorStatusLoginFragment.value == LoginViewErrors.NONE) {\n\t\t\t\t\tviewModel.loginErrorStatus.observe(viewLifecycleOwner) {\n\t\t\t\t\t\tif (it == LogInErrors.NONE) {\n\t\t\t\t\t\t\tval isRemOn = binding.loginRemSwitch.isChecked\n\t\t\t\t\t\t\tval bundle = bundleOf(\n\t\t\t\t\t\t\t\t\"uData\" to viewModel.userData.value,\n\t\t\t\t\t\t\t\t\"loginRememberMe\" to isRemOn\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tlaunchOtpActivity(getString(R.string.login_fragment_label), bundle)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tsetUpClickableSignUpText()\n\t}\n\n\tprivate fun modifyErrors(err: LoginViewErrors) {\n\t\twhen (err) {\n\t\t\tLoginViewErrors.NONE -> setEditTextErrors()\n\t\t\tLoginViewErrors.ERR_EMPTY -> setErrorText(\"Fill all details\")\n\t\t\tLoginViewErrors.ERR_MOBILE -> setEditTextErrors(MOB_ERROR_TEXT)\n\t\t}\n\t}\n\n\tprivate fun setErrorText(errText: String?) {\n\t\tbinding.loginErrorTextView.visibility = View.VISIBLE\n\t\tif (errText != null) {\n\t\t\tbinding.loginErrorTextView.text = errText\n\t\t}\n\t}\n\n\tprivate fun setEditTextErrors(mobError: String? = null) {\n\t\tbinding.loginErrorTextView.visibility = View.GONE\n\t\tbinding.loginMobileEditText.error = mobError\n\t}\n\n\tprivate fun setUpClickableSignUpText() {\n\t\tval signUpText = getString(R.string.login_signup_text)\n\t\tval ss = SpannableString(signUpText)\n\t\tval clickableSpan = object : ClickableSpan() {\n\t\t\toverride fun onClick(widget: View) {\n\t\t\t\tfindNavController().navigateUp()\n\t\t\t}\n\t\t}\n\n\t\tss.setSpan(clickableSpan, 10, 17, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)\n\t\tbinding.loginSignupTextView.apply {\n\t\t\ttext = ss\n\t\t\tmovementMethod = LinkMovementMethod.getInstance()\n\t\t}\n\t}\n\n\tprivate fun onLogin() {\n\t\tval mob = binding.loginMobileEditText.text.toString()\n\t\tval pwd = binding.loginPasswordEditText.text.toString()\n\n\t\tviewModel.loginSubmitData(mob, pwd)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/loginSignup/LoginSignupActivity.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.loginSignup\n\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport com.vishalgaur.shoppingapp.R\n\nclass LoginSignupActivity : AppCompatActivity() {\n\toverride fun onCreate(savedInstanceState: Bundle?) {\n\t\tsuper.onCreate(savedInstanceState)\n\t\tsetContentView(R.layout.activity_signup)\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/loginSignup/LoginSignupBaseFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.loginSignup\n\nimport android.content.Intent\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.viewbinding.ViewBinding\nimport com.vishalgaur.shoppingapp.ui.MyOnFocusChangeListener\nimport com.vishalgaur.shoppingapp.viewModels.AuthViewModel\n\nabstract class LoginSignupBaseFragment<VBinding : ViewBinding> : Fragment() {\n\n\tprotected val viewModel: AuthViewModel by activityViewModels()\n\n\tprotected lateinit var binding: VBinding\n\tprotected abstract fun setViewBinding(): VBinding\n\n\tprotected val focusChangeListener = MyOnFocusChangeListener()\n\n\toverride fun onCreate(savedInstanceState: Bundle?) {\n\t\tsuper.onCreate(savedInstanceState)\n\t\tinit()\n\t}\n\n\toverride fun onCreateView(\n\t\tinflater: LayoutInflater,\n\t\tcontainer: ViewGroup?,\n\t\tsavedInstanceState: Bundle?\n\t): View? {\n\t\tsetUpViews()\n\t\tobserveView()\n\t\treturn binding.root\n\t}\n\n\tfun launchOtpActivity(from: String, extras: Bundle) {\n\t\tval intent = Intent(context, OtpActivity::class.java).putExtra(\n\t\t\t\"from\",\n\t\t\tfrom\n\t\t).putExtras(extras)\n\t\tstartActivity(intent)\n\t}\n\n\topen fun setUpViews() {}\n\n\topen fun observeView() {}\n\n\tprivate fun init() {\n\t\tbinding = setViewBinding()\n\t}\n\n\tinterface OnClickListener : View.OnClickListener\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/loginSignup/OtpActivity.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.loginSignup\n\nimport android.app.Application\nimport android.os.Bundle\nimport android.view.View\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.ViewModelProvider\nimport com.google.android.material.snackbar.Snackbar\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.databinding.ActivityOtpBinding\nimport com.vishalgaur.shoppingapp.shouldBypassOTPValidation\nimport com.vishalgaur.shoppingapp.ui.OTPStatus\nimport com.vishalgaur.shoppingapp.ui.launchHome\nimport com.vishalgaur.shoppingapp.viewModels.OtpViewModel\n\nclass OtpActivity : AppCompatActivity() {\n\tprivate lateinit var binding: ActivityOtpBinding\n\n\tprivate lateinit var viewModel: OtpViewModel\n\n\tprivate lateinit var fromWhere: String\n\n\tclass OtpViewModelFactory(\n\t\tprivate val application: Application, private val uData: UserData\n\t) : ViewModelProvider.Factory {\n\t\t@Suppress(\"UNCHECKED_CAST\")\n\t\toverride fun <T : ViewModel?> create(modelClass: Class<T>): T {\n\t\t\tif (modelClass.isAssignableFrom(OtpViewModel::class.java)) {\n\t\t\t\treturn OtpViewModel(application, uData) as T\n\t\t\t}\n\t\t\tthrow IllegalArgumentException(\"Unknown ViewModel Class\")\n\t\t}\n\t}\n\n\toverride fun onCreate(savedInstanceState: Bundle?) {\n\t\tsuper.onCreate(savedInstanceState)\n\t\tbinding = ActivityOtpBinding.inflate(layoutInflater)\n\t\tval uData: UserData? = intent.getParcelableExtra(\"uData\")\n\t\tfromWhere = intent.getStringExtra(\"from\").toString()\n\t\tif (uData != null) {\n\t\t\tval viewModelFactory = OtpViewModelFactory(application, uData)\n\t\t\tviewModel =\n\t\t\t\tViewModelProvider(this, viewModelFactory).get(OtpViewModel::class.java)\n\n\t\t\tif (shouldBypassOTPValidation()) {\n\t\t\t\tviewModel.manuallyOverrideVerification()\n\t\t\t} else {\n\t\t\t\tviewModel.verifyPhoneOTPStart(uData.mobile, this)\n\t\t\t}\n\t\t}\n\t\tsetViews()\n\n\t\tsetObservers()\n\t\tsetContentView(binding.root)\n\t}\n\n\tprivate fun setObservers() {\n\t\tviewModel.otpStatus.observe(this) {\n\t\t\twhen (it) {\n\t\t\t\tOTPStatus.WRONG -> binding.otpVerifyError.visibility = View.VISIBLE\n\t\t\t\tOTPStatus.INVALID_REQ -> {\n\t\t\t\t\tbinding.loaderLayout.loaderCard.visibility = View.GONE\n\t\t\t\t\tval contextView = binding.loaderLayout.loaderCard\n\t\t\t\t\tSnackbar.make(contextView, R.string.otp_invalid_req_failure, Snackbar.LENGTH_SHORT).show()\n\t\t\t\t}\n\t\t\t\telse -> binding.otpVerifyError.visibility = View.GONE\n\t\t\t}\n\t\t}\n\n\t\tviewModel.isUserLoggedIn.observe(this) {\n\t\t\tif (it == true) {\n\t\t\t\tif (fromWhere == getString(R.string.signup_fragment_label)) {\n\t\t\t\t\tviewModel.signUp()\n\t\t\t\t} else {\n\t\t\t\t\tval rememberMe = intent.getBooleanExtra(\"loginRememberMe\", false)\n\t\t\t\t\tviewModel.login(rememberMe)\n\t\t\t\t}\n\t\t\t\tlaunchHome(this)\n\t\t\t\tfinish()\n\t\t\t}\n\t\t}\n\n\t\tviewModel.isOTPSent.observe(this) {\n\t\t\tif(it == true) {\n\t\t\t\tbinding.loaderLayout.loaderCard.visibility = View.GONE\n\t\t\t\tval contextView = binding.loaderLayout.loaderCard\n\t\t\t\tSnackbar.make(contextView, R.string.otp_sent_msg, Snackbar.LENGTH_SHORT).show()\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun setViews() {\n\t\tbinding.otpVerifyError.visibility = View.GONE\n\t\tbinding.loaderLayout.loaderCard.visibility = View.VISIBLE\n\t\tbinding.loaderLayout.loadingMessage.text = getString(R.string.sending_otp_msg)\n\t\tbinding.loaderLayout.circularLoader.showAnimationBehavior\n\t\tbinding.otpVerifyBtn.setOnClickListener {\n\t\t\tonVerify()\n\t\t}\n\t}\n\n\tprivate fun onVerify() {\n\t\tval otp = binding.otpOtpEditText.text.toString()\n\t\tviewModel.verifyOTP(otp)\n\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/ui/loginSignup/SignupFragment.kt",
    "content": "package com.vishalgaur.shoppingapp.ui.loginSignup\n\nimport android.text.SpannableString\nimport android.text.Spanned\nimport android.text.method.LinkMovementMethod\nimport android.text.style.ClickableSpan\nimport android.view.View\nimport androidx.core.os.bundleOf\nimport androidx.navigation.fragment.findNavController\nimport com.vishalgaur.shoppingapp.EMAIL_ERROR_TEXT\nimport com.vishalgaur.shoppingapp.MOB_ERROR_TEXT\nimport com.vishalgaur.shoppingapp.R\nimport com.vishalgaur.shoppingapp.data.utils.SignUpErrors\nimport com.vishalgaur.shoppingapp.databinding.FragmentSignupBinding\nimport com.vishalgaur.shoppingapp.ui.SignUpViewErrors\n\nclass SignupFragment : LoginSignupBaseFragment<FragmentSignupBinding>() {\n\n\toverride fun setViewBinding(): FragmentSignupBinding {\n\t\treturn FragmentSignupBinding.inflate(layoutInflater)\n\t}\n\n\toverride fun observeView() {\n\t\tsuper.observeView()\n\t\tviewModel.errorStatus.observe(viewLifecycleOwner) { err ->\n\t\t\tmodifyErrors(err)\n\t\t}\n\t}\n\n\toverride fun setUpViews() {\n\t\tsuper.setUpViews()\n\t\tbinding.signupErrorTextView.visibility = View.GONE\n\n\t\tbinding.signupNameEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.signupMobileEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.signupEmailEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.signupPasswordEditText.onFocusChangeListener = focusChangeListener\n\t\tbinding.signupCnfPasswordEditText.onFocusChangeListener = focusChangeListener\n\n\t\tbinding.signupSignupBtn.setOnClickListener(object : OnClickListener {\n\t\t\toverride fun onClick(v: View?) {\n\t\t\t\tonSignUp()\n\t\t\t\tif (viewModel.errorStatus.value == SignUpViewErrors.NONE) {\n\t\t\t\t\tviewModel.signErrorStatus.observe(viewLifecycleOwner) {\n\t\t\t\t\t\tif (it == SignUpErrors.NONE) {\n\t\t\t\t\t\t\tval bundle = bundleOf(\"uData\" to viewModel.userData.value)\n\t\t\t\t\t\t\tlaunchOtpActivity(getString(R.string.signup_fragment_label), bundle)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t})\n\n\t\tsetUpClickableLoginText()\n\t}\n\n\tprivate fun setUpClickableLoginText() {\n\t\tval loginText = getString(R.string.signup_login_text)\n\t\tval ss = SpannableString(loginText)\n\n\t\tval clickableSpan = object : ClickableSpan() {\n\t\t\toverride fun onClick(widget: View) {\n\t\t\t\tfindNavController().navigate(R.id.action_signup_to_login)\n\t\t\t}\n\t\t}\n\n\t\tss.setSpan(clickableSpan, 25, 31, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)\n\t\tbinding.signupLoginTextView.apply {\n\t\t\ttext = ss\n\t\t\tmovementMethod = LinkMovementMethod.getInstance()\n\t\t}\n\t}\n\n\tprivate fun onSignUp() {\n\t\tval name = binding.signupNameEditText.text.toString()\n\t\tval mobile = binding.signupMobileEditText.text.toString()\n\t\tval email = binding.signupEmailEditText.text.toString()\n\t\tval password1 = binding.signupPasswordEditText.text.toString()\n\t\tval password2 = binding.signupCnfPasswordEditText.text.toString()\n\t\tval isAccepted = binding.signupPolicySwitch.isChecked\n\t\tval isSeller = binding.signupSellerSwitch.isChecked\n\n\t\tviewModel.signUpSubmitData(name, mobile, email, password1, password2, isAccepted, isSeller)\n\t}\n\n\tprivate fun modifyErrors(err: SignUpViewErrors) {\n\t\twhen (err) {\n\t\t\tSignUpViewErrors.NONE -> setEditTextsError()\n\t\t\tSignUpViewErrors.ERR_EMAIL -> setEditTextsError(emailError = EMAIL_ERROR_TEXT)\n\t\t\tSignUpViewErrors.ERR_MOBILE -> setEditTextsError(mobError = MOB_ERROR_TEXT)\n\t\t\tSignUpViewErrors.ERR_EMAIL_MOBILE -> setEditTextsError(EMAIL_ERROR_TEXT, MOB_ERROR_TEXT)\n\t\t\tSignUpViewErrors.ERR_EMPTY -> setErrorText(\"Fill all details.\")\n\t\t\tSignUpViewErrors.ERR_NOT_ACC -> setErrorText(\"Accept the Terms.\")\n\t\t\tSignUpViewErrors.ERR_PWD12NS -> setErrorText(\"Both passwords are not same!\")\n\t\t}\n\t}\n\n\tprivate fun setErrorText(errText: String?) {\n\t\tbinding.signupErrorTextView.visibility = View.VISIBLE\n\t\tif (errText != null) {\n\t\t\tbinding.signupErrorTextView.text = errText\n\t\t}\n\t}\n\n\tprivate fun setEditTextsError(emailError: String? = null, mobError: String? = null) {\n\t\tbinding.signupEmailEditText.error = emailError\n\t\tbinding.signupMobileEditText.error = mobError\n\t\tbinding.signupErrorTextView.visibility = View.GONE\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/viewModels/AddEditAddressViewModel.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport android.app.Application\nimport android.util.Log\nimport androidx.annotation.VisibleForTesting\nimport androidx.lifecycle.AndroidViewModel\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.viewModelScope\nimport com.vishalgaur.shoppingapp.ShoppingApplication\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.source.repository.AuthRepository\nimport com.vishalgaur.shoppingapp.data.utils.AddObjectStatus\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.getAddressId\nimport com.vishalgaur.shoppingapp.isPhoneValid\nimport com.vishalgaur.shoppingapp.isZipCodeValid\nimport com.vishalgaur.shoppingapp.ui.AddAddressViewErrors\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.launch\n\nclass AddEditAddressViewModel(application: Application) : AndroidViewModel(application) {\n\n\tprivate val authRepository = (application as ShoppingApplication).authRepository\n\n\tprivate val sessionManager = ShoppingAppSessionManager(application.applicationContext)\n\tprivate val currentUser = sessionManager.getUserIdFromSession()\n\n\tprivate val _isEdit = MutableLiveData<Boolean>()\n\tval isEdit: LiveData<Boolean> get() = _isEdit\n\n\tprivate val _addressId = MutableLiveData<String>()\n\tval addressId: LiveData<String> get() = _addressId\n\n\tprivate val _dataStatus = MutableLiveData<StoreDataStatus>()\n\tval dataStatus: LiveData<StoreDataStatus> get() = _dataStatus\n\n\tprivate val _errorStatus = MutableLiveData<List<AddAddressViewErrors>>()\n\tval errorStatus: LiveData<List<AddAddressViewErrors>> get() = _errorStatus\n\n\tprivate val _addAddressStatus = MutableLiveData<AddObjectStatus?>()\n\tval addAddressStatus: LiveData<AddObjectStatus?> get() = _addAddressStatus\n\n\tprivate val _addressData = MutableLiveData<UserData.Address>()\n\tval addressData: LiveData<UserData.Address> get() = _addressData\n\n\t@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)\n\tval newAddressData = MutableLiveData<UserData.Address>()\n\n\tinit {\n\t\t_errorStatus.value = mutableListOf()\n\t}\n\n\tfun setIsEdit(state: Boolean) {\n\t\t_isEdit.value = state\n\t}\n\n\tfun setAddressData(addressId: String) {\n\t\t_addressId.value = addressId\n\t\tviewModelScope.launch {\n\t\t\tLog.d(TAG, \"onLoad: Getting Address Data\")\n\t\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\t\tval res = async { authRepository.getAddressesByUserId(currentUser!!) }\n\t\t\tval addRes = res.await()\n\t\t\tif (addRes is Success) {\n\t\t\t\tval addData = addRes.data?.find { address -> address.addressId == addressId }\n\t\t\t\t_addressData.value = addData ?: UserData.Address()\n\t\t\t\tLog.d(TAG, \"onLoad: Success\")\n\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t} else {\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\t_addressData.value = UserData.Address()\n\t\t\t\tif (addRes is Error)\n\t\t\t\t\tLog.d(TAG, \"onLoad: Error, ${addRes.exception.message}\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun submitAddress(\n\t\tcountryCode: String,\n\t\tfirstName: String,\n\t\tlastName: String,\n\t\tstreetAdd: String,\n\t\tstreetAdd2: String,\n\t\tcity: String,\n\t\tstate: String,\n\t\tzipCode: String,\n\t\tphoneNumber: String\n\t) {\n\t\tval errorsList = mutableListOf<AddAddressViewErrors>()\n\t\tif (firstName.isBlank() || lastName.isBlank() || streetAdd.isBlank() || city.isBlank() || state.isBlank() || zipCode.isBlank() || phoneNumber.isBlank())\n\t\t\terrorsList.add(AddAddressViewErrors.EMPTY)\n\t\tif (firstName.isBlank()) errorsList.add(AddAddressViewErrors.ERR_FNAME_EMPTY)\n\t\tif (lastName.isBlank()) errorsList.add(AddAddressViewErrors.ERR_LNAME_EMPTY)\n\t\tif (streetAdd.isBlank()) errorsList.add(AddAddressViewErrors.ERR_STR1_EMPTY)\n\t\tif (city.isBlank()) errorsList.add(AddAddressViewErrors.ERR_CITY_EMPTY)\n\t\tif (state.isBlank()) errorsList.add(AddAddressViewErrors.ERR_STATE_EMPTY)\n\t\tif (zipCode.isBlank()) errorsList.add(AddAddressViewErrors.ERR_ZIP_EMPTY)\n\t\telse if (!isZipCodeValid(zipCode)) errorsList.add(AddAddressViewErrors.ERR_ZIP_INVALID)\n\t\tif (phoneNumber.isBlank()) errorsList.add(AddAddressViewErrors.ERR_PHONE_EMPTY)\n\t\telse if (!isPhoneValid(phoneNumber)) errorsList.add(AddAddressViewErrors.ERR_PHONE_INVALID)\n\n\t\t_errorStatus.value = errorsList\n\n\t\tif (errorsList.isEmpty()) {\n\t\t\tval addressId = if (_isEdit.value == true) _addressId.value!! else\n\t\t\t\tgetAddressId(currentUser!!)\n\t\t\tval newAddress = UserData.Address(\n\t\t\t\taddressId,\n\t\t\t\tfirstName.trim(),\n\t\t\t\tlastName.trim(),\n\t\t\t\tcountryCode.trim(),\n\t\t\t\tstreetAdd.trim(),\n\t\t\t\tstreetAdd2.trim(),\n\t\t\t\tcity.trim(),\n\t\t\t\tstate.trim(),\n\t\t\t\tzipCode.trim(),\n\t\t\t\t\"+91\" + phoneNumber.trim()\n\t\t\t)\n\t\t\tnewAddressData.value = newAddress\n\t\t\tif (_isEdit.value == true) {\n\t\t\t\tupdateAddress()\n\t\t\t} else {\n\t\t\t\tinsertAddress()\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun updateAddress() {\n\t\tviewModelScope.launch {\n\t\t\tif (newAddressData.value != null && _addressData.value != null) {\n\t\t\t\t_addAddressStatus.value = AddObjectStatus.ADDING\n\t\t\t\tval updateRes = async {\n\t\t\t\t\tauthRepository.updateAddress(newAddressData.value!!, currentUser!!)\n\t\t\t\t}\n\t\t\t\tval res = updateRes.await()\n\t\t\t\tif (res is Success) {\n\t\t\t\t\tauthRepository.hardRefreshUserData()\n\t\t\t\t\tLog.d(TAG, \"onUpdate: Success\")\n\t\t\t\t\t_addAddressStatus.value = AddObjectStatus.DONE\n\t\t\t\t} else {\n\t\t\t\t\tLog.d(TAG, \"onUpdate: Some error occurred!\")\n\t\t\t\t\t_addAddressStatus.value = AddObjectStatus.ERR_ADD\n\t\t\t\t\tif (res is Error)\n\t\t\t\t\t\tLog.d(TAG, \"onUpdate: Error, ${res.exception}\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tLog.d(TAG, \"Address Null, Cannot Update!\")\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun insertAddress() {\n\t\tviewModelScope.launch {\n\t\t\tif (newAddressData.value != null) {\n\t\t\t\t_addAddressStatus.value = AddObjectStatus.ADDING\n\t\t\t\tval deferredRes = async {\n\t\t\t\t\tauthRepository.insertAddress(newAddressData.value!!, currentUser!!)\n\t\t\t\t}\n\t\t\t\tval res = deferredRes.await()\n\t\t\t\tif (res is Success) {\n\t\t\t\t\tauthRepository.hardRefreshUserData()\n\t\t\t\t\tLog.d(TAG, \"onInsertAddress: Success\")\n\t\t\t\t\t_addAddressStatus.value = AddObjectStatus.DONE\n\t\t\t\t} else {\n\t\t\t\t\t_addAddressStatus.value = AddObjectStatus.ERR_ADD\n\t\t\t\t\tif (res is Error) {\n\t\t\t\t\t\tLog.d(TAG, \"onInsertAddress: Error, ${res.exception.message}\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tLog.d(TAG, \"Address is Null, Cannot Add!\")\n\t\t\t}\n\t\t}\n\t}\n\n\tcompanion object {\n\t\tprivate const val TAG = \"AddAddressViewModel\"\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/viewModels/AddEditProductViewModel.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport android.app.Application\nimport android.net.Uri\nimport android.util.Log\nimport androidx.annotation.VisibleForTesting\nimport androidx.lifecycle.AndroidViewModel\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.viewModelScope\nimport com.vishalgaur.shoppingapp.ERR_UPLOAD\nimport com.vishalgaur.shoppingapp.ShoppingApplication\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.utils.AddProductErrors\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.getProductId\nimport com.vishalgaur.shoppingapp.ui.AddProductViewErrors\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.launch\n\nprivate const val TAG = \"AddEditViewModel\"\n\nclass AddEditProductViewModel(application: Application) : AndroidViewModel(application) {\n\n\tprivate val productsRepository =\n\t\t(application.applicationContext as ShoppingApplication).productsRepository\n\n\tprivate val sessionManager = ShoppingAppSessionManager(application.applicationContext)\n\n\tprivate val currentUser = sessionManager.getUserIdFromSession()\n\n\tprivate val _selectedCategory = MutableLiveData<String>()\n\tval selectedCategory: LiveData<String> get() = _selectedCategory\n\n\tprivate val _productId = MutableLiveData<String>()\n\tval productId: LiveData<String> get() = _productId\n\n\tprivate val _isEdit = MutableLiveData<Boolean>()\n\tval isEdit: LiveData<Boolean> get() = _isEdit\n\n\tprivate val _errorStatus = MutableLiveData<AddProductViewErrors>()\n\tval errorStatus: LiveData<AddProductViewErrors> get() = _errorStatus\n\n\tprivate val _dataStatus = MutableLiveData<StoreDataStatus>()\n\tval dataStatus: LiveData<StoreDataStatus> get() = _dataStatus\n\n\tprivate val _addProductErrors = MutableLiveData<AddProductErrors?>()\n\tval addProductErrors: LiveData<AddProductErrors?> get() = _addProductErrors\n\n\tprivate val _productData = MutableLiveData<Product>()\n\tval productData: LiveData<Product> get() = _productData\n\n\t@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)\n\tval newProductData = MutableLiveData<Product>()\n\n\tinit {\n\t\t_errorStatus.value = AddProductViewErrors.NONE\n\t}\n\n\tfun setIsEdit(state: Boolean) {\n\t\t_isEdit.value = state\n\t}\n\n\tfun setCategory(catName: String) {\n\t\t_selectedCategory.value = catName\n\t}\n\n\tfun setProductData(productId: String) {\n\t\t_productId.value = productId\n\t\tviewModelScope.launch {\n\t\t\tLog.d(TAG, \"onLoad: Getting product Data\")\n\t\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\t\tval res = async { productsRepository.getProductById(productId) }\n\t\t\tval proRes = res.await()\n\t\t\tif (proRes is Success) {\n\t\t\t\tval proData = proRes.data\n\t\t\t\t_productData.value = proData\n\t\t\t\t_selectedCategory.value = _productData.value!!.category\n\t\t\t\tLog.d(TAG, \"onLoad: Successfully retrieved product data\")\n\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t} else if (proRes is Error) {\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\tLog.d(TAG, \"onLoad: Error getting product data\")\n\t\t\t\t_productData.value = Product()\n\t\t\t}\n\t\t}\n\t}\n\n\tfun submitProduct(\n\t\tname: String,\n\t\tprice: Double?,\n\t\tmrp: Double?,\n\t\tdesc: String,\n\t\tsizes: List<Int>,\n\t\tcolors: List<String>,\n\t\timgList: List<Uri>,\n\t) {\n\t\tif (name.isBlank() || price == null || mrp == null || desc.isBlank() || sizes.isNullOrEmpty() || colors.isNullOrEmpty() || imgList.isNullOrEmpty()) {\n\t\t\t_errorStatus.value = AddProductViewErrors.EMPTY\n\t\t} else {\n\t\t\tif (price == 0.0 || mrp == 0.0) {\n\t\t\t\t_errorStatus.value = AddProductViewErrors.ERR_PRICE_0\n\t\t\t} else {\n\t\t\t\t_errorStatus.value = AddProductViewErrors.NONE\n\t\t\t\tval proId = if (_isEdit.value == true) _productId.value!! else\n\t\t\t\t\tgetProductId(currentUser!!, selectedCategory.value!!)\n\t\t\t\tval newProduct =\n\t\t\t\t\tProduct(\n\t\t\t\t\t\tproId,\n\t\t\t\t\t\tname.trim(),\n\t\t\t\t\t\tcurrentUser!!,\n\t\t\t\t\t\tdesc.trim(),\n\t\t\t\t\t\t_selectedCategory.value!!,\n\t\t\t\t\t\tprice,\n\t\t\t\t\t\tmrp,\n\t\t\t\t\t\tsizes,\n\t\t\t\t\t\tcolors,\n\t\t\t\t\t\temptyList(),\n\t\t\t\t\t\t0.0\n\t\t\t\t\t)\n\t\t\t\tnewProductData.value = newProduct\n\t\t\t\tLog.d(TAG, \"pro = $newProduct\")\n\t\t\t\tif (_isEdit.value == true) {\n\t\t\t\t\tupdateProduct(imgList)\n\t\t\t\t} else {\n\t\t\t\t\tinsertProduct(imgList)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun updateProduct(imgList: List<Uri>) {\n\t\tviewModelScope.launch {\n\t\t\tif (newProductData.value != null && _productData.value != null) {\n\t\t\t\t_addProductErrors.value = AddProductErrors.ADDING\n\t\t\t\tval resImg =\n\t\t\t\t\tasync { productsRepository.updateImages(imgList, _productData.value!!.images) }\n\t\t\t\tval imagesPaths = resImg.await()\n\t\t\t\tnewProductData.value?.images = imagesPaths\n\t\t\t\tif (newProductData.value?.images?.isNotEmpty() == true) {\n\t\t\t\t\tif (imagesPaths[0] == ERR_UPLOAD) {\n\t\t\t\t\t\tLog.d(TAG, \"error uploading images\")\n\t\t\t\t\t\t_addProductErrors.value = AddProductErrors.ERR_ADD_IMG\n\t\t\t\t\t} else {\n\t\t\t\t\t\tval updateRes =\n\t\t\t\t\t\t\tasync { productsRepository.updateProduct(newProductData.value!!) }\n\t\t\t\t\t\tval res = updateRes.await()\n\t\t\t\t\t\tif (res is Success) {\n\t\t\t\t\t\t\tLog.d(TAG, \"onUpdate: Success\")\n\t\t\t\t\t\t\t_addProductErrors.value = AddProductErrors.NONE\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tLog.d(TAG, \"onUpdate: Some error occurred!\")\n\t\t\t\t\t\t\t_addProductErrors.value = AddProductErrors.ERR_ADD\n\t\t\t\t\t\t\tif (res is Error)\n\t\t\t\t\t\t\t\tLog.d(TAG, \"onUpdate: Error, ${res.exception}\")\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tLog.d(TAG, \"Product images empty, Cannot Add Product\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tLog.d(TAG, \"Product is Null, Cannot Add Product\")\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun insertProduct(imgList: List<Uri>) {\n\t\tviewModelScope.launch {\n\t\t\tif (newProductData.value != null) {\n\t\t\t\t_addProductErrors.value = AddProductErrors.ADDING\n\t\t\t\tval resImg = async { productsRepository.insertImages(imgList) }\n\t\t\t\tval imagesPaths = resImg.await()\n\t\t\t\tnewProductData.value?.images = imagesPaths\n\t\t\t\tif (newProductData.value?.images?.isNotEmpty() == true) {\n\t\t\t\t\tif (imagesPaths[0] == ERR_UPLOAD) {\n\t\t\t\t\t\tLog.d(TAG, \"error uploading images\")\n\t\t\t\t\t\t_addProductErrors.value = AddProductErrors.ERR_ADD_IMG\n\t\t\t\t\t} else {\n\t\t\t\t\t\tval deferredRes = async {\n\t\t\t\t\t\t\tproductsRepository.insertProduct(newProductData.value!!)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tval res = deferredRes.await()\n\t\t\t\t\t\tif (res is Success) {\n\t\t\t\t\t\t\tLog.d(TAG, \"onInsertProduct: Success\")\n\t\t\t\t\t\t\t_addProductErrors.value = AddProductErrors.NONE\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t_addProductErrors.value = AddProductErrors.ERR_ADD\n\t\t\t\t\t\t\tif (res is Error)\n\t\t\t\t\t\t\t\tLog.d(TAG, \"onInsertProduct: Error Occurred, ${res.exception}\")\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tLog.d(TAG, \"Product images empty, Cannot Add Product\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tLog.d(TAG, \"Product is Null, Cannot Add Product\")\n\t\t\t}\n\t\t}\n\t}\n\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/viewModels/AuthViewModel.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport android.app.Application\nimport android.util.Log\nimport androidx.lifecycle.AndroidViewModel\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.viewModelScope\nimport com.vishalgaur.shoppingapp.*\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.LogInErrors\nimport com.vishalgaur.shoppingapp.data.utils.SignUpErrors\nimport com.vishalgaur.shoppingapp.data.utils.UserType\nimport com.vishalgaur.shoppingapp.ui.LoginViewErrors\nimport com.vishalgaur.shoppingapp.ui.SignUpViewErrors\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.launch\n\nprivate const val TAG = \"AuthViewModel\"\n\nclass AuthViewModel(application: Application) : AndroidViewModel(application) {\n\n\tprivate val authRepository = (application as ShoppingApplication).authRepository\n\tprivate val productsRepository = (application as ShoppingApplication).productsRepository\n\n\tprivate val _userData = MutableLiveData<UserData>()\n\tval userData: LiveData<UserData> get() = _userData\n\n\tprivate val _signErrorStatus = MutableLiveData<SignUpErrors?>()\n\tval signErrorStatus: LiveData<SignUpErrors?> get() = _signErrorStatus\n\n\tprivate val _errorStatus = MutableLiveData<SignUpViewErrors>()\n\tval errorStatus: LiveData<SignUpViewErrors> get() = _errorStatus\n\n\tprivate val _errorStatusLoginFragment = MutableLiveData<LoginViewErrors>()\n\tval errorStatusLoginFragment: LiveData<LoginViewErrors> get() = _errorStatusLoginFragment\n\n\tprivate val _loginErrorStatus = MutableLiveData<LogInErrors?>()\n\tval loginErrorStatus: LiveData<LogInErrors?> get() = _loginErrorStatus\n\n\tinit {\n\t\t_errorStatus.value = SignUpViewErrors.NONE\n\t\t_errorStatusLoginFragment.value = LoginViewErrors.NONE\n\t\trefreshStatus()\n\t}\n\n\tprivate fun refreshStatus() {\n\t\tviewModelScope.launch {\n\t\t\tgetCurrUser()\n\t\t\tproductsRepository.refreshProducts()\n\t\t}\n\t}\n\n\tfun signUpSubmitData(\n\t\tname: String,\n\t\tmobile: String,\n\t\temail: String,\n\t\tpwd1: String,\n\t\tpwd2: String,\n\t\tisAccepted: Boolean,\n\t\tisSeller: Boolean\n\t) {\n\t\tif (name.isBlank() || mobile.isBlank() || email.isBlank() || pwd1.isBlank() || pwd2.isBlank()) {\n\t\t\t_errorStatus.value = SignUpViewErrors.ERR_EMPTY\n\t\t} else {\n\t\t\tif (pwd1 != pwd2) {\n\t\t\t\t_errorStatus.value = SignUpViewErrors.ERR_PWD12NS\n\t\t\t} else {\n\t\t\t\tif (!isAccepted) {\n\t\t\t\t\t_errorStatus.value = SignUpViewErrors.ERR_NOT_ACC\n\t\t\t\t} else {\n\t\t\t\t\tvar err = ERR_INIT\n\t\t\t\t\tif (!isEmailValid(email)) {\n\t\t\t\t\t\terr += ERR_EMAIL\n\t\t\t\t\t}\n\t\t\t\t\tif (!isPhoneValid(mobile)) {\n\t\t\t\t\t\terr += ERR_MOBILE\n\t\t\t\t\t}\n\t\t\t\t\twhen (err) {\n\t\t\t\t\t\tERR_INIT -> {\n\t\t\t\t\t\t\t_errorStatus.value = SignUpViewErrors.NONE\n\t\t\t\t\t\t\tval uId = getRandomString(32, \"91\" + mobile.trim(), 6)\n\t\t\t\t\t\t\tval newData =\n\t\t\t\t\t\t\t\tUserData(\n\t\t\t\t\t\t\t\t\tuId,\n\t\t\t\t\t\t\t\t\tname.trim(),\n\t\t\t\t\t\t\t\t\t\"+91\" + mobile.trim(),\n\t\t\t\t\t\t\t\t\temail.trim(),\n\t\t\t\t\t\t\t\t\tpwd1.trim(),\n\t\t\t\t\t\t\t\t\tArrayList(),\n\t\t\t\t\t\t\t\t\tArrayList(),\n\t\t\t\t\t\t\t\t\tArrayList(),\n\t\t\t\t\t\t\t\t\tArrayList(),\n\t\t\t\t\t\t\t\t\tif (isSeller) UserType.SELLER.name else UserType.CUSTOMER.name\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t_userData.value = newData\n\t\t\t\t\t\t\tcheckUniqueUser(newData)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t(ERR_INIT + ERR_EMAIL) -> _errorStatus.value = SignUpViewErrors.ERR_EMAIL\n\t\t\t\t\t\t(ERR_INIT + ERR_MOBILE) -> _errorStatus.value = SignUpViewErrors.ERR_MOBILE\n\t\t\t\t\t\t(ERR_INIT + ERR_EMAIL + ERR_MOBILE) -> _errorStatus.value =\n\t\t\t\t\t\t\tSignUpViewErrors.ERR_EMAIL_MOBILE\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\tprivate fun checkUniqueUser(uData: UserData) {\n\t\tviewModelScope.launch {\n\t\t\tval res = async { authRepository.checkEmailAndMobile(uData.email, uData.mobile, getApplication<ShoppingApplication>().applicationContext) }\n\t\t\t_signErrorStatus.value = res.await()\n\t\t}\n\t}\n\n\tfun loginSubmitData(mobile: String, password: String) {\n\t\tif (mobile.isBlank() || password.isBlank()) {\n\t\t\t_errorStatusLoginFragment.value = LoginViewErrors.ERR_EMPTY\n\t\t} else {\n\t\t\tif (!isPhoneValid(mobile)) {\n\t\t\t\t_errorStatusLoginFragment.value = LoginViewErrors.ERR_MOBILE\n\t\t\t} else {\n\t\t\t\t_errorStatusLoginFragment.value = LoginViewErrors.NONE\n\t\t\t\tlogIn(\"+91\" + mobile.trim(), password)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fun logIn(phoneNumber: String, pwd: String) {\n\t\tviewModelScope.launch {\n\t\t\tval res = async { authRepository.checkLogin(phoneNumber, pwd) }\n\t\t\t_userData.value = res.await()\n\t\t\tif (_userData.value != null) {\n\t\t\t\t_loginErrorStatus.value = LogInErrors.NONE\n\t\t\t} else {\n\t\t\t\t_loginErrorStatus.value = LogInErrors.LERR\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate suspend fun getCurrUser() {\n\t\tLog.d(TAG, \"refreshing data...\")\n\t\tauthRepository.refreshData()\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/viewModels/HomeViewModel.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport android.app.Application\nimport android.util.Log\nimport androidx.lifecycle.*\nimport com.vishalgaur.shoppingapp.ShoppingApplication\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.launch\nimport java.time.Month\nimport java.util.*\n\nprivate const val TAG = \"HomeViewModel\"\n\nclass HomeViewModel(application: Application) : AndroidViewModel(application) {\n\n\tprivate val productsRepository =\n\t\t(application.applicationContext as ShoppingApplication).productsRepository\n\tprivate val authRepository =\n\t\t(application.applicationContext as ShoppingApplication).authRepository\n\n\tprivate val sessionManager = ShoppingAppSessionManager(application.applicationContext)\n\tprivate val currentUser = sessionManager.getUserIdFromSession()\n\tval isUserASeller = sessionManager.isUserSeller()\n\n\tprivate var _products = MutableLiveData<List<Product>>()\n\tval products: LiveData<List<Product>> get() = _products\n\n\tprivate lateinit var _allProducts: MutableLiveData<List<Product>>\n\tval allProducts: LiveData<List<Product>> get() = _allProducts\n\n\tprivate var _userProducts = MutableLiveData<List<Product>>()\n\tval userProducts: LiveData<List<Product>> get() = _userProducts\n\n\tprivate var _userOrders = MutableLiveData<List<UserData.OrderItem>>()\n\tval userOrders: LiveData<List<UserData.OrderItem>> get() = _userOrders\n\n\tprivate var _userAddresses = MutableLiveData<List<UserData.Address>>()\n\tval userAddresses: LiveData<List<UserData.Address>> get() = _userAddresses\n\n\tprivate var _selectedOrder = MutableLiveData<UserData.OrderItem?>()\n\tval selectedOrder: LiveData<UserData.OrderItem?> get() = _selectedOrder\n\n\tprivate var _orderProducts = MutableLiveData<List<Product>>()\n\tval orderProducts: LiveData<List<Product>> get() = _orderProducts\n\n\tprivate var _likedProducts = MutableLiveData<List<Product>>()\n\tval likedProducts: LiveData<List<Product>> get() = _likedProducts\n\n\tprivate var _userLikes = MutableLiveData<List<String>>()\n\tval userLikes: LiveData<List<String>> get() = _userLikes\n\n\tprivate var _filterCategory = MutableLiveData(\"All\")\n\tval filterCategory: LiveData<String> get() = _filterCategory\n\n\tprivate val _storeDataStatus = MutableLiveData<StoreDataStatus>()\n\tval storeDataStatus: LiveData<StoreDataStatus> get() = _storeDataStatus\n\n\tprivate val _dataStatus = MutableLiveData<StoreDataStatus>()\n\tval dataStatus: LiveData<StoreDataStatus> get() = _dataStatus\n\n\tprivate val _userData = MutableLiveData<UserData?>()\n\tval userData: LiveData<UserData?> get() = _userData\n\n\tinit {\n\t\tviewModelScope.launch {\n\t\t\tauthRepository.hardRefreshUserData()\n\t\t\tgetUserLikes()\n\t\t}\n\n\t\tif (isUserASeller)\n\t\t\tgetProductsByOwner()\n\t\telse\n\t\t\tgetProducts()\n\t}\n\n\tfun setDataLoaded() {\n\t\t_storeDataStatus.value = StoreDataStatus.DONE\n\t}\n\n\tfun isProductLiked(productId: String): Boolean {\n\t\treturn _userLikes.value?.contains(productId) == true\n\t}\n\n\tfun toggleLikeByProductId(productId: String) {\n\t\tLog.d(TAG, \"Toggling Like\")\n\t\tviewModelScope.launch {\n\t\t\tval isLiked = isProductLiked(productId)\n\t\t\tval allLikes = _userLikes.value?.toMutableList() ?: mutableListOf()\n\t\t\tval deferredRes = async {\n\t\t\t\tif (isLiked) {\n\t\t\t\t\tauthRepository.removeProductFromLikes(productId, currentUser!!)\n\t\t\t\t} else {\n\t\t\t\t\tauthRepository.insertProductToLikes(productId, currentUser!!)\n\t\t\t\t}\n\t\t\t}\n\t\t\tval res = deferredRes.await()\n\t\t\tif (res is Success) {\n\t\t\t\tif (isLiked) {\n\t\t\t\t\tallLikes.remove(productId)\n\t\t\t\t} else {\n\t\t\t\t\tallLikes.add(productId)\n\t\t\t\t}\n\t\t\t\t_userLikes.value = allLikes\n\t\t\t\tval proList = _likedProducts.value?.toMutableList() ?: mutableListOf()\n\t\t\t\tval pro = proList.find { it.productId == productId }\n\t\t\t\tif (pro != null) {\n\t\t\t\t\tproList.remove(pro)\n\t\t\t\t}\n\t\t\t\t_likedProducts.value = proList\n\t\t\t\tLog.d(TAG, \"onToggleLike: Success\")\n\t\t\t} else {\n\t\t\t\tif (res is Error) {\n\t\t\t\t\tLog.d(TAG, \"onToggleLike: Error, ${res.exception}\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfun isProductInCart(productId: String): Boolean {\n\t\treturn false\n\t}\n\n\tfun toggleProductInCart(product: Product) {\n\n\t}\n\n\tfun setDataLoading() {\n\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t}\n\n\tprivate fun getProducts() {\n\t\t_allProducts = Transformations.switchMap(productsRepository.observeProducts()) {\n\t\t\tgetProductsLiveData(it)\n\t\t} as MutableLiveData<List<Product>>\n\t\tviewModelScope.launch {\n\t\t\t_storeDataStatus.value = StoreDataStatus.LOADING\n\t\t\tval res = async { productsRepository.refreshProducts() }\n\t\t\tres.await()\n\t\t\tLog.d(TAG, \"getAllProducts: status = ${_storeDataStatus.value}\")\n\t\t}\n\t}\n\n\tfun getUserLikes() {\n\t\tviewModelScope.launch {\n\t\t\tval res = authRepository.getLikesByUserId(currentUser!!)\n\t\t\tif (res is Success) {\n\t\t\t\tval data = res.data ?: emptyList()\n\t\t\t\tif (data[0] != \"\") {\n\t\t\t\t\t_userLikes.value = data\n\t\t\t\t} else {\n\t\t\t\t\t_userLikes.value = emptyList()\n\t\t\t\t}\n\t\t\t\tLog.d(TAG, \"Getting Likes: Success\")\n\t\t\t} else {\n\t\t\t\t_userLikes.value = emptyList()\n\t\t\t\tif (res is Error)\n\t\t\t\t\tLog.d(TAG, \"Getting Likes: Error, ${res.exception}\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun getLikedProducts() {\n\t\tval res: List<Product> = if (_userLikes.value != null) {\n\t\t\tval allLikes = _userLikes.value ?: emptyList()\n\t\t\tif (!allLikes.isNullOrEmpty()) {\n\t\t\t\tLog.d(TAG, \"alllikes = ${allLikes.size}\")\n\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t\tallLikes.map { proId ->\n\t\t\t\t\t_allProducts.value?.find { it.productId == proId } ?: Product()\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\temptyList()\n\t\t\t}\n\t\t} else {\n\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\temptyList()\n\t\t}\n\t\t_likedProducts.value = res\n\t}\n\n\tprivate fun getProductsLiveData(result: Result<List<Product>?>?): LiveData<List<Product>> {\n\t\tval res = MutableLiveData<List<Product>>()\n\t\tif (result is Success) {\n\t\t\tLog.d(TAG, \"result is success\")\n\t\t\t_storeDataStatus.value = StoreDataStatus.DONE\n\t\t\tres.value = result.data ?: emptyList()\n\t\t} else {\n\t\t\tLog.d(TAG, \"result is not success\")\n\t\t\tres.value = emptyList()\n\t\t\t_storeDataStatus.value = StoreDataStatus.ERROR\n\t\t\tif (result is Error)\n\t\t\t\tLog.d(TAG, \"getProductsLiveData: Error Occurred: ${result.exception}\")\n\t\t}\n\t\treturn res\n\t}\n\n\tprivate fun getProductsByOwner() {\n\t\t_allProducts =\n\t\t\tTransformations.switchMap(productsRepository.observeProductsByOwner(currentUser!!)) {\n\t\t\t\tLog.d(TAG, it.toString())\n\t\t\t\tgetProductsLiveData(it)\n\t\t\t} as MutableLiveData<List<Product>>\n\t\tviewModelScope.launch {\n\t\t\t_storeDataStatus.value = StoreDataStatus.LOADING\n\t\t\tval res = async { productsRepository.refreshProducts() }\n\t\t\tres.await()\n\t\t\tLog.d(TAG, \"getProductsByOwner: status = ${_storeDataStatus.value}\")\n\t\t}\n\t}\n\n\tfun refreshProducts() {\n\t\tgetProducts()\n\t}\n\n\tfun filterBySearch(queryText: String) {\n\t\tfilterProducts(_filterCategory.value!!)\n\t\t_products.value = _products.value?.filter { product ->\n\t\t\tproduct.name.contains(queryText, true) or\n\t\t\t\t\t((queryText.toDoubleOrNull() ?: 0.0).compareTo(product.price) == 0)\n\t\t}\n\t}\n\n\tfun filterProducts(filterType: String) {\n\t\tLog.d(TAG, \"filterType is $filterType\")\n\t\t_filterCategory.value = filterType\n\t\t_products.value = when (filterType) {\n\t\t\t\"None\" -> emptyList()\n\t\t\t\"All\" -> _allProducts.value\n\t\t\telse -> _allProducts.value?.filter { product ->\n\t\t\t\tproduct.category == filterType\n\t\t\t}\n\t\t}\n\t}\n\n\tfun deleteProduct(productId: String) {\n\t\tviewModelScope.launch {\n\t\t\tval delRes = async { productsRepository.deleteProductById(productId) }\n\t\t\twhen (val res = delRes.await()) {\n\t\t\t\tis Success -> Log.d(TAG, \"onDelete: Success\")\n\t\t\t\tis Error -> Log.d(TAG, \"onDelete: Error, ${res.exception}\")\n\t\t\t\telse -> Log.d(TAG, \"onDelete: Some error occurred!\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun signOut() {\n\t\tviewModelScope.launch {\n\t\t\tval deferredRes = async { authRepository.signOut() }\n\t\t\tdeferredRes.await()\n\t\t}\n\t}\n\n\tfun getAllOrders() {\n\t\tviewModelScope.launch {\n\t\t\t_storeDataStatus.value = StoreDataStatus.LOADING\n\t\t\tval deferredRes = async { authRepository.getOrdersByUserId(currentUser!!) }\n\t\t\tval res = deferredRes.await()\n\t\t\tif (res is Success) {\n\t\t\t\t_userOrders.value = res.data ?: emptyList()\n\t\t\t\t_storeDataStatus.value = StoreDataStatus.DONE\n\t\t\t\tLog.d(TAG, \"Getting Orders: Success\")\n\t\t\t} else {\n\t\t\t\t_userOrders.value = emptyList()\n\t\t\t\t_storeDataStatus.value = StoreDataStatus.ERROR\n\t\t\t\tif (res is Error)\n\t\t\t\t\tLog.d(TAG, \"Getting Orders: Error, ${res.exception}\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun getOrderDetailsByOrderId(orderId: String) {\n\t\tviewModelScope.launch {\n\t\t\t_storeDataStatus.value = StoreDataStatus.LOADING\n\t\t\tif (_userOrders.value != null) {\n\t\t\t\tval orderData = _userOrders.value!!.find { it.orderId == orderId }\n\t\t\t\tif (orderData != null) {\n\t\t\t\t\t_selectedOrder.value = orderData\n\t\t\t\t\t_orderProducts.value =\n\t\t\t\t\t\torderData.items.map {\n\t\t\t\t\t\t\t_allProducts.value?.find { pro -> pro.productId == it.productId }\n\t\t\t\t\t\t\t\t?: Product()\n\t\t\t\t\t\t}\n\t\t\t\t\t_storeDataStatus.value = StoreDataStatus.DONE\n\t\t\t\t} else {\n\t\t\t\t\t_selectedOrder.value = null\n\t\t\t\t\t_storeDataStatus.value = StoreDataStatus.ERROR\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfun onSetStatusOfOrder(orderId: String, status: String) {\n\t\tval currDate = Calendar.getInstance()\n\t\tval dateString =\n\t\t\t\"${Month.values()[(currDate.get(Calendar.MONTH))].name} ${\n\t\t\t\tcurrDate.get(Calendar.DAY_OF_MONTH)\n\t\t\t}, ${currDate.get(Calendar.YEAR)}\"\n\t\tLog.d(TAG, \"Selected Status is $status ON $dateString\")\n\t\tsetStatusOfOrder(orderId, \"$status ON $dateString\")\n\t}\n\n\tprivate fun setStatusOfOrder(orderId: String, statusString: String) {\n\t\tviewModelScope.launch {\n\t\t\t_storeDataStatus.value = StoreDataStatus.LOADING\n\t\t\tval deferredRes = async {\n\t\t\t\tauthRepository.setStatusOfOrder(orderId, currentUser!!, statusString)\n\t\t\t}\n\t\t\tval res = deferredRes.await()\n\t\t\tif (res is Success) {\n\t\t\t\tval orderData = _selectedOrder.value\n\t\t\t\torderData?.status = statusString\n\t\t\t\t_selectedOrder.value = orderData\n\t\t\t\tgetOrderDetailsByOrderId(orderId)\n\t\t\t} else {\n\t\t\t\t_storeDataStatus.value = StoreDataStatus.ERROR\n\t\t\t\tif (res is Error)\n\t\t\t\t\tLog.d(TAG, \"Error updating status, ${res.exception}\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun getUserAddresses() {\n\t\tLog.d(TAG, \"Getting Addresses\")\n\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\tviewModelScope.launch {\n\t\t\tval res = authRepository.getAddressesByUserId(currentUser!!)\n\t\t\tif (res is Success) {\n\t\t\t\t_userAddresses.value = res.data ?: emptyList()\n\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t\tLog.d(TAG, \"Getting Addresses: Success\")\n\t\t\t} else {\n\t\t\t\t_userAddresses.value = emptyList()\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\tif (res is Error)\n\t\t\t\t\tLog.d(TAG, \"Getting Addresses: Error Occurred, ${res.exception.message}\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun deleteAddress(addressId: String) {\n\t\tviewModelScope.launch {\n\t\t\tval delRes = async { authRepository.deleteAddressById(addressId, currentUser!!) }\n\t\t\twhen (val res = delRes.await()) {\n\t\t\t\tis Success -> {\n\t\t\t\t\tLog.d(TAG, \"onDeleteAddress: Success\")\n\t\t\t\t\tval addresses = _userAddresses.value?.toMutableList()\n\t\t\t\t\taddresses?.let {\n\t\t\t\t\t\tval pos =\n\t\t\t\t\t\t\taddresses.indexOfFirst { address -> address.addressId == addressId }\n\t\t\t\t\t\tif (pos >= 0)\n\t\t\t\t\t\t\tit.removeAt(pos)\n\t\t\t\t\t\t_userAddresses.value = it\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tis Error -> Log.d(TAG, \"onDeleteAddress: Error, ${res.exception}\")\n\t\t\t\telse -> Log.d(TAG, \"onDeleteAddress: Some error occurred!\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun getUserData() {\n\t\tviewModelScope.launch {\n\t\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\t\tval deferredRes = async { authRepository.getUserData(currentUser!!) }\n\t\t\tval res = deferredRes.await()\n\t\t\tif (res is Success) {\n\t\t\t\tval uData = res.data\n\t\t\t\t_userData.value = uData\n\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t} else {\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\t_userData.value = null\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/viewModels/OrderViewModel.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport android.app.Application\nimport android.util.Log\nimport androidx.lifecycle.AndroidViewModel\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.viewModelScope\nimport com.vishalgaur.shoppingapp.ShoppingApplication\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.getRandomString\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.launch\nimport java.util.*\n\nprivate const val TAG = \"OrderViewModel\"\n\nclass OrderViewModel(application: Application) : AndroidViewModel(application) {\n\n\tprivate val sessionManager = ShoppingAppSessionManager(application.applicationContext)\n\tprivate val currentUser = sessionManager.getUserIdFromSession()\n\n\tprivate val authRepository = (application as ShoppingApplication).authRepository\n\tprivate val productsRepository = (application as ShoppingApplication).productsRepository\n\n\tprivate val _userAddresses = MutableLiveData<List<UserData.Address>>()\n\tval userAddresses: LiveData<List<UserData.Address>> get() = _userAddresses\n\n\tprivate val _userLikes = MutableLiveData<List<String>>()\n\tval userLikes: LiveData<List<String>> get() = _userLikes\n\n\tprivate val _cartItems = MutableLiveData<List<UserData.CartItem>>()\n\tval cartItems: LiveData<List<UserData.CartItem>> get() = _cartItems\n\n\tprivate val _priceList = MutableLiveData<Map<String, Double>>()\n\tval priceList: LiveData<Map<String, Double>> get() = _priceList\n\n\tprivate val _cartProducts = MutableLiveData<List<Product>>()\n\tval cartProducts: LiveData<List<Product>> get() = _cartProducts\n\n\tprivate val _dataStatus = MutableLiveData<StoreDataStatus>()\n\tval dataStatus: LiveData<StoreDataStatus> get() = _dataStatus\n\n\tprivate val _orderStatus = MutableLiveData<StoreDataStatus>()\n\tval orderStatus: LiveData<StoreDataStatus> get() = _orderStatus\n\n\tprivate val _selectedAddress = MutableLiveData<String>()\n\tprivate val _selectedPaymentMethod = MutableLiveData<String>()\n\tprivate val newOrderData = MutableLiveData<UserData.OrderItem>()\n\n\tinit {\n\t\tviewModelScope.launch {\n\t\t\tgetUserLikes()\n\t\t}\n\t}\n\n\tfun getCartItems() {\n\t\tLog.d(TAG, \"Getting Cart Items\")\n\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\tviewModelScope.launch {\n\t\t\tval deferredRes = async {\n\t\t\t\tauthRepository.hardRefreshUserData()\n\t\t\t\tauthRepository.getUserData(currentUser!!)\n\t\t\t}\n\t\t\tval userRes = deferredRes.await()\n\t\t\tif (userRes is Success) {\n\t\t\t\tval uData = userRes.data\n\t\t\t\tif (uData != null) {\n\t\t\t\t\t_cartItems.value = uData.cart\n\t\t\t\t\tval priceRes = async { getAllProductsInCart() }\n\t\t\t\t\tpriceRes.await()\n\t\t\t\t\tLog.d(TAG, \"Getting Cart Items: Success ${_priceList.value}\")\n\t\t\t\t} else {\n\t\t\t\t\t_cartItems.value = emptyList()\n\t\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\t\tLog.d(TAG, \"Getting Cart Items: User Not Found\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t_cartItems.value = emptyList()\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\tLog.d(TAG, \"Getting Cart Items: Error Occurred\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun getUserAddresses() {\n\t\tLog.d(TAG, \"Getting Addresses\")\n\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\tviewModelScope.launch {\n\t\t\tval res = authRepository.getAddressesByUserId(currentUser!!)\n\t\t\tif (res is Success) {\n\t\t\t\t_userAddresses.value = res.data ?: emptyList()\n\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t\tLog.d(TAG, \"Getting Addresses: Success\")\n\t\t\t} else {\n\t\t\t\t_userAddresses.value = emptyList()\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\tif (res is Error)\n\t\t\t\t\tLog.d(TAG, \"Getting Addresses: Error Occurred, ${res.exception.message}\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun getUserLikes() {\n\t\tLog.d(TAG, \"Getting Likes\")\n//\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\tviewModelScope.launch {\n\t\t\tval res = authRepository.getLikesByUserId(currentUser!!)\n\t\t\tif (res is Success) {\n\t\t\t\tval data = res.data ?: emptyList()\n\t\t\t\tif (data[0] != \"\") {\n\t\t\t\t\t_userLikes.value = data\n\t\t\t\t} else {\n\t\t\t\t\t_userLikes.value = emptyList()\n\t\t\t\t}\n\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t\tLog.d(TAG, \"Getting Likes: Success\")\n\t\t\t} else {\n\t\t\t\t_userLikes.value = emptyList()\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\tif (res is Error)\n\t\t\t\t\tLog.d(TAG, \"Getting Likes: Error Occurred, ${res.exception.message}\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun deleteAddress(addressId: String) {\n\t\tviewModelScope.launch {\n\t\t\tval delRes = async { authRepository.deleteAddressById(addressId, currentUser!!) }\n\t\t\twhen (val res = delRes.await()) {\n\t\t\t\tis Success -> {\n\t\t\t\t\tLog.d(TAG, \"onDeleteAddress: Success\")\n\t\t\t\t\tval addresses = _userAddresses.value?.toMutableList()\n\t\t\t\t\taddresses?.let {\n\t\t\t\t\t\tval pos =\n\t\t\t\t\t\t\taddresses.indexOfFirst { address -> address.addressId == addressId }\n\t\t\t\t\t\tif (pos >= 0)\n\t\t\t\t\t\t\tit.removeAt(pos)\n\t\t\t\t\t\t_userAddresses.value = it\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tis Error -> Log.d(TAG, \"onDeleteAddress: Error, ${res.exception}\")\n\t\t\t\telse -> Log.d(TAG, \"onDeleteAddress: Some error occurred!\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun getItemsPriceTotal(): Double {\n\t\tvar totalPrice = 0.0\n\t\t_priceList.value?.forEach { (itemId, price) ->\n\t\t\ttotalPrice += price * (_cartItems.value?.find { it.itemId == itemId }?.quantity ?: 1)\n\t\t}\n\t\treturn totalPrice\n\t}\n\n\tfun toggleLikeProduct(productId: String) {\n\t\tLog.d(TAG, \"toggling Like\")\n\t\tviewModelScope.launch {\n//\t\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\t\tval isLiked = _userLikes.value?.contains(productId) == true\n\t\t\tval allLikes = _userLikes.value?.toMutableList() ?: mutableListOf()\n\t\t\tval deferredRes = async {\n\t\t\t\tif (isLiked) {\n\t\t\t\t\tauthRepository.removeProductFromLikes(productId, currentUser!!)\n\t\t\t\t} else {\n\t\t\t\t\tauthRepository.insertProductToLikes(productId, currentUser!!)\n\t\t\t\t}\n\t\t\t}\n\t\t\tval res = deferredRes.await()\n\t\t\tif (res is Success) {\n\t\t\t\tif (isLiked) {\n\t\t\t\t\tallLikes.remove(productId)\n\t\t\t\t} else {\n\t\t\t\t\tallLikes.add(productId)\n\t\t\t\t}\n\t\t\t\t_userLikes.value = allLikes\n\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t} else {\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\tif (res is Error)\n\t\t\t\t\tLog.d(TAG, \"onUpdateQuantity: Error Occurred: ${res.exception.message}\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun getItemsCount(): Int {\n\t\tvar totalCount = 0\n\t\t_cartItems.value?.forEach {\n\t\t\ttotalCount += it.quantity\n\t\t}\n\t\treturn totalCount\n\t}\n\n\tfun setQuantityOfItem(itemId: String, value: Int) {\n\t\tviewModelScope.launch {\n//\t\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\t\tvar cartList: MutableList<UserData.CartItem>\n\t\t\t_cartItems.value?.let { items ->\n\t\t\t\tval item = items.find { it.itemId == itemId }\n\t\t\t\tval itemPos = items.indexOfFirst { it.itemId == itemId }\n\t\t\t\tcartList = items.toMutableList()\n\t\t\t\tif (item != null) {\n\t\t\t\t\titem.quantity = item.quantity + value\n\t\t\t\t\tval deferredRes = async {\n\t\t\t\t\t\tauthRepository.updateCartItemByUserId(item, currentUser!!)\n\t\t\t\t\t}\n\t\t\t\t\tval res = deferredRes.await()\n\t\t\t\t\tif (res is Success) {\n\t\t\t\t\t\tcartList[itemPos] = item\n\t\t\t\t\t\t_cartItems.value = cartList\n\t\t\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\t\t\tif (res is Error)\n\t\t\t\t\t\t\tLog.d(TAG, \"onUpdateQuantity: Error Occurred: ${res.exception.message}\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfun deleteItemFromCart(itemId: String) {\n\t\tviewModelScope.launch {\n//\t\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\t\tvar cartList: MutableList<UserData.CartItem>\n\t\t\t_cartItems.value?.let { items ->\n\t\t\t\tval itemPos = items.indexOfFirst { it.itemId == itemId }\n\t\t\t\tcartList = items.toMutableList()\n\t\t\t\tval deferredRes = async {\n\t\t\t\t\tauthRepository.deleteCartItemByUserId(itemId, currentUser!!)\n\t\t\t\t}\n\t\t\t\tval res = deferredRes.await()\n\t\t\t\tif (res is Success) {\n\t\t\t\t\tcartList.removeAt(itemPos)\n\t\t\t\t\t_cartItems.value = cartList\n\t\t\t\t\tval priceRes = async { getAllProductsInCart() }\n\t\t\t\t\tpriceRes.await()\n\t\t\t\t} else {\n\t\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t\t\tif (res is Error)\n\t\t\t\t\t\tLog.d(TAG, \"onUpdateQuantity: Error Occurred: ${res.exception.message}\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfun setSelectedAddress(addressId: String) {\n\t\t_selectedAddress.value = addressId\n\t}\n\n\tfun setSelectedPaymentMethod(method: String) {\n\t\t_selectedPaymentMethod.value = method\n\t}\n\n\tfun finalizeOrder() {\n\t\t_orderStatus.value = StoreDataStatus.LOADING\n\t\tval deliveryAddress =\n\t\t\t_userAddresses.value?.find { it.addressId == _selectedAddress.value }\n\t\tval paymentMethod = _selectedPaymentMethod.value\n\t\tval currDate = Date()\n\t\tval orderId = getRandomString(6, currDate.time.toString(), 1)\n\t\tval items = _cartItems.value\n\t\tval itemPrices = _priceList.value\n\t\tval shippingCharges = 0.0\n\t\tif (deliveryAddress != null && paymentMethod != null && !items.isNullOrEmpty() && !itemPrices.isNullOrEmpty()) {\n\t\t\tval newOrder = UserData.OrderItem(\n\t\t\t\torderId,\n\t\t\t\tcurrentUser!!,\n\t\t\t\titems,\n\t\t\t\titemPrices,\n\t\t\t\tdeliveryAddress,\n\t\t\t\tshippingCharges,\n\t\t\t\tpaymentMethod,\n\t\t\t\tcurrDate,\n\t\t\t)\n\t\t\tnewOrderData.value = newOrder\n\t\t\tinsertOrder()\n\t\t} else {\n\t\t\tLog.d(TAG, \"orFinalizeOrder: Error, data null or empty\")\n\t\t\t_orderStatus.value = StoreDataStatus.ERROR\n\t\t}\n\t}\n\n\tprivate fun insertOrder() {\n\t\tviewModelScope.launch {\n\t\t\tif (newOrderData.value != null) {\n\t\t\t\t_orderStatus.value = StoreDataStatus.LOADING\n\t\t\t\tval deferredRes = async {\n\t\t\t\t\tauthRepository.placeOrder(newOrderData.value!!, currentUser!!)\n\t\t\t\t}\n\t\t\t\tval res = deferredRes.await()\n\t\t\t\tif (res is Success) {\n\t\t\t\t\tLog.d(TAG, \"onInsertOrder: Success\")\n\t\t\t\t\t_cartItems.value = emptyList()\n\t\t\t\t\t_cartProducts.value = emptyList()\n\t\t\t\t\t_priceList.value = emptyMap()\n\t\t\t\t\t_orderStatus.value = StoreDataStatus.DONE\n\t\t\t\t} else {\n\t\t\t\t\t_orderStatus.value = StoreDataStatus.ERROR\n\t\t\t\t\tif (res is Error) {\n\t\t\t\t\t\tLog.d(TAG, \"onInsertOrder: Error, ${res.exception}\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tLog.d(TAG, \"orInsertOrder: Error, newProduct Null\")\n\t\t\t\t_orderStatus.value = StoreDataStatus.ERROR\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate suspend fun getAllProductsInCart() {\n\t\tviewModelScope.launch {\n//\t\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\t\tval priceMap = mutableMapOf<String, Double>()\n\t\t\tval proList = mutableListOf<Product>()\n\t\t\tvar res = true\n\t\t\t_cartItems.value?.let { itemList ->\n\t\t\t\titemList.forEach label@{ item ->\n\t\t\t\t\tval productDeferredRes = async {\n\t\t\t\t\t\tproductsRepository.getProductById(item.productId, true)\n\t\t\t\t\t}\n\t\t\t\t\tval proRes = productDeferredRes.await()\n\t\t\t\t\tif (proRes is Success) {\n\t\t\t\t\t\tval proData = proRes.data\n\t\t\t\t\t\tproList.add(proData)\n\t\t\t\t\t\tpriceMap[item.itemId] = proData.price\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres = false\n\t\t\t\t\t\treturn@label\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t_priceList.value = priceMap\n\t\t\t_cartProducts.value = proList\n\t\t\tif (!res) {\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t} else {\n\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/viewModels/OtpViewModel.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport android.app.Application\nimport android.util.Log\nimport androidx.fragment.app.FragmentActivity\nimport androidx.lifecycle.AndroidViewModel\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.viewModelScope\nimport com.google.firebase.FirebaseException\nimport com.google.firebase.FirebaseTooManyRequestsException\nimport com.google.firebase.auth.FirebaseAuthInvalidCredentialsException\nimport com.google.firebase.auth.PhoneAuthCredential\nimport com.google.firebase.auth.PhoneAuthOptions\nimport com.google.firebase.auth.PhoneAuthProvider\nimport com.vishalgaur.shoppingapp.ShoppingApplication\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.shouldBypassOTPValidation\nimport com.vishalgaur.shoppingapp.ui.OTPStatus\nimport kotlinx.coroutines.launch\nimport java.util.concurrent.TimeUnit\n\nprivate const val TAG = \"OtpViewModel\"\n\nclass OtpViewModel(application: Application, private val uData: UserData) :\n\tAndroidViewModel(application) {\n\n\tprivate val _otpStatus = MutableLiveData<OTPStatus>()\n\tval otpStatus: LiveData<OTPStatus> get() = _otpStatus\n\n\tprivate val _isOTPSent = MutableLiveData<Boolean>()\n\tval isOTPSent: LiveData<Boolean> get() = _isOTPSent\n\n\tprivate val authRepository = (application as ShoppingApplication).authRepository\n\n\tvar isUserLoggedIn = MutableLiveData(false)\n\tvar storedVerificationId: String? = \"\"\n\tprivate var verificationInProgress = false\n\tprivate lateinit var resendToken: PhoneAuthProvider.ForceResendingToken\n\n\tinit {\n\t\t_isOTPSent.value = false\n\t}\n\n\tfun verifyOTP(otp: String) {\n\t\tviewModelScope.launch {\n\t\t\tverifyPhoneWithCode(storedVerificationId!!, otp, isUserLoggedIn)\n\t\t}\n\t}\n\n\tfun signUp() {\n\t\tviewModelScope.launch {\n\t\t\tauthRepository.signUp(uData)\n\t\t}\n\t}\n\n\tfun login(rememberMe: Boolean) {\n\t\tviewModelScope.launch {\n\t\t\tauthRepository.login(uData, rememberMe)\n\t\t}\n\t}\n\n\tfun verifyPhoneOTPStart(phoneNumber: String, activity: FragmentActivity) {\n\t\tval options = PhoneAuthOptions.newBuilder(authRepository.getFirebaseAuth())\n\t\t\t.setPhoneNumber(phoneNumber)       // Phone number to verify\n\t\t\t.setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit\n\t\t\t.setActivity(activity)                 // Activity (for callback binding)\n\t\t\t.setCallbacks(callbacks)          // OnVerificationStateChangedCallbacks\n\t\t\t.build()\n\t\tPhoneAuthProvider.verifyPhoneNumber(options)\n\n\t\tverificationInProgress = true\n\t}\n\n\tfun manuallyOverrideVerification() {\n\t\tif (shouldBypassOTPValidation())\n\t\t\tisUserLoggedIn.value = true\n\t}\n\n\tprivate val callbacks = object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {\n\n\t\toverride fun onVerificationCompleted(credential: PhoneAuthCredential) {\n\t\t\tLog.d(TAG, \"onVerificationCompleted:$credential\")\n\t\t\t_otpStatus.value = OTPStatus.CORRECT\n\t\t\tauthRepository.signInWithPhoneAuthCredential(credential, isUserLoggedIn, application.applicationContext)\n\t\t}\n\n\t\toverride fun onVerificationFailed(e: FirebaseException) {\n\t\t\tLog.w(TAG, \"onVerificationFailed\", e)\n\t\t\t_otpStatus.value = OTPStatus.INVALID_REQ\n\t\t\tif (e is FirebaseAuthInvalidCredentialsException) {\n\t\t\t\tLog.w(TAG, \"onVerificationFailed, invalid request, \", e)\n\t\t\t} else if (e is FirebaseTooManyRequestsException) {\n\t\t\t\tLog.w(TAG, \"onVerificationFailed, sms quota exceeded, \", e)\n\t\t\t}\n\t\t}\n\n\t\toverride fun onCodeSent(\n\t\t\tverificationId: String,\n\t\t\ttoken: PhoneAuthProvider.ForceResendingToken\n\t\t) {\n\t\t\t// Save verification ID and resending token so we can use them later\n\t\t\tstoredVerificationId = verificationId\n\t\t\tresendToken = token\n\t\t\tLog.w(TAG, \"OTP SENT\")\n\t\t\t_isOTPSent.value = true\n\t\t\t_otpStatus.value = OTPStatus.NONE\n\t\t}\n\t}\n\n\tprivate fun verifyPhoneWithCode(verificationId: String, code: String, isUserLoggedIn: MutableLiveData<Boolean>) {\n\t\ttry {\n\t\t\tval credential = PhoneAuthProvider.getCredential(verificationId, code)\n\t\t\tauthRepository.signInWithPhoneAuthCredential(credential, isUserLoggedIn, getApplication<ShoppingApplication>().applicationContext)\n\t\t} catch (e: Exception) {\n\t\t\tLog.d(TAG, \"onVerifyWithCode: Exception Occurred: ${e.message}\")\n\t\t\t_otpStatus.value = OTPStatus.INVALID_REQ\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/java/com/vishalgaur/shoppingapp/viewModels/ProductViewModel.kt",
    "content": "package com.vishalgaur.shoppingapp.viewModels\n\nimport android.app.Application\nimport android.util.Log\nimport androidx.lifecycle.AndroidViewModel\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.viewModelScope\nimport com.vishalgaur.shoppingapp.ShoppingApplication\nimport com.vishalgaur.shoppingapp.data.Product\nimport com.vishalgaur.shoppingapp.data.Result.Error\nimport com.vishalgaur.shoppingapp.data.Result.Success\nimport com.vishalgaur.shoppingapp.data.ShoppingAppSessionManager\nimport com.vishalgaur.shoppingapp.data.UserData\nimport com.vishalgaur.shoppingapp.data.utils.AddObjectStatus\nimport com.vishalgaur.shoppingapp.data.utils.StoreDataStatus\nimport com.vishalgaur.shoppingapp.ui.AddItemErrors\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.launch\nimport java.util.*\n\nprivate const val TAG = \"ProductViewModel\"\n\nclass ProductViewModel(private val productId: String, application: Application) :\n\tAndroidViewModel(application) {\n\n\tprivate val _productData = MutableLiveData<Product?>()\n\tval productData: LiveData<Product?> get() = _productData\n\n\tprivate val _dataStatus = MutableLiveData<StoreDataStatus>()\n\tval dataStatus: LiveData<StoreDataStatus> get() = _dataStatus\n\n\tprivate val _errorStatus = MutableLiveData<List<AddItemErrors>>()\n\tval errorStatus: LiveData<List<AddItemErrors>> get() = _errorStatus\n\n\tprivate val _addItemStatus = MutableLiveData<AddObjectStatus?>()\n\tval addItemStatus: LiveData<AddObjectStatus?> get() = _addItemStatus\n\n\tprivate val _isLiked = MutableLiveData<Boolean>()\n\tval isLiked: LiveData<Boolean> get() = _isLiked\n\n\tprivate val _isItemInCart = MutableLiveData<Boolean>()\n\tval isItemInCart: LiveData<Boolean> get() = _isItemInCart\n\n\tprivate val productsRepository =(application as ShoppingApplication).productsRepository\n\tprivate val authRepository = (application as ShoppingApplication).authRepository\n\tprivate val sessionManager = ShoppingAppSessionManager(application.applicationContext)\n\tprivate val currentUserId = sessionManager.getUserIdFromSession()\n\n\tinit {\n\t\t_isLiked.value = false\n\t\t_errorStatus.value = emptyList()\n\t\tviewModelScope.launch {\n\t\t\tLog.d(TAG, \"init: productId: $productId\")\n\t\t\tgetProductDetails()\n\t\t\tcheckIfInCart()\n\t\t\tsetLike()\n\t\t}\n\n\t}\n\n\tprivate fun getProductDetails() {\n\t\tviewModelScope.launch {\n\t\t\t_dataStatus.value = StoreDataStatus.LOADING\n\t\t\ttry {\n\t\t\t\tLog.d(TAG, \"getting product Data\")\n\t\t\t\tval res = productsRepository.getProductById(productId)\n\t\t\t\tif (res is Success) {\n\t\t\t\t\t_productData.value = res.data\n\t\t\t\t\t_dataStatus.value = StoreDataStatus.DONE\n\t\t\t\t} else if (res is Error) {\n\t\t\t\t\tthrow Exception(\"Error getting product\")\n\t\t\t\t}\n\t\t\t} catch (e: Exception) {\n\t\t\t\t_productData.value = Product()\n\t\t\t\t_dataStatus.value = StoreDataStatus.ERROR\n\t\t\t}\n\t\t}\n\t}\n\n\tfun setLike() {\n\t\tviewModelScope.launch {\n\t\t\tval res = authRepository.getLikesByUserId(currentUserId!!)\n\t\t\tif (res is Success) {\n\t\t\t\tval userLikes = res.data ?: emptyList()\n\t\t\t\t_isLiked.value = userLikes.contains(productId)\n\t\t\t\tLog.d(TAG, \"Setting Like: Success, value = ${_isLiked.value}, ${res.data?.size}\")\n\t\t\t} else {\n\t\t\t\tif (res is Error)\n\t\t\t\t\tLog.d(TAG, \"Getting Likes: Error Occurred, ${res.exception.message}\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun toggleLikeProduct() {\n\t\tLog.d(TAG, \"toggling Like\")\n\t\tviewModelScope.launch {\n\t\t\tval deferredRes = async {\n\t\t\t\tif (_isLiked.value == true) {\n\t\t\t\t\tauthRepository.removeProductFromLikes(productId, currentUserId!!)\n\t\t\t\t} else {\n\t\t\t\t\tauthRepository.insertProductToLikes(productId, currentUserId!!)\n\t\t\t\t}\n\t\t\t}\n\t\t\tval res = deferredRes.await()\n\t\t\tif (res is Success) {\n\t\t\t\t_isLiked.value = !_isLiked.value!!\n\t\t\t} else{\n\t\t\t\tif(res is Error)\n\t\t\t\t\tLog.d(TAG, \"Error toggling like, ${res.exception}\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfun isSeller() = sessionManager.isUserSeller()\n\n\tfun checkIfInCart() {\n\t\tviewModelScope.launch {\n\t\t\tval deferredRes = async { authRepository.getUserData(currentUserId!!) }\n\t\t\tval userRes = deferredRes.await()\n\t\t\tif (userRes is Success) {\n\t\t\t\tval uData = userRes.data\n\t\t\t\tif (uData != null) {\n\t\t\t\t\tval cartList = uData.cart\n\t\t\t\t\tval idx = cartList.indexOfFirst { it.productId == productId }\n\t\t\t\t\t_isItemInCart.value = idx >= 0\n\t\t\t\t\tLog.d(TAG, \"Checking in Cart: Success, value = ${_isItemInCart.value}, ${cartList.size}\")\n\t\t\t\t} else {\n\t\t\t\t\t_isItemInCart.value = false\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t_isItemInCart.value = false\n\t\t\t}\n\t\t}\n\t}\n\n\tfun addToCart(size: Int?, color: String?) {\n\t\tval errList = mutableListOf<AddItemErrors>()\n\t\tif (size == null) errList.add(AddItemErrors.ERROR_SIZE)\n\t\tif (color.isNullOrBlank()) errList.add(AddItemErrors.ERROR_COLOR)\n\n\t\tif (errList.isEmpty()) {\n\t\t\tval itemId = UUID.randomUUID().toString()\n\t\t\tval newItem = UserData.CartItem(\n\t\t\t\titemId, productId, productData.value!!.owner, 1, color, size\n\t\t\t)\n\t\t\tinsertCartItem(newItem)\n\t\t}\n\t}\n\n\tprivate fun insertCartItem(item: UserData.CartItem) {\n\t\tviewModelScope.launch {\n\t\t\t_addItemStatus.value = AddObjectStatus.ADDING\n\t\t\tval deferredRes = async {\n\t\t\t\tauthRepository.insertCartItemByUserId(item, currentUserId!!)\n\t\t\t}\n\t\t\tval res = deferredRes.await()\n\t\t\tif (res is Success) {\n\t\t\t\tLog.d(TAG, \"onAddItem: Success\")\n\t\t\t\t_addItemStatus.value = AddObjectStatus.DONE\n\t\t\t} else {\n\t\t\t\t_addItemStatus.value = AddObjectStatus.ERR_ADD\n\t\t\t\tif (res is Error) {\n\t\t\t\t\tLog.d(TAG, \"onAddItem: Error, ${res.exception.message}\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "app/src/main/res/drawable/address_account_drawable.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n        android:width=\"32dp\"\n        android:height=\"32dp\"\n        android:drawable=\"@drawable/ic_filled_location_on_24\" />\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/avatar_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:innerRadius=\"0dp\"\n    android:shape=\"ring\"\n    android:thicknessRatio=\"2.0\"\n    android:useLevel=\"false\">\n    <stroke\n        android:width=\"4dp\"\n        android:color=\"@color/blue_accent_300\" />\n    <solid android:color=\"@color/white\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/bottom_nav_selector.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:color=\"@color/blue_accent_300\" android:state_checked=\"true\" />\n    <item android:color=\"@color/light_gray\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/btn_gradient.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <gradient\n        android:angle=\"360\"\n        android:endColor=\"@color/blue_500\"\n        android:startColor=\"@color/blue_200\"\n        android:type=\"linear\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/card_item_selector.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <item android:state_checked=\"true\" app:strokeColor=\"@color/blue_accent_300\" app:strokeWidth=\"2dp\" />\n    <item app:strokeColor=\"@color/light_gray\" app:strokeWidth=\"1dp\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/color_radio_normal.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"oval\">\n    <stroke\n        android:width=\"0.5dp\"\n        android:color=\"#CCCCCC\" />\n    <solid android:color=\"@color/transparent\" />\n    <size\n        android:width=\"48dp\"\n        android:height=\"48dp\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/color_radio_selected.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <!-- Larger blue circle in back -->\n    <item>\n        <shape android:shape=\"oval\">\n            <solid android:color=\"@color/transparent\" />\n            <stroke\n                android:color=\"#CCCCCC\"\n                android:width=\"0.5dp\" />\n            <size\n                android:width=\"48dp\"\n                android:height=\"48dp\" />\n        </shape>\n    </item>\n    <!-- Smaller white circle in front -->\n    <item>\n        <shape android:shape=\"oval\">\n            <!-- transparent stroke = larger_circle_size - smaller_circle_size -->\n            <stroke\n                android:color=\"@android:color/transparent\"\n                android:width=\"32dp\" />\n            <solid android:color=\"#EEEEEE\" />\n            <size\n                android:width=\"16dp\"\n                android:height=\"16dp\" />\n        </shape>\n    </item>\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/color_radio_selector.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@drawable/color_radio_selected\" android:state_checked=\"true\" />\n    <item android:drawable=\"@drawable/color_radio_normal\" android:state_checked=\"false\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/dotted_line_drawable.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"line\">\n\n    <stroke\n        android:color=\"@color/gray\"\n        android:dashWidth=\"20px\"\n        android:dashGap=\"10px\"\n        android:width=\"1dp\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/heart_icon_drawable.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24.0\"\n    android:viewportHeight=\"24.0\">\n    <path\n        android:strokeColor=\"@color/gray\"\n        android:strokeWidth=\"2\"\n        android:pathData=\"M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_add_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_add_48.xml",
    "content": "<vector android:height=\"48dp\"\n    android:tint=\"@color/blue_accent_300\"\n    android:viewportHeight=\"24\"\n    android:viewportWidth=\"24\"\n    android:width=\"48dp\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path\n        android:fillColor=\"@android:color/white\"\n        android:pathData=\"M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_add_shopping_cart_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M11,9h2L13,6h3L16,4h-3L13,1h-2v3L8,4v2h3v3zM7,18c-1.1,0 -1.99,0.9 -1.99,2S5.9,22 7,22s2,-0.9 2,-2 -0.9,-2 -2,-2zM17,18c-1.1,0 -1.99,0.9 -1.99,2s0.89,2 1.99,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM7.17,14.75l0.03,-0.12 0.9,-1.63h7.45c0.75,0 1.41,-0.41 1.75,-1.03l3.86,-7.01L19.42,4h-0.01l-1.1,2 -2.76,5L8.53,11l-0.13,-0.27L6.16,6l-0.95,-2 -0.94,-2L1,2v2h2l3.6,7.59 -1.35,2.45c-0.16,0.28 -0.25,0.61 -0.25,0.96 0,1.1 0.9,2 2,2h12v-2L7.42,15c-0.13,0 -0.25,-0.11 -0.25,-0.25z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_baseline_person_24.xml",
    "content": "<vector android:height=\"64dp\" android:tint=\"?attr/colorControlNormal\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"64dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_baseline_shopping_cart_24.xml",
    "content": "<vector android:height=\"64dp\" android:tint=\"?attr/colorControlNormal\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"64dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M7,18c-1.1,0 -1.99,0.9 -1.99,2S5.9,22 7,22s2,-0.9 2,-2 -0.9,-2 -2,-2zM1,2v2h2l3.6,7.59 -1.35,2.45c-0.16,0.28 -0.25,0.61 -0.25,0.96 0,1.1 0.9,2 2,2h12v-2L7.42,15c-0.14,0 -0.25,-0.11 -0.25,-0.25l0.03,-0.12 0.9,-1.63h7.45c0.75,0 1.41,-0.41 1.75,-1.03l3.58,-6.49c0.08,-0.14 0.12,-0.31 0.12,-0.48 0,-0.55 -0.45,-1 -1,-1L5.21,4l-0.94,-2L1,2zM17,18c-1.1,0 -1.99,0.9 -1.99,2s0.89,2 1.99,2 2,-0.9 2,-2 -0.9,-2 -2,-2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_cancel_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n    <path\n        android:fillColor=\"@android:color/white\"\n        android:pathData=\"M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM16.3,16.3c-0.39,0.39 -1.02,0.39 -1.41,0L12,13.41 9.11,16.3c-0.39,0.39 -1.02,0.39 -1.41,0 -0.39,-0.39 -0.39,-1.02 0,-1.41L10.59,12 7.7,9.11c-0.39,-0.39 -0.39,-1.02 0,-1.41 0.39,-0.39 1.02,-0.39 1.41,0L12,10.59l2.89,-2.89c0.39,-0.39 1.02,-0.39 1.41,0 0.39,0.39 0.39,1.02 0,1.41L13.41,12l2.89,2.89c0.38,0.38 0.38,1.02 0,1.41z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_chevron_left_48.xml",
    "content": "<vector android:height=\"48dp\"\n    android:tint=\"?attr/colorControlNormal\"\n    android:viewportHeight=\"24\"\n    android:viewportWidth=\"24\"\n    android:width=\"48dp\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path\n        android:fillColor=\"@android:color/white\"\n        android:pathData=\"M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_delete_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n    <path\n        android:fillColor=\"@android:color/white\"\n        android:pathData=\"M16,9v10H8V9h8m-1.5,-6h-5l-1,1H5v2h14V4h-3.5l-1,-1zM18,7H6v12c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_edit_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n    <path\n        android:fillColor=\"@android:color/white\"\n        android:pathData=\"M3,17.46v3.04c0,0.28 0.22,0.5 0.5,0.5h3.04c0.13,0 0.26,-0.05 0.35,-0.15L17.81,9.94l-3.75,-3.75L3.15,17.1c-0.1,0.1 -0.15,0.22 -0.15,0.36zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_favorite_filled_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_favorite_outlined_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"@color/gray\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3 4.42,3 2,5.42 2,8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5 22,5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1 -0.1,-0.1C7.14,14.24 4,11.39 4,8.5 4,6.5 5.5,5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5 0,2.89 -3.14,5.74 -7.9,10.05z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_filled_check_circle_24.xml",
    "content": "<vector android:height=\"48dp\" android:tint=\"?attr/colorControlNormal\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"48dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_filled_library_books_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\"\n    android:autoMirrored=\"true\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M4,6L2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6zM20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM19,11L9,11L9,9h10v2zM15,15L9,15v-2h6v2zM19,7L9,7L9,5h10v2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_filled_location_on_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_filled_logout_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\"\n    android:autoMirrored=\"true\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M17,7l-1.41,1.41L18.17,11H8v2h10.17l-2.58,2.58L17,17l5,-5zM4,5h8V3H4c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h8v-2H4V5z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_filled_person_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_filter_alt_24.xml",
    "content": "<vector android:height=\"24dp\"\n    android:tint=\"#AAAAAA\"\n    android:viewportHeight=\"24\"\n    android:viewportWidth=\"24\"\n    android:width=\"24dp\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path\n        android:fillColor=\"@android:color/white\"\n        android:pathData=\"M7,6h10l-5.01,6.3L7,6zM4.25,5.61C6.27,8.2 10,13 10,13v6c0,0.55 0.45,1 1,1h2c0.55,0 1,-0.45 1,-1v-6c0,0 3.72,-4.8 5.74,-7.39C20.25,4.95 19.78,4 18.95,4H5.04C4.21,4 3.74,4.95 4.25,5.61z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path\n        android:fillColor=\"#3DDC84\"\n        android:pathData=\"M0,0h108v108h-108z\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M9,0L9,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,0L19,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,0L29,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,0L39,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,0L49,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,0L59,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,0L69,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,0L79,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M89,0L89,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M99,0L99,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,9L108,9\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,19L108,19\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,29L108,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,39L108,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,49L108,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,59L108,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,69L108,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,79L108,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,89L108,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,99L108,99\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,29L89,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,39L89,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,49L89,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,59L89,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,69L89,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,79L89,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,19L29,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,19L39,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,19L49,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,19L59,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,19L69,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,19L79,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_menu_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n    <path\n        android:fillColor=\"@android:color/white\"\n        android:pathData=\"M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_arrow_back_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\"\n    android:autoMirrored=\"true\">\n    <path\n        android:fillColor=\"@android:color/white\"\n        android:pathData=\"M17.51,3.87L15.73,2.1 5.84,12l9.9,9.9 1.77,-1.77L9.38,12l8.13,-8.13z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_email_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M22,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6zM20,6l-8,5 -8,-5h16zM20,18L4,18L4,8l8,5 8,-5v10z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_library_books_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\"\n    android:autoMirrored=\"true\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M4,6L2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6zM20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM20,16L8,16L8,4h12v12zM10,9h8v2h-8zM10,12h4v2h-4zM10,6h8v2h-8z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outline_phone_android_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M16,1L8,1C6.34,1 5,2.34 5,4v16c0,1.66 1.34,3 3,3h8c1.66,0 3,-1.34 3,-3L19,4c0,-1.66 -1.34,-3 -3,-3zM17,18L7,18L7,4h10v14zM14,21h-4v-1h4v1z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outlined_home_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M12,5.69l5,4.5V18h-2v-6H9v6H7v-7.81l5,-4.5M12,3L2,12h3v8h6v-6h2v6h6v-8h3L12,3z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outlined_person_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M12,6c1.1,0 2,0.9 2,2s-0.9,2 -2,2 -2,-0.9 -2,-2 0.9,-2 2,-2m0,10c2.7,0 5.8,1.29 6,2L6,18c0.23,-0.72 3.31,-2 6,-2m0,-12C9.79,4 8,5.79 8,8s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_outlined_shopping_cart_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M15.55,13c0.75,0 1.41,-0.41 1.75,-1.03l3.58,-6.49c0.37,-0.66 -0.11,-1.48 -0.87,-1.48L5.21,4l-0.94,-2L1,2v2h2l3.6,7.59 -1.35,2.44C4.52,15.37 5.48,17 7,17h12v-2L7,15l1.1,-2h7.45zM6.16,6h12.15l-2.76,5L8.53,11L6.16,6zM7,18c-1.1,0 -1.99,0.9 -1.99,2S5.9,22 7,22s2,-0.9 2,-2 -0.9,-2 -2,-2zM17,18c-1.1,0 -1.99,0.9 -1.99,2s0.89,2 1.99,2 2,-0.9 2,-2 -0.9,-2 -2,-2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_remove_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M19,13H5v-2h14v2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_remove_shopping_cart_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"?attr/colorControlNormal\">\n  <path\n      android:fillColor=\"@android:color/white\"\n      android:pathData=\"M22.73,22.73L2.77,2.77 2,2l-0.73,-0.73L0,2.54l4.39,4.39 2.21,4.66 -1.35,2.45c-0.16,0.28 -0.25,0.61 -0.25,0.96 0,1.1 0.9,2 2,2h7.46l1.38,1.38c-0.5,0.36 -0.83,0.95 -0.83,1.62 0,1.1 0.89,2 1.99,2 0.67,0 1.26,-0.33 1.62,-0.84L21.46,24l1.27,-1.27zM7.42,15c-0.14,0 -0.25,-0.11 -0.25,-0.25l0.03,-0.12 0.9,-1.63h2.36l2,2L7.42,15zM15.55,13c0.75,0 1.41,-0.41 1.75,-1.03l3.58,-6.49c0.08,-0.14 0.12,-0.31 0.12,-0.48 0,-0.55 -0.45,-1 -1,-1L6.54,4l9.01,9zM7,18c-1.1,0 -1.99,0.9 -1.99,2S5.9,22 7,22s2,-0.9 2,-2 -0.9,-2 -2,-2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_search_24.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    android:tint=\"@color/gray\">\n    <path\n        android:fillColor=\"@android:color/white\"\n        android:pathData=\"M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/layout_background_rounded_corners.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n    <corners android:radius=\"4dp\" />\n    <stroke\n        android:width=\"1dp\"\n        android:color=\"@color/light_gray\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/liked_heart_drawable.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24.0\"\n    android:viewportHeight=\"24.0\">\n    <path\n        android:strokeColor=\"@color/gray\"\n        android:fillColor=\"#FF0000\"\n        android:strokeWidth=\"0.5\"\n        android:pathData=\"M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/login_bg_img.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"200dp\"\n    android:height=\"150dp\"\n    android:viewportWidth=\"950.0\"\n    android:viewportHeight=\"775.0\">\n    <group\n        android:name=\"draws_one\"\n        android:rotation=\"0\">\n\n        <path\n            android:name=\"layout_shadow_path\"\n            android:fillType=\"evenOdd\"\n            android:pathData=\"M 575,0\n            a 275,275 0 0,0 260,110\n             a 55,55 0 1,1 5,115\n              a 200,200 0 0,0 -200,150\n              a 400,400 0 1,1 -850,-275 V0\">\n            <aapt:attr name=\"android:fillColor\">\n                <gradient\n                    android:centerX=\"325\"\n                    android:centerY=\"225\"\n                    android:gradientRadius=\"550\"\n                    android:type=\"radial\">\n                    <item\n                        android:color=\"#004dca\"\n                        android:offset=\"0.0\" />\n                    <item\n                        android:color=\"#FFFFFF\"\n                        android:offset=\"1.0\" />\n                </gradient>\n            </aapt:attr>\n        </path>\n\n        <path\n            android:name=\"layout_path\"\n            android:fillType=\"evenOdd\"\n            android:pathData=\"M 600,0\n            a 250,250 0 0,0 225,70\n             a 60,60 0 1,1 5,125\n             a 200,200 0 0,0 -200,150\n             a 400,400 0 1,1 -850,-250 V0\">\n            <aapt:attr name=\"android:fillColor\">\n                <gradient\n                    android:centerX=\"-50\"\n                    android:centerY=\"325\"\n                    android:gradientRadius=\"600\"\n                    android:type=\"radial\">\n                    <item\n                        android:color=\"#4284ed\"\n                        android:offset=\"0.0\" />\n                    <item\n                        android:color=\"#004dca\"\n                        android:offset=\"1.0\" />\n                </gradient>\n            </aapt:attr>\n        </path>\n    </group>\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/orders_account_drawable.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n        android:width=\"32dp\"\n        android:height=\"32dp\"\n        android:drawable=\"@drawable/ic_filled_library_books_24\" />\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/person_account_drawable.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n        android:width=\"32dp\"\n        android:height=\"32dp\"\n        android:drawable=\"@drawable/ic_filled_person_24\" />\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/radio_normal.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"oval\">\n    <stroke\n        android:width=\"0.5dp\"\n        android:color=\"#CCCCCC\" />\n    <solid android:color=\"@color/transparent\" />\n    <size\n        android:width=\"48dp\"\n        android:height=\"48dp\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/radio_selected.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"oval\">\n    <stroke\n        android:width=\"2dp\"\n        android:color=\"@color/blue_accent_300\" />\n    <size\n        android:height=\"64dp\"\n        android:width=\"64dp\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/radio_selector.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@drawable/radio_selected\" android:state_checked=\"true\" />\n    <item android:drawable=\"@drawable/radio_normal\" android:state_checked=\"false\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/round_button.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"false\">\n        <shape android:shape=\"oval\">\n            <size android:width=\"24dp\" android:height=\"24dp\" />\n            <solid android:color=\"@color/transparent\" />\n        </shape>\n    </item>\n    <item android:state_pressed=\"true\">\n        <shape android:shape=\"oval\">\n            <size android:width=\"24dp\" android:height=\"24dp\" />\n            <solid android:color=\"@color/blue_accent_300\" />\n        </shape>\n    </item>\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/round_outline_rect.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n    <corners android:radius=\"6dp\" />\n    <solid android:color=\"@color/white\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/signout_account_drawable.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n        android:width=\"32dp\"\n        android:height=\"32dp\"\n        android:drawable=\"@drawable/ic_filled_logout_24\" />\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/sl_favourite_24dp.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@drawable/ic_favorite_outlined_24\" android:state_checked=\"false\" />\n    <item android:drawable=\"@drawable/ic_favorite_filled_24\" android:state_checked=\"true\" />\n    <item android:drawable=\"@drawable/ic_favorite_outlined_24\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path android:pathData=\"M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"85.84757\"\n                android:endY=\"92.4963\"\n                android:startX=\"42.9492\"\n                android:startY=\"49.59793\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\" />\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\" />\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        android:pathData=\"M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/font/nunito_sans.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<font-family xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    app:fontProviderAuthority=\"com.google.android.gms.fonts\"\n    app:fontProviderCerts=\"@array/com_google_android_gms_fonts_certs\"\n    app:fontProviderPackage=\"com.google.android.gms\"\n    app:fontProviderQuery=\"Nunito Sans\" />\n"
  },
  {
    "path": "app/src/main/res/font/nunito_sans_extrabold.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<font-family xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        app:fontProviderAuthority=\"com.google.android.gms.fonts\"\n        app:fontProviderPackage=\"com.google.android.gms\"\n        app:fontProviderQuery=\"name=Nunito Sans&amp;weight=800\"\n        app:fontProviderCerts=\"@array/com_google_android_gms_fonts_certs\">\n</font-family>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_launch.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@color/blue_accent_300\">\n\n    <ImageView\n        android:id=\"@+id/imageView\"\n        android:layout_width=\"100dp\"\n        android:layout_height=\"100dp\"\n        android:contentDescription=\"@string/app_icon_img_desc\"\n        android:scaleType=\"fitCenter\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.52\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:srcCompat=\"@drawable/ic_baseline_shopping_cart_24\"\n        app:tint=\"@color/white\" />\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.home.MainActivity\">\n\n    <androidx.fragment.app.FragmentContainerView\n        android:id=\"@+id/home_nav_host_fragment\"\n        android:name=\"androidx.navigation.fragment.NavHostFragment\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        app:defaultNavHost=\"true\"\n        app:layout_constraintBottom_toTopOf=\"@id/home_bottom_navigation\"\n        app:layout_constraintLeft_toLeftOf=\"parent\"\n        app:layout_constraintRight_toRightOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:navGraph=\"@navigation/home_nav_graph\" />\n\n    <com.google.android.material.bottomnavigation.BottomNavigationView\n        android:id=\"@+id/home_bottom_navigation\"\n        style=\"@style/BottomNavigationStyle\"\n        android:layout_width=\"match_parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        android:layout_height=\"wrap_content\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        android:layout_alignParentBottom=\"true\"\n        app:menu=\"@menu/bottom_navigation_menu\" />\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_otp.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.loginSignup.OtpActivity\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        tools:context=\".ui.loginSignup.OtpActivity\">\n\n        <include\n            android:id=\"@+id/loader_layout\"\n            layout=\"@layout/layout_loader_card\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:layout_constraintVertical_bias=\"0.77\" />\n\n        <ImageView\n            android:id=\"@+id/otp_image_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"280dp\"\n            android:contentDescription=\"@string/bg_img_desc\"\n            android:scaleType=\"fitStart\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:srcCompat=\"@drawable/login_bg_img\" />\n\n        <TextView\n            android:id=\"@+id/otp_message_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"64dp\"\n            android:text=\"@string/otp_message_1\"\n            android:textColor=\"@color/white\"\n            android:textSize=\"22sp\"\n            app:layout_constraintStart_toStartOf=\"@id/otp_image_view\"\n            app:layout_constraintTop_toTopOf=\"@id/otp_image_view\" />\n\n        <TextView\n            android:id=\"@+id/otp_message_2_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:text=\"@string/otp_message_2\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline3\"\n            android:textColor=\"@color/white\"\n            android:textStyle=\"bold\"\n            app:layout_constraintStart_toStartOf=\"@id/otp_image_view\"\n            app:layout_constraintTop_toBottomOf=\"@+id/otp_message_tv\" />\n\n        <TextView\n            android:id=\"@+id/otp_label\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"32dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:text=\"@string/otp_label_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline5\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/otp_image_view\" />\n\n        <com.google.android.material.textfield.TextInputLayout\n            android:id=\"@+id/otpOutlinedTextField\"\n            style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"16dp\"\n            android:layout_marginEnd=\"24dp\"\n            app:expandedHintEnabled=\"false\"\n            app:hintTextAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/otp_label\"\n            app:placeholderText=\"@string/otp_otp_ph\"\n            app:placeholderTextAppearance=\"@style/TextAppearance.MyTheme.Body2\">\n\n            <com.google.android.material.textfield.TextInputEditText\n                android:id=\"@+id/otp_otp_edit_text\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:inputType=\"number\"\n                android:maxLength=\"6\"\n                android:paddingTop=\"12dp\"\n                android:paddingBottom=\"12dp\" />\n        </com.google.android.material.textfield.TextInputLayout>\n\n        <TextView\n            android:id=\"@+id/otp_verify_error\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"32dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:text=\"@string/otp_verify_error_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            android:textColor=\"?attr/colorError\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/otpOutlinedTextField\" />\n\n        <Button\n            android:id=\"@+id/otp_verify_btn\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"32dp\"\n            android:layout_marginBottom=\"16dp\"\n            android:layout_weight=\"1\"\n            android:paddingStart=\"32dp\"\n            android:paddingEnd=\"32dp\"\n            android:text=\"@string/otp_verify_btn_text\"\n            android:textAllCaps=\"false\"\n            android:textStyle=\"bold\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/otp_verify_error\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</ScrollView>"
  },
  {
    "path": "app/src/main/res/layout/activity_signup.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.loginSignup.LoginSignupActivity\">\n\n    <androidx.fragment.app.FragmentContainerView\n        android:id=\"@+id/nav_host_fragment\"\n        android:name=\"androidx.navigation.fragment.NavHostFragment\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        app:defaultNavHost=\"true\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintLeft_toLeftOf=\"parent\"\n        app:layout_constraintRight_toRightOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:navGraph=\"@navigation/signup_nav_graph\" />\n\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/add_images_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"-->\n<!--    xmlns:app=\"http://schemas.android.com/apk/res-auto\"-->\n<!--    xmlns:tools=\"http://schemas.android.com/tools\"-->\n<!--    android:layout_width=\"wrap_content\"-->\n<!--    android:layout_height=\"wrap_content\">-->\n\n<!--    <ImageView-->\n<!--        android:id=\"@+id/add_images_image_view\"-->\n<!--        android:layout_width=\"100dp\"-->\n<!--        android:layout_height=\"100dp\"-->\n<!--        android:layout_marginStart=\"16dp\"-->\n<!--        android:layout_marginTop=\"8dp\"-->\n<!--        android:scaleType=\"centerInside\"-->\n<!--        app:layout_constraintEnd_toEndOf=\"parent\"-->\n<!--        app:layout_constraintStart_toStartOf=\"parent\"-->\n<!--        app:layout_constraintTop_toTopOf=\"parent\"-->\n<!--        tools:srcCompat=\"@tools:sample/backgrounds/scenic\" />-->\n<!--</androidx.constraintlayout.widget.ConstraintLayout>-->\n\n<com.google.android.material.card.MaterialCardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:layout_marginStart=\"16dp\"\n    android:layout_marginTop=\"8dp\"\n    android:layout_marginBottom=\"8dp\"\n    app:cardElevation=\"4dp\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\">\n\n        <ImageView\n            android:id=\"@+id/add_images_image_view\"\n            android:layout_width=\"120dp\"\n            android:layout_height=\"80dp\"\n            android:layout_marginStart=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_marginEnd=\"8dp\"\n            android:layout_marginBottom=\"8dp\"\n            android:contentDescription=\"@string/add_img_item_desc\"\n            android:scaleType=\"centerInside\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:srcCompat=\"@tools:sample/backgrounds/scenic\" />\n\n        <ImageView\n            android:id=\"@+id/add_img_close_btn\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"@null\"\n            android:contentDescription=\"@string/add_img_close_btn_desc\"\n            android:scaleType=\"centerCrop\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:srcCompat=\"@drawable/ic_cancel_24\"\n            app:tint=\"@color/blue_accent_300\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</com.google.android.material.card.MaterialCardView>"
  },
  {
    "path": "app/src/main/res/layout/cart_list_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.card.MaterialCardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/product_card\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_margin=\"8dp\"\n    android:clickable=\"false\"\n    android:focusable=\"true\"\n    app:cardElevation=\"0dp\"\n    app:strokeColor=\"#CCCCCC\"\n    app:strokeWidth=\"1dp\">\n\n    <include\n        android:id=\"@+id/loader_layout\"\n        layout=\"@layout/layout_circular_loader\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"8dp\">\n\n        <ImageView\n            android:id=\"@+id/product_image_view\"\n            android:layout_width=\"100dp\"\n            android:layout_height=\"100dp\"\n            android:layout_marginStart=\"8dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_marginBottom=\"8dp\"\n            android:background=\"@drawable/round_outline_rect\"\n            android:contentDescription=\"@string/add_img_item_desc\"\n            android:scaleType=\"centerCrop\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:srcCompat=\"@tools:sample/backgrounds/scenic\" />\n\n        <TextView\n            android:id=\"@+id/cart_product_title_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_marginEnd=\"8dp\"\n            android:lines=\"2\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textStyle=\"bold\"\n            app:layout_constraintEnd_toStartOf=\"@+id/cart_product_like_btn\"\n            app:layout_constraintStart_toEndOf=\"@+id/product_image_view\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:text=\"some title may be two lines\" />\n\n        <ImageButton\n            android:id=\"@+id/cart_product_like_btn\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginEnd=\"8dp\"\n            android:background=\"@drawable/round_button\"\n            android:backgroundTint=\"#FFFFFF\"\n            android:contentDescription=\"@string/pro_details_like_btn_desc\"\n            android:scaleType=\"center\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/cart_product_title_tv\"\n            app:layout_constraintEnd_toStartOf=\"@+id/cart_product_delete_btn\"\n            app:layout_constraintTop_toTopOf=\"@+id/cart_product_title_tv\"\n            app:layout_constraintVertical_bias=\"0.0\"\n            app:srcCompat=\"@drawable/heart_icon_drawable\" />\n\n        <ImageButton\n            android:id=\"@+id/cart_product_delete_btn\"\n            android:layout_width=\"30dp\"\n            android:layout_height=\"30dp\"\n            android:layout_marginEnd=\"8dp\"\n            android:background=\"@drawable/round_button\"\n            android:contentDescription=\"@string/pro_details_delete_btn_desc\"\n            android:scaleType=\"fitXY\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/cart_product_like_btn\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"@+id/cart_product_like_btn\"\n            app:srcCompat=\"@drawable/ic_delete_24\"\n            app:tint=\"@color/gray\" />\n\n        <TextView\n            android:id=\"@+id/cart_product_price_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginBottom=\"8dp\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/blue_accent_300\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toEndOf=\"@+id/product_image_view\"\n            app:layout_constraintTop_toBottomOf=\"@+id/cart_product_title_tv\"\n            app:layout_constraintVertical_bias=\"1.0\"\n            tools:text=\"$1234.56\" />\n\n        <LinearLayout\n            android:id=\"@+id/cart_product_quantity_buttons_layout\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginEnd=\"8dp\"\n            android:background=\"@drawable/layout_background_rounded_corners\"\n            android:orientation=\"horizontal\"\n            app:layout_constraintBottom_toBottomOf=\"@id/cart_product_price_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"1.0\"\n            app:layout_constraintStart_toEndOf=\"@id/cart_product_price_tv\"\n            app:layout_constraintTop_toTopOf=\"@+id/cart_product_price_tv\"\n            app:layout_constraintVertical_bias=\"1.0\">\n\n            <ImageButton\n                android:id=\"@+id/cart_product_minus_btn\"\n                android:layout_width=\"36dp\"\n                android:layout_height=\"30dp\"\n                android:layout_weight=\"1\"\n                android:background=\"@null\"\n                android:contentDescription=\"@string/minus_btn_desc\"\n                app:srcCompat=\"@drawable/ic_remove_24\" />\n\n            <TextView\n                android:id=\"@+id/cart_product_quantity_text_View\"\n                android:layout_width=\"40dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_weight=\"1\"\n                android:background=\"@color/blue_shadow_color\"\n                android:gravity=\"center_horizontal|center_vertical\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n                android:textSize=\"14sp\"\n                android:textStyle=\"bold\"\n                tools:text=\"123\" />\n\n            <ImageButton\n                android:id=\"@+id/cart_product_plus_btn\"\n                android:layout_width=\"36dp\"\n                android:layout_height=\"30dp\"\n                android:layout_weight=\"1\"\n                android:background=\"@null\"\n                android:contentDescription=\"@string/plus_btn_desc\"\n                app:srcCompat=\"@drawable/ic_add_24\" />\n\n        </LinearLayout>\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</com.google.android.material.card.MaterialCardView>"
  },
  {
    "path": "app/src/main/res/layout/country_list_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<TextView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:ellipsize=\"end\"\n    android:maxLines=\"1\"\n    android:padding=\"16dp\"\n    android:textAppearance=\"?attr/textAppearanceSubtitle1\" />"
  },
  {
    "path": "app/src/main/res/layout/fragment_account.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    tools:context=\".ui.home.AccountFragment\">\n\n    <include\n        android:id=\"@+id/account_top_app_bar\"\n        layout=\"@layout/layout_no_icon_app_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/account_top_app_bar\">\n\n        <TextView\n            android:id=\"@+id/account_profile_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"?attr/selectableItemBackground\"\n            android:clickable=\"true\"\n            android:drawablePadding=\"16dp\"\n            android:focusable=\"true\"\n            android:gravity=\"center_vertical\"\n            android:includeFontPadding=\"false\"\n            android:padding=\"16dp\"\n            android:text=\"@string/account_profile_label\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textSize=\"16sp\"\n            android:textStyle=\"bold\"\n            app:drawableStartCompat=\"@drawable/person_account_drawable\"\n            app:drawableTint=\"@color/blue_accent_300\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <TextView\n            android:id=\"@+id/account_orders_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"?attr/selectableItemBackground\"\n            android:clickable=\"true\"\n            android:drawablePadding=\"16dp\"\n            android:focusable=\"true\"\n            android:gravity=\"center_vertical\"\n            android:includeFontPadding=\"false\"\n            android:padding=\"16dp\"\n            android:text=\"@string/account_orders_label\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textSize=\"16sp\"\n            android:textStyle=\"bold\"\n            app:drawableStartCompat=\"@drawable/orders_account_drawable\"\n            app:drawableTint=\"@color/blue_accent_300\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/account_profile_tv\" />\n\n        <TextView\n            android:id=\"@+id/account_address_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"?attr/selectableItemBackground\"\n            android:clickable=\"true\"\n            android:drawablePadding=\"16dp\"\n            android:focusable=\"true\"\n            android:gravity=\"center_vertical\"\n            android:includeFontPadding=\"false\"\n            android:padding=\"16dp\"\n            android:text=\"@string/account_address_label\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textSize=\"16sp\"\n            android:textStyle=\"bold\"\n            app:drawableStartCompat=\"@drawable/address_account_drawable\"\n            app:drawableTint=\"@color/blue_accent_300\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/account_orders_tv\" />\n\n        <View\n            android:id=\"@+id/divider\"\n            android:layout_width=\"match_parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/account_address_tv\"\n            android:layout_height=\"1dp\"\n            android:background=\"?android:attr/listDivider\" />\n\n        <TextView\n            android:id=\"@+id/account_sign_out_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"?attr/selectableItemBackground\"\n            android:clickable=\"true\"\n            android:drawablePadding=\"16dp\"\n            android:focusable=\"true\"\n            android:gravity=\"center_vertical\"\n            android:includeFontPadding=\"false\"\n            android:padding=\"16dp\"\n            android:text=\"@string/account_sign_out_label\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textSize=\"16sp\"\n            app:drawableStartCompat=\"@drawable/signout_account_drawable\"\n            android:textStyle=\"bold\"\n            app:drawableTint=\"@color/blue_accent_300\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/divider\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_add_edit_address.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    tools:context=\".ui.home.AddEditAddressFragment\">\n\n    <include\n        android:id=\"@+id/add_address_top_app_bar\"\n        layout=\"@layout/layout_top_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <include\n        android:id=\"@+id/loader_layout\"\n        layout=\"@layout/layout_circular_loader\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/add_address_top_app_bar\" />\n\n    <androidx.core.widget.NestedScrollView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@id/add_address_top_app_bar\"\n        android:fillViewport=\"true\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <androidx.constraintlayout.widget.ConstraintLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:layout_marginBottom=\"80dp\">\n\n            <TextView\n                android:id=\"@+id/add_address_country_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_address_country_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toTopOf=\"parent\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/selectCountryTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_address_country_label\">\n\n                <AutoCompleteTextView\n                    android:id=\"@+id/address_country_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:dropDownHeight=\"240dp\"\n                    android:inputType=\"none\"\n                    android:labelFor=\"@id/selectCountryTextField\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_address_first_name_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_address_first_name_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/selectCountryTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/fNameOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_address_first_name_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/address_first_name_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"textPersonName\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_address_last_name_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_address_last_name_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/fNameOutlinedTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/lNameOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_address_last_name_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/address_last_name_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"textPersonName\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_address_street_add_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_address_street_add_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/lNameOutlinedTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/streetAddOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_address_street_add_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/address_street_add_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"text|textPostalAddress\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_address_street_add2_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_address_street_add2_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/streetAddOutlinedTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/streetAdd2OutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_address_street_add2_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/address_street_add2_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"textPostalAddress\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_address_city_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_address_city_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/streetAdd2OutlinedTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/cityOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_address_city_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/address_city_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"textPersonName\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_address_state_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_address_state_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/cityOutlinedTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/stateOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_address_state_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/address_state_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"textPersonName|text\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_address_zipcode_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_address_zipcode_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/stateOutlinedTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/zipCodeOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_address_zipcode_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/address_zipcode_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"number|text\"\n                    android:maxLength=\"6\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_address_phone_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_address_phone_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/zipCodeOutlinedTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/phoneOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_address_phone_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/address_phone_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"text|phone\"\n                    android:maxLength=\"10\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_address_error_text_view\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:gravity=\"center_vertical\"\n                android:text=\"@string/add_pro_error_empty\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n                android:textColor=\"?attr/colorError\"\n                app:drawableStartCompat=\"@android:drawable/stat_notify_error\"\n                app:drawableTint=\"?attr/colorError\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/phoneOutlinedTextField\" />\n\n\n        </androidx.constraintlayout.widget.ConstraintLayout>\n\n    </androidx.core.widget.NestedScrollView>\n\n    <Button\n        android:id=\"@+id/add_address_save_btn\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_marginStart=\"16dp\"\n        android:layout_marginTop=\"16dp\"\n        android:layout_marginEnd=\"16dp\"\n        android:layout_marginBottom=\"8dp\"\n        android:backgroundTint=\"@color/blue_accent_300\"\n        android:padding=\"16dp\"\n        android:text=\"@string/add_address_btn_text\"\n        android:textAllCaps=\"false\"\n        android:textSize=\"16sp\"\n        android:textStyle=\"bold\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_add_edit_product.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/add_pro_app_bar\"\n        layout=\"@layout/layout_top_bar\" />\n\n    <include\n        android:id=\"@+id/loader_layout\"\n        layout=\"@layout/layout_circular_loader\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_gravity=\"center\" />\n\n    <androidx.core.widget.NestedScrollView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:fillViewport=\"true\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <androidx.constraintlayout.widget.ConstraintLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"72dp\">\n\n            <TextView\n                android:id=\"@+id/add_pro_name_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_pro_name_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toTopOf=\"parent\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/nameOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_pro_name_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/pro_name_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"text\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_pro_price_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_pro_price_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/nameOutlinedTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/priceOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_pro_price_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/pro_price_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"numberDecimal\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_pro_mrp_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_pro_mrp_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/priceOutlinedTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/mrpOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_pro_mrp_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/pro_mrp_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:inputType=\"numberDecimal\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_pro_desc_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_pro_desc_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/mrpOutlinedTextField\" />\n\n            <com.google.android.material.textfield.TextInputLayout\n                android:id=\"@+id/descOutlinedTextField\"\n                style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:boxStrokeColor=\"@color/blue_accent_300\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_pro_desc_label\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    android:id=\"@+id/pro_desc_edit_text\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:gravity=\"start|top\"\n                    android:inputType=\"textMultiLine\"\n                    android:minLines=\"3\"\n                    android:paddingTop=\"12dp\"\n                    android:paddingBottom=\"12dp\"\n                    android:textColor=\"@color/gray\"\n                    android:textStyle=\"bold\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <TextView\n                android:id=\"@+id/add_pro_images_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_pro_images_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toStartOf=\"@+id/add_pro_images_btn\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/descOutlinedTextField\" />\n\n            <ImageButton\n                android:id=\"@+id/add_pro_images_btn\"\n                android:layout_width=\"35dp\"\n                android:layout_height=\"40dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:backgroundTint=\"@color/blue_accent_300\"\n                android:contentDescription=\"@string/add_pro_images_label_text\"\n                android:scaleType=\"centerCrop\"\n                android:tint=\"@color/white\"\n                app:layout_constraintBottom_toBottomOf=\"@+id/add_pro_images_label\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintTop_toTopOf=\"@+id/add_pro_images_label\"\n                app:srcCompat=\"@drawable/ic_add_48\" />\n\n            <androidx.recyclerview.widget.RecyclerView\n                android:id=\"@+id/add_pro_images_rv\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"8dp\"\n                android:orientation=\"horizontal\"\n                app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_pro_images_label\"\n                tools:itemCount=\"5\"\n                tools:listitem=\"@layout/add_images_item\" />\n\n            <TextView\n                android:id=\"@+id/add_pro_sizes_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_pro_sizes_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_pro_images_rv\" />\n\n            <com.google.android.material.chip.ChipGroup\n                android:id=\"@+id/add_pro_size_chip_group\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:chipSpacingHorizontal=\"10dp\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_pro_sizes_label\"\n                app:selectionRequired=\"true\">\n\n            </com.google.android.material.chip.ChipGroup>\n\n            <TextView\n                android:id=\"@+id/add_pro_color_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/add_pro_color_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/black\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_pro_size_chip_group\" />\n\n            <com.google.android.material.chip.ChipGroup\n                android:id=\"@+id/add_pro_color_chip_group\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:chipSpacingHorizontal=\"10dp\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_pro_color_label\"\n                app:selectionRequired=\"true\">\n\n            </com.google.android.material.chip.ChipGroup>\n\n            <TextView\n                android:id=\"@+id/add_pro_error_text_view\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:gravity=\"center_vertical\"\n                android:text=\"@string/add_pro_error_empty\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n                android:textColor=\"?attr/colorError\"\n                app:drawableStartCompat=\"@android:drawable/stat_notify_error\"\n                app:drawableTint=\"?attr/colorError\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/add_pro_color_chip_group\" />\n\n        </androidx.constraintlayout.widget.ConstraintLayout>\n\n    </androidx.core.widget.NestedScrollView>\n\n    <Button\n        android:id=\"@+id/add_pro_btn\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center_horizontal|bottom\"\n        android:layout_marginStart=\"16dp\"\n        android:layout_marginTop=\"16dp\"\n        android:layout_marginEnd=\"16dp\"\n        android:layout_marginBottom=\"8dp\"\n        android:backgroundTint=\"@color/blue_accent_300\"\n        android:padding=\"16dp\"\n        android:text=\"@string/app_pro_btn_text\"\n        android:textAllCaps=\"false\"\n        android:textSize=\"16sp\"\n        android:textStyle=\"bold\" />\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_address.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    tools:context=\".ui.home.AddressFragment\">\n\n    <include\n        android:id=\"@+id/address_app_bar\"\n        layout=\"@layout/layout_top_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <include\n        android:id=\"@+id/loader_layout\"\n        layout=\"@layout/layout_circular_loader\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/address_app_bar\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/address_app_bar\"\n        android:layout_marginBottom=\"72dp\">\n\n        <TextView\n            android:id=\"@+id/address_empty_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:fontFamily=\"@font/nunito_sans\"\n            android:text=\"@string/no_addresses_text\"\n            android:textAlignment=\"center\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline3\"\n            android:textColor=\"@color/blue_accent_300\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/address_addresses_recycler_view\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:clipToPadding=\"false\"\n            android:overScrollMode=\"never\"\n            android:padding=\"8dp\"\n            app:flow_horizontalAlign=\"center\"\n            app:flow_verticalAlign=\"center\"\n            app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:itemCount=\"2\"\n            tools:listitem=\"@layout/layout_address_card\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n    <Button\n        android:id=\"@+id/address_add_btn\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_marginStart=\"16dp\"\n        android:layout_marginTop=\"16dp\"\n        android:layout_marginEnd=\"16dp\"\n        android:backgroundTint=\"@color/blue_accent_300\"\n        android:padding=\"16dp\"\n        android:text=\"@string/add_address_btn_text\"\n        android:textAllCaps=\"false\"\n        android:textSize=\"16sp\"\n        android:textStyle=\"bold\"\n        android:translationY=\"-8dp\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_cart.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    tools:context=\".ui.home.CartFragment\">\n\n    <include\n        android:id=\"@+id/cart_app_bar\"\n        layout=\"@layout/layout_no_icon_app_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <include\n        android:id=\"@+id/loader_layout\"\n        layout=\"@layout/layout_circular_loader\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/cart_app_bar\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/cart_app_bar\"\n        android:layout_marginBottom=\"72dp\">\n\n        <TextView\n            android:id=\"@+id/cart_empty_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:fontFamily=\"@font/nunito_sans\"\n            android:text=\"@string/no_items_in_cart_text\"\n            android:textAlignment=\"center\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline3\"\n            android:textColor=\"@color/blue_accent_300\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/cart_products_recycler_view\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:clipToPadding=\"false\"\n            android:overScrollMode=\"never\"\n            android:padding=\"8dp\"\n            app:flow_horizontalAlign=\"center\"\n            app:flow_verticalAlign=\"center\"\n            app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:itemCount=\"2\"\n            tools:listitem=\"@layout/cart_list_item\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n    <Button\n        android:id=\"@+id/cart_check_out_btn\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_marginStart=\"16dp\"\n        android:layout_marginTop=\"16dp\"\n        android:layout_marginEnd=\"16dp\"\n        android:backgroundTint=\"@color/blue_accent_300\"\n        android:padding=\"16dp\"\n        android:text=\"@string/cart_check_out_btn\"\n        android:textAllCaps=\"false\"\n        android:textSize=\"16sp\"\n        android:textStyle=\"bold\"\n        android:translationY=\"-8dp\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_favorites.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    tools:context=\".ui.home.FavoritesFragment\">\n\n    <include\n        android:id=\"@+id/fav_top_app_bar\"\n        layout=\"@layout/layout_top_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/fav_top_app_bar\">\n\n        <TextView\n            android:id=\"@+id/fav_empty_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:fontFamily=\"@font/nunito_sans\"\n            android:text=\"@string/no_likes_text\"\n            android:textAlignment=\"center\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline3\"\n            android:textColor=\"@color/blue_accent_300\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <include\n            android:id=\"@+id/loader_layout\"\n            layout=\"@layout/layout_circular_loader\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/fav_products_recycler_view\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:clipToPadding=\"false\"\n            android:padding=\"8dp\"\n            app:flow_horizontalAlign=\"center\"\n            app:layoutManager=\"androidx.recyclerview.widget.GridLayoutManager\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:spanCount=\"2\"\n            tools:itemCount=\"10\"\n            tools:listitem=\"@layout/products_list_item\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_home.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:focusableInTouchMode=\"true\"\n    tools:context=\".ui.home.HomeFragment\">\n\n    <include\n        android:id=\"@+id/home_top_app_bar\"\n        layout=\"@layout/layout_home_top_app_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/home_top_app_bar\">\n\n        <include\n            android:id=\"@+id/loader_layout\"\n            layout=\"@layout/layout_circular_loader\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0dp\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/products_recycler_view\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:clipToPadding=\"false\"\n            android:padding=\"8dp\"\n            app:flow_horizontalAlign=\"center\"\n            app:layoutManager=\"androidx.recyclerview.widget.GridLayoutManager\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:spanCount=\"2\"\n            tools:itemCount=\"10\"\n            tools:listitem=\"@layout/products_list_item\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n    <com.google.android.material.floatingactionbutton.FloatingActionButton\n        android:id=\"@+id/home_fab_add_product\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentEnd=\"true\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_marginEnd=\"16dp\"\n        android:layout_marginBottom=\"16dp\"\n        android:contentDescription=\"@string/home_add_fab_desc\"\n        app:srcCompat=\"@drawable/ic_add_48\" />\n\n\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_login.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.loginSignup.LoginFragment\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n        <ImageView\n            android:id=\"@+id/login_image_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"280dp\"\n            android:contentDescription=\"@string/bg_img_desc\"\n            android:scaleType=\"fitStart\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:srcCompat=\"@drawable/login_bg_img\" />\n\n        <TextView\n            android:id=\"@+id/login_welcome_hello_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"64dp\"\n            android:text=\"@string/login_welcome\"\n            android:textColor=\"@color/white\"\n            android:textSize=\"22sp\"\n            app:layout_constraintStart_toStartOf=\"@id/login_image_view\"\n            app:layout_constraintTop_toTopOf=\"@id/login_image_view\" />\n\n        <TextView\n            android:id=\"@+id/login_welcome_text_view\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:text=\"@string/login_welcome_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline3\"\n            android:textColor=\"@color/white\"\n            android:textStyle=\"bold\"\n            app:layout_constraintStart_toStartOf=\"@id/login_image_view\"\n            app:layout_constraintTop_toBottomOf=\"@+id/login_welcome_hello_tv\" />\n\n        <com.google.android.material.textfield.TextInputLayout\n            android:id=\"@+id/mobileOutlinedTextField\"\n            style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"16dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:hint=\"@string/login_mobile_hint\"\n            app:expandedHintEnabled=\"false\"\n            app:hintTextAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/login_image_view\"\n            app:placeholderText=\"@string/login_mobile_ph\"\n            app:placeholderTextAppearance=\"@style/TextAppearance.MyTheme.Body2\">\n\n            <com.google.android.material.textfield.TextInputEditText\n                android:id=\"@+id/login_mobile_edit_text\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:inputType=\"phone\"\n                android:paddingTop=\"12dp\"\n                android:paddingBottom=\"12dp\" />\n        </com.google.android.material.textfield.TextInputLayout>\n\n        <com.google.android.material.textfield.TextInputLayout\n            android:id=\"@+id/passwordOutlinedTextField\"\n            style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:hint=\"@string/login_password_hint\"\n            app:endIconMode=\"password_toggle\"\n            app:expandedHintEnabled=\"false\"\n            app:hintTextAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/mobileOutlinedTextField\"\n            app:placeholderText=\"@string/login_password_ph\"\n            app:placeholderTextAppearance=\"@style/TextAppearance.MyTheme.Body2\">\n\n            <com.google.android.material.textfield.TextInputEditText\n                android:id=\"@+id/login_password_edit_text\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:inputType=\"textPassword\"\n                android:paddingTop=\"10dp\"\n                android:paddingBottom=\"10dp\" />\n\n        </com.google.android.material.textfield.TextInputLayout>\n\n        <TextView\n            android:id=\"@+id/login_error_text_view\"\n            android:gravity=\"center_vertical\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            android:textColor=\"?attr/colorError\"\n            app:drawableStartCompat=\"@android:drawable/stat_notify_error\"\n            app:drawableTint=\"?attr/colorError\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"16dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:text=\"@string/login_error_text\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/passwordOutlinedTextField\" />\n\n        <com.google.android.material.switchmaterial.SwitchMaterial\n            android:id=\"@+id/login_rem_switch\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"16dp\"\n            android:checked=\"false\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/login_error_text_view\"\n            app:switchTextAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\" />\n\n\n        <TextView\n            android:id=\"@+id/login_rem_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"8dp\"\n            android:text=\"@string/login_switch_remember_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            android:textSize=\"12sp\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/login_rem_switch\"\n            app:layout_constraintStart_toEndOf=\"@+id/login_rem_switch\"\n            app:layout_constraintTop_toTopOf=\"@+id/login_rem_switch\" />\n\n        <TextView\n            android:id=\"@+id/login_forgot_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginEnd=\"24dp\"\n            android:text=\"@string/login_forgot_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            android:textSize=\"12sp\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/login_rem_switch\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"@+id/login_rem_switch\" />\n\n        <TextView\n            android:id=\"@+id/login_signup_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"16dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:text=\"@string/login_signup_text\"\n            android:textAlignment=\"center\"\n            android:textStyle=\"bold\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/login_rem_switch\" />\n\n        <Button\n            android:id=\"@+id/login_login_btn\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"24dp\"\n            android:layout_marginBottom=\"16dp\"\n            android:layout_weight=\"1\"\n            android:paddingStart=\"32dp\"\n            android:paddingEnd=\"32dp\"\n            android:text=\"@string/login_btn_text\"\n            android:textAllCaps=\"false\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/login_signup_text_view\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</ScrollView>"
  },
  {
    "path": "app/src/main/res/layout/fragment_order_details.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    tools:context=\".ui.home.OrderDetailsFragment\">\n\n    <include\n        android:id=\"@+id/order_detail_app_bar\"\n        layout=\"@layout/layout_top_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <include\n        android:id=\"@+id/loader_layout\"\n        layout=\"@layout/layout_circular_loader\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/order_detail_app_bar\" />\n\n    <androidx.core.widget.NestedScrollView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@id/order_detail_app_bar\"\n        android:fillViewport=\"true\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <androidx.constraintlayout.widget.ConstraintLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:layout_below=\"@id/order_detail_app_bar\"\n            android:paddingBottom=\"72dp\">\n\n            <androidx.constraintlayout.widget.Group\n                android:id=\"@+id/order_details_constraint_group\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                app:constraint_referenced_ids=\"order_details_payment_label_tv,\n                order_details_pro_label_tv,order_details_ship_label_tv,\n                order_details_payment_layout,order_details_shipping_add_layout,\n                order_details_pro_recycler_view,order_change_status_btn\" />\n\n            <TextView\n                android:id=\"@+id/order_details_pro_label_tv\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/products_label_text\"\n                android:textAlignment=\"viewStart\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textSize=\"18sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toTopOf=\"parent\" />\n\n            <androidx.recyclerview.widget.RecyclerView\n                android:id=\"@+id/order_details_pro_recycler_view\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:clipToPadding=\"false\"\n                android:overScrollMode=\"never\"\n                android:padding=\"8dp\"\n                app:flow_horizontalAlign=\"center\"\n                app:flow_verticalAlign=\"center\"\n                app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/order_details_pro_label_tv\"\n\n                tools:itemCount=\"2\"\n                tools:listitem=\"@layout/cart_list_item\">\n\n            </androidx.recyclerview.widget.RecyclerView>\n\n            <TextView\n                android:id=\"@+id/order_details_ship_label_tv\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/shipping_details_label_text\"\n                android:textAlignment=\"viewStart\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textSize=\"18sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/order_details_pro_recycler_view\" />\n\n            <ImageButton\n                android:id=\"@+id/order_change_status_btn\"\n                android:layout_width=\"35dp\"\n                android:layout_height=\"40dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:backgroundTint=\"@color/blue_accent_300\"\n                android:contentDescription=\"@string/change_status_label_text\"\n                android:scaleType=\"centerCrop\"\n                android:tint=\"@color/white\"\n                app:layout_constraintBottom_toBottomOf=\"@+id/order_details_ship_label_tv\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintTop_toTopOf=\"@+id/order_details_ship_label_tv\"\n                app:srcCompat=\"@drawable/ic_edit_24\" />\n\n            <include\n                android:id=\"@+id/order_details_shipping_add_layout\"\n                layout=\"@layout/layout_shipping_card\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/order_details_ship_label_tv\" />\n\n            <TextView\n                android:id=\"@+id/order_details_payment_label_tv\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"24dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:text=\"@string/payment_details_label_text\"\n                android:textAlignment=\"viewStart\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textSize=\"18sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/order_details_shipping_add_layout\" />\n\n            <include\n                android:id=\"@+id/order_details_payment_layout\"\n                layout=\"@layout/layout_price_card\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/order_details_payment_label_tv\" />\n\n\n        </androidx.constraintlayout.widget.ConstraintLayout>\n    </androidx.core.widget.NestedScrollView>\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_order_success.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.home.OrderSuccessFragment\">\n\n    <androidx.constraintlayout.widget.Group\n        android:id=\"@+id/order_constraint_group\"\n        android:layout_width=\"wrap_content\"\n        app:constraint_referenced_ids=\"order_success_image,order_success_label_tv,\n        order_success_message_tv,back_to_home_btn, redirect_home_timer_tv\"\n        android:layout_height=\"wrap_content\" />\n\n    <include\n        android:id=\"@+id/loader_layout\"\n        layout=\"@layout/layout_loader_card\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:visibility=\"gone\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <ImageView\n        android:id=\"@+id/order_success_image\"\n        android:layout_width=\"80dp\"\n        android:layout_height=\"80dp\"\n        android:layout_marginBottom=\"8dp\"\n        android:contentDescription=\"@string/success_img_desc\"\n        app:layout_constraintBottom_toTopOf=\"@+id/order_success_label_tv\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:srcCompat=\"@drawable/ic_filled_check_circle_24\"\n        app:tint=\"@color/blue_accent_300\" />\n\n    <TextView\n        android:id=\"@+id/order_success_label_tv\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:fontFamily=\"@font/nunito_sans\"\n        android:text=\"@string/success_label\"\n        android:textAppearance=\"@style/TextAppearance.MyTheme.Headline5\"\n        android:textColor=\"@color/black\"\n        android:textStyle=\"bold\"\n        app:layout_constraintBottom_toTopOf=\"@id/guideline2\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\" />\n\n    <androidx.constraintlayout.widget.Guideline\n        android:id=\"@+id/guideline2\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\"\n        app:layout_constraintGuide_percent=\"0.5\" />\n\n    <TextView\n        android:id=\"@+id/order_success_message_tv\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"8dp\"\n        android:text=\"@string/order_success_message_text\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toBottomOf=\"@id/guideline2\" />\n\n    <TextView\n        android:id=\"@+id/redirect_home_timer_tv\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"16dp\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toBottomOf=\"@+id/back_to_home_btn\"\n        tools:text=\"Redirecting to home in 5\" />\n\n    <Button\n        android:id=\"@+id/back_to_home_btn\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginStart=\"16dp\"\n        android:layout_marginTop=\"8dp\"\n        android:layout_marginEnd=\"16dp\"\n        android:backgroundTint=\"@color/blue_accent_300\"\n        android:padding=\"16dp\"\n        android:text=\"@string/back_to_home_text\"\n        android:textAllCaps=\"false\"\n        android:textSize=\"16sp\"\n        android:textStyle=\"bold\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toBottomOf=\"@id/order_success_message_tv\" />\n\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_orders.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    tools:context=\".ui.home.OrdersFragment\">\n\n    <include\n        android:id=\"@+id/orders_app_bar\"\n        layout=\"@layout/layout_top_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/orders_app_bar\">\n\n        <TextView\n            android:id=\"@+id/orders_empty_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:fontFamily=\"@font/nunito_sans\"\n            android:text=\"@string/no_orders_placed_text\"\n            android:textAlignment=\"center\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline3\"\n            android:textColor=\"@color/blue_accent_300\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <include\n            android:id=\"@+id/loader_layout\"\n            layout=\"@layout/layout_circular_loader\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/order_all_orders_recycler_view\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:clipToPadding=\"false\"\n            android:padding=\"8dp\"\n            app:flow_horizontalAlign=\"center\"\n            app:flow_verticalAlign=\"center\"\n            app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:itemCount=\"3\"\n            tools:listitem=\"@layout/layout_order_summary_card\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_product_details.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <include\n        android:id=\"@+id/add_pro_app_bar\"\n        layout=\"@layout/layout_top_bar\" />\n\n    <include\n        android:id=\"@+id/loader_layout\"\n        layout=\"@layout/layout_circular_loader\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/add_pro_app_bar\"\n        android:layout_gravity=\"center\" />\n\n    <androidx.core.widget.NestedScrollView\n        android:id=\"@+id/pro_details_scroll_view\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@id/add_pro_app_bar\"\n        android:fillViewport=\"true\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <androidx.constraintlayout.widget.ConstraintLayout\n            android:id=\"@+id/pro_details_layout\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"72dp\">\n\n            <androidx.constraintlayout.widget.Group\n                android:id=\"@+id/layout_views_group\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                app:constraint_referenced_ids=\"pro_details_images_recyclerview,\n                pro_details_title_tv,pro_details_like_btn,pro_details_rating_bar,\n                pro_details_price_tv,pro_details_select_size_label,pro_details_select_color_label,\n                pro_details_specifications_label\" />\n\n            <androidx.recyclerview.widget.RecyclerView\n                android:id=\"@+id/pro_details_images_recyclerview\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:orientation=\"horizontal\"\n                app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toTopOf=\"parent\"\n                tools:itemCount=\"3\"\n                tools:listitem=\"@layout/images_item\" />\n\n            <TextView\n                android:id=\"@+id/pro_details_title_tv\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:textAlignment=\"viewStart\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textSize=\"18sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintEnd_toStartOf=\"@+id/pro_details_like_btn\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@+id/pro_details_images_recyclerview\"\n                tools:text=\"Some Title of The Product van be multiline\" />\n\n            <ImageButton\n                android:id=\"@+id/pro_details_like_btn\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginEnd=\"16dp\"\n                android:background=\"@null\"\n                android:backgroundTint=\"#FFFFFF\"\n                android:contentDescription=\"@string/pro_details_like_btn_desc\"\n                android:padding=\"4dp\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintTop_toTopOf=\"@+id/pro_details_title_tv\"\n                app:srcCompat=\"@drawable/heart_icon_drawable\" />\n\n            <RatingBar\n                android:id=\"@+id/pro_details_rating_bar\"\n                style=\"@style/Widget.AppCompat.RatingBar.Small\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:progressTint=\"@color/gold\"\n                android:rating=\"3.5\"\n                android:secondaryProgressTint=\"#FFFFFF\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/pro_details_title_tv\" />\n\n            <TextView\n                android:id=\"@+id/pro_details_price_tv\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16dp\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n                android:textColor=\"@color/blue_accent_300\"\n                android:textSize=\"18sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@+id/pro_details_rating_bar\"\n                tools:text=\"$ 200.99\" />\n\n            <TextView\n                android:id=\"@+id/pro_details_select_size_label\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"16sp\"\n                android:text=\"@string/pro_details_select_size_lable_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle1\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@+id/pro_details_price_tv\" />\n\n            <HorizontalScrollView\n                android:id=\"@+id/pro_size_radio_scroll\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:scrollbars=\"none\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@+id/pro_details_select_size_label\">\n\n                <RadioGroup\n                    android:id=\"@+id/pro_details_sizes_radio_group\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:orientation=\"horizontal\">\n\n                </RadioGroup>\n            </HorizontalScrollView>\n\n            <TextView\n                android:id=\"@+id/pro_details_select_color_label\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:text=\"@string/pro_details_select_color_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle1\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@+id/pro_size_radio_scroll\" />\n\n            <HorizontalScrollView\n                android:id=\"@+id/pro_color_radio_scroll\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:scrollbars=\"none\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@id/pro_details_select_color_label\">\n\n                <RadioGroup\n                    android:id=\"@+id/pro_details_colors_radio_group\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:orientation=\"horizontal\">\n\n                </RadioGroup>\n            </HorizontalScrollView>\n\n            <TextView\n                android:id=\"@+id/pro_details_specifications_label\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:text=\"@string/pro_details_specif_label_text\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle1\"\n                android:textSize=\"16sp\"\n                android:textStyle=\"bold\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@+id/pro_color_radio_scroll\" />\n\n            <TextView\n                android:id=\"@+id/pro_details_specifics_text\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginStart=\"16dp\"\n                android:layout_marginTop=\"8dp\"\n                android:layout_marginEnd=\"16dp\"\n                android:textSize=\"14sp\"\n                app:layout_constraintEnd_toEndOf=\"parent\"\n                app:layout_constraintStart_toStartOf=\"parent\"\n                app:layout_constraintTop_toBottomOf=\"@+id/pro_details_specifications_label\"\n                tools:text=\"TextViewveoihj\" />\n\n\n        </androidx.constraintlayout.widget.ConstraintLayout>\n\n    </androidx.core.widget.NestedScrollView>\n\n    <Button\n        android:id=\"@+id/pro_details_add_cart_btn\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_marginStart=\"16dp\"\n        android:layout_marginTop=\"16dp\"\n        android:layout_marginEnd=\"16dp\"\n        android:backgroundTint=\"@color/blue_accent_300\"\n        android:padding=\"16dp\"\n        android:text=\"@string/pro_details_add_to_cart_btn_text\"\n        android:textAllCaps=\"false\"\n        android:textSize=\"16sp\"\n        android:textStyle=\"bold\"\n        android:translationY=\"-8dp\" />\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_profile.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    tools:context=\".ui.home.ProfileFragment\">\n\n    <include\n        android:id=\"@+id/profile_top_app_bar\"\n        layout=\"@layout/layout_top_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/profile_top_app_bar\">\n\n        <ImageView\n            android:id=\"@+id/profile_image_view\"\n            android:layout_width=\"80dp\"\n            android:layout_height=\"80dp\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"32dp\"\n            android:background=\"@drawable/avatar_background\"\n            android:contentDescription=\"@string/profile_img_desc\"\n            android:scaleType=\"center\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:srcCompat=\"@drawable/ic_baseline_person_24\"\n            app:tint=\"@color/blue_accent_300\" />\n\n        <TextView\n            android:id=\"@+id/profile_name_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n            android:textSize=\"16sp\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/profile_image_view\"\n            app:layout_constraintStart_toEndOf=\"@+id/profile_image_view\"\n            app:layout_constraintTop_toTopOf=\"@+id/profile_image_view\"\n            tools:text=\"Some User Name\" />\n\n        <TextView\n            android:id=\"@+id/profile_email_label_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:drawablePadding=\"16dp\"\n            android:padding=\"16dp\"\n            android:text=\"@string/profile_email_label_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textSize=\"16sp\"\n            android:textStyle=\"bold\"\n            app:drawableStartCompat=\"@drawable/ic_outline_email_24\"\n            app:drawableTint=\"@color/blue_accent_300\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/profile_image_view\" />\n\n        <TextView\n            android:id=\"@+id/profile_email_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:padding=\"16dp\"\n            android:textAlignment=\"viewEnd\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle1\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/profile_email_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"1.0\"\n            app:layout_constraintStart_toEndOf=\"@+id/profile_email_label_tv\"\n            app:layout_constraintTop_toTopOf=\"@+id/profile_email_label_tv\"\n            tools:text=\"somemail@example.com\" />\n\n        <TextView\n            android:id=\"@+id/profile_mobile_label_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:drawablePadding=\"16dp\"\n            android:padding=\"16dp\"\n            android:text=\"@string/profile_mobile_label_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textSize=\"16sp\"\n            android:textStyle=\"bold\"\n            app:drawableStartCompat=\"@drawable/ic_outline_phone_android_24\"\n            app:drawableTint=\"@color/blue_accent_300\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/profile_email_label_tv\" />\n\n        <TextView\n            android:id=\"@+id/profile_mobile_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:padding=\"16dp\"\n            android:textAlignment=\"viewEnd\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle1\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/profile_mobile_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"1.0\"\n            app:layout_constraintStart_toEndOf=\"@+id/profile_mobile_label_tv\"\n            app:layout_constraintTop_toTopOf=\"@+id/profile_mobile_label_tv\"\n            tools:text=\"+91 9999988888\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_select_address.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    tools:context=\".ui.home.SelectAddressFragment\">\n\n    <include\n        android:id=\"@+id/ship_to_app_bar\"\n        layout=\"@layout/layout_top_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/ship_to_app_bar\"\n        android:layout_marginBottom=\"72dp\">\n\n        <include\n            android:id=\"@+id/loader_layout\"\n            layout=\"@layout/layout_circular_loader\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/ship_to_addresses_recycler_view\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:clipToPadding=\"false\"\n            android:overScrollMode=\"never\"\n            android:padding=\"8dp\"\n            app:flow_horizontalAlign=\"center\"\n            app:flow_verticalAlign=\"center\"\n            app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:itemCount=\"3\"\n            tools:listitem=\"@layout/layout_address_card\" />\n\n        <TextView\n            android:id=\"@+id/address_empty_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:fontFamily=\"@font/nunito_sans\"\n            android:text=\"@string/no_addresses_text\"\n            android:textAlignment=\"center\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline3\"\n            android:textColor=\"@color/blue_accent_300\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <TextView\n            android:id=\"@+id/ship_to_error_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"16dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:gravity=\"center_vertical\"\n            android:text=\"@string/ship_to_error_empty\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            android:textColor=\"?attr/colorError\"\n            app:drawableStartCompat=\"@android:drawable/stat_notify_error\"\n            app:drawableTint=\"?attr/colorError\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintVertical_bias=\"0.98\"\n            app:layout_constraintTop_toBottomOf=\"@id/ship_to_addresses_recycler_view\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n    <Button\n        android:id=\"@+id/ship_to_next_btn\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_marginStart=\"16dp\"\n        android:layout_marginTop=\"16dp\"\n        android:layout_marginEnd=\"16dp\"\n        android:backgroundTint=\"@color/blue_accent_300\"\n        android:padding=\"16dp\"\n        android:text=\"@string/next_btn_text\"\n        android:textAllCaps=\"false\"\n        android:textSize=\"16sp\"\n        android:textStyle=\"bold\"\n        android:translationY=\"-8dp\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_select_payment.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    tools:context=\".ui.home.SelectPaymentFragment\">\n\n    <include\n        android:id=\"@+id/pay_by_app_bar\"\n        layout=\"@layout/layout_top_bar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentTop=\"true\" />\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/pay_by_app_bar\"\n        android:layout_marginBottom=\"72dp\">\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/pay_by_payments_recycler_view\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:clipToPadding=\"false\"\n            android:overScrollMode=\"never\"\n            android:padding=\"8dp\"\n            app:flow_horizontalAlign=\"center\"\n            app:flow_verticalAlign=\"center\"\n            app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:itemCount=\"2\"\n            tools:listitem=\"@layout/layout_list_item\" />\n\n        <TextView\n            android:id=\"@+id/pay_by_error_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"16dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:gravity=\"center_vertical\"\n            android:text=\"@string/pay_by_error_empty\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            android:textColor=\"?attr/colorError\"\n            app:drawableStartCompat=\"@android:drawable/stat_notify_error\"\n            app:drawableTint=\"?attr/colorError\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/pay_by_payments_recycler_view\"\n            app:layout_constraintVertical_bias=\"0.98\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n    <Button\n        android:id=\"@+id/pay_by_next_btn\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_marginStart=\"16dp\"\n        android:layout_marginTop=\"16dp\"\n        android:layout_marginEnd=\"16dp\"\n        android:backgroundTint=\"@color/blue_accent_300\"\n        android:padding=\"16dp\"\n        android:textAllCaps=\"false\"\n        android:textSize=\"16sp\"\n        android:textStyle=\"bold\"\n        android:translationY=\"-8dp\"\n        tools:text=\"@string/next_btn_text\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_signup.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:focusableInTouchMode=\"true\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.loginSignup.SignupFragment\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n        <ImageView\n            android:id=\"@+id/signup_image_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"280dp\"\n            android:contentDescription=\"@string/bg_img_desc\"\n            android:scaleType=\"fitStart\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:srcCompat=\"@drawable/login_bg_img\" />\n\n        <TextView\n            android:id=\"@+id/signup_welcome_hello_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"64dp\"\n            android:text=\"@string/signup_welcome_hello\"\n            android:textColor=\"@color/white\"\n            android:textSize=\"22sp\"\n            app:layout_constraintStart_toStartOf=\"@id/signup_image_view\"\n            app:layout_constraintTop_toTopOf=\"@id/signup_image_view\" />\n\n        <TextView\n            android:id=\"@+id/signup_welcome_text_view\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:text=\"@string/signup_welcome_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline3\"\n            android:textColor=\"@color/white\"\n            android:textStyle=\"bold\"\n            app:layout_constraintStart_toStartOf=\"@id/signup_image_view\"\n            app:layout_constraintTop_toBottomOf=\"@+id/signup_welcome_hello_tv\" />\n\n        <com.google.android.material.textfield.TextInputLayout\n            android:id=\"@+id/nameOutlinedTextField\"\n            style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:hint=\"@string/signup_name_hint\"\n            app:expandedHintEnabled=\"false\"\n            app:hintTextAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/signup_image_view\"\n            app:placeholderText=\"@string/signup_name_ph\"\n            app:placeholderTextAppearance=\"@style/TextAppearance.MyTheme.Body2\">\n\n            <com.google.android.material.textfield.TextInputEditText\n                android:id=\"@+id/signup_name_edit_text\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:inputType=\"textPersonName\"\n                android:paddingTop=\"12dp\"\n                android:paddingBottom=\"12dp\" />\n\n        </com.google.android.material.textfield.TextInputLayout>\n\n        <com.google.android.material.textfield.TextInputLayout\n            android:id=\"@+id/mobileOutlinedTextField\"\n            style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:hint=\"@string/signup_mobile_hint\"\n            app:expandedHintEnabled=\"false\"\n            app:hintTextAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/nameOutlinedTextField\"\n            app:placeholderText=\"@string/signup_mobile_ph\"\n            app:placeholderTextAppearance=\"@style/TextAppearance.MyTheme.Body2\">\n\n            <com.google.android.material.textfield.TextInputEditText\n                android:id=\"@+id/signup_mobile_edit_text\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:inputType=\"phone\"\n                android:paddingTop=\"12dp\"\n                android:paddingBottom=\"12dp\" />\n        </com.google.android.material.textfield.TextInputLayout>\n\n        <com.google.android.material.textfield.TextInputLayout\n            android:id=\"@+id/emailOutlinedTextField\"\n            style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:hint=\"@string/signup_email_hint\"\n            app:expandedHintEnabled=\"false\"\n            app:hintTextAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/mobileOutlinedTextField\"\n            app:placeholderText=\"@string/signup_email_ph\"\n            app:placeholderTextAppearance=\"@style/TextAppearance.MyTheme.Body2\">\n\n            <com.google.android.material.textfield.TextInputEditText\n                android:id=\"@+id/signup_email_edit_text\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:inputType=\"textWebEmailAddress\"\n                android:paddingTop=\"12dp\"\n                android:paddingBottom=\"12dp\" />\n        </com.google.android.material.textfield.TextInputLayout>\n\n        <com.google.android.material.textfield.TextInputLayout\n            android:id=\"@+id/passwordOutlinedTextField\"\n            style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:hint=\"@string/signup_password_hint\"\n            app:endIconMode=\"password_toggle\"\n            app:expandedHintEnabled=\"false\"\n            app:hintTextAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/emailOutlinedTextField\"\n            app:placeholderText=\"@string/signup_password_ph\"\n            app:placeholderTextAppearance=\"@style/TextAppearance.MyTheme.Body2\">\n\n            <com.google.android.material.textfield.TextInputEditText\n                android:id=\"@+id/signup_password_edit_text\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:inputType=\"textPassword\"\n                android:paddingTop=\"10dp\"\n                android:paddingBottom=\"10dp\" />\n\n        </com.google.android.material.textfield.TextInputLayout>\n\n        <com.google.android.material.textfield.TextInputLayout\n            android:id=\"@+id/confirmPasswordOutlinedTextField\"\n            style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:hint=\"@string/signup_conf_password_hint\"\n            app:endIconMode=\"password_toggle\"\n            app:expandedHintEnabled=\"false\"\n            app:hintTextAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/passwordOutlinedTextField\"\n            app:placeholderText=\"@string/signup_cnf_password_ph\"\n            app:placeholderTextAppearance=\"@style/TextAppearance.MyTheme.Body2\">\n\n            <com.google.android.material.textfield.TextInputEditText\n                android:id=\"@+id/signup_cnf_password_edit_text\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:inputType=\"textPassword\"\n                android:paddingTop=\"10dp\"\n                android:paddingBottom=\"10dp\" />\n\n        </com.google.android.material.textfield.TextInputLayout>\n\n        <com.google.android.material.switchmaterial.SwitchMaterial\n            android:id=\"@+id/signup_seller_switch\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:checked=\"false\"\n            android:paddingStart=\"2dp\"\n            android:paddingEnd=\"2dp\"\n            android:text=\"@string/signup_seller_text\"\n            android:textSize=\"14sp\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/confirmPasswordOutlinedTextField\"\n            app:switchPadding=\"4dp\" />\n\n        <com.google.android.material.switchmaterial.SwitchMaterial\n            android:id=\"@+id/signup_policy_switch\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:checked=\"false\"\n            android:paddingStart=\"2dp\"\n            android:paddingEnd=\"2dp\"\n            android:text=\"@string/signup_switch_tnc_label\"\n            android:textSize=\"12sp\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/signup_seller_switch\"\n            app:switchPadding=\"8dp\"\n            app:switchTextAppearance=\"@style/TextAppearance.MyTheme.Caption\" />\n\n        <TextView\n            android:id=\"@+id/signup_error_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:gravity=\"center_vertical\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle2\"\n            android:textColor=\"?attr/colorError\"\n            app:drawableStartCompat=\"@android:drawable/stat_notify_error\"\n            app:drawableTint=\"?attr/colorError\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/signup_policy_switch\"\n            tools:text=\"Some error occured\" />\n\n        <TextView\n            android:id=\"@+id/signup_login_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"24dp\"\n            android:layout_marginTop=\"16dp\"\n            android:layout_marginEnd=\"24dp\"\n            android:text=\"@string/signup_login_text\"\n            android:textAlignment=\"center\"\n            android:textStyle=\"bold\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/signup_error_text_view\" />\n\n        <Button\n            android:id=\"@+id/signup_signup_btn\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_weight=\"1\"\n            android:paddingStart=\"32dp\"\n            android:paddingEnd=\"32dp\"\n            android:text=\"@string/signup_btn_text\"\n            android:textAllCaps=\"false\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/signup_login_text_view\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</ScrollView>"
  },
  {
    "path": "app/src/main/res/layout/images_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <ImageView\n        android:id=\"@+id/rc_image_view\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"250dp\"\n        android:contentDescription=\"@string/product_detail_image_desc\"\n        android:scaleType=\"fitCenter\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        tools:srcCompat=\"@tools:sample/backgrounds/scenic\" />\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_address_card.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.card.MaterialCardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/address_card\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_margin=\"8dp\"\n    android:checkable=\"true\"\n    android:clickable=\"true\"\n    android:focusable=\"true\"\n    app:cardElevation=\"0dp\"\n    app:checkedIcon=\"@null\"\n    app:strokeColor=\"@color/light_gray\"\n    app:strokeWidth=\"1dp\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"16dp\">\n\n        <TextView\n            android:id=\"@+id/address_person_name_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n            android:textColor=\"@color/dark_gray\"\n            android:textSize=\"18sp\"\n            android:textStyle=\"bold\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:text=\"Some Name\" />\n\n        <TextView\n            android:id=\"@+id/address_complete_address_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:minLines=\"2\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/gray\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/address_person_name_tv\"\n            tools:text=\"3249857, pwoei owirgfhjow, Kanpur Nagar, Uttar Pradesh, 208002\" />\n\n        <TextView\n            android:id=\"@+id/address_mobile_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/gray\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/address_complete_address_tv\"\n            tools:text=\"+91 9999988888\" />\n\n        <Button\n            android:id=\"@+id/address_edit_btn\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:backgroundTint=\"@color/blue_accent_300\"\n            android:padding=\"16dp\"\n            android:text=\"@string/edit_btn_text\"\n            android:textAllCaps=\"false\"\n            android:textSize=\"16sp\"\n            android:textStyle=\"bold\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/address_mobile_tv\" />\n\n        <ImageView\n            android:id=\"@+id/address_delete_btn\"\n            android:layout_width=\"32dp\"\n            android:layout_height=\"32dp\"\n            android:layout_marginStart=\"32dp\"\n            android:background=\"@drawable/round_button\"\n            android:contentDescription=\"@string/pro_details_delete_btn_desc\"\n            android:scaleType=\"centerCrop\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/address_edit_btn\"\n            app:layout_constraintStart_toEndOf=\"@+id/address_edit_btn\"\n            app:layout_constraintTop_toTopOf=\"@+id/address_edit_btn\"\n            app:srcCompat=\"@drawable/ic_delete_24\"\n            app:tint=\"@color/gray\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</com.google.android.material.card.MaterialCardView>"
  },
  {
    "path": "app/src/main/res/layout/layout_circular_loader.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/loader_frame_layout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:layout_gravity=\"center\"\n    android:background=\"@color/loader_background_color\"\n    android:translationZ=\"2dp\">\n\n    <com.google.android.material.progressindicator.CircularProgressIndicator\n        android:id=\"@+id/circular_loader\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:indeterminate=\"true\"\n        app:indicatorColor=\"@color/blue_accent_300\"\n        app:indicatorDirectionCircular=\"clockwise\"\n        app:trackColor=\"@color/white\"\n        app:trackThickness=\"6dp\" />\n\n</FrameLayout>\n\n"
  },
  {
    "path": "app/src/main/res/layout/layout_home_ad.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.card.MaterialCardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/ad_card\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:clickable=\"false\"\n    android:focusable=\"true\"\n    app:cardElevation=\"0dp\"\n    app:strokeColor=\"#CCCCCC\"\n    app:strokeWidth=\"1dp\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n        <ImageView\n            android:id=\"@+id/ad_image_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"180dp\"\n            android:background=\"@drawable/round_outline_rect\"\n            android:contentDescription=\"@string/home_ad_image_desc\"\n            android:scaleType=\"fitXY\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:srcCompat=\"@drawable/ad_ex_1\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</com.google.android.material.card.MaterialCardView>"
  },
  {
    "path": "app/src/main/res/layout/layout_home_top_app_bar.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.appbar.AppBarLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/home_app_bar_layout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"@color/white\"\n    android:elevation=\"4dp\">\n\n    <com.google.android.material.appbar.MaterialToolbar\n        android:id=\"@+id/topAppBar\"\n        style=\"@style/Widget.MaterialComponents.Toolbar.Primary\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"72dp\"\n        android:background=\"@color/white\"\n        app:buttonGravity=\"center_vertical\"\n        app:contentInsetStartWithNavigation=\"0dp\"\n        app:titleTextAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n        app:titleTextColor=\"@color/black\">\n\n        <com.google.android.material.textfield.TextInputLayout\n            android:id=\"@+id/searchOutlinedTextLayout\"\n            style=\"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:focusable=\"false\"\n            app:boxStrokeColor=\"@color/blue_accent_300\"\n            app:endIconMode=\"clear_text\"\n            app:endIconTint=\"@color/blue_accent_300\"\n            app:hintEnabled=\"false\"\n            app:startIconDrawable=\"@drawable/ic_search_24\"\n            app:startIconTint=\"@color/blue_accent_300\">\n\n            <com.google.android.material.textfield.TextInputEditText\n                android:id=\"@+id/home_search_edit_text\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:hint=\"@string/search_placeholder_text\"\n                android:imeOptions=\"actionSearch\"\n                android:inputType=\"text\"\n                android:paddingTop=\"12dp\"\n                android:paddingBottom=\"12dp\"\n                android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle1\"\n                android:textColor=\"@color/gray\"\n                android:textColorHint=\"@color/gray\" />\n\n        </com.google.android.material.textfield.TextInputLayout>\n\n    </com.google.android.material.appbar.MaterialToolbar>\n\n\n</com.google.android.material.appbar.AppBarLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_list_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.card.MaterialCardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/item_card\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_margin=\"8dp\"\n    android:checkable=\"true\"\n    android:clickable=\"true\"\n    android:focusable=\"true\"\n    app:cardElevation=\"0dp\"\n    app:checkedIcon=\"@null\"\n    app:strokeColor=\"@color/light_gray\"\n    app:strokeWidth=\"1dp\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:padding=\"8dp\">\n\n        <TextView\n            android:id=\"@+id/item_title_text_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"8dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:layout_marginBottom=\"8dp\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/gray\"\n            android:textSize=\"18sp\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:text=\"TextView\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</com.google.android.material.card.MaterialCardView>"
  },
  {
    "path": "app/src/main/res/layout/layout_loader_card.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.card.MaterialCardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"wrap_content\"\n    android:id=\"@+id/loader_card\"\n    android:layout_height=\"wrap_content\"\n    app:cardElevation=\"8dp\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"4dp\">\n\n        <com.google.android.material.progressindicator.CircularProgressIndicator\n            android:id=\"@+id/circular_loader\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"32dp\"\n            android:layout_marginEnd=\"16dp\"\n            android:indeterminate=\"true\"\n            app:indicatorColor=\"@color/blue_accent_300\"\n            app:indicatorDirectionCircular=\"clockwise\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:trackColor=\"@color/white\"\n            app:trackThickness=\"6dp\" />\n\n        <TextView\n            android:id=\"@+id/loading_message\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"32dp\"\n            android:layout_marginTop=\"16dp\"\n            android:layout_marginEnd=\"32dp\"\n            android:layout_marginBottom=\"16dp\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/circular_loader\"\n            tools:text=\"Loading Data...\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</com.google.android.material.card.MaterialCardView>"
  },
  {
    "path": "app/src/main/res/layout/layout_no_icon_app_bar.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.appbar.AppBarLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/top_bar_layout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"@color/white\"\n    android:elevation=\"4dp\">\n\n    <com.google.android.material.appbar.MaterialToolbar\n        android:id=\"@+id/topAppBar\"\n        style=\"@style/Widget.MaterialComponents.Toolbar.Primary\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"72dp\"\n        android:background=\"@color/white\"\n        app:buttonGravity=\"center_vertical\"\n        app:contentInsetStartWithNavigation=\"0dp\"\n        app:titleTextAppearance=\"@style/AppBarTitleStyle\"\n        app:titleTextColor=\"@color/black\"\n        tools:title=\"@string/app_name\" />\n\n\n</com.google.android.material.appbar.AppBarLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_order_summary_card.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.card.MaterialCardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/order_summary_card\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_margin=\"8dp\"\n    android:clickable=\"true\"\n    android:focusable=\"true\"\n    app:cardElevation=\"0dp\"\n    app:strokeColor=\"#CCCCCC\"\n    app:strokeWidth=\"1dp\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"16dp\">\n\n        <TextView\n            android:id=\"@+id/order_summary_id_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:ellipsize=\"end\"\n            android:maxLines=\"1\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n            android:textStyle=\"bold\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:text=\"BIUGIFD928IUKGI\" />\n\n        <TextView\n            android:id=\"@+id/order_summary_date_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"12dp\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body2\"\n            android:textColor=\"@color/dark_gray\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/order_summary_id_tv\"\n            tools:text=\"Ordered On : January 1, 2021\" />\n\n        <ImageView\n            android:id=\"@+id/order_card_dotted_divider\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"5dp\"\n            android:layout_marginTop=\"16dp\"\n            android:contentDescription=\"@string/price_card_divider_desc\"\n            android:layerType=\"software\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/order_summary_date_tv\"\n            app:srcCompat=\"@drawable/dotted_line_drawable\" />\n\n        <TextView\n            android:id=\"@+id/order_summary_status_label_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:text=\"@string/price_card_status_label_string\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body2\"\n            android:textColor=\"@color/dark_gray\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/order_card_dotted_divider\" />\n\n        <TextView\n            android:id=\"@+id/order_summary_status_value_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"32dp\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body2\"\n            android:textColor=\"@color/black\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/order_summary_status_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"1.0\"\n            app:layout_constraintStart_toEndOf=\"@+id/order_summary_status_label_tv\"\n            app:layout_constraintTop_toTopOf=\"@+id/order_summary_status_label_tv\"\n            tools:text=\"Shipping\" />\n\n        <TextView\n            android:id=\"@+id/order_summary_items_label_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"12dp\"\n            android:text=\"@string/order_summary_items_label\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body2\"\n            android:textColor=\"@color/dark_gray\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/order_summary_status_label_tv\" />\n\n        <TextView\n            android:id=\"@+id/order_summary_items_count_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body2\"\n            android:textColor=\"@color/black\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/order_summary_items_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"@+id/order_summary_items_label_tv\"\n            tools:text=\"4 items purchased\" />\n\n        <TextView\n            android:id=\"@+id/order_summary_price_label_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"12dp\"\n            android:text=\"@string/price_card_total_label_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body2\"\n            android:textColor=\"@color/dark_gray\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/order_summary_items_label_tv\" />\n\n        <TextView\n            android:id=\"@+id/order_summary_total_amount_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body2\"\n            android:textColor=\"@color/blue_accent_300\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/order_summary_price_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"@+id/order_summary_price_label_tv\"\n            tools:text=\"$123.45\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</com.google.android.material.card.MaterialCardView>"
  },
  {
    "path": "app/src/main/res/layout/layout_price_card.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.card.MaterialCardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/ad_card\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_margin=\"8dp\"\n    android:clickable=\"false\"\n    android:focusable=\"true\"\n    app:cardElevation=\"0dp\"\n    app:strokeColor=\"#CCCCCC\"\n    app:strokeWidth=\"1dp\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"16dp\">\n\n        <TextView\n            android:id=\"@+id/price_items_label_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/dark_gray\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:text=\"Items(3)\" />\n\n        <TextView\n            android:id=\"@+id/price_items_amount_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/black\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/price_items_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"@+id/price_items_label_tv\"\n            tools:text=\"$123.45\" />\n\n        <TextView\n            android:id=\"@+id/price_shipping_label_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:text=\"@string/price_card_shipping_label_string\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/dark_gray\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/price_items_label_tv\" />\n\n        <TextView\n            android:id=\"@+id/price_shipping_amount_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/black\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/price_shipping_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"@+id/price_shipping_label_tv\"\n            tools:text=\"$123.45\" />\n\n        <TextView\n            android:id=\"@+id/price_charges_label_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:text=\"@string/price_card_charges_label_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/dark_gray\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/price_shipping_label_tv\" />\n\n        <TextView\n            android:id=\"@+id/price_charges_amount_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/black\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/price_charges_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"@+id/price_charges_label_tv\"\n            tools:text=\"$123.45\" />\n\n        <ImageView\n            android:id=\"@+id/card_dotted_divider\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"5dp\"\n            android:layout_marginTop=\"16dp\"\n            android:contentDescription=\"@string/price_card_divider_desc\"\n            android:layerType=\"software\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/price_charges_label_tv\"\n            app:srcCompat=\"@drawable/dotted_line_drawable\" />\n\n        <TextView\n            android:id=\"@+id/price_total_label_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:text=\"@string/price_card_total_label_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/dark_gray\"\n            android:textStyle=\"bold\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/card_dotted_divider\" />\n\n        <TextView\n            android:id=\"@+id/price_total_amount_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/blue_accent_300\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/price_total_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"@+id/price_total_label_tv\"\n            tools:text=\"$123.45\" />\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</com.google.android.material.card.MaterialCardView>"
  },
  {
    "path": "app/src/main/res/layout/layout_shipping_card.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.card.MaterialCardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/shipping_card\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_margin=\"8dp\"\n    android:clickable=\"false\"\n    android:focusable=\"true\"\n    app:cardElevation=\"0dp\"\n    app:strokeColor=\"#CCCCCC\"\n    app:strokeWidth=\"1dp\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"16dp\">\n\n        <TextView\n            android:id=\"@+id/ship_date_label_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/dark_gray\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            android:text=\"@string/ship_date_text\" />\n\n        <TextView\n            android:id=\"@+id/ship_date_value_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/black\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/ship_date_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"@+id/ship_date_label_tv\"\n            tools:text=\"December 01, 2022\" />\n\n        <TextView\n            android:id=\"@+id/ship_add_label_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:text=\"@string/shipping_address_label_string\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/dark_gray\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/ship_date_label_tv\" />\n\n        <TextView\n            android:id=\"@+id/ship_add_value_tv\"\n            android:layout_width=\"160dp\"\n            android:layout_height=\"wrap_content\"\n            android:textAlignment=\"textEnd\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/black\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/ship_add_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"1.0\"\n            app:layout_constraintStart_toEndOf=\"@+id/ship_add_label_tv\"\n            app:layout_constraintTop_toTopOf=\"@+id/ship_add_label_tv\"\n            app:layout_constraintVertical_bias=\"0.0\"\n            tools:text=\"123, Sonmwe Soijr, Ouiwy qwei, Uytwuf, India, 208242\" />\n\n        <ImageView\n            android:id=\"@+id/card_dotted_divider\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"5dp\"\n            android:layout_marginTop=\"16dp\"\n            android:contentDescription=\"@string/price_card_divider_desc\"\n            android:layerType=\"software\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/ship_add_value_tv\"\n            app:srcCompat=\"@drawable/dotted_line_drawable\" />\n\n        <TextView\n            android:id=\"@+id/ship_curr_status_label_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:text=\"@string/ship_curr_status_label_text\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/dark_gray\"\n            android:textStyle=\"bold\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/card_dotted_divider\" />\n\n        <TextView\n            android:id=\"@+id/ship_curr_status_value_tv\"\n            android:layout_width=\"160dp\"\n            android:layout_height=\"wrap_content\"\n            android:textAlignment=\"textEnd\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Body1\"\n            android:textColor=\"@color/blue_accent_300\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/ship_curr_status_label_tv\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"@+id/ship_curr_status_label_tv\"\n            tools:text=\"DELIVERED ON January 01, 2023\" />\n\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n\n</com.google.android.material.card.MaterialCardView>"
  },
  {
    "path": "app/src/main/res/layout/layout_top_bar.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.google.android.material.appbar.AppBarLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/top_bar_layout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"@color/white\"\n    android:elevation=\"4dp\">\n\n    <com.google.android.material.appbar.MaterialToolbar\n        android:id=\"@+id/topAppBar\"\n        style=\"@style/Widget.MaterialComponents.Toolbar.Primary\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"72dp\"\n        android:background=\"@color/white\"\n        app:buttonGravity=\"center_vertical\"\n        app:contentInsetStartWithNavigation=\"0dp\"\n        app:navigationIcon=\"@drawable/ic_outline_arrow_back_24\"\n        app:navigationIconTint=\"@color/gray\"\n        tools:title=\"@string/app_name\"\n        app:titleTextAppearance=\"@style/AppBarTitleStyle\"\n        app:titleTextColor=\"@color/black\" />\n\n\n</com.google.android.material.appbar.AppBarLayout>"
  },
  {
    "path": "app/src/main/res/layout/products_list_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<com.google.android.material.card.MaterialCardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/product_card\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:clickable=\"true\"\n    android:focusable=\"true\"\n    app:cardElevation=\"0dp\"\n    app:strokeColor=\"#CCCCCC\"\n    app:strokeWidth=\"1dp\">\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"12dp\">\n\n        <ImageView\n            android:id=\"@+id/product_image_view\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"150dp\"\n            android:background=\"@drawable/round_outline_rect\"\n            android:contentDescription=\"@string/add_img_item_desc\"\n            android:scaleType=\"centerCrop\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:srcCompat=\"@tools:sample/backgrounds/scenic\" />\n\n        <ImageView\n            android:id=\"@+id/product_delete_button\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"@drawable/round_button\"\n            android:contentDescription=\"@string/add_img_close_btn_desc\"\n            android:scaleType=\"centerCrop\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            app:srcCompat=\"@drawable/ic_delete_24\"\n            app:tint=\"@color/gray\" />\n\n        <CheckBox\n            android:id=\"@+id/product_like_checkbox\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:button=\"@drawable/sl_favourite_24dp\"\n            android:gravity=\"end|top\"\n            android:layoutDirection=\"rtl\"\n            app:buttonTint=\"@color/gray\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintHorizontal_bias=\"0.0\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <TextView\n            android:id=\"@+id/product_name_tv\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"4dp\"\n            android:lines=\"2\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Subtitle1\"\n            android:textStyle=\"bold\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/product_image_view\"\n            tools:text=\"Item Name name name wofe348\" />\n\n        <RatingBar\n            android:id=\"@+id/product_rating_bar\"\n            style=\"@style/Widget.AppCompat.RatingBar.Small\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:progressTint=\"@color/gold\"\n            android:rating=\"4.25\"\n            android:secondaryProgressTint=\"#FFFFFF\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/product_name_tv\" />\n\n        <TextView\n            android:id=\"@+id/product_price_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"16dp\"\n            android:textAppearance=\"@style/TextAppearance.MyTheme.Headline6\"\n            android:textColor=\"@color/blue_accent_300\"\n            android:textSize=\"16sp\"\n            android:textStyle=\"bold\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/product_rating_bar\"\n            tools:text=\"$2000\" />\n\n        <TextView\n            android:id=\"@+id/product_actual_price_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"8dp\"\n            android:textSize=\"12sp\"\n            android:textStyle=\"bold\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@id/product_price_tv\"\n            tools:text=\"@string/product_actual_price_text\" />\n\n        <TextView\n            android:id=\"@+id/product_offer_value_tv\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"8dp\"\n            android:textColor=\"@android:color/holo_red_light\"\n            android:textSize=\"12sp\"\n            android:textStyle=\"bold\"\n            app:layout_constraintBottom_toBottomOf=\"@+id/product_actual_price_tv\"\n            app:layout_constraintStart_toEndOf=\"@+id/product_actual_price_tv\"\n            app:layout_constraintTop_toTopOf=\"@+id/product_actual_price_tv\"\n            tools:text=\"@string/product_offer_percent_text\" />\n\n        <ImageView\n            android:id=\"@+id/product_edit_button\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"@drawable/round_button\"\n            android:contentDescription=\"@string/add_img_close_btn_desc\"\n            android:scaleType=\"centerCrop\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:srcCompat=\"@drawable/ic_edit_24\"\n            app:tint=\"@color/gray\" />\n\n        <ImageView\n            android:id=\"@+id/product_add_to_cart_button\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"@drawable/round_button\"\n            android:contentDescription=\"@string/add_img_close_btn_desc\"\n            android:scaleType=\"centerCrop\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:srcCompat=\"@drawable/ic_add_shopping_cart_24\"\n            app:tint=\"@color/gray\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</com.google.android.material.card.MaterialCardView>\n"
  },
  {
    "path": "app/src/main/res/menu/app_bar_menu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <item\n        android:id=\"@+id/more\"\n        android:title=\"@string/more_app_bar_title\"\n        android:contentDescription=\"@string/content_description_more\"\n        app:showAsAction=\"never\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/bottom_navigation_menu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n        android:id=\"@+id/homeFragment\"\n        android:enabled=\"true\"\n        android:icon=\"@drawable/ic_outlined_home_24\"\n        android:title=\"@string/bottom_nav_home_label\"/>\n    <item\n        android:id=\"@+id/cartFragment\"\n        android:enabled=\"true\"\n        android:icon=\"@drawable/ic_outlined_shopping_cart_24\"\n        android:title=\"@string/bottom_nav_cart_label\"/>\n    <item\n        android:id=\"@+id/ordersFragment\"\n        android:enabled=\"true\"\n        android:icon=\"@drawable/ic_outline_library_books_24\"\n        android:title=\"@string/bottom_nav_orders_label\" />\n    <item\n        android:id=\"@+id/accountFragment\"\n        android:enabled=\"true\"\n        android:icon=\"@drawable/ic_outlined_person_24\"\n        android:title=\"@string/bottom_nav_account_label\"/>\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/home_app_bar_menu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <item\n        android:id=\"@+id/home_favorites\"\n        android:icon=\"@drawable/ic_favorite_outlined_24\"\n        android:title=\"@string/home_app_bar_favorites_label\"\n        app:showAsAction=\"ifRoom\" />\n    <item\n        android:id=\"@+id/home_filter\"\n        android:icon=\"@drawable/ic_filter_alt_24\"\n        android:title=\"@string/home_app_bar_filter_label\"\n        app:showAsAction=\"ifRoom\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_main.xml",
    "content": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:context=\"com.vishalgaur.shoppingapp.ui.home.MainActivity\">\n    <item\n        android:id=\"@+id/action_settings\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/action_settings\"\n        app:showAsAction=\"never\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_with_add_only.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item\n        android:id=\"@+id/add_item\"\n        android:icon=\"@drawable/ic_add_48\"\n        android:title=\"@string/add_menu_item_title\"\n        app:showAsAction=\"always\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/navigation/home_nav_graph.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<navigation xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/home_nav_graph\"\n    app:startDestination=\"@id/homeFragment\">\n\n    <fragment\n        android:id=\"@+id/homeFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.HomeFragment\"\n        android:label=\"fragment_home\"\n        tools:layout=\"@layout/fragment_home\">\n        <action\n            android:id=\"@+id/action_goto_addProduct\"\n            app:destination=\"@id/addEditProductFragment\" />\n        <action\n            android:id=\"@+id/action_seeProduct\"\n            app:destination=\"@id/productDetailsFragment\" />\n        <action\n            android:id=\"@+id/action_homeFragment_to_favoritesFragment\"\n            app:destination=\"@id/favoritesFragment\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/addEditProductFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.AddEditProductFragment\"\n        android:label=\"AddProductFragment\"\n        tools:layout=\"@layout/fragment_add_edit_product\">\n        <argument\n            android:name=\"categoryName\"\n            app:argType=\"string\"\n            app:nullable=\"true\" />\n        <argument\n            android:name=\"isEdit\"\n            app:argType=\"boolean\"\n            app:nullable=\"false\" />\n        <argument\n            android:name=\"productId\"\n            app:argType=\"string\"\n            app:nullable=\"true\" />\n        <action\n            android:id=\"@+id/action_addProductFragment_to_homeFragment\"\n            app:destination=\"@id/homeFragment\"\n            app:popUpTo=\"@id/homeFragment\"\n            app:popUpToInclusive=\"true\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/productDetailsFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.ProductDetailsFragment\"\n        android:label=\"ProductDetailsFragment\"\n        tools:layout=\"@layout/fragment_product_details\">\n        <action\n            android:id=\"@+id/action_productDetailsFragment_to_homeFragment\"\n            app:destination=\"@id/homeFragment\"\n            app:popUpTo=\"@id/homeFragment\"\n            app:popUpToInclusive=\"true\" />\n        <argument\n            android:name=\"productId\"\n            app:argType=\"string\" />\n        <action\n            android:id=\"@+id/action_productDetailsFragment_to_cartFragment\"\n            app:destination=\"@id/cartFragment\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/cartFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.CartFragment\"\n        android:label=\"fragment_cart\"\n        tools:layout=\"@layout/fragment_cart\" >\n        <action\n            android:id=\"@+id/action_cartFragment_to_selectAddressFragment\"\n            app:destination=\"@id/selectAddressFragment\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/selectAddressFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.SelectAddressFragment\"\n        android:label=\"fragment_select_address\"\n        tools:layout=\"@layout/fragment_select_address\" >\n        <action\n            android:id=\"@+id/action_selectAddressFragment_to_addEditAddressFragment\"\n            app:destination=\"@id/addEditAddressFragment\" />\n        <action\n            android:id=\"@+id/action_selectAddressFragment_to_selectPaymentFragment\"\n            app:destination=\"@id/selectPaymentFragment\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/addEditAddressFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.AddEditAddressFragment\"\n        android:label=\"fragment_add_edit_address\"\n        tools:layout=\"@layout/fragment_add_edit_address\" >\n        <argument\n            android:name=\"isEdit\"\n            app:argType=\"boolean\" />\n        <argument\n            android:name=\"addressId\"\n            app:argType=\"string\"\n            app:nullable=\"true\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/favoritesFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.FavoritesFragment\"\n        android:label=\"fragment_favorites\"\n        tools:layout=\"@layout/fragment_favorites\" >\n        <action\n            android:id=\"@+id/action_favoritesFragment_to_productDetailsFragment\"\n            app:destination=\"@id/productDetailsFragment\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/selectPaymentFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.SelectPaymentFragment\"\n        android:label=\"fragment_select_payment\"\n        tools:layout=\"@layout/fragment_select_payment\" >\n        <action\n            android:id=\"@+id/action_selectPaymentFragment_to_orderSuccessFragment\"\n            app:destination=\"@id/orderSuccessFragment\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/orderSuccessFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.OrderSuccessFragment\"\n        android:label=\"fragment_order_success\"\n        tools:layout=\"@layout/fragment_order_success\" >\n        <action\n            android:id=\"@+id/action_orderSuccessFragment_to_homeFragment\"\n            app:destination=\"@id/homeFragment\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/accountFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.AccountFragment\"\n        android:label=\"fragment_account\"\n        tools:layout=\"@layout/fragment_account\" >\n        <action\n            android:id=\"@+id/action_accountFragment_to_ordersFragment\"\n            app:destination=\"@id/ordersFragment\" />\n        <action\n            android:id=\"@+id/action_accountFragment_to_addressFragment\"\n            app:destination=\"@id/addressFragment\" />\n        <action\n            android:id=\"@+id/action_accountFragment_to_profileFragment\"\n            app:destination=\"@id/profileFragment\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/ordersFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.OrdersFragment\"\n        android:label=\"fragment_orders\"\n        tools:layout=\"@layout/fragment_orders\" >\n        <action\n            android:id=\"@+id/action_ordersFragment_to_orderDetailsFragment\"\n            app:destination=\"@id/orderDetailsFragment\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/orderDetailsFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.OrderDetailsFragment\"\n        android:label=\"fragment_order_details\"\n        tools:layout=\"@layout/fragment_order_details\" >\n        <argument\n            android:name=\"orderId\"\n            app:argType=\"string\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/addressFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.AddressFragment\"\n        android:label=\"fragment_address\"\n        tools:layout=\"@layout/fragment_address\" >\n        <action\n            android:id=\"@+id/action_addressFragment_to_addEditAddressFragment\"\n            app:destination=\"@id/addEditAddressFragment\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/profileFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.home.ProfileFragment\"\n        android:label=\"fragment_profile\"\n        tools:layout=\"@layout/fragment_profile\" />\n</navigation>"
  },
  {
    "path": "app/src/main/res/navigation/signup_nav_graph.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<navigation xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/nav_graph\"\n    app:startDestination=\"@id/SignupFragment\">\n    <fragment\n        android:id=\"@+id/LoginFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.loginSignup.LoginFragment\"\n        android:label=\"@string/login_fragment_label\"\n        tools:layout=\"@layout/fragment_login\">\n        <action\n            android:id=\"@+id/action_login_to_signup\"\n            app:destination=\"@id/SignupFragment\"\n            app:popUpTo=\"@id/SignupFragment\"\n            app:popUpToInclusive=\"true\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/SignupFragment\"\n        android:name=\"com.vishalgaur.shoppingapp.ui.loginSignup.SignupFragment\"\n        android:label=\"@string/signup_fragment_label\"\n        tools:layout=\"@layout/fragment_signup\">\n        <action\n            android:id=\"@+id/action_signup_to_login\"\n            app:destination=\"@id/LoginFragment\" />\n    </fragment>\n</navigation>"
  },
  {
    "path": "app/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <declare-styleable name=\"AppBar\">\n        <attr name=\"actionBarSize\">72dp</attr>\n    </declare-styleable>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"purple_200\">#FFBB86FC</color>\n    <color name=\"purple_500\">#FF6200EE</color>\n    <color name=\"purple_700\">#FF3700B3</color>\n    <color name=\"teal_200\">#FF03DAC5</color>\n    <color name=\"teal_700\">#FF018786</color>\n    <color name=\"green_500\">#018786</color>\n    <color name=\"red_600\">#b00020</color>\n    <color name=\"holo_red_light\">#ff4444</color>\n    <color name=\"black\">#FF000000</color>\n    <color name=\"dark_gray\">#505050</color>\n    <color name=\"gray\">#999999</color>\n    <color name=\"white\">#FFFFFFFF</color>\n    <color name=\"blue_500\">#004dca</color>\n    <color name=\"blue_200\">#4284ed</color>\n    <color name=\"blue_accent_300\">#02d5ee</color>\n    <color name=\"gold\">#FFD770</color>\n    <color name=\"light_gray\">#CCCCCC</color>\n    <color name=\"mtrl_textinput_default_box_stroke_color\">#cccccc</color>\n    <color name=\"transparent\">#00000000</color>\n    <color name=\"blue_shadow_color\">#B9DADF</color>\n    <color name=\"loader_background_color\">#55AAAAAA</color>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <dimen name=\"fab_margin\">16dp</dimen>\n    <dimen name=\"radius\">3dp</dimen>\n    <dimen name=\"dots_height\">32dp</dimen>\n    <dimen name=\"radio_padding_size\">16dp</dimen>\n    <dimen name=\"radio_margin_size\">8dp</dimen>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/font_certs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <array name=\"com_google_android_gms_fonts_certs\">\n        <item>@array/com_google_android_gms_fonts_certs_dev</item>\n        <item>@array/com_google_android_gms_fonts_certs_prod</item>\n    </array>\n    <string-array name=\"com_google_android_gms_fonts_certs_dev\">\n        <item>\n            MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=\n        </item>\n    </string-array>\n    <string-array name=\"com_google_android_gms_fonts_certs_prod\">\n        <item>\n            MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK\n        </item>\n    </string-array>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/preloaded_fonts.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <array name=\"preloaded_fonts\" translatable=\"false\">\n        <item>@font/nunito_sans</item>\n        <item>@font/nunito_sans_extrabold</item>\n    </array>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/shapes.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!--Shape Appearance for small components like chips, buttons, text fields and FABs-->\n    <style name=\"ShapeAppearance.MyTheme.SmallComponent\" parent=\"ShapeAppearance.MaterialComponents.SmallComponent\">\n        <!--Your custom shape here-->\n        <item name=\"cornerSize\">4dp</item>\n    </style>\n\n    <!--Shape Appearance for medium components like cards, alert dialogs-->\n    <style name=\"ShapeAppearance.MyTheme.MediumComponent\" parent=\"ShapeAppearance.MaterialComponents.MediumComponent\">\n        <!--Your custom shape here-->\n        <item name=\"cornerSize\">4dp</item>\n    </style>\n\n    <!--Shape Appearance for large components like side and bottom navigation drawers-->\n    <style name=\"ShapeAppearance.MyTheme.LargeComponent\" parent=\"ShapeAppearance.MaterialComponents.LargeComponent\">\n        <!--Your custom shape here-->\n        <item name=\"cornerSize\">4dp</item>\n    </style>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Shopping App</string>\n    <string name=\"action_settings\">Settings</string>\n    <!-- Strings used for fragments for navigation -->\n    <string name=\"first_fragment_label\">First Fragment</string>\n    <string name=\"second_fragment_label\">Second Fragment</string>\n    <string name=\"login_fragment_label\">Login Fragment</string>\n    <string name=\"signup_fragment_label\">Signup Fragment</string>\n    <string name=\"otp_fragment_label\">Otp Fragment</string>\n    <string name=\"signup_welcome_hello\">Hello,</string>\n    <string name=\"signup_welcome_text\">Sign Up!</string>\n    <string name=\"signup_name_hint\">USER NAME</string>\n    <string name=\"signup_mobile_hint\">MOBILE</string>\n    <string name=\"signup_password_hint\">PASSWORD</string>\n    <string name=\"signup_conf_password_hint\">CONFIRM PASSWORD</string>\n    <string name=\"signup_switch_tnc_label\">I accept the policy and terms</string>\n    <string name=\"signup_btn_text\">Sign Up</string>\n    <string name=\"signup_name_ph\">Your Name</string>\n    <string name=\"signup_mobile_ph\">Your Mobile</string>\n    <string name=\"signup_email_hint\">E-Mail</string>\n    <string name=\"signup_email_ph\">Your email</string>\n    <string name=\"signup_password_ph\">Enter Password</string>\n    <string name=\"signup_cnf_password_ph\">Enter Password Again</string>\n    <string name=\"signup_login_text\">Already have an account? Log In</string>\n    <string name=\"bg_img_desc\">Image View</string>\n    <string name=\"login_welcome\">Welcome Back,</string>\n    <string name=\"login_welcome_text\">Log In!</string>\n    <string name=\"login_mobile_hint\">MOBILE NUMBER</string>\n    <string name=\"login_mobile_ph\">Enter mobile number</string>\n    <string name=\"login_password_hint\">PASSWORD</string>\n    <string name=\"login_password_ph\">Enter Password</string>\n    <string name=\"login_switch_remember_text\">Remember Me</string>\n    <string name=\"login_btn_text\">Log In</string>\n    <string name=\"login_forgot_text\">Forgot Password?</string>\n    <string name=\"otp_label_text\">Enter the OTP received on Registered Mobile Number</string>\n    <string name=\"otp_otp_ph\">6 Digit OTP</string>\n    <string name=\"otp_verify_btn_text\">VERIFY</string>\n    <string name=\"otp_verify_error_text\">Wrong OTP!</string>\n    <string name=\"otp_message_1\">One Step to go…</string>\n    <string name=\"otp_message_2\">O T P</string>\n    <string name=\"login_error_text\">Incorrect Mobile Number or Password</string>\n    <string name=\"login_signup_text\">New User? Sign Up</string>\n    <string name=\"signup_seller_text\">Do you wish to sell any products?</string>\n    <string name=\"home_add_fab_desc\">Add Product FAB</string>\n    <string name=\"add_pro_name_label_text\">Product Name</string>\n    <string name=\"add_pro_price_label_text\">Selling Price</string>\n    <string name=\"add_pro_mrp_label_text\">MRP</string>\n    <string name=\"add_pro_desc_label_text\">Description</string>\n    <string name=\"add_pro_sizes_label_text\">Sizes Available</string>\n    <string name=\"app_pro_btn_text\">Add Product</string>\n    <string name=\"pro_cat_dialog_title\">Select Product Category</string>\n    <string name=\"pro_cat_dialog_cancel_btn\">Cancel</string>\n    <string name=\"pro_cat_dialog_ok_btn\">OK</string>\n    <string name=\"add_pro_error_empty\">Fill all the details!</string>\n    <string name=\"add_pro_color_label_text\">Colors Available</string>\n    <string name=\"add_product_error_string\">Fill all the details!</string>\n    <string name=\"add_pro_error_price_string\">Price can not be 0.</string>\n    <string name=\"pro_item_price\">Price: $%d</string>\n    <string name=\"product_detail_image_desc\">Product Image</string>\n    <string name=\"pro_details_like_btn_desc\">Like Button</string>\n    <string name=\"pro_details_select_size_lable_text\">Select Size</string>\n    <string name=\"pro_details_select_color_label_text\">Select Color</string>\n    <string name=\"pro_details_specif_label_text\">Specification</string>\n    <string name=\"pro_details_price_value\">$%s</string>\n    <string name=\"pro_details_actual_strike_value\">$%s</string>\n    <string name=\"add_pro_images_label_text\">Product Images (Max: 3)</string>\n    <string name=\"search_app_bar_title\">Search</string>\n    <string name=\"content_description_search\">Search Icon</string>\n    <string name=\"more_app_bar_title\">More</string>\n    <string name=\"content_description_more\">More Icon</string>\n    <string name=\"add_img_item_desc\">Image Item</string>\n    <string name=\"add_img_close_btn_desc\">Image Remove Button</string>\n    <string name=\"add_product_error_img_upload\">Error uploading Images, Try Again!</string>\n    <string name=\"product_actual_price_text\"><strike>$1000.00</strike></string>\n    <string name=\"product_offer_percent_text\">25% Off</string>\n    <string name=\"pro_offer_precent_text\">%s%% Off</string>\n    <string name=\"delete_dialog_title_text\">Are you sure?</string>\n    <string name=\"delete_dialog_message_text\">On proceeding, Product : %s will be deleted.</string>\n    <string name=\"delete_dialog_delete_btn_text\">Delete</string>\n    <string name=\"edit_product_btn_text\">Save Changes</string>\n    <string name=\"home_app_bar_search_label\">Search</string>\n    <string name=\"home_app_bar_filter_label\">Filter</string>\n    <string name=\"search_hint\">Search Product…</string>\n    <string name=\"search_placeholder_text\">Search Product</string>\n    <string name=\"add_product_insert_error\">Error Saving Product!</string>\n    <string name=\"app_icon_img_desc\">App Icon</string>\n    <string name=\"pro_details_add_to_cart_btn_text\">Add To Cart</string>\n    <string name=\"pro_details_go_to_cart_btn_text\">Go To Cart</string>\n    <string name=\"pro_details_delete_btn_desc\">Remove Product Button</string>\n    <string name=\"cart_check_out_btn\">Check Out</string>\n    <string name=\"price_card_items_string\">Items(%s)</string>\n    <string name=\"price_card_shipping_label_string\">Shipping</string>\n    <string name=\"price_card_charges_label_text\">Import Charges</string>\n    <string name=\"price_card_divider_desc\">Divider Line</string>\n    <string name=\"cart_fragment_label\">Your Cart</string>\n    <string name=\"next_btn_text\">Next</string>\n    <string name=\"edit_btn_text\">Edit</string>\n    <string name=\"ship_to_title\">Ship To</string>\n    <string name=\"add_menu_item_title\">Add</string>\n    <string name=\"add_address_btn_text\">Add Address</string>\n    <string name=\"save_address_btn_text\">Save Address</string>\n    <string name=\"price_card_total_label_text\">Total Price</string>\n    <string name=\"price_text\">$%s</string>\n    <string name=\"add_address_country_label_text\">Country or region</string>\n    <string name=\"add_address_first_name_label_text\">First Name</string>\n    <string name=\"add_address_last_name_label_text\">Last Name</string>\n    <string name=\"add_address_street_add_label_text\">Street Address</string>\n    <string name=\"add_address_street_add2_label_text\">Street Address 2 (Optional)</string>\n    <string name=\"add_address_city_label_text\">City</string>\n    <string name=\"add_address_state_label_text\">State/Province/Region</string>\n    <string name=\"add_address_phone_label_text\">Phone Number</string>\n    <string name=\"county_hint\">India</string>\n    <string name=\"add_address_zipcode_label_text\">Zip Code</string>\n    <string name=\"person_name\">%s %s</string>\n    <string name=\"save_address_error_text\">Error Saving Address!</string>\n    <string name=\"ship_to_error_empty\">Please select an address!</string>\n    <string name=\"delete_address_message_text\">On clicking Delete, Address will be deleted premanently!</string>\n    <string name=\"plus_btn_desc\">Increase Button</string>\n    <string name=\"minus_btn_desc\">Decrease Button</string>\n    <string name=\"delete_cart_item_message_text\">On Proceeding, selected Item will be deleted from your Cart.</string>\n    <string name=\"buy_now_btn_text\">Buy Now</string>\n    <string name=\"home_app_bar_favorites_label\">Favorites</string>\n    <string name=\"no_likes_text\">No Products Liked Yet!</string>\n    <string name=\"home_ad_image_desc\">Advertisement</string>\n    <string name=\"bottom_nav_home_label\">Home</string>\n    <string name=\"bottom_nav_cart_label\">Cart</string>\n    <string name=\"bottom_nav_account_label\">Account</string>\n    <string name=\"pay_by_title\">Choose Payment Method</string>\n    <string name=\"pay_by_next_btn_text\">Pay $%s</string>\n    <string name=\"pay_by_error_empty\">Select a payment method!</string>\n    <string name=\"back_to_home_text\">Back To Home</string>\n    <string name=\"success_img_desc\">Success Tick Image</string>\n    <string name=\"success_label\">Success</string>\n    <string name=\"order_success_message_text\">thank you for shopping</string>\n    <string name=\"no_items_in_cart_text\">No Products Added Yet!</string>\n    <string name=\"bottom_nav_orders_label\">Orders</string>\n    <string name=\"account_profile_label\">Profile</string>\n    <string name=\"account_orders_label\">Orders</string>\n    <string name=\"account_address_label\">Address</string>\n    <string name=\"account_fragment_title\">Account</string>\n    <string name=\"account_sign_out_label\">Sign Out</string>\n    <string name=\"sign_out_dialog_title_text\">Sign Out?</string>\n    <string name=\"sign_out_dialog_message_text\">On proceeding, you will be signed out of the app.</string>\n    <string name=\"dialog_sign_out_btn_text\">Sign Out</string>\n    <string name=\"order_summary_items_label\">Items</string>\n    <string name=\"no_orders_placed_text\">Nothing To Show</string>\n    <string name=\"orders_fragment_title\">Orders</string>\n    <string name=\"order_date_text\">Ordered On : %s %s, %s</string>\n    <string name=\"order_items_count_text\">%s items purchased</string>\n    <string name=\"products_label_text\">Products</string>\n    <string name=\"shipping_details_label_text\">Shipping Details</string>\n    <string name=\"payment_details_label_text\">Payment Details</string>\n    <string name=\"ship_date_text\">Date Shipping</string>\n    <string name=\"shipping_address_label_string\">Address</string>\n    <string name=\"ship_curr_status_label_text\">Current Status</string>\n    <string name=\"order_details_fragment_title\">Order Details</string>\n    <string name=\"change_status_label_text\">Change Order Status Button</string>\n    <string name=\"no_addresses_text\">No Address added Yet!</string>\n    <string name=\"profile_img_desc\">Profile Image</string>\n    <string name=\"profile_email_label_text\">Email</string>\n    <string name=\"profile_mobile_label_text\">Mobile Number</string>\n    <string name=\"sending_otp_msg\">Sending OTP…</string>\n    <string name=\"otp_sent_msg\">OTP Sent</string>\n    <string name=\"otp_invalid_req_failure\">Request Failure</string>\n    <string name=\"process_order_msg\">Processing your Order…</string>\n    <string name=\"redirect_home_timer_text\">Redirecting to home in %s</string>\n    <string name=\"status_dialog_title\">Select Status of Product</string>\n    <string name=\"price_card_status_label_string\">Order Status</string>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <!--Bottom Sheets-->\n    <style name=\"ThemeOverlay.MyTheme.BottomSheetDialog\" parent=\"ThemeOverlay.MaterialComponents.Dialog\">\n        <item name=\"android:windowIsFloating\">false</item>\n        <item name=\"android:windowBackground\">@android:color/transparent</item>\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n        <item name=\"bottomSheetStyle\">@style/Widget.MyTheme.BottomSheet.Modal</item>\n        <item name=\"android:navigationBarColor\">?attr/colorSurface</item>\n        <item name=\"android:navigationBarDividerColor\" tools:ignore=\"NewApi\">\n            @android:color/transparent\n        </item>\n    </style>\n\n    <style name=\"Widget.MyTheme.BottomSheet.Modal\" parent=\"Widget.MaterialComponents.BottomSheet.Modal\">\n        <item name=\"shapeAppearanceOverlay\">?attr/shapeAppearanceLargeComponent</item>\n    </style>\n\n    <!--Navigation Drawer-->\n    <style name=\"Widget.MyTheme.NavigationView\" parent=\"Widget.MaterialComponents.NavigationView\">\n        <item name=\"itemTextAppearance\">?attr/textAppearanceBody2</item>\n    </style>\n\n    <style name=\"Widget.App.Button.OutlinedButton.IconOnly\" parent=\"Widget.MaterialComponents.Button.OutlinedButton\">\n        <item name=\"iconPadding\">0dp</item>\n        <item name=\"android:insetTop\">0dp</item>\n        <item name=\"android:insetBottom\">0dp</item>\n        <item name=\"android:paddingLeft\">8dp</item>\n        <item name=\"android:paddingRight\">8dp</item>\n        <item name=\"android:minWidth\">30dp</item>\n        <item name=\"android:minHeight\">30dp</item>\n    </style>\n\n    <style name=\"AppBarTitleStyle\" parent=\"TextAppearance.MyTheme.Headline6\">\n        <item name=\"android:textStyle\">bold</item>\n    </style>\n\n    <style name=\"BottomNavigationStyle\" parent=\"Widget.MaterialComponents.BottomNavigationView\">\n        <item name=\"itemIconSize\">28dp</item>\n        <item name=\"itemTextColor\">@drawable/bottom_nav_selector</item>\n        <item name=\"itemIconTint\">@drawable/bottom_nav_selector</item>\n    </style>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.ShoppingApp\" parent=\"Base.Theme.ShoppingApp\" />\n\n    <style name=\"Base.Theme.ShoppingApp\" parent=\"Theme.MaterialComponents.Light.NoActionBar\">\n        <!-- Primary brand color. -->\n        <item name=\"colorPrimary\">@color/blue_500</item>\n        <item name=\"colorPrimaryVariant\">@color/purple_700</item>\n        <!-- Secondary brand color. -->\n        <item name=\"colorSecondary\">@color/blue_accent_300</item>\n        <item name=\"colorSecondaryVariant\">@color/green_500</item>\n\n        <item name=\"android:colorBackground\">@color/white</item>\n        <item name=\"colorSurface\">@color/white</item>\n        <item name=\"colorError\">@color/red_600</item>\n        <!--\"On\" colors define how text, icons and strokes are colored in relation to the surface-->\n        <!--on which they appear.-->\n        <item name=\"colorOnPrimary\">@color/white</item>\n        <item name=\"colorOnSecondary\">@color/white</item>\n        <item name=\"colorOnBackground\">@color/black</item>\n        <item name=\"colorOnSurface\">@color/black</item>\n        <item name=\"colorOnError\">@color/white</item>\n        <!-- Status bar color. -->\n        <item name=\"android:statusBarColor\" tools:targetApi=\"l\">?attr/colorSurface</item>\n        <item name=\"android:windowLightStatusBar\">true</item>\n        <!-- Customize your theme here. -->\n\n\n        <item name=\"fontFamily\">@font/nunito_sans</item>\n\n        <!--Material type attributes-->\n        <item name=\"textAppearanceHeadline1\">@style/TextAppearance.MyTheme.Headline1</item>\n        <item name=\"textAppearanceHeadline2\">@style/TextAppearance.MyTheme.Headline2</item>\n        <item name=\"textAppearanceHeadline3\">@style/TextAppearance.MyTheme.Headline3</item>\n        <item name=\"textAppearanceHeadline4\">@style/TextAppearance.MyTheme.Headline4</item>\n        <item name=\"textAppearanceHeadline5\">@style/TextAppearance.MyTheme.Headline5</item>\n        <item name=\"textAppearanceHeadline6\">@style/TextAppearance.MyTheme.Headline6</item>\n        <item name=\"textAppearanceSubtitle1\">@style/TextAppearance.MyTheme.Subtitle1</item>\n        <item name=\"textAppearanceSubtitle2\">@style/TextAppearance.MyTheme.Subtitle2</item>\n        <item name=\"textAppearanceBody1\">@style/TextAppearance.MyTheme.Body1</item>\n        <item name=\"textAppearanceBody2\">@style/TextAppearance.MyTheme.Body2</item>\n        <item name=\"textAppearanceButton\">@style/TextAppearance.MyTheme.Button</item>\n        <item name=\"textAppearanceCaption\">@style/TextAppearance.MyTheme.Caption</item>\n        <item name=\"textAppearanceOverline\">@style/TextAppearance.MyTheme.Overline</item>\n        <!--Material shape attributes-->\n        <item name=\"shapeAppearanceSmallComponent\">@style/ShapeAppearance.MyTheme.SmallComponent\n        </item>\n        <item name=\"shapeAppearanceMediumComponent\">@style/ShapeAppearance.MyTheme.MediumComponent\n        </item>\n        <item name=\"shapeAppearanceLargeComponent\">@style/ShapeAppearance.MyTheme.LargeComponent\n        </item>\n        <!--Component styles-->\n        <item name=\"materialAlertDialogTheme\">@style/ThemeOverlay.MaterialComponents.Dialog.Alert\n        </item>\n        <item name=\"bottomSheetDialogTheme\">@style/ThemeOverlay.MyTheme.BottomSheetDialog</item>\n        <item name=\"navigationViewStyle\">@style/Widget.MyTheme.NavigationView</item>\n        <item name=\"toolbarStyle\">@style/Widget.MaterialComponents.Toolbar.PrimarySurface</item>\n    </style>\n\n    <!--    <style name=\"Theme.ShoppingApp.NoActionBar\">-->\n    <!--        <item name=\"windowActionBar\">false</item>-->\n    <!--        <item name=\"windowNoTitle\">true</item>-->\n    <!--    </style>-->\n\n    <!--    <style name=\"Theme.ShoppingApp.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\" />-->\n\n    <!--    <style name=\"Theme.ShoppingApp.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\" />-->\n</resources>"
  },
  {
    "path": "app/src/main/res/values/type.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <!--Typography-->\n\n    <style name=\"TextAppearance.MyTheme.Headline1\" parent=\"TextAppearance.MaterialComponents.Headline1\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Headline2\" parent=\"TextAppearance.MaterialComponents.Headline2\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Headline3\" parent=\"TextAppearance.MaterialComponents.Headline3\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Headline4\" parent=\"TextAppearance.MaterialComponents.Headline4\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Headline5\" parent=\"TextAppearance.MaterialComponents.Headline5\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Headline6\" parent=\"TextAppearance.MaterialComponents.Headline6\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Subtitle1\" parent=\"TextAppearance.MaterialComponents.Subtitle1\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Subtitle2\" parent=\"TextAppearance.MaterialComponents.Subtitle2\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Body1\" parent=\"TextAppearance.MaterialComponents.Body1\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Body2\" parent=\"TextAppearance.MaterialComponents.Body2\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Button\" parent=\"TextAppearance.MaterialComponents.Button\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Caption\" parent=\"TextAppearance.MaterialComponents.Caption\">\n        <!--Your custom type style here-->\n    </style>\n\n    <style name=\"TextAppearance.MyTheme.Overline\" parent=\"TextAppearance.MaterialComponents.Overline\">\n        <!--Your custom type style here-->\n    </style>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values-night/themes.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.ShoppingApp\" parent=\"Theme.MaterialComponents.DayNight.DarkActionBar\">\n        <!-- Primary brand color. -->\n        <item name=\"colorPrimary\">@color/purple_200</item>\n        <item name=\"colorPrimaryVariant\">@color/purple_700</item>\n        <item name=\"colorOnPrimary\">@color/black</item>\n        <!-- Secondary brand color. -->\n        <item name=\"colorSecondary\">@color/teal_200</item>\n        <item name=\"colorSecondaryVariant\">@color/teal_200</item>\n        <item name=\"colorOnSecondary\">@color/black</item>\n        <!-- Status bar color. -->\n        <item name=\"android:statusBarColor\" tools:targetApi=\"l\">?attr/colorPrimaryVariant</item>\n        <!-- Customize your theme here. -->\n    </style>\n</resources>"
  },
  {
    "path": "app/src/test/java/com/vishalgaur/shoppingapp/UtilsTest.kt",
    "content": "package com.vishalgaur.shoppingapp\n\nimport org.hamcrest.CoreMatchers.`is`\nimport org.hamcrest.MatcherAssert.assertThat\nimport org.junit.Assert.assertEquals\nimport org.junit.Test\n\nclass UtilsTest {\n\t@Test\n\tfun checkEmail_empty_returnsFalse() {\n\t\tval email = \"\"\n\t\tval result = isEmailValid(email)\n\n\t\tassertEquals(result, false)\n\t}\n\n\t@Test\n\tfun checkEmail_invalid_returnsFalse() {\n\t\tval email1 = \"vishalgaur\"\n\t\tval email2 = \"vishalgaur.com\"\n\t\tval email3 = \"vishalgaur@google\"\n\t\tval result1 = isEmailValid(email1)\n\t\tval result2 = isEmailValid(email2)\n\t\tval result3 = isEmailValid(email3)\n\n\t\tassertEquals(result1, false)\n\t\tassertEquals(result2, false)\n\t\tassertEquals(result3, false)\n\t}\n\n\t@Test\n\tfun checkEmail_valid_returnsTrue() {\n\t\tval email1 = \"    vishalgaur@google.com\"\n\t\tval email2 = \"vishal123@gmail.co.in     \"\n\t\tval email3 = \"rr.vishalgaur@gmail.com\"\n\t\tval result1 = isEmailValid(email1)\n\t\tval result2 = isEmailValid(email2)\n\t\tval result3 = isEmailValid(email3)\n\n\t\tassertEquals(result1, true)\n\t\tassertEquals(result2, true)\n\t\tassertEquals(result3, true)\n\t}\n\n\t@Test\n\tfun checkPhone_empty_returnsFalse() {\n\t\tval phone = \"\"\n\t\tval result = isPhoneValid(phone)\n\n\t\tassertEquals(result, false)\n\t}\n\n\t@Test\n\tfun checkPhone_invalid_returnsFalse() {\n\t\tval phone1 = \"1968743574694865\"\n\t\tval phone2 = \"  1111  \"\n\t\tval phone3 = \"2454678910\"\n\t\tval result1 = isPhoneValid(phone1)\n\t\tval result2 = isPhoneValid(phone2)\n\t\tval result3 = isPhoneValid(phone3)\n\n\t\tassertEquals(result1, false)\n\t\tassertEquals(result2, false)\n\t\tassertEquals(result3, false)\n\t}\n\n\t@Test\n\tfun checkPhone_valid_returnsTrue() {\n\t\tval phone1 = \"9876543210\"\n\t\tval phone2 = \"    6985741526\"\n\t\tval phone3 = \"8989895858   \"\n\t\tval result1 = isPhoneValid(phone1)\n\t\tval result2 = isPhoneValid(phone2)\n\t\tval result3 = isPhoneValid(phone3)\n\n\t\tassertEquals(result1, true)\n\t\tassertEquals(result2, true)\n\t\tassertEquals(result3, true)\n\t}\n\n\t@Test\n\tfun getRandomString_hasExpectedLength() {\n\t\tval result1 = getRandomString(10, \"odweuih\", 10)\n\t\tval result2 = getRandomString(10, \"\", 5)\n\t\tassertThat(result1.length, `is`(27))\n\t\tassertThat(result2.length, `is`(15))\n\t}\n\n\t@Test\n\tfun getProductId_hasExpectedSubStrings() {\n\t\tval result = getProductId(\"soewifnc9we48yf0\", \"shoes\")\n\t\tval subs = result.split(\"-\")\n\t\tassert(subs.size >= 3)\n\t}\n\n\t@Test\n\tfun getOfferPercentage_zeroZero_returnsZero() {\n\t\tval result = getOfferPercentage(0.0, 0.0)\n\t\tassertThat(result, `is`(0))\n\t}\n\n\t@Test\n\tfun getOfferPercentage_highLow_returnsZero() {\n\t\tval result = getOfferPercentage(90.0, 100.0)\n\t\tassertThat(result, `is`(0))\n\t}\n\n\t@Test\n\tfun getOfferPercentage_lowHigh_returnsOfferInt() {\n\t\tval result1 = getOfferPercentage(100.0, 90.5)\n\t\tval result2 = getOfferPercentage(100.0, 90.75)\n\t\tval result3 = getOfferPercentage(100.0, 90.25)\n\t\tassertThat(result1, `is`(10))\n\t\tassertThat(result2, `is`(9))\n\t\tassertThat(result3, `is`(10))\n\t}\n\n\t@Test\n\tfun getOfferPercentage_equal_returnsZero() {\n\t\tval result = getOfferPercentage(90.5, 90.5)\n\t\tassertThat(result, `is`(0))\n\t}\n}"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\nbuildscript {\n    ext {\n        kotlin_version = \"1.4.32\"\n        lifecycle_version = \"2.3.1\"\n        room_version = \"2.3.0\"\n        glide_version = \"4.11.0\"\n    }\n    repositories {\n        google()\n        jcenter()\n    }\n    dependencies {\n        classpath \"com.android.tools.build:gradle:4.1.3\"\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n        classpath 'com.google.gms:google-services:4.3.5'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Thu Apr 15 13:02:30 IST 2021\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.5-bin.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n# AndroidX package structure to make it clearer which packages are bundled with the\n# Android operating system, and which are packaged with your app\"s APK\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\nandroid.useAndroidX=true\n# Automatically convert third-party libraries to use AndroidX\nandroid.enableJetifier=true\n# Kotlin code style for this project: \"official\" or \"obsolete\":\nkotlin.code.style=official"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windows variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app'\nrootProject.name = \"Shopping App\""
  }
]