...
This commit is contained in:
@@ -0,0 +1,134 @@
|
|||||||
|
package com.example.pap_teste;
|
||||||
|
|
||||||
|
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.example.pap_teste.models.Restaurant;
|
||||||
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
import com.google.firebase.auth.FirebaseUser;
|
||||||
|
import com.google.firebase.database.DataSnapshot;
|
||||||
|
import com.google.firebase.database.DatabaseError;
|
||||||
|
import com.google.firebase.database.DatabaseReference;
|
||||||
|
import com.google.firebase.database.FirebaseDatabase;
|
||||||
|
import com.google.firebase.database.ValueEventListener;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FeaturedRestaurantAdapter extends RecyclerView.Adapter<FeaturedRestaurantAdapter.ViewHolder> {
|
||||||
|
private List<Restaurant> restaurants;
|
||||||
|
private RestaurantAdapter.OnRestaurantClickListener listener;
|
||||||
|
|
||||||
|
public FeaturedRestaurantAdapter(List<Restaurant> restaurants, RestaurantAdapter.OnRestaurantClickListener listener) {
|
||||||
|
this.restaurants = restaurants;
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_restaurant_featured, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
Restaurant restaurant = restaurants.get(position);
|
||||||
|
holder.txtName.setText(restaurant.getName());
|
||||||
|
holder.txtCategory.setText("• " + restaurant.getCategory());
|
||||||
|
|
||||||
|
if (holder.txtRating != null) {
|
||||||
|
if (restaurant.getRatingAvg() != null && restaurant.getRatingAvg() > 0) {
|
||||||
|
holder.txtRating.setText(String.format(java.util.Locale.getDefault(), "%.1f", restaurant.getRatingAvg()));
|
||||||
|
} else {
|
||||||
|
holder.txtRating.setText("Novo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restaurant.getLogoUrl() != null && !restaurant.getLogoUrl().isEmpty()) {
|
||||||
|
com.bumptech.glide.Glide.with(holder.itemView.getContext())
|
||||||
|
.load(restaurant.getLogoUrl())
|
||||||
|
.centerCrop()
|
||||||
|
.into(holder.imgCover);
|
||||||
|
} else {
|
||||||
|
holder.imgCover.setImageResource(R.mipmap.ic_launcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(v -> {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onRestaurantClick(restaurant);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (holder.btnFavorite != null) {
|
||||||
|
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||||
|
if (user != null && user.getEmail() != null && restaurant.getEmail() != null) {
|
||||||
|
String encodedUserEmail = user.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
String encodedRestEmail = restaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("users")
|
||||||
|
.child(encodedUserEmail).child("favorites").child(encodedRestEmail);
|
||||||
|
|
||||||
|
// Read initial state
|
||||||
|
favRef.addListenerForSingleValueEvent(new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
holder.btnFavorite.setTag(snapshot.exists());
|
||||||
|
if (snapshot.exists()) {
|
||||||
|
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_on);
|
||||||
|
holder.btnFavorite.setColorFilter(androidx.core.content.ContextCompat.getColor(holder.itemView.getContext(), R.color.colorPrimary));
|
||||||
|
} else {
|
||||||
|
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_off);
|
||||||
|
holder.btnFavorite.clearColorFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@NonNull DatabaseError error) { }
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.btnFavorite.setOnClickListener(v -> {
|
||||||
|
// Optimistic UI update
|
||||||
|
boolean isFav = holder.btnFavorite.getTag() != null && (Boolean) holder.btnFavorite.getTag();
|
||||||
|
boolean newFavState = !isFav;
|
||||||
|
holder.btnFavorite.setTag(newFavState);
|
||||||
|
|
||||||
|
if (newFavState) {
|
||||||
|
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_on);
|
||||||
|
holder.btnFavorite.setColorFilter(androidx.core.content.ContextCompat.getColor(holder.itemView.getContext(), R.color.colorPrimary));
|
||||||
|
favRef.setValue(restaurant);
|
||||||
|
com.google.android.material.snackbar.Snackbar.make(v, "Adicionado aos Favoritos!", com.google.android.material.snackbar.Snackbar.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_off);
|
||||||
|
holder.btnFavorite.clearColorFilter();
|
||||||
|
favRef.removeValue();
|
||||||
|
com.google.android.material.snackbar.Snackbar.make(v, "Removido dos Favoritos.", com.google.android.material.snackbar.Snackbar.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return restaurants.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView txtName, txtCategory, txtRating;
|
||||||
|
ImageView imgCover;
|
||||||
|
android.widget.ImageButton btnFavorite;
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
txtName = itemView.findViewById(R.id.txtFeaturedName);
|
||||||
|
txtCategory = itemView.findViewById(R.id.txtFeaturedCategory);
|
||||||
|
txtRating = itemView.findViewById(R.id.txtFeaturedRating);
|
||||||
|
imgCover = itemView.findViewById(R.id.imgFeaturedCover);
|
||||||
|
btnFavorite = itemView.findViewById(R.id.btnFavorite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
app/src/main/java/com/example/pap_teste/ReviewAdapter.java
Normal file
75
app/src/main/java/com/example/pap_teste/ReviewAdapter.java
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package com.example.pap_teste;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.example.pap_teste.models.Review;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ReviewAdapter extends RecyclerView.Adapter<ReviewAdapter.ViewHolder> {
|
||||||
|
private List<Review> reviews;
|
||||||
|
private String currentUserEmail;
|
||||||
|
private OnReviewDeleteListener deleteListener;
|
||||||
|
|
||||||
|
public interface OnReviewDeleteListener {
|
||||||
|
void onDeleteClick(Review review);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReviewAdapter(List<Review> reviews, String currentUserEmail, OnReviewDeleteListener deleteListener) {
|
||||||
|
this.reviews = reviews;
|
||||||
|
this.currentUserEmail = currentUserEmail;
|
||||||
|
this.deleteListener = deleteListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_review, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
Review review = reviews.get(position);
|
||||||
|
|
||||||
|
holder.txtAuthor.setText(review.getAuthor() != null ? review.getAuthor() : "Anónimo");
|
||||||
|
holder.txtText.setText(review.getText() != null ? review.getText() : "");
|
||||||
|
holder.txtRating.setText(String.valueOf(review.getRating()));
|
||||||
|
|
||||||
|
if (currentUserEmail != null && currentUserEmail.equals(review.getUserEmail())) {
|
||||||
|
holder.btnDelete.setVisibility(View.VISIBLE);
|
||||||
|
holder.btnDelete.setOnClickListener(v -> {
|
||||||
|
if (deleteListener != null) {
|
||||||
|
deleteListener.onDeleteClick(review);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
holder.btnDelete.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return reviews.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView txtAuthor, txtText, txtRating;
|
||||||
|
ImageButton btnDelete;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
txtAuthor = itemView.findViewById(R.id.txtReviewAuthor);
|
||||||
|
txtText = itemView.findViewById(R.id.txtReviewText);
|
||||||
|
txtRating = itemView.findViewById(R.id.txtReviewRating);
|
||||||
|
btnDelete = itemView.findViewById(R.id.btnDeleteReview);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
package com.example.pap_teste.components;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.example.pap_teste.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class InteractiveRatingBar extends LinearLayout {
|
||||||
|
|
||||||
|
public interface OnRatingChangeListener {
|
||||||
|
void onRatingChanged(double rating);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnRatingChangeListener listener;
|
||||||
|
private int numStars = 5;
|
||||||
|
private double currentRating = 5.0;
|
||||||
|
private List<ImageView> stars = new ArrayList<>();
|
||||||
|
|
||||||
|
// Size settings
|
||||||
|
private int starSizeDp = 40;
|
||||||
|
private int starPaddingDp = 4;
|
||||||
|
|
||||||
|
public InteractiveRatingBar(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InteractiveRatingBar(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InteractiveRatingBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Context context) {
|
||||||
|
setOrientation(HORIZONTAL);
|
||||||
|
setGravity(android.view.Gravity.CENTER);
|
||||||
|
|
||||||
|
int sizePx = (int) (starSizeDp * context.getResources().getDisplayMetrics().density);
|
||||||
|
int paddingPx = (int) (starPaddingDp * context.getResources().getDisplayMetrics().density);
|
||||||
|
|
||||||
|
for (int i = 0; i < numStars; i++) {
|
||||||
|
ImageView star = new ImageView(context);
|
||||||
|
LayoutParams params = new LayoutParams(sizePx, sizePx);
|
||||||
|
params.setMargins(paddingPx, paddingPx, paddingPx, paddingPx);
|
||||||
|
star.setLayoutParams(params);
|
||||||
|
|
||||||
|
// Set scale type to fit center
|
||||||
|
star.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
||||||
|
|
||||||
|
addView(star);
|
||||||
|
stars.add(star);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStars(currentRating, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnRatingChangeListener(OnRatingChangeListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRating() {
|
||||||
|
return currentRating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRating(double rating) {
|
||||||
|
this.currentRating = Math.max(0.0, Math.min(rating, numStars));
|
||||||
|
updateStars(currentRating, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||||
|
float x = event.getX();
|
||||||
|
calculateRatingFromTouch(x);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calculateRatingFromTouch(float x) {
|
||||||
|
if (stars.isEmpty()) return;
|
||||||
|
|
||||||
|
double newRating = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < numStars; i++) {
|
||||||
|
ImageView star = stars.get(i);
|
||||||
|
float starLeft = star.getLeft();
|
||||||
|
float starRight = star.getRight();
|
||||||
|
float starCenter = starLeft + (star.getWidth() / 2f);
|
||||||
|
|
||||||
|
if (x >= starRight) {
|
||||||
|
newRating = i + 1.0;
|
||||||
|
} else if (x >= starCenter && x < starRight) {
|
||||||
|
newRating = i + 1.0;
|
||||||
|
break;
|
||||||
|
} else if (x >= starLeft && x < starCenter) {
|
||||||
|
newRating = i + 0.5;
|
||||||
|
break;
|
||||||
|
} else if (x < starLeft && i == 0) {
|
||||||
|
newRating = 0.5; // Minimum 0.5 when touched
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp values
|
||||||
|
newRating = Math.max(0.5, Math.min(newRating, numStars));
|
||||||
|
|
||||||
|
if (newRating != currentRating) {
|
||||||
|
currentRating = newRating;
|
||||||
|
updateStars(currentRating, true);
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onRatingChanged(currentRating);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateStars(double rating, boolean animate) {
|
||||||
|
for (int i = 0; i < numStars; i++) {
|
||||||
|
ImageView star = stars.get(i);
|
||||||
|
int previousResId = (Integer) (star.getTag() != null ? star.getTag() : 0);
|
||||||
|
int newResId;
|
||||||
|
|
||||||
|
double starVal = i + 1;
|
||||||
|
if (rating >= starVal) {
|
||||||
|
newResId = R.drawable.ic_star_full;
|
||||||
|
} else if (rating >= starVal - 0.5) {
|
||||||
|
newResId = R.drawable.ic_star_half;
|
||||||
|
} else {
|
||||||
|
newResId = R.drawable.ic_star_empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousResId != newResId) {
|
||||||
|
star.setImageResource(newResId);
|
||||||
|
star.setTag(newResId);
|
||||||
|
|
||||||
|
if (animate) {
|
||||||
|
// Micro-animation (Bounce scale)
|
||||||
|
star.animate()
|
||||||
|
.scaleX(1.2f)
|
||||||
|
.scaleY(1.2f)
|
||||||
|
.setDuration(100)
|
||||||
|
.withEndAction(() -> {
|
||||||
|
star.animate()
|
||||||
|
.scaleX(1.0f)
|
||||||
|
.scaleY(1.0f)
|
||||||
|
.setDuration(100)
|
||||||
|
.start();
|
||||||
|
})
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
app/src/main/java/com/example/pap_teste/models/Review.java
Normal file
34
app/src/main/java/com/example/pap_teste/models/Review.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package com.example.pap_teste.models;
|
||||||
|
|
||||||
|
public class Review {
|
||||||
|
private String key;
|
||||||
|
private String author;
|
||||||
|
private String text;
|
||||||
|
private float rating;
|
||||||
|
private String userEmail;
|
||||||
|
|
||||||
|
public Review() {}
|
||||||
|
|
||||||
|
public Review(String key, String author, String text, float rating, String userEmail) {
|
||||||
|
this.key = key;
|
||||||
|
this.author = author;
|
||||||
|
this.text = text;
|
||||||
|
this.rating = rating;
|
||||||
|
this.userEmail = userEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() { return key; }
|
||||||
|
public void setKey(String key) { this.key = key; }
|
||||||
|
|
||||||
|
public String getAuthor() { return author; }
|
||||||
|
public void setAuthor(String author) { this.author = author; }
|
||||||
|
|
||||||
|
public String getText() { return text; }
|
||||||
|
public void setText(String text) { this.text = text; }
|
||||||
|
|
||||||
|
public float getRating() { return rating; }
|
||||||
|
public void setRating(float rating) { this.rating = rating; }
|
||||||
|
|
||||||
|
public String getUserEmail() { return userEmail; }
|
||||||
|
public void setUserEmail(String userEmail) { this.userEmail = userEmail; }
|
||||||
|
}
|
||||||
5
app/src/main/res/drawable/bg_circle_white.xml
Normal file
5
app/src/main/res/drawable/bg_circle_white.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="oval">
|
||||||
|
<solid android:color="#E6FFFFFF" />
|
||||||
|
</shape>
|
||||||
8
app/src/main/res/drawable/bg_input_modern.xml
Normal file
8
app/src/main/res/drawable/bg_input_modern.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/colorBackground"/>
|
||||||
|
<corners android:radius="12dp"/>
|
||||||
|
<stroke android:width="1dp" android:color="@color/colorDivider"/>
|
||||||
|
<padding android:left="16dp" android:top="12dp" android:right="16dp" android:bottom="12dp"/>
|
||||||
|
</shape>
|
||||||
7
app/src/main/res/drawable/bg_rounded_card.xml
Normal file
7
app/src/main/res/drawable/bg_rounded_card.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/colorSurface"/>
|
||||||
|
<corners android:radius="16dp"/>
|
||||||
|
<stroke android:width="1dp" android:color="@color/colorDivider"/>
|
||||||
|
</shape>
|
||||||
7
app/src/main/res/drawable/gradient_shadow_up.xml
Normal file
7
app/src/main/res/drawable/gradient_shadow_up.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<gradient
|
||||||
|
android:angle="90"
|
||||||
|
android:startColor="#88000000"
|
||||||
|
android:endColor="#00000000" />
|
||||||
|
</shape>
|
||||||
6
app/src/main/res/drawable/ic_star_empty.xml
Normal file
6
app/src/main/res/drawable/ic_star_empty.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#D3D3D3"
|
||||||
|
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
|
||||||
|
</vector>
|
||||||
6
app/src/main/res/drawable/ic_star_full.xml
Normal file
6
app/src/main/res/drawable/ic_star_full.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/colorWarning"
|
||||||
|
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
|
||||||
|
</vector>
|
||||||
9
app/src/main/res/drawable/ic_star_half.xml
Normal file
9
app/src/main/res/drawable/ic_star_half.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#D3D3D3"
|
||||||
|
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/colorWarning"
|
||||||
|
android:pathData="M12,2 L9.19,8.63 L2,9.24 L5.46,13.97 L4.82,21 L12,17.27 V2 z"/>
|
||||||
|
</vector>
|
||||||
78
app/src/main/res/layout/dialog_leave_review.xml
Normal file
78
app/src/main/res/layout/dialog_leave_review.xml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="24dp"
|
||||||
|
android:background="@drawable/bg_rounded_card">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Deixe a sua Avaliação"
|
||||||
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
android:textSize="22sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:layout_marginBottom="8dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Como foi a sua experiência neste restaurante?"
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:layout_marginBottom="24dp" />
|
||||||
|
|
||||||
|
<com.example.pap_teste.components.InteractiveRatingBar
|
||||||
|
android:id="@+id/interactiveRatingBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginBottom="24dp" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etReviewComment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="120dp"
|
||||||
|
android:background="@drawable/bg_input_modern"
|
||||||
|
android:gravity="top|start"
|
||||||
|
android:hint="Partilha a tua experiência..."
|
||||||
|
android:inputType="textMultiLine|textCapSentences|textAutoCorrect"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
android:textColorHint="@color/colorTextHint"
|
||||||
|
android:layout_marginBottom="24dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnCancelReview"
|
||||||
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="54dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Cancelar"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/colorTextSecondary" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnSubmitReview"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="54dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
app:cornerRadius="12dp"
|
||||||
|
app:backgroundTint="@color/colorPrimary"
|
||||||
|
android:text="Submeter"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
63
app/src/main/res/layout/dialog_reviews_list.xml
Normal file
63
app/src/main/res/layout/dialog_reviews_list.xml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="20dp"
|
||||||
|
android:background="@drawable/bg_rounded_card">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Avaliações"
|
||||||
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
android:textSize="22sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtEmptyReviews"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Ainda sem avaliações."
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvReviewsList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clipToPadding="false" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="16dp">
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnCloseReviews"
|
||||||
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="54dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Fechar"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/colorTextSecondary" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnAddReview"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="54dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Adicionar"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
app:backgroundTint="@color/colorPrimary" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
125
app/src/main/res/layout/item_restaurant_featured.xml
Normal file
125
app/src/main/res/layout/item_restaurant_featured.xml
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="280dp"
|
||||||
|
android:layout_height="180dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginVertical="8dp"
|
||||||
|
app:cardCornerRadius="24dp"
|
||||||
|
app:cardElevation="4dp"
|
||||||
|
app:strokeWidth="0dp">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imgFeaturedCover"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@mipmap/ic_launcher"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:background="@drawable/gradient_shadow_up"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtFeaturedName"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:text="Restaurante"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/layoutRating"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btnFavorite"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:background="@drawable/bg_circle_white"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:src="@android:drawable/btn_star_big_off"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:tint="@color/colorTextPrimary" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layoutRating"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:src="@android:drawable/star_on"
|
||||||
|
app:tint="@color/colorWarning" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtFeaturedRating"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:text="4.8"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtFeaturedCategory"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="6dp"
|
||||||
|
android:text="• Sushi"
|
||||||
|
android:textColor="#E0E0E0"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
app:cardCornerRadius="12dp"
|
||||||
|
app:cardBackgroundColor="#CCFFFFFF"
|
||||||
|
app:strokeWidth="0dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="12dp"
|
||||||
|
android:paddingVertical="6dp"
|
||||||
|
android:text="Destaque"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/colorTextPrimary" />
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
73
app/src/main/res/layout/item_review.xml
Normal file
73
app/src/main/res/layout/item_review.xml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:background="@drawable/bg_rounded_card"
|
||||||
|
android:layout_marginBottom="12dp">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtReviewAuthor"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Author Name"
|
||||||
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="4dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="14dp"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:src="@android:drawable/star_on"
|
||||||
|
app:tint="@color/colorWarning" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtReviewRating"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:text="5.0"
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btnDeleteReview"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:src="@android:drawable/ic_menu_delete"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:tint="@color/colorError" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtReviewText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="Review text goes here."
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
15
app/src/main/res/menu/bottom_nav_menu.xml
Normal file
15
app/src/main/res/menu/bottom_nav_menu.xml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_home"
|
||||||
|
android:icon="@android:drawable/ic_menu_compass"
|
||||||
|
android:title="Início" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_reservations"
|
||||||
|
android:icon="@android:drawable/ic_menu_agenda"
|
||||||
|
android:title="Reservas" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_profile"
|
||||||
|
android:icon="@android:drawable/ic_menu_info_details"
|
||||||
|
android:title="Perfil" />
|
||||||
|
</menu>
|
||||||
Reference in New Issue
Block a user