finished opening screen
This commit is contained in:
2
.idea/deploymentTargetSelector.xml
generated
2
.idea/deploymentTargetSelector.xml
generated
@ -4,7 +4,7 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2025-09-19T19:11:24.523816400Z">
|
<DropdownSelection timestamp="2025-09-21T10:53:27.572746300Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\danie\.android\avd\Medium_Phone.avd" />
|
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\danie\.android\avd\Medium_Phone.avd" />
|
||||||
|
|||||||
@ -13,7 +13,7 @@ android {
|
|||||||
minSdk = 29
|
minSdk = 29
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "1.1"
|
versionName = "1.2"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "questionnaire_6_follow_up_survey.json",
|
"file": "questionnaire_6_follow_up_survey.json",
|
||||||
"showPoints": false,
|
"showPoints": true,
|
||||||
"condition": {
|
"condition": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -14,8 +14,8 @@ class EditButtonHandler(
|
|||||||
private val questionnaireFiles: Map<Button, String>,
|
private val questionnaireFiles: Map<Button, String>,
|
||||||
private val buttonPoints: MutableMap<String, Int>,
|
private val buttonPoints: MutableMap<String, Int>,
|
||||||
private val updateButtonTexts: () -> Unit,
|
private val updateButtonTexts: () -> Unit,
|
||||||
private val setButtonsEnabled: (List<Button>) -> Unit,
|
private val setButtonsEnabled: (List<Button>, Boolean) -> Unit,
|
||||||
// vor "Bearbeiten" ggf. Laden anstoßen
|
private val setUiFreeze: (Boolean) -> Unit,
|
||||||
private val triggerLoad: () -> Unit
|
private val triggerLoad: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ -38,29 +38,29 @@ class EditButtonHandler(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nutzerwunsch merken (info)
|
|
||||||
GlobalValues.LAST_CLIENT_CODE = desiredCode
|
GlobalValues.LAST_CLIENT_CODE = desiredCode
|
||||||
|
|
||||||
// Nur laden, wenn noch nicht/anders geladen
|
|
||||||
val needLoad = GlobalValues.LOADED_CLIENT_CODE?.equals(desiredCode) != true
|
val needLoad = GlobalValues.LOADED_CLIENT_CODE?.equals(desiredCode) != true
|
||||||
if (needLoad) triggerLoad()
|
if (needLoad) {
|
||||||
|
// Zwischenzustände aus dem Load-Handler unterdrücken
|
||||||
|
setUiFreeze(true)
|
||||||
|
triggerLoad()
|
||||||
|
}
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val loadedOk = waitUntilClientLoaded(desiredCode, timeoutMs = 2500, stepMs = 50)
|
val loadedOk = waitUntilClientLoaded(desiredCode, timeoutMs = 2500, stepMs = 50)
|
||||||
if (!loadedOk) {
|
if (!loadedOk) {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
Toast.makeText(activity, "Bitte den Klienten über \"Laden\" öffnen.", Toast.LENGTH_LONG).show()
|
Toast.makeText(activity, "Bitte den Klienten über \"Laden\" öffnen.", Toast.LENGTH_LONG).show()
|
||||||
|
setUiFreeze(false)
|
||||||
}
|
}
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ab hier: geladen → Bearbeiten-Logik
|
|
||||||
val completedEntries: List<CompletedQuestionnaire> =
|
val completedEntries: List<CompletedQuestionnaire> =
|
||||||
MyApp.database.completedQuestionnaireDao().getAllForClient(desiredCode)
|
MyApp.database.completedQuestionnaireDao().getAllForClient(desiredCode)
|
||||||
|
|
||||||
val completedFiles = completedEntries
|
val completedFiles = completedEntries.filter { it.isDone }.map { it.questionnaireId.lowercase() }
|
||||||
.filter { it.isDone }
|
|
||||||
.map { it.questionnaireId.lowercase() }
|
|
||||||
|
|
||||||
buttonPoints.clear()
|
buttonPoints.clear()
|
||||||
for (entry in completedEntries) {
|
for (entry in completedEntries) {
|
||||||
@ -70,21 +70,19 @@ class EditButtonHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
// nur den finalen Zustand anzeigen
|
||||||
updateButtonTexts()
|
updateButtonTexts()
|
||||||
|
|
||||||
val enabledButtons = questionnaireFiles.filter { (_, fileName) ->
|
val enabledButtons = questionnaireFiles.filter { (_, fileName) ->
|
||||||
completedFiles.any { completedId -> fileName.lowercase().contains(completedId) }
|
completedFiles.any { completedId -> fileName.lowercase().contains(completedId) }
|
||||||
}.keys.toList()
|
}.keys.toList()
|
||||||
|
setButtonsEnabled(enabledButtons, true)
|
||||||
setButtonsEnabled(enabledButtons)
|
setUiFreeze(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun waitUntilClientLoaded(expectedCode: String, timeoutMs: Long, stepMs: Long): Boolean {
|
private suspend fun waitUntilClientLoaded(expectedCode: String, timeoutMs: Long, stepMs: Long): Boolean {
|
||||||
// sofort ok, wenn bereits korrekt geladen
|
|
||||||
if (GlobalValues.LOADED_CLIENT_CODE?.equals(expectedCode) == true) return true
|
if (GlobalValues.LOADED_CLIENT_CODE?.equals(expectedCode) == true) return true
|
||||||
|
|
||||||
var waited = 0L
|
var waited = 0L
|
||||||
while (waited < timeoutMs) {
|
while (waited < timeoutMs) {
|
||||||
delay(stepMs)
|
delay(stepMs)
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
package com.dano.test1
|
package com.dano.test1
|
||||||
|
|
||||||
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import kotlinx.coroutines.*
|
import com.google.android.material.button.MaterialButton
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -22,37 +25,46 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
private lateinit var editButton: Button
|
private lateinit var editButton: Button
|
||||||
private lateinit var uploadButton: Button
|
private lateinit var uploadButton: Button
|
||||||
private lateinit var downloadButton: Button
|
private lateinit var downloadButton: Button
|
||||||
private lateinit var databaseButton: Button // <-- NEU
|
private lateinit var databaseButton: Button
|
||||||
|
|
||||||
private val dynamicButtons = mutableListOf<Button>()
|
private val dynamicButtons = mutableListOf<Button>()
|
||||||
private val questionnaireFiles = mutableMapOf<Button, String>()
|
private val questionnaireFiles = mutableMapOf<Button, String>()
|
||||||
|
|
||||||
|
private data class CardParts(
|
||||||
|
val title: TextView,
|
||||||
|
val subtitle: TextView,
|
||||||
|
val chip: TextView
|
||||||
|
)
|
||||||
|
private val cardParts = mutableMapOf<Button, CardParts>()
|
||||||
|
|
||||||
private val buttonPoints: MutableMap<String, Int> = mutableMapOf()
|
private val buttonPoints: MutableMap<String, Int> = mutableMapOf()
|
||||||
private var questionnaireEntries: List<QuestionItem.QuestionnaireEntry> = emptyList()
|
private var questionnaireEntries: List<QuestionItem.QuestionnaireEntry> = emptyList()
|
||||||
|
|
||||||
|
private var uiFreeze: Boolean = false
|
||||||
|
|
||||||
|
// Feste Standard-Randfarben
|
||||||
|
private val STROKE_ENABLED = Color.parseColor("#8C79F2") // wenn anklickbar
|
||||||
|
private val STROKE_DISABLED = Color.parseColor("#D8D3F5") // wenn nicht anklickbar
|
||||||
|
|
||||||
|
private fun t(id: String) = LanguageManager.getText(languageID, id)
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
activity.setContentView(R.layout.opening_screen)
|
activity.setContentView(R.layout.opening_screen)
|
||||||
|
|
||||||
bindViews()
|
bindViews()
|
||||||
|
|
||||||
loadQuestionnaireOrder()
|
loadQuestionnaireOrder()
|
||||||
createQuestionnaireButtons()
|
createQuestionnaireButtons()
|
||||||
restorePreviousClientCode()
|
restorePreviousClientCode()
|
||||||
|
|
||||||
setupLanguageSpinner()
|
setupLanguageSpinner()
|
||||||
setupLoadButton()
|
setupLoadButton()
|
||||||
setupSaveButton()
|
setupSaveButton()
|
||||||
setupEditButtonHandler()
|
setupEditButtonHandler()
|
||||||
setupUploadButton()
|
setupUploadButton()
|
||||||
setupDownloadButton()
|
setupDownloadButton()
|
||||||
setupDatabaseButtonHandler() // <-- NEU
|
setupDatabaseButtonHandler()
|
||||||
|
|
||||||
val dbPath = "/data/data/com.dano.test1/databases/questionnaire_database"
|
val pathExists = File("/data/data/com.dano.test1/databases/questionnaire_database").exists()
|
||||||
val pathExists = File(dbPath).exists()
|
|
||||||
updateMainButtonsState(pathExists)
|
updateMainButtonsState(pathExists)
|
||||||
|
if (pathExists && !editText.text.isNullOrBlank()) buttonLoad.performClick()
|
||||||
if (pathExists && !editText.text.isNullOrBlank()) {
|
|
||||||
buttonLoad.performClick()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindViews() {
|
private fun bindViews() {
|
||||||
@ -65,11 +77,11 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
editButton = activity.findViewById(R.id.editButton)
|
editButton = activity.findViewById(R.id.editButton)
|
||||||
uploadButton = activity.findViewById(R.id.uploadButton)
|
uploadButton = activity.findViewById(R.id.uploadButton)
|
||||||
downloadButton = activity.findViewById(R.id.downloadButton)
|
downloadButton = activity.findViewById(R.id.downloadButton)
|
||||||
databaseButton = activity.findViewById(R.id.databaseButton) // <-- NEU
|
databaseButton = activity.findViewById(R.id.databaseButton)
|
||||||
|
|
||||||
val tag = editText.tag as? String ?: ""
|
val tag = editText.tag as? String ?: ""
|
||||||
editText.hint = LanguageManager.getText(languageID, tag)
|
editText.hint = t(tag)
|
||||||
textView.text = LanguageManager.getText(languageID, "example_text")
|
textView.text = t("example_text")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadQuestionnaireOrder() {
|
private fun loadQuestionnaireOrder() {
|
||||||
@ -84,11 +96,9 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
val conditionObj = obj.optJSONObject("condition")
|
val conditionObj = obj.optJSONObject("condition")
|
||||||
val condition = parseCondition(conditionObj)
|
val condition = parseCondition(conditionObj)
|
||||||
val showPoints = obj.optBoolean("showPoints", false)
|
val showPoints = obj.optBoolean("showPoints", false)
|
||||||
|
|
||||||
QuestionItem.QuestionnaireEntry(file, condition, showPoints)
|
QuestionItem.QuestionnaireEntry(file, condition, showPoints)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (_: Exception) {
|
||||||
e.printStackTrace()
|
|
||||||
questionnaireEntries = emptyList()
|
questionnaireEntries = emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,17 +114,14 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
}
|
}
|
||||||
return QuestionItem.Condition.AnyOf(conditions)
|
return QuestionItem.Condition.AnyOf(conditions)
|
||||||
}
|
}
|
||||||
if (conditionObj.has("alwaysAvailable")) {
|
if (conditionObj.has("alwaysAvailable") && conditionObj.optBoolean("alwaysAvailable", false)) {
|
||||||
val flag = conditionObj.optBoolean("alwaysAvailable", false)
|
return QuestionItem.Condition.AlwaysAvailable
|
||||||
if (flag) return QuestionItem.Condition.AlwaysAvailable
|
|
||||||
}
|
}
|
||||||
val requiresList = mutableListOf<String>()
|
val requiresList = mutableListOf<String>()
|
||||||
if (conditionObj.has("requiresCompleted")) {
|
if (conditionObj.has("requiresCompleted")) {
|
||||||
val reqArr = conditionObj.optJSONArray("requiresCompleted")
|
val reqArr = conditionObj.optJSONArray("requiresCompleted")
|
||||||
if (reqArr != null) {
|
if (reqArr != null) {
|
||||||
for (i in 0 until reqArr.length()) {
|
for (i in 0 until reqArr.length()) requiresList.add(reqArr.optString(i))
|
||||||
requiresList.add(reqArr.optString(i))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
conditionObj.optString("requiresCompleted")?.let { if (it.isNotBlank()) requiresList.add(it) }
|
conditionObj.optString("requiresCompleted")?.let { if (it.isNotBlank()) requiresList.add(it) }
|
||||||
}
|
}
|
||||||
@ -123,17 +130,15 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
val questionId = conditionObj.optString("questionId", null)
|
val questionId = conditionObj.optString("questionId", null)
|
||||||
val operator = conditionObj.optString("operator", null)
|
val operator = conditionObj.optString("operator", null)
|
||||||
val value = conditionObj.optString("value", null)
|
val value = conditionObj.optString("value", null)
|
||||||
val hasQuestionCheck = !questionnaire.isNullOrBlank() && !questionId.isNullOrBlank() && !operator.isNullOrBlank() && value != null
|
val hasQuestionCheck =
|
||||||
|
!questionnaire.isNullOrBlank() && !questionId.isNullOrBlank() && !operator.isNullOrBlank() && value != null
|
||||||
return when {
|
return when {
|
||||||
requiresList.isNotEmpty() && hasQuestionCheck -> {
|
requiresList.isNotEmpty() && hasQuestionCheck ->
|
||||||
QuestionItem.Condition.Combined(requiresList, QuestionItem.Condition.QuestionCondition(questionnaire!!, questionId!!, operator!!, value!!))
|
QuestionItem.Condition.Combined(requiresList, QuestionItem.Condition.QuestionCondition(questionnaire!!, questionId!!, operator!!, value!!))
|
||||||
}
|
hasQuestionCheck ->
|
||||||
hasQuestionCheck -> {
|
|
||||||
QuestionItem.Condition.QuestionCondition(questionnaire!!, questionId!!, operator!!, value!!)
|
QuestionItem.Condition.QuestionCondition(questionnaire!!, questionId!!, operator!!, value!!)
|
||||||
}
|
requiresList.isNotEmpty() ->
|
||||||
requiresList.isNotEmpty() -> {
|
|
||||||
QuestionItem.Condition.RequiresCompleted(requiresList)
|
QuestionItem.Condition.RequiresCompleted(requiresList)
|
||||||
}
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,34 +147,95 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
buttonContainer.removeAllViews()
|
buttonContainer.removeAllViews()
|
||||||
dynamicButtons.clear()
|
dynamicButtons.clear()
|
||||||
questionnaireFiles.clear()
|
questionnaireFiles.clear()
|
||||||
for ((index, entry) in questionnaireEntries.withIndex()) {
|
cardParts.clear()
|
||||||
val button = Button(activity).apply {
|
|
||||||
|
val vMargin = dp(8)
|
||||||
|
val startEnabled = mutableListOf<Button>()
|
||||||
|
|
||||||
|
questionnaireEntries.forEachIndexed { index, entry ->
|
||||||
|
val row = FrameLayout(activity).apply {
|
||||||
layoutParams = LinearLayout.LayoutParams(
|
layoutParams = LinearLayout.LayoutParams(
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
).apply { setMargins(0, 8, 0, 8) }
|
).also { it.setMargins(0, vMargin, 0, vMargin) }
|
||||||
text = "Questionnaire ${index + 1}"
|
}
|
||||||
|
|
||||||
|
val btn = MaterialButton(activity).apply {
|
||||||
|
layoutParams = FrameLayout.LayoutParams(
|
||||||
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
dp(84)
|
||||||
|
)
|
||||||
|
text = ""
|
||||||
|
isAllCaps = false
|
||||||
|
setMinimumWidth(0)
|
||||||
|
setMinimumHeight(0)
|
||||||
|
cornerRadius = dp(22)
|
||||||
|
strokeWidth = dp(1)
|
||||||
|
strokeColor = ColorStateList.valueOf(STROKE_DISABLED)
|
||||||
|
backgroundTintList = ColorStateList.valueOf(Color.WHITE)
|
||||||
|
rippleColor = ColorStateList.valueOf(Color.parseColor("#22000000"))
|
||||||
|
gravity = Gravity.START or Gravity.CENTER_VERTICAL
|
||||||
|
setPadding(dp(20), 0, dp(20), 0)
|
||||||
id = View.generateViewId()
|
id = View.generateViewId()
|
||||||
}
|
setOnClickListener {
|
||||||
buttonContainer.addView(button)
|
|
||||||
dynamicButtons.add(button)
|
|
||||||
questionnaireFiles[button] = entry.file
|
|
||||||
}
|
|
||||||
updateButtonTexts()
|
|
||||||
|
|
||||||
val alwaysButtons = questionnaireEntries.mapIndexedNotNull { idx, entry ->
|
|
||||||
val btn = dynamicButtons.getOrNull(idx)
|
|
||||||
if (entry.condition is QuestionItem.Condition.AlwaysAvailable) btn else null
|
|
||||||
}
|
|
||||||
setButtonsEnabled(alwaysButtons)
|
|
||||||
|
|
||||||
dynamicButtons.forEach { button ->
|
|
||||||
button.setOnClickListener {
|
|
||||||
GlobalValues.LAST_CLIENT_CODE = GlobalValues.LOADED_CLIENT_CODE
|
GlobalValues.LAST_CLIENT_CODE = GlobalValues.LOADED_CLIENT_CODE
|
||||||
startQuestionnaireForButton(button)
|
val fileName = questionnaireFiles[this] ?: return@setOnClickListener
|
||||||
setButtonsEnabled(dynamicButtons.filter { it == button })
|
val questionnaire = QuestionnaireGeneric(fileName)
|
||||||
|
startQuestionnaire(questionnaire)
|
||||||
|
applySetButtonsEnabled(dynamicButtons.filter { it == this }, allowCompleted = false, force = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val textColumn = LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
layoutParams = FrameLayout.LayoutParams(
|
||||||
|
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
Gravity.START or Gravity.CENTER_VERTICAL
|
||||||
|
).also { it.marginStart = dp(24) }
|
||||||
|
}
|
||||||
|
val tvTitle = TextView(activity).apply {
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
|
||||||
|
setTextColor(Color.parseColor("#2F2A49"))
|
||||||
|
setPadding(0, dp(6), 0, dp(2))
|
||||||
|
}
|
||||||
|
val tvSubtitle = TextView(activity).apply {
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f)
|
||||||
|
setTextColor(Color.parseColor("#7B7794"))
|
||||||
|
visibility = View.GONE
|
||||||
|
}
|
||||||
|
textColumn.addView(tvTitle)
|
||||||
|
textColumn.addView(tvSubtitle)
|
||||||
|
|
||||||
|
val chip = TextView(activity).apply {
|
||||||
|
setPadding(dp(14), dp(8), dp(14), dp(8))
|
||||||
|
setTextColor(Color.WHITE)
|
||||||
|
text = t("start")
|
||||||
|
setBackgroundResource(R.drawable.bg_chip_amber)
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
|
||||||
|
layoutParams = FrameLayout.LayoutParams(
|
||||||
|
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
Gravity.END or Gravity.CENTER_VERTICAL
|
||||||
|
).also { it.marginEnd = dp(16) }
|
||||||
|
}
|
||||||
|
|
||||||
|
row.addView(btn)
|
||||||
|
row.addView(textColumn)
|
||||||
|
row.addView(chip)
|
||||||
|
|
||||||
|
buttonContainer.addView(row)
|
||||||
|
dynamicButtons.add(btn)
|
||||||
|
questionnaireFiles[btn] = entry.file
|
||||||
|
cardParts[btn] = CardParts(tvTitle, tvSubtitle, chip)
|
||||||
|
|
||||||
|
tvTitle.text = "Questionnaire ${index + 1}"
|
||||||
|
|
||||||
|
if (entry.condition is QuestionItem.Condition.AlwaysAvailable) startEnabled.add(btn)
|
||||||
|
}
|
||||||
|
|
||||||
|
applyUpdateButtonTexts(force = false)
|
||||||
|
applySetButtonsEnabled(startEnabled, allowCompleted = false, force = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restorePreviousClientCode() {
|
private fun restorePreviousClientCode() {
|
||||||
@ -186,9 +252,9 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
|
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
|
||||||
languageID = languages[position]
|
languageID = languages[position]
|
||||||
updateButtonTexts()
|
applyUpdateButtonTexts(force = false)
|
||||||
val hintTag = editText.tag as? String ?: ""
|
val hintTag = editText.tag as? String ?: ""
|
||||||
editText.hint = LanguageManager.getText(languageID, hintTag)
|
editText.hint = t(hintTag)
|
||||||
}
|
}
|
||||||
override fun onNothingSelected(parent: AdapterView<*>) {}
|
override fun onNothingSelected(parent: AdapterView<*>) {}
|
||||||
}
|
}
|
||||||
@ -203,64 +269,135 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
questionnaireEntriesProvider = { questionnaireEntries },
|
questionnaireEntriesProvider = { questionnaireEntries },
|
||||||
dynamicButtonsProvider = { dynamicButtons },
|
dynamicButtonsProvider = { dynamicButtons },
|
||||||
buttonPoints = buttonPoints,
|
buttonPoints = buttonPoints,
|
||||||
updateButtonTexts = { updateButtonTexts() },
|
updateButtonTexts = { applyUpdateButtonTexts(force = false) },
|
||||||
setButtonsEnabled = { setButtonsEnabled(it) },
|
setButtonsEnabled = { list -> applySetButtonsEnabled(list, allowCompleted = false, force = false) },
|
||||||
updateMainButtonsState = { updateMainButtonsState(it) },
|
updateMainButtonsState = { updateMainButtonsState(it) },
|
||||||
).setup()
|
).setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateButtonTexts() {
|
private fun applyUpdateButtonTexts(force: Boolean) {
|
||||||
// --- dynamische Fragebogen-Buttons wie gehabt ---
|
if (uiFreeze && !force) return
|
||||||
|
|
||||||
questionnaireFiles.forEach { (button, fileName) ->
|
questionnaireFiles.forEach { (button, fileName) ->
|
||||||
val entry = questionnaireEntries.firstOrNull { it.file == fileName }
|
val entry = questionnaireEntries.firstOrNull { it.file == fileName }
|
||||||
val key = fileName.substringAfter("questionnaire_").substringAfter("_").removeSuffix(".json")
|
val key = fileName.substringAfter("questionnaire_").substringAfter("_").removeSuffix(".json")
|
||||||
var buttonText = LanguageManager.getText(languageID, key)
|
val titleText = t(key)
|
||||||
val pointsAvailable = buttonPoints.entries.firstOrNull { fileName.contains(it.key, ignoreCase = true) }
|
|
||||||
val points = pointsAvailable?.value ?: 0
|
|
||||||
|
|
||||||
if (entry?.showPoints == true && pointsAvailable != null) {
|
val parts = cardParts[button] ?: return@forEach
|
||||||
buttonText += " (${points} P)"
|
parts.title.text = titleText
|
||||||
}
|
|
||||||
button.text = buttonText
|
|
||||||
|
|
||||||
if (entry?.showPoints == true && pointsAvailable != null) {
|
val points = buttonPoints.entries.firstOrNull { fileName.contains(it.key, ignoreCase = true) }?.value
|
||||||
when {
|
val completed = isCompleted(button)
|
||||||
points in 0..12 -> button.setBackgroundColor(Color.parseColor("#4CAF50"))
|
val enabled = button.isEnabled
|
||||||
points in 13..36 -> button.setBackgroundColor(Color.parseColor("#FFEB3B"))
|
val locked = !enabled && !completed
|
||||||
points in 37..100-> button.setBackgroundColor(Color.parseColor("#F44336"))
|
|
||||||
else -> button.setBackgroundColor(Color.parseColor("#E0E0E0"))
|
// Rahmenbreite & -farbe je nach Klickbarkeit
|
||||||
}
|
setClickableStroke(button, enabled)
|
||||||
|
|
||||||
|
if (locked) {
|
||||||
|
setLockedAppearance(button, true)
|
||||||
|
parts.title.setTextColor(Color.WHITE)
|
||||||
|
parts.subtitle.setTextColor(Color.parseColor("#E0E0E0"))
|
||||||
} else {
|
} else {
|
||||||
button.setBackgroundColor(Color.parseColor("#E0E0E0"))
|
setLockedAppearance(button, false)
|
||||||
|
parts.title.setTextColor(Color.parseColor("#2F2A49"))
|
||||||
|
parts.subtitle.setTextColor(Color.parseColor("#7B7794"))
|
||||||
|
// Tönung nur wenn showPoints == true
|
||||||
|
applyTintForButton(button, points, emphasize = enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry?.showPoints == true && points != null) {
|
||||||
|
parts.subtitle.visibility = View.VISIBLE
|
||||||
|
parts.subtitle.text = "${t("points")}: $points"
|
||||||
|
} else {
|
||||||
|
parts.subtitle.visibility = View.GONE
|
||||||
|
parts.subtitle.text = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
when {
|
||||||
|
completed -> {
|
||||||
|
parts.chip.text = t("done")
|
||||||
|
parts.chip.setBackgroundResource(R.drawable.bg_chip_green)
|
||||||
|
parts.chip.setTextColor(Color.WHITE)
|
||||||
|
}
|
||||||
|
enabled -> {
|
||||||
|
parts.chip.text = t("start")
|
||||||
|
parts.chip.setBackgroundResource(R.drawable.bg_chip_amber)
|
||||||
|
parts.chip.setTextColor(Color.WHITE)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
parts.chip.text = t("locked")
|
||||||
|
parts.chip.setBackgroundResource(R.drawable.bg_chip_grey)
|
||||||
|
parts.chip.setTextColor(Color.parseColor("#2F2A49"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- HIER: alle Hauptbuttons nach Sprache neu setzen ---
|
buttonLoad.text = t("load")
|
||||||
buttonLoad.text = LanguageManager.getText(languageID, "load")
|
saveButton.text = t("save")
|
||||||
saveButton.text = LanguageManager.getText(languageID, "save")
|
editButton.text = t("edit")
|
||||||
editButton.text = LanguageManager.getText(languageID, "edit")
|
uploadButton.text = t("upload")
|
||||||
uploadButton.text = LanguageManager.getText(languageID, "upload")
|
downloadButton.text = t("download")
|
||||||
downloadButton.text= LanguageManager.getText(languageID, "download")
|
databaseButton.text = t("database")
|
||||||
databaseButton.text= LanguageManager.getText(languageID, "database")
|
|
||||||
|
|
||||||
// optional: Beispieltext/Hints auch aktualisieren
|
|
||||||
val hintTag = editText.tag as? String ?: ""
|
val hintTag = editText.tag as? String ?: ""
|
||||||
editText.hint = LanguageManager.getText(languageID, hintTag)
|
editText.hint = t(hintTag)
|
||||||
textView.text = LanguageManager.getText(languageID, "example_text")
|
textView.text = t("example_text")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setButtonsEnabled(enabledButtons: List<Button>) {
|
private fun applySetButtonsEnabled(enabledButtons: List<Button>, allowCompleted: Boolean, force: Boolean) {
|
||||||
|
if (uiFreeze && !force) return
|
||||||
|
|
||||||
questionnaireFiles.keys.forEach { button ->
|
questionnaireFiles.keys.forEach { button ->
|
||||||
button.isEnabled = enabledButtons.contains(button)
|
val completed = isCompleted(button)
|
||||||
button.alpha = if (button.isEnabled) 1.0f else 0.5f
|
val isAllowed = enabledButtons.contains(button)
|
||||||
|
val shouldEnable = if (allowCompleted) isAllowed else isAllowed && !completed
|
||||||
|
val locked = !shouldEnable && !completed
|
||||||
|
|
||||||
|
button.isEnabled = shouldEnable
|
||||||
|
button.alpha = if (completed || shouldEnable) 1.0f else 0.6f
|
||||||
|
|
||||||
|
// Rahmenbreite & -farbe je nach Klickbarkeit
|
||||||
|
setClickableStroke(button, shouldEnable)
|
||||||
|
|
||||||
|
cardParts[button]?.let { parts ->
|
||||||
|
if (locked) {
|
||||||
|
setLockedAppearance(button, true)
|
||||||
|
parts.title.setTextColor(Color.WHITE)
|
||||||
|
parts.subtitle.setTextColor(Color.parseColor("#E0E0E0"))
|
||||||
|
} else {
|
||||||
|
setLockedAppearance(button, false)
|
||||||
|
parts.title.setTextColor(Color.parseColor("#2F2A49"))
|
||||||
|
parts.subtitle.setTextColor(Color.parseColor("#7B7794"))
|
||||||
|
// Tönung nur wenn showPoints == true
|
||||||
|
applyTintForButton(button, getPointsForButton(button), emphasize = shouldEnable)
|
||||||
|
}
|
||||||
|
|
||||||
|
when {
|
||||||
|
completed -> {
|
||||||
|
parts.chip.text = t("done")
|
||||||
|
parts.chip.setBackgroundResource(R.drawable.bg_chip_green)
|
||||||
|
parts.chip.setTextColor(Color.WHITE)
|
||||||
|
}
|
||||||
|
shouldEnable -> {
|
||||||
|
parts.chip.text = t("start")
|
||||||
|
parts.chip.setBackgroundResource(R.drawable.bg_chip_amber)
|
||||||
|
parts.chip.setTextColor(Color.WHITE)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
parts.chip.text = t("locked")
|
||||||
|
parts.chip.setBackgroundResource(R.drawable.bg_chip_grey)
|
||||||
|
parts.chip.setTextColor(Color.parseColor("#2F2A49"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startQuestionnaireForButton(button: Button) {
|
// öffentliche Wrapper
|
||||||
val fileName = questionnaireFiles[button] ?: return
|
private fun updateButtonTexts() = applyUpdateButtonTexts(force = false)
|
||||||
val questionnaire = QuestionnaireGeneric(fileName)
|
private fun setButtonsEnabled(enabledButtons: List<Button>, allowCompleted: Boolean = false) =
|
||||||
startQuestionnaire(questionnaire)
|
applySetButtonsEnabled(enabledButtons, allowCompleted, force = false)
|
||||||
}
|
|
||||||
|
|
||||||
private fun startQuestionnaire(questionnaire: QuestionnaireBase<*>) {
|
private fun startQuestionnaire(questionnaire: QuestionnaireBase<*>) {
|
||||||
activity.startQuestionnaire(questionnaire, languageID)
|
activity.startQuestionnaire(questionnaire, languageID)
|
||||||
@ -285,48 +422,46 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
languageIDProvider = { languageID },
|
languageIDProvider = { languageID },
|
||||||
questionnaireFiles = questionnaireFiles,
|
questionnaireFiles = questionnaireFiles,
|
||||||
buttonPoints = buttonPoints,
|
buttonPoints = buttonPoints,
|
||||||
updateButtonTexts = { updateButtonTexts() },
|
updateButtonTexts = { applyUpdateButtonTexts(force = true) },
|
||||||
setButtonsEnabled = { setButtonsEnabled(it) },
|
setButtonsEnabled = { list, allowCompleted ->
|
||||||
|
applySetButtonsEnabled(list, allowCompleted, force = true)
|
||||||
|
},
|
||||||
|
setUiFreeze = { freeze -> uiFreeze = freeze },
|
||||||
triggerLoad = { buttonLoad.performClick() }
|
triggerLoad = { buttonLoad.performClick() }
|
||||||
).setup()
|
).setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupUploadButton() {
|
private fun setupUploadButton() {
|
||||||
uploadButton.text = "Upload"
|
uploadButton.text = t("upload")
|
||||||
uploadButton.setOnClickListener {
|
uploadButton.setOnClickListener {
|
||||||
val clientCode = editText.text.toString().trim()
|
val clientCode = editText.text.toString().trim()
|
||||||
|
|
||||||
GlobalValues.LAST_CLIENT_CODE = clientCode
|
GlobalValues.LAST_CLIENT_CODE = clientCode
|
||||||
|
|
||||||
val input = EditText(activity).apply { hint = "Server-Passwort" }
|
val input = EditText(activity).apply { hint = "Server-Passwort" }
|
||||||
|
|
||||||
android.app.AlertDialog.Builder(activity)
|
android.app.AlertDialog.Builder(activity)
|
||||||
.setTitle("Login erforderlich")
|
.setTitle(t("login_required"))
|
||||||
.setView(input)
|
.setView(input)
|
||||||
.setPositiveButton("OK") { _, _ ->
|
.setPositiveButton("OK") { _, _ ->
|
||||||
val password = input.text.toString()
|
val password = input.text.toString()
|
||||||
if (password.isNotBlank()) {
|
if (password.isNotBlank()) {
|
||||||
Toast.makeText(activity, "Login wird überprüft...", Toast.LENGTH_SHORT).show()
|
Toast.makeText(activity, t("checking_login"), Toast.LENGTH_SHORT).show()
|
||||||
DatabaseUploader.uploadDatabaseWithLogin(activity, password)
|
DatabaseUploader.uploadDatabaseWithLogin(activity, password)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(activity, "Bitte Passwort eingeben", Toast.LENGTH_SHORT).show()
|
Toast.makeText(activity, t("enter_password"), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.setNegativeButton("Abbrechen", null)
|
.setNegativeButton(t("cancel"), null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupDownloadButton() {
|
private fun setupDownloadButton() {
|
||||||
downloadButton.text = "Download"
|
downloadButton.text = t("download")
|
||||||
downloadButton.setOnClickListener {
|
downloadButton.setOnClickListener {
|
||||||
val clientCode = editText.text.toString().trim()
|
val clientCode = editText.text.toString().trim()
|
||||||
GlobalValues.LAST_CLIENT_CODE = clientCode
|
GlobalValues.LAST_CLIENT_CODE = clientCode
|
||||||
|
|
||||||
val input = EditText(activity).apply { hint = "Server-Passwort" }
|
val input = EditText(activity).apply { hint = "Server-Passwort" }
|
||||||
|
|
||||||
android.app.AlertDialog.Builder(activity)
|
android.app.AlertDialog.Builder(activity)
|
||||||
.setTitle("Login erforderlich")
|
.setTitle(t("login_required"))
|
||||||
.setView(input)
|
.setView(input)
|
||||||
.setPositiveButton("OK") { _, _ ->
|
.setPositiveButton("OK") { _, _ ->
|
||||||
val password = input.text.toString()
|
val password = input.text.toString()
|
||||||
@ -335,7 +470,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
context = activity,
|
context = activity,
|
||||||
password = password,
|
password = password,
|
||||||
onSuccess = { token ->
|
onSuccess = { token ->
|
||||||
Toast.makeText(activity, "Login erfolgreich", Toast.LENGTH_SHORT).show()
|
Toast.makeText(activity, t("login_ok"), Toast.LENGTH_SHORT).show()
|
||||||
DatabaseDownloader.downloadAndReplaceDatabase(activity, token)
|
DatabaseDownloader.downloadAndReplaceDatabase(activity, token)
|
||||||
updateMainButtonsState(true)
|
updateMainButtonsState(true)
|
||||||
},
|
},
|
||||||
@ -344,10 +479,10 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(activity, "Bitte Passwort eingeben", Toast.LENGTH_SHORT).show()
|
Toast.makeText(activity, t("enter_password"), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.setNegativeButton("Abbrechen", null)
|
.setNegativeButton(t("cancel"), null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,20 +491,92 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
DatabaseButtonHandler(
|
DatabaseButtonHandler(
|
||||||
activity = activity,
|
activity = activity,
|
||||||
databaseButton = databaseButton,
|
databaseButton = databaseButton,
|
||||||
onClose = {
|
onClose = { init() },
|
||||||
// zurück zum Opening-Screen
|
languageIDProvider = { languageID }
|
||||||
init()
|
|
||||||
},
|
|
||||||
languageIDProvider = { languageID } // aktuelle Sprache an DatabaseButtonHandler weitergeben
|
|
||||||
).setup()
|
).setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun updateMainButtonsState(isDatabaseAvailable: Boolean) {
|
private fun updateMainButtonsState(isDatabaseAvailable: Boolean) {
|
||||||
val buttons = listOf(buttonLoad, saveButton, editButton, databaseButton) // <-- NEU dabei
|
listOf(buttonLoad, saveButton, editButton, databaseButton).forEach { b ->
|
||||||
buttons.forEach { button ->
|
b.isEnabled = isDatabaseAvailable
|
||||||
button.isEnabled = isDatabaseAvailable
|
b.alpha = if (isDatabaseAvailable) 1.0f else 0.5f
|
||||||
button.alpha = if (isDatabaseAvailable) 1.0f else 0.5f
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun dp(v: Int): Int =
|
||||||
|
(v * activity.resources.displayMetrics.density).toInt()
|
||||||
|
|
||||||
|
private fun isCompleted(button: Button): Boolean {
|
||||||
|
val fileName = questionnaireFiles[button] ?: return false
|
||||||
|
return buttonPoints.keys.any { k ->
|
||||||
|
fileName.contains(k, ignoreCase = true) || k.contains(fileName, ignoreCase = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPointsForButton(button: Button): Int? {
|
||||||
|
val fileName = questionnaireFiles[button] ?: return null
|
||||||
|
return buttonPoints.entries.firstOrNull { (k, _) ->
|
||||||
|
fileName.contains(k, ignoreCase = true) || k.contains(fileName, ignoreCase = true)
|
||||||
|
}?.value
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Locked-Optik: schwarzer Hintergrund, fester grauer Rand */
|
||||||
|
private fun setLockedAppearance(button: Button, locked: Boolean) {
|
||||||
|
val mb = button as? MaterialButton ?: return
|
||||||
|
if (locked) {
|
||||||
|
mb.backgroundTintList = ColorStateList.valueOf(Color.BLACK)
|
||||||
|
mb.strokeColor = ColorStateList.valueOf(STROKE_DISABLED)
|
||||||
|
} else {
|
||||||
|
mb.backgroundTintList = ColorStateList.valueOf(Color.WHITE)
|
||||||
|
mb.strokeColor = ColorStateList.valueOf(if (button.isEnabled) STROKE_ENABLED else STROKE_DISABLED)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Standardfarben wiederherstellen (wenn showPoints == false) – hier nicht mehr für locked zuständig */
|
||||||
|
private fun resetTint(button: Button) {
|
||||||
|
val mb = button as? MaterialButton ?: return
|
||||||
|
mb.backgroundTintList = ColorStateList.valueOf(Color.WHITE)
|
||||||
|
mb.strokeColor = ColorStateList.valueOf(STROKE_DISABLED)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tönung nur anwenden, wenn showPoints == true (und Button nicht locked) */
|
||||||
|
private fun applyTintForButton(button: Button, points: Int?, emphasize: Boolean) {
|
||||||
|
val file = questionnaireFiles[button] ?: return
|
||||||
|
val entry = questionnaireEntries.firstOrNull { it.file == file }
|
||||||
|
|
||||||
|
if (entry?.showPoints != true) {
|
||||||
|
val mb = button as? MaterialButton ?: return
|
||||||
|
mb.backgroundTintList = ColorStateList.valueOf(if (emphasize) Color.parseColor("#F1EEFF") else Color.WHITE)
|
||||||
|
mb.strokeColor = ColorStateList.valueOf(if (emphasize) STROKE_ENABLED else STROKE_DISABLED)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setScoreTint(button, points, emphasize)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dickere Kontur, wenn anklickbar; Farbe bleibt fix */
|
||||||
|
private fun setClickableStroke(button: Button, enabled: Boolean) {
|
||||||
|
val mb = button as? MaterialButton ?: return
|
||||||
|
mb.strokeWidth = if (enabled) dp(2) else dp(1)
|
||||||
|
mb.strokeColor = ColorStateList.valueOf(if (enabled) STROKE_ENABLED else STROKE_DISABLED)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Hintergrund nach Score; Rand bleibt fix */
|
||||||
|
private fun setScoreTint(button: Button, points: Int?, emphasize: Boolean) {
|
||||||
|
val mb = button as? MaterialButton ?: return
|
||||||
|
|
||||||
|
val bg = when {
|
||||||
|
points == null && emphasize -> Color.parseColor("#F1EEFF")
|
||||||
|
points == null -> Color.parseColor("#FFFFFF")
|
||||||
|
points in 0..12 && emphasize -> Color.parseColor("#C8E6C9")
|
||||||
|
points in 0..12 -> Color.parseColor("#E8F5E9")
|
||||||
|
points in 13..36 && emphasize -> Color.parseColor("#FFE0B2")
|
||||||
|
points in 13..36 -> Color.parseColor("#FFF8E1")
|
||||||
|
points >= 37 && emphasize -> Color.parseColor("#FFCDD2")
|
||||||
|
else -> Color.parseColor("#FFEBEE")
|
||||||
|
}
|
||||||
|
|
||||||
|
mb.backgroundTintList = ColorStateList.valueOf(bg)
|
||||||
|
mb.strokeColor = ColorStateList.valueOf(if (emphasize) STROKE_ENABLED else STROKE_DISABLED)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -352,10 +352,9 @@ object LanguageManager {
|
|||||||
"export_success_downloads_headers" to "Export erfolgreich: Downloads/ClientHeaders.xlsx",
|
"export_success_downloads_headers" to "Export erfolgreich: Downloads/ClientHeaders.xlsx",
|
||||||
"export_failed" to "Export fehlgeschlagen.",
|
"export_failed" to "Export fehlgeschlagen.",
|
||||||
"error_generic" to "Fehler",
|
"error_generic" to "Fehler",
|
||||||
"done" to "abgeschlossen",
|
"not_done" to "Nicht Fertog",
|
||||||
"not_done" to "nicht abgeschlossen",
|
"none" to "Keine Angabe",
|
||||||
"none" to "keine Angabe",
|
"points" to "Punkte"
|
||||||
|
|
||||||
),
|
),
|
||||||
|
|
||||||
"ENGLISH" to mapOf(
|
"ENGLISH" to mapOf(
|
||||||
@ -675,9 +674,12 @@ object LanguageManager {
|
|||||||
"export_success_downloads_headers" to "Export successful: Downloads/ClientHeaders.xlsx",
|
"export_success_downloads_headers" to "Export successful: Downloads/ClientHeaders.xlsx",
|
||||||
"export_failed" to "Export failed.",
|
"export_failed" to "Export failed.",
|
||||||
"error_generic" to "Error",
|
"error_generic" to "Error",
|
||||||
"done" to "Done",
|
|
||||||
"not_done" to "Not Done",
|
"not_done" to "Not Done",
|
||||||
"none" to "None",
|
"none" to "None",
|
||||||
|
"done" to "Done",
|
||||||
|
"locked" to "Locked",
|
||||||
|
"start" to "Start",
|
||||||
|
"points" to "Points"
|
||||||
),
|
),
|
||||||
|
|
||||||
"FRENCH" to mapOf(
|
"FRENCH" to mapOf(
|
||||||
@ -1001,9 +1003,12 @@ object LanguageManager {
|
|||||||
"export_success_downloads_headers" to "Export réussi : Downloads/ClientHeaders.xlsx",
|
"export_success_downloads_headers" to "Export réussi : Downloads/ClientHeaders.xlsx",
|
||||||
"export_failed" to "Échec de l’exportation.",
|
"export_failed" to "Échec de l’exportation.",
|
||||||
"error_generic" to "Erreur",
|
"error_generic" to "Erreur",
|
||||||
"done" to "terminé",
|
|
||||||
"not_done" to "non terminé",
|
"not_done" to "non terminé",
|
||||||
"none" to "aucune réponse",
|
"none" to "aucune réponse",
|
||||||
|
"done" to "Terminé",
|
||||||
|
"locked" to "Verrouillé",
|
||||||
|
"start" to "Commencer",
|
||||||
|
"points" to "Points"
|
||||||
),
|
),
|
||||||
|
|
||||||
"RUSSIAN" to mapOf(
|
"RUSSIAN" to mapOf(
|
||||||
@ -1323,9 +1328,12 @@ object LanguageManager {
|
|||||||
"export_success_downloads_headers" to "Экспорт выполнен: Downloads/ClientHeaders.xlsx",
|
"export_success_downloads_headers" to "Экспорт выполнен: Downloads/ClientHeaders.xlsx",
|
||||||
"export_failed" to "Экспорт не выполнен.",
|
"export_failed" to "Экспорт не выполнен.",
|
||||||
"error_generic" to "Ошибка",
|
"error_generic" to "Ошибка",
|
||||||
"done" to "выполнено",
|
|
||||||
"not_done" to "не выполнено",
|
"not_done" to "не выполнено",
|
||||||
"none" to "нет ответа",
|
"none" to "нет ответа",
|
||||||
|
"done" to "Готово",
|
||||||
|
"locked" to "Заблокировано",
|
||||||
|
"start" to "Начать",
|
||||||
|
"points" to "Баллы"
|
||||||
),
|
),
|
||||||
|
|
||||||
"UKRAINIAN" to mapOf(
|
"UKRAINIAN" to mapOf(
|
||||||
@ -1649,9 +1657,12 @@ object LanguageManager {
|
|||||||
"export_success_downloads_headers" to "Експорт успішний: Downloads/ClientHeaders.xlsx",
|
"export_success_downloads_headers" to "Експорт успішний: Downloads/ClientHeaders.xlsx",
|
||||||
"export_failed" to "Помилка експорту.",
|
"export_failed" to "Помилка експорту.",
|
||||||
"error_generic" to "Помилка",
|
"error_generic" to "Помилка",
|
||||||
"done" to "завершено",
|
|
||||||
"not_done" to "не завершено",
|
"not_done" to "не завершено",
|
||||||
"none" to "немає відповіді",
|
"none" to "немає відповіді",
|
||||||
|
"done" to "Завершено",
|
||||||
|
"locked" to "Заблоковано",
|
||||||
|
"start" to "Почати",
|
||||||
|
"points" to "Бали"
|
||||||
),
|
),
|
||||||
|
|
||||||
"TURKISH" to mapOf(
|
"TURKISH" to mapOf(
|
||||||
@ -1975,9 +1986,12 @@ object LanguageManager {
|
|||||||
"export_success_downloads_headers" to "Dışa aktarma başarılı: Downloads/ClientHeaders.xlsx",
|
"export_success_downloads_headers" to "Dışa aktarma başarılı: Downloads/ClientHeaders.xlsx",
|
||||||
"export_failed" to "Dışa aktarma başarısız.",
|
"export_failed" to "Dışa aktarma başarısız.",
|
||||||
"error_generic" to "Hata",
|
"error_generic" to "Hata",
|
||||||
"done" to "tamamlandı",
|
|
||||||
"not_done" to "tamamlanmadı",
|
"not_done" to "tamamlanmadı",
|
||||||
"none" to "yanıt yok",
|
"none" to "yanıt yok",
|
||||||
|
"done" to "Tamamlandı",
|
||||||
|
"locked" to "Kilitli",
|
||||||
|
"start" to "Başlat",
|
||||||
|
"points" to "Puan"
|
||||||
),
|
),
|
||||||
|
|
||||||
"POLISH" to mapOf(
|
"POLISH" to mapOf(
|
||||||
@ -2301,9 +2315,12 @@ object LanguageManager {
|
|||||||
"export_success_downloads_headers" to "Eksport zakończony: Downloads/ClientHeaders.xlsx",
|
"export_success_downloads_headers" to "Eksport zakończony: Downloads/ClientHeaders.xlsx",
|
||||||
"export_failed" to "Eksport nieudany.",
|
"export_failed" to "Eksport nieudany.",
|
||||||
"error_generic" to "Błąd",
|
"error_generic" to "Błąd",
|
||||||
"done" to "zakończono",
|
|
||||||
"not_done" to "nie zakończono",
|
"not_done" to "nie zakończono",
|
||||||
"none" to "brak odpowiedzi",
|
"none" to "brak odpowiedzi",
|
||||||
|
"done" to "Gotowe",
|
||||||
|
"locked" to "Zablokowane",
|
||||||
|
"start" to "Rozpocznij",
|
||||||
|
"points" to "Punkty"
|
||||||
),
|
),
|
||||||
|
|
||||||
"ARABIC" to mapOf(
|
"ARABIC" to mapOf(
|
||||||
@ -2627,9 +2644,12 @@ object LanguageManager {
|
|||||||
"export_success_downloads_headers" to "تم التصدير بنجاح: Downloads/ClientHeaders.xlsx",
|
"export_success_downloads_headers" to "تم التصدير بنجاح: Downloads/ClientHeaders.xlsx",
|
||||||
"export_failed" to "فشل التصدير.",
|
"export_failed" to "فشل التصدير.",
|
||||||
"error_generic" to "خطأ",
|
"error_generic" to "خطأ",
|
||||||
"done" to "مكتمل",
|
|
||||||
"not_done" to "غير مكتمل",
|
"not_done" to "غير مكتمل",
|
||||||
"none" to "لا توجد إجابة",
|
"none" to "لا توجد إجابة",
|
||||||
|
"done" to "تم",
|
||||||
|
"locked" to "مقفل",
|
||||||
|
"start" to "ابدأ",
|
||||||
|
"points" to "النقاط"
|
||||||
),
|
),
|
||||||
|
|
||||||
"ROMANIAN" to mapOf(
|
"ROMANIAN" to mapOf(
|
||||||
@ -2953,9 +2973,12 @@ object LanguageManager {
|
|||||||
"export_success_downloads_headers" to "Export reușit: Downloads/ClientHeaders.xlsx",
|
"export_success_downloads_headers" to "Export reușit: Downloads/ClientHeaders.xlsx",
|
||||||
"export_failed" to "Export nereușit.",
|
"export_failed" to "Export nereușit.",
|
||||||
"error_generic" to "Eroare",
|
"error_generic" to "Eroare",
|
||||||
"done" to "finalizat",
|
|
||||||
"not_done" to "nefinalizat",
|
"not_done" to "nefinalizat",
|
||||||
"none" to "niciun răspuns",
|
"none" to "niciun răspuns",
|
||||||
|
"done" to "Finalizat",
|
||||||
|
"locked" to "Blocat",
|
||||||
|
"start" to "Începe",
|
||||||
|
"points" to "Puncte"
|
||||||
),
|
),
|
||||||
|
|
||||||
"SPANISH" to mapOf(
|
"SPANISH" to mapOf(
|
||||||
@ -3279,9 +3302,12 @@ object LanguageManager {
|
|||||||
"export_success_downloads_headers" to "Exportación correcta: Downloads/ClientHeaders.xlsx",
|
"export_success_downloads_headers" to "Exportación correcta: Downloads/ClientHeaders.xlsx",
|
||||||
"export_failed" to "Fallo en la exportación.",
|
"export_failed" to "Fallo en la exportación.",
|
||||||
"error_generic" to "Error",
|
"error_generic" to "Error",
|
||||||
"done" to "completado",
|
|
||||||
"not_done" to "no completado",
|
"not_done" to "no completado",
|
||||||
"none" to "sin respuesta",
|
"none" to "sin respuesta",
|
||||||
|
"done" to "Completado",
|
||||||
|
"locked" to "Bloqueado",
|
||||||
|
"start" to "Iniciar",
|
||||||
|
"points" to "Puncte"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,10 +25,6 @@ class LoadButtonHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleLoadButton() {
|
private fun handleLoadButton() {
|
||||||
buttonPoints.clear()
|
|
||||||
updateButtonTexts()
|
|
||||||
setButtonsEnabled(emptyList())
|
|
||||||
|
|
||||||
val inputText = editText.text.toString().trim()
|
val inputText = editText.text.toString().trim()
|
||||||
if (inputText.isBlank()) {
|
if (inputText.isBlank()) {
|
||||||
val message = LanguageManager.getText(languageIDProvider(), "please_client_code")
|
val message = LanguageManager.getText(languageIDProvider(), "please_client_code")
|
||||||
@ -36,13 +32,16 @@ class LoadButtonHandler(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buttonPoints.clear()
|
||||||
|
setButtonsEnabled(emptyList()) // temporär sperren
|
||||||
|
updateButtonTexts() // Chips zeigen vorläufig „Gesperrt“
|
||||||
|
|
||||||
val clientCode = inputText
|
val clientCode = inputText
|
||||||
GlobalValues.LAST_CLIENT_CODE = clientCode
|
GlobalValues.LAST_CLIENT_CODE = clientCode
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val client = MyApp.database.clientDao().getClientByCode(clientCode)
|
val client = MyApp.database.clientDao().getClientByCode(clientCode)
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
// Kein Profil → als NICHT geladen markieren
|
|
||||||
GlobalValues.LOADED_CLIENT_CODE = null
|
GlobalValues.LOADED_CLIENT_CODE = null
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
val message = LanguageManager.getText(languageIDProvider(), "no_profile")
|
val message = LanguageManager.getText(languageIDProvider(), "no_profile")
|
||||||
@ -53,21 +52,18 @@ class LoadButtonHandler(
|
|||||||
if (entry.condition is QuestionItem.Condition.AlwaysAvailable) btn else null
|
if (entry.condition is QuestionItem.Condition.AlwaysAvailable) btn else null
|
||||||
}
|
}
|
||||||
setButtonsEnabled(alwaysButtons)
|
setButtonsEnabled(alwaysButtons)
|
||||||
|
updateButtonTexts() // <- nach dem Aktivieren Chips aktualisieren
|
||||||
}
|
}
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Profil gefunden → als geladen markieren
|
|
||||||
GlobalValues.LOADED_CLIENT_CODE = clientCode
|
GlobalValues.LOADED_CLIENT_CODE = clientCode
|
||||||
|
withContext(Dispatchers.Main) { updateMainButtonsState(true) }
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
updateMainButtonsState(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
handleNormalLoad(clientCode)
|
handleNormalLoad(clientCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private suspend fun evaluateCondition(
|
private suspend fun evaluateCondition(
|
||||||
condition: QuestionItem.Condition?,
|
condition: QuestionItem.Condition?,
|
||||||
clientCode: String,
|
clientCode: String,
|
||||||
@ -134,10 +130,6 @@ class LoadButtonHandler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
updateButtonTexts()
|
|
||||||
}
|
|
||||||
|
|
||||||
val enabledButtons = mutableListOf<Button>()
|
val enabledButtons = mutableListOf<Button>()
|
||||||
val questionnaireEntries = questionnaireEntriesProvider()
|
val questionnaireEntries = questionnaireEntriesProvider()
|
||||||
val dynamicButtons = dynamicButtonsProvider()
|
val dynamicButtons = dynamicButtonsProvider()
|
||||||
@ -158,13 +150,9 @@ class LoadButtonHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
if (enabledButtons.isEmpty()) {
|
setButtonsEnabled(enabledButtons) // erst aktivieren …
|
||||||
setButtonsEnabled(emptyList())
|
updateButtonTexts() // … dann Chips/Labels korrekt setzen
|
||||||
val message = LanguageManager.getText(languageIDProvider(), "questionnaires_finished")
|
|
||||||
Toast.makeText(activity, message, Toast.LENGTH_LONG).show()
|
|
||||||
} else {
|
|
||||||
setButtonsEnabled(enabledButtons)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
5
app/src/main/res/drawable/bg_chip_amber.xml
Normal file
5
app/src/main/res/drawable/bg_chip_amber.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<solid android:color="#F2B544"/>
|
||||||
|
<corners android:radius="18dp"/>
|
||||||
|
<padding android:left="8dp" android:top="6dp" android:right="8dp" android:bottom="6dp"/>
|
||||||
|
</shape>
|
||||||
5
app/src/main/res/drawable/bg_chip_green.xml
Normal file
5
app/src/main/res/drawable/bg_chip_green.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<solid android:color="#43B581"/>
|
||||||
|
<corners android:radius="18dp"/>
|
||||||
|
<padding android:left="8dp" android:top="6dp" android:right="8dp" android:bottom="6dp"/>
|
||||||
|
</shape>
|
||||||
5
app/src/main/res/drawable/bg_chip_grey.xml
Normal file
5
app/src/main/res/drawable/bg_chip_grey.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<solid android:color="#E3E5EF"/>
|
||||||
|
<corners android:radius="18dp"/>
|
||||||
|
<padding android:left="8dp" android:top="6dp" android:right="8dp" android:bottom="6dp"/>
|
||||||
|
</shape>
|
||||||
@ -10,6 +10,7 @@
|
|||||||
android:id="@+id/headerCard"
|
android:id="@+id/headerCard"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
android:paddingStart="24dp"
|
android:paddingStart="24dp"
|
||||||
android:paddingEnd="24dp"
|
android:paddingEnd="24dp"
|
||||||
android:paddingTop="20dp"
|
android:paddingTop="20dp"
|
||||||
@ -207,14 +208,24 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/questionnaireScroll"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/textView"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/buttonContainer"
|
android:id="@+id/buttonContainer"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_marginTop="8dp"
|
android:paddingTop="8dp"/>
|
||||||
app:layout_constraintTop_toBottomOf="@id/textView"
|
</androidx.core.widget.NestedScrollView>
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
Reference in New Issue
Block a user