diff --git a/app/build.gradle b/app/build.gradle index 1d529f8..c364b78 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,7 +13,7 @@ android { defaultConfig { applicationId "com.capstone.foodify" - minSdk 24 + minSdk 26 targetSdk 33 versionCode 1 versionName "1.0" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f5b9782..51b2a20 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,9 @@ android:theme="@style/Theme.Foodify" tools:replace="android:theme" tools:targetApi="31"> + diff --git a/app/src/main/java/com/capstone/foodify/Activity/OrderActivity.java b/app/src/main/java/com/capstone/foodify/Activity/OrderActivity.java index 6f397b9..3f9fe38 100644 --- a/app/src/main/java/com/capstone/foodify/Activity/OrderActivity.java +++ b/app/src/main/java/com/capstone/foodify/Activity/OrderActivity.java @@ -4,6 +4,8 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.viewpager2.widget.ViewPager2; import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; import com.capstone.foodify.Fragment.Order.ViewPagerAdapter; import com.capstone.foodify.R; @@ -14,14 +16,18 @@ public class OrderActivity extends AppCompatActivity { TabLayout tabLayout; ViewPager2 viewPager2; ViewPagerAdapter viewPagerAdapter; + ImageView back_image; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_order); + //Init Component tabLayout = findViewById(R.id.tab_layout); viewPager2 = findViewById(R.id.view_pager); + back_image = findViewById(R.id.back_image); + viewPagerAdapter = new ViewPagerAdapter(this); viewPager2.setAdapter(viewPagerAdapter); @@ -49,5 +55,12 @@ public class OrderActivity extends AppCompatActivity { tabLayout.getTabAt(position).select(); } }); + + back_image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onBackPressed(); + } + }); } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/foodify/Activity/OrderDetailActivity.java b/app/src/main/java/com/capstone/foodify/Activity/OrderDetailActivity.java new file mode 100644 index 0000000..5be4239 --- /dev/null +++ b/app/src/main/java/com/capstone/foodify/Activity/OrderDetailActivity.java @@ -0,0 +1,74 @@ +package com.capstone.foodify.Activity; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.capstone.foodify.Model.Order.OrderDetail; +import com.capstone.foodify.Model.Order.OrderDetailAdapter; +import com.capstone.foodify.R; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +public class OrderDetailActivity extends AppCompatActivity { + + private TextView order_tracking_number, user_name, phone, address, orderTime, total; + private ImageView back_image; + public List listOrderDetails = new ArrayList<>(); + OrderDetailAdapter adapter; + RecyclerView recyclerView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_order_detail); + + //Init Component + order_tracking_number = findViewById(R.id.order_tracking_number); + user_name = findViewById(R.id.user_name); + phone = findViewById(R.id.phone); + address = findViewById(R.id.address); + orderTime = findViewById(R.id.order_time); + total = findViewById(R.id.total); + adapter = new OrderDetailAdapter(); + recyclerView = findViewById(R.id.recycler_view_order_detail); + back_image = findViewById(R.id.back_image); + + //Init temp data + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm:ss dd/MM/yyyy"); + LocalDateTime now = LocalDateTime.now(); + + int b = (int)(Math.random()*(999999-100000+1)+100000); + order_tracking_number.setText("Order Id: #" + b); + user_name.setText("Tên: Nguyễn Văn A"); + phone.setText("0987654321"); + address.setText("Phạm Như Xương, Hoà Khánh Nam, Liên Chiểu"); + orderTime.setText(dtf.format(now)); + total.setText("Tổng: 1.200.000đ"); + + for(int i = 0; i < 5; i++){ + listOrderDetails.add(new OrderDetail()); + } + + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false); + recyclerView.setLayoutManager(linearLayoutManager); + + adapter.setData(listOrderDetails); + recyclerView.setAdapter(adapter); + + back_image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onBackPressed(); + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/foodify/Fragment/Order/CompleteOrderFragment.java b/app/src/main/java/com/capstone/foodify/Fragment/Order/CompleteOrderFragment.java index 340296c..4d55d01 100644 --- a/app/src/main/java/com/capstone/foodify/Fragment/Order/CompleteOrderFragment.java +++ b/app/src/main/java/com/capstone/foodify/Fragment/Order/CompleteOrderFragment.java @@ -3,19 +3,48 @@ package com.capstone.foodify.Fragment.Order; import android.os.Bundle; import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.capstone.foodify.Model.Order.Order; +import com.capstone.foodify.Model.Order.OrderAdapter; import com.capstone.foodify.R; +import java.util.ArrayList; +import java.util.List; + public class CompleteOrderFragment extends Fragment { + private List listOrders = new ArrayList<>(); + RecyclerView recyclerView; + OrderAdapter orderAdapter; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_complete_order, container, false); + View view = inflater.inflate(R.layout.fragment_complete_order, container, false); + + //Init Component + recyclerView = view.findViewById(R.id.recycler_view_process_order); + + orderAdapter = new OrderAdapter(); + + for(int i = 0; i < 5; i++){ + int b = (int)(Math.random()*(999999-100000+1)+100000); + listOrders.add(new Order(String.valueOf(b))); + } + + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false); + recyclerView.setLayoutManager(linearLayoutManager); + + orderAdapter.setData(listOrders); + recyclerView.setAdapter(orderAdapter); + return view; } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/foodify/Fragment/Order/PreparingFragment.java b/app/src/main/java/com/capstone/foodify/Fragment/Order/PreparingFragment.java new file mode 100644 index 0000000..05188eb --- /dev/null +++ b/app/src/main/java/com/capstone/foodify/Fragment/Order/PreparingFragment.java @@ -0,0 +1,50 @@ +package com.capstone.foodify.Fragment.Order; + +import android.os.Bundle; + +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.capstone.foodify.Model.Order.Order; +import com.capstone.foodify.Model.Order.OrderAdapter; +import com.capstone.foodify.R; + +import java.util.ArrayList; +import java.util.List; + +public class PreparingFragment extends Fragment { + + private List listOrders = new ArrayList<>(); + RecyclerView recyclerView; + OrderAdapter orderAdapter; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(R.layout.fragment_preparing, container, false); + + //Init Component + recyclerView = view.findViewById(R.id.recycler_view_process_order); + + orderAdapter = new OrderAdapter(); + + for(int i = 0; i < 5; i++){ + int b = (int)(Math.random()*(999999-100000+1)+100000); + listOrders.add(new Order(String.valueOf(b))); + } + + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false); + recyclerView.setLayoutManager(linearLayoutManager); + + orderAdapter.setData(listOrders); + recyclerView.setAdapter(orderAdapter); + return view; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/foodify/Fragment/Order/ProcessOderFragment.java b/app/src/main/java/com/capstone/foodify/Fragment/Order/ProcessOderFragment.java new file mode 100644 index 0000000..b696e3d --- /dev/null +++ b/app/src/main/java/com/capstone/foodify/Fragment/Order/ProcessOderFragment.java @@ -0,0 +1,51 @@ +package com.capstone.foodify.Fragment.Order; + +import android.os.Bundle; + +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.capstone.foodify.Model.Order.Order; +import com.capstone.foodify.Model.Order.OrderAdapter; +import com.capstone.foodify.R; + +import java.util.ArrayList; +import java.util.List; + +public class ProcessOderFragment extends Fragment { + + private List listOrders = new ArrayList<>(); + RecyclerView recyclerView; + OrderAdapter orderAdapter; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(R.layout.fragment_process_order, container, false); + + //Init Component + recyclerView = view.findViewById(R.id.recycler_view_process_order); + + orderAdapter = new OrderAdapter(); + + for(int i = 0; i < 5; i++){ + int b = (int)(Math.random()*(999999-100000+1)+100000); + listOrders.add(new Order(String.valueOf(b))); + } + + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false); + recyclerView.setLayoutManager(linearLayoutManager); + + orderAdapter.setData(listOrders); + recyclerView.setAdapter(orderAdapter); + + return view; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/foodify/Fragment/Order/ProgressOderFragment.java b/app/src/main/java/com/capstone/foodify/Fragment/Order/ProgressOderFragment.java deleted file mode 100644 index 558eedb..0000000 --- a/app/src/main/java/com/capstone/foodify/Fragment/Order/ProgressOderFragment.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.capstone.foodify.Fragment.Order; - -import android.os.Bundle; - -import androidx.fragment.app.Fragment; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.capstone.foodify.R; - -public class ProgressOderFragment extends Fragment { - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_progress_order, container, false); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/capstone/foodify/Fragment/Order/ShipOrderFragment.java b/app/src/main/java/com/capstone/foodify/Fragment/Order/ShipOrderFragment.java index 34f4bfd..cc784ab 100644 --- a/app/src/main/java/com/capstone/foodify/Fragment/Order/ShipOrderFragment.java +++ b/app/src/main/java/com/capstone/foodify/Fragment/Order/ShipOrderFragment.java @@ -3,19 +3,48 @@ package com.capstone.foodify.Fragment.Order; import android.os.Bundle; import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.capstone.foodify.Model.Order.Order; +import com.capstone.foodify.Model.Order.OrderAdapter; import com.capstone.foodify.R; +import java.util.ArrayList; +import java.util.List; + public class ShipOrderFragment extends Fragment { + private List listOrders = new ArrayList<>(); + RecyclerView recyclerView; + OrderAdapter orderAdapter; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_ship_order, container, false); + View view = inflater.inflate(R.layout.fragment_ship_order, container, false); + + //Init Component + recyclerView = view.findViewById(R.id.recycler_view_process_order); + + orderAdapter = new OrderAdapter(); + + for(int i = 0; i < 5; i++){ + int b = (int)(Math.random()*(999999-100000+1)+100000); + listOrders.add(new Order(String.valueOf(b))); + } + + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false); + recyclerView.setLayoutManager(linearLayoutManager); + + orderAdapter.setData(listOrders); + recyclerView.setAdapter(orderAdapter); + return view; } } \ No newline at end of file diff --git a/app/src/main/java/com/capstone/foodify/Fragment/Order/ViewPagerAdapter.java b/app/src/main/java/com/capstone/foodify/Fragment/Order/ViewPagerAdapter.java index f382f48..b77522c 100644 --- a/app/src/main/java/com/capstone/foodify/Fragment/Order/ViewPagerAdapter.java +++ b/app/src/main/java/com/capstone/foodify/Fragment/Order/ViewPagerAdapter.java @@ -16,16 +16,18 @@ public class ViewPagerAdapter extends FragmentStateAdapter { public Fragment createFragment(int position) { switch(position){ case 1: - return new ShipOrderFragment(); + return new PreparingFragment(); case 2: + return new ShipOrderFragment(); + case 3: return new CompleteOrderFragment(); default: - return new ProgressOderFragment(); + return new ProcessOderFragment(); } } @Override public int getItemCount() { - return 3; + return 4; } } diff --git a/app/src/main/java/com/capstone/foodify/Model/Order/Order.java b/app/src/main/java/com/capstone/foodify/Model/Order/Order.java new file mode 100644 index 0000000..5ee5428 --- /dev/null +++ b/app/src/main/java/com/capstone/foodify/Model/Order/Order.java @@ -0,0 +1,110 @@ +package com.capstone.foodify.Model.Order; + +import java.util.Date; +import java.util.List; + +public class Order { + private int id; + private String orderTrackingNumber; + private int userId; + private int shipperId; + private String paymentMethod; + private float productCost; + private float shippingCost; + private float total; + private String status; + private int address_id; + private List listOrderDetail; + + public Order(String orderTrackingNumber) { + this.orderTrackingNumber = orderTrackingNumber; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getOrderTrackingNumber() { + return orderTrackingNumber; + } + + public void setOrderTrackingNumber(String orderTrackingNumber) { + this.orderTrackingNumber = orderTrackingNumber; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public int getShipperId() { + return shipperId; + } + + public void setShipperId(int shipperId) { + this.shipperId = shipperId; + } + + public String getPaymentMethod() { + return paymentMethod; + } + + public void setPaymentMethod(String paymentMethod) { + this.paymentMethod = paymentMethod; + } + + public float getProductCost() { + return productCost; + } + + public void setProductCost(float productCost) { + this.productCost = productCost; + } + + public float getShippingCost() { + return shippingCost; + } + + public void setShippingCost(float shippingCost) { + this.shippingCost = shippingCost; + } + + public float getTotal() { + return total; + } + + public void setTotal(float total) { + this.total = total; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public int getAddress_id() { + return address_id; + } + + public void setAddress_id(int address_id) { + this.address_id = address_id; + } + + public List getListOrderDetail() { + return listOrderDetail; + } + + public void setListOrderDetail(List listOrderDetail) { + this.listOrderDetail = listOrderDetail; + } +} diff --git a/app/src/main/java/com/capstone/foodify/Model/Order/OrderAdapter.java b/app/src/main/java/com/capstone/foodify/Model/Order/OrderAdapter.java new file mode 100644 index 0000000..ca2448e --- /dev/null +++ b/app/src/main/java/com/capstone/foodify/Model/Order/OrderAdapter.java @@ -0,0 +1,87 @@ +package com.capstone.foodify.Model.Order; + +import android.content.Context; +import android.content.Intent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.capstone.foodify.Activity.OrderDetailActivity; +import com.capstone.foodify.R; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; + +public class OrderAdapter extends RecyclerView.Adapter{ + + public List listOrders; + + public OrderAdapter() { + } + + public void setData(List listOrders){ + this.listOrders = listOrders; + } + + @NonNull + @Override + public OrderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_order, parent, false); + return new OrderViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull OrderViewHolder holder, int position) { + Order order = listOrders.get(position); + + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm:ss dd/MM/yyyy"); + LocalDateTime now = LocalDateTime.now(); + + if(order == null) + return; + + holder.order_tracking_number.setText("Order Id: #" + order.getOrderTrackingNumber()); + holder.user_name.setText("Tên: Nguyễn Văn A"); + holder.phone.setText("0987654321"); + holder.address.setText("Phạm Như Xương, Hoà Khánh Nam, Liên Chiểu"); + holder.orderTime.setText(dtf.format(now)); + holder.total.setText("Tổng: 1.200.000đ"); + } + + @Override + public int getItemCount() { + if(listOrders != null) + return listOrders.size(); + return 0; + } + + public class OrderViewHolder extends RecyclerView.ViewHolder{ + + TextView order_tracking_number, user_name, phone, address, orderTime, total; + Context context; + + public OrderViewHolder(@NonNull View itemView) { + super(itemView); + context = itemView.getContext(); + + order_tracking_number = itemView.findViewById(R.id.order_tracking_number); + user_name = itemView.findViewById(R.id.user_name); + phone = itemView.findViewById(R.id.phone); + address = itemView.findViewById(R.id.address); + orderTime = itemView.findViewById(R.id.order_time); + total = itemView.findViewById(R.id.total); + + itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + context.startActivity(new Intent(context, OrderDetailActivity.class)); + } + }); + } + } +} diff --git a/app/src/main/java/com/capstone/foodify/Model/Order/OrderDetail.java b/app/src/main/java/com/capstone/foodify/Model/Order/OrderDetail.java new file mode 100644 index 0000000..199fcd4 --- /dev/null +++ b/app/src/main/java/com/capstone/foodify/Model/Order/OrderDetail.java @@ -0,0 +1,49 @@ +package com.capstone.foodify.Model.Order; + +public class OrderDetail { + private int id; + private int orderId; + private int productId; + private String quantity; + private float subTotal; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getOrderId() { + return orderId; + } + + public void setOrderId(int orderId) { + this.orderId = orderId; + } + + public int getProductId() { + return productId; + } + + public void setProductId(int productId) { + this.productId = productId; + } + + public String getQuantity() { + return quantity; + } + + public void setQuantity(String quantity) { + this.quantity = quantity; + } + + public float getSubTotal() { + return subTotal; + } + + public void setSubTotal(float subTotal) { + this.subTotal = subTotal; + } +} diff --git a/app/src/main/java/com/capstone/foodify/Model/Order/OrderDetailAdapter.java b/app/src/main/java/com/capstone/foodify/Model/Order/OrderDetailAdapter.java new file mode 100644 index 0000000..d65132a --- /dev/null +++ b/app/src/main/java/com/capstone/foodify/Model/Order/OrderDetailAdapter.java @@ -0,0 +1,71 @@ +package com.capstone.foodify.Model.Order; + +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.capstone.foodify.R; +import com.squareup.picasso.Picasso; + +import java.util.List; + +public class OrderDetailAdapter extends RecyclerView.Adapter{ + + public List listOrderDetails; + + public OrderDetailAdapter(){} + + public void setData(List listOrderDetails){ + this.listOrderDetails = listOrderDetails; + } + + + @NonNull + @Override + public OrderDetailViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_order_detail, parent, false); + return new OrderDetailViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull OrderDetailViewHolder holder, int position) { + OrderDetail orderDetail = listOrderDetails.get(position); + + if(orderDetail == null) + return; + + Picasso.get().load("https://images.unsplash.com/photo-1546069901-ba9599a7e63c?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MXx8fGVufDB8fHx8&w=1000&q=80").into(holder.image_view); + holder.food_name.setText("Food Name"); + holder.shop_name.setText("Shop Name"); + holder.price.setText("120000 đ"); + holder.quantity.setText("Số lượng: 2"); + } + + @Override + public int getItemCount() { + if(listOrderDetails != null) + return listOrderDetails.size(); + return 0; + } + + public class OrderDetailViewHolder extends RecyclerView.ViewHolder{ + ImageView image_view; + TextView food_name, shop_name, price, quantity; + + public OrderDetailViewHolder(@NonNull View itemView) { + super(itemView); + + //Init Component + image_view = itemView.findViewById(R.id.image_view); + food_name = itemView.findViewById(R.id.food_name_text_view); + shop_name = itemView.findViewById(R.id.shop_name_text_view); + price = itemView.findViewById(R.id.price_text_view); + quantity = itemView.findViewById(R.id.quantity_text_view); + } + } +} diff --git a/app/src/main/res/layout/activity_order.xml b/app/src/main/res/layout/activity_order.xml index 9ef5650..351dc97 100644 --- a/app/src/main/res/layout/activity_order.xml +++ b/app/src/main/res/layout/activity_order.xml @@ -6,16 +6,52 @@ android:layout_height="match_parent" tools:context=".Activity.OrderActivity"> + + + + + + + + @@ -25,7 +61,7 @@ android:layout_height="wrap_content" /> diff --git a/app/src/main/res/layout/activity_order_detail.xml b/app/src/main/res/layout/activity_order_detail.xml new file mode 100644 index 0000000..8d7cea2 --- /dev/null +++ b/app/src/main/res/layout/activity_order_detail.xml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +