Add sleep tracking, statistics module and backup features
Features: - Sleep tracking with timer and manual duration input - Statistics module with 5 tabs (daily summary, feeding, diapers, sleep, growth) - Export/Import backup functionality in settings - Complete German, French and Italian translations
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
package it.danieleverducci.lunatracker.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import it.danieleverducci.lunatracker.R
|
||||
import it.danieleverducci.lunatracker.StatisticsActivity
|
||||
import utils.DailySummary
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
class DailySummaryFragment : Fragment() {
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
return inflater.inflate(R.layout.fragment_daily_summary, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
updateUI(view)
|
||||
}
|
||||
|
||||
private fun updateUI(view: View) {
|
||||
val activity = activity as? StatisticsActivity ?: return
|
||||
val calculator = activity.getCalculator()
|
||||
val period = activity.getSelectedPeriod()
|
||||
|
||||
// Get today's summary and average for comparison
|
||||
val todaySummary = calculator.getTodaySummary()
|
||||
val feedingStats = calculator.getFeedingStats(period)
|
||||
val sleepStats = calculator.getSleepStats(period)
|
||||
val diaperStats = calculator.getDiaperStats(period)
|
||||
|
||||
// Date header
|
||||
val dateFormat = SimpleDateFormat("EEEE, d MMMM", Locale.getDefault())
|
||||
view.findViewById<TextView>(R.id.date_header).text = dateFormat.format(Date())
|
||||
|
||||
// Bottle summary
|
||||
val bottleSummary = view.findViewById<TextView>(R.id.bottle_summary)
|
||||
val bottleProgress = view.findViewById<ProgressBar>(R.id.bottle_progress)
|
||||
val avgBottle = feedingStats.avgBottleMlPerDay.toInt()
|
||||
bottleSummary.text = "${todaySummary.totalBottleMl} ml (${todaySummary.bottleCount}×) | Ø $avgBottle ml"
|
||||
if (avgBottle > 0) {
|
||||
bottleProgress.max = (avgBottle * 1.5).toInt()
|
||||
bottleProgress.progress = todaySummary.totalBottleMl
|
||||
}
|
||||
|
||||
// Breastfeeding summary
|
||||
val breastfeedingContainer = view.findViewById<LinearLayout>(R.id.breastfeeding_container)
|
||||
val breastfeedingSummary = view.findViewById<TextView>(R.id.breastfeeding_summary)
|
||||
val breastfeedingProgress = view.findViewById<ProgressBar>(R.id.breastfeeding_progress)
|
||||
|
||||
if (todaySummary.breastfeedingCount > 0 || feedingStats.avgBreastfeedingMinPerDay > 0) {
|
||||
breastfeedingContainer.visibility = View.VISIBLE
|
||||
val avgBf = feedingStats.avgBreastfeedingMinPerDay.toInt()
|
||||
breastfeedingSummary.text = "${todaySummary.totalBreastfeedingMin} min (${todaySummary.breastfeedingCount}×) | Ø $avgBf min"
|
||||
if (avgBf > 0) {
|
||||
breastfeedingProgress.max = (avgBf * 1.5).toInt()
|
||||
breastfeedingProgress.progress = todaySummary.totalBreastfeedingMin
|
||||
}
|
||||
} else {
|
||||
breastfeedingContainer.visibility = View.GONE
|
||||
}
|
||||
|
||||
// Sleep summary
|
||||
val sleepSummary = view.findViewById<TextView>(R.id.sleep_summary)
|
||||
val sleepProgress = view.findViewById<ProgressBar>(R.id.sleep_progress)
|
||||
val avgSleepMin = sleepStats.avgSleepMinPerDay.toInt()
|
||||
val todaySleepHours = todaySummary.totalSleepMin / 60f
|
||||
val avgSleepHours = avgSleepMin / 60f
|
||||
sleepSummary.text = String.format(Locale.getDefault(), "%.1f h (%d×) | Ø %.1f h",
|
||||
todaySleepHours, todaySummary.sleepCount, avgSleepHours)
|
||||
if (avgSleepMin > 0) {
|
||||
sleepProgress.max = (avgSleepMin * 1.5).toInt()
|
||||
sleepProgress.progress = todaySummary.totalSleepMin
|
||||
}
|
||||
|
||||
// Diaper summaries
|
||||
val pooSummary = view.findViewById<TextView>(R.id.poo_summary)
|
||||
val peeSummary = view.findViewById<TextView>(R.id.pee_summary)
|
||||
pooSummary.text = String.format(Locale.getDefault(), "%d× | Ø %.1f",
|
||||
todaySummary.diaperPooCount, diaperStats.avgPooPerDay)
|
||||
peeSummary.text = String.format(Locale.getDefault(), "%d× | Ø %.1f",
|
||||
todaySummary.diaperPeeCount, diaperStats.avgPeePerDay)
|
||||
|
||||
// Health card (weight/temperature)
|
||||
val healthCard = view.findViewById<LinearLayout>(R.id.health_card)
|
||||
val weightSummary = view.findViewById<TextView>(R.id.weight_summary)
|
||||
val tempSummary = view.findViewById<TextView>(R.id.temperature_summary)
|
||||
|
||||
if (todaySummary.latestWeight != null || todaySummary.latestTemperature != null) {
|
||||
healthCard.visibility = View.VISIBLE
|
||||
|
||||
if (todaySummary.latestWeight != null) {
|
||||
val weightKg = todaySummary.latestWeight / 1000f
|
||||
weightSummary.text = "⚖️ ${String.format(Locale.getDefault(), "%.2f kg", weightKg)}"
|
||||
weightSummary.visibility = View.VISIBLE
|
||||
} else {
|
||||
weightSummary.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (todaySummary.latestTemperature != null) {
|
||||
val tempC = todaySummary.latestTemperature / 10f
|
||||
tempSummary.text = "🌡️ ${String.format(Locale.getDefault(), "%.1f °C", tempC)}"
|
||||
tempSummary.visibility = View.VISIBLE
|
||||
} else {
|
||||
tempSummary.visibility = View.GONE
|
||||
}
|
||||
} else {
|
||||
healthCard.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user