..
This commit is contained in:
1
.idea/.name
generated
Normal file
1
.idea/.name
generated
Normal file
@@ -0,0 +1 @@
|
||||
Pap_teste
|
||||
@@ -98,16 +98,18 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca
|
||||
}
|
||||
|
||||
private boolean hasRequiredPermissions() {
|
||||
boolean fineLocation = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
||||
boolean fineLocation = ActivityCompat.checkSelfPermission(this,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
boolean btScan = ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED;
|
||||
boolean btScan = ActivityCompat.checkSelfPermission(this,
|
||||
Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED;
|
||||
return fineLocation && btScan;
|
||||
}
|
||||
return fineLocation;
|
||||
}
|
||||
|
||||
private void loadRestaurantSettings(String restaurantId) {
|
||||
databaseReference = FirebaseDatabase.getInstance().getReference().child("users").child(restaurantId);
|
||||
databaseReference = FirebaseDatabase.getInstance().getReference().child("Restaurantes").child(restaurantId);
|
||||
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
@@ -161,7 +163,8 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca
|
||||
}
|
||||
|
||||
private void startLocationUpdates() {
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
if (ActivityCompat.checkSelfPermission(this,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -44,11 +44,11 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
|
||||
private List<Restaurant> allRestaurants = new ArrayList<>();
|
||||
private List<Restaurant> filteredRestaurants = new ArrayList<>();
|
||||
|
||||
|
||||
private RestaurantAdapter mainAdapter;
|
||||
private FeaturedRestaurantAdapter featuredAdapter;
|
||||
|
||||
private final String[] CATEGORIES = {"Tudo", "Carnes", "Massas", "Sushi", "Pizzas", "Sobremesas"};
|
||||
private final String[] CATEGORIES = { "Tudo", "Carnes", "Massas", "Sushi", "Pizzas", "Sobremesas" };
|
||||
private String currentCategoryFilter = "Tudo";
|
||||
private String currentSearchFilter = "";
|
||||
|
||||
@@ -57,7 +57,7 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
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);
|
||||
@@ -71,7 +71,7 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
setupBottomNavigation();
|
||||
setupSearch();
|
||||
setupCategories();
|
||||
|
||||
|
||||
updateGreeting();
|
||||
fetchProfilePicture();
|
||||
fetchRestaurants();
|
||||
@@ -94,15 +94,17 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
// 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
|
||||
// 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);
|
||||
|
||||
@@ -146,14 +148,16 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void fetchProfilePicture() {
|
||||
if (email == null) return;
|
||||
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);
|
||||
}
|
||||
});
|
||||
FirebaseDatabase.getInstance().getReference().child("Clientes").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 fetchRestaurants() {
|
||||
@@ -161,7 +165,7 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
layoutFeatured.setVisibility(View.GONE);
|
||||
layoutAllRestaurants.setVisibility(View.GONE);
|
||||
|
||||
DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("users");
|
||||
DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("Restaurantes");
|
||||
usersRef.addListenerForSingleValueEvent(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@androidx.annotation.NonNull DataSnapshot snapshot) {
|
||||
@@ -171,20 +175,23 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||
String role = ds.child("role").getValue(String.class);
|
||||
String accountType = ds.child("accountType").getValue(String.class);
|
||||
|
||||
|
||||
if ("ADMIN".equalsIgnoreCase(role) || "ESTABELECIMENTO".equalsIgnoreCase(accountType)) {
|
||||
String name = ds.child("establishmentName").getValue(String.class);
|
||||
if (name == null) name = ds.child("displayName").getValue(String.class);
|
||||
if (name == null)
|
||||
name = ds.child("displayName").getValue(String.class);
|
||||
String email = ds.child("email").getValue(String.class);
|
||||
String cat = ds.child("category").getValue(String.class);
|
||||
String logoUrl = ds.child("logoUrl").getValue(String.class);
|
||||
Double ratingAvg = ds.child("ratingAvg").getValue(Double.class);
|
||||
Integer ratingCount = ds.child("ratingCount").getValue(Integer.class);
|
||||
|
||||
|
||||
if (name != null && email != null) {
|
||||
Restaurant r = new Restaurant(name, cat != null ? cat : "Vário", email, false, logoUrl);
|
||||
if (ratingAvg != null) r.setRatingAvg(ratingAvg);
|
||||
if (ratingCount != null) r.setRatingCount(ratingCount);
|
||||
if (ratingAvg != null)
|
||||
r.setRatingAvg(ratingAvg);
|
||||
if (ratingCount != null)
|
||||
r.setRatingCount(ratingCount);
|
||||
allRestaurants.add(r);
|
||||
}
|
||||
}
|
||||
@@ -209,13 +216,13 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
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
|
||||
@@ -228,7 +235,7 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
}
|
||||
chip.setChipBackgroundColorResource(R.color.colorPrimary);
|
||||
chip.setTextColor(getResources().getColor(R.color.white));
|
||||
|
||||
|
||||
currentCategoryFilter = category;
|
||||
applyFilters();
|
||||
} else if (currentCategoryFilter.equals(category)) {
|
||||
@@ -243,7 +250,8 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
private void setupSearch() {
|
||||
etSearch.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
@@ -252,47 +260,50 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {}
|
||||
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());
|
||||
|
||||
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);
|
||||
|
||||
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 "";
|
||||
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}+", "");
|
||||
|
||||
@@ -59,7 +59,7 @@ public class DefinicoesAdminActivity extends AppCompatActivity {
|
||||
documentId = email.replace(".", "_").replace("@", "_at_");
|
||||
}
|
||||
|
||||
databaseReference = FirebaseDatabase.getInstance().getReference().child("users");
|
||||
databaseReference = FirebaseDatabase.getInstance().getReference().child("Restaurantes");
|
||||
|
||||
inputRadius = findViewById(R.id.inputRadius);
|
||||
inputAddress = findViewById(R.id.inputAddress);
|
||||
|
||||
@@ -42,8 +42,13 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
||||
});
|
||||
|
||||
restaurantEmail = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL);
|
||||
if (restaurantEmail == null)
|
||||
restaurantEmail = "sabor_arte@restaurante.com";
|
||||
if (restaurantEmail == null) {
|
||||
if (com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null) {
|
||||
restaurantEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail();
|
||||
} else {
|
||||
restaurantEmail = "sabor_arte@restaurante.com";
|
||||
}
|
||||
}
|
||||
|
||||
bindViews();
|
||||
setupList();
|
||||
|
||||
@@ -46,27 +46,49 @@ public class EstablishmentDashboardActivity extends AppCompatActivity {
|
||||
Button btnSettings = findViewById(R.id.btnDefinicoes);
|
||||
Button btnBack = findViewById(R.id.btnVoltar);
|
||||
|
||||
btnOpenWalkIns.setOnClickListener(v -> startActivity(new Intent(this, ListaEsperaActivity.class)));
|
||||
String email = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL);
|
||||
if (email == null) {
|
||||
if (com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null) {
|
||||
email = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail();
|
||||
} else {
|
||||
return; // Can't proceed without email
|
||||
}
|
||||
}
|
||||
final String finalEmail = email;
|
||||
|
||||
btnStaff.setOnClickListener(v -> startActivity(new Intent(this, GestaoStaffActivity.class)));
|
||||
btnOpenWalkIns.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(this, ListaEsperaActivity.class);
|
||||
intent.putExtra(MainActivity.EXTRA_EMAIL, finalEmail);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
btnGerirMesas.setOnClickListener(v -> startActivity(new Intent(this, GerirMesasActivity.class)));
|
||||
btnStaff.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(this, GestaoStaffActivity.class);
|
||||
intent.putExtra(MainActivity.EXTRA_EMAIL, finalEmail);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
btnGerirMesas.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(this, GerirMesasActivity.class);
|
||||
intent.putExtra(MainActivity.EXTRA_EMAIL, finalEmail);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
btnDetails.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(this, DetalhesReservasActivity.class);
|
||||
intent.putExtra(MainActivity.EXTRA_EMAIL, getIntent().getStringExtra(MainActivity.EXTRA_EMAIL));
|
||||
intent.putExtra(MainActivity.EXTRA_EMAIL, finalEmail);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
btnSettings.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(this, DefinicoesAdminActivity.class);
|
||||
intent.putExtra(MainActivity.EXTRA_EMAIL, getIntent().getStringExtra(MainActivity.EXTRA_EMAIL));
|
||||
intent.putExtra(MainActivity.EXTRA_EMAIL, finalEmail);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
findViewById(R.id.cardReservasHoje).setOnClickListener(v -> {
|
||||
Intent intent = new Intent(this, DetalhesReservasActivity.class);
|
||||
intent.putExtra(MainActivity.EXTRA_EMAIL, getIntent().getStringExtra(MainActivity.EXTRA_EMAIL));
|
||||
intent.putExtra(MainActivity.EXTRA_EMAIL, finalEmail);
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -89,23 +88,26 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void loadRestaurantRating() {
|
||||
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||
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")
|
||||
|
||||
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("Restaurantes")
|
||||
.child(encodedEmail)
|
||||
.addValueEventListener(new com.google.firebase.database.ValueEventListener() {
|
||||
@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) {
|
||||
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));
|
||||
txtTotalReviews
|
||||
.setText(String.format(java.util.Locale.getDefault(), "(%d avaliações)", count));
|
||||
} else {
|
||||
txtAvgRating.setText("0.0");
|
||||
txtTotalReviews.setText("(0 avaliações)");
|
||||
@@ -113,44 +115,51 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
@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) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupRestaurantList() {
|
||||
String filter = getIntent().getStringExtra("category_filter");
|
||||
java.util.List<com.example.pap_teste.models.Restaurant> restaurantsList = 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("Restaurantes");
|
||||
|
||||
com.google.firebase.database.Query query = usersRef;
|
||||
if (filter != null) {
|
||||
query = usersRef.orderByChild("category").equalTo(filter);
|
||||
}
|
||||
|
||||
if (progressBar != null) progressBar.setVisibility(android.view.View.VISIBLE);
|
||||
if (progressBar != null)
|
||||
progressBar.setVisibility(android.view.View.VISIBLE);
|
||||
|
||||
query.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||
if (progressBar != null)
|
||||
progressBar.setVisibility(android.view.View.GONE);
|
||||
restaurantsList.clear();
|
||||
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
||||
String role = ds.child("role").getValue(String.class);
|
||||
String accountType = ds.child("accountType").getValue(String.class);
|
||||
|
||||
|
||||
if ("ADMIN".equalsIgnoreCase(role) || "ESTABELECIMENTO".equalsIgnoreCase(accountType)) {
|
||||
String name = ds.child("establishmentName").getValue(String.class);
|
||||
if (name == null) name = ds.child("displayName").getValue(String.class);
|
||||
if (name == null)
|
||||
name = ds.child("displayName").getValue(String.class);
|
||||
String email = ds.child("email").getValue(String.class);
|
||||
String cat = ds.child("category").getValue(String.class);
|
||||
String logoUrl = ds.child("logoUrl").getValue(String.class);
|
||||
|
||||
|
||||
if (name != null && email != null) {
|
||||
restaurantsList.add(new com.example.pap_teste.models.Restaurant(name, cat, email, false, logoUrl));
|
||||
restaurantsList
|
||||
.add(new com.example.pap_teste.models.Restaurant(name, cat, email, false, logoUrl));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RestaurantAdapter adapter = new RestaurantAdapter(restaurantsList, restaurant -> {
|
||||
selectedRestaurant = restaurant;
|
||||
currentState = State.DETAILS;
|
||||
@@ -161,8 +170,10 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
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();
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -178,7 +189,8 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
new android.app.DatePickerDialog(this, (view, year, month, dayOfMonth) -> {
|
||||
selectedDate = dayOfMonth + "/" + (month + 1) + "/" + year;
|
||||
btnDate.setText(selectedDate);
|
||||
}, cal.get(java.util.Calendar.YEAR), cal.get(java.util.Calendar.MONTH), cal.get(java.util.Calendar.DAY_OF_MONTH)).show();
|
||||
}, cal.get(java.util.Calendar.YEAR), cal.get(java.util.Calendar.MONTH),
|
||||
cal.get(java.util.Calendar.DAY_OF_MONTH)).show();
|
||||
});
|
||||
|
||||
btnTime.setOnClickListener(v -> {
|
||||
@@ -201,9 +213,11 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void uploadRestaurantPhoto(android.net.Uri imageUri) {
|
||||
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null)
|
||||
return;
|
||||
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||
com.google.firebase.storage.StorageReference storageRef = com.google.firebase.storage.FirebaseStorage.getInstance().getReference()
|
||||
com.google.firebase.storage.StorageReference storageRef = com.google.firebase.storage.FirebaseStorage
|
||||
.getInstance().getReference()
|
||||
.child("restaurant_photos/" + encodedEmail + "/" + java.util.UUID.randomUUID().toString());
|
||||
|
||||
storageRef.putFile(imageUri).addOnSuccessListener(taskSnapshot -> {
|
||||
@@ -212,17 +226,20 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("photos").child(encodedEmail)
|
||||
.push().child("url").setValue(photoUrl).addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful()) {
|
||||
android.widget.Toast.makeText(this, "Foto adicionada com sucesso!", android.widget.Toast.LENGTH_SHORT).show();
|
||||
android.widget.Toast.makeText(this, "Foto adicionada com sucesso!",
|
||||
android.widget.Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
});
|
||||
}).addOnFailureListener(e -> {
|
||||
android.widget.Toast.makeText(this, "Falha no upload: " + e.getMessage(), android.widget.Toast.LENGTH_LONG).show();
|
||||
android.widget.Toast.makeText(this, "Falha no upload: " + e.getMessage(), android.widget.Toast.LENGTH_LONG)
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
private void showReviewsDialog() {
|
||||
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null)
|
||||
return;
|
||||
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||
|
||||
android.view.View dialogView = getLayoutInflater().inflate(R.layout.dialog_reviews_list, null);
|
||||
@@ -244,11 +261,13 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
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);
|
||||
|
||||
String currentUserEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null ?
|
||||
com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail() : null;
|
||||
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
|
||||
@@ -259,8 +278,9 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
String text = dst.child("text").getValue(String.class);
|
||||
String uEmail = dst.child("userEmail").getValue(String.class);
|
||||
Float rating = dst.child("rating").getValue(Float.class);
|
||||
|
||||
if (rating == null) rating = 0f;
|
||||
|
||||
if (rating == null)
|
||||
rating = 0f;
|
||||
|
||||
com.example.pap_teste.models.Review rev = new com.example.pap_teste.models.Review(
|
||||
dst.getKey(), author, text, rating, uEmail);
|
||||
@@ -292,7 +312,8 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -300,14 +321,17 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void deleteReview(String reviewKey) {
|
||||
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||
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()
|
||||
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();
|
||||
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);
|
||||
});
|
||||
}
|
||||
@@ -316,7 +340,8 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
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) {
|
||||
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()) {
|
||||
@@ -326,27 +351,31 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
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")
|
||||
|
||||
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("Restaurantes")
|
||||
.child(encodedEmail).updateChildren(updates);
|
||||
}
|
||||
|
||||
@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) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addReviewDialog() {
|
||||
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null)
|
||||
return;
|
||||
|
||||
android.view.View dialogView = getLayoutInflater().inflate(R.layout.dialog_leave_review, null);
|
||||
com.example.pap_teste.components.InteractiveRatingBar ratingBar = dialogView.findViewById(R.id.interactiveRatingBar);
|
||||
com.example.pap_teste.components.InteractiveRatingBar ratingBar = dialogView
|
||||
.findViewById(R.id.interactiveRatingBar);
|
||||
android.widget.EditText input = dialogView.findViewById(R.id.etReviewComment);
|
||||
android.widget.Button btnSubmit = dialogView.findViewById(R.id.btnSubmitReview);
|
||||
android.widget.Button btnCancel = dialogView.findViewById(R.id.btnCancelReview);
|
||||
@@ -356,7 +385,8 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
|
||||
input.addTextChangedListener(new android.text.TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
@@ -366,33 +396,37 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(android.text.Editable s) {}
|
||||
public void afterTextChanged(android.text.Editable s) {
|
||||
}
|
||||
});
|
||||
|
||||
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();
|
||||
|
||||
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();
|
||||
});
|
||||
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("Clientes").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();
|
||||
@@ -404,10 +438,11 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
|
||||
private void submitReviewToFirebase(String authorName, String revText, float newRating) {
|
||||
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||
|
||||
com.google.firebase.auth.FirebaseUser currentUser = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
|
||||
|
||||
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<>();
|
||||
review.put("author", authorName);
|
||||
@@ -419,32 +454,39 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reviews")
|
||||
.child(encodedEmail).push().setValue(review).addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful()) {
|
||||
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();
|
||||
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);
|
||||
com.google.firebase.database.DatabaseReference restRef = com.google.firebase.database.FirebaseDatabase
|
||||
.getInstance().getReference("Restaurantes").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;
|
||||
|
||||
|
||||
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) {}
|
||||
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -453,7 +495,8 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
||||
int partySize = 0;
|
||||
try {
|
||||
partySize = Integer.parseInt(etPartySize.getText().toString());
|
||||
} catch (Exception e) {}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
if (selectedDate == null || selectedTime == null || partySize == 0) {
|
||||
android.widget.Toast.makeText(this, "Por favor, selecione data, hora e número de pessoas.",
|
||||
|
||||
@@ -51,7 +51,7 @@ public class FavoritosActivity extends AppCompatActivity {
|
||||
rv = findViewById(R.id.rvFavoritos);
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
emptyState = findViewById(R.id.emptyState);
|
||||
|
||||
|
||||
list = new ArrayList<>();
|
||||
adapter = new RestaurantAdapter(list, restaurant -> {
|
||||
android.content.Intent intent = new android.content.Intent(this, ExplorarRestaurantesActivity.class);
|
||||
@@ -67,13 +67,14 @@ public class FavoritosActivity extends AppCompatActivity {
|
||||
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||
if (user != null && user.getEmail() != null) {
|
||||
String encodedUserEmail = user.getEmail().replace(".", "_").replace("@", "_at_");
|
||||
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("users")
|
||||
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("Clientes")
|
||||
.child(encodedUserEmail).child("favorites");
|
||||
|
||||
favRef.addValueEventListener(new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||
if (progressBar != null)
|
||||
progressBar.setVisibility(android.view.View.GONE);
|
||||
list.clear();
|
||||
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||
Restaurant restaurant = ds.getValue(Restaurant.class);
|
||||
@@ -82,7 +83,7 @@ public class FavoritosActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
|
||||
if (emptyState != null) {
|
||||
emptyState.setVisibility(list.isEmpty() ? android.view.View.VISIBLE : android.view.View.GONE);
|
||||
}
|
||||
@@ -90,7 +91,8 @@ public class FavoritosActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
if (progressBar != null) progressBar.setVisibility(android.view.View.GONE);
|
||||
if (progressBar != null)
|
||||
progressBar.setVisibility(android.view.View.GONE);
|
||||
Toast.makeText(FavoritosActivity.this, "Erro ao carregar favoritos.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -24,7 +24,8 @@ public class FeaturedRestaurantAdapter extends RecyclerView.Adapter<FeaturedRest
|
||||
private List<Restaurant> restaurants;
|
||||
private RestaurantAdapter.OnRestaurantClickListener listener;
|
||||
|
||||
public FeaturedRestaurantAdapter(List<Restaurant> restaurants, RestaurantAdapter.OnRestaurantClickListener listener) {
|
||||
public FeaturedRestaurantAdapter(List<Restaurant> restaurants,
|
||||
RestaurantAdapter.OnRestaurantClickListener listener) {
|
||||
this.restaurants = restaurants;
|
||||
this.listener = listener;
|
||||
}
|
||||
@@ -41,15 +42,16 @@ public class FeaturedRestaurantAdapter extends RecyclerView.Adapter<FeaturedRest
|
||||
Restaurant restaurant = restaurants.get(position);
|
||||
holder.txtName.setText(restaurant.getName());
|
||||
holder.txtCategory.setText("• " + restaurant.getCategory());
|
||||
|
||||
|
||||
if (holder.txtRating != null) {
|
||||
if (restaurant.getRatingAvg() != null && restaurant.getRatingAvg() > 0) {
|
||||
holder.txtRating.setText(String.format(java.util.Locale.getDefault(), "%.1f", restaurant.getRatingAvg()));
|
||||
holder.txtRating
|
||||
.setText(String.format(java.util.Locale.getDefault(), "%.1f", restaurant.getRatingAvg()));
|
||||
} else {
|
||||
holder.txtRating.setText("Novo");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (restaurant.getLogoUrl() != null && !restaurant.getLogoUrl().isEmpty()) {
|
||||
com.bumptech.glide.Glide.with(holder.itemView.getContext())
|
||||
.load(restaurant.getLogoUrl())
|
||||
@@ -58,7 +60,7 @@ public class FeaturedRestaurantAdapter extends RecyclerView.Adapter<FeaturedRest
|
||||
} else {
|
||||
holder.imgCover.setImageResource(R.mipmap.ic_launcher);
|
||||
}
|
||||
|
||||
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (listener != null) {
|
||||
listener.onRestaurantClick(restaurant);
|
||||
@@ -70,7 +72,7 @@ public class FeaturedRestaurantAdapter extends RecyclerView.Adapter<FeaturedRest
|
||||
if (user != null && user.getEmail() != null && restaurant.getEmail() != null) {
|
||||
String encodedUserEmail = user.getEmail().replace(".", "_").replace("@", "_at_");
|
||||
String encodedRestEmail = restaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("users")
|
||||
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("Clientes")
|
||||
.child(encodedUserEmail).child("favorites").child(encodedRestEmail);
|
||||
|
||||
// Read initial state
|
||||
@@ -80,7 +82,8 @@ public class FeaturedRestaurantAdapter extends RecyclerView.Adapter<FeaturedRest
|
||||
holder.btnFavorite.setTag(snapshot.exists());
|
||||
if (snapshot.exists()) {
|
||||
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_on);
|
||||
holder.btnFavorite.setColorFilter(androidx.core.content.ContextCompat.getColor(holder.itemView.getContext(), R.color.colorPrimary));
|
||||
holder.btnFavorite.setColorFilter(androidx.core.content.ContextCompat
|
||||
.getColor(holder.itemView.getContext(), R.color.colorPrimary));
|
||||
} else {
|
||||
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_off);
|
||||
holder.btnFavorite.clearColorFilter();
|
||||
@@ -88,7 +91,8 @@ public class FeaturedRestaurantAdapter extends RecyclerView.Adapter<FeaturedRest
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) { }
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
}
|
||||
});
|
||||
|
||||
holder.btnFavorite.setOnClickListener(v -> {
|
||||
@@ -96,17 +100,20 @@ public class FeaturedRestaurantAdapter extends RecyclerView.Adapter<FeaturedRest
|
||||
boolean isFav = holder.btnFavorite.getTag() != null && (Boolean) holder.btnFavorite.getTag();
|
||||
boolean newFavState = !isFav;
|
||||
holder.btnFavorite.setTag(newFavState);
|
||||
|
||||
|
||||
if (newFavState) {
|
||||
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_on);
|
||||
holder.btnFavorite.setColorFilter(androidx.core.content.ContextCompat.getColor(holder.itemView.getContext(), R.color.colorPrimary));
|
||||
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();
|
||||
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();
|
||||
com.google.android.material.snackbar.Snackbar.make(v, "Removido dos Favoritos.",
|
||||
com.google.android.material.snackbar.Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -122,6 +129,7 @@ public class FeaturedRestaurantAdapter extends RecyclerView.Adapter<FeaturedRest
|
||||
TextView txtName, txtCategory, txtRating;
|
||||
ImageView imgCover;
|
||||
android.widget.ImageButton btnFavorite;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
txtName = itemView.findViewById(R.id.txtFeaturedName);
|
||||
|
||||
@@ -49,11 +49,10 @@ public class ListaEsperaActivity extends AppCompatActivity {
|
||||
|
||||
restaurantEmail = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL);
|
||||
if (restaurantEmail == null) {
|
||||
// Se o extra não chegou, falha segura
|
||||
if (com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null) {
|
||||
restaurantEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail();
|
||||
} else {
|
||||
restaurantEmail = "sabor_arte@restaurante.com";
|
||||
restaurantEmail = ""; // Avoid hardcoded sabor_arte so we don't accidentally load wrong data
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,29 +110,55 @@ public class MainActivity extends AppCompatActivity {
|
||||
setupActionToggle();
|
||||
setupPrimaryAction();
|
||||
checkPermissions();
|
||||
migrateUsersNodeToSeparateCollections();
|
||||
}
|
||||
|
||||
private void migrateUsersNodeToSeparateCollections() {
|
||||
if (databaseReference == null) return;
|
||||
databaseReference.child("users").get().addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful() && task.getResult() != null && task.getResult().exists()) {
|
||||
for (DataSnapshot userSnapshot : task.getResult().getChildren()) {
|
||||
String accountType = userSnapshot.child("accountType").getValue(String.class);
|
||||
String role = userSnapshot.child("role").getValue(String.class);
|
||||
|
||||
String targetCollection = "Clientes";
|
||||
if ("ESTABELECIMENTO".equalsIgnoreCase(accountType) || "ADMIN".equalsIgnoreCase(role)) {
|
||||
targetCollection = "Restaurantes";
|
||||
}
|
||||
|
||||
databaseReference.child(targetCollection).child(userSnapshot.getKey())
|
||||
.setValue(userSnapshot.getValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void checkPermissions() {
|
||||
List<String> permissionsNeeded = new ArrayList<>();
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
if (ContextCompat.checkSelfPermission(this,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
|
||||
}
|
||||
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
|
||||
if (ContextCompat.checkSelfPermission(this,
|
||||
Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH_SCAN);
|
||||
}
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
||||
if (ContextCompat.checkSelfPermission(this,
|
||||
Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.BLUETOOTH_CONNECT);
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
|
||||
if (ContextCompat.checkSelfPermission(this,
|
||||
Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.READ_MEDIA_IMAGES);
|
||||
}
|
||||
} else {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
if (ContextCompat.checkSelfPermission(this,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
permissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||
}
|
||||
}
|
||||
@@ -140,7 +166,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
if (!permissionsNeeded.isEmpty()) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("Permissões Necessárias")
|
||||
.setMessage("Para o correto funcionamento do check-in, serviços de proximidade e fotos da galeria, precisamos de algumas permissões.")
|
||||
.setMessage(
|
||||
"Para o correto funcionamento do check-in, serviços de proximidade e fotos da galeria, precisamos de algumas permissões.")
|
||||
.setPositiveButton("Configurar", (dialog, which) -> {
|
||||
permissionRequest.launch(permissionsNeeded.toArray(new String[0]));
|
||||
})
|
||||
@@ -164,47 +191,52 @@ public class MainActivity extends AppCompatActivity {
|
||||
inputEstablishmentPhone = findViewById(R.id.inputEstablishmentPhone);
|
||||
txtForgotPassword = findViewById(R.id.txtForgotPassword);
|
||||
iconPasswordVisibility = findViewById(R.id.iconPasswordVisibility);
|
||||
|
||||
|
||||
setupPasswordFeatures();
|
||||
}
|
||||
|
||||
|
||||
private void setupPasswordFeatures() {
|
||||
iconPasswordVisibility.setOnClickListener(v -> {
|
||||
isPasswordVisible = !isPasswordVisible;
|
||||
if (isPasswordVisible) {
|
||||
inputPassword.setInputType(android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
|
||||
inputPassword.setInputType(android.text.InputType.TYPE_CLASS_TEXT
|
||||
| android.text.InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
|
||||
iconPasswordVisibility.setImageResource(R.drawable.ic_visibility);
|
||||
} else {
|
||||
inputPassword.setInputType(android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
inputPassword.setInputType(
|
||||
android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
iconPasswordVisibility.setImageResource(R.drawable.ic_visibility_off);
|
||||
}
|
||||
inputPassword.setSelection(inputPassword.getText().length());
|
||||
});
|
||||
|
||||
|
||||
txtForgotPassword.setOnClickListener(v -> {
|
||||
String email = inputEmail.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(email)) {
|
||||
Toast.makeText(this, "Por favor, introduza o seu email primeiro.", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("Recuperar palavra-passe")
|
||||
.setMessage("Deseja enviar um email de recuperação para " + email + "?")
|
||||
.setPositiveButton("Sim", (dialog, which) -> {
|
||||
if (firebaseAuth != null) {
|
||||
firebaseAuth.sendPasswordResetEmail(email)
|
||||
.addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful()) {
|
||||
Toast.makeText(MainActivity.this, "Email de recuperação enviado!", Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(MainActivity.this, "Falha ao enviar email. Verifique se o endereço está correto.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.setNegativeButton("Não", null)
|
||||
.show();
|
||||
.setTitle("Recuperar palavra-passe")
|
||||
.setMessage("Deseja enviar um email de recuperação para " + email + "?")
|
||||
.setPositiveButton("Sim", (dialog, which) -> {
|
||||
if (firebaseAuth != null) {
|
||||
firebaseAuth.sendPasswordResetEmail(email)
|
||||
.addOnCompleteListener(task -> {
|
||||
if (task.isSuccessful()) {
|
||||
Toast.makeText(MainActivity.this, "Email de recuperação enviado!",
|
||||
Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(MainActivity.this,
|
||||
"Falha ao enviar email. Verifique se o endereço está correto.",
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.setNegativeButton("Não", null)
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -274,7 +306,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
inputEstablishmentName.setVisibility(creatingAccount && isEstablishment ? View.VISIBLE : View.GONE);
|
||||
inputEstablishmentEmail.setVisibility(creatingAccount && isEstablishment ? View.VISIBLE : View.GONE);
|
||||
inputEstablishmentPhone.setVisibility(creatingAccount && isEstablishment ? View.VISIBLE : View.GONE);
|
||||
|
||||
|
||||
if (txtForgotPassword != null) {
|
||||
txtForgotPassword.setVisibility(creatingAccount ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
@@ -439,33 +471,35 @@ public class MainActivity extends AppCompatActivity {
|
||||
private void fetchAccountAndNavigate(String email, String fallbackName, String resolvedRole) {
|
||||
if (databaseReference == null) {
|
||||
Toast.makeText(this, "Firebase indisponível.", Toast.LENGTH_SHORT).show();
|
||||
navigateToDashboard(email, fallbackName, resolvedRole);
|
||||
if (firebaseAuth != null) firebaseAuth.signOut();
|
||||
return;
|
||||
}
|
||||
|
||||
String documentId = buildDocumentId(email);
|
||||
databaseReference.child("users").child(documentId).get().addOnCompleteListener(task -> {
|
||||
String collectionPath = selectedAccountType == AccountType.ESTABELECIMENTO ? "Restaurantes" : "Clientes";
|
||||
databaseReference.child(collectionPath).child(documentId).get().addOnCompleteListener(task -> {
|
||||
if (!task.isSuccessful()) {
|
||||
android.util.Log.e("LoginError", "Database check failed", task.getException());
|
||||
Toast.makeText(this, "Falha ao validar perfil na cloud. A entrar em modo básico.", Toast.LENGTH_SHORT)
|
||||
Toast.makeText(this, "Falha ao validar perfil. Tente novamente.", Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
navigateToDashboard(email, fallbackName, resolvedRole);
|
||||
if (firebaseAuth != null) firebaseAuth.signOut();
|
||||
return;
|
||||
}
|
||||
|
||||
DataSnapshot snapshot = task.getResult();
|
||||
if (snapshot == null || !snapshot.exists()) {
|
||||
// Toast.makeText(this, "Conta sem perfil na cloud. A entrar em modo básico.",
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
navigateToDashboard(email, fallbackName, resolvedRole);
|
||||
String tipo = selectedAccountType == AccountType.ESTABELECIMENTO ? "Estabelecimento" : "Cliente";
|
||||
Toast.makeText(this, "Conta não encontrada como " + tipo + ".\nPor favor, crie uma conta nova.", Toast.LENGTH_LONG).show();
|
||||
if (firebaseAuth != null) firebaseAuth.signOut();
|
||||
return;
|
||||
}
|
||||
|
||||
String accountTypeInFirebase = snapshot.child("accountType").getValue(String.class);
|
||||
if (accountTypeInFirebase != null
|
||||
&& !accountTypeInFirebase.equalsIgnoreCase(selectedAccountType.name())) {
|
||||
Toast.makeText(this, "Tipo de conta não corresponde ao registo no Firebase.", Toast.LENGTH_SHORT)
|
||||
Toast.makeText(this, "Tipo de conta não corresponde ao registo.\nPor favor verifique se escolheu a opção correta.", Toast.LENGTH_LONG)
|
||||
.show();
|
||||
if (firebaseAuth != null) firebaseAuth.signOut();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -533,7 +567,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
payload.put("establishmentPhone", establishmentPhone);
|
||||
}
|
||||
|
||||
databaseReference.child("users").child(documentId).updateChildren(payload)
|
||||
String collectionPath = selectedAccountType == AccountType.ESTABELECIMENTO ? "Restaurantes" : "Clientes";
|
||||
databaseReference.child(collectionPath).child(documentId).updateChildren(payload)
|
||||
.addOnSuccessListener(unused -> {
|
||||
Toast.makeText(this, "Conta guardada na cloud.", Toast.LENGTH_SHORT).show();
|
||||
if (onSuccess != null) {
|
||||
|
||||
@@ -102,7 +102,7 @@ public class NovaReservaActivity extends AppCompatActivity {
|
||||
private void setupRestaurants() {
|
||||
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");
|
||||
.getInstance().getReference("Restaurantes");
|
||||
|
||||
if (progressBar != null)
|
||||
progressBar.setVisibility(android.view.View.VISIBLE);
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ProfileDashboardActivity extends AppCompatActivity {
|
||||
documentId = email.replace(".", "_").replace("@", "_at_");
|
||||
}
|
||||
|
||||
databaseReference = FirebaseDatabase.getInstance().getReference().child("users");
|
||||
databaseReference = FirebaseDatabase.getInstance().getReference().child("Clientes");
|
||||
|
||||
inputName = findViewById(R.id.inputProfileName);
|
||||
inputPhone = findViewById(R.id.inputProfilePhone);
|
||||
|
||||
@@ -45,16 +45,18 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Restaurant restaurant = restaurants.get(position);
|
||||
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()));
|
||||
holder.txtRating
|
||||
.setText(String.format(java.util.Locale.getDefault(), "%.1f", restaurant.getRatingAvg()));
|
||||
} else {
|
||||
holder.txtRating.setText("Novo");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (restaurant.getLogoUrl() != null && !restaurant.getLogoUrl().isEmpty()) {
|
||||
com.bumptech.glide.Glide.with(holder.itemView.getContext())
|
||||
.load(restaurant.getLogoUrl())
|
||||
@@ -63,7 +65,7 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
||||
} else {
|
||||
holder.imgThumb.setImageResource(R.mipmap.ic_launcher);
|
||||
}
|
||||
|
||||
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (listener != null) {
|
||||
listener.onRestaurantClick(restaurant);
|
||||
@@ -82,7 +84,7 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
||||
if (user != null && user.getEmail() != null && restaurant.getEmail() != null) {
|
||||
String encodedUserEmail = user.getEmail().replace(".", "_").replace("@", "_at_");
|
||||
String encodedRestEmail = restaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("users")
|
||||
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("Clientes")
|
||||
.child(encodedUserEmail).child("favorites").child(encodedRestEmail);
|
||||
|
||||
// Read initial state
|
||||
@@ -92,7 +94,8 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
||||
holder.btnFavorite.setTag(snapshot.exists());
|
||||
if (snapshot.exists()) {
|
||||
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_on);
|
||||
holder.btnFavorite.setColorFilter(androidx.core.content.ContextCompat.getColor(holder.itemView.getContext(), R.color.colorPrimary));
|
||||
holder.btnFavorite.setColorFilter(androidx.core.content.ContextCompat
|
||||
.getColor(holder.itemView.getContext(), R.color.colorPrimary));
|
||||
} else {
|
||||
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_off);
|
||||
holder.btnFavorite.clearColorFilter();
|
||||
@@ -100,7 +103,8 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(@NonNull DatabaseError error) { }
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
}
|
||||
});
|
||||
|
||||
holder.btnFavorite.setOnClickListener(v -> {
|
||||
@@ -108,17 +112,20 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
||||
boolean isFav = holder.btnFavorite.getTag() != null && (Boolean) holder.btnFavorite.getTag();
|
||||
boolean newFavState = !isFav;
|
||||
holder.btnFavorite.setTag(newFavState);
|
||||
|
||||
|
||||
if (newFavState) {
|
||||
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_on);
|
||||
holder.btnFavorite.setColorFilter(androidx.core.content.ContextCompat.getColor(holder.itemView.getContext(), R.color.colorPrimary));
|
||||
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();
|
||||
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();
|
||||
com.google.android.material.snackbar.Snackbar.make(v, "Removido dos Favoritos.",
|
||||
com.google.android.material.snackbar.Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -134,6 +141,7 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
||||
ImageButton btnFavorite;
|
||||
android.widget.ImageView imgThumb;
|
||||
Button btnReservar;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
text1 = itemView.findViewById(R.id.txtRestaurantName);
|
||||
|
||||
Reference in New Issue
Block a user