Added product reviews section

This commit is contained in:
Gilbert Kimutai 2019-03-20 06:34:08 +03:00
parent 82c76bb970
commit 37e71535b7
15 changed files with 402 additions and 21 deletions

View File

@ -12,6 +12,7 @@ android {
targetSdkVersion 28
versionCode 1
versionName "1.0"
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
@ -87,5 +88,7 @@ dependencies {
implementation 'me.relex:circleindicator:1.2.2@aar'
implementation 'net.danlew:android.joda:2.9.9.4'
}

View File

@ -4,6 +4,7 @@ import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import me.gilo.wc.ui.home.HomeActivity
import me.gilo.wc.ui.product.ProductActivity
class MainActivity : AppCompatActivity() {
@ -15,10 +16,10 @@ class MainActivity : AppCompatActivity() {
startActivity(Intent(baseContext, HomeActivity::class.java))
// val intent = Intent(baseContext, ProductActivity::class.java)
// intent.putExtra("productId", 63)
//
// startActivity(intent)
val intent = Intent(baseContext, ProductActivity::class.java)
intent.putExtra("productId", 63)
startActivity(intent)
finish()

View File

@ -0,0 +1,36 @@
package me.gilo.wc.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import me.gilo.wc.R;
import me.gilo.wc.adapter.viewholder.ProductReviewViewHolder;
import me.gilo.wc.adapter.viewholder.ProductViewHolder;
import me.gilo.woodroid.models.Product;
import me.gilo.woodroid.models.ProductReview;
import java.util.List;
public class ProductReviewAdapter extends RecyclerView.Adapter<ProductReviewViewHolder> {
private List<ProductReview> reviews;
public ProductReviewAdapter(List<ProductReview> reviews) {
this.reviews = reviews;
}
@Override
public ProductReviewViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ProductReviewViewHolder(parent.getContext(), LayoutInflater.from(parent.getContext()).inflate(R.layout.single_product_review, parent, false));
}
@Override
public void onBindViewHolder(ProductReviewViewHolder holder, int position) {
holder.renderView(reviews.get(position));
}
@Override
public int getItemCount() {
return reviews.size() == 0 ? 0 : reviews.size();
}
}

View File

@ -0,0 +1,34 @@
package me.gilo.wc.adapter.viewholder
import android.content.Context
import android.content.Intent
import android.support.v7.widget.RecyclerView
import android.text.Html
import android.view.View
import android.widget.RatingBar
import android.widget.TextView
import me.gilo.wc.R
import me.gilo.wc.ui.product.ShopActivity
import me.gilo.wc.utils.DateUtils
import me.gilo.woodroid.models.Category
import me.gilo.woodroid.models.ProductReview
class ProductReviewViewHolder(val context: Context, itemView: View) :
RecyclerView.ViewHolder(itemView) {
fun renderView(review: ProductReview) {
val tvName = itemView.findViewById<TextView>(R.id.tvName)
val tvDate = itemView.findViewById<TextView>(R.id.tvDate)
val rbRating = itemView.findViewById<RatingBar>(R.id.rbRating)
val tvMessage = itemView.findViewById<TextView>(R.id.tvMessage)
tvName.text = review.reviewer
tvMessage.text = Html.fromHtml(review.review)
rbRating.rating = review.rating.toFloat()
tvDate.text = DateUtils.getDateString_shortAndSmart(review.date_created)
}
}

View File

@ -4,7 +4,9 @@ package me.gilo.wc.repo;
import me.gilo.wc.common.WooLiveData;
import me.gilo.woodroid.Woocommerce;
import me.gilo.woodroid.models.Product;
import me.gilo.woodroid.models.ProductReview;
import me.gilo.woodroid.models.filters.ProductFilter;
import me.gilo.woodroid.models.filters.ProductReviewFilter;
import javax.inject.Inject;
import java.util.List;
@ -41,6 +43,19 @@ public class ProductRepository {
}
public WooLiveData<List<ProductReview>> reviews(int productId) {
final WooLiveData<List<ProductReview>> callBack = new WooLiveData();
ProductReviewFilter filter = new ProductReviewFilter();
int[] products = {productId};
filter.setProduct(products);
woocommerce.ReviewRepository().reviews(filter).enqueue(callBack);
return callBack;
}
public WooLiveData<List<Product>> search(String term) {
final WooLiveData<List<Product>> callBack = new WooLiveData();

View File

@ -10,11 +10,13 @@ import kotlinx.android.synthetic.main.content_product.*
import me.gilo.wc.R
import me.gilo.wc.adapter.HomeProductAdapter
import me.gilo.wc.adapter.ImagePagerAdapter
import me.gilo.wc.adapter.ProductReviewAdapter
import me.gilo.wc.common.BaseActivity
import me.gilo.wc.common.Status
import me.gilo.wc.ui.state.ProgressDialogFragment
import me.gilo.wc.viewmodels.ProductViewModel
import me.gilo.woodroid.models.Product
import me.gilo.woodroid.models.ProductReview
import me.gilo.woodroid.models.filters.ProductFilter
import java.util.ArrayList
@ -38,6 +40,7 @@ class ProductActivity : BaseActivity() {
if (productId != 0){
product(productId)
reviews(productId)
}
@ -63,10 +66,6 @@ class ProductActivity : BaseActivity() {
val filter = ProductFilter()
filter.include = product.related_ids.toIntArray()
for (id in product.related_ids){
Log.d("Related ids", "" + id)
}
viewModel.products(filter).observe(this, android.arch.lifecycle.Observer { response ->
when (response!!.status()) {
Status.LOADING -> {
@ -149,6 +148,50 @@ class ProductActivity : BaseActivity() {
}
private fun reviews(productId : Int) {
val layoutManager = LinearLayoutManager(baseContext, LinearLayoutManager.VERTICAL, false)
rvReviews.layoutManager = layoutManager
rvReviews.isNestedScrollingEnabled = false
var reviews = ArrayList<ProductReview>()
var productReviewAdapter = ProductReviewAdapter(reviews)
rvReviews.adapter = productReviewAdapter
viewModel.reviews(productId).observe(this, android.arch.lifecycle.Observer { response ->
when (response!!.status()) {
Status.LOADING -> {
}
Status.SUCCESS -> {
reviews.clear()
val reviewsResponse = response.data()
for (review in reviewsResponse) {
reviews.add(review)
}
productReviewAdapter.notifyDataSetChanged()
}
Status.ERROR -> {
Log.d("Error", response.error().message)
}
Status.EMPTY -> {
}
}
})
}
private fun setUpPage(product: Product) {
tvTitle.text = product.name
tvDescription.text = Html.fromHtml(product.description)

View File

@ -0,0 +1,87 @@
package me.gilo.wc.utils;
import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.Days;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtils {
static SimpleDateFormat dateFormat = new SimpleDateFormat("EEE hh:mma MMM d, yyyy");
static SimpleDateFormat longagoDateFormat = new SimpleDateFormat("dd/MM/yyyy");
static SimpleDateFormat weekdayFormat = new SimpleDateFormat("EEE");
static SimpleDateFormat hourMinuteFormat = new SimpleDateFormat("hh:mm a");
private static boolean isToday (DateTime dateTime) {
DateMidnight today = new DateMidnight();
return today.equals(dateTime.toDateMidnight());
}
private static boolean isYesterday (DateTime dateTime) {
DateMidnight yesterday = (new DateMidnight()).minusDays(1);
return yesterday.equals(dateTime.toDateMidnight());
}
private static String getDayString(Date date) {
String s;
if (isToday(new DateTime(date)))
s = "Today";
else if (isYesterday(new DateTime(date)))
s = "Yesterday";
else
s = weekdayFormat.format(date);
return s;
}
public static String getDateString_shortAndSmart(Date date) {
String s;
DateTime nowDT = new DateTime();
DateTime dateDT = new DateTime(date);
int days = Days.daysBetween(dateDT, nowDT).getDays();
if (isToday(new DateTime(date)))
s = getHourMinuteString(date);
else if (days < 7)
s = getDayString(date);
else
s = getDateString(date);
return s;
}
public static String getDateStatus(Date date) {
String s;
if (date == null)
return "Null";
DateTime nowDT = new DateTime();
DateTime dateDT = new DateTime(date);
int days = Days.daysBetween(dateDT, nowDT).getDays();
if (isToday(new DateTime(date)))
s = getHourMinuteString(date);
else if (days < 7)
s = getDayString(date) + "at " + getHourMinuteString(date);
else
s = getDateString(date);
return "Last online " + s;
}
private static String getDateString(Date date) {
return longagoDateFormat.format(date);
}
private static String getHourMinuteString(Date date) {
String s = hourMinuteFormat.format(date);
return s;
}
}

View File

@ -8,6 +8,7 @@ import me.gilo.wc.repo.OrderRepository;
import me.gilo.wc.repo.ProductRepository;
import me.gilo.woodroid.models.LineItem;
import me.gilo.woodroid.models.Product;
import me.gilo.woodroid.models.ProductReview;
import me.gilo.woodroid.models.filters.ProductFilter;
import javax.inject.Inject;
@ -50,6 +51,11 @@ public final class ProductViewModel extends ViewModel {
return productRepository.product(productId);
}
public WooLiveData<List<ProductReview>> reviews(int productId) {
return productRepository.reviews(productId);
}
public WooLiveData<List<Product>> search(String term) {
return productRepository.search(term);
}

View File

@ -21,6 +21,7 @@
android:layout_width="match_parent"
android:layout_height="320dp"
android:layout_marginBottom="16dp"
android:layout_marginTop="16dp"
>
@ -109,7 +110,7 @@
<TextView
fontPath="@string/font_medium"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_height="wrap_content"
android:gravity="left"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
@ -122,7 +123,27 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/rvShop"
></android.support.v7.widget.RecyclerView>
<TextView
fontPath="@string/font_medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginRight="16dp"
android:text="Reviews"
android:textColor="@color/text_black_2"
android:textSize="20sp"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/rvReviews"
android:background="@drawable/rect_white"
android:layout_margin="16dp"
></android.support.v7.widget.RecyclerView>
</LinearLayout>

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:background="#ffffff"
tools:ignore="MissingPrefix">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#ffffff"
tools:ignore="MissingPrefix">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="1"
android:layout_marginRight="8dp"
>
<TextView
android:id="@+id/tvName"
fontPath="@string/font_medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:maxLines="1"
android:text="Gilbert Kimutai"
android:textColor="@color/text_black_4"
android:textSize="16sp"/>
<android.support.v7.widget.AppCompatRatingBar
android:id="@+id/rbRating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="5"
android:rating="4"
android:layout_marginTop="4dp"
style="?android:attr/ratingBarStyleSmall"
/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="right"
>
<TextView
android:id="@+id/tvDate"
fontPath="@string/font_regular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:text="Jan 7, 2018"
android:maxLines="2"
android:lineSpacingMultiplier="1.2"
android:textColor="@color/text_black_5"
android:textSize="14sp"/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tvMessage"
fontPath="@string/font_regular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:text="@string/lorem"
android:maxLines="4"
android:layout_marginTop="8dp"
android:lineSpacingMultiplier="1.2"
android:textColor="@color/text_black_5"
android:textSize="16sp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="16dp"
android:background="@color/bg"
/>
</LinearLayout>

View File

@ -27,6 +27,8 @@ public class Woocommerce {
final OrderRepository orderRepository;
final ProductRepository productRepository;
final ReviewRepository reviewRepository;
final ReportsRepository reportsRepository;
final CartRepository cartRepository;
@ -75,6 +77,8 @@ public class Woocommerce {
cartRepository = new CartRepository(cartBaseUrl, consumerKey, consumerSecret);
reviewRepository = new ReviewRepository(baseUrl, consumerKey, consumerSecret);
}
@ -162,6 +166,10 @@ public class Woocommerce {
return productRepository;
}
public ReviewRepository ReviewRepository() {
return reviewRepository;
}
public ReportsRepository ReportsRepository() {
return reportsRepository;
}

View File

@ -3,6 +3,7 @@ package me.gilo.woodroid.data.api;
import me.gilo.woodroid.data.callbacks.ReviewsData;
import me.gilo.woodroid.models.Coupon;
import me.gilo.woodroid.models.Product;
import me.gilo.woodroid.models.ProductReview;
import retrofit2.Call;
import retrofit2.http.*;

View File

@ -2,16 +2,21 @@ package me.gilo.woodroid.models;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
public class ProductReview implements Serializable{
private int id;
private Date date_created;
private Date date_created_gmt;
int product_id;
String reviewer;
String reviewer_email;
Map<String, String> reviewer_avatar_urls;
private String review;
private int rating;
private String name;
private String email;
private boolean verified;
public int getId() {
@ -54,20 +59,36 @@ public class ProductReview implements Serializable{
this.rating = rating;
}
public String getName() {
return name;
public int getProduct_id() {
return product_id;
}
public void setName(String name) {
this.name = name;
public void setProduct_id(int product_id) {
this.product_id = product_id;
}
public String getEmail() {
return email;
public String getReviewer() {
return reviewer;
}
public void setEmail(String email) {
this.email = email;
public void setReviewer(String reviewer) {
this.reviewer = reviewer;
}
public String getReviewer_email() {
return reviewer_email;
}
public void setReviewer_email(String reviewer_email) {
this.reviewer_email = reviewer_email;
}
public Map<String, String> getReviewer_avatar_urls() {
return reviewer_avatar_urls;
}
public void setReviewer_avatar_urls(Map<String, String> reviewer_avatar_urls) {
this.reviewer_avatar_urls = reviewer_avatar_urls;
}
public boolean isVerified() {

View File

@ -1,6 +1,5 @@
package me.gilo.woodroid.models.filters;
import android.util.Log;
import me.gilo.woodroid.utils.Converter;
import java.util.*;

View File

@ -1,5 +1,7 @@
package me.gilo.woodroid.repo;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import me.gilo.woodroid.data.auth.AuthIntercepter;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
@ -17,6 +19,11 @@ public class WooRepository {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.create();
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new AuthIntercepter(consumerKey, consumerSecret))
.addInterceptor(loggingInterceptor)
@ -27,7 +34,7 @@ public class WooRepository {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
}