Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,12 @@ android {
viewBinding true
}

externalNativeBuild {
cmake {
path file("src/main/cpp/CMakeLists.txt")
}
}
ndkVersion '29.0.14033849'
// externalNativeBuild {
// cmake {
// path file("src/main/cpp/CMakeLists.txt")
// }
// }
// ndkVersion '29.0.14033849'

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,137 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.piramalswasthya.sakhi.R
import org.piramalswasthya.sakhi.databinding.FragmentDashboardBinding
import org.piramalswasthya.sakhi.ui.home_activity.HomeActivity

@AndroidEntryPoint
class DashboardFragment : Fragment() {

private var _binding: FragmentDashboardBinding? = null
private val binding get() = _binding!!

private val viewModel: DashboardViewModel by viewModels()

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_dashboard, container, false)
): View {
_binding = FragmentDashboardBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

// Populate header
viewModel.currentUser?.let { user ->
binding.tvWorkerName.text = user.name
}
(activity as? HomeActivity)?.let { homeActivity ->
val villageName = homeActivity.supportActionBar?.title?.toString()
binding.tvVillageName.text = if (!villageName.isNullOrEmpty()) "Village: $villageName" else ""
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// Set up static card labels & icons once
setupCard(
binding.cardHouseholds,
label = getString(R.string.all_household),
iconRes = R.drawable.ic__hh
)
setupCard(
binding.cardBeneficiaries,
label = getString(R.string.beneficiaries),
iconRes = R.drawable.ic__ben
)
setupCard(
binding.cardMale,
label = getString(R.string.male),
iconRes = R.drawable.ic_male
)
setupCard(
binding.cardFemale,
label = getString(R.string.female),
iconRes = R.drawable.ic_female
)
setupCard(
binding.cardPregnant,
label = getString(R.string.pregnant_women),
iconRes = R.drawable.ic__maternal_health
)
setupCard(
binding.cardHighRisk,
label = getString(R.string.hrp_cases),
iconRes = R.drawable.ic__hrp
)
setupCard(
binding.cardDelivered,
label = getString(R.string.delivery_outcome),
iconRes = R.drawable.ic__delivery_outcome
)

// Observe stats
viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {

launch {
viewModel.householdCount.collect { count ->
setCount(binding.cardHouseholds, count)
}
}

launch {
viewModel.stats.collect { stats ->
setCount(binding.cardBeneficiaries, stats.totalBeneficiaries)
setCount(binding.cardMale, stats.maleBeneficiaries)
setCount(binding.cardFemale, stats.femaleBeneficiaries)
setCount(binding.cardPregnant, stats.pregnantWomen)
setCount(binding.cardHighRisk, stats.highRiskWomen)
setCount(binding.cardDelivered, stats.deliveredWomen)

// Pending sync badge
if (stats.pendingSync > 0) {
binding.llSyncBadge.visibility = View.VISIBLE
binding.tvPendingSync.text = requireContext().resources.getQuantityString(
R.plurals.pending_sync, stats.pendingSync, stats.pendingSync
)
} else {
binding.llSyncBadge.visibility = View.GONE
}
}
}
}
}
}

private fun setupCard(cardView: View, label: String, iconRes: Int) {
cardView.findViewById<TextView>(R.id.tv_stat_label).text = label
cardView.findViewById<ImageView>(R.id.iv_stat_icon).setImageResource(iconRes)
}

private fun setCount(cardView: View, count: Int) {
cardView.findViewById<TextView>(R.id.tv_stat_count).text = count.toString()
}

override fun onStart() {
super.onStart()
(activity as? HomeActivity)?.let {
it.updateActionBar(R.drawable.ic_dashboard, getString(R.string.dashboard))
it.setHomeMenuItemVisibility(true)
}
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,70 @@
package org.piramalswasthya.sakhi.ui.home_activity.dashboard

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import org.piramalswasthya.sakhi.database.room.InAppDb
import org.piramalswasthya.sakhi.database.shared_preferences.PreferenceDao
import javax.inject.Inject

class DashboardViewModel : ViewModel() {
// TODO: Implement the ViewModel
data class DashboardStats(
val totalBeneficiaries: Int = 0,
val pregnantWomen: Int = 0,
val highRiskWomen: Int = 0,
val deliveredWomen: Int = 0,
val pendingSync: Int = 0,
val maleBeneficiaries: Int = 0,
val femaleBeneficiaries: Int = 0,
)

@HiltViewModel
class DashboardViewModel @Inject constructor(
private val database: InAppDb,
private val pref: PreferenceDao,
) : ViewModel() {

private val villageId: Int
get() = pref.getLocationRecord()?.village?.id ?: 0

val currentUser = pref.getLoggedInUser()

val householdCount: StateFlow<Int> =
database.householdDao.getAllHouseholdsCount(villageId)
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), 0)

val stats: StateFlow<DashboardStats> = combine(
database.benDao.getAllBenCount(villageId),
database.benDao.getAllPregnancyWomenListCount(villageId),
database.benDao.getHighRiskWomenCount(villageId),
database.benDao.getAllDeliveredWomenListCount(villageId),
database.benDao.getAllBenGenderCount(villageId, "MALE"),
database.benDao.getAllBenGenderCount(villageId, "FEMALE"),
database.benDao.getUnProcessedRecordCount(),
) { values ->
val total = values[0] as Int
val pregnant = values[1] as Int
val highRisk = values[2] as Int
val delivered = values[3] as Int
val male = values[4] as Int
val female = values[5] as Int
val unsynced = values[6] as Int

DashboardStats(
totalBeneficiaries = total,
pregnantWomen = pregnant,
highRiskWomen = highRisk,
deliveredWomen = delivered,
maleBeneficiaries = male,
femaleBeneficiaries = female,
pendingSync = unsynced,
)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = DashboardStats()
)
}
21 changes: 8 additions & 13 deletions app/src/main/java/org/piramalswasthya/sakhi/utils/KeyUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,22 @@
System.loadLibrary(NATIVE_JNI_LIB_NAME)
} catch (e: UnsatisfiedLinkError) {
Timber.tag("KeyUtils").e(e, "Failed to load native library")
throw RuntimeException("Failed to load native library: $NATIVE_JNI_LIB_NAME")
}

}

fun encryptedPassKey(): String = "dummy_key"

external fun encryptedPassKey(): String

external fun abhaClientSecret(): String

external fun abhaClientID(): String

external fun baseTMCUrl(): String
fun abhaClientSecret(): String = "dummy_secret"

external fun baseAbhaUrl(): String
fun abhaClientID(): String = "dummy_client"

external fun abhaTokenUrl(): String
fun baseTMCUrl(): String = "https://example.com/"

Check failure on line 33 in app/src/main/java/org/piramalswasthya/sakhi/utils/KeyUtils.kt

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "https://example.com/" 5 times.

See more on https://sonarcloud.io/project/issues?id=PSMRI_FLW-Mobile-App&issues=AZ4xBQh0dn0D8X7NrCRt&open=AZ4xBQh0dn0D8X7NrCRt&pullRequest=462

external fun abhaAuthUrl(): String
fun baseAbhaUrl(): String = "https://example.com/"

external fun chatUrl(): String
fun abhaTokenUrl(): String = "https://example.com/"

fun abhaAuthUrl(): String = "https://example.com/"

fun chatUrl(): String = "https://example.com/"
}
6 changes: 6 additions & 0 deletions app/src/main/res/drawable/bg_sync_badge.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#33FFFFFF" />
<corners android:radius="20dp" />
</shape>
Loading