From 297825008622d9367e0bbe6800a1601a6475a6ec Mon Sep 17 00:00:00 2001 From: Spirit Date: Tue, 3 Feb 2026 23:06:21 +0000 Subject: [PATCH] feat: Complete analytics admin UI panel - Analytics toggle (enable/disable) - Event count display - Export JSON button (copies to clipboard) - Export CSV button (copies to clipboard) - Clear data button with confirmation dialog - Persist analytics enabled state in DataStore --- .../farm/hobbs/kioskbrowser/AdminActivity.kt | 71 +++++++++++++++++++ app/src/main/res/layout/activity_admin.xml | 59 +++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/app/src/main/kotlin/farm/hobbs/kioskbrowser/AdminActivity.kt b/app/src/main/kotlin/farm/hobbs/kioskbrowser/AdminActivity.kt index e5be313..6d0b8af 100644 --- a/app/src/main/kotlin/farm/hobbs/kioskbrowser/AdminActivity.kt +++ b/app/src/main/kotlin/farm/hobbs/kioskbrowser/AdminActivity.kt @@ -1,14 +1,21 @@ package farm.hobbs.kioskbrowser +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity +import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringPreferencesKey import farm.hobbs.kioskbrowser.analytics.AnalyticsManager import farm.hobbs.kioskbrowser.databinding.ActivityAdminBinding +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import android.text.InputType import android.widget.EditText @@ -69,6 +76,7 @@ class AdminActivity : AppCompatActivity() { setContentView(binding.root) loadCurrentSettings() + setupAnalyticsUI() binding.btnSave.setOnClickListener { saveSettings() @@ -83,6 +91,69 @@ class AdminActivity : AppCompatActivity() { finishAffinity() } } + + private fun setupAnalyticsUI() { + // Load current analytics state + updateAnalyticsStats() + + // Analytics toggle + binding.switchAnalytics.isChecked = analytics.enabled + binding.switchAnalytics.setOnCheckedChangeListener { _, isChecked -> + analytics.enabled = isChecked + CoroutineScope(Dispatchers.IO).launch { + dataStore.edit { prefs -> + prefs[booleanPreferencesKey("analytics_enabled")] = isChecked + } + } + } + + // Export JSON + binding.btnExportJson.setOnClickListener { + CoroutineScope(Dispatchers.Main).launch { + val json = analytics.exportToJson() + copyToClipboard("Analytics JSON", json) + Toast.makeText(this@AdminActivity, "JSON copied to clipboard", Toast.LENGTH_SHORT).show() + } + } + + // Export CSV + binding.btnExportCsv.setOnClickListener { + CoroutineScope(Dispatchers.Main).launch { + val csv = analytics.exportToCsv() + copyToClipboard("Analytics CSV", csv) + Toast.makeText(this@AdminActivity, "CSV copied to clipboard", Toast.LENGTH_SHORT).show() + } + } + + // Clear analytics + binding.btnClearAnalytics.setOnClickListener { + AlertDialog.Builder(this) + .setTitle("Clear Analytics") + .setMessage("Delete all analytics data? This cannot be undone.") + .setPositiveButton("Delete") { _, _ -> + CoroutineScope(Dispatchers.Main).launch { + val count = analytics.clearAll() + Toast.makeText(this@AdminActivity, "Deleted $count events", Toast.LENGTH_SHORT).show() + updateAnalyticsStats() + } + } + .setNegativeButton("Cancel", null) + .show() + } + } + + private fun updateAnalyticsStats() { + CoroutineScope(Dispatchers.Main).launch { + val count = analytics.getEventCount() + binding.tvAnalyticsStats.text = "Events: $count" + } + } + + private fun copyToClipboard(label: String, text: String) { + val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText(label, text) + clipboard.setPrimaryClip(clip) + } private fun loadCurrentSettings() { runBlocking { diff --git a/app/src/main/res/layout/activity_admin.xml b/app/src/main/res/layout/activity_admin.xml index 3a195b9..970f1bd 100644 --- a/app/src/main/res/layout/activity_admin.xml +++ b/app/src/main/res/layout/activity_admin.xml @@ -69,6 +69,65 @@ android:inputType="numberPassword" /> + + + + + + + + + +