diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 56bae304b5c2e253b3592cf577d7c063e8159bc5..ff29bd341581f4d3114504c489618663fe93acb8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -66,4 +66,6 @@ dependencies { annotationProcessor("androidx.room:room-compiler:2.6.1") kapt("androidx.room:room-compiler:2.6.1") + // graph + implementation("com.github.PhilJay:MPAndroidChart:v3.1.0") } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b75a0b30d2ac9c98ea0e213662aa93828f04aba1..674a26c95b340ba6ea72cf6e1254ac1d0ac428a7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ android:required="false" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> @@ -31,15 +32,13 @@ android:screenOrientation="portrait" /> <activity android:name=".MainActivity" - android:exported="false" - android:screenOrientation="portrait" /> + android:exported="false" /> <activity android:name=".SplashActivity" android:exported="true" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> @@ -47,6 +46,13 @@ android:name=".services.JWTExpiry" android:enabled="true" android:exported="false" /> + <receiver + android:name=".services.RandomizeTransaction" + android:enabled="true" + android:exported="false"> + <intent-filter> + <action android:name="com.example.bondoman.services.RandomizeTransaction" /> + </intent-filter> + </receiver> </application> - </manifest> \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/GraphFragment.kt b/app/src/main/java/com/example/bondoman/GraphFragment.kt index dfe6439e3aada5ca058fe7251284fd5fec4416ce..39756ce0696417c9e03e1b6b92a31fec426ba7d0 100644 --- a/app/src/main/java/com/example/bondoman/GraphFragment.kt +++ b/app/src/main/java/com/example/bondoman/GraphFragment.kt @@ -1,19 +1,56 @@ package com.example.bondoman + import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import androidx.navigation.fragment.findNavController +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.data.PieData +import com.github.mikephil.charting.data.PieDataSet +import com.github.mikephil.charting.data.PieEntry + +class GraphFragment : Fragment() { -class GraphFragment: Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - val navController = findNavController() - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_grafik, container, false) + val view = inflater.inflate(R.layout.fragment_grafik, container, false) + val pieChart: PieChart = view.findViewById(R.id.pieChart) + + // Dummy data + val income = 5000f + val outcome = 3000f + + val entries = ArrayList<PieEntry>() + entries.add(PieEntry(income, "Income")) + entries.add(PieEntry(outcome, "Outcome")) + + val dataSet = PieDataSet(entries, "Transaction Summary") + + val colors = ArrayList<Int>() + colors.add(resources.getColor(R.color.colorIncome)) + colors.add(resources.getColor(R.color.colorOutcome)) + dataSet.colors = colors + dataSet.valueTextSize = 24f + dataSet.valueTextColor = resources.getColor(R.color.text_graph) + + + val data = PieData(dataSet) + + pieChart.data = data + + pieChart.description.isEnabled = false + + pieChart.setHoleColor(android.R.color.transparent) + + val legend = pieChart.legend + legend.isEnabled = false + + pieChart.invalidate() + + return view } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/example/bondoman/LoginActivity.kt b/app/src/main/java/com/example/bondoman/LoginActivity.kt index 65bddea00f70e36c7783ce9aca81083c9af12ae1..46560ff0b1ee0e10f6a3565a609e9f614f22602b 100644 --- a/app/src/main/java/com/example/bondoman/LoginActivity.kt +++ b/app/src/main/java/com/example/bondoman/LoginActivity.kt @@ -1,6 +1,5 @@ package com.example.bondoman - import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button @@ -11,17 +10,16 @@ import android.widget.Toast import android.annotation.SuppressLint import android.util.Log import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch -import kotlinx.coroutines.DelicateCoroutinesApi import com.example.bondoman.models.LoginRequest import com.example.bondoman.utils.RetrofitInstance +import kotlinx.coroutines.CoroutineScope import org.json.JSONException import org.json.JSONObject class LoginActivity : AppCompatActivity() { @SuppressLint("CommitPrefEdits") - @OptIn(DelicateCoroutinesApi::class) +// @OptIn(DelicateCoroutinesApi::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) @@ -36,10 +34,8 @@ class LoginActivity : AppCompatActivity() { val email = "13521010@std.stei.itb.ac.id" val password = "password_13521010" - GlobalScope.launch(Dispatchers.Main) { + CoroutineScope(Dispatchers.IO).launch { try { - Log.d("LoginActivity", "Email: $email") - Log.d("LoginActivity", "Password: $password") val response = RetrofitInstance.api.login(LoginRequest(email, password)) if (response.isSuccessful) { val token = response.body()?.token diff --git a/app/src/main/java/com/example/bondoman/LogoutFragment.kt b/app/src/main/java/com/example/bondoman/LogoutFragment.kt index 40daa4ad6f016b637c950568032f9bf4fe2e90c6..2861f8e5d055e30495ee65df4e2fc49882b0fa6e 100644 --- a/app/src/main/java/com/example/bondoman/LogoutFragment.kt +++ b/app/src/main/java/com/example/bondoman/LogoutFragment.kt @@ -7,6 +7,8 @@ import android.view.ViewGroup import android.widget.Button import androidx.fragment.app.Fragment import android.content.Intent +import android.widget.EditText +import com.example.bondoman.services.RandomizeTransaction class LogoutFragment : Fragment() { @@ -19,6 +21,16 @@ class LogoutFragment : Fragment() { view.findViewById<Button>(R.id.logoutButton).setOnClickListener { logout() } + + view.findViewById<Button>(R.id.randomButton).setOnClickListener { + val listRandomText = listOf("MacBook Pro", "MacBook Air", "Mac Mini", "Mac Pro", "iMac") + val randomText = listRandomText.random() + + val randomizeTransactionIntent = Intent(requireContext(), RandomizeTransaction::class.java) + randomizeTransactionIntent.putExtra("transactionName", randomText) + randomizeTransactionIntent.setAction("com.example.bondoman.services.RandomizeTransaction") + requireContext().sendBroadcast(randomizeTransactionIntent) + } return view } @@ -36,4 +48,8 @@ class LogoutFragment : Fragment() { editor.clear() editor.apply() } + + fun updateEditText(randomText: String?) { + view?.findViewById<EditText>(R.id.transactionName)?.setText(randomText) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/MainActivity.kt b/app/src/main/java/com/example/bondoman/MainActivity.kt index 5842ec038131f88dd1238a7dedf55e3dba04f173..5089f388a98dfb75324d8a9beeffd21fa725c251 100644 --- a/app/src/main/java/com/example/bondoman/MainActivity.kt +++ b/app/src/main/java/com/example/bondoman/MainActivity.kt @@ -15,29 +15,43 @@ import androidx.navigation.NavController import androidx.navigation.Navigation import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment +import com.example.bondoman.services.JWTExpiry +import android.widget.ImageButton +import android.widget.Toast +import androidx.core.content.ContextCompat +import androidx.lifecycle.lifecycleScope import com.example.bondoman.services.JWTExpiry +import androidx.navigation.findNavController +import androidx.navigation.fragment.NavHostFragment +import com.example.bondoman.services.ConnectivityObserver +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import com.example.bondoman.services.NetworkSensing class MainActivity : AppCompatActivity() { + private lateinit var service: Intent + private lateinit var networkSensing: NetworkSensing private lateinit var service: Intent private lateinit var transactionButton: ImageButton private lateinit var graphButton: ImageButton private lateinit var settingButton: ImageButton private lateinit var scanButton: ImageButton private lateinit var navController: NavController + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) service = Intent(this, JWTExpiry::class.java) startService(service) -// supportFragmentManager.beginTransaction() -// .replace(R.id.fragment_container, LogoutFragment()) -// .commit() + networkSensing = NetworkSensing(this) val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment val toolbarButton = findViewById<ImageButton>(R.id.toolbar_back_button) navController = navHostFragment.navController val fragmentManager: FragmentManager = supportFragmentManager + val navController = navHostFragment.navController + transactionButton = findViewById(R.id.transaction_button) transactionButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.navbar_transaction_selector)) transactionButton.isSelected = true @@ -84,6 +98,19 @@ class MainActivity : AppCompatActivity() { navbar.visibility = View.VISIBLE } } + networkSensing.observe() + .onEach { state -> + when (state) { + ConnectivityObserver.NetworkState.CONNECTED -> { + Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show() + } + ConnectivityObserver.NetworkState.DISCONNECTED -> { + Toast.makeText(this, "Disconnected", Toast.LENGTH_SHORT).show() + } + } + } + .launchIn(lifecycleScope) + } override fun onSupportNavigateUp(): Boolean { val navController = findNavController(R.id.nav_host_fragment) diff --git a/app/src/main/java/com/example/bondoman/services/ConnectivityObserver.kt b/app/src/main/java/com/example/bondoman/services/ConnectivityObserver.kt new file mode 100644 index 0000000000000000000000000000000000000000..24af286cca655ee8ab6f8e70e78f5611e9c70a18 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/services/ConnectivityObserver.kt @@ -0,0 +1,11 @@ +package com.example.bondoman.services + +import kotlinx.coroutines.flow.Flow + +interface ConnectivityObserver { + fun observe() : Flow<NetworkState> + + enum class NetworkState { + CONNECTED, DISCONNECTED + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/services/JWTExpiry.kt b/app/src/main/java/com/example/bondoman/services/JWTExpiry.kt index 1a79e54c4da5d152044c812ab7d204ec239a1109..30273fb3b19c7494a2ab0fa35c37a4c1f520f1f8 100644 --- a/app/src/main/java/com/example/bondoman/services/JWTExpiry.kt +++ b/app/src/main/java/com/example/bondoman/services/JWTExpiry.kt @@ -65,10 +65,6 @@ class JWTExpiry : Service() { Log.e("JWTExpiry", "HTTP Exception: ${e.message()}") redirectToLogin() break - } catch (e: Throwable) { - Log.e("JWTExpiry", "Error: ${e.message}") - redirectToLogin() - break } } } diff --git a/app/src/main/java/com/example/bondoman/services/NetworkSensing.kt b/app/src/main/java/com/example/bondoman/services/NetworkSensing.kt new file mode 100644 index 0000000000000000000000000000000000000000..466223a2da015006752a7793791bf4f48ae3fdf2 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/services/NetworkSensing.kt @@ -0,0 +1,30 @@ +package com.example.bondoman.services + +import android.content.Context +import android.net.ConnectivityManager +import kotlinx.coroutines.flow.Flow +import com.example.bondoman.services.ConnectivityObserver.NetworkState +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import android.net.Network + +class NetworkSensing (private val context: Context) : ConnectivityObserver { + + private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + override fun observe(): Flow<NetworkState> { + return callbackFlow { + val networkCallback = object : ConnectivityManager.NetworkCallback() { + override fun onAvailable(network: Network) { + trySend(NetworkState.CONNECTED) + } + + override fun onLost(network: Network) { + trySend(NetworkState.DISCONNECTED) + } + } + connectivityManager.registerDefaultNetworkCallback(networkCallback) + awaitClose { connectivityManager.unregisterNetworkCallback(networkCallback) } + }.distinctUntilChanged() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/services/RandomizeTransaction.kt b/app/src/main/java/com/example/bondoman/services/RandomizeTransaction.kt new file mode 100644 index 0000000000000000000000000000000000000000..9f0e0539e4070e5664382cd71802012630ddd8a6 --- /dev/null +++ b/app/src/main/java/com/example/bondoman/services/RandomizeTransaction.kt @@ -0,0 +1,27 @@ + package com.example.bondoman.services + + import android.content.BroadcastReceiver + import android.content.Context + import android.content.Intent + import android.os.Handler + import android.os.Looper + import android.util.Log + import android.widget.EditText + import androidx.appcompat.app.AppCompatActivity + import com.example.bondoman.LogoutFragment + import com.example.bondoman.R + + class RandomizeTransaction : BroadcastReceiver() { + private var text: String = "" + override fun onReceive(context: Context?, intent: Intent?) { + text = intent?.getStringExtra("transactionName").toString() + + Log.d("BroadcastRandomizeTransaction", "Random text: $text") + +// val activity = context as? AppCompatActivity +// activity?.runOnUiThread { +// val fragment = activity.supportFragmentManager.findFragmentById(R.id.fragment_container) as? LogoutFragment +// fragment?.updateEditText(randomText) +// } + } + } \ No newline at end of file diff --git a/app/src/main/res/layout-land/fragment_grafik.xml b/app/src/main/res/layout-land/fragment_grafik.xml new file mode 100644 index 0000000000000000000000000000000000000000..7b3764dfc0084e56be18792d0cddd1d289e20d37 --- /dev/null +++ b/app/src/main/res/layout-land/fragment_grafik.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#000113"> + + <com.github.mikephil.charting.charts.PieChart + android:id="@+id/pieChart" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginBottom="16dp"/> + +</RelativeLayout> diff --git a/app/src/main/res/layout/fragment_grafik.xml b/app/src/main/res/layout/fragment_grafik.xml index 8a4c372a4dff0e20a6b38578700ab1b884436391..7b3764dfc0084e56be18792d0cddd1d289e20d37 100644 --- a/app/src/main/res/layout/fragment_grafik.xml +++ b/app/src/main/res/layout/fragment_grafik.xml @@ -1,16 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - xmlns:app="http://schemas.android.com/apk/res-auto"> + android:background="#000113"> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - android:text="@string/graph_button_description"> - </TextView> + <com.github.mikephil.charting.charts.PieChart + android:id="@+id/pieChart" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginBottom="16dp"/> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file +</RelativeLayout> diff --git a/app/src/main/res/layout/fragment_logout.xml b/app/src/main/res/layout/fragment_logout.xml index bbb6942ac6f8fcf02210b53a8fda2923d110b166..8d9e9f814a0702d41a148ca007ec676507131089 100644 --- a/app/src/main/res/layout/fragment_logout.xml +++ b/app/src/main/res/layout/fragment_logout.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" ?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" @@ -6,7 +6,25 @@ <Button android:id="@+id/logoutButton" - android:layout_width="wrap_content" + android:layout_width="200dp" android:layout_height="wrap_content" - android:text="@string/logout"/> + android:text="@string/logout" /> + + <EditText + android:id="@+id/transactionName" + android:layout_width="200dp" + android:layout_height="wrap_content" + android:layout_below="@+id/logoutButton" + android:layout_marginTop="20dp" + android:autofillHints="" + android:hint="@string/transaction_name" + android:inputType="text" /> + + <Button + android:id="@+id/randomButton" + android:layout_width="200dp" + android:layout_height="wrap_content" + android:text="@string/randomize" + android:layout_below="@+id/transactionName" + android:layout_marginTop="20dp" /> </RelativeLayout> \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f97cf6dffd64c6c08a9f0cc08f90558d282fac72..dfffc97b3a6fc643cf4a61b1c6e7ee9f1fc02665 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -11,4 +11,7 @@ <color name="light_purple">#9290C3</color> <color name="light_grey">#EAEAEA</color> <color name="text_grey">#475569</color> + <color name="colorIncome">#1B1A55</color> + <color name="colorOutcome">#9290C3</color> + <color name="text_graph">#5852EE</color> </resources> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0b2acbf6008b4ca603433365e5dc0463897cd677..5de3deffd40fa7984561a376fdd94b7612db0aae 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4,6 +4,8 @@ <string name="hint_input_email_address">Input Email Address</string> <string name="hint_input_password">Input Password</string> <string name="logout">Logout</string> + <string name="transaction_name">Transaction Name</string> + <string name="randomize">Randomize</string> <string name="transaction_button_description">Transaksi</string> <string name="graph_button_description">Grafik</string> <string name="setting_button_description">Pengaturan</string> diff --git a/settings.gradle.kts b/settings.gradle.kts index a8ccf6044d00204dc748e81f126373ec02d71ad2..e76ad3ee0278e4805ffdae7c49fc18bef57de286 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,6 +3,7 @@ pluginManagement { google() mavenCentral() gradlePluginPortal() + maven("https://jitpack.io") } } dependencyResolutionManagement { @@ -10,6 +11,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + maven("https://jitpack.io") } }