From 0dfc5df8783b4bf66f7d8d4c81175b8c86f28003 Mon Sep 17 00:00:00 2001 From: oxidiert Date: Mon, 8 Sep 2025 13:04:37 +0200 Subject: [PATCH] added database feature, to check entries --- app/src/main/java/com/dano/test1/Daos.kt | 3 + .../com/dano/test1/DatabaseButtonHandler.kt | 279 ++++++++++++++++++ .../com/dano/test1/HandlerOpeningScreen.kt | 47 ++- .../res/layout/client_overview_screen.xml | 62 ++++ app/src/main/res/layout/database_screen.xml | 62 ++++ app/src/main/res/layout/opening_screen.xml | 16 +- .../layout/questionnaire_detail_screen.xml | 62 ++++ 7 files changed, 502 insertions(+), 29 deletions(-) create mode 100644 app/src/main/java/com/dano/test1/DatabaseButtonHandler.kt create mode 100644 app/src/main/res/layout/client_overview_screen.xml create mode 100644 app/src/main/res/layout/database_screen.xml create mode 100644 app/src/main/res/layout/questionnaire_detail_screen.xml diff --git a/app/src/main/java/com/dano/test1/Daos.kt b/app/src/main/java/com/dano/test1/Daos.kt index 2e25538..d7ac85e 100644 --- a/app/src/main/java/com/dano/test1/Daos.kt +++ b/app/src/main/java/com/dano/test1/Daos.kt @@ -28,6 +28,9 @@ interface QuestionnaireDao { @Query("SELECT * FROM questionnaires WHERE id = :id LIMIT 1") suspend fun getById(id: String): Questionnaire? + + @Query("SELECT * FROM questionnaires") + suspend fun getAll(): List // <-- NEU } @Dao diff --git a/app/src/main/java/com/dano/test1/DatabaseButtonHandler.kt b/app/src/main/java/com/dano/test1/DatabaseButtonHandler.kt new file mode 100644 index 0000000..efcc5b0 --- /dev/null +++ b/app/src/main/java/com/dano/test1/DatabaseButtonHandler.kt @@ -0,0 +1,279 @@ +package com.dano.test1 + +import android.util.Log +import android.view.View +import android.widget.* +import com.dano.test1.data.Client +import com.dano.test1.data.CompletedQuestionnaire +import com.dano.test1.data.Question +import com.dano.test1.data.Questionnaire +import kotlinx.coroutines.* +import kotlin.math.roundToInt +import com.dano.test1.R + +class DatabaseButtonHandler( + private val activity: MainActivity, + private val databaseButton: Button, + private val onClose: () -> Unit +) { + private val uiScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) + private val tag = "DatabaseButtonHandler" + + fun setup() { + databaseButton.text = "Datenbank" + databaseButton.setOnClickListener { openDatabaseScreen() } + } + + // --------------------------- + // SCREEN 1: Client-Liste + // --------------------------- + private fun openDatabaseScreen() { + activity.setContentView(R.layout.database_screen) + + val table: TableLayout = requireView(R.id.tableClients, "tableClients") + val progress: ProgressBar = requireView(R.id.progressBar, "progressBar") + val emptyView: TextView = requireView(R.id.emptyView, "emptyView") + val backButton: Button = requireView(R.id.backButton, "backButton") + + backButton.setOnClickListener { onClose() } + + progress.visibility = View.VISIBLE + emptyView.visibility = View.GONE + table.removeAllViews() + + addHeaderRow(table, listOf("#", "Client-Code")) + + uiScope.launch { + val clients: List = withContext(Dispatchers.IO) { + MyApp.database.clientDao().getAllClients() + } + + progress.visibility = View.GONE + + if (clients.isEmpty()) { + emptyView.visibility = View.VISIBLE + return@launch + } + + clients.forEachIndexed { index, client -> + addClickableRow( + table = table, + cells = listOf((index + 1).toString(), client.clientCode), + onClick = { openClientOverviewScreen(client.clientCode) } + ) + } + } + } + + // --------------------------- + // SCREEN 2: Fragebogen-Übersicht für einen Client + // --------------------------- + private fun openClientOverviewScreen(clientCode: String) { + activity.setContentView(R.layout.client_overview_screen) + + val title: TextView = requireView(R.id.titleClientOverview, "titleClientOverview") + val table: TableLayout = requireView(R.id.tableQuestionnaires, "tableQuestionnaires") + val progress: ProgressBar = requireView(R.id.progressBarClient, "progressBarClient") + val emptyView: TextView = requireView(R.id.emptyViewClient, "emptyViewClient") + val backButton: Button = requireView(R.id.backButtonClient, "backButtonClient") + + title.text = "Client: $clientCode – Fragebögen" + backButton.setOnClickListener { openDatabaseScreen() } + + progress.visibility = View.VISIBLE + emptyView.visibility = View.GONE + table.removeAllViews() + + addHeaderRow(table, listOf("#", "Fragebogen-ID", "Status")) + + uiScope.launch { + val (allQuestionnaires, completedForClient) = withContext(Dispatchers.IO) { + val qs = MyApp.database.questionnaireDao().getAll() + val done = MyApp.database.completedQuestionnaireDao().getAllForClient(clientCode) + qs to done + } + + progress.visibility = View.GONE + + if (allQuestionnaires.isEmpty()) { + emptyView.text = "Keine Fragebögen vorhanden." + emptyView.visibility = View.VISIBLE + return@launch + } + + val statusMap = completedForClient.associate { it.questionnaireId to it.isDone } + + allQuestionnaires.forEachIndexed { idx, q -> + val isDone = statusMap[q.id] ?: false + val statusText = if (isDone) "✓" else "✗" + val statusColor = if (isDone) 0xFF4CAF50.toInt() else 0xFFF44336.toInt() + + if (isDone) { + // NUR diese sind klickbar + addClickableRow( + table = table, + cells = listOf((idx + 1).toString(), q.id, statusText), + onClick = { openQuestionnaireDetailScreen(clientCode, q.id) }, + colorOverrides = mapOf(2 to statusColor) + ) + } else { + // Nicht klickbar, leicht ausgegraut + addDisabledRow( + table = table, + cells = listOf((idx + 1).toString(), q.id, statusText), + colorOverrides = mapOf(2 to statusColor) + ) + } + } + } + } + + // --------------------------- + // SCREEN 3: Fragen & Antworten zu einem Fragebogen + // --------------------------- + private fun openQuestionnaireDetailScreen(clientCode: String, questionnaireId: String) { + activity.setContentView(R.layout.questionnaire_detail_screen) + + val title: TextView = requireView(R.id.titleQuestionnaireDetail, "titleQuestionnaireDetail") + val table: TableLayout = requireView(R.id.tableQA, "tableQA") + val progress: ProgressBar = requireView(R.id.progressBarQA, "progressBarQA") + val emptyView: TextView = requireView(R.id.emptyViewQA, "emptyViewQA") + val backButton: Button = requireView(R.id.backButtonQA, "backButtonQA") + + title.text = "Client: $clientCode – Fragebogen: $questionnaireId" + backButton.setOnClickListener { openClientOverviewScreen(clientCode) } + + progress.visibility = View.VISIBLE + emptyView.visibility = View.GONE + table.removeAllViews() + + addHeaderRow(table, listOf("#", "Frage", "Antwort")) + + uiScope.launch { + val (questions, answersForClient) = withContext(Dispatchers.IO) { + val qs = MyApp.database.questionDao().getQuestionsForQuestionnaire(questionnaireId) + val ans = MyApp.database.answerDao() + .getAnswersForClientAndQuestionnaire(clientCode, questionnaireId) + qs to ans + } + + progress.visibility = View.GONE + + if (questions.isEmpty()) { + emptyView.text = "Keine Fragen vorhanden." + emptyView.visibility = View.VISIBLE + return@launch + } + + val answerMap = answersForClient.associate { it.questionId to it.answerValue } + + questions.forEachIndexed { idx, q: Question -> + val qText = q.question.takeIf { it.isNotBlank() } ?: q.questionId + val aText = answerMap[q.questionId]?.takeIf { it.isNotBlank() } ?: "—" + addRow(table, listOf((idx + 1).toString(), qText, aText)) + } + } + } + + // --------------------------- + // UI-Helfer + // --------------------------- + private fun addHeaderRow(table: TableLayout, labels: List) { + val row = TableRow(activity) + labels.forEach { label -> row.addView(makeHeaderCell(label)) } + table.addView(row) + addDivider(table) + } + + private fun addRow( + table: TableLayout, + cells: List, + colorOverrides: Map = emptyMap() + ) { + val row = TableRow(activity) + cells.forEachIndexed { index, text -> + row.addView(makeBodyCell(text, colorOverrides[index])) + } + table.addView(row) + addDivider(table) + } + + private fun addClickableRow( + table: TableLayout, + cells: List, + onClick: () -> Unit, + colorOverrides: Map = emptyMap() + ) { + val row = TableRow(activity).apply { + isClickable = true + isFocusable = true + setBackgroundResource(android.R.drawable.list_selector_background) + setOnClickListener { onClick() } + } + cells.forEachIndexed { index, text -> + row.addView(makeBodyCell(text, colorOverrides[index])) + } + table.addView(row) + addDivider(table) + } + + private fun addDisabledRow( + table: TableLayout, + cells: List, + colorOverrides: Map = emptyMap() + ) { + val row = TableRow(activity).apply { + isClickable = false + isEnabled = false + alpha = 0.6f // leicht ausgegraut + } + cells.forEachIndexed { index, text -> + row.addView(makeBodyCell(text, colorOverrides[index])) + } + table.addView(row) + addDivider(table) + } + + private fun addDivider(table: TableLayout) { + val divider = View(activity) + val params = TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + dp(1) + ) + divider.layoutParams = params + divider.setBackgroundColor(0xFFDDDDDD.toInt()) + table.addView(divider) + } + + private fun makeHeaderCell(text: String): TextView = + TextView(activity).apply { + this.text = text + setPadding(dp(12), dp(10), dp(12), dp(10)) + textSize = 16f + setTypeface(typeface, android.graphics.Typeface.BOLD) + } + + private fun makeBodyCell(text: String, color: Int? = null): TextView = + TextView(activity).apply { + this.text = text + setPadding(dp(12), dp(10), dp(12), dp(10)) + textSize = 15f + color?.let { setTextColor(it) } + } + + private fun dp(value: Int): Int { + val density = activity.resources.displayMetrics.density + return (value * density).roundToInt() + } + + private fun requireView(id: Int, name: String): T { + val v = activity.findViewById(id) + if (v == null) { + val msg = "View with id '$name' not found in current layout." + Log.e(tag, msg) + Toast.makeText(activity, "Fehlende View: $name", Toast.LENGTH_LONG).show() + throw IllegalStateException(msg) + } + return v + } +} diff --git a/app/src/main/java/com/dano/test1/HandlerOpeningScreen.kt b/app/src/main/java/com/dano/test1/HandlerOpeningScreen.kt index 3f3ae41..66e5de5 100644 --- a/app/src/main/java/com/dano/test1/HandlerOpeningScreen.kt +++ b/app/src/main/java/com/dano/test1/HandlerOpeningScreen.kt @@ -22,6 +22,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) { private lateinit var editButton: Button private lateinit var uploadButton: Button private lateinit var downloadButton: Button + private lateinit var databaseButton: Button // <-- NEU private val dynamicButtons = mutableListOf