package com.example.agriflex.ui.fooddetail;
import android.content.DialogInterface;
import android.icu.util.IslamicCalendar;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RatingBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.RecyclerView;
import com.andremion.counterfab.CounterFab;
import com.bumptech.glide.Glide;
import com.cepheuen.elegantnumberbutton.view.ElegantNumberButton;
import com.example.agriflex.Common.Common;
import com.example.agriflex.Model.CommentModel;
import com.example.agriflex.Model.FoodModel;
import com.example.agriflex.Model.SizeModel;
import com.example.agriflex.R;
import com.example.agriflex.ui.comments.CommentFragment;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ServerValue;
import com.google.firebase.database.ValueEventListener;
import java.util.HashMap;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import dmax.dialog.SpotsDialog;
public class FoodDetailFragment extends Fragment {
private FoodDetailViewModel foodDetailViewModel;
private Unbinder unbinder;
private android.app.AlertDialog waitingDialog;
@BindView(R.id.img_food)
ImageView img_food;
@BindView(R.id.btnCart)
CounterFab btnCart;
@BindView(R.id.btn_rating)
FloatingActionButton btn_rating;
@BindView(R.id.food_name)
TextView food_name;
@BindView(R.id.food_description)
TextView food_description;
@BindView(R.id.food_price)
TextView food_price;
@BindView(R.id.number_button)
ElegantNumberButton numberButton;
@BindView(R.id.ratingBar)
RatingBar ratingBar;
@BindView(R.id.btnShowComment)
Button btnShowComment;
@BindView(R.id.rdi_group_size)
RadioGroup rdi_group_size;
@OnClick(R.id.btn_rating)
void onRatingButtonClick() {
showDialogRating();
}
@OnClick(R.id.btnShowComment)
void onShowCommentButtonClick() {
CommentFragment commentFragment = CommentFragment.getInstance();
commentFragment.show(getActivity().getSupportFragmentManager(), "CommentFragment");
}
private void showDialogRating() {
androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(getContext());
builder.setTitle("Rating Food");
builder.setMessage("Please fill Information");
View itemView = LayoutInflater.from(getContext()).inflate(R.layout.layout_rating, null);
RatingBar ratingBar = (RatingBar) itemView.findViewById(R.id.rating_bar);
EditText edt_comment = (EditText) itemView.findViewById(R.id.edt_comment);
builder.setView(itemView);
builder.setNegativeButton("CANCEL", (dialogInterface, i) -> {
dialogInterface.dismiss();
});
builder.setPositiveButton("OK", (dialogInterface, i) -> {
CommentModel commentModel = new CommentModel();
commentModel.setName(Common.currentUser.getName());
commentModel.setUid(Common.currentUser.getUid());
commentModel.setComment(edt_comment.getText().toString());
commentModel.setRatingValue(ratingBar.getRating());
Map<String, Object> serverTimeStamp = new HashMap<>();
serverTimeStamp.put("timeStamp", ServerValue.TIMESTAMP);
commentModel.setCommentTimeStamp(serverTimeStamp);
foodDetailViewModel.setCommentModel(commentModel);
});
AlertDialog dialog = builder.create();
dialog.show();
}
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
foodDetailViewModel =
ViewModelProviders.of(this).get(FoodDetailViewModel.class);
View root = inflater.inflate(R.layout.fragment_food_detail, container, false);
unbinder = ButterKnife.bind(this, root);
initViews();
foodDetailViewModel.getMutableLiveDataFood().observe(this, foodModel -> {
displayInfo(foodModel);
});
foodDetailViewModel.getMutableLiveDataComment().observe(this, commentModel -> {
submitRatingToFirebase(commentModel);
});
return root;
}
private void initViews() {
waitingDialog = new SpotsDialog.Builder().setCancelable(false).setContext(getContext()).build();
}
private void submitRatingToFirebase(CommentModel commentModel) {
waitingDialog.show();
//First , we will submit to Comments ref
FirebaseDatabase.getInstance()
.getReference(Common.COMMENT_REF)
.child(Common.selectedFood.getId())
.push()
.setValue(commentModel)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
//After submit to CommentRef , we will update value aveger in food
addRatingToFood(commentModel.getRatingValue());
}
waitingDialog.dismiss();
});
}
private void addRatingToFood(float ratingValue) {
FirebaseDatabase.getInstance()
.getReference(Common.CATEGORY_REF)
.child(Common.CategorySelected.getMenu_id()) // Select Category
.child("foods") // select array list 'foods' of this category
.child(Common.selectedFood.getKey()) // Because food item is array list so key is index of arraylist
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
FoodModel foodModel = dataSnapshot.getValue(FoodModel.class);
foodModel.setKey(Common.selectedFood.getKey()); //Don't forget set it
//Apply rating
if (foodModel.getRatingValue() == null)
foodModel.setRatingValue(0d); // d = D lower case
if (foodModel.getRatingCount() == null)
foodModel.setRatingCount(0l); // l = L lower case, not 1 (number 1)
double sumRating = foodModel.getRatingValue() + ratingValue;
long ratingCount = foodModel.getRatingCount() + 1;
double result = sumRating / ratingCount;
Map<String, Object> updateData = new HashMap<>();
updateData.put("ratingValue", result);
updateData.put("ratingCount", ratingCount);
//update data in variable
foodModel.setRatingValue(result);
foodModel.setRatingCount(ratingCount);
dataSnapshot.getRef()
.updateChildren(updateData)
.addOnCompleteListener(task -> {
waitingDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(getContext(), "Thank you !", Toast.LENGTH_SHORT).show();
Common.selectedFood = foodModel;
foodDetailViewModel.setFoodModel(foodModel); // Call refresh
}
});
} else
waitingDialog.dismiss();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
waitingDialog.dismiss();
Toast.makeText(getContext(), "" + databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void displayInfo(FoodModel foodModel) {
Glide.with(getContext()).load(foodModel.getImage()).into(img_food);
food_name.setText(new StringBuilder(foodModel.getName()));
food_description.setText(new StringBuilder(foodModel.getDescription()));
food_price.setText(new StringBuilder(foodModel.getPrice().toString()));
if (foodModel.getRatingValue() != null)
ratingBar.setRating(foodModel.getRatingValue().floatValue());
((AppCompatActivity)getActivity())
.getSupportActionBar()
.setTitle(Common.selectedFood.getName());
//Size
for (SizeModel sizeModel: Common.selectedFood.getSizeModel())
{
RadioButton radioButton = new RadioButton(getContext());
radioButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked)
Common.selectedFood.setUserSelectedSize(sizeModel);
calculateTotalPrice(); //Update Price
});
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,
LinearLayout.LayoutParams.MATCH_PARENT,
1.0f);
radioButton.setLayoutParams(params);
radioButton.setText(sizeModel.getName());
radioButton.setTag(sizeModel.getPrice());
rdi_group_size.addView(radioButton);
}
if (rdi_group_size.getChildCount() > 0) {
RadioButton radioButton = (RadioButton) rdi_group_size.getChildAt(0);
radioButton.setChecked(true); //Default First Select
}
calculateTotalPrice();
}
private void calculateTotalPrice () {
double totalPrice = Double.parseDouble(Common.selectedFood.getPrice().toString()), displayPrice = 0.0;
//Size
totalPrice += Double.parseDouble(Common.selectedFood.getUserSelectedSize().getPrice().toString());
displayPrice = totalPrice * (Integer.parseInt(numberButton.getNumber()));
displayPrice = Math.round(displayPrice * 100.0 / 100.0);
food_price.setText(new StringBuilder("").append(Common.formatPrice(displayPrice)).toString());
}
}
----------
## Heading ##
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.agriflex, PID: 5673
java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()' on a null object reference
at com.example.agriflex.ui.fooddetail.FoodDetailFragment.displayInfo(FoodDetailFragment.java:236)
at com.example.agriflex.ui.fooddetail.FoodDetailFragment.lambda$onCreateView$2$FoodDetailFragment(FoodDetailFragment.java:135)
at com.example.agriflex.ui.fooddetail.-$$Lambda$FoodDetailFragment$qUbisKr6hIzCwm4MXSIKgBZ3EXA.onChanged(Unknown Source:4)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:113)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:126)
at androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged(LiveData.java:424)
at androidx.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged(LiveData.java:376)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
at androidx.fragment.app.Fragment.performStart(Fragment.java:2637)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:915)
at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManagerImpl.java:2100)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1874)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1830)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
I/zygote: Do full code cache collection, code=495KB, data=334KB After code cache collection, code=484KB, data=293KB