...
This commit is contained in:
@@ -2,7 +2,12 @@ package com.example.pap_teste;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.widget.Button;
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import androidx.activity.EdgeToEdge;
|
||||||
@@ -10,214 +15,279 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||||||
import androidx.core.graphics.Insets;
|
import androidx.core.graphics.Insets;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import com.example.pap_teste.models.FoodCategory;
|
|
||||||
|
import com.example.pap_teste.models.Restaurant;
|
||||||
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||||
|
import com.google.android.material.chip.Chip;
|
||||||
|
import com.google.android.material.chip.ChipGroup;
|
||||||
|
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.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ClientDashboardActivity extends AppCompatActivity {
|
public class ClientDashboardActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private String email, displayName, role;
|
private String email, displayName;
|
||||||
private TextView txtGreeting;
|
private TextView txtGreeting;
|
||||||
private androidx.activity.result.ActivityResultLauncher<Intent> profileLauncher;
|
private ImageView imgProfile;
|
||||||
|
private EditText etSearch;
|
||||||
|
private ChipGroup chipGroupCategories;
|
||||||
|
private RecyclerView rvFeatured, rvMainRestaurants;
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
private View layoutFeatured, layoutAllRestaurants;
|
||||||
|
|
||||||
@Override
|
private List<Restaurant> allRestaurants = new ArrayList<>();
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
private List<Restaurant> filteredRestaurants = new ArrayList<>();
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
EdgeToEdge.enable(this);
|
|
||||||
setContentView(R.layout.activity_client_dashboard);
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.clientRoot), (v, insets) -> {
|
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
|
||||||
return insets;
|
|
||||||
});
|
|
||||||
|
|
||||||
txtGreeting = findViewById(R.id.txtClientGreeting);
|
private RestaurantAdapter mainAdapter;
|
||||||
|
private FeaturedRestaurantAdapter featuredAdapter;
|
||||||
|
|
||||||
email = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL);
|
private final String[] CATEGORIES = {"Tudo", "Carnes", "Massas", "Sushi", "Pizzas", "Sobremesas"};
|
||||||
displayName = getIntent().getStringExtra(MainActivity.EXTRA_DISPLAY_NAME);
|
private String currentCategoryFilter = "Tudo";
|
||||||
role = getIntent().getStringExtra(MainActivity.EXTRA_ROLE);
|
private String currentSearchFilter = "";
|
||||||
|
|
||||||
profileLauncher = registerForActivityResult(
|
@Override
|
||||||
new androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult(),
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
result -> {
|
super.onCreate(savedInstanceState);
|
||||||
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
|
EdgeToEdge.enable(this);
|
||||||
String updatedName = result.getData()
|
setContentView(R.layout.activity_client_dashboard);
|
||||||
.getStringExtra(MainActivity.EXTRA_DISPLAY_NAME);
|
|
||||||
if (updatedName != null) {
|
|
||||||
displayName = updatedName;
|
|
||||||
updateGreeting();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
updateGreeting();
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.clientRoot), (v, insets) -> {
|
||||||
fetchProfilePicture();
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
setupCategories();
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
setupActions();
|
return insets;
|
||||||
loadNextReservation();
|
});
|
||||||
|
|
||||||
|
email = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL);
|
||||||
|
displayName = getIntent().getStringExtra(MainActivity.EXTRA_DISPLAY_NAME);
|
||||||
|
|
||||||
|
initViews();
|
||||||
|
setupBottomNavigation();
|
||||||
|
setupSearch();
|
||||||
|
setupCategories();
|
||||||
|
|
||||||
|
updateGreeting();
|
||||||
|
fetchProfilePicture();
|
||||||
|
fetchRestaurants();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initViews() {
|
||||||
|
txtGreeting = findViewById(R.id.txtClientGreeting);
|
||||||
|
imgProfile = findViewById(R.id.imgProfile);
|
||||||
|
etSearch = findViewById(R.id.etSearch);
|
||||||
|
chipGroupCategories = findViewById(R.id.chipGroupCategories);
|
||||||
|
rvFeatured = findViewById(R.id.rvFeatured);
|
||||||
|
rvMainRestaurants = findViewById(R.id.rvMainRestaurants);
|
||||||
|
progressBar = findViewById(R.id.progressBar);
|
||||||
|
layoutFeatured = findViewById(R.id.layoutFeatured);
|
||||||
|
layoutAllRestaurants = findViewById(R.id.layoutAllRestaurants);
|
||||||
|
|
||||||
|
rvFeatured.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
|
||||||
|
rvMainRestaurants.setLayoutManager(new LinearLayoutManager(this));
|
||||||
|
|
||||||
|
// Click listener for restaurants to open booking flow
|
||||||
|
RestaurantAdapter.OnRestaurantClickListener clickListener = restaurant -> {
|
||||||
|
Intent intent = new Intent(this, ExplorarRestaurantesActivity.class);
|
||||||
|
// Reusing existing activity for details if needed, or pass data to NovaReservaActivity
|
||||||
|
// We pass the filter so it can maybe open directly or we just pass restaurant email
|
||||||
|
intent.putExtra("category_filter", restaurant.getCategory());
|
||||||
|
startActivity(intent);
|
||||||
|
};
|
||||||
|
|
||||||
|
featuredAdapter = new FeaturedRestaurantAdapter(new ArrayList<>(), clickListener);
|
||||||
|
mainAdapter = new RestaurantAdapter(filteredRestaurants, clickListener);
|
||||||
|
|
||||||
|
rvFeatured.setAdapter(featuredAdapter);
|
||||||
|
rvMainRestaurants.setAdapter(mainAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupBottomNavigation() {
|
||||||
|
BottomNavigationView bottomNav = findViewById(R.id.bottomNavigation);
|
||||||
|
bottomNav.setOnItemSelectedListener(item -> {
|
||||||
|
int id = item.getItemId();
|
||||||
|
if (id == R.id.nav_home) {
|
||||||
|
return true;
|
||||||
|
} else if (id == R.id.nav_reservations) {
|
||||||
|
Intent intent = new Intent(this, MinhasReservasActivity.class);
|
||||||
|
intent.putExtra(MainActivity.EXTRA_EMAIL, email);
|
||||||
|
startActivity(intent);
|
||||||
|
return false; // Don't highlight if we open new activity
|
||||||
|
} else if (id == R.id.nav_profile) {
|
||||||
|
Intent intent = new Intent(this, ProfileDashboardActivity.class);
|
||||||
|
intent.putExtra(MainActivity.EXTRA_EMAIL, email);
|
||||||
|
intent.putExtra(MainActivity.EXTRA_DISPLAY_NAME, displayName);
|
||||||
|
startActivity(intent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateGreeting() {
|
||||||
|
if (displayName != null && !displayName.isEmpty()) {
|
||||||
|
txtGreeting.setText("Olá, " + displayName.split(" ")[0] + "!");
|
||||||
|
} else {
|
||||||
|
txtGreeting.setText("Olá, Visitante!");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateGreeting() {
|
private void fetchProfilePicture() {
|
||||||
txtGreeting.setText(String.format("Olá, %s", displayName != null ? displayName : "convidado"));
|
if (email == null) return;
|
||||||
}
|
String documentId = email.replace(".", "_").replace("@", "_at_");
|
||||||
|
FirebaseDatabase.getInstance().getReference().child("users").child(documentId).child("photoUrl")
|
||||||
|
.get().addOnSuccessListener(snapshot -> {
|
||||||
|
if (!isDestroyed() && snapshot.exists() && snapshot.getValue(String.class) != null) {
|
||||||
|
com.bumptech.glide.Glide.with(this).load(snapshot.getValue(String.class)).circleCrop().into(imgProfile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void fetchProfilePicture() {
|
private void fetchRestaurants() {
|
||||||
if (email == null) return;
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
String documentId = email.replace(".", "_").replace("@", "_at_");
|
layoutFeatured.setVisibility(View.GONE);
|
||||||
com.google.firebase.database.FirebaseDatabase.getInstance().getReference()
|
layoutAllRestaurants.setVisibility(View.GONE);
|
||||||
.child("users").child(documentId).child("photoUrl")
|
|
||||||
.get().addOnSuccessListener(snapshot -> {
|
|
||||||
if (!isDestroyed() && snapshot.exists()) {
|
|
||||||
String photoUrl = snapshot.getValue(String.class);
|
|
||||||
if (photoUrl != null && !photoUrl.isEmpty()) {
|
|
||||||
android.widget.ImageView imgProfile = findViewById(R.id.imgProfile);
|
|
||||||
com.bumptech.glide.Glide.with(this).load(photoUrl).circleCrop().into(imgProfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupCategories() {
|
DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("users");
|
||||||
RecyclerView rv = findViewById(R.id.rvCategories);
|
usersRef.addListenerForSingleValueEvent(new ValueEventListener() {
|
||||||
List<FoodCategory> cats = new ArrayList<>();
|
@Override
|
||||||
cats.add(new FoodCategory("Carnes", R.drawable.cat_carnes));
|
public void onDataChange(@androidx.annotation.NonNull DataSnapshot snapshot) {
|
||||||
cats.add(new FoodCategory("Massas", R.drawable.cat_massas));
|
progressBar.setVisibility(View.GONE);
|
||||||
cats.add(new FoodCategory("Sushi", R.drawable.cat_sushi));
|
allRestaurants.clear();
|
||||||
cats.add(new FoodCategory("Pizzas", R.drawable.cat_pizzas));
|
|
||||||
cats.add(new FoodCategory("Sobremesas", R.drawable.cat_sobremesas));
|
|
||||||
|
|
||||||
FoodCategoryAdapter adapter = new FoodCategoryAdapter(cats, category -> {
|
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||||
Intent intent = new Intent(this, ExplorarRestaurantesActivity.class);
|
String role = ds.child("role").getValue(String.class);
|
||||||
intent.putExtra("category_filter", category.getName());
|
String accountType = ds.child("accountType").getValue(String.class);
|
||||||
startActivity(intent);
|
|
||||||
});
|
|
||||||
rv.setAdapter(adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupActions() {
|
if ("ADMIN".equalsIgnoreCase(role) || "ESTABELECIMENTO".equalsIgnoreCase(accountType)) {
|
||||||
findViewById(R.id.cardProfile).setOnClickListener(v -> {
|
String name = ds.child("establishmentName").getValue(String.class);
|
||||||
Intent intent = new Intent(this, ProfileDashboardActivity.class);
|
if (name == null) name = ds.child("displayName").getValue(String.class);
|
||||||
intent.putExtra(MainActivity.EXTRA_EMAIL, email);
|
String email = ds.child("email").getValue(String.class);
|
||||||
intent.putExtra(MainActivity.EXTRA_DISPLAY_NAME, displayName);
|
String cat = ds.child("category").getValue(String.class);
|
||||||
profileLauncher.launch(intent);
|
String logoUrl = ds.child("logoUrl").getValue(String.class);
|
||||||
});
|
Double ratingAvg = ds.child("ratingAvg").getValue(Double.class);
|
||||||
|
Integer ratingCount = ds.child("ratingCount").getValue(Integer.class);
|
||||||
|
|
||||||
findViewById(R.id.btnVoltar).setOnClickListener(v -> finish());
|
if (name != null && email != null) {
|
||||||
|
Restaurant r = new Restaurant(name, cat != null ? cat : "Vário", email, false, logoUrl);
|
||||||
findViewById(R.id.btnPartilhar).setOnClickListener(
|
if (ratingAvg != null) r.setRatingAvg(ratingAvg);
|
||||||
v -> startActivity(new Intent(this, PartilharReservaActivity.class)));
|
if (ratingCount != null) r.setRatingCount(ratingCount);
|
||||||
|
allRestaurants.add(r);
|
||||||
findViewById(R.id.btnNovaReserva)
|
|
||||||
.setOnClickListener(v -> startActivity(new Intent(this, NovaReservaActivity.class)));
|
|
||||||
|
|
||||||
findViewById(R.id.btnMinhasReservas)
|
|
||||||
.setOnClickListener(v -> {
|
|
||||||
Intent intent = new Intent(this, MinhasReservasActivity.class);
|
|
||||||
intent.putExtra(MainActivity.EXTRA_EMAIL, email);
|
|
||||||
startActivity(intent);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadNextReservation() {
|
|
||||||
if (email == null) return;
|
|
||||||
com.google.firebase.database.DatabaseReference ref = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reservas");
|
|
||||||
ref.orderByChild("clienteEmail").equalTo(email).addValueEventListener(new com.google.firebase.database.ValueEventListener() {
|
|
||||||
@Override
|
|
||||||
public void onDataChange(com.google.firebase.database.DataSnapshot snapshot) {
|
|
||||||
com.example.pap_teste.models.Reserva proxima = null;
|
|
||||||
long timeProx = Long.MAX_VALUE;
|
|
||||||
long currentTime = System.currentTimeMillis();
|
|
||||||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm", java.util.Locale.getDefault());
|
|
||||||
|
|
||||||
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
|
||||||
com.example.pap_teste.models.Reserva r = ds.getValue(com.example.pap_teste.models.Reserva.class);
|
|
||||||
if (r != null && (r.getEstado().startsWith("Confirmada") || r.getEstado().equals("Pendente"))) {
|
|
||||||
try {
|
|
||||||
java.util.Date rDate = sdf.parse(r.getData() + " " + r.getHora());
|
|
||||||
if (rDate != null) {
|
|
||||||
long rTime = rDate.getTime();
|
|
||||||
// Consider reservations from the last 2 hours and in the future
|
|
||||||
if (rTime >= currentTime - 2L * 60 * 60 * 1000) {
|
|
||||||
if (rTime < timeProx) {
|
|
||||||
timeProx = rTime;
|
|
||||||
proxima = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextView txtTitle = findViewById(R.id.txtResTitle);
|
|
||||||
TextView txtTime = findViewById(R.id.txtResTime);
|
|
||||||
Button btnCheckIn = findViewById(R.id.btnCheckIn);
|
|
||||||
Button btnPartilhar = findViewById(R.id.btnPartilhar);
|
|
||||||
|
|
||||||
if (proxima != null) {
|
|
||||||
txtTitle.setText(proxima.getRestauranteName());
|
|
||||||
|
|
||||||
// Formatting to show "Hoje", "Amanhã" or the date itself
|
|
||||||
String dateStr = proxima.getData();
|
|
||||||
try {
|
|
||||||
java.util.Date rDate = sdf.parse(proxima.getData() + " " + proxima.getHora());
|
|
||||||
if (rDate != null) {
|
|
||||||
java.util.Calendar cal = java.util.Calendar.getInstance();
|
|
||||||
cal.setTime(rDate);
|
|
||||||
|
|
||||||
java.util.Calendar today = java.util.Calendar.getInstance();
|
|
||||||
|
|
||||||
java.util.Calendar tmr = java.util.Calendar.getInstance();
|
|
||||||
tmr.add(java.util.Calendar.DAY_OF_YEAR, 1);
|
|
||||||
|
|
||||||
if (cal.get(java.util.Calendar.YEAR) == today.get(java.util.Calendar.YEAR) && cal.get(java.util.Calendar.DAY_OF_YEAR) == today.get(java.util.Calendar.DAY_OF_YEAR)) {
|
|
||||||
dateStr = "Hoje";
|
|
||||||
} else if (cal.get(java.util.Calendar.YEAR) == tmr.get(java.util.Calendar.YEAR) && cal.get(java.util.Calendar.DAY_OF_YEAR) == tmr.get(java.util.Calendar.DAY_OF_YEAR)) {
|
|
||||||
dateStr = "Amanhã";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
txtTime.setText(String.format("%s às %s • %d pessoas", dateStr, proxima.getHora(), proxima.getPessoas()));
|
|
||||||
btnCheckIn.setVisibility(android.view.View.VISIBLE);
|
|
||||||
btnPartilhar.setVisibility(android.view.View.VISIBLE);
|
|
||||||
|
|
||||||
String encodedEmail = proxima.getRestauranteEmail().replace(".", "_").replace("@", "_at_");
|
|
||||||
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users").child(encodedEmail)
|
|
||||||
.child("logoUrl").get().addOnSuccessListener(s -> {
|
|
||||||
if (!isDestroyed() && s.exists() && s.getValue() != null) {
|
|
||||||
android.widget.ImageView imgResIcon = findViewById(R.id.imgResIcon);
|
|
||||||
com.bumptech.glide.Glide.with(ClientDashboardActivity.this).load(s.getValue(String.class)).circleCrop().into(imgResIcon);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
com.example.pap_teste.models.Reserva finalProxima = proxima;
|
|
||||||
btnCheckIn.setOnClickListener(v -> {
|
|
||||||
boolean hasLocationPermission = androidx.core.app.ActivityCompat.checkSelfPermission(ClientDashboardActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION) == android.content.pm.PackageManager.PERMISSION_GRANTED;
|
|
||||||
if (!hasLocationPermission) {
|
|
||||||
android.widget.Toast.makeText(ClientDashboardActivity.this, "Dê permissões de localização para aceder ao check-in.", android.widget.Toast.LENGTH_SHORT).show();
|
|
||||||
} else {
|
|
||||||
Intent intent = new Intent(ClientDashboardActivity.this, CheckInAntecipadoActivity.class);
|
|
||||||
intent.putExtra("restaurant_email", finalProxima.getRestauranteEmail());
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
txtTitle.setText("Sem reservas ativas");
|
|
||||||
txtTime.setText("Explore os restaurantes e reserve!");
|
|
||||||
btnCheckIn.setVisibility(android.view.View.GONE);
|
|
||||||
btnPartilhar.setVisibility(android.view.View.GONE);
|
|
||||||
android.widget.ImageView imgResIcon = findViewById(R.id.imgResIcon);
|
|
||||||
imgResIcon.setImageResource(R.drawable.circle_bg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@Override
|
}
|
||||||
public void onCancelled(com.google.firebase.database.DatabaseError error) {}
|
}
|
||||||
});
|
applyFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull DatabaseError error) {
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupCategories() {
|
||||||
|
for (String category : CATEGORIES) {
|
||||||
|
Chip chip = new Chip(this);
|
||||||
|
chip.setText(category);
|
||||||
|
chip.setCheckable(true);
|
||||||
|
chip.setClickable(true);
|
||||||
|
// Default styling
|
||||||
|
chip.setChipBackgroundColorResource(R.color.colorSurface);
|
||||||
|
chip.setTextColor(getResources().getColor(R.color.colorTextSecondary));
|
||||||
|
chip.setChipStrokeWidth(0f);
|
||||||
|
|
||||||
|
if (category.equals("Tudo")) {
|
||||||
|
chip.setChecked(true);
|
||||||
|
chip.setChipBackgroundColorResource(R.color.colorPrimary);
|
||||||
|
chip.setTextColor(getResources().getColor(R.color.white));
|
||||||
|
}
|
||||||
|
|
||||||
|
chip.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
|
if (isChecked) {
|
||||||
|
// Reset all other chips visual state
|
||||||
|
for (int i = 0; i < chipGroupCategories.getChildCount(); i++) {
|
||||||
|
Chip c = (Chip) chipGroupCategories.getChildAt(i);
|
||||||
|
if (c != chip) {
|
||||||
|
c.setChipBackgroundColorResource(R.color.colorSurface);
|
||||||
|
c.setTextColor(getResources().getColor(R.color.colorTextSecondary));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chip.setChipBackgroundColorResource(R.color.colorPrimary);
|
||||||
|
chip.setTextColor(getResources().getColor(R.color.white));
|
||||||
|
|
||||||
|
currentCategoryFilter = category;
|
||||||
|
applyFilters();
|
||||||
|
} else if (currentCategoryFilter.equals(category)) {
|
||||||
|
// Prevent unchecking the currently selected chip
|
||||||
|
chip.setChecked(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
chipGroupCategories.addView(chip);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupSearch() {
|
||||||
|
etSearch.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
currentSearchFilter = s.toString().toLowerCase().trim();
|
||||||
|
applyFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyFilters() {
|
||||||
|
filteredRestaurants.clear();
|
||||||
|
String normalizedSearch = normalizeString(currentSearchFilter);
|
||||||
|
|
||||||
|
for (Restaurant r : allRestaurants) {
|
||||||
|
boolean matchesCategory = currentCategoryFilter.equals("Tudo") || currentCategoryFilter.equals(r.getCategory());
|
||||||
|
|
||||||
|
String normalizedName = normalizeString(r.getName());
|
||||||
|
boolean matchesSearch = currentSearchFilter.isEmpty() || normalizedName.contains(normalizedSearch);
|
||||||
|
|
||||||
|
if (matchesCategory && matchesSearch) {
|
||||||
|
filteredRestaurants.add(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mainAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
// Update featured (just the first 3 for demo, or based on a specific logic)
|
||||||
|
List<Restaurant> featuredList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < Math.min(3, filteredRestaurants.size()); i++) {
|
||||||
|
featuredList.add(filteredRestaurants.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
featuredAdapter = new FeaturedRestaurantAdapter(featuredList, mainAdapter instanceof RestaurantAdapter ?
|
||||||
|
restaurant -> {
|
||||||
|
Intent intent = new Intent(this, ExplorarRestaurantesActivity.class);
|
||||||
|
intent.putExtra("category_filter", restaurant.getCategory());
|
||||||
|
startActivity(intent);
|
||||||
|
} : null);
|
||||||
|
rvFeatured.setAdapter(featuredAdapter);
|
||||||
|
|
||||||
|
layoutFeatured.setVisibility(featuredList.isEmpty() ? View.GONE : View.VISIBLE);
|
||||||
|
layoutAllRestaurants.setVisibility(filteredRestaurants.isEmpty() ? View.GONE : View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeString(String str) {
|
||||||
|
if (str == null) return "";
|
||||||
|
// Remove accents and special marks, and convert to lowercase
|
||||||
|
String normalized = java.text.Normalizer.normalize(str, java.text.Normalizer.Form.NFD);
|
||||||
|
normalized = normalized.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
|
||||||
|
return normalized.toLowerCase().trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
private android.view.View scrollReservaDetails;
|
private android.view.View scrollReservaDetails;
|
||||||
private androidx.recyclerview.widget.RecyclerView rvRestaurants;
|
private androidx.recyclerview.widget.RecyclerView rvRestaurants;
|
||||||
private android.widget.TextView txtTitle;
|
private android.widget.TextView txtTitle;
|
||||||
|
private android.widget.ProgressBar progressBar;
|
||||||
|
|
||||||
private String selectedDate = null;
|
private String selectedDate = null;
|
||||||
private String selectedTime = null;
|
private String selectedTime = null;
|
||||||
@@ -52,6 +53,7 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
rvRestaurants = findViewById(R.id.rvRestaurants);
|
rvRestaurants = findViewById(R.id.rvRestaurants);
|
||||||
scrollReservaDetails = findViewById(R.id.scrollReservaDetails);
|
scrollReservaDetails = findViewById(R.id.scrollReservaDetails);
|
||||||
txtTitle = findViewById(R.id.txtTituloExplorar);
|
txtTitle = findViewById(R.id.txtTituloExplorar);
|
||||||
|
progressBar = findViewById(R.id.progressBar);
|
||||||
|
|
||||||
Button back = findViewById(R.id.btnVoltar);
|
Button back = findViewById(R.id.btnVoltar);
|
||||||
if (back != null) {
|
if (back != null) {
|
||||||
@@ -82,9 +84,39 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
} else {
|
} else {
|
||||||
txtTitle.setText("Reserva: " + (selectedRestaurant != null ? selectedRestaurant.getName() : ""));
|
txtTitle.setText("Reserva: " + (selectedRestaurant != null ? selectedRestaurant.getName() : ""));
|
||||||
setupReservationOptions();
|
setupReservationOptions();
|
||||||
|
loadRestaurantRating();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadRestaurantRating() {
|
||||||
|
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||||
|
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
|
||||||
|
android.widget.TextView txtAvgRating = findViewById(R.id.txtAvgRating);
|
||||||
|
android.widget.TextView txtTotalReviews = findViewById(R.id.txtTotalReviews);
|
||||||
|
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users")
|
||||||
|
.child(encodedEmail)
|
||||||
|
.addValueEventListener(new com.google.firebase.database.ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
Double avg = snapshot.child("ratingAvg").getValue(Double.class);
|
||||||
|
Integer count = snapshot.child("ratingCount").getValue(Integer.class);
|
||||||
|
|
||||||
|
if (avg != null && count != null && count > 0) {
|
||||||
|
txtAvgRating.setText(String.format(java.util.Locale.getDefault(), "%.1f", avg));
|
||||||
|
txtTotalReviews.setText(String.format(java.util.Locale.getDefault(), "(%d avaliações)", count));
|
||||||
|
} else {
|
||||||
|
txtAvgRating.setText("0.0");
|
||||||
|
txtTotalReviews.setText("(0 avaliações)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void setupRestaurantList() {
|
private void setupRestaurantList() {
|
||||||
String filter = getIntent().getStringExtra("category_filter");
|
String filter = getIntent().getStringExtra("category_filter");
|
||||||
java.util.List<com.example.pap_teste.models.Restaurant> restaurantsList = new java.util.ArrayList<>();
|
java.util.List<com.example.pap_teste.models.Restaurant> restaurantsList = new java.util.ArrayList<>();
|
||||||
@@ -95,9 +127,12 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
query = usersRef.orderByChild("category").equalTo(filter);
|
query = usersRef.orderByChild("category").equalTo(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.VISIBLE);
|
||||||
|
|
||||||
query.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
query.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||||
restaurantsList.clear();
|
restaurantsList.clear();
|
||||||
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
||||||
String role = ds.child("role").getValue(String.class);
|
String role = ds.child("role").getValue(String.class);
|
||||||
@@ -126,6 +161,7 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||||
android.widget.Toast.makeText(ExplorarRestaurantesActivity.this, "Erro ao carregar restaurantes.", android.widget.Toast.LENGTH_SHORT).show();
|
android.widget.Toast.makeText(ExplorarRestaurantesActivity.this, "Erro ao carregar restaurantes.", android.widget.Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -189,32 +225,69 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||||
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
|
||||||
|
android.view.View dialogView = getLayoutInflater().inflate(R.layout.dialog_reviews_list, null);
|
||||||
|
androidx.recyclerview.widget.RecyclerView rvReviews = dialogView.findViewById(R.id.rvReviewsList);
|
||||||
|
android.widget.TextView txtEmpty = dialogView.findViewById(R.id.txtEmptyReviews);
|
||||||
|
android.widget.Button btnClose = dialogView.findViewById(R.id.btnCloseReviews);
|
||||||
|
android.widget.Button btnAdd = dialogView.findViewById(R.id.btnAddReview);
|
||||||
|
|
||||||
|
rvReviews.setLayoutManager(new androidx.recyclerview.widget.LinearLayoutManager(this));
|
||||||
|
|
||||||
|
androidx.appcompat.app.AlertDialog dialog = new androidx.appcompat.app.AlertDialog.Builder(this)
|
||||||
|
.setView(dialogView)
|
||||||
|
.create();
|
||||||
|
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
|
||||||
|
|
||||||
|
btnClose.setOnClickListener(v -> dialog.dismiss());
|
||||||
|
btnAdd.setOnClickListener(v -> {
|
||||||
|
dialog.dismiss();
|
||||||
|
addReviewDialog();
|
||||||
|
});
|
||||||
|
|
||||||
com.google.firebase.database.DatabaseReference reviewsRef = com.google.firebase.database.FirebaseDatabase.getInstance()
|
com.google.firebase.database.DatabaseReference reviewsRef = com.google.firebase.database.FirebaseDatabase.getInstance()
|
||||||
.getReference("reviews").child(encodedEmail);
|
.getReference("reviews").child(encodedEmail);
|
||||||
|
|
||||||
reviewsRef.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
String currentUserEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null ?
|
||||||
|
com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail() : null;
|
||||||
|
|
||||||
|
reviewsRef.addValueEventListener(new com.google.firebase.database.ValueEventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
java.util.List<String> reviewsList = new java.util.ArrayList<>();
|
java.util.List<com.example.pap_teste.models.Review> reviewsList = new java.util.ArrayList<>();
|
||||||
for (com.google.firebase.database.DataSnapshot dst : snapshot.getChildren()) {
|
for (com.google.firebase.database.DataSnapshot dst : snapshot.getChildren()) {
|
||||||
String author = dst.child("author").getValue(String.class);
|
String author = dst.child("author").getValue(String.class);
|
||||||
String text = dst.child("text").getValue(String.class);
|
String text = dst.child("text").getValue(String.class);
|
||||||
if (author != null && text != null) {
|
String uEmail = dst.child("userEmail").getValue(String.class);
|
||||||
reviewsList.add(author + "\n" + text);
|
Float rating = dst.child("rating").getValue(Float.class);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] reviewsArray = reviewsList.toArray(new String[0]);
|
if (rating == null) rating = 0f;
|
||||||
androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(ExplorarRestaurantesActivity.this)
|
|
||||||
.setTitle("Avaliações")
|
com.example.pap_teste.models.Review rev = new com.example.pap_teste.models.Review(
|
||||||
.setItems(reviewsArray, null)
|
dst.getKey(), author, text, rating, uEmail);
|
||||||
.setPositiveButton("Fechar", null)
|
reviewsList.add(rev);
|
||||||
.setNeutralButton("Adicionar", (dialog, which) -> addReviewDialog());
|
}
|
||||||
|
|
||||||
if (reviewsList.isEmpty()) {
|
if (reviewsList.isEmpty()) {
|
||||||
builder.setMessage("Ainda sem avaliações.");
|
txtEmpty.setVisibility(android.view.View.VISIBLE);
|
||||||
|
rvReviews.setVisibility(android.view.View.GONE);
|
||||||
|
} else {
|
||||||
|
txtEmpty.setVisibility(android.view.View.GONE);
|
||||||
|
rvReviews.setVisibility(android.view.View.VISIBLE);
|
||||||
}
|
}
|
||||||
builder.show();
|
|
||||||
|
ReviewAdapter adapter = new ReviewAdapter(reviewsList, currentUserEmail, review -> {
|
||||||
|
// Confirmação de Apagar
|
||||||
|
new androidx.appcompat.app.AlertDialog.Builder(ExplorarRestaurantesActivity.this)
|
||||||
|
.setTitle("Apagar Avaliação")
|
||||||
|
.setMessage("Tens a certeza que queres apagar esta avaliação?")
|
||||||
|
.setPositiveButton("Sim", (d, w) -> {
|
||||||
|
deleteReview(review.getKey());
|
||||||
|
d.dismiss();
|
||||||
|
})
|
||||||
|
.setNegativeButton("Não", null)
|
||||||
|
.show();
|
||||||
|
});
|
||||||
|
rvReviews.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -222,49 +295,157 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
android.widget.Toast.makeText(ExplorarRestaurantesActivity.this, "Erro ao carregar avaliações.", android.widget.Toast.LENGTH_SHORT).show();
|
android.widget.Toast.makeText(ExplorarRestaurantesActivity.this, "Erro ao carregar avaliações.", android.widget.Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteReview(String reviewKey) {
|
||||||
|
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||||
|
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
|
||||||
|
com.google.firebase.database.DatabaseReference reviewsRef = com.google.firebase.database.FirebaseDatabase.getInstance()
|
||||||
|
.getReference("reviews").child(encodedEmail);
|
||||||
|
|
||||||
|
reviewsRef.child(reviewKey).removeValue().addOnSuccessListener(aVoid -> {
|
||||||
|
com.google.android.material.snackbar.Snackbar.make(findViewById(R.id.explorarRoot), "Avaliação removida", com.google.android.material.snackbar.Snackbar.LENGTH_SHORT).show();
|
||||||
|
recalculateRestaurantAverage(encodedEmail);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recalculateRestaurantAverage(String encodedEmail) {
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reviews").child(encodedEmail)
|
||||||
|
.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
double totalRating = 0;
|
||||||
|
int count = 0;
|
||||||
|
for (com.google.firebase.database.DataSnapshot dst : snapshot.getChildren()) {
|
||||||
|
Float r = dst.child("rating").getValue(Float.class);
|
||||||
|
if (r != null) {
|
||||||
|
totalRating += r;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double newAvg = count > 0 ? (totalRating / count) : 0.0;
|
||||||
|
|
||||||
|
java.util.Map<String, Object> updates = new java.util.HashMap<>();
|
||||||
|
updates.put("ratingAvg", newAvg);
|
||||||
|
updates.put("ratingCount", count);
|
||||||
|
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users")
|
||||||
|
.child(encodedEmail).updateChildren(updates);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addReviewDialog() {
|
private void addReviewDialog() {
|
||||||
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||||
|
|
||||||
android.widget.EditText input = new android.widget.EditText(this);
|
android.view.View dialogView = getLayoutInflater().inflate(R.layout.dialog_leave_review, null);
|
||||||
input.setHint("Escreva a sua avaliação aqui...");
|
com.example.pap_teste.components.InteractiveRatingBar ratingBar = dialogView.findViewById(R.id.interactiveRatingBar);
|
||||||
new androidx.appcompat.app.AlertDialog.Builder(this)
|
android.widget.EditText input = dialogView.findViewById(R.id.etReviewComment);
|
||||||
.setTitle("Adicionar Avaliação")
|
android.widget.Button btnSubmit = dialogView.findViewById(R.id.btnSubmitReview);
|
||||||
.setView(input)
|
android.widget.Button btnCancel = dialogView.findViewById(R.id.btnCancelReview);
|
||||||
.setPositiveButton("Enviar", (dialog, which) -> {
|
|
||||||
String revText = input.getText().toString().trim();
|
btnSubmit.setEnabled(false);
|
||||||
if (!revText.isEmpty()) {
|
btnSubmit.setAlpha(0.5f);
|
||||||
com.google.firebase.auth.FirebaseUser currentUser = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
|
|
||||||
if (currentUser != null && currentUser.getEmail() != null) {
|
input.addTextChangedListener(new android.text.TextWatcher() {
|
||||||
String userDoc = currentUser.getEmail().replace(".", "_").replace("@", "_at_");
|
@Override
|
||||||
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users").child(userDoc).get().addOnSuccessListener(snapshot -> {
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
String authorName = snapshot.exists() && snapshot.child("displayName").getValue(String.class) != null
|
|
||||||
? snapshot.child("displayName").getValue(String.class)
|
@Override
|
||||||
: "Visitante";
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
submitReviewToFirebase(authorName, revText);
|
boolean hasText = s != null && s.toString().trim().length() > 0;
|
||||||
}).addOnFailureListener(e -> submitReviewToFirebase("Visitante", revText));
|
btnSubmit.setEnabled(hasText);
|
||||||
} else {
|
btnSubmit.setAlpha(hasText ? 1.0f : 0.5f);
|
||||||
submitReviewToFirebase("Visitante", revText);
|
}
|
||||||
}
|
|
||||||
}
|
@Override
|
||||||
})
|
public void afterTextChanged(android.text.Editable s) {}
|
||||||
.setNegativeButton("Cancelar", null)
|
});
|
||||||
.show();
|
|
||||||
|
androidx.appcompat.app.AlertDialog dialog = new androidx.appcompat.app.AlertDialog.Builder(this)
|
||||||
|
.setView(dialogView)
|
||||||
|
.create();
|
||||||
|
|
||||||
|
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
|
||||||
|
|
||||||
|
btnCancel.setOnClickListener(v -> dialog.dismiss());
|
||||||
|
btnSubmit.setOnClickListener(v -> {
|
||||||
|
float rating = (float) ratingBar.getRating();
|
||||||
|
String revText = input.getText().toString().trim();
|
||||||
|
|
||||||
|
com.google.firebase.auth.FirebaseUser currentUser = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
|
||||||
|
if (currentUser != null && currentUser.getEmail() != null) {
|
||||||
|
String userDoc = currentUser.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users").child(userDoc).get().addOnSuccessListener(snapshot -> {
|
||||||
|
String authorName = snapshot.exists() && snapshot.child("displayName").getValue(String.class) != null
|
||||||
|
? snapshot.child("displayName").getValue(String.class)
|
||||||
|
: "Visitante";
|
||||||
|
submitReviewToFirebase(authorName, revText, rating);
|
||||||
|
dialog.dismiss();
|
||||||
|
}).addOnFailureListener(e -> {
|
||||||
|
submitReviewToFirebase("Visitante", revText, rating);
|
||||||
|
dialog.dismiss();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
submitReviewToFirebase("Visitante", revText, rating);
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void submitReviewToFirebase(String authorName, String revText) {
|
private void submitReviewToFirebase(String authorName, String revText, float newRating) {
|
||||||
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
|
||||||
|
com.google.firebase.auth.FirebaseUser currentUser = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
|
||||||
|
String uEmail = currentUser != null ? currentUser.getEmail() : null;
|
||||||
|
|
||||||
|
// 1. Guardar a Review
|
||||||
java.util.Map<String, Object> review = new java.util.HashMap<>();
|
java.util.Map<String, Object> review = new java.util.HashMap<>();
|
||||||
review.put("author", authorName);
|
review.put("author", authorName);
|
||||||
review.put("text", revText);
|
review.put("text", revText);
|
||||||
|
review.put("rating", newRating);
|
||||||
|
review.put("userEmail", uEmail);
|
||||||
|
review.put("timestamp", com.google.firebase.database.ServerValue.TIMESTAMP);
|
||||||
|
|
||||||
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reviews")
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reviews")
|
||||||
.child(encodedEmail).push().setValue(review).addOnCompleteListener(task -> {
|
.child(encodedEmail).push().setValue(review).addOnCompleteListener(task -> {
|
||||||
if (task.isSuccessful()) {
|
if (task.isSuccessful()) {
|
||||||
android.widget.Toast.makeText(this, "Avaliação enviada!", android.widget.Toast.LENGTH_SHORT).show();
|
com.google.android.material.snackbar.Snackbar.make(findViewById(R.id.explorarRoot), "Obrigado pela tua avaliação!", com.google.android.material.snackbar.Snackbar.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 2. Atualizar Média no Restaurante
|
||||||
|
com.google.firebase.database.DatabaseReference restRef = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users").child(encodedEmail);
|
||||||
|
restRef.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
Double currentAvg = snapshot.child("ratingAvg").getValue(Double.class);
|
||||||
|
Integer currentCount = snapshot.child("ratingCount").getValue(Integer.class);
|
||||||
|
|
||||||
|
if (currentAvg == null) currentAvg = 0.0;
|
||||||
|
if (currentCount == null) currentCount = 0;
|
||||||
|
|
||||||
|
double newAvg = ((currentAvg * currentCount) + newRating) / (currentCount + 1);
|
||||||
|
|
||||||
|
java.util.Map<String, Object> updates = new java.util.HashMap<>();
|
||||||
|
updates.put("ratingAvg", newAvg);
|
||||||
|
updates.put("ratingCount", currentCount + 1);
|
||||||
|
|
||||||
|
restRef.updateChildren(updates);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveReservation() {
|
private void saveReservation() {
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ public class FavoritosActivity extends AppCompatActivity {
|
|||||||
private androidx.recyclerview.widget.RecyclerView rv;
|
private androidx.recyclerview.widget.RecyclerView rv;
|
||||||
private RestaurantAdapter adapter;
|
private RestaurantAdapter adapter;
|
||||||
private List<Restaurant> list;
|
private List<Restaurant> list;
|
||||||
|
private android.widget.ProgressBar progressBar;
|
||||||
|
private android.view.View emptyState;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -47,8 +49,15 @@ public class FavoritosActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rv = findViewById(R.id.rvFavoritos);
|
rv = findViewById(R.id.rvFavoritos);
|
||||||
|
progressBar = findViewById(R.id.progressBar);
|
||||||
|
emptyState = findViewById(R.id.emptyState);
|
||||||
|
|
||||||
list = new ArrayList<>();
|
list = new ArrayList<>();
|
||||||
adapter = new RestaurantAdapter(list, null);
|
adapter = new RestaurantAdapter(list, restaurant -> {
|
||||||
|
android.content.Intent intent = new android.content.Intent(this, ExplorarRestaurantesActivity.class);
|
||||||
|
intent.putExtra("category_filter", restaurant.getCategory()); // just as demo
|
||||||
|
startActivity(intent);
|
||||||
|
});
|
||||||
rv.setAdapter(adapter);
|
rv.setAdapter(adapter);
|
||||||
|
|
||||||
setupFavoritesList();
|
setupFavoritesList();
|
||||||
@@ -64,6 +73,7 @@ public class FavoritosActivity extends AppCompatActivity {
|
|||||||
favRef.addValueEventListener(new ValueEventListener() {
|
favRef.addValueEventListener(new ValueEventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||||
list.clear();
|
list.clear();
|
||||||
for (DataSnapshot ds : snapshot.getChildren()) {
|
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||||
Restaurant restaurant = ds.getValue(Restaurant.class);
|
Restaurant restaurant = ds.getValue(Restaurant.class);
|
||||||
@@ -72,10 +82,15 @@ public class FavoritosActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
if (emptyState != null) {
|
||||||
|
emptyState.setVisibility(list.isEmpty() ? android.view.View.VISIBLE : android.view.View.GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCancelled(@NonNull DatabaseError error) {
|
public void onCancelled(@NonNull DatabaseError error) {
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||||
Toast.makeText(FavoritosActivity.this, "Erro ao carregar favoritos.", Toast.LENGTH_SHORT).show();
|
Toast.makeText(FavoritosActivity.this, "Erro ao carregar favoritos.", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ public class MinhasReservasActivity extends AppCompatActivity {
|
|||||||
private final List<Reserva> reservaList = new ArrayList<>();
|
private final List<Reserva> reservaList = new ArrayList<>();
|
||||||
private DatabaseReference databaseReference;
|
private DatabaseReference databaseReference;
|
||||||
private String clientEmail;
|
private String clientEmail;
|
||||||
|
private android.widget.ProgressBar progressBar;
|
||||||
|
private android.view.View emptyState;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -56,6 +58,8 @@ public class MinhasReservasActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rvMinhasReservas = findViewById(R.id.rvMinhasReservas);
|
rvMinhasReservas = findViewById(R.id.rvMinhasReservas);
|
||||||
|
progressBar = findViewById(R.id.progressBar);
|
||||||
|
emptyState = findViewById(R.id.emptyState);
|
||||||
Button btnVoltar = findViewById(R.id.btnVoltar);
|
Button btnVoltar = findViewById(R.id.btnVoltar);
|
||||||
btnVoltar.setOnClickListener(v -> finish());
|
btnVoltar.setOnClickListener(v -> finish());
|
||||||
|
|
||||||
@@ -82,10 +86,14 @@ public class MinhasReservasActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
private void loadReservations() {
|
private void loadReservations() {
|
||||||
databaseReference = FirebaseDatabase.getInstance().getReference("reservas");
|
databaseReference = FirebaseDatabase.getInstance().getReference("reservas");
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.VISIBLE);
|
||||||
|
if (emptyState != null) emptyState.setVisibility(android.view.View.GONE);
|
||||||
|
|
||||||
databaseReference.orderByChild("clienteEmail").equalTo(clientEmail)
|
databaseReference.orderByChild("clienteEmail").equalTo(clientEmail)
|
||||||
.addValueEventListener(new ValueEventListener() {
|
.addValueEventListener(new ValueEventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||||
reservaList.clear();
|
reservaList.clear();
|
||||||
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
|
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
|
||||||
Reserva reserva = dataSnapshot.getValue(Reserva.class);
|
Reserva reserva = dataSnapshot.getValue(Reserva.class);
|
||||||
@@ -93,11 +101,18 @@ public class MinhasReservasActivity extends AppCompatActivity {
|
|||||||
reservaList.add(reserva);
|
reservaList.add(reserva);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Order reservations (newest first based on ID or we can just reverse the list)
|
||||||
|
java.util.Collections.reverse(reservaList);
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
if (emptyState != null) {
|
||||||
|
emptyState.setVisibility(reservaList.isEmpty() ? android.view.View.VISIBLE : android.view.View.GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCancelled(@NonNull DatabaseError error) {
|
public void onCancelled(@NonNull DatabaseError error) {
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||||
Toast.makeText(MinhasReservasActivity.this, "Erro ao carregar reservas.", Toast.LENGTH_SHORT)
|
Toast.makeText(MinhasReservasActivity.this, "Erro ao carregar reservas.", Toast.LENGTH_SHORT)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
private androidx.recyclerview.widget.RecyclerView rvCategories, rvRestaurants;
|
private androidx.recyclerview.widget.RecyclerView rvCategories, rvRestaurants;
|
||||||
private android.view.View scrollNovaReserva;
|
private android.view.View scrollNovaReserva;
|
||||||
private android.widget.TextView txtTitle;
|
private android.widget.TextView txtTitle;
|
||||||
|
private android.widget.ProgressBar progressBar;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -40,6 +41,7 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
rvRestaurants = findViewById(R.id.rvRestaurants);
|
rvRestaurants = findViewById(R.id.rvRestaurants);
|
||||||
scrollNovaReserva = findViewById(R.id.scrollNovaReserva);
|
scrollNovaReserva = findViewById(R.id.scrollNovaReserva);
|
||||||
txtTitle = findViewById(R.id.txtTituloNovaReserva);
|
txtTitle = findViewById(R.id.txtTituloNovaReserva);
|
||||||
|
progressBar = findViewById(R.id.progressBar);
|
||||||
|
|
||||||
Button back = findViewById(R.id.btnVoltar);
|
Button back = findViewById(R.id.btnVoltar);
|
||||||
if (back != null) {
|
if (back != null) {
|
||||||
@@ -101,9 +103,12 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
java.util.List<com.example.pap_teste.models.Restaurant> filteredList = new java.util.ArrayList<>();
|
java.util.List<com.example.pap_teste.models.Restaurant> filteredList = new java.util.ArrayList<>();
|
||||||
com.google.firebase.database.DatabaseReference usersRef = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users");
|
com.google.firebase.database.DatabaseReference usersRef = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users");
|
||||||
|
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.VISIBLE);
|
||||||
|
|
||||||
usersRef.orderByChild("category").equalTo(selectedCategory).addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
usersRef.orderByChild("category").equalTo(selectedCategory).addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||||
filteredList.clear();
|
filteredList.clear();
|
||||||
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
||||||
String role = ds.child("role").getValue(String.class);
|
String role = ds.child("role").getValue(String.class);
|
||||||
@@ -132,6 +137,7 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||||
android.widget.Toast.makeText(NovaReservaActivity.this, "Erro ao carregar restaurantes.", android.widget.Toast.LENGTH_SHORT).show();
|
android.widget.Toast.makeText(NovaReservaActivity.this, "Erro ao carregar restaurantes.", android.widget.Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -179,6 +185,10 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
String restEmail = selectedRestaurant.getEmail();
|
String restEmail = selectedRestaurant.getEmail();
|
||||||
|
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.VISIBLE);
|
||||||
|
android.widget.Button btnConfirmar = findViewById(R.id.btnConfirmarReserva);
|
||||||
|
if (btnConfirmar != null) btnConfirmar.setEnabled(false);
|
||||||
|
|
||||||
com.google.firebase.database.DatabaseReference mesasRef = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("Mesas");
|
com.google.firebase.database.DatabaseReference mesasRef = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("Mesas");
|
||||||
|
|
||||||
mesasRef.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
mesasRef.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
||||||
@@ -276,6 +286,10 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
ref.child(id).setValue(reserva).addOnCompleteListener(task -> {
|
ref.child(id).setValue(reserva).addOnCompleteListener(task -> {
|
||||||
|
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||||
|
android.widget.Button btnConfirmar = findViewById(R.id.btnConfirmarReserva);
|
||||||
|
if (btnConfirmar != null) btnConfirmar.setEnabled(true);
|
||||||
|
|
||||||
if (task.isSuccessful()) {
|
if (task.isSuccessful()) {
|
||||||
android.widget.Toast
|
android.widget.Toast
|
||||||
.makeText(NovaReservaActivity.this, "Reserva solicitada com sucesso!", android.widget.Toast.LENGTH_SHORT)
|
.makeText(NovaReservaActivity.this, "Reserva solicitada com sucesso!", android.widget.Toast.LENGTH_SHORT)
|
||||||
|
|||||||
@@ -41,7 +41,25 @@ public class ReservaAdapter extends RecyclerView.Adapter<ReservaAdapter.ViewHold
|
|||||||
Reserva reserva = reservas.get(position);
|
Reserva reserva = reservas.get(position);
|
||||||
holder.txtRestaurante.setText(reserva.getRestauranteName());
|
holder.txtRestaurante.setText(reserva.getRestauranteName());
|
||||||
holder.txtDataHora.setText(reserva.getData() + " às " + reserva.getHora() + " • " + reserva.getPessoas() + "p");
|
holder.txtDataHora.setText(reserva.getData() + " às " + reserva.getHora() + " • " + reserva.getPessoas() + "p");
|
||||||
holder.txtStatus.setText("Estado: " + reserva.getEstado());
|
|
||||||
|
if (holder.chipStatus != null) {
|
||||||
|
String state = reserva.getEstado() != null ? reserva.getEstado() : "Pendente";
|
||||||
|
holder.chipStatus.setText(state);
|
||||||
|
int colorBg, colorText;
|
||||||
|
android.content.Context ctx = holder.itemView.getContext();
|
||||||
|
if ("Confirmada".equals(state)) {
|
||||||
|
colorBg = androidx.core.content.ContextCompat.getColor(ctx, R.color.colorChipConfirmed);
|
||||||
|
colorText = androidx.core.content.ContextCompat.getColor(ctx, R.color.colorChipConfirmedText);
|
||||||
|
} else if ("Cancelada".equals(state) || "Recusada".equals(state)) {
|
||||||
|
colorBg = androidx.core.content.ContextCompat.getColor(ctx, R.color.colorChipCancelled);
|
||||||
|
colorText = androidx.core.content.ContextCompat.getColor(ctx, R.color.colorChipCancelledText);
|
||||||
|
} else {
|
||||||
|
colorBg = androidx.core.content.ContextCompat.getColor(ctx, R.color.colorChipPending);
|
||||||
|
colorText = androidx.core.content.ContextCompat.getColor(ctx, R.color.colorChipPendingText);
|
||||||
|
}
|
||||||
|
holder.chipStatus.setChipBackgroundColor(android.content.res.ColorStateList.valueOf(colorBg));
|
||||||
|
holder.chipStatus.setTextColor(colorText);
|
||||||
|
}
|
||||||
|
|
||||||
// Enable check-in only if confirmed
|
// Enable check-in only if confirmed
|
||||||
boolean isConfirmed = "Confirmada".equals(reserva.getEstado());
|
boolean isConfirmed = "Confirmada".equals(reserva.getEstado());
|
||||||
@@ -89,6 +107,7 @@ public class ReservaAdapter extends RecyclerView.Adapter<ReservaAdapter.ViewHold
|
|||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
TextView txtRestaurante, txtDataHora, txtStatus, txtLocationWarning;
|
TextView txtRestaurante, txtDataHora, txtStatus, txtLocationWarning;
|
||||||
Button btnCheckIn, btnCancelar;
|
Button btnCheckIn, btnCancelar;
|
||||||
|
com.google.android.material.chip.Chip chipStatus;
|
||||||
|
|
||||||
public ViewHolder(@NonNull View itemView) {
|
public ViewHolder(@NonNull View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
@@ -98,6 +117,7 @@ public class ReservaAdapter extends RecyclerView.Adapter<ReservaAdapter.ViewHold
|
|||||||
btnCheckIn = itemView.findViewById(R.id.btnCheckIn);
|
btnCheckIn = itemView.findViewById(R.id.btnCheckIn);
|
||||||
btnCancelar = itemView.findViewById(R.id.btnCancelar);
|
btnCancelar = itemView.findViewById(R.id.btnCancelar);
|
||||||
txtLocationWarning = itemView.findViewById(R.id.txtLocationWarning);
|
txtLocationWarning = itemView.findViewById(R.id.txtLocationWarning);
|
||||||
|
chipStatus = itemView.findViewById(R.id.chipReservaStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.example.pap_teste;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@@ -46,6 +47,14 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
|||||||
holder.text1.setText(restaurant.getName());
|
holder.text1.setText(restaurant.getName());
|
||||||
holder.text2.setText(restaurant.getCategory() + (restaurant.isAvailable() ? " - Disponível" : " - Indisponível"));
|
holder.text2.setText(restaurant.getCategory() + (restaurant.isAvailable() ? " - Disponível" : " - Indisponível"));
|
||||||
|
|
||||||
|
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()) {
|
if (restaurant.getLogoUrl() != null && !restaurant.getLogoUrl().isEmpty()) {
|
||||||
com.bumptech.glide.Glide.with(holder.itemView.getContext())
|
com.bumptech.glide.Glide.with(holder.itemView.getContext())
|
||||||
.load(restaurant.getLogoUrl())
|
.load(restaurant.getLogoUrl())
|
||||||
@@ -61,6 +70,14 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (holder.btnReservar != null) {
|
||||||
|
holder.btnReservar.setOnClickListener(v -> {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onRestaurantClick(restaurant);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||||
if (user != null && user.getEmail() != null && restaurant.getEmail() != null) {
|
if (user != null && user.getEmail() != null && restaurant.getEmail() != null) {
|
||||||
String encodedUserEmail = user.getEmail().replace(".", "_").replace("@", "_at_");
|
String encodedUserEmail = user.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
@@ -68,13 +85,17 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
|||||||
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("users")
|
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("users")
|
||||||
.child(encodedUserEmail).child("favorites").child(encodedRestEmail);
|
.child(encodedUserEmail).child("favorites").child(encodedRestEmail);
|
||||||
|
|
||||||
favRef.addValueEventListener(new ValueEventListener() {
|
// Read initial state
|
||||||
|
favRef.addListenerForSingleValueEvent(new ValueEventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
holder.btnFavorite.setTag(snapshot.exists());
|
||||||
if (snapshot.exists()) {
|
if (snapshot.exists()) {
|
||||||
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_on);
|
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 {
|
} else {
|
||||||
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_off);
|
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_off);
|
||||||
|
holder.btnFavorite.clearColorFilter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,19 +104,22 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
|||||||
});
|
});
|
||||||
|
|
||||||
holder.btnFavorite.setOnClickListener(v -> {
|
holder.btnFavorite.setOnClickListener(v -> {
|
||||||
favRef.addListenerForSingleValueEvent(new ValueEventListener() {
|
// Optimistic UI update
|
||||||
@Override
|
boolean isFav = holder.btnFavorite.getTag() != null && (Boolean) holder.btnFavorite.getTag();
|
||||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
boolean newFavState = !isFav;
|
||||||
if (snapshot.exists()) {
|
holder.btnFavorite.setTag(newFavState);
|
||||||
favRef.removeValue();
|
|
||||||
} else {
|
|
||||||
favRef.setValue(restaurant);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (newFavState) {
|
||||||
public void onCancelled(@NonNull DatabaseError error) { }
|
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();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,15 +130,18 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
TextView text1, text2;
|
TextView text1, text2, txtRating;
|
||||||
ImageButton btnFavorite;
|
ImageButton btnFavorite;
|
||||||
android.widget.ImageView imgThumb;
|
android.widget.ImageView imgThumb;
|
||||||
|
Button btnReservar;
|
||||||
public ViewHolder(@NonNull View itemView) {
|
public ViewHolder(@NonNull View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
text1 = itemView.findViewById(R.id.txtRestaurantName);
|
text1 = itemView.findViewById(R.id.txtRestaurantName);
|
||||||
text2 = itemView.findViewById(R.id.txtRestaurantCategory);
|
text2 = itemView.findViewById(R.id.txtRestaurantCategory);
|
||||||
|
txtRating = itemView.findViewById(R.id.txtRestaurantRating);
|
||||||
btnFavorite = itemView.findViewById(R.id.btnFavorite);
|
btnFavorite = itemView.findViewById(R.id.btnFavorite);
|
||||||
imgThumb = itemView.findViewById(R.id.imgRestaurantThumb);
|
imgThumb = itemView.findViewById(R.id.imgRestaurantThumb);
|
||||||
|
btnReservar = itemView.findViewById(R.id.btnReservarCard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ public class Restaurant {
|
|||||||
private String email;
|
private String email;
|
||||||
private boolean available;
|
private boolean available;
|
||||||
private String logoUrl;
|
private String logoUrl;
|
||||||
|
private Double ratingAvg;
|
||||||
|
private Integer ratingCount;
|
||||||
|
|
||||||
// No-argument constructor required for Firebase
|
// No-argument constructor required for Firebase
|
||||||
public Restaurant() {
|
public Restaurant() {
|
||||||
@@ -37,4 +39,9 @@ public class Restaurant {
|
|||||||
public void setEmail(String email) { this.email = email; }
|
public void setEmail(String email) { this.email = email; }
|
||||||
public void setAvailable(boolean available) { this.available = available; }
|
public void setAvailable(boolean available) { this.available = available; }
|
||||||
public void setLogoUrl(String logoUrl) { this.logoUrl = logoUrl; }
|
public void setLogoUrl(String logoUrl) { this.logoUrl = logoUrl; }
|
||||||
|
|
||||||
|
public Double getRatingAvg() { return ratingAvg; }
|
||||||
|
public void setRatingAvg(Double ratingAvg) { this.ratingAvg = ratingAvg; }
|
||||||
|
public Integer getRatingCount() { return ratingCount; }
|
||||||
|
public void setRatingCount(Integer ratingCount) { this.ratingCount = ratingCount; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,283 +8,232 @@
|
|||||||
android:background="@color/colorBackground"
|
android:background="@color/colorBackground"
|
||||||
tools:context=".ClientDashboardActivity">
|
tools:context=".ClientDashboardActivity">
|
||||||
|
|
||||||
<!-- Top Bar with Profile Icon -->
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
|
||||||
android:id="@+id/cardProfile"
|
|
||||||
android:layout_width="50dp"
|
|
||||||
android:layout_height="50dp"
|
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
app:cardCornerRadius="25dp"
|
|
||||||
app:cardElevation="2dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imgProfile"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:src="@drawable/circle_bg" />
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtClientGreeting"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:text="Olá, convidado"
|
|
||||||
android:textColor="@color/colorTextPrimary"
|
|
||||||
android:textSize="22sp"
|
|
||||||
android:fontFamily="sans-serif-medium"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/cardProfile"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/cardProfile"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/cardProfile" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btnVoltar"
|
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:text="Sair"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="@color/colorError"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/cardProfile"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/cardProfile" />
|
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:id="@+id/clientScroll"
|
android:id="@+id/clientScroll"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:fillViewport="true"
|
android:fillViewport="true"
|
||||||
android:scrollbars="none"
|
android:scrollbars="none"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintBottom_toTopOf="@id/bottomNavigation"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/cardProfile">
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="40dp">
|
android:paddingBottom="24dp">
|
||||||
|
|
||||||
<!-- Categories Section -->
|
<!-- Header -->
|
||||||
<TextView
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:text="Categorias"
|
|
||||||
android:textColor="@color/colorTextPrimary"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/rvCategories"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="12dp"
|
android:paddingHorizontal="24dp"
|
||||||
android:clipToPadding="false"
|
android:paddingTop="32dp">
|
||||||
android:orientation="horizontal"
|
|
||||||
android:paddingStart="16dp"
|
|
||||||
android:paddingEnd="16dp"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
|
||||||
tools:listitem="@layout/item_food_category" />
|
|
||||||
|
|
||||||
<!-- Integrated Next Reservation Card -->
|
<TextView
|
||||||
<TextView
|
android:id="@+id/txtClientGreeting"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="24dp"
|
android:text="Olá, convidado!"
|
||||||
android:layout_marginTop="32dp"
|
android:textColor="@color/colorTextPrimary"
|
||||||
android:text="A sua próxima reserva"
|
android:textSize="28sp"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textStyle="bold"
|
||||||
android:textSize="20sp"
|
android:fontFamily="sans-serif"
|
||||||
android:fontFamily="sans-serif-medium" />
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/imgNotification"
|
||||||
|
android:layout_marginEnd="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Encontre a sua próxima mesa."
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/txtClientGreeting"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/imgNotification" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/imgNotification"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:background="@drawable/bg_circle_white"
|
||||||
|
android:src="@android:drawable/ic_popup_reminder"
|
||||||
|
app:tint="@color/colorTextPrimary"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/cardProfile"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/cardProfile"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/cardProfile" />
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/cardProfile"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
app:cardCornerRadius="25dp"
|
||||||
|
app:cardElevation="2dp"
|
||||||
|
app:strokeWidth="0dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imgProfile"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@drawable/circle_bg" />
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<!-- Search Bar -->
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:id="@+id/cardNextReservation"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="56dp"
|
||||||
android:layout_marginHorizontal="24dp"
|
android:layout_marginHorizontal="24dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="24dp"
|
||||||
app:cardBackgroundColor="@color/colorSurface"
|
app:cardCornerRadius="16dp"
|
||||||
app:cardCornerRadius="24dp"
|
app:cardElevation="4dp"
|
||||||
app:cardElevation="6dp">
|
app:strokeWidth="0dp"
|
||||||
|
app:cardBackgroundColor="@color/colorSurface">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="horizontal"
|
||||||
android:padding="24dp">
|
android:gravity="center_vertical"
|
||||||
|
android:paddingHorizontal="16dp">
|
||||||
|
|
||||||
<RelativeLayout
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@android:drawable/ic_menu_search"
|
||||||
|
app:tint="@color/colorTextSecondary" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etSearch"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
<TextView
|
android:background="@null"
|
||||||
android:id="@+id/txtResTitle"
|
android:hint="Pesquisar restaurantes..."
|
||||||
android:layout_width="wrap_content"
|
android:textColor="@color/colorTextPrimary"
|
||||||
android:layout_height="wrap_content"
|
android:textColorHint="@color/colorTextHint"
|
||||||
android:text="Sabor & Arte"
|
android:textSize="16sp"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:maxLines="1"
|
||||||
android:textSize="20sp"
|
android:inputType="text" />
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtResTime"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/txtResTitle"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:text="Amanhã às 20h00 • 2 pessoas"
|
|
||||||
android:textColor="@color/colorTextSecondary"
|
|
||||||
android:textSize="15sp" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imgResIcon"
|
|
||||||
android:layout_width="56dp"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:src="@drawable/circle_bg"
|
|
||||||
app:tint="@color/colorPrimary" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:layout_marginVertical="20dp"
|
|
||||||
android:background="@color/colorDivider" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btnCheckIn"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="54dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
app:cornerRadius="14dp"
|
|
||||||
app:backgroundTint="@color/colorPrimary"
|
|
||||||
android:text="Check-in"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="15sp" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btnPartilhar"
|
|
||||||
style="@style/Widget.Material3.Button.TonalButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="54dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
app:cornerRadius="14dp"
|
|
||||||
android:text="Partilhar"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textSize="15sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
<!-- Actions Section -->
|
<!-- Category Pills -->
|
||||||
<TextView
|
<HorizontalScrollView
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginTop="40dp"
|
|
||||||
android:text="Mais opções"
|
|
||||||
android:textColor="@color/colorTextPrimary"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<GridLayout
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginTop="24dp"
|
||||||
android:layout_marginTop="16dp"
|
android:scrollbars="none"
|
||||||
android:columnCount="1">
|
android:clipToPadding="false"
|
||||||
|
android:paddingHorizontal="20dp">
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.chip.ChipGroup
|
||||||
android:id="@+id/cardNewRes"
|
android:id="@+id/chipGroupCategories"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="90dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
app:singleLine="true"
|
||||||
app:cardCornerRadius="16dp"
|
app:singleSelection="true">
|
||||||
app:cardElevation="2dp"
|
<!-- Chips will be added programmatically -->
|
||||||
app:cardBackgroundColor="@color/colorSurface">
|
</com.google.android.material.chip.ChipGroup>
|
||||||
<LinearLayout
|
</HorizontalScrollView>
|
||||||
android:id="@+id/btnNovaReserva"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="?attr/selectableItemBackground">
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Reservar"
|
|
||||||
android:textColor="@color/colorTextPrimary"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
</LinearLayout>
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<!-- Loading Spinner -->
|
||||||
android:id="@+id/cardMinhasReservas"
|
<ProgressBar
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/progressBar"
|
||||||
android:layout_height="90dp"
|
|
||||||
android:layout_margin="8dp"
|
|
||||||
app:cardCornerRadius="16dp"
|
|
||||||
app:cardElevation="2dp"
|
|
||||||
app:cardBackgroundColor="@color/colorSurface">
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/btnMinhasReservas"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="?attr/selectableItemBackground">
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Minhas Reservas"
|
|
||||||
android:textColor="@color/colorTextPrimary"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
</LinearLayout>
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
|
|
||||||
</GridLayout>
|
|
||||||
|
|
||||||
<!-- Status Section -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtClientStatus"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="32dp"
|
|
||||||
android:layout_marginTop="40dp"
|
|
||||||
android:text="Tudo pronto para a sua próxima refeição!"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="@color/colorTextSecondary"
|
|
||||||
android:textSize="15sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtClientRole"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="40dp"
|
||||||
android:text="Modo Cliente"
|
android:visibility="visible"
|
||||||
android:textColor="#94A3B8"
|
android:indeterminateTint="@color/colorPrimary" />
|
||||||
android:textSize="12sp" />
|
|
||||||
|
<!-- Featured Carousel -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layoutFeatured"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginTop="24dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:text="Restaurantes Populares"
|
||||||
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:fontFamily="sans-serif" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvFeatured"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingStart="24dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
tools:listitem="@layout/item_restaurant_featured" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Main Restaurant Grid/List -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layoutAllRestaurants"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginTop="32dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtListTitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:text="Todos os Restaurantes"
|
||||||
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:fontFamily="sans-serif" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvMainRestaurants"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
tools:listitem="@layout/item_restaurant" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
<!-- Bottom Navigation Bar -->
|
||||||
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
|
android:id="@+id/bottomNavigation"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/colorSurface"
|
||||||
|
app:itemIconTint="@color/colorPrimary"
|
||||||
|
app:itemTextColor="@color/colorPrimary"
|
||||||
|
app:menu="@menu/bottom_nav_menu"
|
||||||
|
app:elevation="16dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -8,60 +8,77 @@
|
|||||||
android:background="@color/colorBackground"
|
android:background="@color/colorBackground"
|
||||||
tools:context=".ExplorarRestaurantesActivity">
|
tools:context=".ExplorarRestaurantesActivity">
|
||||||
|
|
||||||
|
<!-- Header Section -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnVoltar"
|
android:id="@+id/btnVoltar"
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
style="@style/Widget.Material3.Button.IconButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="48dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="← Voltar"
|
app:icon="@android:drawable/ic_menu_revert"
|
||||||
android:textAllCaps="false"
|
app:iconTint="@color/colorTextPrimary"
|
||||||
android:textColor="@color/colorTextSecondary"
|
|
||||||
android:textSize="16sp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtTituloExplorar"
|
android:id="@+id/txtTituloExplorar"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
android:text="Explorar restaurantes"
|
android:text="Explorar restaurantes"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textColor="@color/colorTextPrimary"
|
||||||
android:textSize="28sp"
|
android:textSize="28sp"
|
||||||
android:fontFamily="sans-serif-medium"
|
android:textStyle="bold"
|
||||||
app:layout_constraintTop_toBottomOf="@id/btnVoltar"
|
android:fontFamily="sans-serif"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintTop_toTopOf="@id/btnVoltar"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintBottom_toBottomOf="@id/btnVoltar"
|
||||||
android:layout_marginTop="20dp" />
|
app:layout_constraintStart_toEndOf="@id/btnVoltar"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<!-- Loading Spinner -->
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/colorPrimary"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<!-- Restaurant List -->
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvRestaurants"
|
android:id="@+id/rvRestaurants"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="16dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="24dp"
|
android:paddingBottom="24dp"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/txtTituloExplorar"
|
app:layout_constraintTop_toBottomOf="@id/btnVoltar"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
tools:listitem="@layout/item_restaurant" />
|
tools:listitem="@layout/item_restaurant" />
|
||||||
|
|
||||||
|
<!-- Details and Reservation Flow (Overlay) -->
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:id="@+id/scrollReservaDetails"
|
android:id="@+id/scrollReservaDetails"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="16dp"
|
||||||
android:fillViewport="true"
|
android:fillViewport="true"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:scrollbars="none"
|
android:scrollbars="none"
|
||||||
|
android:background="@color/colorBackground"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/txtTituloExplorar">
|
app:layout_constraintTop_toBottomOf="@id/btnVoltar">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -69,12 +86,48 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="48dp">
|
android:paddingBottom="48dp">
|
||||||
|
|
||||||
|
<!-- Rating Section -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingHorizontal="24dp"
|
android:paddingHorizontal="24dp"
|
||||||
android:layout_marginTop="8dp">
|
android:layout_marginTop="16dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@android:drawable/star_on"
|
||||||
|
app:tint="@color/colorWarning" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtAvgRating"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:text="0.0"
|
||||||
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtTotalReviews"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:text="(0 avaliações)"
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Action Buttons for Details -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingHorizontal="24dp"
|
||||||
|
android:layout_marginTop="16dp">
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnVerAvaliacoes"
|
android:id="@+id/btnVerAvaliacoes"
|
||||||
@@ -84,7 +137,7 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
app:cornerRadius="12dp"
|
app:cornerRadius="12dp"
|
||||||
android:text="Avaliações"
|
android:text="Ver / Deixar Avaliação"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/colorPrimary"
|
android:textColor="@color/colorPrimary"
|
||||||
app:strokeColor="@color/colorPrimary" />
|
app:strokeColor="@color/colorPrimary" />
|
||||||
@@ -103,13 +156,15 @@
|
|||||||
app:strokeColor="@color/colorError" />
|
app:strokeColor="@color/colorError" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Reservation Form Card -->
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="24dp"
|
android:layout_marginHorizontal="24dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
app:cardCornerRadius="20dp"
|
app:cardCornerRadius="24dp"
|
||||||
app:cardElevation="2dp"
|
app:cardElevation="4dp"
|
||||||
|
app:strokeWidth="0dp"
|
||||||
app:cardBackgroundColor="@color/colorSurface">
|
app:cardBackgroundColor="@color/colorSurface">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -121,60 +176,69 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Data da reserva"
|
android:text="Detalhes da Reserva"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textColor="@color/colorTextPrimary"
|
||||||
android:textSize="16sp"
|
android:textSize="20sp"
|
||||||
android:fontFamily="sans-serif-medium" />
|
android:textStyle="bold"
|
||||||
|
android:layout_marginBottom="24dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Data da reserva"
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnSelectDate"
|
android:id="@+id/btnSelectDate"
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="54dp"
|
android:layout_height="56dp"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="8dp"
|
||||||
app:cornerRadius="12dp"
|
app:cornerRadius="12dp"
|
||||||
android:text="Selecionar Data"
|
android:text="Selecionar Data"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/colorTextSecondary" />
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
app:strokeColor="@color/colorDivider" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="20dp"
|
||||||
android:text="Hora da reserva"
|
android:text="Hora da reserva"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textColor="@color/colorTextSecondary"
|
||||||
android:textSize="16sp"
|
android:textSize="14sp" />
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnSelectTime"
|
android:id="@+id/btnSelectTime"
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="54dp"
|
android:layout_height="56dp"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="8dp"
|
||||||
app:cornerRadius="12dp"
|
app:cornerRadius="12dp"
|
||||||
android:text="Selecionar Hora"
|
android:text="Selecionar Hora"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/colorTextSecondary" />
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
app:strokeColor="@color/colorDivider" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="20dp"
|
||||||
android:text="Número de pessoas"
|
android:text="Número de pessoas"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textColor="@color/colorTextSecondary"
|
||||||
android:textSize="16sp"
|
android:textSize="14sp" />
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/etPartySize"
|
android:id="@+id/etPartySize"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="54dp"
|
android:layout_height="56dp"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="8dp"
|
||||||
android:background="@drawable/input_bg"
|
android:background="@drawable/bg_input_modern"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
android:hint="Ex: 2"
|
android:hint="Ex: 2"
|
||||||
|
android:textColorHint="@color/colorTextHint"
|
||||||
android:textColor="@color/colorTextPrimary" />
|
android:textColor="@color/colorTextPrimary" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
@@ -182,15 +246,16 @@
|
|||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnConfirmarReserva"
|
android:id="@+id/btnConfirmarReserva"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="56dp"
|
android:layout_height="60dp"
|
||||||
android:layout_marginHorizontal="24dp"
|
android:layout_marginHorizontal="24dp"
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="32dp"
|
||||||
app:cornerRadius="14dp"
|
app:cornerRadius="16dp"
|
||||||
app:backgroundTint="@color/colorPrimary"
|
app:backgroundTint="@color/colorPrimary"
|
||||||
android:text="Confirmar Reserva"
|
android:text="Confirmar Reserva"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="16sp" />
|
android:textStyle="bold"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -8,44 +8,82 @@
|
|||||||
android:background="@color/colorBackground"
|
android:background="@color/colorBackground"
|
||||||
tools:context=".FavoritosActivity">
|
tools:context=".FavoritosActivity">
|
||||||
|
|
||||||
|
<!-- Header Section -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnVoltar"
|
android:id="@+id/btnVoltar"
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
style="@style/Widget.Material3.Button.IconButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="48dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="← Voltar"
|
app:icon="@android:drawable/ic_menu_revert"
|
||||||
android:textAllCaps="false"
|
app:iconTint="@color/colorTextPrimary"
|
||||||
android:textColor="@color/colorTextSecondary"
|
|
||||||
android:textSize="16sp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtTituloFavoritos"
|
android:id="@+id/txtTituloFavoritos"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Restaurantes favoritos"
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:text="Os Meus Favoritos"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textColor="@color/colorTextPrimary"
|
||||||
android:textSize="28sp"
|
android:textSize="28sp"
|
||||||
android:fontFamily="sans-serif-medium"
|
android:textStyle="bold"
|
||||||
app:layout_constraintTop_toBottomOf="@id/btnVoltar"
|
android:fontFamily="sans-serif"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/btnVoltar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/btnVoltar"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/btnVoltar"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<!-- Loading Spinner -->
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:indeterminateTint="@color/colorPrimary"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
android:layout_marginTop="20dp" />
|
|
||||||
|
<!-- Empty State -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/emptyState"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:src="@android:drawable/btn_star_big_off"
|
||||||
|
app:tint="@color/colorDivider" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="Ainda não tens favoritos guardados."
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvFavoritos"
|
android:id="@+id/rvFavoritos"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="16dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="24dp"
|
android:paddingBottom="24dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/btnVoltar"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/txtTituloFavoritos"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
tools:listitem="@layout/item_restaurant" />
|
tools:listitem="@layout/item_restaurant" />
|
||||||
|
|
||||||
|
|||||||
@@ -8,41 +8,81 @@
|
|||||||
android:background="@color/colorBackground"
|
android:background="@color/colorBackground"
|
||||||
tools:context=".MinhasReservasActivity">
|
tools:context=".MinhasReservasActivity">
|
||||||
|
|
||||||
|
<!-- Header Section -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnVoltar"
|
android:id="@+id/btnVoltar"
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
style="@style/Widget.Material3.Button.IconButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="48dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="← Voltar"
|
app:icon="@android:drawable/ic_menu_revert"
|
||||||
android:textAllCaps="false"
|
app:iconTint="@color/colorTextPrimary"
|
||||||
android:textColor="@color/colorTextSecondary"
|
|
||||||
android:textSize="16sp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtTituloMinhasReservas"
|
android:id="@+id/txtTituloMinhasReservas"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
android:text="Minhas Reservas"
|
android:text="Minhas Reservas"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textColor="@color/colorTextPrimary"
|
||||||
android:textSize="28sp"
|
android:textSize="28sp"
|
||||||
android:fontFamily="sans-serif-medium"
|
android:textStyle="bold"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/btnVoltar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/btnVoltar"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/btnVoltar"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<!-- Loading Spinner -->
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/colorPrimary"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
app:layout_constraintTop_toBottomOf="@id/btnVoltar"
|
|
||||||
android:layout_marginTop="20dp" />
|
<!-- Empty State -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/emptyState"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:src="@android:drawable/ic_menu_today"
|
||||||
|
app:tint="@color/colorDivider" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="Sem reservas encontradas."
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvMinhasReservas"
|
android:id="@+id/rvMinhasReservas"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="16dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="16dp"
|
android:paddingBottom="24dp"
|
||||||
app:layout_constraintTop_toBottomOf="@id/txtTituloMinhasReservas"
|
app:layout_constraintTop_toBottomOf="@id/btnVoltar"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|||||||
@@ -8,73 +8,88 @@
|
|||||||
android:background="@color/colorBackground"
|
android:background="@color/colorBackground"
|
||||||
tools:context=".NovaReservaActivity">
|
tools:context=".NovaReservaActivity">
|
||||||
|
|
||||||
|
<!-- Header Section -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnVoltar"
|
android:id="@+id/btnVoltar"
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
style="@style/Widget.Material3.Button.IconButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="48dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="← Voltar"
|
app:icon="@android:drawable/ic_menu_revert"
|
||||||
android:textAllCaps="false"
|
app:iconTint="@color/colorTextPrimary"
|
||||||
android:textColor="@color/colorTextSecondary"
|
|
||||||
android:textSize="16sp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtTituloNovaReserva"
|
android:id="@+id/txtTituloNovaReserva"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
android:text="Nova reserva"
|
android:text="Nova reserva"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textColor="@color/colorTextPrimary"
|
||||||
android:textSize="28sp"
|
android:textSize="28sp"
|
||||||
android:fontFamily="sans-serif-medium"
|
android:textStyle="bold"
|
||||||
app:layout_constraintTop_toBottomOf="@id/btnVoltar"
|
android:fontFamily="sans-serif"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/btnVoltar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/btnVoltar"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/btnVoltar"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<!-- Loading Spinner -->
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/colorPrimary"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
android:layout_marginTop="20dp" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvCategories"
|
android:id="@+id/rvCategories"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="16dp"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="16dp"
|
android:paddingBottom="16dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/txtTituloNovaReserva"
|
app:layout_constraintTop_toBottomOf="@id/btnVoltar"
|
||||||
tools:listitem="@layout/item_food_category" />
|
tools:listitem="@layout/item_food_category" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvRestaurants"
|
android:id="@+id/rvRestaurants"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="16dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="16dp"
|
android:paddingBottom="16dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/txtTituloNovaReserva"
|
app:layout_constraintTop_toBottomOf="@id/btnVoltar"
|
||||||
tools:listitem="@layout/item_restaurant" />
|
tools:listitem="@layout/item_restaurant" />
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:id="@+id/scrollNovaReserva"
|
android:id="@+id/scrollNovaReserva"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="16dp"
|
||||||
android:fillViewport="true"
|
android:fillViewport="true"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:scrollbars="none"
|
android:scrollbars="none"
|
||||||
|
android:background="@color/colorBackground"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/txtTituloNovaReserva">
|
app:layout_constraintTop_toBottomOf="@id/btnVoltar">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -87,8 +102,9 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="24dp"
|
android:layout_marginHorizontal="24dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
app:cardCornerRadius="20dp"
|
app:cardCornerRadius="24dp"
|
||||||
app:cardElevation="2dp"
|
app:cardElevation="4dp"
|
||||||
|
app:strokeWidth="0dp"
|
||||||
app:cardBackgroundColor="@color/colorSurface">
|
app:cardBackgroundColor="@color/colorSurface">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -100,62 +116,69 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Data da reserva"
|
android:text="Detalhes da Reserva"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textColor="@color/colorTextPrimary"
|
||||||
android:textSize="16sp"
|
android:textSize="20sp"
|
||||||
android:fontFamily="sans-serif-medium" />
|
android:textStyle="bold"
|
||||||
|
android:layout_marginBottom="24dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Data da reserva"
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnSelectDate"
|
android:id="@+id/btnSelectDate"
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="54dp"
|
android:layout_height="56dp"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="8dp"
|
||||||
app:cornerRadius="12dp"
|
app:cornerRadius="12dp"
|
||||||
android:text="Selecionar Data"
|
android:text="Selecionar Data"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textSize="16sp"
|
android:textColor="@color/colorTextPrimary"
|
||||||
android:textColor="@color/colorTextSecondary" />
|
app:strokeColor="@color/colorDivider" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="20dp"
|
||||||
android:text="Hora da reserva"
|
android:text="Hora da reserva"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textColor="@color/colorTextSecondary"
|
||||||
android:textSize="16sp"
|
android:textSize="14sp" />
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnSelectTime"
|
android:id="@+id/btnSelectTime"
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="54dp"
|
android:layout_height="56dp"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="8dp"
|
||||||
app:cornerRadius="12dp"
|
app:cornerRadius="12dp"
|
||||||
android:text="Selecionar Hora"
|
android:text="Selecionar Hora"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textSize="16sp"
|
android:textColor="@color/colorTextPrimary"
|
||||||
android:textColor="@color/colorTextSecondary" />
|
app:strokeColor="@color/colorDivider" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="20dp"
|
||||||
android:text="Número de pessoas"
|
android:text="Número de pessoas"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:textColor="@color/colorTextSecondary"
|
||||||
android:textSize="16sp"
|
android:textSize="14sp" />
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/etPartySize"
|
android:id="@+id/etPartySize"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="54dp"
|
android:layout_height="56dp"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="8dp"
|
||||||
android:background="@drawable/input_bg"
|
android:background="@drawable/bg_input_modern"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
android:hint="Ex: 2"
|
android:hint="Ex: 2"
|
||||||
|
android:textColorHint="@color/colorTextHint"
|
||||||
android:textColor="@color/colorTextPrimary" />
|
android:textColor="@color/colorTextPrimary" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -164,15 +187,16 @@
|
|||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnConfirmarReserva"
|
android:id="@+id/btnConfirmarReserva"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="56dp"
|
android:layout_height="60dp"
|
||||||
android:layout_marginHorizontal="24dp"
|
android:layout_marginHorizontal="24dp"
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="32dp"
|
||||||
app:cornerRadius="14dp"
|
app:cornerRadius="16dp"
|
||||||
app:backgroundTint="@color/colorPrimary"
|
app:backgroundTint="@color/colorPrimary"
|
||||||
android:text="Confirmar Reserva"
|
android:text="Confirmar Reserva"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="16sp" />
|
android:textStyle="bold"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -3,13 +3,12 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="20dp"
|
||||||
android:layout_marginVertical="8dp"
|
android:layout_marginVertical="8dp"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="20dp"
|
||||||
app:cardElevation="4dp"
|
app:cardElevation="2dp"
|
||||||
app:cardBackgroundColor="@color/colorSurface"
|
app:cardBackgroundColor="@color/colorSurface"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="0dp">
|
||||||
app:strokeColor="@color/colorDivider">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -17,59 +16,91 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="20dp">
|
android:padding="20dp">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/txtReservaRestaurante"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Nome do Restaurante"
|
android:orientation="horizontal"
|
||||||
android:textColor="@color/colorTextPrimary"
|
android:gravity="center_vertical">
|
||||||
android:textSize="18sp"
|
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtReservaDataHora"
|
android:id="@+id/txtReservaRestaurante"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Nome do Restaurante"
|
||||||
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:fontFamily="sans-serif" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/chipReservaStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Pendente"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/colorChipPendingText"
|
||||||
|
app:chipBackgroundColor="@color/colorChipPending"
|
||||||
|
app:chipStrokeWidth="0dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:orientation="horizontal"
|
||||||
android:text="Hoje às 20:00"
|
android:layout_marginTop="8dp"
|
||||||
android:textColor="@color/colorTextSecondary"
|
android:gravity="center_vertical">
|
||||||
android:textSize="14sp" />
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:src="@android:drawable/ic_menu_recent_history"
|
||||||
|
app:tint="@color/colorTextSecondary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtReservaDataHora"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:text="Hoje às 20:00"
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtReservaStatus"
|
android:id="@+id/txtReservaStatus"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:visibility="gone"
|
||||||
android:text="Estado: Pendente"
|
android:text="Pendente" /> <!-- Kept for backward compatibility if needed in adapter -->
|
||||||
android:textSize="14sp"
|
|
||||||
android:textColor="@color/colorSecondary"
|
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="20dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnCheckIn"
|
android:id="@+id/btnCheckIn"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="50dp"
|
android:layout_height="52dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginEnd="6dp"
|
android:layout_marginEnd="8dp"
|
||||||
app:cornerRadius="12dp"
|
app:cornerRadius="12dp"
|
||||||
app:backgroundTint="@color/colorPrimary"
|
app:backgroundTint="@color/colorPrimary"
|
||||||
android:text="Check-in"
|
android:text="Check-in"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
|
android:textStyle="bold"
|
||||||
android:textColor="@color/white" />
|
android:textColor="@color/white" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btnCancelar"
|
android:id="@+id/btnCancelar"
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="50dp"
|
android:layout_height="52dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginStart="6dp"
|
android:layout_marginStart="8dp"
|
||||||
app:cornerRadius="12dp"
|
app:cornerRadius="12dp"
|
||||||
app:strokeColor="@color/colorError"
|
app:strokeColor="@color/colorError"
|
||||||
android:text="Cancelar"
|
android:text="Cancelar"
|
||||||
@@ -81,7 +112,7 @@
|
|||||||
android:id="@+id/txtLocationWarning"
|
android:id="@+id/txtLocationWarning"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="12dp"
|
||||||
android:text="Dê permissões de localização para aceder ao check-in."
|
android:text="Dê permissões de localização para aceder ao check-in."
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@color/colorWarning"
|
android:textColor="@color/colorWarning"
|
||||||
|
|||||||
@@ -3,66 +3,115 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="20dp"
|
||||||
android:layout_marginVertical="8dp"
|
android:layout_marginVertical="12dp"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="24dp"
|
||||||
app:cardElevation="2dp"
|
app:cardElevation="6dp"
|
||||||
app:cardBackgroundColor="@color/colorSurface"
|
app:cardBackgroundColor="@color/colorSurface"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="0dp">
|
||||||
app:strokeColor="@color/colorDivider">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<com.google.android.material.imageview.ShapeableImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/imgRestaurantThumb"
|
android:id="@+id/imgRestaurantThumb"
|
||||||
android:layout_width="60dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="180dp"
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@mipmap/ic_launcher"
|
android:src="@mipmap/ic_launcher"
|
||||||
app:shapeAppearanceOverlay="@style/ShapeAppearance.Material3.Corner.Medium" />
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
<LinearLayout
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_toEndOf="@id/imgRestaurantThumb"
|
|
||||||
android:layout_toStartOf="@id/btnFavorite"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtRestaurantName"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Restaurant Name"
|
|
||||||
android:textColor="@color/colorTextPrimary"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txtRestaurantCategory"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="Category"
|
|
||||||
android:textColor="@color/colorTextSecondary"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/btnFavorite"
|
android:id="@+id/btnFavorite"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_marginTop="12dp"
|
||||||
android:layout_centerVertical="true"
|
android:layout_marginEnd="12dp"
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
android:background="@drawable/bg_circle_white"
|
||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:src="@android:drawable/btn_star_big_off" />
|
android:src="@android:drawable/btn_star_big_off"
|
||||||
</RelativeLayout>
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:tint="@color/colorTextPrimary" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/bottomContent"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="20dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/imgRestaurantThumb"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtRestaurantName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Restaurant Name"
|
||||||
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
android:textSize="22sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:fontFamily="sans-serif" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtRestaurantCategory"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Category"
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text=" • "
|
||||||
|
android:textColor="@color/colorTextSecondary"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:src="@android:drawable/star_on"
|
||||||
|
app:tint="@color/colorWarning" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtRestaurantRating"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:text="N/A"
|
||||||
|
android:textColor="@color/colorTextPrimary"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- New Elegant Reserve Button -->
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnReservarCard"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="52dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
app:cornerRadius="12dp"
|
||||||
|
app:backgroundTint="@color/colorPrimary"
|
||||||
|
android:text="Reservar Mesa"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|||||||
@@ -1,23 +1,30 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Brand Colors -->
|
<!-- Brand Colors - Warm Premium Palette -->
|
||||||
<color name="colorPrimary">#06C167</color>
|
<color name="colorPrimary">#FF5A5F</color> <!-- Airbnb/UberEats Coral -->
|
||||||
<color name="colorPrimaryVariant">#05A357</color>
|
<color name="colorPrimaryVariant">#FF3B30</color>
|
||||||
<color name="colorSecondary">#06C167</color>
|
<color name="colorSecondary">#FF5A5F</color>
|
||||||
|
|
||||||
<!-- Neutral Colors -->
|
<!-- Neutral Colors -->
|
||||||
<color name="black">#FF000000</color>
|
<color name="black">#FF000000</color>
|
||||||
<color name="white">#FFFFFFFF</color>
|
<color name="white">#FFFFFFFF</color>
|
||||||
<color name="colorBackground">#F8FAFC</color>
|
<color name="colorBackground">#F7F7F9</color> <!-- Soft grey for modern background -->
|
||||||
<color name="colorSurface">#FFFFFF</color>
|
<color name="colorSurface">#FFFFFF</color>
|
||||||
<color name="colorTextPrimary">#1E293B</color>
|
<color name="colorTextPrimary">#1A1A1A</color> <!-- Dark but not pure black -->
|
||||||
<color name="colorTextSecondary">#64748B</color>
|
<color name="colorTextSecondary">#757575</color>
|
||||||
|
<color name="colorTextHint">#BDBDBD</color>
|
||||||
|
|
||||||
<!-- Semantic Colors -->
|
<!-- Semantic Colors -->
|
||||||
<color name="colorSuccess">#10B981</color>
|
<color name="colorSuccess">#34C759</color> <!-- iOS green -->
|
||||||
<color name="colorError">#EF4444</color>
|
<color name="colorError">#FF3B30</color>
|
||||||
<color name="colorWarning">#F59E0B</color>
|
<color name="colorWarning">#FFCC00</color>
|
||||||
<color name="colorDivider">#E2E8F0</color>
|
<color name="colorDivider">#E0E0E0</color>
|
||||||
|
<color name="colorChipPending">#FFE0B2</color>
|
||||||
|
<color name="colorChipPendingText">#E65100</color>
|
||||||
|
<color name="colorChipConfirmed">#C8E6C9</color>
|
||||||
|
<color name="colorChipConfirmedText">#1B5E20</color>
|
||||||
|
<color name="colorChipCancelled">#FFCDD2</color>
|
||||||
|
<color name="colorChipCancelledText">#B71C1C</color>
|
||||||
|
|
||||||
<!-- Legacy compatibility -->
|
<!-- Legacy compatibility -->
|
||||||
<color name="my_light_primary">#BE1F13</color>
|
<color name="my_light_primary">#BE1F13</color>
|
||||||
|
|||||||
Reference in New Issue
Block a user