Merge API to Shop Detail screen

This commit is contained in:
Nezumi
2023-03-11 15:04:21 +07:00
parent 7259ab0d59
commit 5905fbf5a4
10 changed files with 295 additions and 50 deletions
+2 -1
View File
@@ -19,7 +19,8 @@
tools:targetApi="31">
<activity
android:name=".Activity.ShopDetailActivity"
android:exported="false" />
android:exported="false"
/>
<activity
android:name=".Activity.OrderDetailActivity"
android:exported="false" />
@@ -5,6 +5,7 @@ import com.capstone.foodify.Model.DistrictWard.DistrictWardResponse;
import com.capstone.foodify.Model.Food.Food;
import com.capstone.foodify.Model.Response.Foods;
import com.capstone.foodify.Model.Response.Shops;
import com.capstone.foodify.Model.Shop.Shop;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -54,8 +55,11 @@ public interface FoodApi {
@GET("products/{id}")
Call<Food> detailFood(@Path("id") String id);
// @GET("detail/{id}/image")
// Call<List<ImageFood>> getImageFoodById(@Path("id") String id);
@GET("shops/{id}")
Call<Shop> detailShop(@Path("id") int id);
@GET("products/shops/{id}")
Call<Foods> listFoodByShopId(@Path("id") int id, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
@GET("district/{districtId}/ward")
Call<List<DistrictWardResponse>> wardResponse(@Path("districtId") int district_id);
@@ -1,6 +1,8 @@
package com.capstone.foodify.Activity;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.widget.NestedScrollView;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -8,21 +10,48 @@ import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.capstone.foodify.API.FoodApi;
import com.capstone.foodify.Common;
import com.capstone.foodify.Model.Food.Food;
import com.capstone.foodify.Adapter.FoodShopAdapter;
import com.capstone.foodify.Model.Response.Foods;
import com.capstone.foodify.Model.Response.Shops;
import com.capstone.foodify.Model.Shop.Shop;
import com.capstone.foodify.R;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.saadahmedsoft.popupdialog.PopupDialog;
import com.saadahmedsoft.popupdialog.Styles;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ShopDetailActivity extends AppCompatActivity {
private static int CURRENT_PAGE;
private static int PAGE_SIZE = 8;
private static String SORT_BY = "name";
private static String SORT_DIR = "asc";
private static boolean LAST_PAGE = false;
private int shopId;
private List<Food> listFood = new ArrayList<>();
TextView content_description_text_view, student_shop_text_view, end_of_list_text_view;
ImageView imageShop, back_image;
RecyclerView recycler_view_food_shop;
FoodShopAdapter adapter;
private CollapsingToolbarLayout collapsingToolbarLayout;
private PopupDialog popupDialog;
private NestedScrollView nestedScrollView;
private ProgressBar progressBar;
private Shop shop;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -33,14 +62,26 @@ public class ShopDetailActivity extends AppCompatActivity {
imageShop = findViewById(R.id.image_shop);
recycler_view_food_shop = findViewById(R.id.recycler_view_food_shop);
back_image = findViewById(R.id.back_image);
adapter = new FoodShopAdapter();
adapter = new FoodShopAdapter(this);
collapsingToolbarLayout = findViewById(R.id.collapsing);
content_description_text_view = findViewById(R.id.content_description_text_view);
student_shop_text_view = findViewById(R.id.student_shop_text_view);
nestedScrollView = findViewById(R.id.food_detail);
progressBar = findViewById(R.id.progress_bar);
end_of_list_text_view = findViewById(R.id.end_of_list_text);
//Init temp data
Picasso.get().load("https://firebasestorage.googleapis.com/v0/b/foodify-55954.appspot.com/o/Free%20Food%20Advertising%20Banner%20Template.jpg?alt=media&token=8b836fd7-f18f-46c6-a14f-27680e51a1d5").into(imageShop);
popupDialog = PopupDialog.getInstance(this);
popupDialog.setStyle(Styles.PROGRESS).setProgressDialogTint(getResources().getColor(R.color.primaryColor, null))
.setCancelable(false).showDialog();
// for(int i = 1; i <= 10; i++){
// listFood.add(new Food("https://images.unsplash.com/photo-1546069901-ba9599a7e63c?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MXx8fGVufDB8fHx8&w=1000&q=80", "Food " + i, "50.000đ"));
// }
//Get data
if (getIntent() != null)
shopId = getIntent().getIntExtra("ShopId", 0);
//Set the first page after call api
CURRENT_PAGE = 0;
getDetailShop(shopId);
nestedScrollView.setVisibility(View.GONE);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recycler_view_food_shop.setLayoutManager(linearLayoutManager);
@@ -48,9 +89,6 @@ public class ShopDetailActivity extends AppCompatActivity {
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
recycler_view_food_shop.addItemDecoration(itemDecoration);
adapter.setData(listFood);
recycler_view_food_shop.setAdapter(adapter);
back_image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -58,5 +96,98 @@ public class ShopDetailActivity extends AppCompatActivity {
}
});
if (nestedScrollView != null) {
nestedScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(@NonNull NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
if (scrollY == (v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight())) {
//When user scroll to bottom, load more data
dataLoadMore();
}
}
});
}
}
private void getListFood(int shopId){
FoodApi.apiService.listFoodByShopId(shopId, CURRENT_PAGE++, PAGE_SIZE, SORT_BY, SORT_DIR).enqueue(new Callback<Foods>() {
@Override
public void onResponse(Call<Foods> call, Response<Foods> response) {
Foods tempFood = response.body();
if(tempFood == null)
return;
//Init last page from api
LAST_PAGE = tempFood.getPage().isLast();
//Add food to list
listFood.addAll(tempFood.getProducts());
adapter.setData(listFood);
recycler_view_food_shop.setAdapter(adapter);
initData(shop);
}
@Override
public void onFailure(Call<Foods> call, Throwable t) {
//Check internet connection
Common.showNotificationError(t, getBaseContext(), ShopDetailActivity.this);
}
});
}
private void getDetailShop(int shopId) {
FoodApi.apiService.detailShop(shopId).enqueue(new Callback<Shop>() {
@Override
public void onResponse(Call<Shop> call, Response<Shop> response) {
Shop tempShop = response.body();
//Init shop data to "local data" shop;
if(tempShop != null)
shop = tempShop;
getListFood(shopId);
}
@Override
public void onFailure(Call<Shop> call, Throwable t) {
Common.showNotificationError(t, getBaseContext(), ShopDetailActivity.this);
}
});
}
private void initData(Shop shop) {
//Init data
Picasso.get().load(shop.getImageUrl()).into(imageShop);
collapsingToolbarLayout.setTitle(shop.getName());
content_description_text_view.setText(shop.getDescription());
//If shop is studentShop, enable tag student shop
if(shop.isStudent()){
student_shop_text_view.setVisibility(View.VISIBLE);
}
//If list data don't have pagination
if(LAST_PAGE)
hideProgressBarAndShowEndOfListText();
nestedScrollView.setVisibility(View.VISIBLE);
popupDialog.dismissDialog();
}
private void hideProgressBarAndShowEndOfListText(){
progressBar.setVisibility(View.GONE);
end_of_list_text_view.setVisibility(View.VISIBLE);
}
private void dataLoadMore() {
if(!LAST_PAGE){
getListFood(shopId);
} else {
hideProgressBarAndShowEndOfListText();
}
}
}
@@ -55,9 +55,15 @@ public class BasketAdapter extends RecyclerView.Adapter<BasketAdapter.BasketView
holder.foodName.setText(foodBasket.getName());
holder.shopName.setText(foodBasket.getShopName());
holder.price.setText(Common.changeCurrencyUnit(foodBasket.getCost()));
Picasso.get().load(foodBasket.getImg()).into(holder.imageView);
holder.quantity.setNumber(foodBasket.getQuantity());
//Check food image is null or not null
if(foodBasket.getImg() == null){
holder.imageView.setImageResource(R.drawable.default_image_food);
} else {
Picasso.get().load(foodBasket.getImg()).into(holder.imageView);
}
//Calculate total price
calculateTotalPrice();
@@ -1,24 +1,33 @@
package com.capstone.foodify.Adapter;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.capstone.foodify.Activity.FoodDetailActivity;
import com.capstone.foodify.Common;
import com.capstone.foodify.Model.Basket.Basket;
import com.capstone.foodify.Model.Food.Food;
import com.capstone.foodify.R;
import com.squareup.picasso.Picasso;
import java.util.List;
public class FoodShopAdapter extends RecyclerView.Adapter<FoodShopAdapter.FoodShopViewHolder> {
private List<Food> listFoodShop;
private Context context;
public FoodShopAdapter() {
public FoodShopAdapter(Context context) {
this.context = context;
}
public void setData(List<Food> listFoodShop){
@@ -39,10 +48,61 @@ public class FoodShopAdapter extends RecyclerView.Adapter<FoodShopAdapter.FoodSh
if(food == null)
return;
// Picasso.get().load(food.getImg()).into(holder.imageView);
// holder.foodName.setText(food.getName());
// holder.quantitySoldOut.setText("1.2k đã bán");
// holder.price.setText(food.getPrice());
if(food.getImages().size() == 0){
holder.imageView.setImageResource(R.drawable.default_image_food);
} else {
Picasso.get().load(food.getImages().get(0).getImageUrl()).into(holder.imageView);
}
holder.foodName.setText(food.getName());
holder.quantitySoldOut.setText("1.2k đã bán");
holder.price.setText(Common.changeCurrencyUnit(food.getCost()));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(context, FoodDetailActivity.class);
intent.putExtra("FoodId", food.getId());
context.startActivity(intent);
}
});
//Set event basket icon
holder.basket_icon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Basket foodInBasket = Common.getFoodExistInBasket(food.getId());
if(foodInBasket == null){
//If item is not exist in basket
//Check food image is null or not
String imageTemp = null;
if(food.getImages().size() > 0)
imageTemp = food.getImages().get(0).getImageUrl();
Common.LIST_BASKET_FOOD.add(new Basket(food.getId(), imageTemp, food.getName(), food.getCost(), food.getShop().getName(),
"1", food.getDiscountPercent()));
} else {
//If item is exist in basket
for(int i = 0; i < Common.LIST_BASKET_FOOD.size(); i++){
String foodId = Common.LIST_BASKET_FOOD.get(i).getId();
//Find foodId exist
if(foodId.equals(food.getId())){
//Get quantity food from basket
String quantity = Common.LIST_BASKET_FOOD.get(i).getQuantity();
//Change quantity food from basket
int quantityInt = Integer.parseInt(quantity) + 1;
Common.LIST_BASKET_FOOD.get(i).setQuantity(String.valueOf(quantityInt));
break;
}
}
}
Toast.makeText(context, "Đã thêm " + food.getName() + " vào giỏ hàng!", Toast.LENGTH_SHORT).show();
}
});
}
@Override
@@ -54,7 +114,7 @@ public class FoodShopAdapter extends RecyclerView.Adapter<FoodShopAdapter.FoodSh
public class FoodShopViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
ImageView imageView, basket_icon;
TextView foodName, quantitySoldOut, price;
@@ -65,6 +125,7 @@ public class FoodShopAdapter extends RecyclerView.Adapter<FoodShopAdapter.FoodSh
foodName = itemView.findViewById(R.id.food_name_text_view);
quantitySoldOut = itemView.findViewById(R.id.quantity_sold_out);
price = itemView.findViewById(R.id.price_text_view);
basket_icon = itemView.findViewById(R.id.basket_icon);
}
}
}
@@ -11,6 +11,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.capstone.foodify.Activity.FoodDetailActivity;
import com.capstone.foodify.Activity.ShopDetailActivity;
import com.capstone.foodify.Model.Shop.Shop;
import com.capstone.foodify.R;
@@ -49,7 +50,7 @@ public class ShopAdapter extends RecyclerView.Adapter<ShopAdapter.ShopViewHolder
//Init data
Picasso.get().load(shop.getImageUrl()).into(holder.imageView);
holder.shopName.setText("Shop Name");
holder.shopName.setText(shop.getName());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
@@ -57,6 +58,15 @@ public class ShopAdapter extends RecyclerView.Adapter<ShopAdapter.ShopViewHolder
context.startActivity(new Intent(context, ShopDetailActivity.class));
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(context, ShopDetailActivity.class);
intent.putExtra("ShopId", shop.getId());
context.startActivity(intent);
}
});
}
@Override
@@ -39,7 +39,7 @@ public class SearchFragment extends Fragment {
private static int CURRENT_PAGE = 0;
private static final int LIMIT = 8;
private static int TOTAL_PAGE = 0;
private static boolean LAST_PAGE;
private static int ACTION_CODE = -1;
private static final int LIST_FOOD = -1;
private static final int SEARCH_FOOD = 0;
@@ -150,7 +150,7 @@ public class SearchFragment extends Fragment {
@Override
public void onResponse(Call<Foods> call, Response<Foods> response) {
//Init total page and total elements value
TOTAL_PAGE = response.body().getPage().getTotalPages();
LAST_PAGE = response.body().getPage().isLast();
loadFoodAdapter(response);
@@ -158,7 +158,8 @@ public class SearchFragment extends Fragment {
@Override
public void onFailure(Call<Foods> call, Throwable t) {
//Check internet connection
Common.showNotificationError(t, getContext(), getActivity());
}
});
}
@@ -173,7 +174,7 @@ public class SearchFragment extends Fragment {
foodAdapter.notifyDataSetChanged();
//If list data don't have pagination
if(TOTAL_PAGE == 1)
if(LAST_PAGE)
hideProgressBarAndShowEndOfListText();
//If search not found
@@ -236,13 +237,7 @@ public class SearchFragment extends Fragment {
@Override
public void onFailure(Call<List<Category>> call, Throwable t) {
//Check internet connection
if(Common.checkInternetConnection(getContext())){
//Has internet connection
Toast.makeText(getContext(), "Error: " + t, Toast.LENGTH_SHORT).show();
} else {
//No internet, show notification
Common.showErrorInternetConnectionNotification(getActivity());
}
Common.showNotificationError(t, getContext(), getActivity());
}
});
}
@@ -252,20 +247,15 @@ public class SearchFragment extends Fragment {
@Override
public void onResponse(Call<Foods> call, Response<Foods> response) {
//Init total page and total elements value
TOTAL_PAGE = response.body().getPage().getTotalPages();
LAST_PAGE = response.body().getPage().isLast();
loadFoodAdapter(response);
}
@Override
public void onFailure(Call<Foods> call, Throwable t) {
//Check internet connection
if(Common.checkInternetConnection(getContext())){
//Has internet connection
Toast.makeText(getContext(), "Error: " + t, Toast.LENGTH_SHORT).show();
} else {
//No internet, show notification
Common.showErrorInternetConnectionNotification(getActivity());
}
//Check internet connection
Common.showNotificationError(t, getContext(), getActivity());
}
});
}
@@ -274,20 +264,14 @@ public class SearchFragment extends Fragment {
FoodApi.apiService.listFood(page, LIMIT, "id", "asc").enqueue(new Callback<Foods>() {
@Override
public void onResponse(Call<Foods> call, Response<Foods> response) {
TOTAL_PAGE = response.body().getPage().getTotalPages();
LAST_PAGE = response.body().getPage().isLast();
loadFoodAdapter(response);
}
@Override
public void onFailure(Call<Foods> call, Throwable t) {
//Check internet connection
if(Common.checkInternetConnection(getContext())){
//Has internet connection
Toast.makeText(getContext(), "Error: " + t, Toast.LENGTH_SHORT).show();
} else {
//No internet, show notification
Common.showErrorInternetConnectionNotification(getActivity());
}
Common.showNotificationError(t, getContext(), getActivity());
}
});
}
@@ -295,7 +279,7 @@ public class SearchFragment extends Fragment {
private void dataLoadMore() {
switch (ACTION_CODE){
case LIST_FOOD:{
if(CURRENT_PAGE < TOTAL_PAGE - 1){
if(!LAST_PAGE){
getListFood(++CURRENT_PAGE);
} else {
hideProgressBarAndShowEndOfListText();
@@ -303,7 +287,7 @@ public class SearchFragment extends Fragment {
break;
}
case SEARCH_FOOD:{
if(CURRENT_PAGE < TOTAL_PAGE - 1){
if(!LAST_PAGE){
getListFoodBySearch(searchQuery, ++CURRENT_PAGE);
} else {
hideProgressBarAndShowEndOfListText();
@@ -311,7 +295,7 @@ public class SearchFragment extends Fragment {
break;
}
case LIST_FOOD_BY_CATEGORY:{
if(CURRENT_PAGE < TOTAL_PAGE - 1){
if(!LAST_PAGE){
getListFoodByCategory(++CURRENT_PAGE);
} else {
hideProgressBarAndShowEndOfListText();
@@ -76,6 +76,7 @@
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:visibility="gone"
/>
<TextView
@@ -134,6 +135,30 @@
app:layout_constraintStart_toStartOf="parent"
/>
<ProgressBar
android:id="@+id/progress_bar"
android:indeterminateTint="@color/primaryColor"
app:layout_constraintTop_toBottomOf="@id/recycler_view_food_shop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/end_of_list_text"
android:text="End of list"
android:fontFamily="@font/opensans"
android:textColor="@color/grayLight"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/progress_bar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
@@ -122,6 +122,7 @@
android:layout_height="wrap_content"
android:src="@drawable/basket_icon"
android:layout_gravity="center_vertical"
android:id="@+id/basket_icon"
/>
</LinearLayout>