Panagiotis Triantafyllou

questionnaire part1

1 package ly.warp.sdk.activities; 1 package ly.warp.sdk.activities;
2 2
3 import android.app.Activity; 3 import android.app.Activity;
4 -import android.content.ActivityNotFoundException;
5 import android.content.Intent; 4 import android.content.Intent;
6 -import android.net.Uri;
7 import android.os.Bundle; 5 import android.os.Bundle;
6 +import android.os.Handler;
8 import android.os.Parcelable; 7 import android.os.Parcelable;
9 import android.text.TextUtils; 8 import android.text.TextUtils;
10 import android.util.TypedValue; 9 import android.util.TypedValue;
...@@ -21,12 +20,16 @@ import androidx.appcompat.content.res.AppCompatResources; ...@@ -21,12 +20,16 @@ import androidx.appcompat.content.res.AppCompatResources;
21 import androidx.constraintlayout.widget.ConstraintLayout; 20 import androidx.constraintlayout.widget.ConstraintLayout;
22 import androidx.recyclerview.widget.LinearLayoutManager; 21 import androidx.recyclerview.widget.LinearLayoutManager;
23 import androidx.recyclerview.widget.RecyclerView; 22 import androidx.recyclerview.widget.RecyclerView;
24 -import androidx.viewpager2.widget.ViewPager2;
25 23
26 import com.bumptech.glide.Glide; 24 import com.bumptech.glide.Glide;
27 import com.bumptech.glide.load.engine.DiskCacheStrategy; 25 import com.bumptech.glide.load.engine.DiskCacheStrategy;
28 import com.google.android.material.bottomsheet.BottomSheetBehavior; 26 import com.google.android.material.bottomsheet.BottomSheetBehavior;
29 import com.google.android.material.bottomsheet.BottomSheetDialog; 27 import com.google.android.material.bottomsheet.BottomSheetDialog;
28 +import com.google.common.util.concurrent.FutureCallback;
29 +import com.google.common.util.concurrent.Futures;
30 +import com.google.common.util.concurrent.ListenableFuture;
31 +import com.google.common.util.concurrent.MoreExecutors;
32 +import com.google.common.util.concurrent.SettableFuture;
30 33
31 import java.util.ArrayList; 34 import java.util.ArrayList;
32 import java.util.LinkedHashMap; 35 import java.util.LinkedHashMap;
...@@ -46,7 +49,6 @@ import ly.warp.sdk.utils.WarpUtils; ...@@ -46,7 +49,6 @@ import ly.warp.sdk.utils.WarpUtils;
46 import ly.warp.sdk.utils.WarplyManagerHelper; 49 import ly.warp.sdk.utils.WarplyManagerHelper;
47 import ly.warp.sdk.utils.managers.WarplyManager; 50 import ly.warp.sdk.utils.managers.WarplyManager;
48 import ly.warp.sdk.views.HorizontalSpaceItemDecoration; 51 import ly.warp.sdk.views.HorizontalSpaceItemDecoration;
49 -import ly.warp.sdk.views.VerticalSpaceItemDecoration;
50 52
51 public class HomeActivity extends Activity implements View.OnClickListener, CouponsetAdapter.OnCouponsetClickListener { 53 public class HomeActivity extends Activity implements View.OnClickListener, CouponsetAdapter.OnCouponsetClickListener {
52 // =========================================================== 54 // ===========================================================
...@@ -73,6 +75,9 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup ...@@ -73,6 +75,9 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup
73 private ConstraintLayout mViewPager; 75 private ConstraintLayout mViewPager;
74 private LinearLayout mSectionsContainer; 76 private LinearLayout mSectionsContainer;
75 private RelativeLayout mSectionsLoading; 77 private RelativeLayout mSectionsLoading;
78 + private int mCurrentQuestionIndex = 1;
79 + private SettableFuture<ArrayList<CarouselItem>> carouselFuture = SettableFuture.create();
80 + private SettableFuture<LinkedHashMap<String, ArrayList<Couponset>>> couponsetsFuture = SettableFuture.create();
76 81
77 // =========================================================== 82 // ===========================================================
78 // Methods for/from SuperClass/Interfaces 83 // Methods for/from SuperClass/Interfaces
...@@ -89,15 +94,36 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup ...@@ -89,15 +94,36 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup
89 findViewById(R.id.header_layout), 94 findViewById(R.id.header_layout),
90 null); 95 null);
91 96
92 - setUpUser();
93 -
94 mPbLoading.setVisibility(View.VISIBLE); 97 mPbLoading.setVisibility(View.VISIBLE);
95 mSectionsLoading.setVisibility(View.VISIBLE); 98 mSectionsLoading.setVisibility(View.VISIBLE);
96 99
100 + setUpUser();
101 +
97 WarplyManager.getCoupons(mCouponsCallback); 102 WarplyManager.getCoupons(mCouponsCallback);
98 WarplyManager.getCarousel(mCarouselCallback); 103 WarplyManager.getCarousel(mCarouselCallback);
99 WarplyManager.getCouponsets(null, null, mCouponsetsCallback); 104 WarplyManager.getCouponsets(null, null, mCouponsetsCallback);
100 -// WarplyManager.getFilters(mFiltersCallback); 105 +
106 + ListenableFuture<List<Object>> allFutures = Futures.successfulAsList(
107 + carouselFuture,
108 + couponsetsFuture
109 + );
110 +
111 + Futures.addCallback(allFutures, new FutureCallback<List<Object>>() {
112 + @Override
113 + public void onSuccess(List<Object> result) {
114 + runOnUiThread(() -> {
115 + User user = WarplyManagerHelper.getUser();
116 + if (user != null && user.getQuestionnaireAnswers() == null && user.getQuestionnaire() != null) {
117 + new Handler(getMainLooper()).postDelayed(() -> showQuestionnaireDialog(user.getQuestionnaire()), 1000);
118 + }
119 + });
120 + }
121 +
122 + @Override
123 + public void onFailure(Throwable t) {
124 +
125 + }
126 + }, MoreExecutors.directExecutor());
101 } 127 }
102 128
103 @Override 129 @Override
...@@ -489,6 +515,7 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup ...@@ -489,6 +515,7 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup
489 behavior.setSkipCollapsed(true); 515 behavior.setSkipCollapsed(true);
490 behavior.setPeekHeight(screenHeight); 516 behavior.setPeekHeight(screenHeight);
491 behavior.setState(BottomSheetBehavior.STATE_EXPANDED); 517 behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
518 + behavior.setDraggable(false);
492 }); 519 });
493 } 520 }
494 }); 521 });
...@@ -509,6 +536,170 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup ...@@ -509,6 +536,170 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup
509 return null; 536 return null;
510 } 537 }
511 538
539 + private void showQuestionnaireDialog(User.Questionnaire questionnaire) {
540 + if (questionnaire.getQuestions() == null || questionnaire.getQuestions().isEmpty()) return;
541 +
542 + BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(this, R.style.FullScreenBottomSheetDialog);
543 + View dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_fullscreen_questionnaire, null);
544 + bottomSheetDialog.setContentView(dialogView);
545 +
546 + ImageView ivClose = dialogView.findViewById(R.id.iv_back);
547 + ivClose.setOnClickListener(v -> bottomSheetDialog.dismiss());
548 +
549 + mCurrentQuestionIndex = 1;
550 + renderQuestion(questionnaire, dialogView, bottomSheetDialog);
551 +
552 + bottomSheetDialog.setOnShowListener(dialog -> {
553 + View bottomSheet = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
554 + if (bottomSheet != null) {
555 + bottomSheet.post(() -> {
556 + int screenHeight = getResources().getDisplayMetrics().heightPixels;
557 + ViewGroup.LayoutParams lp = bottomSheet.getLayoutParams();
558 + lp.height = screenHeight;
559 + bottomSheet.setLayoutParams(lp);
560 + BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(bottomSheet);
561 + behavior.setSkipCollapsed(true);
562 + behavior.setPeekHeight(screenHeight);
563 + behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
564 + behavior.setDraggable(false);
565 + });
566 + }
567 + });
568 + bottomSheetDialog.show();
569 + }
570 +
571 + private void renderQuestion(User.Questionnaire questionnaire, View dialogView, BottomSheetDialog dialog) {
572 + if (mCurrentQuestionIndex >= questionnaire.getQuestions().size()) {
573 + return;
574 + }
575 +
576 + TextView tvQuestionCount = dialogView.findViewById(R.id.tv_question_count);
577 + tvQuestionCount.setText(String.valueOf(mCurrentQuestionIndex) + "/" + String.valueOf(questionnaire.getQuestions().size()));
578 +
579 + TextView tvQuestionHeaderTitle = dialogView.findViewById(R.id.tv_question_header_title);
580 + TextView tvQuestionHeaderSubtitle = dialogView.findViewById(R.id.tv_question_subtitle);
581 +
582 + User.Question question = questionnaire.getQuestions().get(mCurrentQuestionIndex);
583 + TextView tvQuestionTitle = dialogView.findViewById(R.id.tv_question_title);
584 + LinearLayout llOptionsContainer = dialogView.findViewById(R.id.ll_options_container);
585 + LinearLayout llNextButton = dialogView.findViewById(R.id.ll_next_button);
586 +
587 + tvQuestionTitle.setText(question.getQuestion());
588 + WarpUtils.renderCustomFont(this, R.font.ping_lcg_bold, tvQuestionTitle,
589 + tvQuestionCount, tvQuestionHeaderTitle);
590 + WarpUtils.renderCustomFont(this, R.font.ping_lcg_regular, tvQuestionHeaderSubtitle);
591 +
592 + llOptionsContainer.removeAllViews();
593 +
594 + org.json.JSONArray options = question.getOptions();
595 + String type = question.getType();
596 +
597 + List<Integer> selectedPositions = new ArrayList<>();
598 +
599 + if ("select".equals(type)) {
600 + tvQuestionHeaderSubtitle.setVisibility(View.GONE);
601 + View dropdownHeader = LayoutInflater.from(this).inflate(R.layout.item_questionnaire_option, llOptionsContainer, false);
602 + LinearLayout llDropdownContainer = dropdownHeader.findViewById(R.id.ll_option_container);
603 + TextView tvDropdownTitle = dropdownHeader.findViewById(R.id.tv_option_title);
604 + tvDropdownTitle.setText(getString(R.string.demo_region_title));
605 + WarpUtils.renderCustomFont(this, R.font.ping_lcg_regular, tvDropdownTitle);
606 + llDropdownContainer.setBackground(AppCompatResources.getDrawable(this, R.drawable.shape_questionnaire_option_unselected));
607 + tvDropdownTitle.setTextColor(getColor(R.color.custom_black2));
608 +
609 + LinearLayout llDropdownList = new LinearLayout(this);
610 + llDropdownList.setOrientation(LinearLayout.VERTICAL);
611 + llDropdownList.setVisibility(View.GONE);
612 +
613 + if (options != null) {
614 + for (int i = 0; i < options.length(); i++) {
615 + final int position = i;
616 + String optionText = options.optString(i);
617 + View optionView = LayoutInflater.from(this).inflate(R.layout.item_questionnaire_option, llDropdownList, false);
618 + LinearLayout llOptionContainer = optionView.findViewById(R.id.ll_option_container);
619 + TextView tvOptionTitle = optionView.findViewById(R.id.tv_option_title);
620 + tvOptionTitle.setText(optionText);
621 + WarpUtils.renderCustomFont(this, R.font.ping_lcg_regular, tvOptionTitle);
622 + llOptionContainer.setBackground(AppCompatResources.getDrawable(this, R.drawable.shape_questionnaire_option_unselected));
623 + tvOptionTitle.setTextColor(getColor(R.color.custom_black2));
624 +
625 + optionView.setOnClickListener(v -> {
626 + selectedPositions.clear();
627 + selectedPositions.add(position);
628 + tvDropdownTitle.setText(optionText);
629 + llDropdownList.setVisibility(View.GONE);
630 + llDropdownContainer.setBackground(AppCompatResources.getDrawable(this, R.drawable.shape_rectangle_rounded_light_blue_tr));
631 + tvDropdownTitle.setTextColor(getColor(R.color.white));
632 + });
633 + llDropdownList.addView(optionView);
634 + }
635 + }
636 +
637 + dropdownHeader.setOnClickListener(v -> {
638 + boolean isExpanded = llDropdownList.getVisibility() == View.VISIBLE;
639 + llDropdownList.setVisibility(isExpanded ? View.GONE : View.VISIBLE);
640 + });
641 +
642 + llOptionsContainer.addView(dropdownHeader);
643 + llOptionsContainer.addView(llDropdownList);
644 + } else {
645 + if ("string".equals(type)) {
646 + tvQuestionHeaderSubtitle.setVisibility(View.GONE);
647 + } else if ("multi".equals(type)) {
648 + tvQuestionHeaderSubtitle.setVisibility(View.VISIBLE);
649 + }
650 + if (options != null) {
651 + for (int i = 0; i < options.length(); i++) {
652 + final int position = i;
653 + String optionText = options.optString(i);
654 + if (optionText.startsWith("[")) continue;
655 +
656 + View optionView = LayoutInflater.from(this).inflate(R.layout.item_questionnaire_option, llOptionsContainer, false);
657 +// View separator = LayoutInflater.from(this).inflate(R.layout.item_questionnaire_separator, llOptionsContainer, false);
658 + LinearLayout llOptionContainer = optionView.findViewById(R.id.ll_option_container);
659 + TextView tvOptionTitle = optionView.findViewById(R.id.tv_option_title);
660 + tvOptionTitle.setText(optionText);
661 + WarpUtils.renderCustomFont(this, R.font.ping_lcg_bold, tvOptionTitle);
662 + llOptionContainer.setBackground(AppCompatResources.getDrawable(this, R.drawable.shape_questionnaire_option_unselected));
663 +
664 + optionView.setOnClickListener(v -> {
665 + if ("string".equals(type)) {
666 + selectedPositions.clear();
667 + selectedPositions.add(position);
668 + } else if ("multi".equals(type)) {
669 + if (selectedPositions.contains(position)) {
670 + selectedPositions.remove(Integer.valueOf(position));
671 + } else {
672 + selectedPositions.add(position);
673 + }
674 + }
675 +
676 + for (int j = 0; j < llOptionsContainer.getChildCount(); j++) {
677 + View childView = llOptionsContainer.getChildAt(j);
678 + LinearLayout childContainer = childView.findViewById(R.id.ll_option_container);
679 + if (childContainer == null) continue;
680 + if (selectedPositions.contains(j)) {
681 + childContainer.setBackground(AppCompatResources.getDrawable(this, R.drawable.shape_questionnaire_option_selected));
682 + } else {
683 + childContainer.setBackground(AppCompatResources.getDrawable(this, R.drawable.shape_questionnaire_option_unselected));
684 + }
685 + }
686 + });
687 + llOptionsContainer.addView(optionView);
688 +// llOptionsContainer.addView(separator);
689 + }
690 + }
691 + }
692 +
693 + llNextButton.setOnClickListener(v -> {
694 + if (mCurrentQuestionIndex < questionnaire.getQuestions().size() - 1) {
695 + mCurrentQuestionIndex++;
696 + renderQuestion(questionnaire, dialogView, dialog);
697 + } else {
698 + // Final screen, leave action empty as requested
699 + }
700 + });
701 + }
702 +
512 private final CallbackReceiver<ArrayList<CarouselItem>> mCarouselCallback = new CallbackReceiver<ArrayList<CarouselItem>>() { 703 private final CallbackReceiver<ArrayList<CarouselItem>> mCarouselCallback = new CallbackReceiver<ArrayList<CarouselItem>>() {
513 @Override 704 @Override
514 public void onSuccess(ArrayList<CarouselItem> result) { 705 public void onSuccess(ArrayList<CarouselItem> result) {
...@@ -526,12 +717,14 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup ...@@ -526,12 +717,14 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup
526 } else { 717 } else {
527 mViewPager.setVisibility(View.GONE); 718 mViewPager.setVisibility(View.GONE);
528 } 719 }
720 + carouselFuture.set(result);
529 } 721 }
530 722
531 @Override 723 @Override
532 public void onFailure(int errorCode) { 724 public void onFailure(int errorCode) {
533 mPbLoading.setVisibility(View.GONE); 725 mPbLoading.setVisibility(View.GONE);
534 mViewPager.setVisibility(View.GONE); 726 mViewPager.setVisibility(View.GONE);
727 + carouselFuture.set(new ArrayList<CarouselItem>());
535 } 728 }
536 }; 729 };
537 730
...@@ -542,11 +735,14 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup ...@@ -542,11 +735,14 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup
542 if (result != null && !result.isEmpty()) { 735 if (result != null && !result.isEmpty()) {
543 setupCouponsetSections(result); 736 setupCouponsetSections(result);
544 } 737 }
738 +
739 + couponsetsFuture.set(result);
545 } 740 }
546 741
547 @Override 742 @Override
548 public void onFailure(int errorCode) { 743 public void onFailure(int errorCode) {
549 mSectionsLoading.setVisibility(View.GONE); 744 mSectionsLoading.setVisibility(View.GONE);
745 + couponsetsFuture.set(new LinkedHashMap<String, ArrayList<Couponset>>());
550 } 746 }
551 }; 747 };
552 748
...@@ -567,16 +763,4 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup ...@@ -567,16 +763,4 @@ public class HomeActivity extends Activity implements View.OnClickListener, Coup
567 Toast.makeText(HomeActivity.this, "COUPONS ERROR", Toast.LENGTH_SHORT).show(); 763 Toast.makeText(HomeActivity.this, "COUPONS ERROR", Toast.LENGTH_SHORT).show();
568 } 764 }
569 }; 765 };
570 -
571 -// private final CallbackReceiver<Filter> mFiltersCallback = new CallbackReceiver<Filter>() {
572 -// @Override
573 -// public void onSuccess(Filter result) {
574 -// Toast.makeText(HomeActivity.this, "FILTERS SUCCESS", Toast.LENGTH_SHORT).show();
575 -// }
576 -//
577 -// @Override
578 -// public void onFailure(int errorCode) {
579 -// Toast.makeText(HomeActivity.this, "FILTERS ERROR", Toast.LENGTH_SHORT).show();
580 -// }
581 -// };
582 } 766 }
......
...@@ -221,8 +221,8 @@ public class SingleCouponActivity extends Activity implements View.OnClickListen ...@@ -221,8 +221,8 @@ public class SingleCouponActivity extends Activity implements View.OnClickListen
221 .into(mIvImage); 221 .into(mIvImage);
222 } 222 }
223 223
224 - if (mOfferItem.getCouponsetDetails() != null && mOfferItem.getCouponsetDetails().getMerchantAdminName() != null && !TextUtils.isEmpty(mOfferItem.getCouponsetDetails().getMerchantAdminName())) 224 + if (mOfferItem.getMerchantDetails() != null && mOfferItem.getMerchantDetails().getName() != null && !TextUtils.isEmpty(mOfferItem.getMerchantDetails().getName()))
225 - mTvMerchantName.setText(mOfferItem.getCouponsetDetails().getMerchantAdminName()); 225 + mTvMerchantName.setText(mOfferItem.getMerchantDetails().getName());
226 if (mOfferItem.getCouponsetDetails() != null && mOfferItem.getCouponsetDetails().getName() != null && !TextUtils.isEmpty(mOfferItem.getCouponsetDetails().getName())) 226 if (mOfferItem.getCouponsetDetails() != null && mOfferItem.getCouponsetDetails().getName() != null && !TextUtils.isEmpty(mOfferItem.getCouponsetDetails().getName()))
227 mTvValue.setText(mOfferItem.getCouponsetDetails().getName()); 227 mTvValue.setText(mOfferItem.getCouponsetDetails().getName());
228 if (mOfferItem.getCouponsetDetails() != null && mOfferItem.getCouponsetDetails().getShort_description() != null && !TextUtils.isEmpty(mOfferItem.getCouponsetDetails().getShort_description())) 228 if (mOfferItem.getCouponsetDetails() != null && mOfferItem.getCouponsetDetails().getShort_description() != null && !TextUtils.isEmpty(mOfferItem.getCouponsetDetails().getShort_description()))
......
...@@ -170,7 +170,7 @@ public class CouponAdapter extends RecyclerView.Adapter<CouponAdapter.CouponView ...@@ -170,7 +170,7 @@ public class CouponAdapter extends RecyclerView.Adapter<CouponAdapter.CouponView
170 llDateExpired.setVisibility(View.GONE); 170 llDateExpired.setVisibility(View.GONE);
171 } 171 }
172 172
173 - tvMerchant.setText(!TextUtils.isEmpty(couponItem.getCouponsetDetails().getMerchantAdminName()) ? couponItem.getCouponsetDetails().getMerchantAdminName().trim() : ""); 173 + tvMerchant.setText(!TextUtils.isEmpty(couponItem.getMerchantDetails().getName()) ? couponItem.getMerchantDetails().getName().trim() : "");
174 tvTitle.setText(!TextUtils.isEmpty(couponItem.getCouponsetDetails().getName()) ? couponItem.getCouponsetDetails().getName().trim() : ""); 174 tvTitle.setText(!TextUtils.isEmpty(couponItem.getCouponsetDetails().getName()) ? couponItem.getCouponsetDetails().getName().trim() : "");
175 tvDescription.setText(!TextUtils.isEmpty(couponItem.getCouponsetDetails().getShort_description()) ? couponItem.getCouponsetDetails().getShort_description().trim() : ""); 175 tvDescription.setText(!TextUtils.isEmpty(couponItem.getCouponsetDetails().getShort_description()) ? couponItem.getCouponsetDetails().getShort_description().trim() : "");
176 if (couponItem.getExpiration() != null && !couponItem.getExpiration().isEmpty()) { 176 if (couponItem.getExpiration() != null && !couponItem.getExpiration().isEmpty()) {
......
...@@ -71,7 +71,7 @@ public class User implements Parcelable, Serializable { ...@@ -71,7 +71,7 @@ public class User implements Parcelable, Serializable {
71 private boolean isEligible = false; 71 private boolean isEligible = false;
72 private String msisdn; 72 private String msisdn;
73 private String profileMetadata; 73 private String profileMetadata;
74 - private JSONObject questionnaire; 74 + private Questionnaire questionnaire;
75 private JSONObject questionnaireAnswers; 75 private JSONObject questionnaireAnswers;
76 private JSONObject userAnswers; 76 private JSONObject userAnswers;
77 private String userId; 77 private String userId;
...@@ -127,7 +127,7 @@ public class User implements Parcelable, Serializable { ...@@ -127,7 +127,7 @@ public class User implements Parcelable, Serializable {
127 this.isEligible = json.optBoolean(IS_ELIGIBLE); 127 this.isEligible = json.optBoolean(IS_ELIGIBLE);
128 this.msisdn = optNullableString(json, MSISDN); 128 this.msisdn = optNullableString(json, MSISDN);
129 this.profileMetadata = optNullableString(json, PROFILE_METADATA); 129 this.profileMetadata = optNullableString(json, PROFILE_METADATA);
130 - this.questionnaire = json.optJSONObject(QUESTIONNAIRE); 130 + this.questionnaire = json.isNull(QUESTIONNAIRE) ? null : new Questionnaire(json.optJSONObject(QUESTIONNAIRE));
131 this.questionnaireAnswers = json.optJSONObject(QUESTIONNAIRE_ANSWERS); 131 this.questionnaireAnswers = json.optJSONObject(QUESTIONNAIRE_ANSWERS);
132 this.userAnswers = json.optJSONObject(USER_ANSWERS); 132 this.userAnswers = json.optJSONObject(USER_ANSWERS);
133 this.userId = optNullableString(json, USER_ID); 133 this.userId = optNullableString(json, USER_ID);
...@@ -158,7 +158,7 @@ public class User implements Parcelable, Serializable { ...@@ -158,7 +158,7 @@ public class User implements Parcelable, Serializable {
158 } 158 }
159 try { 159 try {
160 String questionnaireStr = source.readString(); 160 String questionnaireStr = source.readString();
161 - this.questionnaire = questionnaireStr != null ? new JSONObject(questionnaireStr) : null; 161 + this.questionnaire = questionnaireStr != null ? new Questionnaire(new JSONObject(questionnaireStr)) : null;
162 } catch (JSONException e) { 162 } catch (JSONException e) {
163 this.questionnaire = null; 163 this.questionnaire = null;
164 } 164 }
...@@ -214,7 +214,7 @@ public class User implements Parcelable, Serializable { ...@@ -214,7 +214,7 @@ public class User implements Parcelable, Serializable {
214 jObj.putOpt(IS_ELIGIBLE, this.isEligible); 214 jObj.putOpt(IS_ELIGIBLE, this.isEligible);
215 jObj.put(MSISDN, this.msisdn != null ? this.msisdn : JSONObject.NULL); 215 jObj.put(MSISDN, this.msisdn != null ? this.msisdn : JSONObject.NULL);
216 jObj.put(PROFILE_METADATA, this.profileMetadata != null ? this.profileMetadata : JSONObject.NULL); 216 jObj.put(PROFILE_METADATA, this.profileMetadata != null ? this.profileMetadata : JSONObject.NULL);
217 - jObj.put(QUESTIONNAIRE, this.questionnaire != null ? this.questionnaire : JSONObject.NULL); 217 + jObj.put(QUESTIONNAIRE, this.questionnaire != null ? this.questionnaire.toJSONObject() : JSONObject.NULL);
218 jObj.put(QUESTIONNAIRE_ANSWERS, this.questionnaireAnswers != null ? this.questionnaireAnswers : JSONObject.NULL); 218 jObj.put(QUESTIONNAIRE_ANSWERS, this.questionnaireAnswers != null ? this.questionnaireAnswers : JSONObject.NULL);
219 jObj.put(USER_ANSWERS, this.userAnswers != null ? this.userAnswers : JSONObject.NULL); 219 jObj.put(USER_ANSWERS, this.userAnswers != null ? this.userAnswers : JSONObject.NULL);
220 jObj.put(USER_ID, this.userId != null ? this.userId : JSONObject.NULL); 220 jObj.put(USER_ID, this.userId != null ? this.userId : JSONObject.NULL);
...@@ -308,7 +308,7 @@ public class User implements Parcelable, Serializable { ...@@ -308,7 +308,7 @@ public class User implements Parcelable, Serializable {
308 return profileMetadata; 308 return profileMetadata;
309 } 309 }
310 310
311 - public JSONObject getQuestionnaire() { 311 + public Questionnaire getQuestionnaire() {
312 return questionnaire; 312 return questionnaire;
313 } 313 }
314 314
...@@ -368,7 +368,7 @@ public class User implements Parcelable, Serializable { ...@@ -368,7 +368,7 @@ public class User implements Parcelable, Serializable {
368 this.profileMetadata = profileMetadata; 368 this.profileMetadata = profileMetadata;
369 } 369 }
370 370
371 - public void setQuestionnaire(JSONObject questionnaire) { 371 + public void setQuestionnaire(Questionnaire questionnaire) {
372 this.questionnaire = questionnaire; 372 this.questionnaire = questionnaire;
373 } 373 }
374 374
...@@ -416,4 +416,190 @@ public class User implements Parcelable, Serializable { ...@@ -416,4 +416,190 @@ public class User implements Parcelable, Serializable {
416 } 416 }
417 return listData; 417 return listData;
418 } 418 }
419 +
420 + public static class Questionnaire implements Parcelable, Serializable {
421 + private String questionnaireId;
422 + private ArrayList<Question> questions;
423 +
424 + public Questionnaire() {
425 + this.questionnaireId = null;
426 + this.questions = new ArrayList<>();
427 + }
428 +
429 + public Questionnaire(JSONObject json) {
430 + if (json != null) {
431 + this.questionnaireId = json.isNull("questionnaire_id") ? null : json.optString("questionnaire_id");
432 + this.questions = new ArrayList<>();
433 + JSONArray questionsArr = json.optJSONArray("questions");
434 + if (questionsArr != null) {
435 + for (int i = 0; i < questionsArr.length(); i++) {
436 + JSONObject qJson = questionsArr.optJSONObject(i);
437 + if (qJson != null) {
438 + this.questions.add(new Question(qJson));
439 + }
440 + }
441 + }
442 + }
443 + }
444 +
445 + protected Questionnaire(Parcel in) {
446 + questionnaireId = in.readString();
447 + questions = in.createTypedArrayList(Question.CREATOR);
448 + }
449 +
450 + @Override
451 + public void writeToParcel(Parcel dest, int flags) {
452 + dest.writeString(questionnaireId);
453 + dest.writeTypedList(questions);
454 + }
455 +
456 + @Override
457 + public int describeContents() {
458 + return 0;
459 + }
460 +
461 + public static final Creator<Questionnaire> CREATOR = new Creator<Questionnaire>() {
462 + @Override
463 + public Questionnaire createFromParcel(Parcel in) {
464 + return new Questionnaire(in);
465 + }
466 +
467 + @Override
468 + public Questionnaire[] newArray(int size) {
469 + return new Questionnaire[size];
470 + }
471 + };
472 +
473 + public JSONObject toJSONObject() {
474 + JSONObject jObj = new JSONObject();
475 + try {
476 + jObj.put("questionnaire_id", this.questionnaireId != null ? this.questionnaireId : JSONObject.NULL);
477 + JSONArray qArr = new JSONArray();
478 + if (this.questions != null) {
479 + for (Question q : this.questions) {
480 + qArr.put(q.toJSONObject());
481 + }
482 + }
483 + jObj.put("questions", qArr);
484 + } catch (JSONException e) {
485 + if (WarpConstants.DEBUG) e.printStackTrace();
486 + }
487 + return jObj;
488 + }
489 +
490 + public String getQuestionnaireId() { return questionnaireId; }
491 + public void setQuestionnaireId(String questionnaireId) { this.questionnaireId = questionnaireId; }
492 + public ArrayList<Question> getQuestions() { return questions; }
493 + public void setQuestions(ArrayList<Question> questions) { this.questions = questions; }
494 + }
495 +
496 + public static class Question implements Parcelable, Serializable {
497 + private String adminName;
498 + private int id;
499 + private JSONArray options;
500 + private String question;
501 + private JSONObject settings;
502 + private int sorting;
503 + private String type;
504 + private int version;
505 +
506 + public Question() {}
507 +
508 + public Question(JSONObject json) {
509 + if (json != null) {
510 + this.adminName = json.isNull("admin_name") ? null : json.optString("admin_name");
511 + this.id = json.optInt("id", -1);
512 + this.options = json.optJSONArray("options");
513 + this.question = json.isNull("question") ? null : json.optString("question");
514 + this.settings = json.optJSONObject("settings");
515 + this.sorting = json.optInt("sorting", 0);
516 + this.type = json.isNull("type") ? null : json.optString("type");
517 + this.version = json.optInt("version", 0);
518 + }
519 + }
520 +
521 + protected Question(Parcel in) {
522 + adminName = in.readString();
523 + id = in.readInt();
524 + try {
525 + String optionsStr = in.readString();
526 + options = optionsStr != null ? new JSONArray(optionsStr) : null;
527 + } catch (JSONException e) {
528 + options = null;
529 + }
530 + question = in.readString();
531 + try {
532 + String settingsStr = in.readString();
533 + settings = settingsStr != null ? new JSONObject(settingsStr) : null;
534 + } catch (JSONException e) {
535 + settings = null;
536 + }
537 + sorting = in.readInt();
538 + type = in.readString();
539 + version = in.readInt();
540 + }
541 +
542 + @Override
543 + public void writeToParcel(Parcel dest, int flags) {
544 + dest.writeString(adminName);
545 + dest.writeInt(id);
546 + dest.writeString(options != null ? options.toString() : null);
547 + dest.writeString(question);
548 + dest.writeString(settings != null ? settings.toString() : null);
549 + dest.writeInt(sorting);
550 + dest.writeString(type);
551 + dest.writeInt(version);
552 + }
553 +
554 + @Override
555 + public int describeContents() {
556 + return 0;
557 + }
558 +
559 + public static final Creator<Question> CREATOR = new Creator<Question>() {
560 + @Override
561 + public Question createFromParcel(Parcel in) {
562 + return new Question(in);
563 + }
564 +
565 + @Override
566 + public Question[] newArray(int size) {
567 + return new Question[size];
568 + }
569 + };
570 +
571 + public JSONObject toJSONObject() {
572 + JSONObject jObj = new JSONObject();
573 + try {
574 + jObj.put("admin_name", this.adminName != null ? this.adminName : JSONObject.NULL);
575 + jObj.put("id", this.id);
576 + jObj.put("options", this.options != null ? this.options : JSONObject.NULL);
577 + jObj.put("question", this.question != null ? this.question : JSONObject.NULL);
578 + jObj.put("settings", this.settings != null ? this.settings : JSONObject.NULL);
579 + jObj.put("sorting", this.sorting);
580 + jObj.put("type", this.type != null ? this.type : JSONObject.NULL);
581 + jObj.put("version", this.version);
582 + } catch (JSONException e) {
583 + if (WarpConstants.DEBUG) e.printStackTrace();
584 + }
585 + return jObj;
586 + }
587 +
588 + public String getAdminName() { return adminName; }
589 + public void setAdminName(String adminName) { this.adminName = adminName; }
590 + public int getId() { return id; }
591 + public void setId(int id) { this.id = id; }
592 + public JSONArray getOptions() { return options; }
593 + public void setOptions(JSONArray options) { this.options = options; }
594 + public String getQuestion() { return question; }
595 + public void setQuestion(String question) { this.question = question; }
596 + public JSONObject getSettings() { return settings; }
597 + public void setSettings(JSONObject settings) { this.settings = settings; }
598 + public int getSorting() { return sorting; }
599 + public void setSorting(int sorting) { this.sorting = sorting; }
600 + public String getType() { return type; }
601 + public void setType(String type) { this.type = type; }
602 + public int getVersion() { return version; }
603 + public void setVersion(int version) { this.version = version; }
604 + }
419 } 605 }
......
...@@ -192,6 +192,18 @@ public interface ApiService { ...@@ -192,6 +192,18 @@ public interface ApiService {
192 @Header(WarpConstants.HEADER_SIGNATURE) String signature, 192 @Header(WarpConstants.HEADER_SIGNATURE) String signature,
193 @Header(WarpConstants.HEADER_AUTHORIZATION) String bearer); 193 @Header(WarpConstants.HEADER_AUTHORIZATION) String bearer);
194 194
195 + @Headers("Content-Type: application/json")
196 + @POST("/oauth/{appUuid}/context")
197 + Call<ResponseBody> getQuestionnaire(@Path("appUuid") String appUuid,
198 + @Body RequestBody request,
199 + @Header(WarpConstants.HEADER_DATE) String timeStamp,
200 + @Header(WarpConstants.HEADER_LOYALTY_BUNDLE_ID) String bundleId,
201 + @Header(WarpConstants.HEADER_UNIQUE_DEVICE_ID) String deviceId,
202 + @Header(WarpConstants.HEADER_CHANNEL) String channel,
203 + @Header(WarpConstants.HEADER_WEB_ID) String webId,
204 + @Header(WarpConstants.HEADER_SIGNATURE) String signature,
205 + @Header(WarpConstants.HEADER_AUTHORIZATION) String bearer);
206 +
195 // =========================================================== 207 // ===========================================================
196 // Getter & Setter 208 // Getter & Setter
197 // =========================================================== 209 // ===========================================================
......
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<shape xmlns:android="http://schemas.android.com/apk/res/android"
3 + android:shape="rectangle">
4 + <corners android:radius="14dp" />
5 +
6 + <solid android:color="@color/white" />
7 +
8 + <stroke android:width="2dp" android:color="@color/custom_black7" />
9 +</shape>
...\ No newline at end of file ...\ No newline at end of file
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<shape xmlns:android="http://schemas.android.com/apk/res/android"
3 + android:shape="rectangle">
4 + <corners android:radius="14dp" />
5 +
6 + <solid android:color="@color/white" />
7 +
8 + <stroke android:width="1dp" android:color="@color/custom_grey7" />
9 +</shape>
...\ No newline at end of file ...\ No newline at end of file
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 + xmlns:app="http://schemas.android.com/apk/res-auto"
4 + xmlns:tools="http://schemas.android.com/tools"
5 + android:layout_width="match_parent"
6 + android:layout_height="match_parent"
7 + android:background="@color/white">
8 +
9 + <LinearLayout
10 + android:id="@+id/header_layout"
11 + android:layout_width="match_parent"
12 + android:layout_height="wrap_content"
13 + android:layout_gravity="center"
14 + android:background="@color/white"
15 + android:gravity="center_vertical"
16 + android:orientation="horizontal"
17 + android:padding="16dp"
18 + app:layout_constraintEnd_toEndOf="parent"
19 + app:layout_constraintStart_toStartOf="parent"
20 + app:layout_constraintTop_toTopOf="parent">
21 +
22 + <LinearLayout
23 + android:layout_width="0dp"
24 + android:layout_height="wrap_content"
25 + android:layout_weight="1"
26 + android:gravity="center_vertical"
27 + android:orientation="horizontal">
28 +
29 + <ImageView
30 + android:id="@+id/iv_back"
31 + android:layout_width="16dp"
32 + android:layout_height="16dp"
33 + android:layout_marginEnd="24dp"
34 + android:src="@drawable/ic_back" />
35 + </LinearLayout>
36 +
37 + <TextView
38 + android:id="@+id/tv_question_count"
39 + android:layout_width="wrap_content"
40 + android:layout_height="wrap_content"
41 + android:textColor="@color/custom_black4"
42 + android:textSize="18sp"
43 + tools:text="1/7" />
44 + </LinearLayout>
45 +
46 + <ScrollView
47 + android:layout_width="match_parent"
48 + android:layout_height="0dp"
49 + android:fillViewport="true"
50 + android:scrollbars="none"
51 + app:layout_constraintBottom_toTopOf="@id/ll_next_container"
52 + app:layout_constraintTop_toBottomOf="@id/header_layout">
53 +
54 + <LinearLayout
55 + android:layout_width="match_parent"
56 + android:layout_height="wrap_content"
57 + android:orientation="vertical"
58 + android:paddingHorizontal="16dp"
59 + android:paddingBottom="32dp">
60 +
61 + <TextView
62 + android:id="@+id/tv_question_header_title"
63 + android:layout_width="match_parent"
64 + android:layout_height="wrap_content"
65 + android:includeFontPadding="false"
66 + android:text="@string/demo_questionnaire_title"
67 + android:textColor="@color/custom_black4"
68 + android:textSize="22sp" />
69 +
70 + <TextView
71 + android:id="@+id/tv_question_title"
72 + android:layout_width="match_parent"
73 + android:layout_height="wrap_content"
74 + android:includeFontPadding="false"
75 + android:textColor="@color/custom_black4"
76 + android:textSize="18sp"
77 + android:layout_marginTop="40dp"
78 + tools:text="Question Title?" />
79 +
80 + <TextView
81 + android:id="@+id/tv_question_subtitle"
82 + android:layout_width="match_parent"
83 + android:layout_height="wrap_content"
84 + android:includeFontPadding="false"
85 + android:textColor="@color/custom_black2"
86 + android:textSize="14sp"
87 + android:layout_marginTop="8dp"
88 + android:text="@string/demo_questionnaire_subtitle"
89 + android:visibility="gone"/>
90 +
91 + <LinearLayout
92 + android:id="@+id/ll_options_container"
93 + android:layout_width="match_parent"
94 + android:layout_height="wrap_content"
95 + android:layout_marginTop="24dp"
96 + android:orientation="vertical" />
97 + </LinearLayout>
98 + </ScrollView>
99 +
100 + <LinearLayout
101 + android:id="@+id/ll_next_container"
102 + android:layout_width="match_parent"
103 + android:layout_height="wrap_content"
104 + android:orientation="vertical"
105 + android:padding="16dp"
106 + app:layout_constraintBottom_toBottomOf="parent">
107 +
108 + <LinearLayout
109 + android:id="@+id/ll_next_button"
110 + android:layout_width="match_parent"
111 + android:layout_height="55dp"
112 + android:background="@drawable/shape_rectangle_rounded_light_blue_tr"
113 + android:gravity="center"
114 + android:orientation="horizontal">
115 +
116 + <TextView
117 + android:id="@+id/tv_next"
118 + android:layout_width="wrap_content"
119 + android:layout_height="wrap_content"
120 + android:includeFontPadding="false"
121 + android:text="Next"
122 + android:textColor="@color/white"
123 + android:textSize="16sp" />
124 + </LinearLayout>
125 + </LinearLayout>
126 +</androidx.constraintlayout.widget.ConstraintLayout>
...\ No newline at end of file ...\ No newline at end of file
...@@ -42,7 +42,8 @@ ...@@ -42,7 +42,8 @@
42 42
43 <androidx.core.widget.NestedScrollView 43 <androidx.core.widget.NestedScrollView
44 android:layout_width="match_parent" 44 android:layout_width="match_parent"
45 - android:layout_height="match_parent"> 45 + android:layout_height="match_parent"
46 + android:scrollbars="none">
46 47
47 <LinearLayout 48 <LinearLayout
48 android:id="@+id/ll_filter_container" 49 android:id="@+id/ll_filter_container"
......
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 + xmlns:tools="http://schemas.android.com/tools"
4 + android:id="@+id/ll_option_container"
5 + android:layout_width="match_parent"
6 + android:layout_height="55dp"
7 + android:layout_marginBottom="8dp"
8 + android:background="@drawable/shape_questionnaire_option_unselected"
9 + android:gravity="center"
10 + android:orientation="horizontal">
11 +
12 + <TextView
13 + android:id="@+id/tv_option_title"
14 + android:layout_width="wrap_content"
15 + android:layout_height="wrap_content"
16 + android:includeFontPadding="false"
17 + tools:text="Option Title"
18 + android:textColor="@color/black"
19 + android:textSize="15sp" />
20 +</LinearLayout>
...\ No newline at end of file ...\ No newline at end of file
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 + android:id="@+id/ll_option_separator"
4 + android:layout_width="match_parent"
5 + android:layout_height="8dp"
6 + android:orientation="horizontal">
7 +</LinearLayout>
...\ No newline at end of file ...\ No newline at end of file
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
8 <color name="custom_orange">#FF9933</color> 8 <color name="custom_orange">#FF9933</color>
9 <color name="custom_skyblue2">#22A9B5</color> 9 <color name="custom_skyblue2">#22A9B5</color>
10 <color name="custom_blue_dark">#3A5266</color> 10 <color name="custom_blue_dark">#3A5266</color>
11 + <color name="black">#000000</color>
11 <color name="white">#FFFFFF</color> 12 <color name="white">#FFFFFF</color>
12 <color name="white_tr">#66FFFFFF</color> 13 <color name="white_tr">#66FFFFFF</color>
13 <color name="custom_green5">#79BF14</color> 14 <color name="custom_green5">#79BF14</color>
......
...@@ -43,4 +43,7 @@ ...@@ -43,4 +43,7 @@
43 <string name="demo_search_title">Αναζήτηση</string> 43 <string name="demo_search_title">Αναζήτηση</string>
44 <string name="lbl_directions">Οδηγίες</string> 44 <string name="lbl_directions">Οδηγίες</string>
45 <string name="lbl_top_offers">Top offers</string> 45 <string name="lbl_top_offers">Top offers</string>
46 + <string name="demo_questionnaire_title">Questionnaire</string>
47 + <string name="demo_questionnaire_subtitle">(You can select more than one answer)</string>
48 + <string name="demo_region_title">Region</string>
46 </resources> 49 </resources>
......