Før drastisk endring i FormsListFragment.java
This commit is contained in:
parent
56f14e9b92
commit
00028f10e5
4 changed files with 563 additions and 189 deletions
|
|
@ -1,18 +1,26 @@
|
|||
package com.kbs.kbsintranett;
|
||||
|
||||
import android.app.DatePickerDialog;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.Html;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
|
@ -28,8 +36,8 @@ import java.io.IOException;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -47,8 +55,10 @@ public class FormsFragment extends Fragment {
|
|||
private static final String TAG = "FormsFragment";
|
||||
private static final String BASE_URL_GF = "https://intranet.kbs.no/wp-json/gf/v2";
|
||||
|
||||
// ID 1 = Ansatteopplysninger (Skal ha autofyll fra historikk)
|
||||
// SKJEMA ID-er
|
||||
private static final int ID_ANSATTEOPPLYSNINGER = 1;
|
||||
private static final int ID_HMS_BEKREFTELSE = 10;
|
||||
private static final int ID_EGENMELDING = 11;
|
||||
|
||||
private int formId = 1;
|
||||
|
||||
|
|
@ -58,25 +68,27 @@ public class FormsFragment extends Fragment {
|
|||
private TextView lblHistory; // Overskriften "Tidligere innsendinger"
|
||||
private ProgressBar loadingSpinner;
|
||||
|
||||
private Map<String, EditText> dynamicFields = new HashMap<>();
|
||||
// Vi lagrer View-objektene for å kunne toggle synlighet (Conditional Logic)
|
||||
// Key = Field ID (f.eks "2", "7.1")
|
||||
private Map<String, View> fieldWrappers = new HashMap<>(); // Beholderen (Label + Input)
|
||||
private Map<String, View> inputViews = new HashMap<>(); // Selve input-feltet (EditText, RadioGroup, etc)
|
||||
private Map<String, Boolean> requiredFieldsMap = new HashMap<>();
|
||||
|
||||
private GravityForm currentForm; // Holder referanse til skjemaet for logikk-sjekk
|
||||
|
||||
private final OkHttpClient client = new OkHttpClient();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_forms, container, false);
|
||||
|
||||
formContainer = view.findViewById(R.id.form_container);
|
||||
historyContainer = view.findViewById(R.id.historyContainer);
|
||||
txtStatus = view.findViewById(R.id.txt_status);
|
||||
lblHistory = view.findViewById(R.id.lbl_history);
|
||||
loadingSpinner = view.findViewById(R.id.loading_spinner);
|
||||
|
||||
// Fallback hvis XML feiler
|
||||
if (formContainer == null) {
|
||||
// Hvis brukeren ikke har oppdatert XML ennå, unngå krasj
|
||||
formContainer = new LinearLayout(getContext());
|
||||
}
|
||||
|
||||
|
|
@ -99,11 +111,11 @@ public class FormsFragment extends Fragment {
|
|||
@Override
|
||||
public void onResponse(retrofit2.Call<GravityForm> call, retrofit2.Response<GravityForm> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
GravityForm form = response.body();
|
||||
currentForm = response.body();
|
||||
if (getActivity() != null) {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
if (loadingSpinner != null) loadingSpinner.setVisibility(View.GONE);
|
||||
renderDynamicForm(form);
|
||||
renderDynamicForm(currentForm);
|
||||
fetchFormEntries();
|
||||
});
|
||||
}
|
||||
|
|
@ -124,7 +136,8 @@ public class FormsFragment extends Fragment {
|
|||
private void renderDynamicForm(GravityForm form) {
|
||||
if (formContainer == null) return;
|
||||
formContainer.removeAllViews();
|
||||
dynamicFields.clear();
|
||||
fieldWrappers.clear();
|
||||
inputViews.clear();
|
||||
requiredFieldsMap.clear();
|
||||
updateStatus("");
|
||||
|
||||
|
|
@ -146,80 +159,109 @@ public class FormsFragment extends Fragment {
|
|||
|
||||
if (form.fields == null) return;
|
||||
|
||||
UserManager user = UserManager.getInstance();
|
||||
boolean isPersonaliaSection = true;
|
||||
|
||||
boolean hasFilledName = false;
|
||||
boolean hasFilledEmail = false;
|
||||
boolean hasFilledPhone = false;
|
||||
boolean hasFilledJob = false;
|
||||
|
||||
// Bygg feltene
|
||||
for (GravityField field : form.fields) {
|
||||
|
||||
if ("hidden".equals(field.type)) continue;
|
||||
if (field.isHidden) continue;
|
||||
if ("hidden".equals(field.visibility)) continue;
|
||||
|
||||
if ("section".equals(field.type)) {
|
||||
String labelLower = field.label.toLowerCase();
|
||||
isPersonaliaSection = labelLower.contains("personalia");
|
||||
addSectionHeader(field.label, field.description);
|
||||
// Ignorerte felttyper
|
||||
if ("hidden".equals(field.type) || field.isHidden || "hidden".equals(field.visibility)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("html".equals(field.type)) {
|
||||
if (field.content != null && field.content.toLowerCase().contains("pårørende")) {
|
||||
isPersonaliaSection = false;
|
||||
// Wrapper for hele feltet (Label + Input + Description)
|
||||
LinearLayout fieldWrapper = new LinearLayout(getContext());
|
||||
fieldWrapper.setOrientation(LinearLayout.VERTICAL);
|
||||
fieldWrapper.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
fieldWrapper.setPadding(0, 10, 0, 20);
|
||||
|
||||
// Lagre referanse til wrapperen basert på Felt-ID
|
||||
fieldWrappers.put(String.valueOf(field.id), fieldWrapper);
|
||||
|
||||
// 1. Seksjoner (Overskrifter)
|
||||
if ("section".equals(field.type)) {
|
||||
addSectionHeader(fieldWrapper, field.label, field.description);
|
||||
formContainer.addView(fieldWrapper);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2. HTML-blokker
|
||||
if ("html".equals(field.type)) {
|
||||
if (field.content != null && !field.content.isEmpty()) {
|
||||
TextView htmlView = new TextView(getContext());
|
||||
htmlView.setText(Html.fromHtml(field.content, Html.FROM_HTML_MODE_COMPACT));
|
||||
htmlView.setPadding(0, 40, 0, 10);
|
||||
formContainer.addView(htmlView);
|
||||
fieldWrapper.addView(htmlView);
|
||||
}
|
||||
formContainer.addView(fieldWrapper);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field.inputs != null && !field.inputs.isEmpty()) {
|
||||
renderCompositeField(field, isPersonaliaSection);
|
||||
continue;
|
||||
}
|
||||
|
||||
// ENKELTFELT
|
||||
// 3. Label (Overskrift for feltet)
|
||||
TextView label = new TextView(getContext());
|
||||
String labelText = field.label;
|
||||
if (field.isRequired) labelText += " *";
|
||||
label.setText(labelText);
|
||||
label.setTextColor(Color.DKGRAY);
|
||||
label.setPadding(0, 25, 0, 5);
|
||||
formContainer.addView(label);
|
||||
label.setTypeface(null, Typeface.BOLD);
|
||||
label.setPadding(0, 10, 0, 5);
|
||||
fieldWrapper.addView(label);
|
||||
|
||||
// 4. Input-felt basert på type
|
||||
if (field.inputs != null && !field.inputs.isEmpty()) {
|
||||
// Sammensatte felt (Navn, Adresse, Checkbox med inputs)
|
||||
if ("consent".equals(field.type)) {
|
||||
renderConsentField(fieldWrapper, field);
|
||||
} else if ("checkbox".equals(field.type)) {
|
||||
renderCheckboxField(fieldWrapper, field);
|
||||
} else {
|
||||
renderCompositeField(fieldWrapper, field);
|
||||
}
|
||||
} else if ("radio".equals(field.type)) {
|
||||
renderRadioField(fieldWrapper, field);
|
||||
} else if ("select".equals(field.type)) {
|
||||
renderSelectField(fieldWrapper, field);
|
||||
} else if ("textarea".equals(field.type)) {
|
||||
renderTextAreaField(fieldWrapper, field);
|
||||
} else if ("date".equals(field.type)) {
|
||||
renderDateField(fieldWrapper, field);
|
||||
} else if ("consent".equals(field.type)) {
|
||||
renderConsentField(fieldWrapper, field);
|
||||
} else {
|
||||
// Standard tekst, e-post, telefon, nummer
|
||||
renderTextField(fieldWrapper, field);
|
||||
}
|
||||
|
||||
// 5. Beskrivelse (hvis finnes)
|
||||
if (field.description != null && !field.description.isEmpty()) {
|
||||
TextView desc = new TextView(getContext());
|
||||
desc.setText(Html.fromHtml(field.description, Html.FROM_HTML_MODE_COMPACT));
|
||||
desc.setTextSize(12);
|
||||
desc.setTextColor(Color.GRAY);
|
||||
fieldWrapper.addView(desc);
|
||||
}
|
||||
|
||||
formContainer.addView(fieldWrapper);
|
||||
}
|
||||
|
||||
// SEND-KNAPP
|
||||
Button dynamicSubmit = new Button(getContext());
|
||||
dynamicSubmit.setText("Send inn skjema");
|
||||
dynamicSubmit.setTextColor(Color.WHITE);
|
||||
dynamicSubmit.setBackgroundColor(Color.parseColor("#0069B3")); // KBS Blå
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.setMargins(0, 60, 0, 20);
|
||||
dynamicSubmit.setLayoutParams(params);
|
||||
dynamicSubmit.setOnClickListener(v -> submitDynamicForm());
|
||||
formContainer.addView(dynamicSubmit);
|
||||
|
||||
// Etter at alt er tegnet, kjør en initial sjekk på logikken
|
||||
evaluateAllConditionalLogic();
|
||||
}
|
||||
|
||||
// --- RENDER METHODS ---
|
||||
|
||||
private void renderTextField(LinearLayout container, GravityField field) {
|
||||
EditText input = new EditText(getContext());
|
||||
input.setPadding(30, 30, 30, 30);
|
||||
input.setBackgroundResource(android.R.drawable.edit_text);
|
||||
|
||||
// Autofyll fra UserManager (Standardinfo som alltid er greit å fylle ut)
|
||||
if (isPersonaliaSection) {
|
||||
String lowerLabel = field.label.toLowerCase();
|
||||
|
||||
if (!hasFilledName && (lowerLabel.equals("navn") || lowerLabel.equals("navn *"))) {
|
||||
input.setText(user.getUserDisplayName());
|
||||
hasFilledName = true;
|
||||
}
|
||||
else if (!hasFilledEmail && lowerLabel.contains("e-post") && lowerLabel.contains("arbeid")) {
|
||||
input.setText(user.getUserEmail());
|
||||
hasFilledEmail = true;
|
||||
}
|
||||
else if (!hasFilledJob && lowerLabel.contains("stilling")) {
|
||||
input.setText(user.getStilling());
|
||||
hasFilledJob = true;
|
||||
}
|
||||
else if (!hasFilledPhone && (lowerLabel.contains("mobil") || lowerLabel.equals("mobiltelefon"))) {
|
||||
input.setText(user.getMobiltelefon());
|
||||
hasFilledPhone = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ("number".equals(field.type) || "phone".equals(field.type)) {
|
||||
input.setInputType(InputType.TYPE_CLASS_PHONE);
|
||||
} else if ("email".equals(field.type)) {
|
||||
|
|
@ -228,69 +270,211 @@ public class FormsFragment extends Fragment {
|
|||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
}
|
||||
|
||||
formContainer.addView(input);
|
||||
|
||||
if (field.description != null && !field.description.isEmpty()) {
|
||||
addDescription(field.description);
|
||||
}
|
||||
|
||||
dynamicFields.put(String.valueOf(field.id), input);
|
||||
requiredFieldsMap.put(String.valueOf(field.id), field.isRequired);
|
||||
}
|
||||
|
||||
// SEND-KNAPP
|
||||
Button dynamicSubmit = new Button(getContext());
|
||||
dynamicSubmit.setText("Send inn skjema");
|
||||
dynamicSubmit.setTextColor(Color.WHITE);
|
||||
dynamicSubmit.setBackgroundColor(Color.parseColor("#0069B3")); // KBS Blå
|
||||
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
params.setMargins(0, 60, 0, 20);
|
||||
dynamicSubmit.setLayoutParams(params);
|
||||
|
||||
dynamicSubmit.setOnClickListener(v -> submitDynamicForm());
|
||||
formContainer.addView(dynamicSubmit);
|
||||
}
|
||||
|
||||
private void renderCompositeField(GravityField parentField, boolean isPersonaliaSection) {
|
||||
TextView groupLabel = new TextView(getContext());
|
||||
String groupText = parentField.label;
|
||||
if (parentField.isRequired) groupText += " *";
|
||||
groupLabel.setText(groupText);
|
||||
groupLabel.setTextColor(Color.DKGRAY);
|
||||
groupLabel.setTypeface(null, Typeface.BOLD);
|
||||
groupLabel.setPadding(0, 30, 0, 5);
|
||||
formContainer.addView(groupLabel);
|
||||
|
||||
UserManager user = UserManager.getInstance();
|
||||
String lowerParentLabel = parentField.label.toLowerCase();
|
||||
String lowerLabel = field.label.toLowerCase();
|
||||
|
||||
List<GravityField> inputs = new ArrayList<>(parentField.inputs);
|
||||
// Autofyll Logikk
|
||||
if (formId == ID_ANSATTEOPPLYSNINGER) {
|
||||
if (lowerLabel.contains("e-post") && lowerLabel.contains("arbeid")) {
|
||||
input.setText(user.getUserEmail());
|
||||
} else if (lowerLabel.contains("stilling")) {
|
||||
input.setText(user.getStilling());
|
||||
} else if ((lowerLabel.contains("mobil") || lowerLabel.equals("mobiltelefon"))) {
|
||||
input.setText(user.getMobiltelefon());
|
||||
}
|
||||
}
|
||||
else if (formId == ID_HMS_BEKREFTELSE) {
|
||||
if (lowerLabel.contains("e-post")) {
|
||||
input.setText(user.getUserEmail());
|
||||
}
|
||||
}
|
||||
else if (formId == ID_EGENMELDING) {
|
||||
if (lowerLabel.contains("navn")) {
|
||||
input.setText(user.getUserDisplayName());
|
||||
} else if (lowerLabel.contains("stilling")) {
|
||||
input.setText(user.getStilling());
|
||||
} else if (lowerLabel.contains("e-post")) {
|
||||
input.setText(user.getUserEmail());
|
||||
}
|
||||
}
|
||||
|
||||
// Sortering for adresse
|
||||
if (parentField.type.equals("address")) {
|
||||
Collections.sort(inputs, new Comparator<GravityField>() {
|
||||
// Lytter for å trigge Conditional Logic når tekst endres
|
||||
input.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public int compare(GravityField f1, GravityField f2) {
|
||||
int s1 = getAddressScore(f1.label);
|
||||
int s2 = getAddressScore(f2.label);
|
||||
return Integer.compare(s1, s2);
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
evaluateAllConditionalLogic();
|
||||
}
|
||||
});
|
||||
|
||||
container.addView(input);
|
||||
inputViews.put(field.id, input);
|
||||
requiredFieldsMap.put(field.id, field.isRequired);
|
||||
}
|
||||
|
||||
private void renderTextAreaField(LinearLayout container, GravityField field) {
|
||||
EditText input = new EditText(getContext());
|
||||
input.setPadding(30, 30, 30, 30);
|
||||
input.setBackgroundResource(android.R.drawable.edit_text);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
|
||||
input.setMinLines(3);
|
||||
input.setGravity(android.view.Gravity.TOP | android.view.Gravity.START);
|
||||
|
||||
input.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
evaluateAllConditionalLogic();
|
||||
}
|
||||
});
|
||||
|
||||
container.addView(input);
|
||||
inputViews.put(field.id, input);
|
||||
requiredFieldsMap.put(field.id, field.isRequired);
|
||||
}
|
||||
|
||||
private void renderRadioField(LinearLayout container, GravityField field) {
|
||||
RadioGroup group = new RadioGroup(getContext());
|
||||
group.setOrientation(RadioGroup.VERTICAL);
|
||||
|
||||
if (field.choices != null) {
|
||||
for (GravityField.Choice choice : field.choices) {
|
||||
RadioButton rb = new RadioButton(getContext());
|
||||
rb.setText(choice.text);
|
||||
rb.setTag(choice.value);
|
||||
group.addView(rb);
|
||||
}
|
||||
}
|
||||
|
||||
// Lytter for Conditional Logic
|
||||
group.setOnCheckedChangeListener((group1, checkedId) -> evaluateAllConditionalLogic());
|
||||
|
||||
container.addView(group);
|
||||
inputViews.put(field.id, group);
|
||||
requiredFieldsMap.put(field.id, field.isRequired);
|
||||
}
|
||||
|
||||
private void renderSelectField(LinearLayout container, GravityField field) {
|
||||
Spinner spinner = new Spinner(getContext());
|
||||
List<String> labels = new ArrayList<>();
|
||||
labels.add("- Velg -");
|
||||
|
||||
if (field.choices != null) {
|
||||
for (GravityField.Choice c : field.choices) {
|
||||
labels.add(c.text);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, labels);
|
||||
spinner.setAdapter(adapter);
|
||||
|
||||
container.addView(spinner);
|
||||
inputViews.put(field.id, spinner);
|
||||
requiredFieldsMap.put(field.id, field.isRequired);
|
||||
}
|
||||
|
||||
private void renderConsentField(LinearLayout container, GravityField field) {
|
||||
CheckBox checkBox = new CheckBox(getContext());
|
||||
String cbText = (field.checkboxLabel != null && !field.checkboxLabel.isEmpty())
|
||||
? field.checkboxLabel
|
||||
: field.label;
|
||||
checkBox.setText(cbText);
|
||||
checkBox.setTextSize(16);
|
||||
checkBox.setPadding(10, 10, 10, 10);
|
||||
|
||||
String inputId = field.id;
|
||||
if (field.inputs != null && !field.inputs.isEmpty()) {
|
||||
inputId = field.inputs.get(0).id;
|
||||
}
|
||||
|
||||
checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> evaluateAllConditionalLogic());
|
||||
|
||||
container.addView(checkBox);
|
||||
inputViews.put(inputId, checkBox);
|
||||
requiredFieldsMap.put(inputId, field.isRequired);
|
||||
}
|
||||
|
||||
private void renderCheckboxField(LinearLayout container, GravityField field) {
|
||||
// I Gravity Forms er checkboxes en liste av inputs hvis det er flere valg.
|
||||
// Hvis det bare er ett valg (som "Jeg bekrefter..."), er det ofte én input.
|
||||
|
||||
// Sjekk om det er inputs
|
||||
if (field.inputs != null) {
|
||||
for (GravityField inputDef : field.inputs) {
|
||||
CheckBox checkBox = new CheckBox(getContext());
|
||||
checkBox.setText(inputDef.label);
|
||||
checkBox.setTextSize(16);
|
||||
checkBox.setPadding(10, 10, 10, 10);
|
||||
|
||||
// Verdien som sendes er vanligvis etiketten hvis den er huket av.
|
||||
checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> evaluateAllConditionalLogic());
|
||||
|
||||
container.addView(checkBox);
|
||||
inputViews.put(inputDef.id, checkBox);
|
||||
// Checkboxer er sjeldent individuelt påkrevd i en gruppe, men selve feltet er.
|
||||
// Vi markerer den spesifikke boksen som påkrevd hvis feltet er det og det bare er én.
|
||||
if (field.inputs.size() == 1) {
|
||||
requiredFieldsMap.put(inputDef.id, field.isRequired);
|
||||
} else {
|
||||
// Hvis det er flere, er validering mer komplekst (minst én må velges).
|
||||
// Foreløpig enkel implementasjon.
|
||||
requiredFieldsMap.put(inputDef.id, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderDateField(LinearLayout container, GravityField field) {
|
||||
EditText dateInput = new EditText(getContext());
|
||||
dateInput.setPadding(30, 30, 30, 30);
|
||||
dateInput.setBackgroundResource(android.R.drawable.edit_text);
|
||||
dateInput.setFocusable(false); // Hindre tastatur
|
||||
dateInput.setClickable(true); // Tillat klikk
|
||||
dateInput.setHint("dd.mm.yyyy");
|
||||
|
||||
dateInput.setOnClickListener(v -> {
|
||||
final Calendar c = Calendar.getInstance();
|
||||
int year = c.get(Calendar.YEAR);
|
||||
int month = c.get(Calendar.MONTH);
|
||||
int day = c.get(Calendar.DAY_OF_MONTH);
|
||||
|
||||
DatePickerDialog datePickerDialog = new DatePickerDialog(getContext(),
|
||||
(view, year1, monthOfYear, dayOfMonth) -> {
|
||||
// Format: dd.MM.yyyy
|
||||
String selectedDate = String.format(java.util.Locale.getDefault(), "%02d.%02d.%d", dayOfMonth, monthOfYear + 1, year1);
|
||||
dateInput.setText(selectedDate);
|
||||
evaluateAllConditionalLogic();
|
||||
}, year, month, day);
|
||||
datePickerDialog.show();
|
||||
});
|
||||
|
||||
container.addView(dateInput);
|
||||
inputViews.put(field.id, dateInput);
|
||||
requiredFieldsMap.put(field.id, field.isRequired);
|
||||
}
|
||||
|
||||
private void renderCompositeField(LinearLayout container, GravityField parentField) {
|
||||
UserManager user = UserManager.getInstance();
|
||||
boolean isPersonalia = (formId == ID_ANSATTEOPPLYSNINGER);
|
||||
|
||||
List<GravityField> inputs = new ArrayList<>(parentField.inputs);
|
||||
if ("address".equals(parentField.type)) {
|
||||
Collections.sort(inputs, (f1, f2) -> Integer.compare(getAddressScore(f1.label), getAddressScore(f2.label)));
|
||||
}
|
||||
|
||||
for (GravityField subField : inputs) {
|
||||
if (subField.isHidden) continue;
|
||||
if ("hidden".equals(subField.visibility)) continue;
|
||||
if (subField.isHidden || "hidden".equals(subField.visibility)) continue;
|
||||
|
||||
TextView subLabel = new TextView(getContext());
|
||||
String subLabelText = subField.label;
|
||||
|
||||
boolean isSubRequired = parentField.isRequired;
|
||||
if (parentField.type.equals("address") && subField.id.endsWith(".2")) {
|
||||
if ("address".equals(parentField.type) && subField.id.endsWith(".2")) {
|
||||
isSubRequired = false;
|
||||
}
|
||||
if (isSubRequired) subLabelText += " *";
|
||||
|
|
@ -299,32 +483,47 @@ public class FormsFragment extends Fragment {
|
|||
subLabel.setTextColor(Color.GRAY);
|
||||
subLabel.setTextSize(12);
|
||||
subLabel.setPadding(0, 10, 0, 0);
|
||||
formContainer.addView(subLabel);
|
||||
container.addView(subLabel);
|
||||
|
||||
EditText subInput = new EditText(getContext());
|
||||
subInput.setPadding(30, 30, 30, 30);
|
||||
subInput.setBackgroundResource(android.R.drawable.edit_text);
|
||||
subInput.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
|
||||
if (isPersonaliaSection && lowerParentLabel.contains("navn") && !lowerParentLabel.contains("pårørende")) {
|
||||
String lowerSubLabel = subField.label.toLowerCase();
|
||||
if (lowerSubLabel.contains("fornavn")) {
|
||||
subInput.setText(user.getFirstName());
|
||||
}
|
||||
else if (lowerSubLabel.contains("etternavn")) {
|
||||
subInput.setText(user.getLastName());
|
||||
}
|
||||
if (isPersonalia && parentField.label.toLowerCase().contains("navn") && !parentField.label.toLowerCase().contains("pårørende")) {
|
||||
String lowerSub = subField.label.toLowerCase();
|
||||
if (lowerSub.contains("fornavn")) subInput.setText(user.getFirstName());
|
||||
else if (lowerSub.contains("etternavn")) subInput.setText(user.getLastName());
|
||||
}
|
||||
|
||||
formContainer.addView(subInput);
|
||||
|
||||
dynamicFields.put(subField.id, subInput);
|
||||
container.addView(subInput);
|
||||
inputViews.put(subField.id, subInput);
|
||||
requiredFieldsMap.put(subField.id, isSubRequired);
|
||||
}
|
||||
|
||||
if (parentField.description != null && !parentField.description.isEmpty()) {
|
||||
addDescription(parentField.description);
|
||||
}
|
||||
|
||||
private void addSectionHeader(LinearLayout container, String title, String descText) {
|
||||
TextView sectionHeader = new TextView(getContext());
|
||||
sectionHeader.setText(title);
|
||||
sectionHeader.setTextSize(18);
|
||||
sectionHeader.setTypeface(null, Typeface.BOLD);
|
||||
sectionHeader.setTextColor(Color.parseColor("#0069B3"));
|
||||
sectionHeader.setPadding(0, 20, 0, 5);
|
||||
container.addView(sectionHeader);
|
||||
|
||||
if (descText != null && !descText.isEmpty()) {
|
||||
TextView desc = new TextView(getContext());
|
||||
desc.setText(Html.fromHtml(descText, Html.FROM_HTML_MODE_COMPACT));
|
||||
desc.setTextSize(12);
|
||||
desc.setTextColor(Color.GRAY);
|
||||
container.addView(desc);
|
||||
}
|
||||
|
||||
View line = new View(getContext());
|
||||
line.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 2));
|
||||
line.setBackgroundColor(Color.LTGRAY);
|
||||
line.setPadding(0,0,0,20);
|
||||
container.addView(line);
|
||||
}
|
||||
|
||||
private int getAddressScore(String label) {
|
||||
|
|
@ -338,33 +537,103 @@ public class FormsFragment extends Fragment {
|
|||
return 99;
|
||||
}
|
||||
|
||||
private void addDescription(String text) {
|
||||
TextView desc = new TextView(getContext());
|
||||
desc.setText(Html.fromHtml(text, Html.FROM_HTML_MODE_COMPACT));
|
||||
desc.setTextSize(12);
|
||||
desc.setTextColor(Color.GRAY);
|
||||
desc.setPadding(5, 5, 5, 0);
|
||||
formContainer.addView(desc);
|
||||
// --- CONDITIONAL LOGIC ENGINE ---
|
||||
|
||||
private void evaluateAllConditionalLogic() {
|
||||
if (currentForm == null || currentForm.fields == null) return;
|
||||
|
||||
for (GravityField field : currentForm.fields) {
|
||||
if (field.conditionalLogic == null) {
|
||||
setViewVisibility(field.id, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
private void addSectionHeader(String title, String descText) {
|
||||
TextView sectionHeader = new TextView(getContext());
|
||||
sectionHeader.setText(title);
|
||||
sectionHeader.setTextSize(18);
|
||||
sectionHeader.setTypeface(null, Typeface.BOLD);
|
||||
sectionHeader.setTextColor(Color.parseColor("#0069B3"));
|
||||
sectionHeader.setPadding(0, 50, 0, 5);
|
||||
formContainer.addView(sectionHeader);
|
||||
|
||||
if (descText != null && !descText.isEmpty()) {
|
||||
addDescription(descText);
|
||||
boolean isMatch = evaluateLogic(field.conditionalLogic);
|
||||
boolean show = "show".equalsIgnoreCase(field.conditionalLogic.actionType);
|
||||
boolean shouldBeVisible = (show && isMatch) || (!show && !isMatch);
|
||||
setViewVisibility(field.id, shouldBeVisible);
|
||||
}
|
||||
}
|
||||
|
||||
View line = new View(getContext());
|
||||
line.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 2));
|
||||
line.setBackgroundColor(Color.LTGRAY);
|
||||
formContainer.addView(line);
|
||||
private boolean evaluateLogic(GravityField.ConditionalLogic logic) {
|
||||
if (logic.rules == null || logic.rules.isEmpty()) return true;
|
||||
|
||||
boolean isAll = "all".equalsIgnoreCase(logic.logicType);
|
||||
boolean aggregatedResult = isAll;
|
||||
|
||||
for (GravityField.Rule rule : logic.rules) {
|
||||
String val = getInputValue(rule.fieldId);
|
||||
boolean ruleMatch = checkRule(val, rule.operator, rule.value);
|
||||
|
||||
if (isAll) {
|
||||
aggregatedResult = aggregatedResult && ruleMatch;
|
||||
if (!aggregatedResult) break;
|
||||
} else {
|
||||
aggregatedResult = aggregatedResult || ruleMatch;
|
||||
if (aggregatedResult) break;
|
||||
}
|
||||
}
|
||||
return aggregatedResult;
|
||||
}
|
||||
|
||||
private boolean checkRule(String actualValue, String operator, String targetValue) {
|
||||
if (actualValue == null) actualValue = "";
|
||||
if (targetValue == null) targetValue = "";
|
||||
|
||||
switch (operator.toLowerCase()) {
|
||||
case "is":
|
||||
return actualValue.equalsIgnoreCase(targetValue);
|
||||
case "isnot":
|
||||
return !actualValue.equalsIgnoreCase(targetValue);
|
||||
case "contains":
|
||||
return actualValue.toLowerCase().contains(targetValue.toLowerCase());
|
||||
case "starts_with":
|
||||
return actualValue.toLowerCase().startsWith(targetValue.toLowerCase());
|
||||
case "ends_with":
|
||||
return actualValue.toLowerCase().endsWith(targetValue.toLowerCase());
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String getInputValue(String fieldId) {
|
||||
View view = inputViews.get(fieldId);
|
||||
if (view == null) return "";
|
||||
|
||||
if (view instanceof EditText) {
|
||||
return ((EditText) view).getText().toString();
|
||||
} else if (view instanceof RadioGroup) {
|
||||
RadioGroup group = (RadioGroup) view;
|
||||
int checkedId = group.getCheckedRadioButtonId();
|
||||
if (checkedId != -1) {
|
||||
View rb = group.findViewById(checkedId);
|
||||
if (rb != null && rb.getTag() != null) {
|
||||
return rb.getTag().toString();
|
||||
}
|
||||
}
|
||||
} else if (view instanceof Spinner) {
|
||||
Spinner spinner = (Spinner) view;
|
||||
Object item = spinner.getSelectedItem();
|
||||
return item != null ? item.toString() : "";
|
||||
} else if (view instanceof CheckBox) {
|
||||
CheckBox cb = (CheckBox) view;
|
||||
// Hvis sjekket: returner teksten på boksen eller "1" (for consent)
|
||||
// For standard checkbox i GF brukes ofte verdien som er valgt.
|
||||
// Hvis det er en enkel avkryssing (type "Bekreftelse"), er "Ja" eller "1" vanlig.
|
||||
// Vi returnerer teksten hvis den er sjekket, ellers tom streng.
|
||||
return cb.isChecked() ? cb.getText().toString() : "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private void setViewVisibility(String fieldId, boolean visible) {
|
||||
View wrapper = fieldWrappers.get(fieldId);
|
||||
if (wrapper != null) {
|
||||
wrapper.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
// --- DATA HANDLING ---
|
||||
|
||||
private void fetchFormEntries() {
|
||||
UserManager user = UserManager.getInstance();
|
||||
|
|
@ -404,8 +673,8 @@ public class FormsFragment extends Fragment {
|
|||
getActivity().runOnUiThread(() -> {
|
||||
showHistory(entries);
|
||||
|
||||
// VIKTIG: AUTO-FYLL SKJER NÅ KUN FOR SKJEMA ID 1
|
||||
if (entries.length() > 0 && formId == ID_ANSATTEOPPLYSNINGER) {
|
||||
// VIKTIG: AUTO-FYLL SKJER KUN FOR SKJEMA ID 1 ("Ansatteopplysninger")
|
||||
if (formId == ID_ANSATTEOPPLYSNINGER && entries.length() > 0) {
|
||||
try {
|
||||
prefillFormFromHistory(entries.getJSONObject(0));
|
||||
} catch (JSONException e) { e.printStackTrace(); }
|
||||
|
|
@ -420,35 +689,74 @@ public class FormsFragment extends Fragment {
|
|||
}
|
||||
|
||||
private void prefillFormFromHistory(JSONObject latestEntry) {
|
||||
for (Map.Entry<String, EditText> mapEntry : dynamicFields.entrySet()) {
|
||||
String fieldId = mapEntry.getKey();
|
||||
EditText input = mapEntry.getValue();
|
||||
if (latestEntry == null) return;
|
||||
|
||||
if (input.getText().length() > 0) continue;
|
||||
for (Map.Entry<String, View> entry : inputViews.entrySet()) {
|
||||
String fieldId = entry.getKey();
|
||||
View view = entry.getValue();
|
||||
|
||||
if (latestEntry.has(fieldId)) {
|
||||
String prevValue = latestEntry.optString(fieldId);
|
||||
if (!prevValue.isEmpty()) {
|
||||
input.setText(prevValue);
|
||||
String value = latestEntry.optString(fieldId);
|
||||
if (value == null || value.isEmpty()) continue;
|
||||
|
||||
if (view instanceof EditText) {
|
||||
((EditText) view).setText(value);
|
||||
} else if (view instanceof RadioGroup) {
|
||||
RadioGroup group = (RadioGroup) view;
|
||||
for (int i = 0; i < group.getChildCount(); i++) {
|
||||
View child = group.getChildAt(i);
|
||||
if (child instanceof RadioButton) {
|
||||
Object tag = child.getTag();
|
||||
if (tag != null && tag.toString().equalsIgnoreCase(value)) {
|
||||
((RadioButton) child).setChecked(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
updateStatus("Skjemaet er forhåndsutfylt fra din forrige innsending.");
|
||||
} else if (view instanceof CheckBox) {
|
||||
// For Consent er value "1" = Checked.
|
||||
// For vanlig checkbox kan det være verdien av valget.
|
||||
if ("1".equals(value) || "true".equalsIgnoreCase(value) || ((CheckBox)view).getText().toString().equals(value)) {
|
||||
((CheckBox) view).setChecked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateStatus("Skjemaet er forhåndsutfylt fra din siste innsending.");
|
||||
evaluateAllConditionalLogic();
|
||||
}
|
||||
|
||||
private void submitDynamicForm() {
|
||||
JSONObject inputValues = new JSONObject();
|
||||
boolean hasValues = false;
|
||||
|
||||
for (Map.Entry<String, EditText> entry : dynamicFields.entrySet()) {
|
||||
for (Map.Entry<String, View> entry : inputViews.entrySet()) {
|
||||
String fieldId = entry.getKey();
|
||||
EditText input = entry.getValue();
|
||||
String value = input.getText().toString().trim();
|
||||
View view = entry.getValue();
|
||||
|
||||
// Hopp over hvis feltet er skjult av Conditional Logic
|
||||
View wrapper = fieldWrappers.get(fieldId);
|
||||
// Hvis wrapper er null (f.eks sub-input), sjekk parent wrapper
|
||||
if (wrapper == null) {
|
||||
// Forenklet sjekk: hvis selve viewet ikke vises på skjermen
|
||||
if (!view.isShown()) continue;
|
||||
} else {
|
||||
if (wrapper.getVisibility() != View.VISIBLE) continue;
|
||||
}
|
||||
|
||||
String value = getInputValue(fieldId);
|
||||
|
||||
// Validering
|
||||
Boolean isRequired = requiredFieldsMap.get(fieldId);
|
||||
if (isRequired != null && isRequired && value.isEmpty()) {
|
||||
input.setError("Må fylles ut");
|
||||
input.requestFocus();
|
||||
if (view instanceof EditText) {
|
||||
((EditText) view).setError("Må fylles ut");
|
||||
view.requestFocus();
|
||||
} else if (view instanceof CheckBox) {
|
||||
Toast.makeText(getContext(), "Du må bekrefte " + ((CheckBox)view).getText(), Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Vennligst fyll ut alle obligatoriske felt.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -477,7 +785,6 @@ public class FormsFragment extends Fragment {
|
|||
}
|
||||
|
||||
Request request = new Request.Builder().url(url).post(body).header("Cookie", cookie).build();
|
||||
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
|
|
@ -492,6 +799,9 @@ public class FormsFragment extends Fragment {
|
|||
Toast.makeText(getContext(), "Skjema sendt!", Toast.LENGTH_LONG).show();
|
||||
fetchFormEntries();
|
||||
updateStatus("Innsending OK");
|
||||
if (formId != ID_ANSATTEOPPLYSNINGER) {
|
||||
clearInputs();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
@ -501,12 +811,20 @@ public class FormsFragment extends Fragment {
|
|||
});
|
||||
}
|
||||
|
||||
private void clearInputs() {
|
||||
for (View view : inputViews.values()) {
|
||||
if (view instanceof EditText) ((EditText) view).setText("");
|
||||
if (view instanceof RadioGroup) ((RadioGroup) view).clearCheck();
|
||||
if (view instanceof Spinner) ((Spinner) view).setSelection(0);
|
||||
if (view instanceof CheckBox) ((CheckBox) view).setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void showHistory(JSONArray entries) {
|
||||
if (historyContainer == null) return;
|
||||
historyContainer.removeAllViews();
|
||||
|
||||
if (entries.length() == 0) {
|
||||
// Skjul overskriften hvis det ikke er historikk
|
||||
if (lblHistory != null) lblHistory.setVisibility(View.GONE);
|
||||
return;
|
||||
} else {
|
||||
|
|
@ -514,19 +832,19 @@ public class FormsFragment extends Fragment {
|
|||
}
|
||||
|
||||
try {
|
||||
for (int i = 0; i < entries.length(); i++) {
|
||||
int count = Math.min(entries.length(), 5);
|
||||
for (int i = 0; i < count; i++) {
|
||||
JSONObject entry = entries.getJSONObject(i);
|
||||
String date = entry.optString("date_created");
|
||||
TextView item = new TextView(getContext());
|
||||
item.setText(date);
|
||||
item.setText("Innsendt: " + date);
|
||||
item.setPadding(10, 20, 10, 20);
|
||||
|
||||
// Gjør historikken klikkbar (for fremtidig funksjonalitet)
|
||||
item.setBackgroundResource(android.R.drawable.list_selector_background);
|
||||
|
||||
View line = new View(getContext());
|
||||
line.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1));
|
||||
line.setBackgroundColor(Color.LTGRAY);
|
||||
|
||||
historyContainer.addView(item);
|
||||
historyContainer.addView(line);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package com.kbs.kbsintranett;
|
|||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -15,8 +17,13 @@ import androidx.annotation.Nullable;
|
|||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
|
|
@ -24,6 +31,7 @@ import retrofit2.Response;
|
|||
|
||||
public class FormsListFragment extends Fragment {
|
||||
|
||||
private static final String TAG = "FormsListFragment";
|
||||
private LinearLayout container;
|
||||
private ProgressBar loadingSpinner;
|
||||
private TextView txtStatus;
|
||||
|
|
@ -31,23 +39,16 @@ public class FormsListFragment extends Fragment {
|
|||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
// Vi gjenbruker samme layout som detaljvisningen, siden den nå er ryddig
|
||||
View view = inflater.inflate(R.layout.fragment_forms, container, false);
|
||||
|
||||
this.container = view.findViewById(R.id.form_container);
|
||||
this.loadingSpinner = view.findViewById(R.id.loading_spinner);
|
||||
this.txtStatus = view.findViewById(R.id.txt_status);
|
||||
|
||||
// Skjul "Tidligere innsendinger" tekst og container på denne siden,
|
||||
// da vi kun skal vise en meny her.
|
||||
View historyTitle = view.findViewById(R.id.historyContainer); // Egentlig containeren, men vi skjuler alt under
|
||||
View historyTitle = view.findViewById(R.id.historyContainer);
|
||||
if (historyTitle != null) historyTitle.setVisibility(View.GONE);
|
||||
|
||||
// Finn og skjul "Tidligere innsendinger" overskriften hvis mulig
|
||||
// (Siden vi bruker en delt XML er dette litt "hacky", men funker)
|
||||
LinearLayout mainLayout = view.findViewById(R.id.main_layout);
|
||||
if (mainLayout != null && mainLayout.getChildCount() > 4) {
|
||||
// Skjuler elementene nederst som hører til historikk
|
||||
for(int i = 0; i < mainLayout.getChildCount(); i++) {
|
||||
View child = mainLayout.getChildAt(i);
|
||||
if (child instanceof TextView && ((TextView)child).getText().toString().contains("Tidligere")) {
|
||||
|
|
@ -70,34 +71,56 @@ public class FormsListFragment extends Fragment {
|
|||
if (loadingSpinner != null) loadingSpinner.setVisibility(View.VISIBLE);
|
||||
if (txtStatus != null) txtStatus.setText("");
|
||||
|
||||
// Hent listen over skjemaer (Map ID -> Skjema)
|
||||
Log.d(TAG, "Starter henting av skjemaer...");
|
||||
|
||||
RetrofitClient.getApiService().getFormsListMap().enqueue(new Callback<Map<String, GravityForm>>() {
|
||||
@Override
|
||||
public void onResponse(Call<Map<String, GravityForm>> call, Response<Map<String, GravityForm>> response) {
|
||||
if (getContext() == null) return;
|
||||
|
||||
// SKJUL SPINNER NÅR VI FÅR SVAR
|
||||
if (loadingSpinner != null) loadingSpinner.setVisibility(View.GONE);
|
||||
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
Map<String, GravityForm> formMap = response.body();
|
||||
Log.d(TAG, "Fant " + formMap.size() + " skjemaer totalt.");
|
||||
|
||||
if (formMap.isEmpty()) {
|
||||
if (txtStatus != null) txtStatus.setText("Ingen skjemaer funnet.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Vi sorterer listen basert på ID (eller tittel) for ryddighet
|
||||
Map<String, GravityForm> sortedMap = new TreeMap<>(formMap);
|
||||
List<GravityForm> visibleForms = new ArrayList<>();
|
||||
for (GravityForm form : formMap.values()) {
|
||||
boolean isActive = form.isActive == null || !"0".equals(form.isActive);
|
||||
Integer sortOrder = getSortOrderFromDescription(form);
|
||||
|
||||
for (Map.Entry<String, GravityForm> entry : sortedMap.entrySet()) {
|
||||
GravityForm form = entry.getValue();
|
||||
// Sjekk at skjemaet er aktivt og har en tittel
|
||||
if (form != null && form.title != null) {
|
||||
// Logg hva vi finner for hvert skjema
|
||||
Log.d(TAG, "Skjema: " + form.title + " | ID: " + form.id + " | Beskrivelse: " + form.description + " | Sorteringstall funnet: " + sortOrder);
|
||||
|
||||
if (form != null && form.title != null && isActive && sortOrder != null) {
|
||||
visibleForms.add(form);
|
||||
}
|
||||
}
|
||||
|
||||
if (visibleForms.isEmpty()) {
|
||||
Log.w(TAG, "Alle skjemaer ble filtrert bort. Sjekk at beskrivelsene starter med et tall.");
|
||||
if (txtStatus != null) txtStatus.setText("Ingen tilgjengelige skjemaer i appen.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Sorter basert på tallet vi fant
|
||||
Collections.sort(visibleForms, new Comparator<GravityForm>() {
|
||||
@Override
|
||||
public int compare(GravityForm f1, GravityForm f2) {
|
||||
return Integer.compare(getSortOrderFromDescription(f1), getSortOrderFromDescription(f2));
|
||||
}
|
||||
});
|
||||
|
||||
for (GravityForm form : visibleForms) {
|
||||
addFormButton(form);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Log.e(TAG, "Feil fra server: " + response.code());
|
||||
if (txtStatus != null) txtStatus.setText("Kunne ikke laste listen (Kode " + response.code() + ")");
|
||||
}
|
||||
}
|
||||
|
|
@ -105,34 +128,59 @@ public class FormsListFragment extends Fragment {
|
|||
@Override
|
||||
public void onFailure(Call<Map<String, GravityForm>> call, Throwable t) {
|
||||
if (getContext() == null) return;
|
||||
// SKJUL SPINNER VED FEIL
|
||||
if (loadingSpinner != null) loadingSpinner.setVisibility(View.GONE);
|
||||
Log.e(TAG, "Nettverksfeil", t);
|
||||
if (txtStatus != null) txtStatus.setText("Nettverksfeil: " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Leter etter et tall i starten av beskrivelsen.
|
||||
* Håndterer HTML-tags og mellomrom.
|
||||
*/
|
||||
private Integer getSortOrderFromDescription(GravityForm form) {
|
||||
if (form.description == null || form.description.isEmpty()) {
|
||||
return null; // Skjules
|
||||
}
|
||||
|
||||
// 1. Fjern HTML-tags for å få ren tekst (f.eks "<p>10.</p>" -> "10.")
|
||||
String cleanText = Html.fromHtml(form.description, Html.FROM_HTML_MODE_COMPACT).toString().trim();
|
||||
|
||||
// 2. Regex: Finn første sekvens av tall (\d+)
|
||||
// ^\D* betyr "Start på linjen, ignorer ikke-tall (som bokstaver/tegn) i starten"
|
||||
Pattern p = Pattern.compile("^\\D*(\\d+)");
|
||||
Matcher m = p.matcher(cleanText);
|
||||
|
||||
if (m.find()) {
|
||||
try {
|
||||
return Integer.parseInt(m.group(1));
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null; // Ingen tall funnet -> Skjules
|
||||
}
|
||||
|
||||
private void addFormButton(GravityForm form) {
|
||||
Button button = new Button(getContext());
|
||||
button.setText(form.title.toUpperCase()); // Store bokstaver ser ofte ryddigere ut i menyer
|
||||
button.setText(form.title.toUpperCase());
|
||||
button.setTextColor(Color.WHITE);
|
||||
button.setBackgroundColor(Color.parseColor("#0069B3")); // KBS Blå
|
||||
button.setTextSize(14);
|
||||
button.setPadding(30, 30, 30, 30);
|
||||
|
||||
// Klikk-lytter
|
||||
button.setOnClickListener(v -> {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt("formId", form.id);
|
||||
Navigation.findNavController(v).navigate(R.id.action_formsListFragment_to_formsDetailFragment, bundle);
|
||||
});
|
||||
|
||||
// Layout parametere (Marginer)
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
params.setMargins(0, 0, 0, 20); // Avstand mellom knappene
|
||||
params.setMargins(0, 0, 0, 20);
|
||||
button.setLayoutParams(params);
|
||||
|
||||
container.addView(button);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@ public class GravityField {
|
|||
@SerializedName("label")
|
||||
public String label;
|
||||
|
||||
// --- DETTE ER FELTET SOM MANGLER ---
|
||||
@SerializedName("adminLabel")
|
||||
public String adminLabel;
|
||||
// -----------------------------------
|
||||
|
||||
@SerializedName("description")
|
||||
public String description;
|
||||
|
||||
|
|
@ -46,7 +51,7 @@ public class GravityField {
|
|||
@SerializedName("conditionalLogic")
|
||||
public ConditionalLogic conditionalLogic;
|
||||
|
||||
// NYTT: For å lese Populate Anything-regler
|
||||
// For å lese Populate Anything-regler
|
||||
@SerializedName("gppa-values-templates")
|
||||
public java.util.Map<String, String> gppaTemplates;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ public class GravityForm {
|
|||
@SerializedName("description")
|
||||
public String description;
|
||||
|
||||
@SerializedName("is_active")
|
||||
public String isActive; // "1" = Aktiv, "0" = Inaktiv
|
||||
|
||||
@SerializedName("fields")
|
||||
public List<GravityField> fields; // En liste med alle feltene i skjemaet
|
||||
public List<GravityField> fields;
|
||||
}
|
||||
Loading…
Reference in a new issue