diff --git a/.idea/dictionaries/tamkien.xml b/.idea/dictionaries/tamkien.xml
index 166e60c..7f17c43 100644
--- a/.idea/dictionaries/tamkien.xml
+++ b/.idea/dictionaries/tamkien.xml
@@ -2,6 +2,7 @@
signup
+ vijn
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..e8cfb0d
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index a5f05cd..35ffc9d 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -21,5 +21,15 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index d5d35ec..e806de6 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,5 +1,48 @@
+
+
+
+
+
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9c07a47
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# VinMartAuth
+PRM391 Final Project
diff --git a/app/build.gradle b/app/build.gradle
index f72377a..45f73cd 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,10 +4,11 @@ plugins {
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
+apply plugin: 'kotlin-android'
android {
compileSdkVersion 30
- buildToolsVersion "30.0.2"
+ buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.fpt.vinmartauth"
@@ -34,14 +35,29 @@ android {
dependencies {
//Import the FirebaseBOM
implementation platform('com.google.firebase:firebase-bom:26.6.0')
-
+ implementation 'com.github.mukeshsolanki:android-otpview-pinview:2.1.2'
implementation 'com.google.firebase:firebase-analytics'
+ implementation 'com.google.firebase:firebase-firestore'
+ implementation 'com.google.firebase:firebase-auth'
+ implementation 'com.google.firebase:firebase-storage'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.google.firebase:firebase-auth:20.0.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+ implementation 'com.github.mancj:MaterialSearchBar:0.8.5'
+ implementation 'com.github.mancj:MaterialSearchBar:0.8.5'
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
-}
\ No newline at end of file
+ implementation "androidx.core:core-ktx:1.3.2"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'com.github.mancj:MaterialSearchBar:0.8.5'
+ implementation 'com.cepheuen.elegant-number-button:lib:1.0.3'
+ implementation 'com.squareup.picasso:picasso:2.8'
+}
+repositories {
+ mavenCentral()
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f95aa08..8d662d9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,17 +1,29 @@
+ package="com.fpt.vinmartauth"
+ xmlns:tools="http://schemas.android.com/tools">
+
+
+
-
-
-
+ android:theme="@style/Theme.VinMartAuth"
+ tools:replace="android:theme">
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png
new file mode 100644
index 0000000..e0a8515
Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ
diff --git a/app/src/main/java/com/fpt/vinmartauth/MainActivity.java b/app/src/main/java/com/fpt/vinmartauth/MainActivity.java
deleted file mode 100644
index 2524df4..0000000
--- a/app/src/main/java/com/fpt/vinmartauth/MainActivity.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.fpt.vinmartauth;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.widget.Button;
-
-import androidx.appcompat.app.AppCompatActivity;
-
-import com.fpt.vinmartauth.login.LoginActivity;
-
-public class MainActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Button btnSignIn = findViewById(R.id.button);
- btnSignIn.setOnClickListener(view -> {
- Intent i = new Intent(this, LoginActivity.class);
- startActivity(i);
- });
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/adapter/CartAdapter.java b/app/src/main/java/com/fpt/vinmartauth/adapter/CartAdapter.java
new file mode 100644
index 0000000..5222b17
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/adapter/CartAdapter.java
@@ -0,0 +1,106 @@
+package com.fpt.vinmartauth.adapter;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.cepheuen.elegantnumberbutton.view.ElegantNumberButton;
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.entity.CartItem;
+import com.fpt.vinmartauth.view.fragment.cartView.CartFragment;
+import com.squareup.picasso.Picasso;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CartAdapter extends RecyclerView.Adapter{
+
+ private final static List cartItemList = new ArrayList<>();
+ private static final CartAdapter cartAdapter = new CartAdapter();
+
+ private CartAdapter() {}
+
+ public static CartAdapter getInstance() {
+ if (cartAdapter != null) {
+ return cartAdapter;
+ } else return new CartAdapter();
+ }
+
+ public void setData(List cartItems) {
+ cartItemList.clear();
+ cartItemList.addAll(cartItems);
+ notifyDataSetChanged();
+ }
+
+ public List getCartItemList() {
+ return cartItemList;
+ }
+
+ // pass layout to ViewHolder
+ @NonNull
+ @Override
+ public CartHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_row_cart_item, parent, false);
+ return new CartHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull CartHolder holder, int position) {
+ CartItem item = cartItemList.get(position);
+ holder.bind(item);
+ }
+
+ @Override
+ public int getItemCount() {
+ return cartItemList.size();
+ }
+
+
+ public static class CartHolder extends RecyclerView.ViewHolder{
+
+ public TextView tvProductTitle;
+ public TextView tvProductPrice;
+ public ImageView productImage;
+ public ElegantNumberButton quantityUpDownNumBtn;
+ private final String TEXT_VIEW_PRICE_LABEL_HEAD = "Giá:\t";
+ private final String CURRENCY_SYMBOL = " đ";
+
+ public CartHolder(@NonNull View itemView) {
+ super(itemView);
+ tvProductTitle = itemView.findViewById(R.id.tv_product_title);
+ tvProductPrice = itemView.findViewById(R.id.tv_product_price);
+ productImage = itemView.findViewById(R.id.img_product);
+ quantityUpDownNumBtn = itemView.findViewById(R.id.emb_quantity);
+ }
+
+ private String multipleQuantityWithPrice(String quantity, String price) {
+ return TEXT_VIEW_PRICE_LABEL_HEAD
+ .concat(String.valueOf(Integer.parseInt(price)*Integer.parseInt(quantity)))
+ .concat(CURRENCY_SYMBOL);
+ }
+
+ public void bind(CartItem item) {
+ tvProductTitle.setText(item.getProductTitle());
+ tvProductPrice.setText(multipleQuantityWithPrice(item.getQuantity(), item.getProductPrice()));
+ if (!item.getProductImage().isEmpty()) {
+ Picasso.get().load(item.getProductImage()).into(productImage);
+ }
+ quantityUpDownNumBtn.setNumber(item.getQuantity());
+ quantityUpDownNumBtn.setOnValueChangeListener((view, oldValue, newValue) -> {
+ item.setQuantity(String.valueOf(newValue));
+ cartItemList.get(cartItemList.indexOf(item)).setQuantity(String.valueOf(newValue));
+ tvProductPrice.setText(multipleQuantityWithPrice(item.getQuantity(), item.getProductPrice()));
+ // re-calculate and set total price of all items in cart
+ int cartTotal = cartItemList.stream().
+ mapToInt(i -> Integer.parseInt(i.getProductPrice()) * Integer.parseInt(i.getQuantity())).sum();
+ CartFragment.tvCartTotal.setText(String.valueOf(cartTotal).concat(CURRENCY_SYMBOL));
+ });
+ }
+ }
+}
+
diff --git a/app/src/main/java/com/fpt/vinmartauth/adapter/CategoryAdapter.kt b/app/src/main/java/com/fpt/vinmartauth/adapter/CategoryAdapter.kt
new file mode 100644
index 0000000..11eb03c
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/adapter/CategoryAdapter.kt
@@ -0,0 +1,49 @@
+package com.fpt.vinmartauth.adapter
+
+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 androidx.recyclerview.widget.RecyclerView
+import com.fpt.vinmartauth.R
+import com.fpt.vinmartauth.entity.CategoryIcon
+import com.fpt.vinmartauth.view.by_category.ViewByCategoryActivity
+
+class CategoryAdapter(private val list: List) :
+ RecyclerView.Adapter() {
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ val view =
+ LayoutInflater.from(parent.context).inflate(R.layout.layout_category, parent, false)
+ return ViewHolder(view)
+ }
+
+ override fun getItemCount(): Int {
+ return list.size
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ val icon = list[position]
+ if (holder is ViewHolder) {
+ holder.bind(icon)
+ holder.itemView.setOnClickListener { v ->
+ val intent = Intent(v.context, ViewByCategoryActivity::class.java)
+ intent.putExtra("CategoryName", icon.catName)
+ intent.putExtra("CategoryID", icon.catID)
+ v.context.startActivity(intent)
+ }
+ }
+ }
+
+ inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ fun bind(item: CategoryIcon) {
+ val name: TextView = itemView.findViewById(R.id.tvCatName)
+ val imgSrc: ImageView = itemView.findViewById(R.id.ivCatIcon)
+
+ name.text = item.catName
+ imgSrc.setImageResource(item.imgSrc)
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/adapter/ProductAdapter.java b/app/src/main/java/com/fpt/vinmartauth/adapter/ProductAdapter.java
new file mode 100644
index 0000000..15fe583
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/adapter/ProductAdapter.java
@@ -0,0 +1,83 @@
+package com.fpt.vinmartauth.adapter;
+
+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 androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.Adapter;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.entity.Product;
+import com.squareup.picasso.Picasso;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProductAdapter extends Adapter {
+ private final ArrayList items = new ArrayList<>();
+ private ProductAdapterListener listener;
+
+ public void setListener(ProductAdapterListener listener) {
+ this.listener = listener;
+ }
+
+ public void setData(List products) {
+ items.clear();
+ items.addAll(products);
+ notifyDataSetChanged();
+ }
+
+ @NonNull
+ @Override
+ public ProductAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_product, parent, false);
+ return new ProductAdapter.ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+ Product product = items.get(position);
+ ((ProductAdapter.ViewHolder) holder).bind(product);
+ holder.itemView.setOnClickListener(v -> listener.onProductClick(product)
+ );
+ }
+
+ public interface ProductAdapterListener {
+ void onProductClick(Product product);
+ }
+
+ @Override
+ public int getItemCount() {
+ return items.size();
+ }
+
+ static class ViewHolder extends RecyclerView.ViewHolder {
+ private final TextView itemName;
+ private final TextView itemBrand;
+ private final TextView itemPrice;
+ private final ImageView itemImage;
+
+ public ViewHolder(final View view) {
+ super(view);
+ itemName = view.findViewById(R.id.tvProductName);
+ itemBrand = view.findViewById(R.id.tvProductBrand);
+ itemPrice = view.findViewById(R.id.tvProductPrice);
+ itemImage = view.findViewById(R.id.ivProductImage);
+ }
+
+ public void bind(final Product item) {
+ itemName.setText(item.getTitle());
+ itemBrand.setText(item.getVendor());
+ itemPrice.setText(item.getPrice() + "₫");
+ if (!item.getImage().isEmpty()) {
+ Picasso.get().load(item.getImage()).into(itemImage);
+ }
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/adapter/ProfileMenuItemAdapter.java b/app/src/main/java/com/fpt/vinmartauth/adapter/ProfileMenuItemAdapter.java
new file mode 100644
index 0000000..d4828e5
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/adapter/ProfileMenuItemAdapter.java
@@ -0,0 +1,110 @@
+package com.fpt.vinmartauth.adapter;
+
+import android.app.AlertDialog;
+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 androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.entity.ProfileMenuItem;
+import com.fpt.vinmartauth.view.EditProfile;
+import com.fpt.vinmartauth.view.LoginActivity;
+import com.fpt.vinmartauth.view.MainActivity;
+import com.fpt.vinmartauth.view.fragment.cartView.UserSession;
+import com.google.firebase.auth.FirebaseAuth;
+
+import java.util.ArrayList;
+
+import static androidx.recyclerview.widget.RecyclerView.Adapter;
+
+public class ProfileMenuItemAdapter extends Adapter {
+ private final ArrayList items = new ArrayList<>();
+
+ public ProfileMenuItemAdapter(final ArrayList i) {
+ if (i != null) {
+ this.items.addAll(i);
+ }
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_profile_menu_item, parent, false);
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+ ((ViewHolder) holder).bind(items.get(position));
+
+ }
+
+ @Override
+ public int getItemCount() {
+ return items.size();
+ }
+
+ static class ViewHolder extends RecyclerView.ViewHolder implements UserAuthentication {
+ private final TextView itemName;
+ private final ImageView itemIcon;
+
+ public ViewHolder(final View view) {
+ super(view);
+ itemName = view.findViewById(R.id.tvProfileMenuItemName);
+ itemIcon = view.findViewById(R.id.ivProfileMenuItemIcon);
+ view.setOnClickListener(v -> {
+ String item = itemName.getText().toString();
+ Intent intent;
+ switch (item) {
+ case "Chỉnh sửa hồ sơ":
+ intent = new Intent(v.getContext(), EditProfile.class);
+ v.getContext().startActivity(intent);
+ break;
+ case "Đăng nhập":
+ intent = new Intent(v.getContext(), LoginActivity.class);
+ v.getContext().startActivity(intent);
+ break;
+ case "Đăng xuất":
+ new AlertDialog.Builder(v.getContext())
+ .setTitle("Đăng xuất")
+ .setMessage("Bạn có chắc chắn muốn đăng xuất không?")
+ .setNegativeButton("Không", null)
+ .setPositiveButton("Có", (args0, args1) ->{
+ signOut();
+ Intent i = new Intent(v.getContext(), MainActivity.class);
+ v.getContext().startActivity(i);
+ })
+ .create()
+ .show();
+ break;
+ }
+ });
+ }
+
+ public void bind(final ProfileMenuItem item) {
+ itemName.setText(item.getItemName());
+ itemIcon.setImageResource(item.getIconID());
+ }
+
+ @Override
+ public void signOut() {
+ UserSession session = UserSession.getInstance();
+ session.setCartID("");
+ session.setUID("");
+ CartAdapter cartAdapter = CartAdapter.getInstance();
+ cartAdapter.setData(new ArrayList<>());
+ FirebaseAuth.getInstance().signOut();
+ }
+ }
+
+ public interface UserAuthentication {
+ void signOut();
+ }
+
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/authentication/UserAuthentication.java b/app/src/main/java/com/fpt/vinmartauth/authentication/UserAuthentication.java
new file mode 100644
index 0000000..7ed67ef
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/authentication/UserAuthentication.java
@@ -0,0 +1,17 @@
+package com.fpt.vinmartauth.authentication;
+
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+
+public class UserAuthentication {
+
+ private FirebaseAuth mAuth;
+
+ public UserAuthentication() {
+ mAuth = FirebaseAuth.getInstance();
+ }
+
+ public boolean isLoggedIn() {
+ return mAuth.getCurrentUser() != null;
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/entity/Cart.java b/app/src/main/java/com/fpt/vinmartauth/entity/Cart.java
new file mode 100644
index 0000000..fbd2e76
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/entity/Cart.java
@@ -0,0 +1,80 @@
+package com.fpt.vinmartauth.entity;
+
+import com.google.firebase.Timestamp;
+
+import java.util.Date;
+
+public class Cart {
+ private String documentID;
+ private String UID;
+ private boolean isCheckout;
+ private Timestamp createdAt;
+ private Timestamp updatedAt;
+ private String cartTotal; // will set when isCheckout is true
+
+ public Cart() {
+ this.createdAt = new Timestamp(new Date());
+ this.updatedAt = new Timestamp(new Date());
+ this.isCheckout = false;
+ }
+
+ @Override
+ public String toString() {
+ return "Cart{" +
+ "documentID='" + documentID + '\'' +
+ ", UID='" + UID + '\'' +
+ ", isCheckout=" + isCheckout +
+ ", createdAt=" + createdAt +
+ ", updatedAt=" + updatedAt +
+ ", cartTotal='" + cartTotal + '\'' +
+ '}';
+ }
+
+ public String getDocumentID() {
+ return documentID;
+ }
+
+ public void setDocumentID(String documentID) {
+ this.documentID = documentID;
+ }
+
+ public String getUID() {
+ return UID;
+ }
+
+ public void setUID(String UID) {
+ this.UID = UID;
+ }
+
+ public boolean isCheckout() {
+ return isCheckout;
+ }
+
+ public void setCheckout(boolean checkout) {
+ isCheckout = checkout;
+ }
+
+ public Timestamp getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(Timestamp createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public Timestamp getUpdatedAt() {
+ return updatedAt;
+ }
+
+ public void setUpdatedAt(Timestamp updatedAt) {
+ this.updatedAt = updatedAt;
+ }
+
+ public String getCartTotal() {
+ return cartTotal;
+ }
+
+ public void setCartTotal(String cartTotal) {
+ this.cartTotal = cartTotal;
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/entity/CartItem.java b/app/src/main/java/com/fpt/vinmartauth/entity/CartItem.java
new file mode 100644
index 0000000..66806f5
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/entity/CartItem.java
@@ -0,0 +1,83 @@
+package com.fpt.vinmartauth.entity;
+
+public class CartItem {
+ private String documentID;
+ private String productID;
+ private String productImage;
+ private String productTitle;
+ private String productPrice;
+ private String quantity;
+
+ @Override
+ public String toString() {
+ return "CartItem{" +
+ "documentID='" + documentID + '\'' +
+ ", productID='" + productID + '\'' +
+ ", productImage='" + productImage + '\'' +
+ ", productTitle='" + productTitle + '\'' +
+ ", productPrice='" + productPrice + '\'' +
+ ", quantity='" + quantity + '\'' +
+ '}';
+ }
+
+ public CartItem() {
+ }
+
+ public CartItem(String documentID, String productID, String productImage, String productTitle, String productPrice, String quantity) {
+ this.documentID = documentID;
+ this.productID = productID;
+ this.productImage = productImage;
+ this.productTitle = productTitle;
+ this.productPrice = productPrice;
+ this.quantity = quantity;
+ }
+
+ public String getDocumentID() {
+ return documentID;
+ }
+
+ public void setDocumentID(String documentID) {
+ this.documentID = documentID;
+ }
+
+ public String getProductID() {
+ return productID;
+ }
+
+ public void setProductID(String productID) {
+ this.productID = productID;
+ }
+
+ public String getProductImage() {
+ return productImage;
+ }
+
+ public void setProductImage(String productImage) {
+ this.productImage = productImage;
+ }
+
+ public String getProductTitle() {
+ return productTitle;
+ }
+
+ public void setProductTitle(String productTitle) {
+ this.productTitle = productTitle;
+ }
+
+ public String getProductPrice() {
+ return productPrice;
+ }
+
+ public void setProductPrice(String productPrice) {
+ this.productPrice = productPrice;
+ }
+
+ public String getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(String quantity) {
+ this.quantity = quantity;
+ }
+}
+
diff --git a/app/src/main/java/com/fpt/vinmartauth/entity/Category.java b/app/src/main/java/com/fpt/vinmartauth/entity/Category.java
new file mode 100644
index 0000000..8335893
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/entity/Category.java
@@ -0,0 +1,32 @@
+package com.fpt.vinmartauth.entity;
+
+import java.io.Serializable;
+
+public class Category implements Serializable {
+ private String id;
+ private String title;
+
+ public Category(String id, String title) {
+ this.id = id;
+ this.title = title;
+ }
+
+ public Category() {
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/entity/CategoryIcon.kt b/app/src/main/java/com/fpt/vinmartauth/entity/CategoryIcon.kt
new file mode 100644
index 0000000..df176b9
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/entity/CategoryIcon.kt
@@ -0,0 +1,3 @@
+package com.fpt.vinmartauth.entity
+
+class CategoryIcon(var imgSrc: Int, var catName: String, var catID : String)
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/entity/Product.java b/app/src/main/java/com/fpt/vinmartauth/entity/Product.java
new file mode 100644
index 0000000..8e377db
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/entity/Product.java
@@ -0,0 +1,118 @@
+package com.fpt.vinmartauth.entity;
+
+import java.io.Serializable;
+import java.util.Collections;
+
+public class Product implements Serializable, Comparable {
+ private String id;
+ private Category category;
+ private String description;
+ private String image;
+ private int price;
+ private String quantity;
+ private String title;
+ private String vendor;
+
+ public Product(String id, Category category, String description, String image, int price, String quantity, String title, String vendor) {
+ this.id = id;
+ this.category = category;
+ this.description = description;
+ this.image = image;
+ this.price = price;
+ this.quantity = quantity;
+ this.title = title;
+ this.vendor = vendor;
+ }
+
+ public Product() {
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public Category getCategory() {
+ return category;
+ }
+
+ public void setCategory(Category category) {
+ this.category = category;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getImage() {
+ return image;
+ }
+
+ public void setImage(String image) {
+ this.image = image;
+ }
+
+ public int getPrice() {
+ return price;
+ }
+
+ public void setPrice(int price) {
+ this.price = price;
+ }
+
+ public String getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(String quantity) {
+ this.quantity = quantity;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getVendor() {
+ return vendor;
+ }
+
+ public void setVendor(String vendor) {
+ this.vendor = vendor;
+ }
+
+ @Override
+ public String toString() {
+ return "Product{" +
+ "id='" + id + '\'' +
+ ", category=" + category +
+ ", description='" + description + '\'' +
+ ", image='" + image + '\'' +
+ ", price=" + price +
+ ", quantity='" + quantity + '\'' +
+ ", title='" + title + '\'' +
+ ", vendor='" + vendor + '\'' +
+ '}';
+ }
+
+ @Override
+ public int compareTo(Product o) {
+ if(price == o.price){
+ return 0;
+ } else if(price > o.price ){
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/entity/ProfileMenuItem.java b/app/src/main/java/com/fpt/vinmartauth/entity/ProfileMenuItem.java
new file mode 100644
index 0000000..27a1c73
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/entity/ProfileMenuItem.java
@@ -0,0 +1,27 @@
+package com.fpt.vinmartauth.entity;
+
+public class ProfileMenuItem {
+ int iconID;
+ String itemName;
+
+ public ProfileMenuItem(int iconID, String itemName) {
+ this.iconID = iconID;
+ this.itemName = itemName;
+ }
+
+ public int getIconID() {
+ return iconID;
+ }
+
+ public void setIconID(int iconID) {
+ this.iconID = iconID;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public void setItemName(String itemName) {
+ this.itemName = itemName;
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/entity/User.java b/app/src/main/java/com/fpt/vinmartauth/entity/User.java
new file mode 100644
index 0000000..4d48f71
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/entity/User.java
@@ -0,0 +1,70 @@
+package com.fpt.vinmartauth.entity;
+
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Date;
+
+public class User {
+ private String fullName;
+ private String phone;
+ private String email;
+ private String password;
+ private String profileImageLink;
+
+ public User() {
+ }
+
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String fullName) {
+ this.fullName = fullName;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getProfileImageLink() {
+ return profileImageLink;
+ }
+
+ public void setProfileImageLink(String profileImageLink) {
+ this.profileImageLink = profileImageLink;
+ }
+
+ @NotNull
+ @Override
+ public String toString() {
+ return "Customer{" +
+ "fullName='" + fullName + '\'' +
+ ", phone='" + phone + '\'' +
+ ", email='" + email + '\'' +
+ ", password='" + password + '\'' +
+ ", profileImageLink='" + profileImageLink + '\'' +
+ '}';
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/login/LoginActivity.java b/app/src/main/java/com/fpt/vinmartauth/login/LoginActivity.java
deleted file mode 100644
index 64b4b4c..0000000
--- a/app/src/main/java/com/fpt/vinmartauth/login/LoginActivity.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.fpt.vinmartauth.login;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.widget.Button;
-
-import androidx.appcompat.app.AppCompatActivity;
-
-import com.fpt.vinmartauth.R;
-
-public class LoginActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_login);
- Button btnSignUp = findViewById(R.id.btn_sign_up);
- btnSignUp.setOnClickListener(view -> {
- Intent intent = new Intent(this, SignupActivity.class);
- startActivity(intent);
- });
- }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/login/SignupActivity.java b/app/src/main/java/com/fpt/vinmartauth/login/SignupActivity.java
deleted file mode 100644
index 54a039f..0000000
--- a/app/src/main/java/com/fpt/vinmartauth/login/SignupActivity.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.fpt.vinmartauth.login;
-
-import android.os.Bundle;
-import android.widget.ImageView;
-
-import androidx.appcompat.app.AppCompatActivity;
-
-import com.fpt.vinmartauth.R;
-
-public class SignupActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_signup);
- ImageView btnBack = findViewById(R.id.btnBack);
- btnBack.setOnClickListener(view -> finish());
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/model/CartItemModel.java b/app/src/main/java/com/fpt/vinmartauth/model/CartItemModel.java
new file mode 100644
index 0000000..a9ecf5c
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/model/CartItemModel.java
@@ -0,0 +1,323 @@
+package com.fpt.vinmartauth.model;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.fpt.vinmartauth.entity.Cart;
+import com.fpt.vinmartauth.entity.CartItem;
+import com.fpt.vinmartauth.entity.Product;
+import com.fpt.vinmartauth.view.dialog.LoadingDialog;
+import com.fpt.vinmartauth.view.fragment.cartView.UserSession;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.firebase.Timestamp;
+import com.google.firebase.firestore.CollectionReference;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.Query;
+import com.google.firebase.firestore.QuerySnapshot;
+import com.google.firebase.firestore.WriteBatch;
+
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CartItemModel {
+ private final FirebaseFirestore instance;
+ private final String SUCCESS_TAG = "SUCCESS";
+ private final String ERROR_TAG = "ERROR";
+ private final String CART_COLLECTION_PATH = "carts";
+ private final String CART_IS_CHECKOUT_FIELD = "isCheckout";
+ private final String CART_UID_FIELD = "UID";
+ private final String CART_UPDATED_AT_FIELD = "updatedAt";
+ private final String CART_CART_TOTAL_FIELD = "cartTotal";
+ private final String CART_DOCUMENT_ID_FIELD = "documentID";
+ private final String ITEM_COLLECTION_PATH = "items";
+ private final String ITEM_QUANTITY_FIELD = "quantity";
+ private final String UPDATE_SUCCESS_MESSAGE = "Đơn hàng đặt thành công";
+ private final String UPDATE_ERROR_MESSAGE = "Lỗi đặt hàng.";
+ private final String CART_DOCUMENT_ID_PREFIX = "Cax";
+ private final String ITEM_DOCUMENT_ID_PREFIX = "CI";
+ private final String ITEM_DOCUMENT_START_ID = "CI01";
+ private LoadingDialog loadingDialog;
+
+
+ public CartItemModel() {
+ instance = FirestoreInstance.getInstance();
+ }
+
+ // method to get Cart by ID
+ public void getCartByID(String UID, GetCartByIDCallbacks callbacks) {
+ CollectionReference cartRef = instance.collection(CART_COLLECTION_PATH);
+ Query query = cartRef.whereEqualTo(CART_UID_FIELD, UID);
+ query.addSnapshotListener((value, error) -> {
+ if (!value.isEmpty()) {
+ Cart cart = null;
+ for (DocumentSnapshot doc : value.getDocuments()) {
+ if (!doc.getBoolean(CART_IS_CHECKOUT_FIELD)) {
+ cart = doc.toObject(Cart.class);
+ cart.setCheckout(doc.getBoolean(CART_IS_CHECKOUT_FIELD));
+ }
+ }
+ callbacks.onSuccess(cart);
+ } else {
+ Log.d(ERROR_TAG, "Unable to get cart");
+ }
+ });
+ }
+
+ public interface GetCartByIDCallbacks {
+ void onSuccess(Object cart);
+ }
+
+ // method to populate querySnapshot to List of Cart
+ private List populateCart(QuerySnapshot collection) {
+ List carts = new ArrayList<>();
+ for (DocumentSnapshot doc : collection) {
+ Cart c = doc.toObject(Cart.class);
+ c.setCheckout(doc.getBoolean(CART_IS_CHECKOUT_FIELD));
+ carts.add(c);
+ }
+ return carts;
+ }
+
+ // method to create add cart item
+ @SuppressLint("DefaultLocale")
+ public void getCurrentUserCart(String UID, Activity activity, GetCurrentUserCartCallbacks callbacks) {
+ loadingDialog = new LoadingDialog(activity);
+ loadingDialog.startLoadingDialog();
+ Log.d("SESSION", "Start creating new cart");
+ CollectionReference cartRef = instance.collection(CART_COLLECTION_PATH); // có trả về cartRef
+ Log.d("SESSION", "connection to firebase");
+ cartRef.get().addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ QuerySnapshot collection = task.getResult();
+ List allCarts = populateCart(collection);
+ Cart cart = allCarts.stream()
+ .filter(c -> UID.equals(c.getUID()) && !c.isCheckout()).findFirst().orElse(new Cart());
+ if (cart.getDocumentID() == null || "".equals(cart.getDocumentID())) {
+ cart.setUID(UID);
+ cart.setDocumentID(CART_DOCUMENT_ID_PREFIX.concat(String.format("%03d" , allCarts.size() + 1)));
+ cart.setCartTotal("");
+ Map cartMap = new HashMap<>();
+ cartMap.put("documentID", cart.getDocumentID());
+ cartMap.put("cartTotal", cart.getCartTotal());
+ cartMap.put("createdAt", cart.getCreatedAt());
+ cartMap.put("updatedAt", cart.getUpdatedAt());
+ cartMap.put("isCheckout", cart.isCheckout());
+ cartMap.put("UID", cart.getUID());
+ cartRef.document(cart.getDocumentID()).set(cartMap).addOnCompleteListener(task1 -> {
+ if (task1.isSuccessful()) {
+ Log.d(SUCCESS_TAG, "Create new cart for user");
+ Log.d("SESSION", "New cart created");
+ loadingDialog.dismissDialog();
+ callbacks.onSuccess(cart);
+ } else {
+ Log.d(ERROR_TAG, "Unable to create new cart");
+ }
+ });
+ } else {
+ Log.d("SESSION", "Old cart found");
+ loadingDialog.dismissDialog();
+ callbacks.onSuccess(cart);
+ }
+ } else {
+ Log.d(ERROR_TAG, "Unable to get all cart");
+ }
+ });
+ }
+
+ public interface GetCurrentUserCartCallbacks {
+ void onSuccess(Cart cart);
+ }
+
+ private List populateCartItem(QuerySnapshot collection) {
+ List items = new ArrayList<>();
+ for (DocumentSnapshot doc : collection) {
+ CartItem item = doc.toObject(CartItem.class);
+ items.add(item);
+ }
+ return items;
+ }
+
+ // get last documentID in items
+ // example: last documentID is Cx02 => return 2
+ private int getLatestDocumentID(List items) {
+ int lastestIDSuffixNumber = 0;
+ for (CartItem item : items) {
+ String [] IDSuffix = item.getDocumentID().split("I");
+ int processedSuffix = Integer.parseInt(IDSuffix[1]);
+ if (processedSuffix > lastestIDSuffixNumber) lastestIDSuffixNumber = processedSuffix;
+ }
+ return lastestIDSuffixNumber;
+ }
+
+ // method to add cart items
+ @SuppressLint("DefaultLocale")
+ public void addProductToCart(Product product, String cartID, Activity activity, UpdateCartForCheckoutCallbacks callbacks) {
+ loadingDialog = new LoadingDialog(activity);
+ loadingDialog.startLoadingDialog();
+ DocumentReference docCart = instance.collection(CART_COLLECTION_PATH)
+ .document(cartID);
+ docCart.get().addOnCompleteListener(task -> {
+ // if cart exists, do:
+ if (task.isSuccessful()) {
+ docCart.collection(ITEM_COLLECTION_PATH).get()
+ .addOnCompleteListener(task1 -> {
+ // if sub-collection "items" exists, do:
+ if (task.isSuccessful()) {
+ Log.d("ITEM", "Cart result size: " + task1.getResult().size());
+ // populate DocumentSnapshot into List of CartItem for processing
+ QuerySnapshot collection = task1.getResult();
+ List items = populateCartItem(collection);
+ // check if product has exists in cart, return new CartItem if not found
+ CartItem item = items.stream()
+ .filter(i -> product.getId().equals(i.getProductID())).findAny().orElse(new CartItem());
+ Log.d("ITEM", item != null ? item.toString() : "Item is null");
+ if (item.getDocumentID() != null) {
+ /* GIỎ HÀNG ĐÃ TỒN TẠI SẢN PHẨM VÀ THỰC HIỆN CẬP NHẬT SỐ LƯỢNG */
+ WriteBatch updateBatch = instance.batch();
+ CollectionReference itemRef = docCart.collection(ITEM_COLLECTION_PATH);
+ DocumentReference docItem = itemRef.document(item.getDocumentID());
+ updateBatch.update(docItem, ITEM_QUANTITY_FIELD, String.valueOf(Integer.parseInt(item.getQuantity()) + 1));
+ updateBatch.commit().addOnCompleteListener(task2 -> {
+ if (task1.isSuccessful()) {
+ Log.d("ITEM", "Update item quantity");
+ callbacks.onSuccess("Số lượng sản phẩm trong giỏ được cập nhật");
+ loadingDialog.dismissDialog();
+ }
+ });
+ } else {
+ /* GIỎ HÀNG ĐÃ CÓ SẢN PHẨM VÀ THỰC HIỆN THÊM SẢN PHẨM MỚI */
+ // generate item document ID, format type "CIXX" -> XX is number
+ String nextIDSuffixNumber = String.valueOf(getLatestDocumentID(items) + 1);
+ item.setDocumentID(ITEM_DOCUMENT_ID_PREFIX.concat(nextIDSuffixNumber));
+ // set starting quantity as 1
+ item.setQuantity("1");
+ item.setProductID(product.getId());
+ item.setProductImage(product.getImage());
+ item.setProductTitle(product.getTitle());
+ item.setProductPrice(String.valueOf(product.getPrice()));
+ docCart.collection(ITEM_COLLECTION_PATH)
+ .document(item.getDocumentID())
+ .set(item).addOnSuccessListener(aVoid -> {
+ callbacks.onSuccess("Sản phẩm: " + item.getProductTitle() + " được thêm vào giỏ");
+ Log.d("ITEM", "Add new item");
+ loadingDialog.dismissDialog();
+ });
+ }
+ } else {
+ /* GIỎ HÀNG CHƯA CÓ SẢN PHẨM VÀ THỰC HIỆN THÊM SẢN PHẨM ĐẦU TIÊN */
+ // add the first item to sub-collection "items"
+ CartItem item = new CartItem(ITEM_DOCUMENT_START_ID, product.getId(), product.getImage(), product.getTitle(),
+ String.valueOf(product.getPrice()),"1");
+ docCart.collection(ITEM_COLLECTION_PATH)
+ .document(item.getDocumentID())
+ .set(item).addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ /* Do callbacks to send item add success message */
+ callbacks.onSuccess("Sản phẩm: " + item.getProductTitle() + " được thêm vào giỏ");
+ Log.d("ITEM", "Add first item");
+ loadingDialog.dismissDialog();
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+
+ // method to get all cart items
+ public void getAllCartItem(String cartID, Activity activity, GetAllCartsCallbacks callbacks){
+ loadingDialog = new LoadingDialog(activity);
+ loadingDialog.startLoadingDialog();
+ CollectionReference cartRef = instance.collection(CART_COLLECTION_PATH);
+ cartRef.document(cartID)
+ .collection(ITEM_COLLECTION_PATH)
+ .get().addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ QuerySnapshot collection = task.getResult();
+ List items = new ArrayList<>();
+ for (DocumentSnapshot doc : collection) {
+ CartItem item = doc.toObject(CartItem.class);
+ items.add(item);
+ }
+ loadingDialog.dismissDialog();
+ callbacks.onSuccess(items);
+ } else {
+ Log.d(ERROR_TAG, "Get cart failed");
+ }
+ });
+ }
+
+ public interface GetAllCartsCallbacks{
+ void onSuccess(List items);
+ }
+
+ // method to delete cart item
+ public void getCartAfterDelete(String cartID, String itemID, Activity activity, GetAllCartsCallbacks callbacks) {
+ CollectionReference cartRef = instance.collection(CART_COLLECTION_PATH);
+ cartRef.document(cartID)
+ .collection(ITEM_COLLECTION_PATH)
+ .document(itemID).delete().addOnSuccessListener(new OnSuccessListener() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ getAllCartItem(cartID, activity, new GetAllCartsCallbacks() {
+ @Override
+ public void onSuccess(List items) {
+ callbacks.onSuccess(items);
+ }
+ });
+ }
+ });
+ }
+
+ // method to update cart item quantity
+ public void updateCartItemsQuantity(String cartID, List items, Activity activity) {
+ WriteBatch updateBatch = instance.batch();
+ CollectionReference cartItemRef = instance.collection(CART_COLLECTION_PATH)
+ .document(cartID)
+ .collection(ITEM_COLLECTION_PATH);
+ // add item needed update to batch
+ for (CartItem item : items) {
+ DocumentReference docItem = cartItemRef.document(item.getDocumentID());
+ updateBatch.update(docItem, ITEM_QUANTITY_FIELD,item.getQuantity());
+ }
+ updateBatch.commit().addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ Log.d(SUCCESS_TAG, UPDATE_SUCCESS_MESSAGE);
+ } else {
+ Log.d(ERROR_TAG, UPDATE_ERROR_MESSAGE);
+ }
+ });
+ }
+
+ public void updateCartForCheckout(String cartID, int cartTotal, UpdateCartForCheckoutCallbacks callbacks) {
+ WriteBatch updateBatch = instance.batch();
+ DocumentReference docCart = instance.collection(CART_COLLECTION_PATH).document(cartID);
+ updateBatch.update(docCart, CART_CART_TOTAL_FIELD, String.valueOf(cartTotal));
+ updateBatch.update(docCart, CART_IS_CHECKOUT_FIELD, true);
+ updateBatch.update(docCart, CART_UPDATED_AT_FIELD, new Timestamp(new Date()));
+ updateBatch.commit().addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ callbacks.onSuccess(UPDATE_SUCCESS_MESSAGE);
+ } else {
+ callbacks.onFailure(UPDATE_ERROR_MESSAGE);
+ }
+ });
+ }
+
+ public interface UpdateCartForCheckoutCallbacks {
+ void onSuccess(String successMessage);
+ void onFailure(String failureMessage);
+ }
+
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/model/CategoriesModel.java b/app/src/main/java/com/fpt/vinmartauth/model/CategoriesModel.java
new file mode 100644
index 0000000..8d5aca3
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/model/CategoriesModel.java
@@ -0,0 +1,57 @@
+package com.fpt.vinmartauth.model;
+
+import android.util.Log;
+
+import com.fpt.vinmartauth.entity.Category;
+import com.fpt.vinmartauth.entity.Product;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.firebase.firestore.CollectionReference;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.QueryDocumentSnapshot;
+import com.google.firebase.firestore.QuerySnapshot;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CategoriesModel {
+ private final FirebaseFirestore instance = FirestoreInstance.getInstance();
+ private final String SUCCESS_TAG = "Success request: ";
+ private final String ERROR_TAG = "Error request: ";
+
+ public void getAllCategories(CategoriesModel.GetAllCategoriesCallbacks callbacks){
+ CollectionReference categoriesCollectionRef = instance.collection("categories");
+ categoriesCollectionRef.get().addOnCompleteListener(task -> {
+ if(task.isSuccessful()){
+ QuerySnapshot snapshot = task.getResult();
+ List categories = new ArrayList<>();
+ for (QueryDocumentSnapshot document: snapshot) {
+ Category category = document.toObject(Category.class);
+ categories.add(category);
+ }
+ callbacks.onSuccess(categories);
+ }else {
+ callbacks.onFailed();
+ }
+ });
+ }
+
+ public interface GetAllCategoriesCallbacks {
+ void onSuccess(List categories);
+ void onFailed();
+ }
+
+ //comment no di
+// public Category getCategoryById(String id){
+//
+// DocumentReference documentReference = instance.collection("categories").document(id);
+// documentReference.get().addOnCompleteListener(new OnSuccessListener(){
+// @Override
+// public void onSuccess(DocumentSnapshot documentSnapshot) {
+// Category category = documentSnapshot.toObject(Category.class);
+// }
+// });
+//
+// }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/model/CustomerModel.java b/app/src/main/java/com/fpt/vinmartauth/model/CustomerModel.java
new file mode 100644
index 0000000..e69de29
diff --git a/app/src/main/java/com/fpt/vinmartauth/model/FirestoreInstance.java b/app/src/main/java/com/fpt/vinmartauth/model/FirestoreInstance.java
new file mode 100644
index 0000000..1bbd612
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/model/FirestoreInstance.java
@@ -0,0 +1,20 @@
+package com.fpt.vinmartauth.model;
+
+import android.annotation.SuppressLint;
+
+import com.google.firebase.firestore.FirebaseFirestore;
+
+public class FirestoreInstance {
+ @SuppressLint("StaticFieldLeak")
+ private static FirebaseFirestore instance;
+
+ private FirestoreInstance(){
+ }
+
+ public static FirebaseFirestore getInstance() {
+ if (instance == null) {
+ instance = FirebaseFirestore.getInstance();
+ }
+ return instance;
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/model/ProductModel.java b/app/src/main/java/com/fpt/vinmartauth/model/ProductModel.java
new file mode 100644
index 0000000..26ac225
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/model/ProductModel.java
@@ -0,0 +1,128 @@
+package com.fpt.vinmartauth.model;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.fpt.vinmartauth.entity.Category;
+import com.fpt.vinmartauth.entity.Product;
+import com.fpt.vinmartauth.utils.TextUtils;
+import com.google.android.gms.tasks.OnFailureListener;
+import com.google.android.gms.tasks.OnSuccessListener;
+import com.google.firebase.firestore.CollectionReference;
+import com.google.firebase.firestore.DocumentReference;
+import com.google.firebase.firestore.DocumentSnapshot;
+import com.google.firebase.firestore.FirebaseFirestore;
+import com.google.firebase.firestore.Query;
+import com.google.firebase.firestore.QueryDocumentSnapshot;
+import com.google.firebase.firestore.QuerySnapshot;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ProductModel {
+ private final FirebaseFirestore instance = FirestoreInstance.getInstance();
+ private final String SUCCESS_TAG = "Success request: ";
+ private final String ERROR_TAG = "Error request: ";
+
+ public void getAllProduct(GetAllProductsCallbacks callbacks) {
+
+ CollectionReference productsCollectionRef = instance.collection("products");
+ productsCollectionRef.get().addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ QuerySnapshot snapshot = task.getResult();
+ List products = new ArrayList<>();
+ for (QueryDocumentSnapshot document : snapshot) {
+ Product product = document.toObject(Product.class);
+ product.setId(document.getId());
+ products.add(product);
+ Log.d("anhntl", product.toString());
+ }
+ callbacks.onSuccess(products);
+ } else {
+ callbacks.onFailed();
+ }
+ });
+
+
+ }
+
+
+ public interface GetAllProductsCallbacks {
+ void onSuccess(List products);
+
+ void onFailed();
+ }
+
+
+ public void getProductByName(String title, GetProductsByTitleCallbacks callbacks) {
+ //Reuse getAllProduct method
+ getAllProduct(new GetAllProductsCallbacks() {
+ @Override
+ public void onSuccess(List products) {
+ List filteredProducts = new ArrayList<>();
+ products.forEach(product -> {
+ String formattedProductTitle = TextUtils.formatDiacriticalMarks(product.getTitle());
+ String formattedTitle = TextUtils.formatDiacriticalMarks(title);
+ if (formattedProductTitle.contains(formattedTitle)) {
+ filteredProducts.add(product);
+ }
+ });
+ callbacks.onSuccess(filteredProducts);
+
+ }
+
+ @Override
+ public void onFailed() {
+ callbacks.onFailed();
+ }
+ });
+ }
+
+ public interface GetProductsByTitleCallbacks {
+ void onSuccess(List products);
+ void onFailed();
+ }
+
+ public void getProductByCategoryId(Category category,GetProductsByTitleCallbacks callbacks) {
+ getAllProduct(new GetAllProductsCallbacks() {
+ @Override
+ public void onSuccess(List products) {
+ List filteredProducts = new ArrayList<>();
+ products.forEach(product -> {
+ if (product.getCategory().getId().contains(category.getId())) {
+ filteredProducts.add(product);
+ }
+ });
+ callbacks.onSuccess(filteredProducts);
+
+ }
+ @Override
+ public void onFailed() {
+ callbacks.onFailed();
+ }
+ });
+ }
+
+ public void getAllProductSortByPrice(GetProductsByTitleCallbacks callbacks){
+ getAllProduct(new GetAllProductsCallbacks() {
+ @Override
+ public void onSuccess(List products) {
+// List filteredProducts = new ArrayList<>();
+// List p = new ArrayList<>();
+ Collections.sort(products);
+ callbacks.onSuccess(products);
+
+// Log.d("bbbbb",filteredProducts.toString());
+ }
+
+ @Override
+ public void onFailed() {
+ callbacks.onFailed();
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/utils/TextUtils.java b/app/src/main/java/com/fpt/vinmartauth/utils/TextUtils.java
new file mode 100644
index 0000000..fba0ab7
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/utils/TextUtils.java
@@ -0,0 +1,12 @@
+package com.fpt.vinmartauth.utils;
+
+import java.text.Normalizer;
+import java.util.regex.Pattern;
+
+public class TextUtils {
+ public static String formatDiacriticalMarks(String original) {
+ String nfdNormalizedString = Normalizer.normalize(original, Normalizer.Form.NFD);
+ Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
+ return pattern.matcher(nfdNormalizedString).replaceAll("");
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/validation/AuthValidation.java b/app/src/main/java/com/fpt/vinmartauth/validation/AuthValidation.java
new file mode 100644
index 0000000..28e84dc
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/validation/AuthValidation.java
@@ -0,0 +1,23 @@
+package com.fpt.vinmartauth.validation;
+
+import android.util.Log;
+
+import java.util.regex.Pattern;
+
+public class AuthValidation {
+ private final String EMAIL_PATTERN = "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$";
+ private final String PHONE_PATTERN = "^\\+?\\d{10,11}$";
+ private final String PASSWORD_PATTERN = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\\w\\d]).{8,20}$";
+
+ public boolean isEmail(String s) {
+ return s.matches(EMAIL_PATTERN);
+ }
+
+ public boolean isPhone(String s) {
+ return s.matches(PHONE_PATTERN);
+ }
+
+ public boolean isValidPassword(String s) {
+ return s.matches(PASSWORD_PATTERN);
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/EditProfile.java b/app/src/main/java/com/fpt/vinmartauth/view/EditProfile.java
new file mode 100644
index 0000000..b46afaa
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/EditProfile.java
@@ -0,0 +1,172 @@
+package com.fpt.vinmartauth.view;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.entity.User;
+import com.fpt.vinmartauth.view.authentication.AuthenticationController;
+import com.fpt.vinmartauth.view.authentication.UserController;
+import com.fpt.vinmartauth.view.dialog.LoadingDialog;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.auth.UserProfileChangeRequest;
+import com.google.firebase.storage.FirebaseStorage;
+import com.google.firebase.storage.StorageReference;
+import com.squareup.picasso.Callback;
+import com.squareup.picasso.Picasso;
+
+
+public class EditProfile extends AppCompatActivity {
+
+ private ImageView btnBack;
+ private ImageView imgAvatar;
+ private Button btnCancel;
+ private Button btnSave;
+ private EditText edtFullName;
+ private EditText edtEmail;
+ private EditText edtPhone;
+ private TextView tvChangePicture;
+ private TextView tvChangePassword;
+ private Uri filePath;
+ private SwipeRefreshLayout refreshLayout;
+ private UserController userController;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_edit_profile);
+
+ imgAvatar = findViewById(R.id.imageProfile);
+
+ userController = new UserController();
+
+ tvChangePassword = findViewById(R.id.tvChangePassword);
+ tvChangePassword.setOnClickListener(v -> {
+ FirebaseUser user = userController.getmAuth().getCurrentUser();
+ FirebaseAuth.getInstance().sendPasswordResetEmail(user.getEmail());
+ Toast
+ .makeText(EditProfile.this, "Yêu cầu đặt lại mật khẩu đã được gửi đến email", Toast.LENGTH_LONG + 5)
+ .show();
+ });
+
+ refreshLayout = findViewById(R.id.swipeRefresh);
+ refreshLayout.setOnRefreshListener(() -> {
+ });
+
+ btnBack = findViewById(R.id.btnBack);
+ btnBack.setOnClickListener(v -> finish());
+
+ btnCancel = findViewById(R.id.btnCancel);
+ btnCancel.setOnClickListener(v -> new AlertDialog.Builder(this)
+ .setTitle("Thoát")
+ .setMessage("Chưa lưu các thay đổi.Bạn có chắc chắn muốn thoát?")
+ .setNegativeButton("Không", null)
+ .setPositiveButton("Có", (args0, args1) -> finish())
+ .create()
+ .show());
+
+ tvChangePicture = findViewById(R.id.tvChangePicture);
+ tvChangePicture.setOnClickListener(view -> selectImage());
+
+ User user = new AuthenticationController().getCurrentUser();
+
+ edtFullName = findViewById(R.id.edtFullName);
+ edtEmail = findViewById(R.id.edtEmail);
+ edtPhone = findViewById(R.id.edtPhone);
+ btnSave = findViewById(R.id.btnSave);
+
+ edtFullName.setText(user.getFullName());
+ edtEmail.setText(user.getEmail());
+ edtPhone.setText(user.getPhone());
+ LoadingDialog loadingDialog = new LoadingDialog(EditProfile.this);
+ loadingDialog.startLoadingDialog();
+ Picasso.get().load(Uri.parse(user.getProfileImageLink())).into(imgAvatar, new Callback() {
+ @Override
+ public void onSuccess() {
+ loadingDialog.dismissDialog();
+ Log.i("Loading image", "Done!");
+ }
+
+ @Override
+ public void onError(Exception e) {
+ loadingDialog.dismissDialog();
+ Log.i("Loading image", "Failed!");
+ }
+ });
+
+ edtPhone.setEnabled(false);
+ edtEmail.setEnabled(false);
+
+
+ btnSave.setOnClickListener(view -> {
+ String name = edtFullName.getText().toString().trim();
+
+ if (name.equals("")) {
+ edtFullName.setError("Tên không được bỏ trống");
+ return;
+ }
+
+ User u = new User();
+ u.setFullName(name);
+ userController.updateUserProfile(this, u);
+ Intent i = new Intent(EditProfile.this, MainActivity.class);
+ startActivity(i);
+ });
+
+ }
+
+ public void selectImage() {
+ Intent intent = new Intent();
+ intent.setType("image/*");
+ intent.setAction(Intent.ACTION_GET_CONTENT);
+ startActivityForResult(intent, 1);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == 1
+ && resultCode == RESULT_OK
+ && data != null
+ && data.getData() != null) {
+ filePath = data.getData();
+ imgAvatar.setImageURI(filePath);
+ }
+ uploadPicture();
+ }
+
+ private void uploadPicture() {
+ FirebaseUser user = userController.getmAuth().getCurrentUser();
+ StorageReference storageRef = FirebaseStorage.getInstance().getReference().child("images" + user.getUid());
+ storageRef.putFile(filePath).addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ Log.i("Upload image", "Successfully");
+ } else {
+ Log.i("Upload image", "Failed");
+ }
+ });
+ String photoUrl = "https://firebasestorage.googleapis.com/v0/b/vinmartauth.appspot.com/o/images" + user.getUid() + "?alt=media";
+ UserProfileChangeRequest changeRequest = new UserProfileChangeRequest.Builder().setPhotoUri(Uri.parse(photoUrl)).build();
+ user.updateProfile(changeRequest).addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ Log.i("Save image", "Successfully");
+ } else {
+ Log.i("Save image", "Failed");
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/LoginActivity.java b/app/src/main/java/com/fpt/vinmartauth/view/LoginActivity.java
new file mode 100644
index 0000000..2dc5cb9
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/LoginActivity.java
@@ -0,0 +1,73 @@
+package com.fpt.vinmartauth.view;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.validation.AuthValidation;
+import com.fpt.vinmartauth.view.authentication.AuthenticationController;
+
+public class LoginActivity extends AppCompatActivity {
+
+ private final AuthValidation authValidation = new AuthValidation();
+ private ImageView btnBack;
+ private Button btnSignIn;
+ private TextView tvResetPassword;
+ private TextView tvSignUp;
+ private EditText edtEmail;
+ private EditText edtPassword;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_login);
+
+ edtEmail = findViewById(R.id.editTextTextEmailAddress);
+ edtPassword = findViewById(R.id.editTextTextPassword);
+ btnBack = findViewById(R.id.btnBack);
+ btnBack.setOnClickListener(view -> finish());
+
+ btnSignIn = findViewById(R.id.btnHomeSignIn);
+ btnSignIn.setOnClickListener(view -> {
+ String email = edtEmail.getText().toString().toLowerCase().trim();
+ String password = edtPassword.getText().toString().trim();
+ if (!authValidation.isEmail(email)) {
+ edtEmail.setError("Email không hợp lệ");
+ return;
+ }
+ if (!authValidation.isValidPassword(password)) {
+ edtPassword.setError("Mật khẩu không hợp lệ");
+ return;
+ }
+
+ InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+ new AuthenticationController().loginWithEmail(this, email, password);
+
+ });
+
+ tvResetPassword = findViewById(R.id.txtResetPassword);
+ tvResetPassword.setOnClickListener(view -> {
+ Intent i = new Intent(this, ResetPasswordActivity.class);
+ startActivity(i);
+ });
+
+ tvSignUp = findViewById(R.id.tvSignUp);
+ tvSignUp.setOnClickListener(view -> {
+ Intent intent = new Intent(this, SignupActivity.class);
+ startActivity(intent);
+ });
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/MainActivity.java b/app/src/main/java/com/fpt/vinmartauth/view/MainActivity.java
new file mode 100644
index 0000000..9fde8dc
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/MainActivity.java
@@ -0,0 +1,81 @@
+package com.fpt.vinmartauth.view;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.view.fragment.cartView.CartFragment;
+import com.fpt.vinmartauth.view.productview.ProductFragment;
+import com.fpt.vinmartauth.view.fragment.ProfileFragment;
+import com.google.android.material.bottomnavigation.BottomNavigationView;
+
+public class MainActivity extends AppCompatActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ openFragment(ProductFragment.newInstance());
+ //call bottom nav view by id
+ BottomNavigationView bottomNavigation = findViewById(R.id.bottomNavView);
+ //create on-click listener
+ BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = item -> {
+ if (item.getItemId() == R.id.home) {
+ openFragment(ProductFragment.newInstance());
+ } else if (item.getItemId() == R.id.cart) {
+ openFragment(CartFragment.newInstance());
+ } else if (item.getItemId() == R.id.profile) {
+ openFragment(ProfileFragment.newInstance());
+ }
+ return true;
+ };
+ //set the listener
+ bottomNavigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
+ }
+
+ //when back button pressed
+ @Override
+ public void onBackPressed() {
+ BottomNavigationView bottomNavigation = findViewById(R.id.bottomNavView);
+ int selectedItemId = bottomNavigation.getSelectedItemId();
+ //if main fragment is not currently active, back to main fragment
+ if (R.id.home != selectedItemId) {
+ setHomeItem(MainActivity.this);
+ } else {//if user is already in the main fragment
+ new AlertDialog.Builder(this)
+ .setTitle("Xác nhận")
+ .setMessage("Thoát ứng dụng?")
+ .setNegativeButton("Hủy", null) //if no, show main activity.
+ .setPositiveButton("Thoát", (arg0, arg1) -> {//if yes, back to home screen.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }).create().show();
+ }
+ }
+
+ //to set home icon on button nav state to "selected"
+ private static void setHomeItem(Activity activity) {
+ BottomNavigationView bottomNavigationView = activity.findViewById(R.id.bottomNavView);
+ bottomNavigationView.setSelectedItemId(R.id.home);
+ }
+
+ //open fragments
+ private void openFragment(Fragment fragment) {
+ Log.d("Fragment", "Trying to add");
+ FragmentManager fm = getSupportFragmentManager();
+ FragmentTransaction transaction = fm.beginTransaction();
+ //replace this fragment into the old one. There are more e.g add, remove etc
+ transaction.replace(R.id.fragment_container, fragment, "New Fragment");
+ transaction.addToBackStack(null);
+ transaction.commit();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/ResetPasswordActivity.java b/app/src/main/java/com/fpt/vinmartauth/view/ResetPasswordActivity.java
new file mode 100644
index 0000000..c5202cf
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/ResetPasswordActivity.java
@@ -0,0 +1,72 @@
+package com.fpt.vinmartauth.view;
+
+import android.os.Bundle;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.validation.AuthValidation;
+import com.google.firebase.auth.FirebaseAuth;
+
+public class ResetPasswordActivity extends AppCompatActivity {
+
+ private final AuthValidation authValidation = new AuthValidation();
+ private ImageView btnBack;
+ private Button btnResetPassword;
+ private EditText edtEmail;
+ private FirebaseAuth mAuth;
+ private FirebaseAuth.AuthStateListener mAuthListener;
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mAuth.addAuthStateListener(mAuthListener);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (mAuthListener != null) {
+ mAuth.removeAuthStateListener(mAuthListener);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_reset_password);
+
+ mAuth = FirebaseAuth.getInstance();
+ mAuthListener = firebaseAuth -> {};
+
+ edtEmail = findViewById(R.id.editTextConfirmEmail);
+
+ btnBack = findViewById(R.id.btnBack);
+ btnBack.setOnClickListener(view -> finish());
+
+ btnResetPassword = findViewById(R.id.btnResetPassword);
+ btnResetPassword.setOnClickListener(view -> {
+ String email = edtEmail.getText().toString().trim();
+
+ if (!authValidation.isEmail(email)) {
+ edtEmail.setError("Email không hợp lệ");
+ return;
+ }
+
+ mAuth.sendPasswordResetEmail(email).addOnCompleteListener(task -> {
+ if (task.isSuccessful()) {
+ Toast.makeText(ResetPasswordActivity.this, "Yêu cầu gửi lại mật khẩu đã được gửi đến email", Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(ResetPasswordActivity.this, "Có lỗi xảy ra", Toast.LENGTH_LONG).show();
+ }
+ finish();
+ });
+
+
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/SignupActivity.java b/app/src/main/java/com/fpt/vinmartauth/view/SignupActivity.java
new file mode 100644
index 0000000..35f8137
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/SignupActivity.java
@@ -0,0 +1,70 @@
+package com.fpt.vinmartauth.view;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.entity.User;
+import com.fpt.vinmartauth.validation.AuthValidation;
+import com.fpt.vinmartauth.view.authentication.AuthenticationController;
+
+public class SignupActivity extends AppCompatActivity {
+
+ private final AuthValidation authValidation = new AuthValidation();
+ private ImageView btnBack;
+ private Button btnSignUp;
+ private EditText edtFullname;
+ private EditText edtEmail;
+ private EditText edtPassword;
+ private final String DEFAULT_IMAGE_LINK = "https://firebasestorage.googleapis.com/v0/b/vinmartauth.appspot.com/o/default-profile-icon-16.jpg?alt=media";
+
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_signup);
+
+ btnBack = findViewById(R.id.btnBack);
+ btnBack.setOnClickListener(view -> finish());
+
+ edtFullname = findViewById(R.id.etRegName);
+ edtEmail = findViewById(R.id.etRegEmail);
+ edtPassword = findViewById(R.id.etRegPassword);
+
+ btnSignUp = findViewById(R.id.btnSignUp);
+ btnSignUp.setOnClickListener(view -> {
+
+ String name = edtFullname.getText().toString().trim();
+ String email = edtEmail.getText().toString().toLowerCase().trim();
+ String password = edtPassword.getText().toString().trim();
+
+ if (name.equals("")) {
+ edtFullname.setError("Tên không được bỏ trống");
+ return;
+ }
+ if (!authValidation.isEmail(email)) {
+ edtEmail.setError("Email không hợp lệ");
+ return;
+ }
+ if (!authValidation.isValidPassword(password)) {
+ edtPassword.setError("Mật khẩu không hợp lệ");
+ return;
+ }
+
+ InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+ User u = new User();
+ u.setEmail(email);
+ u.setFullName(name);
+ u.setProfileImageLink(DEFAULT_IMAGE_LINK);
+ u.setPassword(password);
+ new AuthenticationController().signUpWithEmail(this, u);
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/VerificationActivity.java b/app/src/main/java/com/fpt/vinmartauth/view/VerificationActivity.java
new file mode 100644
index 0000000..9371843
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/VerificationActivity.java
@@ -0,0 +1,31 @@
+package com.fpt.vinmartauth.view;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.Button;
+import android.widget.ImageView;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.fpt.vinmartauth.R;
+
+public class VerificationActivity extends AppCompatActivity {
+ private ImageView btnBack;
+ private Button btnVerify;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_verification);
+
+
+ btnBack = findViewById(R.id.btnBack);
+ btnBack.setOnClickListener(view -> finish());
+ btnVerify = findViewById(R.id.btnVerify);
+ btnVerify.setOnClickListener(view -> {
+ Intent intent = new Intent(this, MainActivity.class);
+ startActivity(intent);
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/authentication/AuthenticationController.java b/app/src/main/java/com/fpt/vinmartauth/view/authentication/AuthenticationController.java
new file mode 100644
index 0000000..58c4c2c
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/authentication/AuthenticationController.java
@@ -0,0 +1,80 @@
+package com.fpt.vinmartauth.view.authentication;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.fpt.vinmartauth.entity.User;
+import com.fpt.vinmartauth.view.MainActivity;
+import com.fpt.vinmartauth.view.dialog.LoadingDialog;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.auth.UserProfileChangeRequest;
+
+public class AuthenticationController {
+ private FirebaseAuth mAuth;
+ private LoadingDialog loadingDialog;
+
+ public AuthenticationController() {
+ mAuth = FirebaseAuth.getInstance();
+ }
+
+ public void loginWithEmail(Context context, String email, String password) {
+ loadingDialog = new LoadingDialog((Activity) context);
+ loadingDialog.startLoadingDialog();
+ mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(task -> {
+ loadingDialog.dismissDialog();
+ if (task.isSuccessful()) {
+ Log.i("Login", "OK!");
+ Intent intent = new Intent(context, MainActivity.class);
+ context.startActivity(intent);
+ } else {
+ Log.i("Login", "Failed!");
+ Toast toast = Toast.makeText(context, "Sai email hoặc mật khẩu", Toast.LENGTH_LONG);
+ toast.show();
+ }
+ });
+ }
+
+ public void signUpWithEmail(Context context, User user) {
+ loadingDialog = new LoadingDialog((Activity) context);
+ loadingDialog.startLoadingDialog();
+ mAuth.createUserWithEmailAndPassword(user.getEmail(), user.getPassword()).addOnCompleteListener(task -> {
+ loadingDialog.dismissDialog();
+ if (task.isSuccessful()) {
+ FirebaseUser u = mAuth.getCurrentUser();
+ Log.i("Signup", "Successfully");
+ UserProfileChangeRequest profileChangeRequest = new UserProfileChangeRequest.Builder()
+ .setDisplayName(user.getFullName())
+ .setPhotoUri(Uri.parse(user.getProfileImageLink()))
+ .build();
+ u.updateProfile(profileChangeRequest);
+ Toast.makeText(context, "Đăng ký thành công", Toast.LENGTH_LONG).show();
+ Intent intent = new Intent(context, MainActivity.class);
+ intent.putExtra("email", user.getEmail());
+ context.startActivity(intent);
+ } else {
+ Log.i("Signup", "Something wrong happened!");
+ Toast toast = Toast.makeText(context, "Có lỗi xảy ra!", Toast.LENGTH_LONG);
+ toast.show();
+ }
+ });
+
+ }
+
+ public User getCurrentUser() {
+ FirebaseUser u = mAuth.getCurrentUser();
+ if (u != null) {
+ User user = new User();
+ user.setFullName(u.getDisplayName());
+ user.setEmail(u.getEmail());
+ user.setPhone(u.getPhoneNumber());
+ user.setProfileImageLink(u.getPhotoUrl().toString());
+ return user;
+ }
+ return null;
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/authentication/UserController.java b/app/src/main/java/com/fpt/vinmartauth/view/authentication/UserController.java
new file mode 100644
index 0000000..e3549c4
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/authentication/UserController.java
@@ -0,0 +1,41 @@
+package com.fpt.vinmartauth.view.authentication;
+
+import android.app.Activity;
+import android.content.Context;
+import android.widget.Toast;
+
+import com.fpt.vinmartauth.entity.User;
+import com.fpt.vinmartauth.view.dialog.LoadingDialog;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.auth.UserProfileChangeRequest;
+
+public class UserController {
+ private FirebaseAuth mAuth;
+ private LoadingDialog loadingDialog;
+
+ public UserController() {
+ mAuth = FirebaseAuth.getInstance();
+ }
+
+ public void updateUserProfile(Context context, User u) {
+ loadingDialog = new LoadingDialog((Activity) context);
+ FirebaseUser user = mAuth.getCurrentUser();
+ UserProfileChangeRequest changeRequest = new UserProfileChangeRequest.Builder().setDisplayName(u.getFullName()).build();
+ user.updateProfile(changeRequest);
+ loadingDialog.startLoadingDialog();
+ mAuth.updateCurrentUser(user).addOnCompleteListener(task -> {
+ loadingDialog.dismissDialog();
+ if (task.isSuccessful()) {
+ Toast.makeText(context, "Lưu thành công", Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(context, "Lưu thất bại!\nVui lòng thử lại sau", Toast.LENGTH_LONG).show();
+ }
+ });
+ }
+
+ public FirebaseAuth getmAuth() {
+ return mAuth;
+ }
+
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/by_category/ByCategoryController.kt b/app/src/main/java/com/fpt/vinmartauth/view/by_category/ByCategoryController.kt
new file mode 100644
index 0000000..fb78143
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/by_category/ByCategoryController.kt
@@ -0,0 +1,38 @@
+package com.fpt.vinmartauth.view.by_category
+
+import com.fpt.vinmartauth.entity.Category
+import com.fpt.vinmartauth.entity.Product
+import com.fpt.vinmartauth.model.ProductModel
+import com.fpt.vinmartauth.model.ProductModel.GetProductsByTitleCallbacks
+import java.util.*
+
+class ByCategoryController {
+ private var view: ByCategoryView? = null
+ private val productModel = ProductModel()
+ fun setView(view: ByCategoryView?) {
+ this.view = view
+ }
+
+ fun fetchProductByCategory(category: Category?, sort: Int) {
+ productModel.getProductByCategoryId(category, object : GetProductsByTitleCallbacks {
+ override fun onSuccess(products: List) {
+ when (sort) {
+ 0 -> {
+ view!!.setProducts(products.sortedByDescending { it.id })
+ }
+ 2 -> {
+ view!!.setProducts(products.sortedByDescending { it.price})
+ }
+ 1 -> {
+ view!!.setProducts(products.sortedBy { it.price })
+ }
+ else -> view!!.setProducts(products)
+ }
+ }
+
+ override fun onFailed() {
+ view!!.setProducts(ArrayList())
+ }
+ })
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/by_category/ByCategoryView.java b/app/src/main/java/com/fpt/vinmartauth/view/by_category/ByCategoryView.java
new file mode 100644
index 0000000..4692b26
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/by_category/ByCategoryView.java
@@ -0,0 +1,9 @@
+package com.fpt.vinmartauth.view.by_category;
+
+import com.fpt.vinmartauth.entity.Product;
+
+import java.util.List;
+
+public interface ByCategoryView {
+ void setProducts(List products);
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/by_category/ViewByCategoryActivity.kt b/app/src/main/java/com/fpt/vinmartauth/view/by_category/ViewByCategoryActivity.kt
new file mode 100644
index 0000000..b8053fe
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/by_category/ViewByCategoryActivity.kt
@@ -0,0 +1,74 @@
+package com.fpt.vinmartauth.view.by_category
+
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log.d
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.appcompat.app.AppCompatActivity
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.fpt.vinmartauth.R
+import com.fpt.vinmartauth.adapter.ProductAdapter
+import com.fpt.vinmartauth.entity.Category
+import com.fpt.vinmartauth.entity.Product
+import com.fpt.vinmartauth.view.productDetailView.ProductDetailsActivity
+
+class ViewByCategoryActivity : AppCompatActivity(), ByCategoryView, ProductAdapter.ProductAdapterListener {
+ var controller = ByCategoryController()
+ private val productAdapter = ProductAdapter()
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_view_by_category)
+ findViewById(R.id.tvCategoryTitle).text = intent.getStringExtra("CategoryName")
+ val catID = intent.getStringExtra("CategoryID")
+ val view = findViewById(R.id.rvViewByCategory)
+ val tvNewest: TextView = findViewById(R.id.tvNewest)
+ val tvSortBy: TextView = findViewById(R.id.tvSortBy)
+ val tvAsc: TextView = findViewById(R.id.tvAscending)
+ val tvDesc: TextView = findViewById(R.id.tvDescending)
+ view.adapter = productAdapter
+ productAdapter.setListener(this)
+ controller.setView(this)
+ controller.fetchProductByCategory(Category(catID, "pff"), 4)
+ tvNewest.setOnClickListener {
+ d("sorter", "newest")
+ tvNewest.isSelected = true
+ tvSortBy.isSelected = false
+ tvAsc.isSelected = false
+ tvDesc.isSelected = false
+ controller.fetchProductByCategory(Category(catID, "pff"), 0)
+
+ }
+ tvDesc.setOnClickListener {
+ d("sorter", "desc")
+ tvNewest.isSelected = false
+ tvSortBy.isSelected = true
+ tvAsc.isSelected = false
+ tvDesc.isSelected = true
+ controller.fetchProductByCategory(Category(catID, "pff"), 2)
+ }
+ tvAsc.setOnClickListener {
+ d("sorter", "asc")
+ tvNewest.isSelected = false
+ tvSortBy.isSelected = true
+ tvAsc.isSelected = true
+ tvDesc.isSelected = false
+ controller.fetchProductByCategory(Category(catID, "pff"), 1)
+ }
+ view.layoutManager = GridLayoutManager(view?.context, 2)
+ findViewById(R.id.imageView5).setOnClickListener {
+ finish()
+ }
+ }
+
+ override fun setProducts(products: MutableList?) {
+ productAdapter.setData(products)
+ }
+
+ override fun onProductClick(product: Product?) {
+ val intent = Intent(this, ProductDetailsActivity::class.java)
+ intent.putExtra("product", product)
+ startActivity(intent)
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/dialog/LoadingDialog.java b/app/src/main/java/com/fpt/vinmartauth/view/dialog/LoadingDialog.java
new file mode 100644
index 0000000..56e8b26
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/dialog/LoadingDialog.java
@@ -0,0 +1,32 @@
+package com.fpt.vinmartauth.view.dialog;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.view.LayoutInflater;
+
+import com.fpt.vinmartauth.R;
+
+public class LoadingDialog {
+ private Activity activity;
+ private AlertDialog dialog;
+
+ public LoadingDialog(Activity activity) {
+ this.activity = activity;
+ }
+
+ @SuppressLint("InflateParams")
+ public void startLoadingDialog() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ LayoutInflater inflater = activity.getLayoutInflater();
+ builder.setView(inflater.inflate(R.layout.loading_spinner, null));
+ builder.setCancelable(false);
+
+ dialog = builder.create();
+ dialog.show();
+ }
+
+ public void dismissDialog() {
+ dialog.dismiss();
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/fragment/MainFragment.java b/app/src/main/java/com/fpt/vinmartauth/view/fragment/MainFragment.java
new file mode 100644
index 0000000..79ae7aa
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/fragment/MainFragment.java
@@ -0,0 +1,44 @@
+package com.fpt.vinmartauth.view.fragment;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import androidx.fragment.app.Fragment;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.authentication.UserAuthentication;
+import com.fpt.vinmartauth.view.LoginActivity;
+
+
+public class MainFragment extends Fragment {
+ public static MainFragment newInstance() {
+ return new MainFragment();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ //this is actually the fragments' "onCreate"
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ //must declare to find view by id
+ View view = inflater.inflate(R.layout.fragment_main, container, false);
+ Button btnSignIn = view.findViewById(R.id.btnHomeSignIn);
+ btnSignIn.setOnClickListener(view1 -> {
+ //must be this.getContext(), not just "this".
+ if (!new UserAuthentication().isLoggedIn()) {
+ Intent i = new Intent(this.getContext(), LoginActivity.class);
+ startActivity(i);
+ }
+ });
+ // Inflate the layout for this fragment
+ return view;
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/fragment/ProfileFragment.java b/app/src/main/java/com/fpt/vinmartauth/view/fragment/ProfileFragment.java
new file mode 100644
index 0000000..6679442
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/fragment/ProfileFragment.java
@@ -0,0 +1,117 @@
+package com.fpt.vinmartauth.view.fragment;
+
+import android.annotation.SuppressLint;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.adapter.ProfileMenuItemAdapter;
+import com.fpt.vinmartauth.entity.ProfileMenuItem;
+import com.fpt.vinmartauth.entity.User;
+import com.fpt.vinmartauth.view.authentication.AuthenticationController;
+import com.fpt.vinmartauth.view.dialog.LoadingDialog;
+import com.squareup.picasso.Callback;
+import com.squareup.picasso.Picasso;
+
+import java.util.ArrayList;
+
+public class ProfileFragment extends Fragment {
+
+ private ImageView imgAvatar;
+ private TextView userFullName;
+ private TextView userEmail;
+ private final String DEFAULT_IMAGE_LINK = "https://firebasestorage.googleapis.com/v0/b/vinmartauth.appspot.com/o/default-profile-icon-16.jpg?alt=media";
+
+ public ProfileFragment() {
+ // Required empty public constructor
+ }
+
+ public static ProfileFragment newInstance() {
+ return new ProfileFragment();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @SuppressLint("SetTextI18n")
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_profile, container, false);
+ // Inflate the layout for this fragment
+ User user = new AuthenticationController().getCurrentUser();
+ ArrayList items = new ArrayList<>();
+ RecyclerView rv = view.findViewById(R.id.rcvProfileMenu);
+ if (user != null) {
+ items.add(new ProfileMenuItem(R.drawable.ic_baseline_edit_24, getString(R.string.edit_profile)));
+ items.add(new ProfileMenuItem(R.drawable.ic_baseline_location_on_24, getString(R.string.shipping_address)));
+ items.add(new ProfileMenuItem(R.drawable.ic_baseline_favorite_border_24, getString(R.string.favorite)));
+ items.add(new ProfileMenuItem(R.drawable.ic_baseline_history_24, getString(R.string.order_history)));
+ items.add(new ProfileMenuItem(R.drawable.ic_baseline_local_shipping_24, getString(R.string.track_order)));
+ items.add(new ProfileMenuItem(R.drawable.ic_baseline_credit_card_24, getString(R.string.cards)));
+ items.add(new ProfileMenuItem(R.drawable.ic_baseline_notifications_24, getString(R.string.notifications)));
+ items.add(new ProfileMenuItem(R.drawable.ic_baseline_exit_to_app_24, getString(R.string.log_out)));
+ } else {
+ items.add(new ProfileMenuItem(R.drawable.ic_baseline_sign_in, getString(R.string.sign_in)));
+ }
+
+ imgAvatar = view.findViewById(R.id.imgAvatar);
+
+ userFullName = view.findViewById(R.id.userFullName);
+ userEmail = view.findViewById(R.id.userEmail);
+
+ LoadingDialog loadingDialog = new LoadingDialog(this.getActivity());
+ loadingDialog.startLoadingDialog();
+ if (user != null) {
+ userFullName.setText(user.getFullName());
+ userEmail.setText(user.getEmail());
+ Picasso.get().load(Uri.parse(user.getProfileImageLink())).into(imgAvatar, new Callback() {
+ @Override
+ public void onSuccess() {
+ loadingDialog.dismissDialog();
+ Log.i("Loading image", "Done!");
+ }
+
+ @Override
+ public void onError(Exception e) {
+ loadingDialog.dismissDialog();
+ Log.i("Loading image", "Failed!");
+ }
+ });
+ } else {
+ userFullName.setText("Chưa đăng nhập");
+ userEmail.setText("");
+ Picasso.get().load(Uri.parse(DEFAULT_IMAGE_LINK)).into(imgAvatar, new Callback() {
+ @Override
+ public void onSuccess() {
+ loadingDialog.dismissDialog();
+ Log.i("Loading image", "Done!");
+ }
+
+ @Override
+ public void onError(Exception e) {
+ loadingDialog.dismissDialog();
+ Log.i("Loading image", "Failed!");
+ }
+ });
+ }
+
+ ProfileMenuItemAdapter adapter = new ProfileMenuItemAdapter(items);
+ rv.setLayoutManager(new LinearLayoutManager(getActivity()));
+ rv.setAdapter(adapter);
+ return view;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/CartFragment.java b/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/CartFragment.java
new file mode 100644
index 0000000..6cc10ce
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/CartFragment.java
@@ -0,0 +1,174 @@
+package com.fpt.vinmartauth.view.fragment.cartView;
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.adapter.CartAdapter;
+import com.fpt.vinmartauth.entity.Cart;
+import com.fpt.vinmartauth.entity.CartItem;
+import com.fpt.vinmartauth.view.LoginActivity;
+import com.fpt.vinmartauth.view.dialog.LoadingDialog;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.FirebaseUser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+
+
+/**
+ * A simple {@link Fragment} subclass.
+ * Use the {@link CartFragment#newInstance} factory method to
+ * create an instance of this fragment.
+ */
+public class CartFragment extends Fragment implements CartView{
+
+ private RecyclerView rvCartList;
+ public static TextView tvCartTotal;
+ private CartAdapter cartAdapter;
+ private CartViewController controller = new CartViewController();
+ private final String TOAST_DELETE_MESSAGE_HEAD = "Đã xóa: ";
+ private static final String CURRENCY_SYMBOL = " đ";
+ private Button btnCheckout;
+ private FirebaseAuth mAuth;
+ private final UserSession session = UserSession.getInstance();
+
+ public CartFragment() {}
+
+ public static CartFragment newInstance() {
+ return new CartFragment();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_cart, container, false);
+ }
+
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ controller.setView(this);
+ tvCartTotal = view.findViewById(R.id.tv_cart_total);
+ rvCartList = view.findViewById(R.id.rvCart);
+ btnCheckout = view.findViewById(R.id.btn_checkout);
+ rvCartList.setHasFixedSize(true);
+ cartAdapter = CartAdapter.getInstance();
+ rvCartList.setLayoutManager(new LinearLayoutManager(getActivity()));
+ // Attach ItemTouchHepler to the RecyclerView
+ new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(rvCartList);
+ // set checkout button on click listener
+ btnCheckout.setOnClickListener(v -> {
+ if(session.getCartID() != null || "".equals(session.getCartID())) {
+ List cartItemList = cartAdapter.getCartItemList();
+ // do checkout for current cart items
+ controller.doCartCheckout(session.getCartID(), cartItemList);
+ // clear cart items list and reset adapter
+ cartItemList = new ArrayList<>();
+ cartAdapter.setData(cartItemList);
+ tvCartTotal.setText("0 đ");
+ // clear UserSession cartID
+ session.setCartID("");
+ Log.d("checkout", session.getCartID());
+ }
+ });
+ rvCartList.setAdapter(cartAdapter);
+ init();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ List cartItemList = cartAdapter.getCartItemList();
+ Log.d("checkout", "Check cartID has been clear: " + session.getCartID().equals(""));
+ if(!session.getCartID().isEmpty() && !cartItemList.isEmpty()) {
+ controller.doCartItemsUpdate(session.getCartID(), cartItemList, getActivity());
+ }
+ }
+
+ // run first to check if user is logged in
+ private void init() {
+ Log.d("SESSION", "Init run");
+ mAuth = FirebaseAuth.getInstance();
+ FirebaseUser user = mAuth.getCurrentUser();
+ Log.d("SESSION", "Check user mAuth " + String.valueOf(user == null));
+ if (user != null) {
+ // run first time
+ Log.d("SESSION", "User has logged in");
+ if (session.getUID() == null || "".equals(session.getUID())) {
+ session.setUID(user.getUid());
+ }
+ Log.d("SESSION", session.getUID());
+ // run first time or when user need new cart
+ if (session.getCartID() == null || "".equals(session.getCartID())) {
+ controller.fetchUserCart(session.getUID(), getActivity());
+ } else controller.fetchCartItems(session.getCartID(), getActivity());
+ } else {
+ // redirect to login
+ Log.d("SESSION", "User not logged in");
+ Intent intent = new Intent(this.getContext(), LoginActivity.class);
+ startActivity(intent);
+ }
+ }
+
+ // Manage swipe interaction
+ ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new ItemTouchHelper.SimpleCallback(10,ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
+ @Override
+ public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {return false;}
+
+ @Override
+ public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction)
+ {
+ List cartItemList = cartAdapter.getCartItemList();
+ // Show toast message of removed item
+ Toast.makeText(getActivity(), TOAST_DELETE_MESSAGE_HEAD + cartItemList.get(
+ viewHolder.getAdapterPosition()).getProductTitle(), Toast.LENGTH_SHORT).show();
+ // invoke cart item list after delete in firebase
+ controller.fetchCartAfterDelete(session.getCartID(), cartItemList.get(viewHolder.getAdapterPosition()).getDocumentID(), getActivity());
+ cartAdapter.setData(cartItemList);
+ }
+ };
+
+
+ @Override
+ public void setCartItems(List cartItemList) {
+ int itemTotal = 0;
+ for (CartItem item : cartItemList)
+ itemTotal += Integer.parseInt(item.getQuantity()) * Integer.parseInt(item.getProductPrice());
+ tvCartTotal.setText(String.valueOf(itemTotal).concat(CURRENCY_SYMBOL));
+ cartAdapter.setData(cartItemList);
+ }
+
+ @Override
+ public void setMessage(String message) {
+ Toast.makeText(getActivity(), message,Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void setCart(Cart cart) {
+ session.setCartID(cart.getDocumentID());
+ Log.d("SESSION", "Got cartID: " + session.getCartID());
+ controller.fetchCartItems(session.getCartID(),getActivity());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/CartView.java b/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/CartView.java
new file mode 100644
index 0000000..02b89ca
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/CartView.java
@@ -0,0 +1,12 @@
+package com.fpt.vinmartauth.view.fragment.cartView;
+
+import com.fpt.vinmartauth.entity.Cart;
+import com.fpt.vinmartauth.entity.CartItem;
+
+import java.util.List;
+
+public interface CartView {
+ void setCartItems(List cartItemList);
+ void setMessage(String message);
+ void setCart(Cart cart);
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/CartViewController.java b/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/CartViewController.java
new file mode 100644
index 0000000..311bd15
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/CartViewController.java
@@ -0,0 +1,87 @@
+package com.fpt.vinmartauth.view.fragment.cartView;
+
+import android.app.Activity;
+import android.util.Log;
+
+import com.fpt.vinmartauth.entity.Cart;
+import com.fpt.vinmartauth.entity.CartItem;
+import com.fpt.vinmartauth.entity.Product;
+import com.fpt.vinmartauth.model.CartItemModel;
+
+import java.util.List;
+
+public class CartViewController {
+ private CartView view;
+ private final CartItemModel cartItemModel = new CartItemModel();
+
+ public void setView(CartView view) {
+ this.view = view;
+ }
+
+ void fetchCartItems(String cartID, Activity activity) {
+ cartItemModel.getAllCartItem(cartID, activity,new CartItemModel.GetAllCartsCallbacks() {
+
+ @Override
+ public void onSuccess(List items) {
+ view.setCartItems(items);
+ }
+ });
+ }
+
+ void fetchCartAfterDelete(String cartID, String itemID, Activity activity) {
+ cartItemModel.getCartAfterDelete(cartID, itemID, activity,new CartItemModel.GetAllCartsCallbacks() {
+ @Override
+ public void onSuccess(List items) {
+ view.setCartItems(items);
+ }
+ });
+ }
+
+ void doCartItemsUpdate(String cartID, List items, Activity activity) {
+ cartItemModel.updateCartItemsQuantity(cartID, items, activity);
+ }
+
+ // invoke on main activity started
+ public void fetchUserCart(String UID, Activity activity) {
+ Log.d("SESSION", "Cart fetching");
+ cartItemModel.getCurrentUserCart(UID, activity, new CartItemModel.GetCurrentUserCartCallbacks() {
+ @Override
+ public void onSuccess(Cart cart) {
+ view.setCart(cart);
+ }
+ });
+ }
+
+ void doCartCheckout(String cartID, List items) {
+ // Use Java 8 Stream
+ int totalCart = items.stream().mapToInt(i -> Integer.parseInt(i.getProductPrice()) * Integer.parseInt(i.getQuantity())).sum();
+ // Get Current cart
+ cartItemModel.updateCartForCheckout(cartID, totalCart, new CartItemModel.UpdateCartForCheckoutCallbacks() {
+ @Override
+ public void onSuccess(String successMessage) {
+ // set checkout success message
+ view.setMessage(successMessage);
+ }
+
+ @Override
+ public void onFailure(String failureMessage) {
+ // set checkout failure message
+ view.setMessage(failureMessage);
+ }
+ });
+ }
+
+ public void doAddProductItem(Product product, String cartID, Activity activity) {
+ cartItemModel.addProductToCart(product, cartID, activity, new CartItemModel.UpdateCartForCheckoutCallbacks() {
+ @Override
+ public void onSuccess(String successMessage) {
+ view.setMessage(successMessage);
+ }
+
+ @Override
+ public void onFailure(String failureMessage) {
+ view.setMessage(failureMessage);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/UserSession.java b/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/UserSession.java
new file mode 100644
index 0000000..e3fe779
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/fragment/cartView/UserSession.java
@@ -0,0 +1,32 @@
+package com.fpt.vinmartauth.view.fragment.cartView;
+
+public class UserSession {
+ private String UID;
+ private String cartID;
+ private static UserSession session = new UserSession();
+
+ private UserSession() {
+ }
+
+ public static UserSession getInstance() {
+ if (session != null) {
+ return session;
+ } return new UserSession();
+ }
+
+ public String getUID() {
+ return UID;
+ }
+
+ public void setUID(String UID) {
+ this.UID = UID;
+ }
+
+ public String getCartID() {
+ return cartID;
+ }
+
+ public void setCartID(String cartID) {
+ this.cartID = cartID;
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/productDetailView/ProductDetailView.java b/app/src/main/java/com/fpt/vinmartauth/view/productDetailView/ProductDetailView.java
new file mode 100644
index 0000000..feeb416
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/productDetailView/ProductDetailView.java
@@ -0,0 +1,7 @@
+package com.fpt.vinmartauth.view.productDetailView;
+
+import com.fpt.vinmartauth.entity.Product;
+
+public interface ProductDetailView {
+ void setProduct(Product product);
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/productDetailView/ProductDetailViewController.java b/app/src/main/java/com/fpt/vinmartauth/view/productDetailView/ProductDetailViewController.java
new file mode 100644
index 0000000..87da790
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/productDetailView/ProductDetailViewController.java
@@ -0,0 +1,4 @@
+package com.fpt.vinmartauth.view.productDetailView;
+
+public class ProductDetailViewController {
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/productDetailView/ProductDetailsActivity.java b/app/src/main/java/com/fpt/vinmartauth/view/productDetailView/ProductDetailsActivity.java
new file mode 100644
index 0000000..b3583f0
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/productDetailView/ProductDetailsActivity.java
@@ -0,0 +1,75 @@
+package com.fpt.vinmartauth.view.productDetailView;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.entity.Cart;
+import com.fpt.vinmartauth.entity.CartItem;
+import com.fpt.vinmartauth.entity.Product;
+import com.fpt.vinmartauth.view.LoginActivity;
+import com.fpt.vinmartauth.view.fragment.cartView.CartView;
+import com.fpt.vinmartauth.view.fragment.cartView.CartViewController;
+import com.fpt.vinmartauth.view.fragment.cartView.UserSession;
+import com.squareup.picasso.Picasso;
+
+import java.util.List;
+
+public class ProductDetailsActivity extends AppCompatActivity implements CartView {
+
+ private CartViewController controller = new CartViewController();
+ private final UserSession session = UserSession.getInstance();
+ private Product product;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_product_details);
+ product = (Product) getIntent().getSerializableExtra("product");
+ controller.setView(this);
+ ImageView productImg = findViewById(R.id.ivProductDetail);
+ TextView productDetailTitle = findViewById(R.id.tvProductDetailTitle);
+ productDetailTitle.setText(product.getTitle());
+ TextView productDetailDescription = findViewById(R.id.tvProductDetailDescription);
+ productDetailDescription.setText(product.getDescription());
+ TextView productDetailPrice = findViewById(R.id.tvProductDetailPrice);
+ productDetailPrice.setText(product.getPrice() + " đ");
+ Picasso.get().load(product.getImage()).into(productImg);
+ Button btnAdd = findViewById(R.id.btnAddProduct);
+ btnAdd.setOnClickListener(v -> {
+ if(!session.getUID().isEmpty()) {
+ if (session.getCartID() == null || "".equals(session.getCartID())) {
+ controller.fetchUserCart(session.getUID(), this);
+ } else {
+ controller.doAddProductItem(product, session.getCartID(), this);
+ }
+ } else {
+ Intent intent = new Intent(this, LoginActivity.class);
+ startActivity(intent);
+ }
+ });
+ }
+
+ @Override
+ public void setCartItems(List cartItemList) {
+
+ }
+
+ @Override
+ public void setMessage(String message) {
+ Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void setCart(Cart cart) {
+ session.setCartID(cart.getDocumentID());
+ controller.doAddProductItem(product ,cart.getDocumentID(), this);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/productlist/ProductListActivity.java b/app/src/main/java/com/fpt/vinmartauth/view/productlist/ProductListActivity.java
new file mode 100644
index 0000000..b811147
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/productlist/ProductListActivity.java
@@ -0,0 +1,70 @@
+package com.fpt.vinmartauth.view.productlist;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.adapter.ProductAdapter;
+import com.fpt.vinmartauth.entity.Product;
+import com.fpt.vinmartauth.view.productDetailView.ProductDetailsActivity;
+import com.mancj.materialsearchbar.MaterialSearchBar;
+
+import java.util.List;
+
+public class ProductListActivity extends Activity implements ProductListView, ProductAdapter.ProductAdapterListener, MaterialSearchBar.OnSearchActionListener {
+ ProductAdapter adapterProductList = new ProductAdapter();
+ ProductListController controller = new ProductListController();
+ RecyclerView recyclerView;
+ MaterialSearchBar searchBar;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_product_list);
+ recyclerView = findViewById(R.id.rcProducts);
+ recyclerView.setAdapter(adapterProductList);
+ searchBar = findViewById(R.id.search);
+ searchBar.setOnSearchActionListener(this);
+ String keyword = getIntent().getStringExtra("keyword");
+ searchBar.setTextHintColor(ContextCompat.getColor(this, R.color.black));
+ searchBar.setHint(keyword);
+ searchBar.setPlaceHolder(keyword);
+ adapterProductList.setListener(this);
+ controller.setView(this);
+ controller.fetchProductById(keyword);
+ }
+
+ @Override
+ public void onProductClick(Product product) {
+ Intent intent = new Intent(this, ProductDetailsActivity.class);
+ intent.putExtra("product", product);
+ startActivity(intent);
+ }
+
+ @Override
+ public void setData(List products) {
+ //Khi co Adapter roi thi chi can set product nhu nay la no se tu tao cac item tren man hinh dua vao data e dua cho no, that's all
+ adapterProductList.setData(products);
+ }
+
+ @Override
+ public void onSearchStateChanged(boolean enabled) {
+
+ }
+
+ @Override
+ public void onSearchConfirmed(CharSequence text) {
+ searchBar.setPlaceHolder(text.toString().trim());
+ controller.fetchProductById(text.toString().trim());
+ }
+
+ @Override
+ public void onButtonClicked(int buttonCode) {
+
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/productlist/ProductListController.java b/app/src/main/java/com/fpt/vinmartauth/view/productlist/ProductListController.java
new file mode 100644
index 0000000..8e47929
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/productlist/ProductListController.java
@@ -0,0 +1,31 @@
+package com.fpt.vinmartauth.view.productlist;
+
+import com.fpt.vinmartauth.entity.Product;
+import com.fpt.vinmartauth.model.ProductModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProductListController {
+ private ProductListView view;
+ private final ProductModel productModel = new ProductModel();
+
+ void setView(ProductListView view) {
+ this.view = view;
+ }
+
+ void fetchProductById(String title) {
+ productModel.getProductByName(title, new ProductModel.GetProductsByTitleCallbacks() {
+
+ @Override
+ public void onSuccess(List products) {
+ view.setData(products);
+ }
+
+ @Override
+ public void onFailed() {
+ view.setData(new ArrayList<>());
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/productlist/ProductListView.java b/app/src/main/java/com/fpt/vinmartauth/view/productlist/ProductListView.java
new file mode 100644
index 0000000..2125b9a
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/productlist/ProductListView.java
@@ -0,0 +1,9 @@
+package com.fpt.vinmartauth.view.productlist;
+
+import com.fpt.vinmartauth.entity.Product;
+
+import java.util.List;
+
+public interface ProductListView {
+ void setData(List products);
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/productview/ProductFragment.java b/app/src/main/java/com/fpt/vinmartauth/view/productview/ProductFragment.java
new file mode 100644
index 0000000..7a3db26
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/productview/ProductFragment.java
@@ -0,0 +1,118 @@
+package com.fpt.vinmartauth.view.productview;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.fpt.vinmartauth.R;
+import com.fpt.vinmartauth.adapter.CategoryAdapter;
+import com.fpt.vinmartauth.adapter.ProductAdapter;
+import com.fpt.vinmartauth.entity.CategoryIcon;
+import com.fpt.vinmartauth.entity.Product;
+import com.fpt.vinmartauth.view.productDetailView.ProductDetailsActivity;
+import com.fpt.vinmartauth.view.productlist.ProductListActivity;
+import com.mancj.materialsearchbar.MaterialSearchBar;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProductFragment extends Fragment implements ProductView, ProductAdapter.ProductAdapterListener, MaterialSearchBar.OnSearchActionListener {
+ public static ProductFragment newInstance() {
+ return new ProductFragment();
+ }
+
+ ProductAdapter adapterBestSelling = new ProductAdapter();
+ ProductAdapter adapterRecommended = new ProductAdapter();
+ ProductAdapter adapterHighlighted = new ProductAdapter();
+ private ProductViewController controller = new ProductViewController();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ //this is actually the fragments' "onCreate"
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ //must declare to find view by id
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_main, container, false);
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ controller.setView(this);
+ MaterialSearchBar searchBar = view.findViewById(R.id.searchBar);
+ RecyclerView rvRecommended = view.findViewById(R.id.rvRecommended);
+ RecyclerView rvBestSelling = view.findViewById(R.id.rvBestSelling);
+ RecyclerView rvHighlightedProduct = view.findViewById(R.id.rvHighlightedProduct);
+ RecyclerView rvCategory = view.findViewById(R.id.rvCategory);
+ List icons = new ArrayList<>();
+ icons.add(new CategoryIcon(R.drawable.vegetable, "Rau củ", "Cgx001"));
+ icons.add(new CategoryIcon(R.drawable.drinks, "Đồ uống", "Cgx002"));
+ icons.add(new CategoryIcon(R.drawable.milk, "Sữa", "Cgx003"));
+ icons.add(new CategoryIcon(R.drawable.candy, "Bánh kẹo", "Cgx004"));
+ icons.add(new CategoryIcon(R.drawable.noodle, "Mì, phở", "Cgx005"));
+ icons.add(new CategoryIcon(R.drawable.cooking, "Gia vị", "Cgx006"));
+ icons.add(new CategoryIcon(R.drawable.rice, "Gạo, bột", "Cgx007"));
+ icons.add(new CategoryIcon(R.drawable.seafood, "Đồ đông lạnh", "Cgx008"));
+ icons.add(new CategoryIcon(R.drawable.cleaner, "Vệ sinh nhà cửa", "Cgx009"));
+ icons.add(new CategoryIcon(R.drawable.fan, "Đồ dùng gia đình", "Cgx010"));
+ rvCategory.setLayoutManager(new GridLayoutManager(getActivity(), 5));
+ CategoryAdapter categoryAdapter = new CategoryAdapter(icons);
+ rvCategory.setAdapter(categoryAdapter);
+ rvBestSelling.setLayoutManager(new GridLayoutManager(getActivity(), 2));
+ rvBestSelling.setAdapter(adapterBestSelling);
+ rvRecommended.setLayoutManager(new GridLayoutManager(getActivity(), 2));
+ rvRecommended.setAdapter(adapterRecommended);
+ rvHighlightedProduct.setLayoutManager(new GridLayoutManager(getActivity(), 2));
+ rvHighlightedProduct.setAdapter(adapterHighlighted);
+ adapterBestSelling.setListener(this);
+ adapterHighlighted.setListener(this);
+ adapterRecommended.setListener(this);
+ searchBar.setOnSearchActionListener(this);
+ controller.fetchAllProducts();
+ }
+
+ @Override
+ public void setProducts(List products) {
+ adapterRecommended.setData(products);
+ adapterBestSelling.setData(products);
+ adapterHighlighted.setData(products);
+
+ }
+
+ @Override
+ public void onProductClick(Product product) {
+ Intent intent = new Intent(getContext(), ProductDetailsActivity.class);
+ intent.putExtra("product", product);
+ startActivity(intent);
+ }
+
+ @Override
+ public void onSearchStateChanged(boolean enabled) {
+
+ }
+
+ @Override
+ public void onSearchConfirmed(CharSequence text) {
+ Intent intent = new Intent(getContext(), ProductListActivity.class);
+ intent.putExtra("keyword", text.toString().trim());
+ startActivity(intent);
+ }
+
+ @Override
+ public void onButtonClicked(int buttonCode) {
+
+ }
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/productview/ProductView.java b/app/src/main/java/com/fpt/vinmartauth/view/productview/ProductView.java
new file mode 100644
index 0000000..5e02f0c
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/productview/ProductView.java
@@ -0,0 +1,10 @@
+package com.fpt.vinmartauth.view.productview;
+
+import com.fpt.vinmartauth.entity.Product;
+
+import java.util.List;
+
+public interface ProductView {
+ void setProducts(List products);
+
+}
diff --git a/app/src/main/java/com/fpt/vinmartauth/view/productview/ProductViewController.java b/app/src/main/java/com/fpt/vinmartauth/view/productview/ProductViewController.java
new file mode 100644
index 0000000..f96062d
--- /dev/null
+++ b/app/src/main/java/com/fpt/vinmartauth/view/productview/ProductViewController.java
@@ -0,0 +1,29 @@
+package com.fpt.vinmartauth.view.productview;
+
+import com.fpt.vinmartauth.entity.Product;
+import com.fpt.vinmartauth.model.ProductModel;
+
+import java.util.List;
+
+public class ProductViewController {
+ private ProductView view;
+ private final ProductModel productModel = new ProductModel();
+
+ void setView(ProductView view) {
+ this.view = view;
+ }
+
+ void fetchAllProducts() {
+ productModel.getAllProduct(new ProductModel.GetAllProductsCallbacks() {
+ @Override
+ public void onSuccess(List products) {
+ view.setProducts(products);
+ }
+
+ @Override
+ public void onFailed() {
+
+ }
+ });
+ }
+}
diff --git a/app/src/main/res/color/sorter_color.xml b/app/src/main/res/color/sorter_color.xml
new file mode 100644
index 0000000..b38acd2
--- /dev/null
+++ b/app/src/main/res/color/sorter_color.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/avatar.png b/app/src/main/res/drawable/avatar.png
new file mode 100644
index 0000000..23e6ce0
Binary files /dev/null and b/app/src/main/res/drawable/avatar.png differ
diff --git a/app/src/main/res/drawable/bottom_navigation_color_selector.xml b/app/src/main/res/drawable/bottom_navigation_color_selector.xml
new file mode 100644
index 0000000..71cd28a
--- /dev/null
+++ b/app/src/main/res/drawable/bottom_navigation_color_selector.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/candy.png b/app/src/main/res/drawable/candy.png
new file mode 100644
index 0000000..55e34a6
Binary files /dev/null and b/app/src/main/res/drawable/candy.png differ
diff --git a/app/src/main/res/drawable/cleaner.png b/app/src/main/res/drawable/cleaner.png
new file mode 100644
index 0000000..cbe4928
Binary files /dev/null and b/app/src/main/res/drawable/cleaner.png differ
diff --git a/app/src/main/res/drawable/cooking.png b/app/src/main/res/drawable/cooking.png
new file mode 100644
index 0000000..2d789e5
Binary files /dev/null and b/app/src/main/res/drawable/cooking.png differ
diff --git a/app/src/main/res/drawable/drinks.png b/app/src/main/res/drawable/drinks.png
new file mode 100644
index 0000000..3727d16
Binary files /dev/null and b/app/src/main/res/drawable/drinks.png differ
diff --git a/app/src/main/res/drawable/fan.png b/app/src/main/res/drawable/fan.png
new file mode 100644
index 0000000..9d8e8ef
Binary files /dev/null and b/app/src/main/res/drawable/fan.png differ
diff --git a/app/src/main/res/drawable/ic_baseline_account_circle_24.xml b/app/src/main/res/drawable/ic_baseline_account_circle_24.xml
new file mode 100644
index 0000000..89199eb
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_account_circle_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_arrow_forward_ios_24.xml b/app/src/main/res/drawable/ic_baseline_arrow_forward_ios_24.xml
new file mode 100644
index 0000000..d7c08d9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_arrow_forward_ios_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_credit_card_24.xml b/app/src/main/res/drawable/ic_baseline_credit_card_24.xml
new file mode 100644
index 0000000..0e3e0b1
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_credit_card_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_edit_24.xml b/app/src/main/res/drawable/ic_baseline_edit_24.xml
new file mode 100644
index 0000000..de6d842
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_edit_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_exit_to_app_24.xml b/app/src/main/res/drawable/ic_baseline_exit_to_app_24.xml
new file mode 100644
index 0000000..a5f8b54
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_exit_to_app_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_favorite_border_24.xml b/app/src/main/res/drawable/ic_baseline_favorite_border_24.xml
new file mode 100644
index 0000000..ea59b86
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_favorite_border_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_history_24.xml b/app/src/main/res/drawable/ic_baseline_history_24.xml
new file mode 100644
index 0000000..dd66a0d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_history_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_home_24.xml b/app/src/main/res/drawable/ic_baseline_home_24.xml
new file mode 100644
index 0000000..3a4c7da
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_home_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_local_shipping_24.xml b/app/src/main/res/drawable/ic_baseline_local_shipping_24.xml
new file mode 100644
index 0000000..f74470b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_local_shipping_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_location_on_24.xml b/app/src/main/res/drawable/ic_baseline_location_on_24.xml
new file mode 100644
index 0000000..e6b8cf9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_location_on_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_notifications_24.xml b/app/src/main/res/drawable/ic_baseline_notifications_24.xml
new file mode 100644
index 0000000..0c6d647
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_notifications_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_shopping_cart_24.xml b/app/src/main/res/drawable/ic_baseline_shopping_cart_24.xml
new file mode 100644
index 0000000..cf0dcc8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_shopping_cart_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_sign_in.xml b/app/src/main/res/drawable/ic_baseline_sign_in.xml
new file mode 100644
index 0000000..beee9d7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_sign_in.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
similarity index 100%
rename from app/src/main/res/drawable-v24/ic_launcher_foreground.xml
rename to app/src/main/res/drawable/ic_launcher_foreground.xml
diff --git a/app/src/main/res/drawable/milk.png b/app/src/main/res/drawable/milk.png
new file mode 100644
index 0000000..6b667e9
Binary files /dev/null and b/app/src/main/res/drawable/milk.png differ
diff --git a/app/src/main/res/drawable/noodle.png b/app/src/main/res/drawable/noodle.png
new file mode 100644
index 0000000..2579221
Binary files /dev/null and b/app/src/main/res/drawable/noodle.png differ
diff --git a/app/src/main/res/drawable/product_details1.png b/app/src/main/res/drawable/product_details1.png
new file mode 100644
index 0000000..b3e1a68
Binary files /dev/null and b/app/src/main/res/drawable/product_details1.png differ
diff --git a/app/src/main/res/drawable/product_thumbnail.png b/app/src/main/res/drawable/product_thumbnail.png
new file mode 100644
index 0000000..c4f47d0
Binary files /dev/null and b/app/src/main/res/drawable/product_thumbnail.png differ
diff --git a/app/src/main/res/drawable/rice.png b/app/src/main/res/drawable/rice.png
new file mode 100644
index 0000000..432e8eb
Binary files /dev/null and b/app/src/main/res/drawable/rice.png differ
diff --git a/app/src/main/res/drawable/seafood.png b/app/src/main/res/drawable/seafood.png
new file mode 100644
index 0000000..7dd037b
Binary files /dev/null and b/app/src/main/res/drawable/seafood.png differ
diff --git a/app/src/main/res/drawable/vegetable.png b/app/src/main/res/drawable/vegetable.png
new file mode 100644
index 0000000..8042268
Binary files /dev/null and b/app/src/main/res/drawable/vegetable.png differ
diff --git a/app/src/main/res/layout/activity_edit_profile.xml b/app/src/main/res/layout/activity_edit_profile.xml
new file mode 100644
index 0000000..5a9820f
--- /dev/null
+++ b/app/src/main/res/layout/activity_edit_profile.xml
@@ -0,0 +1,230 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
index c837381..9b4710c 100644
--- a/app/src/main/res/layout/activity_login.xml
+++ b/app/src/main/res/layout/activity_login.xml
@@ -2,17 +2,30 @@
+ tools:context=".view.LoginActivity">
+
+
@@ -20,11 +33,12 @@
+ android:background="@color/quite_white">
+ app:layout_constraintTop_toBottomOf="@+id/btnHomeSignIn" />
+ app:layout_constraintTop_toBottomOf="@+id/email"
+ tools:ignore="TextFields" />
-
-
+ app:layout_constraintStart_toStartOf="@+id/editTextTextPassword"
+ app:layout_constraintTop_toBottomOf="@+id/editTextTextPassword" />
-
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintBottom_toBottomOf="parent"
+ android:layout_marginBottom="12dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+
+
+
+
+
+ app:layout_constraintGuide_percent="1.0" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 4bd2c8a..b68b15c 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,28 +1,30 @@
+ android:gravity="start">
+
+
-
+
+
-
-
+ app:layout_constraintTop_toBottomOf="@+id/fragment_container"
+ app:menu="@menu/navigation_menu" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_product_details.xml b/app/src/main/res/layout/activity_product_details.xml
new file mode 100644
index 0000000..dab6ad0
--- /dev/null
+++ b/app/src/main/res/layout/activity_product_details.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_product_list.xml b/app/src/main/res/layout/activity_product_list.xml
new file mode 100644
index 0000000..ed41c58
--- /dev/null
+++ b/app/src/main/res/layout/activity_product_list.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_reset_password.xml b/app/src/main/res/layout/activity_reset_password.xml
new file mode 100644
index 0000000..cc35849
--- /dev/null
+++ b/app/src/main/res/layout/activity_reset_password.xml
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_signup.xml b/app/src/main/res/layout/activity_signup.xml
index 87f0d6d..13fc1f7 100644
--- a/app/src/main/res/layout/activity_signup.xml
+++ b/app/src/main/res/layout/activity_signup.xml
@@ -5,25 +5,24 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/quite_white"
- tools:context=".login.SignupActivity">
+ tools:context=".view.SignupActivity">
+ android:background="@color/quite_white">
+ app:layout_constraintBottom_toTopOf="@+id/etRegEmail"
+ app:layout_constraintStart_toStartOf="@+id/etRegEmail"
+ app:layout_constraintTop_toBottomOf="@+id/etRegName" />
+ app:layout_constraintBottom_toTopOf="@+id/etRegName"
+ app:layout_constraintStart_toStartOf="@+id/etRegName"
+ app:layout_constraintTop_toBottomOf="@+id/verification" />
+ app:layout_constraintBottom_toTopOf="@+id/etRegPassword"
+ app:layout_constraintStart_toStartOf="@+id/etRegPassword"
+ app:layout_constraintTop_toBottomOf="@+id/etRegEmail" />
+ app:layout_constraintTop_toBottomOf="@+id/etRegPassword" />
+ app:layout_constraintGuide_percent="0.8" />
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_bias="0.476" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_verification.xml b/app/src/main/res/layout/activity_verification.xml
new file mode 100644
index 0000000..761dbf9
--- /dev/null
+++ b/app/src/main/res/layout/activity_verification.xml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_view_by_category.xml b/app/src/main/res/layout/activity_view_by_category.xml
new file mode 100644
index 0000000..41a6a74
--- /dev/null
+++ b/app/src/main/res/layout/activity_view_by_category.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_cart.xml b/app/src/main/res/layout/fragment_cart.xml
new file mode 100644
index 0000000..aa11e69
--- /dev/null
+++ b/app/src/main/res/layout/fragment_cart.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml
new file mode 100644
index 0000000..a534671
--- /dev/null
+++ b/app/src/main/res/layout/fragment_main.xml
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml
new file mode 100644
index 0000000..9836d63
--- /dev/null
+++ b/app/src/main/res/layout/fragment_profile.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_category.xml b/app/src/main/res/layout/layout_category.xml
new file mode 100644
index 0000000..8837c6d
--- /dev/null
+++ b/app/src/main/res/layout/layout_category.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_product.xml b/app/src/main/res/layout/layout_product.xml
new file mode 100644
index 0000000..8b462b7
--- /dev/null
+++ b/app/src/main/res/layout/layout_product.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_profile_menu_item.xml b/app/src/main/res/layout/layout_profile_menu_item.xml
new file mode 100644
index 0000000..11be607
--- /dev/null
+++ b/app/src/main/res/layout/layout_profile_menu_item.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_row_cart_item.xml b/app/src/main/res/layout/layout_row_cart_item.xml
new file mode 100644
index 0000000..40308a7
--- /dev/null
+++ b/app/src/main/res/layout/layout_row_cart_item.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/loading_spinner.xml b/app/src/main/res/layout/loading_spinner.xml
new file mode 100644
index 0000000..85c2480
--- /dev/null
+++ b/app/src/main/res/layout/loading_spinner.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/recycler_view_item.xml b/app/src/main/res/layout/recycler_view_item.xml
new file mode 100644
index 0000000..10e149a
--- /dev/null
+++ b/app/src/main/res/layout/recycler_view_item.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/navigation_menu.xml b/app/src/main/res/menu/navigation_menu.xml
new file mode 100644
index 0000000..818d557
--- /dev/null
+++ b/app/src/main/res/menu/navigation_menu.xml
@@ -0,0 +1,16 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
index eca70cf..036d09b 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index eca70cf..036d09b 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
index a571e60..0ce3ed3 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..f348320
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
index 61da551..25dcabf 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
index c41dd28..f06ace2 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..41a2941
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
index db5080a..b3ac8b7 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
index 6dba46d..2ffd67e 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..2ba38bd
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
index da31a87..88bd94e 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
index 15ac681..54d7d83 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..a44aac5
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
index b216f2d..8c084b5 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index f25a419..0f41c7e 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..73ef2d4
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
index e96783c..171afff 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
deleted file mode 100644
index 9f30ebb..0000000
--- a/app/src/main/res/values-night/themes.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 8c98f89..6e75e39 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -12,5 +12,9 @@
#FF000000
#FFFFFFFF
#F5F5F5
+ #e82229
+ #ee1b24
+ #1b77a4
+ #54b8e7
#929292
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..1a7ba4a
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,15 @@
+
+
+
+ 0dp
+
+
+ 5dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..c5d5899
--- /dev/null
+++ b/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #FFFFFF
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2efe883..2226e73 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,16 +1,54 @@
- VinMartAuth
+ VịnMart
Hello blank fragment
- Sign in
- Welcome,
- Sign in to Continue
- Sign Up
+ Đăng nhập
+ Xin chào,
+ Đăng nhập để tiếp tục
+ Đăng ký
Email
- Password
- Forgot Password?
- -OR-
+ Email hoặc số điện thoại
+ Mật khẩu
+ Quên mật khẩu?
+ -HOẶC-
+ Nhập email hoặc số điện thoại
example@abc.com
- Enter Password
- Name
- Back
+ Nhập mật khẩu
+ Tên
+ Quay lại
+ Xác thực
+ Tiếp tục
+ Vui lòng điền mã xác nhận được gửi đến điện thoại của bạn
+ Đặt lại mật khẩu
+ Điền mật khẩu để tiếp tục
+ Mật khẩu mới
+ Xác nhận mật khẩu
+ Mật khẩu mới
+ Trang chủ
+ Giỏ hàng
+ Hồ sơ
+ Item Icon
+ Item Name
+ Arrow forward
+ Chỉnh sửa hồ sơ
+ Địa chỉ giao hàng
+ Sản phẩm yêu thích
+ Lịch sử đơn hàng
+ Theo dõi đơn hàng
+ Thẻ Ngân hàng
+ Thông báo
+ Đăng xuất
+ Chưa có tài khoản?
+ Đang tải
+ CartActivity
+
+ Hello Square World!
+ Tổng tiền:
+ Giỏ hàng
+ Thanh toán
+ 0 đ
+ Rau cai ngong tui 300g
+ Gia: 12000đ
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 817eaa3..e756ed8 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -1,30 +1,80 @@
-
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/com/fpt/vinmartauth/ExampleUnitTest.java b/app/src/test/java/com/fpt/vinmartauth/ExampleUnitTest.java
index 032f6d9..f73f73d 100644
--- a/app/src/test/java/com/fpt/vinmartauth/ExampleUnitTest.java
+++ b/app/src/test/java/com/fpt/vinmartauth/ExampleUnitTest.java
@@ -1,8 +1,9 @@
package com.fpt.vinmartauth;
+
+
import org.junit.Test;
-import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
@@ -11,7 +12,6 @@
*/
public class ExampleUnitTest {
@Test
- public void addition_isCorrect() {
- assertEquals(4, 2 + 2);
+ public void get_firebase_data_test() {
}
}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 671947b..9592a48 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,12 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
+ ext.kotlin_version= '1.4.31'
repositories {
google()
jcenter()
}
dependencies {
- classpath "com.android.tools.build:gradle:4.1.2"
+ classpath "com.android.tools.build:gradle:4.1.3"
classpath 'com.google.gms:google-services:4.3.5'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
@@ -16,6 +18,7 @@ allprojects {
repositories {
google()
jcenter()
+ maven { url "https://jitpack.io" }
}
}
diff --git a/gradle.properties b/gradle.properties
index 52f5917..fb97836 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,19 +1,16 @@
-# Project-wide Gradle settings.
-# IDE (e.g. Android Studio) users:
-# Gradle settings configured through the IDE *will override*
-# any settings specified in this file.
-# For more details on how to configure your build environment visit
+## For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
+#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# Default value: -Xmx1024m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
-# AndroidX package structure to make it clearer which packages are bundled with the
-# Android operating system, and which are packaged with your app"s APK
-# https://developer.android.com/topic/libraries/support-library/androidx-rn
+#Sat Mar 27 09:47:49 ICT 2021
+android.enableJetifier=true
android.useAndroidX=true
-# Automatically convert third-party libraries to use AndroidX
-android.enableJetifier=true
\ No newline at end of file
+org.gradle.jvmargs=-Xmx1536M -Dkotlin.daemon.jvm.options\="-Xmx1536M" -Dfile.encoding\=UTF-8