added button for save and edit

This commit is contained in:
oxidiert
2025-08-04 15:21:17 +02:00
parent e22ff56ab1
commit 2cf9faed38
5 changed files with 110 additions and 64 deletions

View File

@ -20,6 +20,8 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
private lateinit var textView: TextView
private lateinit var buttonContainer: LinearLayout
private lateinit var buttonLoad: Button
private lateinit var saveButton: Button
private lateinit var editButton: Button
private val dynamicButtons = mutableListOf<Button>()
private val questionnaireFiles = mutableMapOf<Button, String>()
@ -36,6 +38,8 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
setupLanguageSpinner()
setupLoadButton()
setupSaveButton()
setupEditButton()
if (!editText.text.isNullOrBlank()) {
buttonLoad.performClick()
@ -48,6 +52,8 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
textView = activity.findViewById(R.id.textView)
buttonContainer = activity.findViewById(R.id.buttonContainer)
buttonLoad = activity.findViewById(R.id.loadButton)
saveButton = activity.findViewById(R.id.saveButton)
editButton = activity.findViewById(R.id.editButton)
val tag = editText.tag as? String ?: ""
editText.hint = LanguageManager.getText(languageID, tag)
@ -154,13 +160,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
return
}
val isDatabaseView = inputText.endsWith("_database")
val isChangeView = inputText.endsWith("_change")
// Extrahiere nur den echten Code, ohne die Suffixe
val clientCode = inputText
.removeSuffix("_database")
.removeSuffix("_change")
GlobalValues.LAST_CLIENT_CODE = clientCode
@ -176,16 +176,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
}
withContext(Dispatchers.Main) {
// Normales Laden
handleNormalLoad(clientCode)
// Erweiterungen bei speziellen Suffixen
if (isDatabaseView) {
showCompletedQuestionnaires(clientCode)
enableCompletedQuestionnaireButtons(clientCode)
} else if (isChangeView) {
enableCompletedQuestionnaireButtons(clientCode)
}
}
}
}
@ -517,4 +508,56 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
}
}
}
private fun setupSaveButton() {
saveButton.text = LanguageManager.getText(languageID, "save")
saveButton.setOnClickListener {
val clientCode = editText.text.toString().trim()
if (clientCode.isBlank()) {
val message = LanguageManager.getText(languageID, "please_client_code")
Toast.makeText(activity, message, Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
GlobalValues.LAST_CLIENT_CODE = clientCode
showCompletedQuestionnaires(clientCode)
}
}
private fun setupEditButton() {
editButton.text = LanguageManager.getText(languageID, "edit")
editButton.setOnClickListener {
val clientCode = editText.text.toString().trim()
if (clientCode.isBlank()) {
val message = LanguageManager.getText(languageID, "please_client_code")
Toast.makeText(activity, message, Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
GlobalValues.LAST_CLIENT_CODE = clientCode
CoroutineScope(Dispatchers.IO).launch {
val completedEntries = MyApp.database.completedQuestionnaireDao().getAllForClient(clientCode)
val completedFiles = completedEntries
.filter { it.isDone }
.map { it.questionnaireId.lowercase() }
buttonPoints.clear()
for (entry in completedEntries) {
if (entry.isDone) {
buttonPoints[entry.questionnaireId] = entry.sumPoints ?: 0
}
}
withContext(Dispatchers.Main) {
updateButtonTexts()
val enabledButtons = questionnaireFiles.filter { (_, fileName) ->
completedFiles.any { completedId -> fileName.lowercase().contains(completedId) }
}.keys.toList()
setButtonsEnabled(enabledButtons)
}
}
}
}
}

View File

@ -19,7 +19,6 @@ class HandlerRadioQuestion(
private lateinit var layout: View
private lateinit var question: QuestionItem.RadioQuestion
// Bind the question data to the view
override fun bind(layout: View, question: QuestionItem) {
this.layout = layout
this.question = question as QuestionItem.RadioQuestion
@ -28,17 +27,14 @@ class HandlerRadioQuestion(
val questionTextView = layout.findViewById<TextView>(R.id.textView)
val questionTitle = layout.findViewById<TextView>(R.id.question)
// Set question text and optional text key
questionTextView.text = question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
questionTitle.text = question.question?.let {
Html.fromHtml(LanguageManager.getText(languageID, it), Html.FROM_HTML_MODE_LEGACY)
} ?: ""
// Clear previous radio buttons if any
radioGroup.removeAllViews()
// Dynamically create radio buttons based on options
question.options.forEach { option ->
val radioButton = RadioButton(context).apply {
text = LanguageManager.getText(languageID, option.key)
@ -55,10 +51,8 @@ class HandlerRadioQuestion(
radioGroup.addView(radioButton)
}
// Restore previous answer if one was saved
restorePreviousAnswer(radioGroup)
// Handle Next button click
layout.findViewById<Button>(R.id.Qnext).setOnClickListener {
if (validate()) {
saveAnswer()
@ -67,7 +61,6 @@ class HandlerRadioQuestion(
val selectedRadioButton = layout.findViewById<RadioButton>(selectedId)
val selectedKey = selectedRadioButton.tag.toString()
// Check if there is a specific next question ID
val nextId = question.options.find { it.key == selectedKey }?.nextQuestionId
if (!nextId.isNullOrEmpty()) {
@ -80,13 +73,11 @@ class HandlerRadioQuestion(
}
}
// Handle Previous button click
layout.findViewById<Button>(R.id.Qprev).setOnClickListener {
goToPreviousQuestion()
}
}
// Restore previously saved answer (if exists)
private fun restorePreviousAnswer(radioGroup: RadioGroup) {
question.question?.let { questionKey ->
val savedAnswer = answers[questionKey] as? String
@ -102,12 +93,10 @@ class HandlerRadioQuestion(
}
}
// Validate if any radio button has been selected
override fun validate(): Boolean {
return layout.findViewById<RadioGroup>(R.id.RadioGroup).checkedRadioButtonId != -1
}
// Save selected answer and update points list
override fun saveAnswer() {
val radioGroup = layout.findViewById<RadioGroup>(R.id.RadioGroup)
val selectedId = radioGroup.checkedRadioButtonId
@ -116,17 +105,13 @@ class HandlerRadioQuestion(
question.question?.let { questionKey ->
// Alte Antwort und Punkt ermitteln
val oldAnswerKey = answers[questionKey] as? String
val oldPoint = oldAnswerKey?.let { question.pointsMap?.get(it) } ?: 0
// Alten Punkt entfernen, falls vorhanden
points.remove(oldPoint)
// Neue Antwort speichern
answers[questionKey] = answerKey
// Neuen Punkt ermitteln und hinzufügen
val newPoint = question.pointsMap?.get(answerKey) ?: 0
points.add(newPoint)
}

View File

@ -324,7 +324,9 @@ object LanguageManager {
"choose_more_elements" to "Es müssen mehr Elemenete ausgewählt werden.",
"please_client_code" to "Bitte Klienten Code eingeben",
"no_profile" to "Dieser Klient ist noch nicht Teil der Datenbank",
"questionnaires_finished" to "Für diesen Klienten wurden alle Fragebögen ausgefüllt!"
"questionnaires_finished" to "Für diesen Klienten wurden alle Fragebögen ausgefüllt!",
"edit" to "Bearbeiten",
"save" to "Speichern"
),
@ -617,7 +619,9 @@ object LanguageManager {
"choose_more_elements" to "More elements must be selected.",
"please_client_code" to "Please enter client code",
"no_profile" to "This client is not yet part of the database",
"questionnaires_finished" to "All questionnaires have been completed for this client!"
"questionnaires_finished" to "All questionnaires have been completed for this client!",
"edit" to "Bearbeiten",
"save" to "Speichern"
),
"FRENCH" to mapOf(
@ -913,7 +917,9 @@ object LanguageManager {
"choose_more_elements" to "Plus déléments doivent être sélectionnés.",
"please_client_code" to "Veuillez saisir le code client",
"no_profile" to "Ce client ne fait pas encore partie de la base de données",
"questionnaires_finished" to "Tous les questionnaires ont été complétés pour ce client !"
"questionnaires_finished" to "Tous les questionnaires ont été complétés pour ce client !",
"edit" to "Modifier",
"save" to "Sauvegarder"
),
"RUSSIAN" to mapOf(
@ -1205,7 +1211,9 @@ object LanguageManager {
"choose_more_elements" to "Необходимо выбрать больше элементов.",
"please_client_code" to "Пожалуйста, введите код клиента",
"no_profile" to "Этот клиент еще не внесен в базу данных",
"questionnaires_finished" to "Для этого клиента все анкеты заполнены!"
"questionnaires_finished" to "Для этого клиента все анкеты заполнены!",
"edit" to "Редактировать",
"save" to "Сохранять"
),
"UKRAINIAN" to mapOf(
@ -1501,7 +1509,9 @@ object LanguageManager {
"choose_more_elements" to "Потрібно вибрати більше елементів.",
"please_client_code" to "Будь ласка, введіть код клієнта",
"no_profile" to "Цей клієнт ще не внесений до бази даних",
"questionnaires_finished" to "Для цього клієнта всі опитувальники заповнені!"
"questionnaires_finished" to "Для цього клієнта всі опитувальники заповнені!",
"edit" to "Редагувати",
"save" to "Зберегти"
),
"TURKISH" to mapOf(
@ -1797,7 +1807,9 @@ object LanguageManager {
"choose_more_elements" to "Daha fazla öğe seçilmesi gerekiyor.",
"please_client_code" to "Lütfen danışan kodunu girin",
"no_profile" to "Bu danışan henüz veritabanında kayıtlı değil",
"questionnaires_finished" to "Bu danışan için tüm anketler doldurulmuştur!"
"questionnaires_finished" to "Bu danışan için tüm anketler doldurulmuştur!",
"edit" to "Düzenlemek",
"save" to "Kaydetmek"
),
"POLISH" to mapOf(
@ -2093,7 +2105,9 @@ object LanguageManager {
"choose_more_elements" to "Należy wybrać więcej elementów.",
"please_client_code" to "Proszę wprowadzić kod klienta",
"no_profile" to "Ten klient nie jest jeszcze częścią bazy danych",
"questionnaires_finished" to "Dla tego klienta wypełniono wszystkie kwestionariusze!"
"questionnaires_finished" to "Dla tego klienta wypełniono wszystkie kwestionariusze!",
"edit" to "Redagować",
"save" to "Ratować"
),
"ARABIC" to mapOf(
@ -2389,7 +2403,9 @@ object LanguageManager {
"choose_more_elements" to "يجب اختيار المزيد من العناصر.",
"please_client_code" to "يرجى إدخال رمز العميل",
"no_profile" to "هذا العميل غير موجود في قاعدة البيانات بعد",
"questionnaires_finished" to "تم الانتهاء من جميع الاستبيانات لهذا العميل!"
"questionnaires_finished" to "تم الانتهاء من جميع الاستبيانات لهذا العميل!",
"edit" to "يحرر",
"save" to "يحفظ"
),
"ROMANIAN" to mapOf(
@ -2685,7 +2701,9 @@ object LanguageManager {
"choose_more_elements" to "Trebuie selectate mai multe elemente.",
"please_client_code" to "Vă rugăm să introduceți codul clientului",
"no_profile" to "Acest client nu face încă parte din baza de date",
"questionnaires_finished" to "Toate chestionarele pentru acest client au fost completate!"
"questionnaires_finished" to "Toate chestionarele pentru acest client au fost completate!",
"edit" to "Editizel",
"save" to "Xastral"
),
"SPANISH" to mapOf(
@ -2981,7 +2999,9 @@ object LanguageManager {
"choose_more_elements" to "Se deben seleccionar más elementos.",
"please_client_code" to "Por favor, ingrese el código de cliente",
"no_profile" to "Este cliente aún no forma parte de la base de datos",
"questionnaires_finished" to "Se han completado todos los cuestionarios para este cliente."
"questionnaires_finished" to "Se han completado todos los cuestionarios para este cliente.",
"edit" to "Editar",
"save" to "Ahorrar"
)
)
}

View File

@ -11,7 +11,6 @@ import kotlinx.coroutines.*
import java.io.File
import java.util.Calendar
// Global constants and values
const val MAX_VALUE_AGE = 122
val MAX_VALUE_YEAR = Calendar.getInstance().get(Calendar.YEAR)
@ -21,11 +20,9 @@ object GlobalValues {
var LOADED_CLIENT_CODE: String? = null
}
// Data classes for questionnaire metadata
data class QuestionnaireMeta(val id: String)
data class QuestionnaireData(val meta: QuestionnaireMeta, val questions: List<QuestionItem>)
// Abstract base class for questionnaire
abstract class QuestionnaireBase<T> {
abstract fun startQuestionnaire()
abstract fun showCurrentQuestion()
@ -35,7 +32,6 @@ abstract class QuestionnaireBase<T> {
this.languageID = language
}
// Protected properties
protected lateinit var questionnaireMeta: QuestionnaireMeta
protected var currentIndex = 0
protected lateinit var questions: List<QuestionItem>
@ -45,7 +41,6 @@ abstract class QuestionnaireBase<T> {
protected lateinit var context: Activity
private val navigationHistory = mutableListOf<Int>()
// Utility functions
protected fun showToast(message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
@ -54,7 +49,6 @@ abstract class QuestionnaireBase<T> {
return fields.all { it.text.toString().trim().isNotEmpty() }
}
// Replace placeholders in file content and save updated file
protected fun updateFileContent(fileName: String, placeholders: Map<String, Any?>) {
val file = File(context.filesDir, fileName)
if (file.exists()) {
@ -66,7 +60,6 @@ abstract class QuestionnaireBase<T> {
}
}
// Setup spinner UI element
protected fun setupSpinner(spinner: Spinner, spinnerValues: List<Any>, selectedValue: Any?) {
val adapter = ArrayAdapter(context, android.R.layout.simple_spinner_item, spinnerValues).apply {
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
@ -80,7 +73,6 @@ abstract class QuestionnaireBase<T> {
}
}
// Navigate to specific layout
protected fun navigateTo(layoutResId: Int, setup: (View) -> Unit) {
context.setContentView(layoutResId)
val rootView = context.findViewById<View>(android.R.id.content)
@ -97,17 +89,14 @@ abstract class QuestionnaireBase<T> {
}
}
// Resolve layout resource ID from layout name
protected fun getLayoutResId(layoutName: String?): Int {
return layoutName?.let {
context.resources.getIdentifier(it, "layout", context.packageName)
} ?: 0
}
// Calculate sum of all points
protected fun calculateIntegrationIndex(): Int = points.sum()
// Navigation logic
protected fun goToPreviousQuestion() {
if (navigationHistory.isNotEmpty()) {
currentIndex = navigationHistory.removeAt(navigationHistory.size - 1)
@ -134,7 +123,6 @@ abstract class QuestionnaireBase<T> {
}
}
// Load questionnaire data from JSON
protected fun loadQuestionnaireFromJson(filename: String): Pair<QuestionnaireMeta, List<QuestionItem>> {
val jsonString = context.assets.open(filename).bufferedReader().use { it.readText() }
val gson = Gson()
@ -165,9 +153,6 @@ abstract class QuestionnaireBase<T> {
return Pair(meta, questionsList)
}
// Factory to create handler for each question type
protected open fun createHandlerForQuestion(question: QuestionItem): QuestionHandler? {
return when (question) {
is QuestionItem.RadioQuestion -> HandlerRadioQuestion(context, answers, points, languageID, ::goToNextQuestion, ::goToPreviousQuestion, ::goToQuestionById, ::showToast)
@ -185,7 +170,6 @@ abstract class QuestionnaireBase<T> {
}
}
// Persist answers into database
suspend fun saveAnswersToDatabase(answers: Map<String, Any>, questionnaireId: String) {
Log.d("AnswersMap", answers.toString())
val db = MyApp.database
@ -241,8 +225,6 @@ abstract class QuestionnaireBase<T> {
db.completedQuestionnaireDao().insert(completedEntry)
}
fun endQuestionnaire() {
(context as? MainActivity)?.finishQuestionnaire()
}

View File

@ -44,16 +44,32 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView" />
<Button
android:id="@+id/loadButton"
android:layout_width="166dp"
android:layout_width="72dp"
android:layout_height="52dp"
app:layout_constraintTop_toBottomOf="@id/editText"
app:layout_constraintStart_toStartOf="@id/editText"
app:layout_constraintEnd_toEndOf="@id/editText"
app:layout_constraintHorizontal_bias="0.5"
/>
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@id/editText"
app:layout_constraintTop_toBottomOf="@id/editText" />
<Button
android:id="@+id/editButton"
android:layout_width="72dp"
android:layout_height="52dp"
app:layout_constraintEnd_toEndOf="@id/editText"
app:layout_constraintStart_toStartOf="@id/editText"
app:layout_constraintTop_toBottomOf="@id/editText" />
<Button
android:id="@+id/saveButton"
android:layout_width="72dp"
android:layout_height="52dp"
app:layout_constraintEnd_toEndOf="@id/editText"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="@id/editText"
app:layout_constraintTop_toBottomOf="@id/editText" />
<TextView
android:id="@+id/textView"