├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── gradle.xml ├── misc.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── noobshubham │ │ └── gostore │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── noobshubham │ │ │ └── gostore │ │ │ ├── Common.kt │ │ │ ├── MapsActivity.kt │ │ │ ├── adapter │ │ │ └── GroceryAdapter.kt │ │ │ ├── database │ │ │ ├── GroceryDao.kt │ │ │ ├── GroceryDatabase.kt │ │ │ ├── GroceryRepository.kt │ │ │ └── entity │ │ │ │ └── GroceryEntities.kt │ │ │ ├── grocery │ │ │ ├── GroceryActivity.kt │ │ │ ├── GroceryViewModal.kt │ │ │ └── GroceryViewModalFactory.kt │ │ │ ├── model │ │ │ ├── Geometry.kt │ │ │ ├── Location.kt │ │ │ ├── MyPlaces.kt │ │ │ ├── Northeast.kt │ │ │ ├── OpeningHours.kt │ │ │ ├── Photos.kt │ │ │ ├── Results.kt │ │ │ ├── Southwest.kt │ │ │ ├── UserData.kt │ │ │ └── Viewport.kt │ │ │ ├── registration │ │ │ ├── LoginFragment.kt │ │ │ ├── RegistrationActivity.kt │ │ │ └── SignupFragment.kt │ │ │ └── remote │ │ │ ├── IGoogleAPIService.kt │ │ │ └── RetrofitClient.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── arrow.xml │ │ ├── buttonshapewhitebg.xml │ │ ├── ic_bank.xml │ │ ├── ic_baseline_add_24.xml │ │ ├── ic_baseline_delete_24.xml │ │ ├── ic_bed.xml │ │ ├── ic_credit_card.xml │ │ ├── ic_doctor.xml │ │ ├── ic_google.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_notes.xml │ │ ├── ic_playlist.xml │ │ ├── ic_restaurants.xml │ │ ├── ic_school.xml │ │ ├── icon.xml │ │ └── splash_image.xml │ │ ├── font │ │ ├── calibri.ttf │ │ ├── gotham.ttf │ │ └── roboto_medium.ttf │ │ ├── layout │ │ ├── activity_grocery.xml │ │ ├── activity_maps.xml │ │ ├── activity_registration.xml │ │ ├── fragment_login.xml │ │ ├── fragment_signup.xml │ │ ├── grocery_add_dialog.xml │ │ └── single_item_view.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── navigation │ │ └── registration_nav.xml │ │ ├── values-land │ │ └── dimens.xml │ │ ├── values-night │ │ └── themes.xml │ │ ├── values-w1240dp │ │ └── dimens.xml │ │ ├── values-w600dp │ │ └── dimens.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ └── test │ └── java │ └── com │ └── noobshubham │ └── gostore │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── preview ├── Screenshot_20220914-082924_GoStore.jpg ├── Screenshot_20220914-082931_GoStore.jpg ├── Screenshot_20220914-083040_Permission controller.jpg ├── Screenshot_20220914-083115_GoStore.jpg ├── Screenshot_20220914-083136_GoStore.jpg ├── Screenshot_20220914-083145_GoStore.jpg ├── Screenshot_20220914-083210_GoStore.jpg ├── Screenshot_20220914-083219_GoStore.jpg ├── Screenshot_20220914-083226_GoStore.jpg ├── Screenshot_20220914-083238_GoStore.jpg ├── Screenshot_20220918-092803_GoStore.jpg ├── Screenshot_20220918-092956_GoStore.jpg └── mockups │ ├── banner.png │ ├── grocery list.png │ ├── map_part.png │ └── registration.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | /app/google-services.json 17 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 42 | 43 | 44 | 45 | 46 | 47 | 49 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 noobshubham 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GoStore: [Internship Program Project](https://github.com/smartinternz02/SPSGP-65269-Virtual-Internship---Android-Application-Development-Using-Kotlin) 2 | ================================== 3 | 4 | ![](https://github.com/noobshubham/GoStore/blob/master/preview/mockups/banner.png) 5 | 6 | A mobile app is built where the user can search for his nearby locations based on his requirement. Whenever the user gives input of business type like a hotel, petrol pumps, hospitals, etc. using Place API and as a response we obtain the co-ordinates that are marked on the Google map. 7 | 8 | Additional Feature 9 | ------------ 10 | 11 | - Digital Grocery List - As we can't remember everything, users frequently go to store & forget to buy the things they want to buy. However, with the assistance of GoStore app, you can make a list of the groceries you intend to buy so that you don't forget anything. 12 | 13 | 14 | Screenshot 15 | ------------ 16 | 17 | ![](https://github.com/noobshubham/GoStore/blob/master/preview/mockups/registration.png) 18 | ![](https://github.com/noobshubham/GoStore/blob/master/preview/mockups/map_part.png) 19 | ![](https://github.com/noobshubham/GoStore/blob/master/preview/mockups/grocery%20list.png) 20 | 21 | 22 | Architecture 23 | ------------ 24 | 25 | ![](https://i.postimg.cc/QtD6LhRL/download.png) 26 | 27 | 28 | Prerequisites 29 | ------------ 30 | 31 | To complete the project successfully, you need to install: 32 | - [Android Studio](https://www.geeksforgeeks.org/guide-to-install-and-set-up-android-studio/) 33 | 34 |
35 | Register On Google Cloud 36 | 37 | - [Link To Register For Cloud Account](https://cloud.google.com/) 38 | - [Signup Reference](https://www.youtube.com/watch?v=Oek2VE2ozzE&ab_channel=CodingFreaks) 39 |
40 | 41 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'org.jetbrains.kotlin.android' 4 | id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin' 5 | // Add the Google services Gradle plugin 6 | id 'com.google.gms.google-services' 7 | id 'kotlin-kapt' 8 | } 9 | 10 | android { 11 | compileSdk 33 12 | 13 | defaultConfig { 14 | applicationId "com.noobshubham.gostore" 15 | minSdk 21 16 | targetSdk 33 17 | versionCode 5 18 | versionName "1.4" 19 | 20 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 21 | } 22 | 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_1_8 31 | targetCompatibility JavaVersion.VERSION_1_8 32 | } 33 | kotlinOptions { 34 | jvmTarget = '1.8' 35 | } 36 | buildFeatures { 37 | viewBinding true 38 | } 39 | } 40 | 41 | dependencies { 42 | 43 | implementation 'androidx.core:core-ktx:1.9.0' 44 | implementation 'androidx.appcompat:appcompat:1.5.1' 45 | implementation 'com.google.android.material:material:1.6.1' 46 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 47 | implementation 'androidx.navigation:navigation-fragment-ktx:2.5.2' 48 | // implementation 'androidx.navigation:navigation-ui-ktx:2.5.1' 49 | 50 | // SplashScreen 51 | implementation 'androidx.core:core-splashscreen:1.0.0' 52 | 53 | // EasyPermission 54 | implementation 'pub.devrel:easypermissions:3.0.0' 55 | 56 | // Firebase Authentication & Google Auth 57 | implementation 'com.google.firebase:firebase-auth:21.0.8' 58 | implementation 'com.google.android.gms:play-services-auth:20.3.0' 59 | 60 | // Retrofit 61 | implementation "com.squareup.retrofit2:retrofit:2.9.0" 62 | implementation "com.squareup.retrofit2:converter-gson:2.9.0" 63 | 64 | // Maps & Location 65 | implementation 'com.google.android.gms:play-services-maps:18.1.0' 66 | implementation 'com.google.android.gms:play-services-location:20.0.0' 67 | implementation 'com.google.maps.android:maps-utils-ktx:0.2' 68 | 69 | // Add Google Places dependency 70 | implementation 'com.google.android.libraries.places:places:2.6.0' 71 | 72 | // Material Design autocomplete Searchbar 73 | implementation 'com.github.mancj:MaterialSearchBar:0.8.5' 74 | 75 | // Room components 76 | implementation 'androidx.room:room-ktx:2.4.3' 77 | kapt 'androidx.room:room-compiler:2.4.3' 78 | androidTestImplementation 'androidx.room:room-testing:2.4.3' 79 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/noobshubham/gostore/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.noobshubham.gostore", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 20 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noobshubham/GoStore/8a16030c641d9a6ce7e3738d02b6cb6855329bb8/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/Common.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore 2 | 3 | import com.noobshubham.gostore.model.Results 4 | import com.noobshubham.gostore.remote.IGoogleAPIService 5 | import com.noobshubham.gostore.remote.RetrofitClient 6 | 7 | const val GOOGLE_API_URL = "https://maps.googleapis.com/" 8 | 9 | object Common { 10 | var currentResult: Results? = null 11 | val googleApiService: IGoogleAPIService 12 | get() = RetrofitClient.getClient(GOOGLE_API_URL).create(IGoogleAPIService::class.java) 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/MapsActivity.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore 2 | 3 | import android.Manifest.permission.ACCESS_FINE_LOCATION 4 | import android.annotation.SuppressLint 5 | import android.content.Intent 6 | import android.content.pm.PackageManager 7 | import android.location.Location 8 | import android.os.Build 9 | import android.os.Bundle 10 | import android.os.Looper 11 | import android.util.Log 12 | import android.view.WindowManager 13 | import android.widget.Toast 14 | import androidx.appcompat.app.AppCompatActivity 15 | import androidx.core.app.ActivityCompat 16 | import androidx.core.content.ContextCompat 17 | import com.google.android.gms.location.* 18 | import com.google.android.gms.maps.CameraUpdateFactory 19 | import com.google.android.gms.maps.GoogleMap 20 | import com.google.android.gms.maps.OnMapReadyCallback 21 | import com.google.android.gms.maps.SupportMapFragment 22 | import com.google.android.gms.maps.model.* 23 | import com.mancj.materialsearchbar.MaterialSearchBar 24 | import com.noobshubham.gostore.databinding.ActivityMapsBinding 25 | import com.noobshubham.gostore.grocery.GroceryActivity 26 | import com.noobshubham.gostore.model.MyPlaces 27 | import com.noobshubham.gostore.remote.IGoogleAPIService 28 | import retrofit2.Call 29 | import retrofit2.Callback 30 | import retrofit2.Response 31 | import java.util.* 32 | 33 | 34 | class MapsActivity : AppCompatActivity(), OnMapReadyCallback { 35 | 36 | private lateinit var binding: ActivityMapsBinding 37 | private var map: GoogleMap? = null 38 | 39 | // A default location (India) 40 | private val india = LatLng(22.80720609595059, 79.637510102395) 41 | 42 | // Material Search Bar 43 | private lateinit var materialSearchBar: MaterialSearchBar 44 | 45 | // from reference video 46 | private var latitude: Double = 0.toDouble() 47 | private var longitude: Double = 0.toDouble() 48 | 49 | private var locationPermissionGranted = false 50 | private val PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1 51 | 52 | private lateinit var mLastLocation: Location 53 | private var marker: Marker? = null 54 | 55 | //location 56 | private lateinit var fusedLocationProviderClient: FusedLocationProviderClient 57 | private lateinit var locationRequest: LocationRequest 58 | private lateinit var locationCallback: LocationCallback 59 | 60 | companion object { 61 | private const val MY_PERMISSION_CODE: Int = 2000 62 | } 63 | 64 | private lateinit var mServices: IGoogleAPIService 65 | internal lateinit var currentPlace: MyPlaces 66 | 67 | // [START maps_current_place_on_create] 68 | @SuppressLint("VisibleForTests") 69 | override fun onCreate(savedInstanceState: Bundle?) { 70 | super.onCreate(savedInstanceState) 71 | binding = ActivityMapsBinding.inflate(layoutInflater) 72 | window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN) 73 | setContentView(binding.root) 74 | 75 | binding.showList.setOnClickListener { startActivity(Intent(this, GroceryActivity::class.java)) } 76 | 77 | materialSearchBar = binding.searchbar 78 | 79 | // Obtain the SupportMapFragment and get notified when the map is ready to be used. 80 | val mapFragment = supportFragmentManager 81 | .findFragmentById(R.id.map) as SupportMapFragment 82 | mapFragment.getMapAsync(this) 83 | 84 | // init service 85 | mServices = Common.googleApiService 86 | 87 | getLocationPermission() 88 | 89 | binding.btnRestaurants.setOnClickListener { nearByPlace("Restaurants") } 90 | binding.btnHospitals.setOnClickListener { nearByPlace("Hospitals") } 91 | binding.btnATMs.setOnClickListener { nearByPlace("ATMs") } 92 | binding.btnBanks.setOnClickListener { nearByPlace("Banks") } 93 | binding.btnSchools.setOnClickListener { nearByPlace("Schools") } 94 | binding.btnHotels.setOnClickListener { nearByPlace("Hotels") } 95 | } 96 | 97 | private fun getLocationPermission() { 98 | /* 99 | * Request location permission, so that we can get the location of the 100 | * device. The result of the permission request is handled by a callback, 101 | * onRequestPermissionsResult. 102 | */ 103 | if (ContextCompat.checkSelfPermission(this.applicationContext, ACCESS_FINE_LOCATION) 104 | == PackageManager.PERMISSION_GRANTED) { 105 | locationPermissionGranted = true 106 | } else { 107 | ActivityCompat.requestPermissions(this, arrayOf(ACCESS_FINE_LOCATION), 108 | PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION) 109 | } 110 | } 111 | 112 | private fun nearByPlace(typePlace: String) { 113 | 114 | //clear all marker from map 115 | map?.clear() 116 | 117 | //build url based on location 118 | val url = getUrl(latitude, longitude, typePlace) 119 | mServices.getNearbyPlaces(url) 120 | .enqueue(object : Callback { 121 | override fun onResponse(call: Call, response: Response) { 122 | 123 | currentPlace = response.body()!! 124 | if (response.isSuccessful) { 125 | for (i in 0 until response.body()!!.results!!.size) { 126 | val markerOptions = MarkerOptions() 127 | val googlePlaces = response.body()!!.results!![i] 128 | val lat = googlePlaces.geometry!!.location!!.lat 129 | val lng = googlePlaces.geometry!!.location!!.lng 130 | val placeName = googlePlaces.name 131 | val latLng = LatLng(lat, lng) 132 | markerOptions.position(latLng) 133 | markerOptions.title(placeName) 134 | 135 | when (typePlace) { 136 | "restaurants" -> markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_restaurants)).title(placeName) 137 | "hospitals" -> markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_doctor)).title(placeName) 138 | "ATMs" -> markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_credit_card)).title(placeName) 139 | "banks" -> markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_bank)).title(placeName) 140 | "schools" -> markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_school)).title(placeName) 141 | "hotels" -> markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_bed)).title(placeName) 142 | else -> markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)) 143 | } 144 | // add marker to map 145 | markerOptions.snippet(latLng.toString()) 146 | // to get the lat/lng of place 147 | map?.addMarker(markerOptions) 148 | // move camera 149 | map?.moveCamera(CameraUpdateFactory.newLatLng(latLng)) 150 | map?.animateCamera(CameraUpdateFactory.zoomTo(12f)) 151 | } 152 | } 153 | } 154 | 155 | override fun onFailure(call: Call, t: Throwable) { 156 | Toast.makeText(baseContext, "Error: ${t.message}", Toast.LENGTH_SHORT).show() 157 | } 158 | }) 159 | } 160 | 161 | private fun getUrl(latitude: Double, longitude: Double, typePlace: String): String { 162 | val googlePlaceUrl = 163 | StringBuilder("https://maps.googleapis.com/maps/api/place/nearbysearch/json") 164 | googlePlaceUrl.append("?keyword=cruise&location=$latitude,$longitude") 165 | googlePlaceUrl.append("&radius=20000") // 20km 166 | googlePlaceUrl.append("&type=$typePlace") 167 | googlePlaceUrl.append(("&key=${this.getString(R.string.maps_api_key)}")) 168 | Log.d("url_debug", googlePlaceUrl.toString()) 169 | return googlePlaceUrl.toString() 170 | } 171 | 172 | private fun buildLocationCallBack() { 173 | locationCallback = object : LocationCallback() { 174 | override fun onLocationResult(p0: LocationResult) { 175 | mLastLocation = p0.locations[p0.locations.size - 1] // Get last location 176 | if (marker != null) { 177 | marker!!.remove() 178 | } 179 | latitude = mLastLocation.latitude 180 | longitude = mLastLocation.longitude 181 | 182 | val latlng = LatLng(latitude, longitude) 183 | val markerOptions = MarkerOptions() 184 | .position(latlng) 185 | .title("Your Location") 186 | .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)) 187 | marker = map?.addMarker(markerOptions) 188 | 189 | //Move Camera 190 | map?.moveCamera(CameraUpdateFactory.newLatLng(latlng)) 191 | map?.animateCamera(CameraUpdateFactory.zoomTo(11f)) 192 | } 193 | } 194 | } 195 | 196 | private fun buildLocationRequest() { 197 | locationRequest = LocationRequest() 198 | locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY 199 | locationRequest.interval = 5000 200 | locationRequest.fastestInterval = 3000 201 | locationRequest.smallestDisplacement = 10f 202 | } 203 | 204 | private fun checkLocationPermission(): Boolean { 205 | return if (ContextCompat.checkSelfPermission( 206 | this, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 207 | if (ActivityCompat.shouldShowRequestPermissionRationale( 208 | this, ACCESS_FINE_LOCATION)) 209 | ActivityCompat.requestPermissions( 210 | this, arrayOf(ACCESS_FINE_LOCATION), MY_PERMISSION_CODE) 211 | else 212 | ActivityCompat.requestPermissions( 213 | this, arrayOf(ACCESS_FINE_LOCATION), MY_PERMISSION_CODE) 214 | false 215 | } else 216 | true 217 | } 218 | 219 | @SuppressLint("MissingPermission") 220 | override fun onRequestPermissionsResult( 221 | requestCode: Int, 222 | permissions: Array, 223 | grantResults: IntArray 224 | ) { 225 | super.onRequestPermissionsResult(requestCode, permissions, grantResults) 226 | when (requestCode) { 227 | MY_PERMISSION_CODE -> { 228 | if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 229 | if (ContextCompat.checkSelfPermission( 230 | this, 231 | ACCESS_FINE_LOCATION 232 | ) == PackageManager.PERMISSION_GRANTED 233 | ) 234 | if (checkLocationPermission()) { 235 | buildLocationRequest() 236 | buildLocationCallBack() 237 | fusedLocationProviderClient = 238 | LocationServices.getFusedLocationProviderClient(this) 239 | fusedLocationProviderClient.requestLocationUpdates( 240 | locationRequest, 241 | locationCallback, 242 | Looper.myLooper() 243 | ) 244 | map?.isMyLocationEnabled 245 | } 246 | } else 247 | Toast.makeText(this, "location Service Not Enabled", Toast.LENGTH_SHORT).show() 248 | } 249 | } 250 | } 251 | 252 | override fun onStop() { 253 | // fusedLocationProviderClient.removeLocationUpdates(locationCallback) 254 | super.onStop() 255 | } 256 | 257 | /** 258 | * Manipulates the map once available. 259 | * This callback is triggered when the map is ready to be used. 260 | * This is where we can add markers or lines, add listeners or move the camera. In this case, 261 | * we just add a marker near Sydney, Australia. 262 | * If Google Play services is not installed on the device, the user will be prompted to install 263 | * it inside the SupportMapFragment. This method will only be triggered once the user has 264 | * installed Google Play services and returned to the app. 265 | */ 266 | override fun onMapReady(map: GoogleMap) { 267 | this.map = map 268 | 269 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 270 | if (ContextCompat.checkSelfPermission( 271 | this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { map.isMyLocationEnabled } 272 | } else 273 | map.isMyLocationEnabled 274 | 275 | map.animateCamera(CameraUpdateFactory.newLatLng(india)) 276 | map.animateCamera(CameraUpdateFactory.newLatLngZoom(india, 7.4F)) 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/adapter/GroceryAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.adapter 2 | 3 | import android.content.Context 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.ImageView 8 | import android.widget.TextView 9 | import androidx.recyclerview.widget.RecyclerView 10 | import com.noobshubham.gostore.R 11 | import com.noobshubham.gostore.database.entity.GroceryEntities 12 | 13 | class GroceryAdapter(val context: Context, 14 | var list: List, 15 | val groceryItemClickInterface: GroceryItemClickInterface 16 | ) : RecyclerView.Adapter() { 17 | 18 | inner class GroceryViewHolder(view: View) : RecyclerView.ViewHolder(view) { 19 | val name: TextView = view.findViewById(R.id.name) 20 | val quantity: TextView = view.findViewById(R.id.quantity) 21 | val rate: TextView = view.findViewById(R.id.rate) 22 | val totalAmount: TextView = view.findViewById(R.id.total_amouont) 23 | val delete: ImageView = view.findViewById(R.id.delete) 24 | } 25 | 26 | interface GroceryItemClickInterface { 27 | fun onItemClick(groceryItems: GroceryEntities) 28 | } 29 | 30 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GroceryViewHolder { 31 | val view = 32 | LayoutInflater.from(parent.context).inflate(R.layout.single_item_view, parent, false) 33 | return GroceryViewHolder(view) 34 | } 35 | 36 | override fun onBindViewHolder(holder: GroceryViewHolder, position: Int) { 37 | holder.name.text = list[position].itemName 38 | holder.quantity.text = context.getString(R.string.quantity, list[position].itemQuantity) 39 | holder.rate.text = context.getString(R.string.rate, list[position].itemPrice) 40 | val itemTotal: Int = list[position].itemPrice * list[position].itemQuantity 41 | holder.totalAmount.text = context.getString(R.string.total_amount, itemTotal) 42 | holder.delete.setOnClickListener { 43 | groceryItemClickInterface.onItemClick(list[position]) 44 | } 45 | } 46 | 47 | override fun getItemCount() = list.size 48 | } 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/database/GroceryDao.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.database 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.* 5 | import com.noobshubham.gostore.database.entity.GroceryEntities 6 | 7 | @Dao 8 | interface GroceryDao { 9 | @Insert(onConflict = OnConflictStrategy.REPLACE) 10 | suspend fun insert(item: GroceryEntities) 11 | 12 | @Delete 13 | suspend fun delete(item: GroceryEntities) 14 | 15 | @Query("SELECT * FROM grocery_data") 16 | fun getAllGroceryItems(): LiveData> 17 | } 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/database/GroceryDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.database 2 | 3 | import android.content.Context 4 | import androidx.room.Database 5 | import androidx.room.Room 6 | import androidx.room.RoomDatabase 7 | import com.noobshubham.gostore.database.entity.GroceryEntities 8 | 9 | @Database(entities = [GroceryEntities::class], version = 1) 10 | abstract class GroceryDatabase : RoomDatabase() { 11 | abstract fun getGroceryDao(): GroceryDao 12 | 13 | companion object { 14 | @Volatile 15 | private var instance: GroceryDatabase? = null 16 | private val LOCK = Any() 17 | 18 | operator fun invoke(context: Context) = instance ?: synchronized(LOCK) { 19 | instance ?: createDatabase(context).also { 20 | instance = it 21 | } 22 | } 23 | 24 | private fun createDatabase(context: Context) = 25 | Room.databaseBuilder( 26 | context.applicationContext, 27 | GroceryDatabase::class.java, 28 | "Grocery.db" 29 | ).build() 30 | } 31 | } 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/database/GroceryRepository.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.database 2 | 3 | import com.noobshubham.gostore.database.entity.GroceryEntities 4 | 5 | class GroceryRepository(private val db: GroceryDatabase) { 6 | suspend fun insert(items: GroceryEntities) = db.getGroceryDao().insert(items) 7 | suspend fun delete(items: GroceryEntities) = db.getGroceryDao().delete(items) 8 | 9 | fun getAllItems() = db.getGroceryDao().getAllGroceryItems() 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/database/entity/GroceryEntities.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.database.entity 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.PrimaryKey 6 | 7 | @Entity(tableName = "grocery_data") 8 | data class GroceryEntities( 9 | @ColumnInfo(name = "Name") 10 | var itemName: String, 11 | 12 | @ColumnInfo(name = "Quantity") 13 | var itemQuantity: Int, 14 | 15 | @ColumnInfo(name = "Price") 16 | var itemPrice: Int, 17 | ) { 18 | @PrimaryKey(autoGenerate = true) 19 | var id: Int? = null 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/grocery/GroceryActivity.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.grocery 2 | 3 | import android.annotation.SuppressLint 4 | import android.app.Dialog 5 | import androidx.appcompat.app.AppCompatActivity 6 | import android.os.Bundle 7 | import android.view.View 8 | import android.widget.Button 9 | import android.widget.EditText 10 | import android.widget.TextView 11 | import android.widget.Toast 12 | import androidx.lifecycle.Observer 13 | import androidx.lifecycle.ViewModelProvider 14 | import androidx.recyclerview.widget.LinearLayoutManager 15 | import com.noobshubham.gostore.R 16 | import com.noobshubham.gostore.adapter.GroceryAdapter 17 | import com.noobshubham.gostore.database.GroceryDatabase 18 | import com.noobshubham.gostore.database.GroceryRepository 19 | import com.noobshubham.gostore.database.entity.GroceryEntities 20 | import com.noobshubham.gostore.databinding.ActivityGroceryBinding 21 | 22 | class GroceryActivity : AppCompatActivity(), GroceryAdapter.GroceryItemClickInterface { 23 | 24 | private lateinit var binding: ActivityGroceryBinding 25 | private lateinit var list: List 26 | private lateinit var groceryAdapter: GroceryAdapter 27 | private lateinit var groceryViewModal: GroceryViewModal 28 | 29 | @SuppressLint("NotifyDataSetChanged") 30 | override fun onCreate(savedInstanceState: Bundle?) { 31 | super.onCreate(savedInstanceState) 32 | binding = ActivityGroceryBinding.inflate(layoutInflater) 33 | setContentView(binding.root) 34 | 35 | list = listOf() 36 | groceryAdapter = GroceryAdapter(this, list, this) 37 | binding.recyclerview.apply { 38 | layoutManager = LinearLayoutManager(context) 39 | adapter = groceryAdapter 40 | } 41 | val groceryRepository = GroceryRepository(GroceryDatabase(this)) 42 | val factory = GroceryViewModalFactory(groceryRepository) 43 | groceryViewModal = ViewModelProvider(this, factory)[GroceryViewModal::class.java] 44 | groceryViewModal.getAllGroceryItems().observe(this, Observer { 45 | groceryAdapter.list = it 46 | groceryAdapter.notifyDataSetChanged() 47 | if (it.isNotEmpty()) { 48 | binding.tempImageView.visibility = View.GONE 49 | binding.tempTextView.visibility = View.GONE 50 | } else { 51 | binding.tempImageView.visibility = View.VISIBLE 52 | binding.tempTextView.visibility = View.VISIBLE 53 | } 54 | }) 55 | binding.fab.setOnClickListener { openDialog() } 56 | } 57 | 58 | private fun openDialog() { 59 | val dialog = Dialog(this, R.style.NewDialog) 60 | dialog.setContentView(R.layout.grocery_add_dialog) 61 | 62 | val cancel: Button = dialog.findViewById(R.id.idBtnCancel) 63 | val add: Button = dialog.findViewById(R.id.idBtnAdd) 64 | val item: EditText = dialog.findViewById(R.id.idEdtItemName) 65 | val price: EditText = dialog.findViewById(R.id.idEdtItemPrice) 66 | val quantity: EditText = dialog.findViewById(R.id.idEdtItemQuantity) 67 | 68 | cancel.setOnClickListener { dialog.dismiss() } 69 | 70 | add.setOnClickListener { 71 | if (validateInput(item, quantity, price)) { 72 | addItemToDB(item.text.toString(), quantity.text.toString(), price.text.toString()) 73 | dialog.dismiss() 74 | } 75 | } 76 | dialog.show() 77 | } 78 | 79 | @SuppressLint("NotifyDataSetChanged") 80 | private fun addItemToDB(itemName: String, quantity: String, price: String) { 81 | val items = GroceryEntities(itemName, quantity.toInt(), price.toInt()) 82 | groceryViewModal.insert(items) 83 | Toast.makeText(this, "Item Added!", Toast.LENGTH_SHORT).show() 84 | groceryAdapter.notifyDataSetChanged() 85 | } 86 | 87 | private fun validateInput(item: TextView, quantity: TextView, price: TextView): Boolean { 88 | if (item.text.isEmpty()) { 89 | item.error = "Name is empty." 90 | return false 91 | } 92 | if (quantity.text.isEmpty()) { 93 | quantity.error = "Quantity is empty." 94 | return false 95 | } 96 | if (price.text.isEmpty()) { 97 | price.error = "Price is empty." 98 | return false 99 | } 100 | return true 101 | } 102 | 103 | @SuppressLint("NotifyDataSetChanged") 104 | override fun onItemClick(groceryItems: GroceryEntities) { 105 | groceryViewModal.delete(groceryItems) 106 | groceryAdapter.notifyDataSetChanged() 107 | Toast.makeText(this, "Deleted!", Toast.LENGTH_SHORT).show() 108 | } 109 | } -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/grocery/GroceryViewModal.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.grocery 2 | 3 | import androidx.lifecycle.ViewModel 4 | import com.noobshubham.gostore.database.GroceryRepository 5 | import com.noobshubham.gostore.database.entity.GroceryEntities 6 | import kotlinx.coroutines.GlobalScope 7 | import kotlinx.coroutines.launch 8 | 9 | class GroceryViewModal(private val repository: GroceryRepository) : ViewModel() { 10 | fun insert(items: GroceryEntities) = GlobalScope.launch { 11 | repository.insert(items) 12 | } 13 | 14 | fun delete(items: GroceryEntities) = GlobalScope.launch { 15 | repository.delete(items) 16 | } 17 | 18 | fun getAllGroceryItems() = repository.getAllItems() 19 | } 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/grocery/GroceryViewModalFactory.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.grocery 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.noobshubham.gostore.database.GroceryRepository 6 | 7 | class GroceryViewModalFactory(private val repository: GroceryRepository) : 8 | ViewModelProvider.NewInstanceFactory() { 9 | 10 | override fun create(modelClass: Class): T { 11 | return GroceryViewModal(repository) as T 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/model/Geometry.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.model 2 | 3 | data class Geometry( 4 | var viewport: Viewport? = null, 5 | var location: Location? = null 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/model/Location.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.model 2 | 3 | data class Location( 4 | var lat: Double = 0.0, 5 | var lng: Double = 0.0 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/model/MyPlaces.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.model 2 | 3 | data class MyPlaces( 4 | var html_attributions: Array? = null, 5 | var status: String? = null, 6 | var results: Array? = null 7 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/model/Northeast.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.model 2 | 3 | data class Northeast( 4 | var lat: Double = 0.0, 5 | var lng: Double = 0.0 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/model/OpeningHours.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.model 2 | 3 | data class OpeningHours( 4 | var open_now: Boolean = false 5 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/model/Photos.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.model 2 | 3 | data class Photos( 4 | var height: Int = 0, 5 | var width: Int = 0, 6 | var photo_reference: String? = null, 7 | var html_attributions: Array? = null, 8 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/model/Results.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.model 2 | 3 | data class Results( 4 | var photos: Array? = null, 5 | var id: String? = null, 6 | var place_id: String? = null, 7 | var price_level: Int = 0, 8 | var rating: Double = 0.0, 9 | var user_ratings_total: Int = 0, 10 | var reference: String? = null, 11 | var scope: String? = null, 12 | var types: Array? = null, 13 | var vicinity: String? = null, 14 | var opening_hours: OpeningHours? = null, 15 | var name: String? = null, 16 | var icon: String? = null, 17 | var geometry: Geometry? = null, 18 | var business_status: String? = null 19 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/model/Southwest.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.model 2 | 3 | data class Southwest( 4 | var lat: Double = 0.0, 5 | var lng: Double = 0.0 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/model/UserData.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.model 2 | 3 | data class UserData( 4 | val username: String, 5 | val email: String, 6 | val password: String 7 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/model/Viewport.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.model 2 | 3 | data class Viewport( 4 | var northeast: Northeast? = null, 5 | var southwest: Southwest? = null 6 | ) 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/registration/LoginFragment.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.registration 2 | 3 | import android.content.Intent 4 | import android.content.IntentSender 5 | import android.os.Bundle 6 | import android.util.Log 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import android.widget.ProgressBar 11 | import android.widget.Toast 12 | import androidx.fragment.app.Fragment 13 | import androidx.navigation.fragment.findNavController 14 | import com.google.android.gms.auth.api.identity.BeginSignInRequest 15 | import com.google.android.gms.auth.api.identity.Identity 16 | import com.google.android.gms.auth.api.identity.SignInClient 17 | import com.google.android.gms.common.api.ApiException 18 | import com.google.android.gms.common.api.CommonStatusCodes 19 | import com.google.android.material.snackbar.Snackbar 20 | import com.google.firebase.auth.FirebaseAuth 21 | import com.google.firebase.auth.FirebaseUser 22 | import com.google.firebase.auth.GoogleAuthProvider 23 | import com.noobshubham.gostore.MapsActivity 24 | import com.noobshubham.gostore.R 25 | import com.noobshubham.gostore.databinding.FragmentLoginBinding 26 | import com.noobshubham.gostore.model.UserData 27 | 28 | const val TAG = "LoginFragment" 29 | const val RC_ONE_TAP = 123 30 | 31 | class LoginFragment : Fragment() { 32 | 33 | private var _binding: FragmentLoginBinding? = null 34 | private val binding get() = _binding!! 35 | 36 | // progressBar 37 | private lateinit var progressBar: ProgressBar 38 | 39 | // Firebase Auth 40 | private lateinit var auth: FirebaseAuth 41 | private lateinit var oneTapClient: SignInClient 42 | private lateinit var signInRequest: BeginSignInRequest 43 | 44 | // Control whether user declined One Tap UI 45 | private var userDeclinedOneTap = false 46 | 47 | override fun onStart() { 48 | super.onStart() 49 | // Check if user is signed in (non-null) and update UI accordingly. 50 | val currentUser = auth.currentUser 51 | updateUI(currentUser) 52 | } 53 | 54 | override fun onCreateView( 55 | inflater: LayoutInflater, container: ViewGroup?, 56 | savedInstanceState: Bundle? 57 | ): View { 58 | // Inflate the layout for this fragment 59 | _binding = FragmentLoginBinding.inflate(inflater, container, false) 60 | auth = FirebaseAuth.getInstance() 61 | progressBar = binding.progressBar 62 | return binding.root 63 | } 64 | 65 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 66 | super.onViewCreated(view, savedInstanceState) 67 | 68 | binding.tvSignUp.setOnClickListener { findNavController().navigate(R.id.action_loginFragment_to_signupFragment) } 69 | 70 | binding.btnLogin.setOnClickListener { 71 | val inputEmail = binding.tietEmail.text.toString().trim() 72 | val inputPassword = binding.tiePassword.text.toString().trim() 73 | 74 | val userData = UserData("${auth.currentUser}", inputEmail, inputPassword) 75 | 76 | if (validateInput(userData)) signIn(userData) 77 | } 78 | 79 | oneTapClient = Identity.getSignInClient(requireActivity()) 80 | signInRequest = BeginSignInRequest.builder() 81 | .setGoogleIdTokenRequestOptions( 82 | BeginSignInRequest.GoogleIdTokenRequestOptions.builder() 83 | .setSupported(true) 84 | // Your server's client ID, not your Android client ID. 85 | .setServerClientId(getString(R.string.default_web_client_id)) 86 | // Only show accounts previously used to sign in. 87 | .setFilterByAuthorizedAccounts(false) 88 | .build() 89 | ) 90 | .setAutoSelectEnabled(true) 91 | .build() 92 | 93 | // auth button click listener 94 | binding.googleButton.setOnClickListener { signInWithGoogle() } 95 | } 96 | 97 | private fun signIn(userData: UserData) { 98 | progressBar.visibility = View.VISIBLE 99 | 100 | auth.signInWithEmailAndPassword(userData.email, userData.password) 101 | .addOnCompleteListener(requireActivity()) { task -> 102 | if (task.isSuccessful) { 103 | Toast.makeText(context, "Login Successful", Toast.LENGTH_SHORT).show() 104 | val user = auth.currentUser 105 | updateUI(user) 106 | } else { 107 | Toast.makeText( 108 | context, "Authentication failed.", 109 | Toast.LENGTH_SHORT 110 | ).show() 111 | updateUI(null) 112 | } 113 | progressBar.visibility = View.GONE 114 | } 115 | } 116 | 117 | private fun validateInput(userData: UserData): Boolean { 118 | if (userData.email.isEmpty()) { 119 | binding.tietEmail.error = "Email is empty." 120 | return false 121 | } 122 | if (userData.password.isEmpty()) { 123 | binding.tiePassword.error = "Password is empty." 124 | return false 125 | } 126 | return true 127 | } 128 | 129 | private fun updateUI(user: FirebaseUser?) { 130 | progressBar.visibility = View.GONE 131 | if (user != null) { 132 | requireActivity().startActivity(Intent(context, MapsActivity::class.java)) 133 | requireActivity().finish() 134 | } 135 | } 136 | 137 | private fun signInWithGoogle() { 138 | oneTapClient.beginSignIn(signInRequest) 139 | .addOnSuccessListener(requireActivity()) { result -> 140 | try { 141 | startIntentSenderForResult( 142 | result.pendingIntent.intentSender, RC_ONE_TAP, 143 | null, 0, 0, 0, null 144 | ) 145 | } catch (e: IntentSender.SendIntentException) { 146 | Snackbar.make(binding.root, e.message.toString(), Snackbar.LENGTH_SHORT) 147 | .show() 148 | } 149 | } 150 | .addOnFailureListener(requireActivity()) { e -> 151 | Snackbar.make(binding.root, e.message.toString(), Snackbar.LENGTH_SHORT).show() 152 | } 153 | } 154 | 155 | private fun firebaseAuthWithGoogle(googleIdToken: String) { 156 | val firebaseCredential = GoogleAuthProvider.getCredential(googleIdToken, null) 157 | auth.signInWithCredential(firebaseCredential) 158 | .addOnCompleteListener(requireActivity()) { task -> 159 | if (task.isSuccessful) { 160 | // Sign in success, update UI with the signed-in user's information 161 | Log.d(TAG, "signInWithCredential:success") 162 | val user = auth.currentUser 163 | updateUI(user) 164 | } else { 165 | // If sign in fails, display a message to the user. 166 | Log.w(TAG, "signInWithCredential:failure", task.exception) 167 | Snackbar.make( 168 | requireView(), 169 | "Authentication Failed.", 170 | Snackbar.LENGTH_SHORT 171 | ).show() 172 | updateUI(null) 173 | } 174 | } 175 | } 176 | 177 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 178 | super.onActivityResult(requestCode, resultCode, data) 179 | 180 | try { 181 | val credential = oneTapClient.getSignInCredentialFromIntent(data) 182 | // This credential contains a googleIdToken which 183 | // we can use to authenticate with FirebaseAuth 184 | credential.googleIdToken?.let { 185 | firebaseAuthWithGoogle(it) 186 | } 187 | } catch (e: ApiException) { 188 | when (e.statusCode) { 189 | CommonStatusCodes.CANCELED -> { 190 | // The user closed the dialog 191 | // userDeclinedOneTap = true 192 | } 193 | CommonStatusCodes.NETWORK_ERROR -> { 194 | // No Internet connection ? 195 | Toast.makeText(context, "Internet Disconnected!", Toast.LENGTH_SHORT).show() 196 | } 197 | else -> { 198 | // Some other error 199 | } 200 | } 201 | } 202 | } 203 | 204 | override fun onDestroyView() { 205 | super.onDestroyView() 206 | _binding = null 207 | } 208 | } -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/registration/RegistrationActivity.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.registration 2 | 3 | import android.content.res.Resources 4 | import androidx.appcompat.app.AppCompatActivity 5 | import android.os.Bundle 6 | import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen 7 | import com.noobshubham.gostore.R 8 | 9 | class RegistrationActivity : AppCompatActivity() { 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | this.installSplashScreen() 13 | setContentView(R.layout.activity_registration) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/registration/SignupFragment.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.registration 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.ProgressBar 9 | import android.widget.Toast 10 | import androidx.fragment.app.Fragment 11 | import androidx.navigation.fragment.findNavController 12 | import com.google.firebase.auth.FirebaseAuth 13 | import com.noobshubham.gostore.MapsActivity 14 | import com.noobshubham.gostore.R 15 | import com.noobshubham.gostore.databinding.FragmentSignupBinding 16 | import com.noobshubham.gostore.model.UserData 17 | 18 | class SignupFragment : Fragment() { 19 | 20 | // binding variables 21 | private var _binding: FragmentSignupBinding? = null 22 | private val binding get() = _binding!! 23 | 24 | // Firebase Auth Variables 25 | private lateinit var auth: FirebaseAuth 26 | 27 | // progressBar 28 | private lateinit var progressBar: ProgressBar 29 | 30 | override fun onCreateView( 31 | inflater: LayoutInflater, container: ViewGroup?, 32 | savedInstanceState: Bundle? 33 | ): View { 34 | _binding = FragmentSignupBinding.inflate(inflater, container, false) 35 | auth = FirebaseAuth.getInstance() 36 | progressBar = binding.progressBar 37 | return binding.root 38 | } 39 | 40 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 41 | super.onViewCreated(view, savedInstanceState) 42 | 43 | // Create Button 44 | binding.btnRegister.setOnClickListener { 45 | val userName = binding.tietUsername.text.toString().trim() 46 | val inputEmail = binding.tietEmail.text.toString().trim() 47 | val passWord = binding.tietPassword.text.toString().trim() 48 | 49 | val userData = UserData(userName, inputEmail, passWord) 50 | 51 | if (validateInput(userData)) createUser(userData) 52 | } 53 | 54 | // SignIn Button 55 | binding.imageView.setOnClickListener { findNavController().navigate(R.id.action_signupFragment_to_loginFragment) } 56 | } 57 | 58 | private fun createUser(userData: UserData) { 59 | progressBar.visibility = View.VISIBLE 60 | auth.createUserWithEmailAndPassword(userData.email, userData.password) 61 | .addOnCompleteListener(requireActivity()) { task -> 62 | if (task.isSuccessful) { 63 | // Sign in success, update UI with the signed-in user's information 64 | Toast.makeText( 65 | context, 66 | "You've been registered successfully.", 67 | Toast.LENGTH_SHORT 68 | ).show() 69 | requireActivity().startActivity(Intent(context, MapsActivity::class.java)) 70 | requireActivity().finish() 71 | } else { 72 | // If sign in fails, display a message to the user. 73 | Toast.makeText( 74 | context, 75 | "Account Creation Failed, Try Again!", 76 | Toast.LENGTH_SHORT 77 | ).show() 78 | } 79 | progressBar.visibility = View.GONE 80 | } 81 | } 82 | 83 | private fun validateInput(userData: UserData): Boolean { 84 | if (userData.username.isEmpty()) { 85 | binding.tietUsername.error = "Username is empty." 86 | return false 87 | } 88 | if (userData.email.isEmpty()) { 89 | binding.tietEmail.error = "Email is empty." 90 | return false 91 | } 92 | if (userData.password.isEmpty()) { 93 | binding.tietPassword.error = "Password is empty." 94 | return false 95 | } 96 | return true 97 | } 98 | 99 | override fun onDestroy() { 100 | super.onDestroy() 101 | _binding = null 102 | } 103 | 104 | } -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/remote/IGoogleAPIService.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.remote 2 | 3 | import com.noobshubham.gostore.model.MyPlaces 4 | import retrofit2.Call 5 | import retrofit2.http.GET 6 | import retrofit2.http.Url 7 | 8 | interface IGoogleAPIService { 9 | @GET 10 | fun getNearbyPlaces(@Url url: String): Call 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/noobshubham/gostore/remote/RetrofitClient.kt: -------------------------------------------------------------------------------- 1 | package com.noobshubham.gostore.remote 2 | 3 | import retrofit2.Retrofit 4 | import retrofit2.converter.gson.GsonConverterFactory 5 | 6 | object RetrofitClient { 7 | private var retrofit: Retrofit? = null 8 | fun getClient(base_url: String): Retrofit { 9 | if (retrofit == null) { 10 | retrofit = Retrofit.Builder() 11 | .baseUrl(base_url) 12 | .addConverterFactory(GsonConverterFactory.create()) 13 | .build() 14 | } 15 | return retrofit!! 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 31 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/arrow.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/buttonshapewhitebg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bank.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_add_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_delete_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bed.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_credit_card.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_doctor.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_google.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_notes.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_playlist.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_restaurants.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_school.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/splash_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/font/calibri.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noobshubham/GoStore/8a16030c641d9a6ce7e3738d02b6cb6855329bb8/app/src/main/res/font/calibri.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/gotham.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noobshubham/GoStore/8a16030c641d9a6ce7e3738d02b6cb6855329bb8/app/src/main/res/font/gotham.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noobshubham/GoStore/8a16030c641d9a6ce7e3738d02b6cb6855329bb8/app/src/main/res/font/roboto_medium.ttf -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_grocery.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 20 | 21 | 32 | 33 | 46 | 47 | 58 | 59 | 69 | 70 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_maps.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 26 | 27 | 36 | 37 | 41 | 42 |