diff --git a/app/build.gradle b/app/build.gradle index a491a4c..d8c3475 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -61,7 +61,7 @@ dependencies { implementation 'androidx.core:core-splashscreen:1.0.0' implementation 'com.google.code.gson:gson:2.10.1' - implementation 'com.google.android.material:material:1.8.0' + implementation 'com.google.android.material:material:1.7.0' implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' diff --git a/app/src/main/java/com/capstone/foodify/API/FoodApi.java b/app/src/main/java/com/capstone/foodify/API/FoodApi.java index af46d05..189561a 100644 --- a/app/src/main/java/com/capstone/foodify/API/FoodApi.java +++ b/app/src/main/java/com/capstone/foodify/API/FoodApi.java @@ -1,6 +1,7 @@ package com.capstone.foodify.API; import com.capstone.foodify.Model.Category; +import com.capstone.foodify.Model.Comment; import com.capstone.foodify.Model.DistrictWardResponse; import com.capstone.foodify.Model.Food; import com.capstone.foodify.Model.Response.Comments; @@ -82,4 +83,7 @@ public interface FoodApi { @GET("products/{productId}/comments") Call getCommentByProductId(@Path("productId") int productId, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir); + + @GET("products/{productId}/users/{userId}") + Call getUserComment(@Path("productId") int productId, @Path("userId") int userId); } diff --git a/app/src/main/java/com/capstone/foodify/API/FoodApiToken.java b/app/src/main/java/com/capstone/foodify/API/FoodApiToken.java index dd0baef..860d24e 100644 --- a/app/src/main/java/com/capstone/foodify/API/FoodApiToken.java +++ b/app/src/main/java/com/capstone/foodify/API/FoodApiToken.java @@ -89,4 +89,7 @@ public interface FoodApiToken { @DELETE("products/{productId}/comments/{commentId}") Call deleteComment(@Path("productId") int productId, @Path("commentId") int commentId); + + @PUT("products/{productId}/comments/{commentId}") + Call updateComment(@Path("productId") int productId, @Path("commentId") int commentId, @Body Comment comment); } diff --git a/app/src/main/java/com/capstone/foodify/Activity/AccountAndProfileActivity.java b/app/src/main/java/com/capstone/foodify/Activity/AccountAndProfileActivity.java index bbaf677..74d9089 100644 --- a/app/src/main/java/com/capstone/foodify/Activity/AccountAndProfileActivity.java +++ b/app/src/main/java/com/capstone/foodify/Activity/AccountAndProfileActivity.java @@ -43,6 +43,7 @@ import com.google.firebase.storage.UploadTask; import com.makeramen.roundedimageview.RoundedImageView; import com.squareup.picasso.Picasso; import com.thecode.aestheticdialogs.AestheticDialog; +import com.thecode.aestheticdialogs.DialogAnimation; import com.thecode.aestheticdialogs.DialogStyle; import com.thecode.aestheticdialogs.DialogType; import com.thecode.aestheticdialogs.OnDialogClickListener; @@ -295,9 +296,10 @@ public class AccountAndProfileActivity extends AppCompatActivity { } private void showDialogCaution() { - new AestheticDialog.Builder(this, DialogStyle.RAINBOW, DialogType.WARNING) + new AestheticDialog.Builder(this, DialogStyle.FLAT, DialogType.WARNING) .setTitle("Email chưa được xác thực!") .setMessage("Vui lòng xác thực email để bạn có thể thực hiện việc lấy lại mật khẩu nếu quên!") + .setAnimation(DialogAnimation.SHRINK) .setCancelable(true) .show(); } diff --git a/app/src/main/java/com/capstone/foodify/Activity/AddressManagerActivity.java b/app/src/main/java/com/capstone/foodify/Activity/AddressManagerActivity.java index 799fbf8..f59de76 100644 --- a/app/src/main/java/com/capstone/foodify/Activity/AddressManagerActivity.java +++ b/app/src/main/java/com/capstone/foodify/Activity/AddressManagerActivity.java @@ -362,6 +362,8 @@ public class AddressManagerActivity extends AppCompatActivity { //Create dialog customViewDialog.Builder(this); + customViewDialog.setDialogBackgroundColor(getResources().getColor(R.color.white, null)); + if(oldAddress == null){ //If this is the create address form diff --git a/app/src/main/java/com/capstone/foodify/Activity/FoodDetailActivity.java b/app/src/main/java/com/capstone/foodify/Activity/FoodDetailActivity.java index d87ac25..a1dceba 100644 --- a/app/src/main/java/com/capstone/foodify/Activity/FoodDetailActivity.java +++ b/app/src/main/java/com/capstone/foodify/Activity/FoodDetailActivity.java @@ -19,6 +19,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import androidx.cardview.widget.CardView; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.widget.NestedScrollView; import androidx.recyclerview.widget.LinearLayoutManager; @@ -41,6 +42,9 @@ import com.denzcoskun.imageslider.models.SlideModel; import com.mcdev.quantitizerlibrary.AnimationStyle; import com.mcdev.quantitizerlibrary.HorizontalQuantitizer; import com.mcdev.quantitizerlibrary.QuantitizerListener; +import com.sjapps.library.customdialog.BasicDialog; +import com.sjapps.library.customdialog.DialogButtonEvent; +import com.sjapps.library.customdialog.DialogButtonEvents; import com.willy.ratingbar.RotationRatingBar; import com.willy.ratingbar.ScaleRatingBar; @@ -52,6 +56,7 @@ import retrofit2.Callback; import retrofit2.Response; public class FoodDetailActivity extends AppCompatActivity { + ArrayList listComment = new ArrayList<>(); private static final int ACTION_CODE = 0; private static final int CREATE_COMMENT = 1; private static final int EDIT_COMMENT = 2; @@ -62,7 +67,7 @@ public class FoodDetailActivity extends AppCompatActivity { private static boolean LAST_PAGE; private HorizontalQuantitizer horizontalQuantitizer; private ImageSlider imageSlider; - private ImageView back_image, not_favorite, is_favorite, delete_button; + private ImageView back_image, not_favorite, is_favorite, delete_button, edt_button; private String foodId = ""; private Food food; private TextView foodName_txt, shopName_txt, discount_txt, price_txt, countRating_txt, description_content_txt, endOfListText, @@ -77,14 +82,10 @@ public class FoodDetailActivity extends AppCompatActivity { private ConstraintLayout progressLayout; private NestedScrollView nestedScrollView; private ProgressBar progressBar; + private CardView user_comment_layout; + private Comment commentUser = null; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_food_detail); - - //Init Component + private void initComponent() { horizontalQuantitizer = findViewById(R.id.quantity_option); imageSlider = findViewById(R.id.slider); back_image = findViewById(R.id.back_image); @@ -109,7 +110,17 @@ public class FoodDetailActivity extends AppCompatActivity { contentComment = findViewById(R.id.comment_user); ratingBarComment = findViewById(R.id.rating_bar_comment); delete_button = findViewById(R.id.delete_button); + user_comment_layout = findViewById(R.id.user_comment_layout); + edt_button = findViewById(R.id.edit_button); + } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_food_detail); + //Init Component + + initComponent(); commentAdapter = new CommentAdapter(this); @@ -126,6 +137,8 @@ public class FoodDetailActivity extends AppCompatActivity { hideUI(); + + if(Common.CURRENT_USER == null){ is_favorite.setVisibility(View.GONE); not_favorite.setVisibility(View.GONE); @@ -219,11 +232,20 @@ public class FoodDetailActivity extends AppCompatActivity { }); } + //Edit button + edt_button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + openCommentDialog(Gravity.CENTER, EDIT_COMMENT); + } + }); + //Delete comment delete_button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - + if(commentUser != null) + showDeleteDialogConfirm(); } }); } @@ -307,13 +329,48 @@ public class FoodDetailActivity extends AppCompatActivity { } } - private List getListComment(int page) { - ArrayList listComment = new ArrayList<>(); + private void getCommentUser(){ + FoodApi.apiService.getUserComment(Integer.parseInt(foodId), Common.CURRENT_USER.getId()).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if(response.code() == 200){ + //Have user comment + Comment commentData = response.body(); + if(commentData != null){ + //Init data + commentUser = commentData; + userNameComment.setText(Common.CURRENT_USER.getFullName()); + ratingBarComment.setRating(commentData.getRating()); + contentComment.setText(commentData.getContent()); + + showUI(); + + rating_button.setVisibility(View.GONE); + } + } else if(response.code() == 404){ + //Don't have user comment + user_comment_layout.setVisibility(View.GONE); + showUI(); + } else { + Toast.makeText(FoodDetailActivity.this, "Có lỗi từ hệ thống! Mã lỗi: " + response.code(), Toast.LENGTH_SHORT).show(); + showUI(); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + showUI(); + Common.showErrorServerNotification(FoodDetailActivity.this, "Lỗi kết nối!"); + } + }); + } + private List getListComment(int page) { FoodApi.apiService.getCommentByProductId(Integer.parseInt(foodId), page, PAGE_SIZE, SORT_BY, SORT_DIR).enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { if(response.code() == 200){ + List tempCommentList = response.body().getComments(); //Init data @@ -326,22 +383,20 @@ public class FoodDetailActivity extends AppCompatActivity { } //Get user's comment - for(Comment tempComment: listComment){ - if(tempComment.getUser().getEmail().equals(Common.CURRENT_USER.getEmail())){ - //Init data comment - userNameComment.setText(Common.CURRENT_USER.getFullName()); - ratingBarComment.setRating(tempComment.getRating()); - contentComment.setText(tempComment.getContent()); + if(Common.CURRENT_USER != null){ + for(Comment tempComment: listComment){ + if(tempComment.getUser().getEmail().equals(Common.CURRENT_USER.getEmail())){ + //Remove comment from list + listComment.remove(tempComment); - //Remove comment from list - listComment.remove(tempComment); - - //Remove button comment - rating_button.setVisibility(View.GONE); - break; + //Remove button comment + rating_button.setVisibility(View.GONE); + break; + } } } + if(listComment.size() == 0) endOfListText.setVisibility(View.GONE); @@ -359,7 +414,6 @@ public class FoodDetailActivity extends AppCompatActivity { return listComment; } - private void hideUI() { content_view.setVisibility(View.GONE); } @@ -377,10 +431,10 @@ public class FoodDetailActivity extends AppCompatActivity { description_content_txt.setText(food.getDescription()); ratingBar.setRating(food.getAverageRating()); - if(food.getCommentCount() == null || Integer.parseInt(food.getCommentCount()) == 0){ + if(food.getReviewCount() == null || Integer.parseInt(food.getReviewCount()) == 0){ countRating_txt.setText("Chưa có bình luận nào!"); } else { - countRating_txt.setText(food.getCommentCount() + " rating"); + countRating_txt.setText(food.getReviewCount() + " đánh giá"); } @@ -432,7 +486,9 @@ public class FoodDetailActivity extends AppCompatActivity { else notFavoriteIcon(); - showUI(); + getCommentUser(); + + } @Override @@ -497,9 +553,11 @@ public class FoodDetailActivity extends AppCompatActivity { Button cancel = dialog.findViewById(R.id.cancel_button); if(actionCode == EDIT_COMMENT){ - //TODO Edit comment //Init data - + if(commentUser != null){ + ratingBar.setRating(commentUser.getRating()); + comment_content.setText(commentUser.getContent()); + } } @@ -515,6 +573,7 @@ public class FoodDetailActivity extends AppCompatActivity { confirm.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + progressLayout.setVisibility(View.VISIBLE); if(actionCode == CREATE_COMMENT){ //Create comment @@ -524,6 +583,18 @@ public class FoodDetailActivity extends AppCompatActivity { public void onResponse(Call call, Response response) { if(response.code() == 201){ Toast.makeText(FoodDetailActivity.this, "Đã thêm bình luận thành công!", Toast.LENGTH_SHORT).show(); + + //Init data + getCommentUser(); + + //Show comment layout and hide rating button when comment completed! + user_comment_layout.setVisibility(View.VISIBLE); + rating_button.setVisibility(View.GONE); + + + dialog.dismiss(); + } else { + Toast.makeText(FoodDetailActivity.this, "Lỗi hệ thống! Mã lỗi: " + response.code(), Toast.LENGTH_SHORT).show(); } } @@ -534,6 +605,34 @@ public class FoodDetailActivity extends AppCompatActivity { }); } else if(actionCode == EDIT_COMMENT){ //Edit comment + if(commentUser != null){ + + //Create object comment + Comment newComment = new Comment(comment_content.getText().toString(), ratingBar.getRating(), Common.CURRENT_USER.getId()); + + FoodApiToken.apiService.updateComment(Integer.parseInt(foodId), commentUser.getId(), newComment).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if(response.code() == 200){ + Toast.makeText(FoodDetailActivity.this, "Đã cập nhật bình luận thành công!", Toast.LENGTH_SHORT).show(); + + ratingBarComment.setRating(ratingBar.getRating()); + contentComment.setText(comment_content.getText().toString()); + + dialog.dismiss(); + + progressLayout.setVisibility(View.GONE); + } else { + Toast.makeText(FoodDetailActivity.this, "Đã có lỗi hệ thống! Mã lỗi: " + response.code(), Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + Toast.makeText(FoodDetailActivity.this, "Đã có lỗi kết nối đến hệ thống!", Toast.LENGTH_SHORT).show(); + } + }); + } } @@ -542,9 +641,58 @@ public class FoodDetailActivity extends AppCompatActivity { dialog.show(); } - private void deleteComment(){ - //TODO Delete comment + FoodApiToken.apiService.deleteComment(Integer.parseInt(foodId), commentUser.getId()).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if(response.code() == 200){ + CustomResponse responseData = response.body(); + + if(responseData != null){ + if(responseData.isTrue()){ + Toast.makeText(FoodDetailActivity.this, "Đã xoá bình luận thành công!", Toast.LENGTH_SHORT).show(); + + //Remove layout comment + rating_button.setVisibility(View.VISIBLE); + user_comment_layout.setVisibility(View.GONE); + + commentUser = null; + } + } + } else { + Toast.makeText(FoodDetailActivity.this, "Lỗi hệ thống! Mã lỗi: " + response.code(), Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + Toast.makeText(FoodDetailActivity.this, "Đã có lỗi kết nối tới hệ thống!", Toast.LENGTH_SHORT).show(); + } + }); + } + private void showDeleteDialogConfirm(){ + BasicDialog dialog = new BasicDialog(); + + dialog.Builder(this) + .setTitle("Xác nhận xoá bình luận?") + .setLeftButtonText("Có") + .setRightButtonText("Không") + .setDialogBackgroundColor(getResources().getColor(R.color.white, null)) + .setLeftButtonColor(getResources().getColor(R.color.primaryColor, null)) + .setRightButtonColor(getResources().getColor(R.color.gray, null)) + .onButtonClick(new DialogButtonEvents() { + @Override + public void onLeftButtonClick() { + deleteComment(); + dialog.dismiss(); + } + + @Override + public void onRightButtonClick() { + dialog.dismiss(); + } + }) + .show(); } private void dataLoadMore() { if(!LAST_PAGE){ diff --git a/app/src/main/java/com/capstone/foodify/Activity/MainActivity.java b/app/src/main/java/com/capstone/foodify/Activity/MainActivity.java index 14e8b3e..8e3bdc8 100644 --- a/app/src/main/java/com/capstone/foodify/Activity/MainActivity.java +++ b/app/src/main/java/com/capstone/foodify/Activity/MainActivity.java @@ -373,6 +373,11 @@ public class MainActivity extends AppCompatActivity { super.onPause(); if (mRequestingLocationUpdates) { stopLocationUpdates(); + + if(Common.CURRENT_LOCATION == null){ + if(mCurrentLocation != null) + Common.CURRENT_LOCATION = mCurrentLocation; + } } } diff --git a/app/src/main/java/com/capstone/foodify/Fragment/Order/CancelOrderFragment.java b/app/src/main/java/com/capstone/foodify/Fragment/Order/CancelOrderFragment.java new file mode 100644 index 0000000..fd572a5 --- /dev/null +++ b/app/src/main/java/com/capstone/foodify/Fragment/Order/CancelOrderFragment.java @@ -0,0 +1,20 @@ +package com.capstone.foodify.Fragment.Order; + +import android.os.Bundle; + +import androidx.fragment.app.Fragment; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.capstone.foodify.R; +public class CancelOrderFragment extends Fragment { + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.fragment_cancel_order, container, false); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/foodify/Fragment/Order/ViewPagerAdapter.java b/app/src/main/java/com/capstone/foodify/Fragment/Order/ViewPagerAdapter.java index b77522c..087f3c5 100644 --- a/app/src/main/java/com/capstone/foodify/Fragment/Order/ViewPagerAdapter.java +++ b/app/src/main/java/com/capstone/foodify/Fragment/Order/ViewPagerAdapter.java @@ -21,6 +21,8 @@ public class ViewPagerAdapter extends FragmentStateAdapter { return new ShipOrderFragment(); case 3: return new CompleteOrderFragment(); + case 4: + return new CancelOrderFragment(); default: return new ProcessOderFragment(); } @@ -28,6 +30,6 @@ public class ViewPagerAdapter extends FragmentStateAdapter { @Override public int getItemCount() { - return 4; + return 5; } } diff --git a/app/src/main/java/com/capstone/foodify/Model/Food.java b/app/src/main/java/com/capstone/foodify/Model/Food.java index 21fee26..061bdee 100644 --- a/app/src/main/java/com/capstone/foodify/Model/Food.java +++ b/app/src/main/java/com/capstone/foodify/Model/Food.java @@ -10,7 +10,7 @@ public class Food implements Comparable{ private float discountPercent; private float cost; private float averageRating; - private String commentCount; + private String reviewCount; private Shop shop; private List categories; private List images; @@ -74,12 +74,12 @@ public class Food implements Comparable{ this.averageRating = averageRating; } - public String getCommentCount() { - return commentCount; + public String getReviewCount() { + return reviewCount; } - public void setCommentCount(String commentCount) { - this.commentCount = commentCount; + public void setReviewCount(String reviewCount) { + this.reviewCount = reviewCount; } public Shop getShop() { @@ -132,7 +132,7 @@ public class Food implements Comparable{ ", discountPercent=" + discountPercent + ", cost=" + cost + ", averageRating=" + averageRating + - ", commentCount='" + commentCount + '\'' + + ", commentCount='" + reviewCount + '\'' + ", shop=" + shop + ", categories=" + categories + ", images=" + images + diff --git a/app/src/main/res/drawable/baseline_delete_24_white.xml b/app/src/main/res/drawable/baseline_delete_24_white.xml new file mode 100644 index 0000000..282594c --- /dev/null +++ b/app/src/main/res/drawable/baseline_delete_24_white.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_food_detail.xml b/app/src/main/res/layout/activity_food_detail.xml index 8a3c37a..4c86bb4 100644 --- a/app/src/main/res/layout/activity_food_detail.xml +++ b/app/src/main/res/layout/activity_food_detail.xml @@ -294,6 +294,7 @@ android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/add_to_basket_button" app:layout_constraintStart_toStartOf="parent" + android:gravity="center_horizontal" >