├── .gitignore
├── .idea
├── .gitignore
├── .name
├── compiler.xml
├── deploymentTargetDropDown.xml
├── gradle.xml
├── misc.xml
├── render.experimental.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── google-services.json
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── rishav
│ │ └── buckoid
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-playstore.png
│ ├── java
│ │ └── com
│ │ │ └── rishav
│ │ │ └── buckoid
│ │ │ ├── Adapter
│ │ │ └── TransactionAdapter.kt
│ │ │ ├── Dao
│ │ │ └── TransactionDao.kt
│ │ │ ├── Database
│ │ │ └── TransactionDatabase.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── Model
│ │ │ ├── Profile.kt
│ │ │ └── Transaction.kt
│ │ │ ├── Repository
│ │ │ └── TransactionRepository.kt
│ │ │ ├── UserDetails.kt
│ │ │ ├── ViewModel
│ │ │ └── TransactionViewModel.kt
│ │ │ └── fragments
│ │ │ ├── AddTransaction.kt
│ │ │ ├── AllTransactions.kt
│ │ │ ├── Authentication
│ │ │ ├── UserDetails.kt
│ │ │ └── UserSignUp.kt
│ │ │ ├── BackupDrive.kt
│ │ │ ├── Dashboard.kt
│ │ │ ├── Profile.kt
│ │ │ └── TransactionDetails.kt
│ └── res
│ │ ├── drawable-v24
│ │ ├── ic_launcher_background.xml
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── bottom_dialog.xml
│ │ ├── button_selector_background.xml
│ │ ├── ic_baseline_add_24.xml
│ │ ├── ic_baseline_arrow_back_ios_24.xml
│ │ ├── ic_baseline_assessment_24.xml
│ │ ├── ic_baseline_auto_stories_24.xml
│ │ ├── ic_baseline_backup_24.xml
│ │ ├── ic_baseline_calendar_month_24.xml
│ │ ├── ic_baseline_category_24.xml
│ │ ├── ic_baseline_currency_rupee_24.xml
│ │ ├── ic_baseline_dashboard_24.xml
│ │ ├── ic_baseline_delete_outline_24.xml
│ │ ├── ic_baseline_directions_transit_24.xml
│ │ ├── ic_baseline_edit_24.xml
│ │ ├── ic_baseline_fastfood_24.xml
│ │ ├── ic_baseline_favorite_24.xml
│ │ ├── ic_baseline_fingerprint_24.xml
│ │ ├── ic_baseline_info_24.xml
│ │ ├── ic_baseline_menu_24.xml
│ │ ├── ic_baseline_mode_night_24.xml
│ │ ├── ic_baseline_person_24.xml
│ │ ├── ic_baseline_share_24.xml
│ │ ├── ic_baseline_shopping_cart_24.xml
│ │ ├── ic_baseline_star_rate_24.xml
│ │ ├── ic_google_icon.xml
│ │ ├── ic_negative_transaction.xml
│ │ ├── ic_positive_amount.xml
│ │ ├── ic_round_add_to_drive_24.xml
│ │ ├── logo.xml
│ │ ├── logo_round.xml
│ │ ├── round.xml
│ │ └── splash_screen.xml
│ │ ├── font
│ │ ├── baloo.xml
│ │ ├── baloo_bhaina.xml
│ │ ├── poppins.xml
│ │ ├── poppins_medium.xml
│ │ └── poppins_semibold.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── activity_user_details.xml
│ │ ├── dialog_delete.xml
│ │ ├── drawer_nav_header.xml
│ │ ├── dropdown_item.xml
│ │ ├── fragment_add_transaction.xml
│ │ ├── fragment_all_transactions.xml
│ │ ├── fragment_backup_drive.xml
│ │ ├── fragment_dashboard.xml
│ │ ├── fragment_profile.xml
│ │ ├── fragment_transaction_details.xml
│ │ ├── fragment_user_details.xml
│ │ ├── fragment_user_sign_up.xml
│ │ ├── night_mode_action_layout_switch.xml
│ │ ├── transaction_item.xml
│ │ └── update_user_details_dialog.xml
│ │ ├── menu
│ │ ├── bottom_nav.xml
│ │ └── menu_drawer.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── navigation
│ │ ├── app_navigation.xml
│ │ └── signup_user_navigation.xml
│ │ ├── values-night
│ │ └── colors.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── font_certs.xml
│ │ ├── preloaded_fonts.xml
│ │ ├── strings.xml
│ │ └── themes.xml
│ └── test
│ └── java
│ └── com
│ └── rishav
│ └── buckoid
│ └── ExampleUnitTest.kt
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── 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 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | Track Back
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/deploymentTargetDropDown.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/.idea/render.experimental.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Android-Study-Jams
2 | Buckoid-Android-App
3 |
4 | Problem Statement:
5 |
6 | How do we track our expenses successfully? What about our personal capital? How much we spend we don't keep track and we spend a lot more than our budget. Let's face it — saving money in today's world is not easy. We need a budget manager and expense tracking App which will keep a track record of all our expenditure.
7 |
8 | Proposed Solution :
9 |
10 | This Project proposes an “Expense Tracking App”. Luckily, Buckoid is more than a money tracker, it's also one of the best savings apps to help you with money management. Keep track of your personal expenses and compare them to your monthly income with the budget planner. Keep track of train, cab, movie, event bookings, and more. Keep your monthly budget in mint condition. This app will helpus to become a budgeting masters and we can start saving money with Buckoid.
11 |
12 |
13 |
14 |
15 |
16 |
17 | Functionality & Concepts used :
18 |
19 | The App has a very simple and interactive interface which helps the user to track his Expenses. Following are a few android concepts used to achieve the functionalities in the app :
20 | - Constraint Layout : Most of the activities in the app uses a flexible constraint layout, which is easy to handle for different screen sizes.
21 | - Simple & Easy Views Design : Use of familiar audience EditText with hints and interactive buttons made it easier for users to add or update transactions. It consists of Material Widgits and Components like Card Views, Toggle Component, etc. Apps also uses App Navigation(Jetpack Library Component) to switch between different screens. It has a graphical representation of data.
22 | - Dark Mode/Light Mode: User can change App Theme easily at any time according to their convenience.
23 | - Bottom Navigation: It has bottom navigation to navigate between top screens and gives user a more enhanced UI/Ux interface.
24 | - RecyclerView : To present the list of different transactions done we used the efficient recyclerview.
25 | - LiveData & Room Database : We are using LiveData to store & Update new transactions.
26 |
27 | Application Link & Future Scope :
28 |
29 | The app is currently in the Playstore in production mode (Under Review).
30 | You can access the app: View On Google Play.
31 | Check our Codebase on Github: Code Link.
32 |
33 | Once the app is fully launched and functional we plan to add more features like Backup in Google Drive using Google Drive API so that all the user data remains saved. Then we are planning to add Collect Coins & Badges on certain no of transactions and unlock more features so that the user comes to the app daily and stores his transactions each time. Then we are planning to include Goal saving features so that users can plan for certain goals and achieve them like Vacation trips, Buying a mobile, etc. Also, we are planning to include more visual data representation so that users can have a very clear look and compare and stay within their Budget.
34 |
35 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'kotlin-android'
4 | id 'kotlin-kapt'
5 | id 'kotlin-parcelize'
6 | }
7 | apply plugin: "androidx.navigation.safeargs.kotlin"
8 |
9 | android {
10 | compileSdk 31
11 |
12 | defaultConfig {
13 | applicationId "com.rishav.buckoid"
14 | minSdk 21
15 | targetSdk 31
16 | versionCode 4
17 | versionName "1.4"
18 |
19 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
20 | }
21 |
22 | buildTypes {
23 | release {
24 | minifyEnabled true
25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
26 | }
27 | }
28 | compileOptions {
29 | sourceCompatibility JavaVersion.VERSION_1_8
30 | targetCompatibility JavaVersion.VERSION_1_8
31 | }
32 | kotlinOptions {
33 | jvmTarget = '1.8'
34 | }
35 | buildFeatures {
36 | viewBinding = true
37 | }
38 | packagingOptions {
39 | exclude 'META-INF/DEPENDENCIES'
40 | }
41 | lintOptions {
42 | checkReleaseBuilds false
43 | }
44 | }
45 |
46 | dependencies {
47 |
48 | implementation 'androidx.core:core-ktx:1.7.0'
49 | implementation 'androidx.appcompat:appcompat:1.4.0'
50 | implementation 'com.google.android.material:material:1.4.0'
51 | implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
52 | implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
53 | implementation "androidx.fragment:fragment-ktx:1.4.0"
54 | implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
55 | implementation 'androidx.legacy:legacy-support-v4:1.0.0'
56 | testImplementation 'junit:junit:4.+'
57 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
58 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
59 | implementation 'com.github.blackfizz:eazegraph:1.2.5l@aar'
60 | implementation 'com.nineoldandroids:library:2.4.0'
61 |
62 | //Room Database
63 | implementation "androidx.room:room-runtime:2.4.0"
64 | kapt "androidx.room:room-compiler:2.4.0"
65 | implementation "androidx.room:room-ktx:2.4.0"
66 | androidTestImplementation "androidx.room:room-testing:2.4.0"
67 |
68 |
69 | // Lifecycle components
70 | implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
71 | implementation "androidx.lifecycle:lifecycle-common-java8:2.4.0"
72 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0"
73 | implementation 'androidx.activity:activity-ktx:1.4.0'
74 |
75 | // Kotlin components
76 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10"
77 |
78 | //coroutines
79 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
80 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
81 |
82 | //play
83 | implementation("com.google.android.play:core-ktx:1.8.1")
84 |
85 | implementation 'uk.co.samuelwall:material-tap-target-prompt:3.3.2'
86 |
87 | //google driver api
88 | implementation 'com.google.android.gms:play-services-auth:20.0.1'
89 | implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
90 | implementation ('com.google.api-client:google-api-client-android:1.26.0')
91 | implementation ('com.google.apis:google-api-services-drive:v3-rev136-1.25.0')
92 | implementation 'com.google.http-client:google-http-client-gson:1.39.2'
93 |
94 | //image uri
95 | implementation 'com.github.bumptech.glide:glide:3.7.0'
96 | }
--------------------------------------------------------------------------------
/app/google-services.json:
--------------------------------------------------------------------------------
1 | {"installed":{"client_id":"936900394467-e70ft0qbhq9v0ip8kdpqd2fps6ag8sme.apps.googleusercontent.com","project_id":"buckoid","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}
--------------------------------------------------------------------------------
/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
22 | -keep class com.rishav.buckoid.Model.Transaction
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/rishav/buckoid/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid
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.example.trackback", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
14 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
29 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rishavchanda/Buckoid-Android-App/c489816f21aeb1250f6751c30b9d6b340af2cdeb/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/Adapter/TransactionAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.Adapter
2 |
3 | import android.annotation.SuppressLint
4 | import android.app.Activity
5 | import android.content.Context
6 | import android.content.SharedPreferences
7 | import android.view.LayoutInflater
8 | import android.view.ViewGroup
9 | import androidx.appcompat.app.AppCompatActivity
10 | import androidx.core.content.ContextCompat
11 | import androidx.navigation.Navigation
12 | import androidx.recyclerview.widget.RecyclerView
13 | import com.rishav.buckoid.Model.Transaction
14 | import com.rishav.buckoid.R
15 | import com.rishav.buckoid.databinding.TransactionItemBinding
16 | import com.rishav.buckoid.fragments.*
17 | import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt
18 | import uk.co.samuelwall.materialtaptargetprompt.extras.backgrounds.RectanglePromptBackground
19 | import uk.co.samuelwall.materialtaptargetprompt.extras.focals.RectanglePromptFocal
20 |
21 | class TransactionAdapter(val context: Context, val activity:Activity,val fragment:String, private val transList: List) : RecyclerView.Adapter(){
22 |
23 | class transactionViewHolder(val binding:TransactionItemBinding) : RecyclerView.ViewHolder(binding.root)
24 |
25 | lateinit var userDetails: SharedPreferences
26 | override fun onCreateViewHolder(
27 | parent: ViewGroup,
28 | viewType: Int
29 | ): transactionViewHolder {
30 | return transactionViewHolder(TransactionItemBinding.inflate(LayoutInflater.from(parent.context),parent,false))
31 |
32 | }
33 |
34 | @SuppressLint("SetTextI18n")
35 | override fun onBindViewHolder(holder: transactionViewHolder, position: Int) {
36 | val data = transList[position]
37 | holder.binding.title.text = data.title
38 | holder.binding.money.text = "₹"+data.amount.toInt().toString()
39 | holder.binding.date.text = data.date
40 | holder.binding.category.text = data.category
41 |
42 | when(data.category){
43 | "Food" -> {
44 | holder.binding.cardIcon.setImageResource(R.drawable.ic_baseline_fastfood_24)
45 | holder.binding.cardIcon.setColorFilter(ContextCompat.getColor(context, R.color.yellow))
46 | holder.binding.category.setTextColor(ContextCompat.getColor(context, R.color.yellow))
47 | holder.binding.cardImage.setCardBackgroundColor(ContextCompat.getColor(context, R.color.yellow_light))
48 | }
49 | "Shopping" -> {
50 | holder.binding.cardIcon.setImageResource(R.drawable.ic_baseline_shopping_cart_24)
51 | holder.binding.cardIcon.setColorFilter(ContextCompat.getColor(context, R.color.lightBlue))
52 | holder.binding.category.setTextColor(ContextCompat.getColor(context, R.color.lightBlue))
53 | holder.binding.cardImage.setCardBackgroundColor(ContextCompat.getColor(context, R.color.lightBlue_light))
54 | }
55 | "Transport" -> {
56 | holder.binding.cardIcon.setImageResource(R.drawable.ic_baseline_directions_transit_24)
57 | holder.binding.cardIcon.setColorFilter(ContextCompat.getColor(context, R.color.violet))
58 | holder.binding.category.setTextColor(ContextCompat.getColor(context, R.color.violet))
59 | holder.binding.cardImage.setCardBackgroundColor(ContextCompat.getColor(context, R.color.violet_light))
60 | }
61 | "Health" -> {
62 | holder.binding.cardIcon.setImageResource(R.drawable.ic_baseline_favorite_24)
63 | holder.binding.cardIcon.setColorFilter(ContextCompat.getColor(context, R.color.red))
64 | holder.binding.category.setTextColor(ContextCompat.getColor(context, R.color.red))
65 | holder.binding.cardImage.setCardBackgroundColor(ContextCompat.getColor(context, R.color.red_light))
66 | }
67 | "Other" -> {
68 | holder.binding.cardIcon.setImageResource(R.drawable.ic_baseline_category_24)
69 | holder.binding.cardIcon.setColorFilter(ContextCompat.getColor(context, R.color.lightBrown))
70 | holder.binding.category.setTextColor(ContextCompat.getColor(context, R.color.lightBrown))
71 | holder.binding.cardImage.setCardBackgroundColor(ContextCompat.getColor(context, R.color.lightBrown_light))
72 | }
73 | "Education" -> {
74 | holder.binding.cardIcon.setImageResource(R.drawable.ic_baseline_auto_stories_24)
75 | holder.binding.cardIcon.setColorFilter(ContextCompat.getColor(context, R.color.green))
76 | holder.binding.category.setTextColor(ContextCompat.getColor(context, R.color.green))
77 | holder.binding.cardImage.setCardBackgroundColor(ContextCompat.getColor(context, R.color.green_light))
78 | }
79 |
80 | }
81 |
82 |
83 | holder.binding.root.setOnClickListener {
84 | if(fragment == "Dashboard"){
85 | val argument = DashboardDirections.goToTransactionDetails(data,fragment)
86 | Navigation.findNavController(it).navigate(argument)
87 | }else if(fragment == "AllTransactions"){
88 | val argument = AllTransactionsDirections.allTransactionToTransactionDetails(data,fragment)
89 | Navigation.findNavController(it).navigate(argument)
90 | }
91 |
92 | }
93 |
94 | }
95 |
96 | override fun getItemCount() = transList.size
97 |
98 | }
99 |
100 |
101 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/Dao/TransactionDao.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.Dao
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.room.*
5 | import com.rishav.buckoid.Model.Transaction
6 |
7 | @Dao
8 | interface TransactionDao {
9 |
10 | @Query("SELECT * FROM `Transaction` ORDER BY year DESC,month DESC,day DESC,category DESC")
11 | fun getTransaction(): LiveData>
12 |
13 | @Query("SELECT * FROM `Transaction` WHERE month=:month AND year=:year")
14 | fun getMonthlyTransaction(month: Int,year: Int): LiveData>
15 |
16 | @Query("SELECT * FROM `Transaction` WHERE year=:year")
17 | fun getYearlyTransaction(year: Int): LiveData>
18 |
19 | @Insert(onConflict = OnConflictStrategy.REPLACE)
20 | fun insertTransaction(transaction: Transaction)
21 |
22 | @Query("DELETE FROM `TRANSACTION` WHERE id=:id")
23 | fun deleteTransaction(id: Int)
24 |
25 | @Update(onConflict = OnConflictStrategy.REPLACE)
26 | fun updateTransaction(transaction: Transaction)
27 |
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/Database/TransactionDatabase.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.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.rishav.buckoid.Dao.TransactionDao
8 | import com.rishav.buckoid.Model.Transaction
9 |
10 | @Database(entities = [Transaction::class], version = 1, exportSchema = false)
11 | abstract class TransactionDatabase : RoomDatabase() {
12 |
13 | abstract fun myTransactionDao(): TransactionDao
14 |
15 | companion object
16 | {
17 | private var INSTANCE: TransactionDatabase?=null
18 | fun getDatabaseInstance(context: Context): TransactionDatabase {
19 | val tempInstance= INSTANCE
20 | if (tempInstance!=null){
21 | return tempInstance
22 | }
23 | synchronized(this)
24 | {
25 | val roomDatabaseInstance = Room.databaseBuilder(context,
26 | TransactionDatabase::class.java,"Transaction").allowMainThreadQueries().build()
27 | INSTANCE =roomDatabaseInstance
28 | return roomDatabaseInstance
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid
2 |
3 | import android.app.KeyguardManager
4 | import android.content.*
5 | import android.content.pm.PackageManager
6 | import android.hardware.biometrics.BiometricPrompt
7 | import android.net.Uri
8 | import android.os.Build
9 | import android.os.Bundle
10 | import android.os.CancellationSignal
11 | import android.view.MenuItem
12 | import android.view.View
13 | import android.widget.Toast
14 | import androidx.annotation.RequiresApi
15 | import androidx.appcompat.app.AppCompatActivity
16 | import androidx.appcompat.app.AppCompatDelegate
17 | import androidx.appcompat.widget.SwitchCompat
18 | import androidx.core.app.ActivityCompat
19 | import androidx.core.view.GravityCompat
20 | import androidx.navigation.fragment.NavHostFragment
21 | import androidx.navigation.ui.setupWithNavController
22 | import com.google.android.material.navigation.NavigationView
23 | import com.google.android.play.core.appupdate.AppUpdateManager
24 | import com.google.android.play.core.appupdate.AppUpdateManagerFactory
25 | import com.google.android.play.core.install.model.AppUpdateType
26 | import com.google.android.play.core.install.model.UpdateAvailability
27 | import com.rishav.buckoid.databinding.ActivityMainBinding
28 | import java.util.*
29 |
30 | import android.content.Intent
31 |
32 |
33 | class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
34 | lateinit var binding:ActivityMainBinding
35 | lateinit var mNightModeSwitch: SwitchCompat
36 | lateinit var userDetails:SharedPreferences
37 | private var appUpdate: AppUpdateManager? = null
38 | var isNight:Boolean = false
39 |
40 | //finger print
41 | var isFingerPrintEnabled:Boolean = false
42 | private var cancellationSignal:CancellationSignal?=null
43 | private val authenticationCallback:BiometricPrompt.AuthenticationCallback
44 | get() =
45 | @RequiresApi(Build.VERSION_CODES.P)
46 | object : BiometricPrompt.AuthenticationCallback(){
47 | override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
48 | super.onAuthenticationError(errorCode, errString)
49 | finish()
50 | }
51 | override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult?) {
52 | super.onAuthenticationSucceeded(result)
53 | }
54 | }
55 | @RequiresApi(Build.VERSION_CODES.Q)
56 | override fun onCreate(savedInstanceState: Bundle?) {
57 | super.onCreate(savedInstanceState)
58 | if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
59 | userDetails = this.getSharedPreferences("UserDetails", MODE_PRIVATE)
60 | isFingerPrintEnabled = userDetails.getBoolean("fingerprint_enabled", false)
61 | if (isFingerPrintEnabled) {
62 | fingerPrintSensor()
63 | }
64 | }
65 | setTheme(R.style.Theme_TrackBack)
66 | binding = ActivityMainBinding.inflate(layoutInflater)
67 | setContentView(binding.root)
68 | nightMode()
69 | inAppUpdater()
70 | binding.navigationView.setNavigationItemSelectedListener(this)
71 | val navHostFragment =
72 | supportFragmentManager.findFragmentById(R.id.fragmentContainerView) as NavHostFragment
73 | val navController = navHostFragment.navController
74 | binding.bottomNavigation.setupWithNavController(navController)
75 |
76 | }
77 |
78 | fun nightMode(){
79 | // Configure night-mode switch
80 | isNight = userDetails.getBoolean("nightMode",true)
81 | val actionLayout:View = binding.navigationView.getMenu().findItem(R.id.dark_mode).getActionView()
82 | mNightModeSwitch = actionLayout.findViewById(R.id.night_switch_compat)
83 | if (isNight) {
84 | mNightModeSwitch.setChecked(true)
85 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
86 | }else{
87 | mNightModeSwitch.setChecked(false)
88 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
89 | }
90 | mNightModeSwitch.setOnCheckedChangeListener { buttonView, isChecked -> applyNightMode(isChecked) }
91 |
92 | }
93 |
94 | private fun applyNightMode(checked: Boolean) {
95 | if (checked) {
96 | isNight = true
97 | saveSettingsBoolean("nightMode",true)
98 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
99 | }else{
100 | isNight = false
101 | saveSettingsBoolean("nightMode",false)
102 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
103 | }
104 | //restartActivityInvalidateBackstack(this)
105 | }
106 | private fun saveSettingsBoolean(mode: String, isNight: Boolean) {
107 | val editor: SharedPreferences.Editor = userDetails.edit()
108 | editor.putBoolean(mode, isNight)
109 | editor.apply()
110 | }
111 |
112 |
113 | override fun onNavigationItemSelected(item: MenuItem): Boolean {
114 | val id = item.getItemId()
115 | if(id == R.id.dark_mode){
116 | mNightModeSwitch.performClick()
117 | }else if(id == R.id.nav_share){
118 | try {
119 | val intent = Intent(Intent.ACTION_SEND)
120 | intent.type = "text/plain"
121 | intent.putExtra(Intent.EXTRA_SUBJECT, "@string/app_name")
122 | intent.putExtra(
123 | Intent.EXTRA_TEXT,
124 | "https://play.google.com/store/apps/details?id="+ this@MainActivity.getPackageName()
125 | )
126 | startActivity(Intent.createChooser(intent, "Share With"))
127 | } catch (e: Exception) {
128 | Toast.makeText(
129 | this@MainActivity,
130 | "Unable to share at this moment.." + e.message.toString(),
131 | Toast.LENGTH_SHORT
132 | ).show()
133 | }
134 | }else if(id == R.id.nav_RateUs){
135 | try {
136 | startActivity(
137 | Intent(
138 | Intent.ACTION_VIEW,
139 | Uri.parse("market://details?id=$packageName")
140 | )
141 | )
142 | } catch (e: ActivityNotFoundException) {
143 | startActivity(
144 | Intent(
145 | Intent.ACTION_VIEW,
146 | Uri.parse("https://play.google.com/store/apps/details?id=$packageName")
147 | )
148 | )
149 | }
150 | }else if(id == R.id.nav_aboutUs){
151 | Toast.makeText(
152 | this,
153 | "Working on this wait for update",
154 | Toast.LENGTH_SHORT
155 | ).show()
156 | }
157 | binding.drawerLayout.closeDrawer(GravityCompat.START);
158 | return true
159 | }
160 |
161 | private fun inAppUpdater() {
162 | appUpdate = AppUpdateManagerFactory.create(this)
163 |
164 | appUpdate?.appUpdateInfo?.addOnSuccessListener { updateInfo ->
165 | if(updateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
166 | && updateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)){
167 | appUpdate!!.startUpdateFlowForResult(updateInfo,AppUpdateType.IMMEDIATE,this,100)
168 | }
169 |
170 | }
171 | }
172 |
173 | override fun onResume() {
174 | super.onResume()
175 | inProgressUpdate()
176 | }
177 |
178 | private fun inProgressUpdate() {
179 | appUpdate?.appUpdateInfo?.addOnSuccessListener { updateInfo ->
180 | if(updateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS){
181 | appUpdate!!.startUpdateFlowForResult(updateInfo,AppUpdateType.IMMEDIATE,this,100)
182 | }
183 |
184 | }
185 | }
186 |
187 |
188 |
189 | @RequiresApi(Build.VERSION_CODES.Q)
190 | private fun fingerPrintSensor() {
191 | checkBiometricSupport()
192 | val biometricPrompt = BiometricPrompt.Builder(this)
193 | .setDeviceCredentialAllowed(true)
194 | .setTitle("Authentication Required")
195 | .setDescription("Please enter your PIN / password to continue")
196 | .build()
197 |
198 | biometricPrompt.authenticate(getCancellationSignal(),mainExecutor,authenticationCallback)
199 |
200 |
201 | }
202 |
203 | private fun getCancellationSignal(): CancellationSignal{
204 | cancellationSignal = CancellationSignal()
205 | cancellationSignal?.setOnCancelListener {
206 | notifyUser("Authentication was cancelled by the user")
207 |
208 | }
209 | return cancellationSignal as CancellationSignal
210 | }
211 |
212 | private fun checkBiometricSupport(): Boolean {
213 | val keyguardManager : KeyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
214 |
215 | if (!keyguardManager.isKeyguardSecure){
216 | notifyUser("Finger print not enabled in settings")
217 | return false
218 | }
219 |
220 | if (ActivityCompat.checkSelfPermission(this,android.Manifest.permission.USE_BIOMETRIC)!= PackageManager.PERMISSION_GRANTED){
221 | notifyUser("Fingerprint authentication permission is not enabled")
222 | return false
223 | }
224 |
225 | return if (packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)){
226 | true
227 | }else true
228 |
229 | }
230 |
231 | private fun notifyUser(message: String) {
232 | Toast.makeText(this,message,Toast.LENGTH_SHORT).show()
233 | }
234 |
235 |
236 |
237 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/Model/Profile.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.Model
2 |
3 | import android.content.Context
4 | import com.google.android.gms.auth.api.signin.GoogleSignIn
5 | import com.google.android.gms.auth.api.signin.GoogleSignInAccount
6 |
7 | class Profile(context:Context){
8 | val mContext:Context = context
9 | val name = getData()?.displayName.toString()
10 | val profilePic = getData()?.photoUrl
11 | val email = getData()?.email
12 | val account = getData()
13 |
14 | fun getData(): GoogleSignInAccount? {
15 | val acct = GoogleSignIn.getLastSignedInAccount(mContext)
16 | return acct
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/Model/Transaction.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.Model
2 |
3 | import android.os.Parcelable
4 | import androidx.room.Entity
5 | import androidx.room.PrimaryKey
6 | import kotlinx.parcelize.Parcelize
7 |
8 | @Entity(tableName = "Transaction")
9 | @Parcelize
10 | data class Transaction (
11 |
12 | @PrimaryKey(autoGenerate = true)
13 | var id:Int? = null,
14 |
15 | var type: String,
16 | var category: String,
17 | var title: String,
18 | var amount: Double,
19 | var date: String,
20 | var day:Int,
21 | var month:Int,
22 | var year:Int,
23 | var note: String
24 |
25 | ) : Parcelable
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/Repository/TransactionRepository.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.Repository
2 |
3 | import androidx.lifecycle.LiveData
4 | import com.rishav.buckoid.Dao.TransactionDao
5 | import com.rishav.buckoid.Model.Transaction
6 |
7 | class TransactionRepository(val dao: TransactionDao) {
8 |
9 | fun getAllTransaction(): LiveData> {
10 | return dao.getTransaction()
11 | }
12 |
13 | fun getMonthlyTransaction(month:Int,Year:Int): LiveData>{
14 | return dao.getMonthlyTransaction(month,Year)
15 | }
16 |
17 | fun getYearlyTransaction(year:Int): LiveData>{
18 | return dao.getYearlyTransaction(year)
19 | }
20 |
21 | fun insertTransaction(transaction: Transaction){
22 | dao.insertTransaction(transaction)
23 | }
24 |
25 | fun deleteTransaction(id:Int){
26 | dao.deleteTransaction(id)
27 | }
28 |
29 | fun updateTransaction(transaction: Transaction){
30 | dao.updateTransaction(transaction)
31 | }
32 |
33 |
34 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/UserDetails.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid
2 |
3 | import android.content.Intent
4 | import android.content.SharedPreferences
5 | import androidx.appcompat.app.AppCompatActivity
6 | import android.os.Bundle
7 | import androidx.appcompat.app.AppCompatDelegate
8 | import com.rishav.buckoid.databinding.ActivityUserDetailsBinding
9 |
10 | class UserDetails : AppCompatActivity() {
11 | lateinit var binding:ActivityUserDetailsBinding
12 | lateinit var userDetails: SharedPreferences
13 | var isFirstTime:Boolean = false
14 | override fun onCreate(savedInstanceState: Bundle?) {
15 | setData()
16 | setTheme(R.style.Theme_TrackBack)
17 | super.onCreate(savedInstanceState)
18 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
19 | binding = ActivityUserDetailsBinding.inflate(layoutInflater)
20 | setContentView(binding.root)
21 |
22 | }
23 |
24 | private fun setData() {
25 | userDetails = this.getSharedPreferences("UserDetails", AppCompatActivity.MODE_PRIVATE)
26 | isFirstTime = userDetails.getBoolean("isFirstTime",true)
27 | if (!isFirstTime){
28 | goToNextScreen()
29 | finish()
30 | }
31 | }
32 |
33 | private fun goToNextScreen() {
34 | val intent = Intent(this, MainActivity::class.java)
35 | startActivity(intent)
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/ViewModel/TransactionViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.ViewModel
2 |
3 | import android.app.Application
4 | import androidx.lifecycle.AndroidViewModel
5 | import androidx.lifecycle.LiveData
6 | import com.rishav.buckoid.Database.TransactionDatabase
7 | import com.rishav.buckoid.Model.Transaction
8 | import com.rishav.buckoid.Repository.TransactionRepository
9 |
10 |
11 | class TransactionViewModel(application: Application): AndroidViewModel(application) {
12 |
13 | val repository: TransactionRepository
14 |
15 | init{
16 | val dao = TransactionDatabase.getDatabaseInstance(application).myTransactionDao()
17 | repository= TransactionRepository(dao)
18 | }
19 |
20 | fun addTransaction(transaction: Transaction){
21 | repository.insertTransaction(transaction)
22 | }
23 |
24 | fun getTransaction(): LiveData> = repository.getAllTransaction()
25 |
26 | fun getMonthlyTransaction(month:Int,Year:Int): LiveData> = repository.getMonthlyTransaction(month,Year)
27 |
28 | fun getYearlyTransaction(year: Int): LiveData> = repository.getYearlyTransaction(year)
29 |
30 | fun deleteTransaction(id:Int){
31 | repository.deleteTransaction(id)
32 | }
33 |
34 | fun updateTransaction(transaction: Transaction){
35 | repository.updateTransaction(transaction)
36 | }
37 |
38 |
39 |
40 |
41 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/fragments/Authentication/UserDetails.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.fragments.Authentication
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Intent
5 | import android.content.SharedPreferences
6 | import android.os.Bundle
7 | import androidx.fragment.app.Fragment
8 | import android.view.LayoutInflater
9 | import android.view.View
10 | import android.view.ViewGroup
11 | import android.widget.Toast
12 | import androidx.appcompat.app.AppCompatActivity
13 | import androidx.core.content.ContextCompat
14 | import com.google.android.gms.auth.api.signin.GoogleSignIn
15 | import com.rishav.buckoid.MainActivity
16 | import com.rishav.buckoid.R
17 | import com.rishav.buckoid.databinding.FragmentUserDetailsBinding
18 |
19 | class UserDetails : Fragment() {
20 |
21 | lateinit var binding:FragmentUserDetailsBinding
22 | lateinit var userDetails: SharedPreferences
23 | override fun onCreateView(
24 | inflater: LayoutInflater, container: ViewGroup?,
25 | savedInstanceState: Bundle?
26 | ): View{
27 | // Inflate the layout for this fragment
28 | getActivity()?.getWindow()?.setStatusBarColor(ContextCompat.getColor(requireActivity(), R.color.background))
29 | binding= FragmentUserDetailsBinding.inflate(inflater, container, false)
30 | setData()
31 | return binding.root
32 | }
33 |
34 | @SuppressLint("SetTextI18n")
35 | private fun setData() {
36 | val googleSignInAccount = GoogleSignIn.getLastSignedInAccount(requireActivity())
37 | val name=googleSignInAccount?.displayName.toString().split(" ")
38 | binding.text1.text = "Good to go \n${name[0]} !!"
39 | userDetails = requireActivity().getSharedPreferences("UserDetails", AppCompatActivity.MODE_PRIVATE)
40 | binding.next.setOnClickListener {
41 | saveUserData()
42 | }
43 | }
44 |
45 | private fun goToNextScreen() {
46 | val intent = Intent(requireActivity(), MainActivity::class.java)
47 | startActivity(intent)
48 | }
49 |
50 | private fun saveUserData() {
51 | val monthly_budget = binding.editMoney.text.toString()
52 | val yearly_budget = binding.editYearMoney
53 | if(monthly_budget.equals("") || yearly_budget.text.toString().equals("")) {
54 | Toast.makeText(requireActivity(), "Enter all details to continue...", Toast.LENGTH_SHORT).show()
55 | }else{
56 | val editor: SharedPreferences.Editor = userDetails.edit()
57 | editor.putBoolean("isFirstTime", false)
58 | editor.putString("MonthlyBudget", monthly_budget)
59 | editor.putString("YearlyBudget", yearly_budget.text.toString())
60 | editor.apply()
61 | goToNextScreen()
62 | }
63 | }
64 |
65 |
66 |
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/fragments/Authentication/UserSignUp.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.fragments.Authentication
2 |
3 | import android.R.attr
4 | import android.app.Activity
5 | import android.content.Intent
6 | import android.os.Bundle
7 | import android.util.Log
8 | import androidx.fragment.app.Fragment
9 | import android.view.LayoutInflater
10 | import android.view.View
11 | import android.view.ViewGroup
12 | import androidx.activity.result.contract.ActivityResultContracts
13 | import com.google.android.gms.auth.api.signin.GoogleSignIn
14 | import com.google.android.gms.auth.api.signin.GoogleSignInAccount
15 | import com.google.android.gms.auth.api.signin.GoogleSignInClient
16 | import com.google.android.gms.auth.api.signin.GoogleSignInOptions
17 | import com.google.android.gms.common.Scopes
18 | import com.google.android.gms.common.api.ApiException
19 | import com.google.android.gms.common.api.Scope
20 | import com.google.android.gms.tasks.Task
21 | import com.google.api.client.extensions.android.http.AndroidHttp
22 | import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential
23 | import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException
24 | import com.google.api.client.http.FileContent
25 | import com.google.api.client.json.gson.GsonFactory
26 | import com.google.api.services.drive.Drive
27 | import com.google.api.services.drive.DriveScopes
28 | import com.rishav.buckoid.databinding.FragmentUserSignUpBinding
29 | import java.util.*
30 | import com.google.api.services.drive.model.FileList
31 | import java.io.File
32 | import java.io.FileOutputStream
33 | import java.io.IOException
34 | import java.io.OutputStream
35 | import android.R.attr.data
36 | import android.widget.Toast
37 | import androidx.core.content.ContextCompat
38 | import androidx.navigation.NavOptions
39 | import androidx.navigation.Navigation
40 | import androidx.navigation.Navigation.findNavController
41 | import com.rishav.buckoid.R
42 |
43 |
44 | class UserSignUp : Fragment() {
45 | lateinit var binding:FragmentUserSignUpBinding
46 | lateinit var client: GoogleSignInClient
47 | override fun onCreateView(
48 | inflater: LayoutInflater, container: ViewGroup?,
49 | savedInstanceState: Bundle?
50 | ): View? {
51 | // Inflate the layout for this fragment
52 | getActivity()?.getWindow()?.setStatusBarColor(ContextCompat.getColor(requireActivity(), R.color.background))
53 | binding= FragmentUserSignUpBinding.inflate(inflater, container, false)
54 |
55 | setUpSignUp()
56 | binding.googleSignUp.setOnClickListener{
57 | signIn()
58 | }
59 | return binding.root
60 | }
61 |
62 | private fun setUpSignUp() {
63 | val account = GoogleSignIn.getLastSignedInAccount(requireActivity())
64 | if (account!=null){
65 | goToNextPage()
66 | }
67 | googleCall()
68 | }
69 | fun googleCall(){
70 | val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
71 | .requestEmail()
72 | .requestScopes(Scope(DriveScopes.DRIVE_FILE))
73 | .build()
74 | client = GoogleSignIn.getClient(requireActivity(), gso)
75 | }
76 | private fun signIn() {
77 | val signInIntent: Intent = client.signInIntent
78 | getResult.launch(signInIntent)
79 | }
80 | private val getResult =
81 | registerForActivityResult(
82 | ActivityResultContracts.StartActivityForResult()
83 | ) {
84 | if (it.resultCode == Activity.RESULT_OK) {
85 | goToNextPage()
86 | }else{
87 | notifyUser("Check Your Network Connection and Try again")
88 | }
89 | }
90 |
91 | private fun notifyUser(message: String) {
92 | Toast.makeText(requireContext(),message, Toast.LENGTH_SHORT).show()
93 | }
94 |
95 | private fun goToNextPage() {
96 | findNavController(requireActivity(),R.id.fragmentContainerView2)
97 | .navigate(R.id.goToUserDetails,
98 | null,
99 | NavOptions.Builder()
100 | .setPopUpTo(R.id.userSignUp,
101 | true).build()
102 | )
103 | }
104 |
105 | /*
106 | private fun handleSignInResult(completedTask: Task) {
107 | try {
108 | val account = completedTask.getResult(ApiException::class.java)
109 | } catch (e: ApiException) {
110 | }
111 | }
112 |
113 | private fun handle(){
114 | val googleSignInAccount = GoogleSignIn.getLastSignedInAccount(requireActivity())
115 | val credential =
116 | GoogleAccountCredential.usingOAuth2(requireContext(), Collections.singleton(Scopes.DRIVE_FILE))
117 | credential.selectedAccount = googleSignInAccount!!.account
118 | val googleDriveService = Drive.Builder(
119 | AndroidHttp.newCompatibleTransport(),
120 | GsonFactory(),
121 | credential
122 | )
123 | .setApplicationName(getString(com.rishav.buckoid.R.string.app_name))
124 | .build()
125 | Thread {
126 | Download(googleDriveService)
127 | }.start()
128 |
129 |
130 | }
131 |
132 | private fun handleSignInIntent(data: Intent?) {
133 |
134 | GoogleSignIn.getSignedInAccountFromIntent(data)
135 | .addOnSuccessListener {
136 | val credential: GoogleAccountCredential = GoogleAccountCredential
137 | .usingOAuth2(requireActivity(), Collections.singleton(DriveScopes.DRIVE_FILE))
138 | credential.setSelectedAccount(it.account)
139 | val googleDriveDevices: Drive = Drive.Builder(
140 | AndroidHttp.newCompatibleTransport(),
141 | GsonFactory(),
142 | credential)
143 | .setApplicationName("Buckoid")
144 | .build()
145 |
146 | Thread(Runnable {
147 | Download(googleDriveDevices)
148 | }).start()
149 | }
150 | .addOnFailureListener{
151 |
152 | }
153 |
154 | }
155 |
156 | private fun upload(googleDriveDevices:Drive){
157 | var storageFile:com.google.api.services.drive.model.File? = null
158 | storageFile?.setParents(Collections.singletonList("appDataFolder"))
159 | storageFile?.setName("Buckoid_Backup_Transaction")
160 |
161 | val filePath:java.io.File = java.io.File(dbPath)
162 | val mediaContent:FileContent = FileContent("",filePath)
163 | try {
164 | val file: com.google.api.services.drive.model.File? = googleDriveDevices.files().create(storageFile,mediaContent).execute();
165 | if (file != null) {
166 | Log.w("@@@","Filename: %s File ID: %s ${file.getName()}, ${file.getId()}")
167 | }
168 | }
169 | catch(e: UserRecoverableAuthIOException){
170 | Log.w("@@@","errorAuthIO:"+e.message.toString())
171 | }
172 | catch (e:Exception) {
173 | Log.w("@@@","error:"+e.message.toString())
174 | }
175 | }
176 |
177 | private fun Download(googleDriveService:Drive) {
178 | try {
179 | val dir = File("/data/data/com.rishav.buckoid/databases")
180 | if (dir.isDirectory) {
181 | val children = dir.list()
182 | for (i in children.indices) {
183 | File(dir, children[i]).delete()
184 | }
185 | }
186 | val files: FileList = googleDriveService.files().list()
187 | .setSpaces("appDataFolder")
188 | .setFields("nextPageToken, files(id, name, createdTime)")
189 | .setPageSize(10)
190 | .execute()
191 | if (files.files.size == 0) Log.e("@@@", "No DB file exists in Drive")
192 | for (file in files.files) {
193 | Log.e("@@@", "Found file: ${file.name}, ${file.id}, ${file.createdTime}")
194 | if (file.name.equals("Buckoid_Backup_Transaction")) {
195 | val outputStream: OutputStream = FileOutputStream(dbPath)
196 | googleDriveService.files().get(file.id).executeMediaAndDownloadTo(outputStream)
197 | }
198 | }
199 | } catch (e: IOException) {
200 | Log.w("@@@","error:"+e.message.toString())
201 | }
202 | }*/
203 |
204 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/fragments/BackupDrive.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.fragments
2 |
3 | import android.os.Bundle
4 | import android.util.Log
5 | import androidx.fragment.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import android.widget.Toast
10 | import androidx.navigation.Navigation
11 | import com.google.android.gms.common.Scopes
12 | import com.google.android.material.bottomnavigation.BottomNavigationView
13 | import com.google.api.client.extensions.android.http.AndroidHttp
14 | import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential
15 | import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException
16 | import com.google.api.client.http.FileContent
17 | import com.google.api.client.json.gson.GsonFactory
18 | import com.google.api.services.drive.Drive
19 | import com.google.api.services.drive.model.FileList
20 | import com.rishav.buckoid.R
21 | import com.rishav.buckoid.databinding.FragmentBackupDriveBinding
22 | import com.rishav.buckoid.Model.Profile
23 | import java.io.FileOutputStream
24 | import java.io.IOException
25 | import java.io.OutputStream
26 | import java.util.*
27 |
28 | class BackupDrive : Fragment() {
29 |
30 | lateinit var binding:FragmentBackupDriveBinding
31 | lateinit var profileModel:Profile
32 | private val dbPath = "/data/data/com.rishav.buckoid/databases/Transaction"
33 | private val dbPathWal = "/data/data/com.rishav.buckoid/databases/Transaction-wal"
34 | private val dbPathShm = "/data/data/com.rishav.buckoid/databases/Transaction-shm"
35 | override fun onCreateView(
36 | inflater: LayoutInflater, container: ViewGroup?,
37 | savedInstanceState: Bundle?
38 | ): View{
39 | // Inflate the layout for this fragment
40 | binding = FragmentBackupDriveBinding.inflate(inflater, container, false)
41 | val bottomNav: BottomNavigationView = requireActivity().findViewById(R.id.bottomNavigation)
42 | bottomNav.visibility = View.GONE
43 |
44 | setData()
45 | return binding.root
46 | }
47 |
48 | private fun setData() {
49 | binding.back.setOnClickListener {
50 | Navigation.findNavController(binding.root).navigate(R.id.action_backupDrive_to_profile)
51 | }
52 |
53 | binding.backupBtn.setOnClickListener{
54 | //backupdata()
55 | Toast.makeText(requireActivity(),"Coming Soon wait for an Update.", Toast.LENGTH_SHORT).show()
56 | //notifyUser("Coming Soon wait for an Update.")
57 | }
58 | }
59 |
60 | private fun notifyUser(message: String) {
61 | Toast.makeText(requireActivity(),message, Toast.LENGTH_SHORT).show()
62 | }
63 |
64 | private fun backupdata() {
65 | profileModel = Profile(requireContext())
66 | val googleSignInAccount = profileModel.account
67 | val credential =
68 | GoogleAccountCredential.usingOAuth2(requireContext(), Collections.singleton(Scopes.DRIVE_FILE))
69 | credential.selectedAccount = googleSignInAccount!!.account
70 | val googleDriveService = Drive.Builder(
71 | AndroidHttp.newCompatibleTransport(),
72 | GsonFactory(),
73 | credential
74 | )
75 | .setApplicationName(getString(com.rishav.buckoid.R.string.app_name))
76 | .build()
77 | Thread {
78 | upload(googleDriveService)
79 | }.start()
80 | }
81 |
82 | private fun upload(googleDriveDevices:Drive){
83 | val storageFile:com.google.api.services.drive.model.File =com.google.api.services.drive.model.File()
84 | //storageFile.setParents(Collections.singletonList("appDataFolder"))
85 | storageFile.setName("Transaction")
86 |
87 | val storageFileShm:com.google.api.services.drive.model.File = com.google.api.services.drive.model.File()
88 | //storageFile.setParents(Collections.singletonList("appDataFolder"))
89 | storageFile.setName("Transaction-shm")
90 |
91 | val storageFileWal:com.google.api.services.drive.model.File = com.google.api.services.drive.model.File()
92 | //storageFile.setParents(Collections.singletonList("appDataFolder"))
93 | storageFile.setName("Transaction-wal")
94 |
95 | val filePath:java.io.File = java.io.File(dbPath)
96 | //val filePathShm:java.io.File = java.io.File(dbPathShm)
97 | //val filePathWal:java.io.File = java.io.File(dbPathWal)
98 | val mediaContent:FileContent = FileContent("",filePath)
99 | //val mediaContentShm:FileContent = FileContent("",filePathShm)
100 | //val mediaContentWal:FileContent = FileContent("",filePathWal)
101 | try {
102 | val file: com.google.api.services.drive.model.File? = googleDriveDevices.files().create(storageFile,mediaContent).execute();
103 | if (file != null) {
104 | Log.w("@@@","Filename: %s File ID: %s ${file.getName()}, ${file.getId()}")
105 | }
106 |
107 | /*val fileWal: com.google.api.services.drive.model.File? = googleDriveDevices.files().create(storageFile,mediaContentWal).execute();
108 | if (fileWal != null) {
109 | Log.w("@@@","Filename: %s File ID: %s ${fileWal.getName()}, ${fileWal.getId()}")
110 | }
111 | val fileShm: com.google.api.services.drive.model.File? = googleDriveDevices.files().create(storageFileShm,mediaContentShm).execute();
112 | if (fileShm != null) {
113 | Log.w("@@@","Filename: %s File ID: %s ${fileShm.getName()}, ${fileShm.getId()}")
114 | }*/
115 |
116 | }
117 | catch(e: UserRecoverableAuthIOException){
118 | Log.w("@@@","errorAuthIO:"+e.message.toString())
119 | }
120 | catch (e:Exception) {
121 | Log.w("@@@","error:"+e.message.toString())
122 | }
123 | }
124 |
125 |
126 | private fun Download(googleDriveService:Drive) {
127 | try {
128 | val dir = java.io.File("/data/data/com.rishav.buckoid/databases")
129 | if (dir.isDirectory) {
130 | val children = dir.list()
131 | for (i in children.indices) {
132 | Log.e("@@@", "Found file: ${children[i]}")
133 | java.io.File(dir, children[i]).delete()
134 | }
135 | //Log.e("@@@", "Found file: ${children}")
136 |
137 | val files: FileList = googleDriveService.files().list()
138 | //.setSpaces("appDataFolder")
139 | .setFields("nextPageToken, files(id, name, createdTime, size)")
140 | .setPageSize(10)
141 | .execute()
142 | if (files.files.size == 0) Log.e("@@@", "No DB file exists in Drive")
143 | for (file in files.files) {
144 | Log.e("@@@", "Found file: ${file.name}, ${file.id}, ${file.createdTime}, ${file.size}")
145 | if (file.name.equals("Transaction")) {
146 | val outputStream: OutputStream = FileOutputStream(dbPath)
147 | googleDriveService.files().get(file.id).executeMediaAndDownloadTo(outputStream)
148 | }else if(file.getName().equals("Transaction-shm")){
149 | val outputStream: OutputStream = FileOutputStream(dbPathShm)
150 | googleDriveService.files().get(file.id).executeMediaAndDownloadTo(outputStream)
151 | }
152 | else if(file.getName().equals("Transaction-wal")){
153 | val outputStream: OutputStream = FileOutputStream(dbPathWal)
154 | googleDriveService.files().get(file.id).executeMediaAndDownloadTo(outputStream)
155 | }
156 | }
157 | Log.e("@@@", "Found file: ${children}")
158 | }
159 | } catch (e: IOException) {
160 | Log.w("@@@","error:"+e.message.toString())
161 | }
162 | }
163 |
164 |
165 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/fragments/Dashboard.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.fragments
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.SharedPreferences
5 | import android.os.Bundle
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import androidx.activity.OnBackPressedCallback
10 | import androidx.appcompat.app.AppCompatActivity
11 | import androidx.core.content.ContextCompat
12 | import androidx.fragment.app.Fragment
13 | import androidx.fragment.app.viewModels
14 | import androidx.navigation.Navigation
15 | import androidx.recyclerview.widget.LinearLayoutManager
16 | import com.rishav.buckoid.Adapter.TransactionAdapter
17 | import com.rishav.buckoid.Model.Transaction
18 | import com.rishav.buckoid.R
19 | import com.rishav.buckoid.ViewModel.TransactionViewModel
20 | import com.rishav.buckoid.databinding.FragmentDashboardBinding
21 | import com.google.android.material.bottomnavigation.BottomNavigationView
22 | import org.eazegraph.lib.models.PieModel
23 | import java.text.SimpleDateFormat
24 | import java.util.*
25 | import androidx.core.view.GravityCompat
26 | import androidx.drawerlayout.widget.DrawerLayout
27 | import com.bumptech.glide.Glide
28 | import com.google.android.material.navigation.NavigationView
29 | import com.rishav.buckoid.Model.Profile
30 | import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt
31 |
32 | class Dashboard : Fragment() {
33 |
34 | lateinit var binding:FragmentDashboardBinding
35 | private val viewModel: TransactionViewModel by viewModels()
36 | private var totalExpense = 0.0
37 | private var totalGoal = 5000.0f
38 | private var totalFood = 0.0f
39 | private var totalShopping = 0.0f
40 | private var totalTransport=0.0f
41 | private var totalHealth = 0.0f
42 | private var totalOthers = 0.0f
43 | private var totalAcademics = 0.0f
44 | lateinit var drawerLayout:DrawerLayout
45 | lateinit var navigationView:NavigationView
46 | lateinit var userDetails: SharedPreferences
47 | lateinit var profileModel: Profile
48 |
49 | override fun onCreateView(
50 | inflater: LayoutInflater, container: ViewGroup?,
51 | savedInstanceState: Bundle?
52 | ): View {
53 | // Inflate the layout for this fragment
54 | getActivity()?.getWindow()?.setStatusBarColor(ContextCompat.getColor(requireActivity(), R.color.background))
55 | binding = FragmentDashboardBinding.inflate(inflater, container, false)
56 | val bottomNav: BottomNavigationView = requireActivity().findViewById(R.id.bottomNavigation)
57 | drawerLayout = requireActivity().findViewById(R.id.drawer_layout)
58 | navigationView = requireActivity().findViewById(R.id.navigationView)
59 | bottomNav.visibility = View.VISIBLE
60 | navigationDrawer()
61 | getData()
62 | val arg = DashboardDirections.actionDashboard2ToAddTransaction(Transaction(null,"","","",0.0,"",0,0,0,""),false)
63 | binding.addNew.setOnClickListener{Navigation.findNavController(binding.root).navigate(arg)}
64 | return binding.root
65 | }
66 |
67 |
68 | //calling data from room database using livedata view model
69 | @SuppressLint("SetTextI18n", "SimpleDateFormat")
70 | private fun getData() {
71 | var format = SimpleDateFormat("MM")
72 | val currentMonth = format.format(Calendar.getInstance().getTime())
73 | format = SimpleDateFormat("yyyy")
74 | val currentYear = format.format(Calendar.getInstance().getTime())
75 | format = SimpleDateFormat("MMMM")
76 | binding.date.text = "${format.format(Calendar.getInstance().getTime())} ${currentYear}"
77 |
78 | userDetails = requireActivity().getSharedPreferences("UserDetails", AppCompatActivity.MODE_PRIVATE)
79 | profileModel = Profile(requireContext())
80 | val name=profileModel.name.split(" ")
81 | binding.name.text = "Hi ${name[0]} !!"
82 | Glide.with(requireActivity()).load(profileModel.profilePic).into(binding.profilePic)
83 |
84 | if(!userDetails.getBoolean("ShowedOnboardingDashboard",false)){
85 | showOnBoarding()
86 | }
87 |
88 | totalExpense = 0.0
89 | totalGoal = userDetails.getString("MonthlyBudget","0")?.toFloat()!!
90 | totalFood = 0.0f
91 | totalShopping = 0.0f
92 | totalTransport=0.0f
93 | totalHealth = 0.0f
94 | totalOthers = 0.0f
95 | totalAcademics = 0.0f
96 | viewModel.getMonthlyTransaction(currentMonth.toInt(),currentYear.toInt()).observe(viewLifecycleOwner,{ transactionList ->
97 | if(transactionList.isEmpty()){
98 | binding.noTransactionsDoneText.text = "Add Your First Transaction of ${format.format(Calendar.getInstance().getTime())} $currentYear \n Click On + to add Transactions"
99 | binding.noTransactionsDoneText.visibility = View.VISIBLE
100 | binding.transactionRecyclerView.visibility = View.GONE
101 | binding.text1.visibility = View.GONE
102 | }
103 | else {
104 | binding.text1.visibility = View.VISIBLE
105 | binding.noTransactionsDoneText.visibility = View.GONE
106 | binding.transactionRecyclerView.visibility = View.VISIBLE
107 | }
108 | binding.transactionRecyclerView.layoutManager =
109 | LinearLayoutManager(requireContext())
110 | binding.transactionRecyclerView.adapter =
111 | TransactionAdapter(requireContext(),requireActivity(), "Dashboard", transactionList.reversed())
112 |
113 | for (i in transactionList) {
114 | totalExpense += i.amount
115 | when (i.category) {
116 | "Food" -> {
117 | totalFood += (i.amount.toFloat())
118 | }
119 | "Shopping" -> {
120 | totalShopping += (i.amount.toFloat())
121 | }
122 | "Transport" -> {
123 | totalTransport += (i.amount.toFloat())
124 | }
125 |
126 | "Health" -> {
127 | totalHealth += (i.amount.toFloat())
128 | }
129 | "Other" -> {
130 | totalOthers += (i.amount.toFloat())
131 | }
132 | "Education" -> {
133 | totalAcademics += (i.amount.toFloat())
134 | }
135 | }
136 | }
137 | binding.expense.text = "₹${totalExpense.toInt()}"
138 | binding.budget.text = "₹${totalGoal.toInt()}"
139 | if (totalExpense > totalGoal) {
140 | binding.indicator.setImageResource(R.drawable.ic_negative_transaction)
141 | binding.expense.setTextColor(
142 | ContextCompat.getColor(
143 | requireContext(),
144 | R.color.red
145 | )
146 | )
147 | } else {
148 | binding.indicator.setImageResource(R.drawable.ic_positive_amount)
149 | }
150 | showPiChart()
151 |
152 | })
153 |
154 | }
155 |
156 | //To show PiChart to main card to users
157 | private fun showPiChart() {
158 | val mPieChart = binding.piechart
159 |
160 | mPieChart.addPieSlice(PieModel("Food", totalFood, ContextCompat.getColor(requireContext(), R.color.yellow)))
161 | mPieChart.addPieSlice(PieModel("Shopping", totalShopping, ContextCompat.getColor(requireContext(), R.color.lightBlue)))
162 | mPieChart.addPieSlice(PieModel("Health", totalHealth, ContextCompat.getColor(requireContext(), R.color.red)))
163 | mPieChart.addPieSlice(PieModel("Others", totalOthers, ContextCompat.getColor(requireContext(), R.color.lightBrown)))
164 | mPieChart.addPieSlice(PieModel("Transport", totalTransport, ContextCompat.getColor(requireContext(), R.color.violet)))
165 | mPieChart.addPieSlice(PieModel("Academics", totalAcademics, ContextCompat.getColor(requireContext(), R.color.green)))
166 |
167 | if (totalGoal>totalExpense){
168 | mPieChart.addPieSlice(PieModel("Left",totalGoal-(totalExpense.toFloat()) , ContextCompat.getColor(requireContext(), R.color.background_deep)))
169 | }
170 |
171 | mPieChart.startAnimation()
172 |
173 | }
174 |
175 |
176 | //navigationDrawer
177 | private fun navigationDrawer() {
178 | navigationView.bringToFront()
179 | binding.drawerMenu.setOnClickListener{
180 | if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
181 | drawerLayout.closeDrawer(GravityCompat.START)
182 | } else {
183 | drawerLayout.openDrawer(GravityCompat.START)
184 | }
185 | }
186 |
187 | requireActivity()
188 | .onBackPressedDispatcher
189 | .addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
190 | override fun handleOnBackPressed() {
191 | if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
192 | drawerLayout.closeDrawer(GravityCompat.START)
193 | }else {
194 | requireActivity().finish()
195 | }
196 | }
197 | }
198 | )
199 |
200 | }
201 |
202 | fun showOnBoarding(){
203 | MaterialTapTargetPrompt.Builder(requireActivity())
204 | .setTarget(binding.addNew)
205 | .setPrimaryText("Hey Click Me!!")
206 | .setFocalRadius(100.0f)
207 | .setSecondaryText("Good to go... Add your first Transaction by Clicking on this Add Button")
208 | .setBackButtonDismissEnabled(true)
209 | .setPromptStateChangeListener{prompt, state ->
210 | if(state == MaterialTapTargetPrompt.STATE_FOCAL_PRESSED || state == MaterialTapTargetPrompt.STATE_NON_FOCAL_PRESSED){
211 | val editor: SharedPreferences.Editor = userDetails.edit()
212 | editor.putBoolean("ShowedOnboardingDashboard", true)
213 | editor.apply()
214 | }
215 | }
216 | .show()
217 |
218 | }
219 |
220 |
221 |
222 | }
223 |
224 |
225 |
--------------------------------------------------------------------------------
/app/src/main/java/com/rishav/buckoid/fragments/TransactionDetails.kt:
--------------------------------------------------------------------------------
1 | package com.rishav.buckoid.fragments
2 |
3 | import android.annotation.SuppressLint
4 | import android.os.Bundle
5 | import androidx.fragment.app.Fragment
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import android.widget.Button
10 | import androidx.activity.OnBackPressedCallback
11 | import androidx.core.content.ContextCompat
12 | import androidx.fragment.app.viewModels
13 | import androidx.navigation.Navigation
14 | import androidx.navigation.fragment.navArgs
15 | import com.rishav.buckoid.R
16 | import com.rishav.buckoid.ViewModel.TransactionViewModel
17 | import com.rishav.buckoid.databinding.FragmentTransactionDetailsBinding
18 | import com.google.android.material.bottomnavigation.BottomNavigationView
19 | import com.google.android.material.bottomsheet.BottomSheetDialog
20 |
21 | class TransactionDetails : Fragment() {
22 |
23 | val transaction by navArgs()
24 | private val viewModel: TransactionViewModel by viewModels()
25 | lateinit var binding: FragmentTransactionDetailsBinding
26 | @SuppressLint("SetTextI18n")
27 | override fun onCreateView(
28 | inflater: LayoutInflater, container: ViewGroup?,
29 | savedInstanceState: Bundle?
30 | ): View {
31 | // Inflate the layout for this fragment
32 | activity?.window?.statusBarColor = ContextCompat.getColor(requireActivity(), R.color.background)
33 | binding = FragmentTransactionDetailsBinding.inflate(inflater, container, false)
34 |
35 | val bottomNav: BottomNavigationView = requireActivity().findViewById(R.id.bottomNavigation)
36 | bottomNav.visibility = View.GONE
37 |
38 | binding.title.text = transaction.data.title
39 | binding.amount.text= "₹${transaction.data.amount}"
40 | binding.category.text = transaction.data.category
41 | binding.date.text = transaction.data.date
42 | binding.note.text = transaction.data.note
43 |
44 | binding.back.setOnClickListener {
45 | if(transaction.fragment == "Dashboard"){
46 | Navigation.findNavController(binding.root).navigate(R.id.action_transactionDetails_to_dashboard2)
47 | }else if(transaction.fragment == "AllTransactions"){
48 | Navigation.findNavController(binding.root).navigate(R.id.action_transactionDetails_to_transactions)
49 | }else{
50 | Navigation.findNavController(binding.root).navigate(R.id.action_transactionDetails_to_dashboard2)
51 | }
52 | }
53 | requireActivity()
54 | .onBackPressedDispatcher
55 | .addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
56 | override fun handleOnBackPressed() {
57 | if(transaction.fragment == "Dashboard"){
58 | Navigation.findNavController(binding.root).navigate(R.id.action_transactionDetails_to_dashboard2)
59 | }else if(transaction.fragment == "AllTransactions"){
60 | Navigation.findNavController(binding.root).navigate(R.id.action_transactionDetails_to_transactions)
61 | }else{
62 | Navigation.findNavController(binding.root).navigate(R.id.action_transactionDetails_to_dashboard2)
63 | }
64 | }
65 | }
66 | )
67 |
68 | binding.edit.setOnClickListener {
69 | val argument = TransactionDetailsDirections.actionTransactionDetailsToAddTransaction(transaction.data,true)
70 | Navigation.findNavController(binding.root).navigate(argument)
71 | }
72 | binding.delete.setOnClickListener { deleteTransaction() }
73 | return binding.root
74 | }
75 |
76 | private fun deleteTransaction() {
77 | val bottomDialog: BottomSheetDialog = BottomSheetDialog(requireContext(),R.style.bottom_dialog)
78 | bottomDialog.setContentView(R.layout.dialog_delete)
79 |
80 | val delete=bottomDialog.findViewById