From cd5ffb3b43b1d9935db60345526a8d994e64e40f Mon Sep 17 00:00:00 2001 From: 230409 <230409@epvc.pt> Date: Wed, 29 Apr 2026 10:36:46 +0100 Subject: [PATCH] ... --- .../pap_teste/ClientDashboardActivity.java | 8 + .../pap_teste/NovaReservaActivity.java | 207 ++++++++++-------- .../pap_teste/ProfileDashboardActivity.java | 19 ++ .../res/layout/activity_profile_dashboard.xml | 14 ++ 4 files changed, 159 insertions(+), 89 deletions(-) diff --git a/app/src/main/java/com/example/pap_teste/ClientDashboardActivity.java b/app/src/main/java/com/example/pap_teste/ClientDashboardActivity.java index 81bae4e..c6f27b4 100644 --- a/app/src/main/java/com/example/pap_teste/ClientDashboardActivity.java +++ b/app/src/main/java/com/example/pap_teste/ClientDashboardActivity.java @@ -105,6 +105,14 @@ public class ClientDashboardActivity extends AppCompatActivity { rvFeatured.setAdapter(featuredAdapter); rvMainRestaurants.setAdapter(mainAdapter); + + // Click listener for profile picture in the header + findViewById(R.id.cardProfile).setOnClickListener(v -> { + Intent intent = new Intent(this, ProfileDashboardActivity.class); + intent.putExtra(MainActivity.EXTRA_EMAIL, email); + intent.putExtra(MainActivity.EXTRA_DISPLAY_NAME, displayName); + startActivity(intent); + }); } private void setupBottomNavigation() { diff --git a/app/src/main/java/com/example/pap_teste/NovaReservaActivity.java b/app/src/main/java/com/example/pap_teste/NovaReservaActivity.java index e58d341..5d58046 100644 --- a/app/src/main/java/com/example/pap_teste/NovaReservaActivity.java +++ b/app/src/main/java/com/example/pap_teste/NovaReservaActivity.java @@ -101,46 +101,57 @@ public class NovaReservaActivity extends AppCompatActivity { private void setupRestaurants() { java.util.List filteredList = new java.util.ArrayList<>(); - 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() { - @Override - public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) { - if (progressBar != null) progressBar.setVisibility(android.view.View.GONE); - filteredList.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); - 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) { - filteredList.add(new com.example.pap_teste.models.Restaurant(name, cat, email, false, logoUrl)); - } - } - } - - rvRestaurants.setLayoutManager(new androidx.recyclerview.widget.LinearLayoutManager(NovaReservaActivity.this)); - rvRestaurants.setAdapter(new RestaurantAdapter(filteredList, restaurant -> { - selectedRestaurant = restaurant; - currentState = State.DETAILS; - updateViewState(); - })); - } + com.google.firebase.database.DatabaseReference usersRef = com.google.firebase.database.FirebaseDatabase + .getInstance().getReference("users"); - @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(NovaReservaActivity.this, "Erro ao carregar restaurantes.", android.widget.Toast.LENGTH_SHORT).show(); - } - }); + if (progressBar != null) + progressBar.setVisibility(android.view.View.VISIBLE); + + usersRef.orderByChild("category").equalTo(selectedCategory) + .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); + filteredList.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); + 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) { + filteredList.add(new com.example.pap_teste.models.Restaurant(name, cat, email, + false, logoUrl)); + } + } + } + + rvRestaurants.setLayoutManager( + new androidx.recyclerview.widget.LinearLayoutManager(NovaReservaActivity.this)); + rvRestaurants.setAdapter(new RestaurantAdapter(filteredList, restaurant -> { + selectedRestaurant = restaurant; + currentState = State.DETAILS; + updateViewState(); + })); + } + + @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(NovaReservaActivity.this, "Erro ao carregar restaurantes.", + android.widget.Toast.LENGTH_SHORT).show(); + } + }); } private String selectedDate = null; @@ -155,7 +166,8 @@ public class NovaReservaActivity 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 -> { @@ -174,7 +186,8 @@ public class NovaReservaActivity extends AppCompatActivity { int val = 0; try { val = Integer.parseInt(etPartySize.getText().toString()); - } catch (Exception e) {} + } catch (Exception e) { + } final int partySize = val; if (selectedDate == null || selectedTime == null || partySize == 0) { @@ -185,12 +198,15 @@ public class NovaReservaActivity extends AppCompatActivity { String restEmail = selectedRestaurant.getEmail(); - if (progressBar != null) progressBar.setVisibility(android.view.View.VISIBLE); + if (progressBar != null) + progressBar.setVisibility(android.view.View.VISIBLE); android.widget.Button btnConfirmar = findViewById(R.id.btnConfirmarReserva); - if (btnConfirmar != null) btnConfirmar.setEnabled(false); + 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() { @Override public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) { @@ -219,51 +235,59 @@ public class NovaReservaActivity extends AppCompatActivity { private void checkReservationsAndSave(int totalMesas, final int partySize) { String restEmail = selectedRestaurant.getEmail(); - com.google.firebase.database.DatabaseReference reservasRef = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reservas"); + com.google.firebase.database.DatabaseReference reservasRef = com.google.firebase.database.FirebaseDatabase + .getInstance().getReference("reservas"); - reservasRef.orderByChild("restauranteEmail").equalTo(restEmail).addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() { - @Override - public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) { - int ocupadas = 0; - java.util.Map ocupacaoPorHora = new java.util.HashMap<>(); + reservasRef.orderByChild("restauranteEmail").equalTo(restEmail) + .addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() { + @Override + public void onDataChange( + @androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) { + int ocupadas = 0; + java.util.Map ocupacaoPorHora = new java.util.HashMap<>(); - 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 && selectedDate.equals(r.getData()) && !"Cancelada".equals(r.getEstado()) && !"Recusada".equals(r.getEstado())) { - int count = ocupacaoPorHora.getOrDefault(r.getHora(), 0) + 1; - ocupacaoPorHora.put(r.getHora(), count); - if (selectedTime.equals(r.getHora())) { - ocupadas++; + 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 && selectedDate.equals(r.getData()) && !"Cancelada".equals(r.getEstado()) + && !"Recusada".equals(r.getEstado())) { + int count = ocupacaoPorHora.getOrDefault(r.getHora(), 0) + 1; + ocupacaoPorHora.put(r.getHora(), count); + if (selectedTime.equals(r.getHora())) { + ocupadas++; + } + } + } + + if (ocupadas >= totalMesas) { + String sugestao = ""; + String[] horasComuns = { "12:00", "12:30", "13:00", "13:30", "14:00", "19:00", "19:30", + "20:00", "20:30", "21:00", "21:30", "22:00" }; + for (String h : horasComuns) { + if (ocupacaoPorHora.getOrDefault(h, 0) < totalMesas && !h.equals(selectedTime)) { + sugestao = h; + break; // Encontramos a primeira sugestão livre + } + } + String msg = "Não há mesas disponíveis para as " + selectedTime + "."; + if (!sugestao.isEmpty()) { + msg += " Sugestão: tente reservar para as " + sugestao + "."; + } else { + msg += " Tente para outro dia."; + } + android.widget.Toast + .makeText(NovaReservaActivity.this, msg, android.widget.Toast.LENGTH_LONG).show(); + } else { + proceedWithReservation(partySize); } } - } - if (ocupadas >= totalMesas) { - String sugestao = ""; - String[] horasComuns = {"12:00", "12:30", "13:00", "13:30", "14:00", "19:00", "19:30", "20:00", "20:30", "21:00", "21:30", "22:00"}; - for (String h : horasComuns) { - if (ocupacaoPorHora.getOrDefault(h, 0) < totalMesas && !h.equals(selectedTime)) { - sugestao = h; - break; // Encontramos a primeira sugestão livre - } + @Override + public void onCancelled( + @androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) { + proceedWithReservation(partySize); } - String msg = "Não há mesas disponíveis para as " + selectedTime + "."; - if (!sugestao.isEmpty()) { - msg += " Sugestão: tente reservar para as " + sugestao + "."; - } else { - msg += " Tente para outro dia."; - } - android.widget.Toast.makeText(NovaReservaActivity.this, msg, android.widget.Toast.LENGTH_LONG).show(); - } else { - proceedWithReservation(partySize); - } - } - - @Override - public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) { - proceedWithReservation(partySize); - } - }); + }); } private void proceedWithReservation(int partySize) { @@ -286,17 +310,22 @@ public class NovaReservaActivity extends AppCompatActivity { if (id != null) { ref.child(id).setValue(reserva).addOnCompleteListener(task -> { - if (progressBar != null) progressBar.setVisibility(android.view.View.GONE); + if (progressBar != null) + progressBar.setVisibility(android.view.View.GONE); android.widget.Button btnConfirmar = findViewById(R.id.btnConfirmarReserva); - if (btnConfirmar != null) btnConfirmar.setEnabled(true); - + if (btnConfirmar != null) + btnConfirmar.setEnabled(true); + if (task.isSuccessful()) { 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) .show(); finish(); } else { - android.widget.Toast.makeText(NovaReservaActivity.this, "Erro ao salvar reserva.", android.widget.Toast.LENGTH_SHORT) + android.widget.Toast + .makeText(NovaReservaActivity.this, "Erro ao salvar reserva.", + android.widget.Toast.LENGTH_SHORT) .show(); } }); diff --git a/app/src/main/java/com/example/pap_teste/ProfileDashboardActivity.java b/app/src/main/java/com/example/pap_teste/ProfileDashboardActivity.java index 8b4a96e..8d431b8 100644 --- a/app/src/main/java/com/example/pap_teste/ProfileDashboardActivity.java +++ b/app/src/main/java/com/example/pap_teste/ProfileDashboardActivity.java @@ -22,6 +22,7 @@ import com.google.firebase.storage.StorageReference; import java.util.UUID; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.auth.FirebaseAuth; import java.util.HashMap; import java.util.Map; @@ -99,9 +100,12 @@ public class ProfileDashboardActivity extends AppCompatActivity { Button btnBack = findViewById(R.id.btnVoltar); Button btnFavs = findViewById(R.id.btnFavoritos); Button btnRes = findViewById(R.id.btnMinhasReservas); + Button btnLogOut = findViewById(R.id.btnLogOut); btnBack.setOnClickListener(v -> finish()); btnSave.setOnClickListener(v -> saveProfile()); + + btnLogOut.setOnClickListener(v -> performLogOut()); btnFavs.setOnClickListener(v -> { startActivity(new Intent(this, FavoritosActivity.class)); @@ -112,6 +116,21 @@ public class ProfileDashboardActivity extends AppCompatActivity { }); } + private void performLogOut() { + try { + FirebaseAuth.getInstance().signOut(); + Toast.makeText(this, "Sessão terminada com sucesso.", Toast.LENGTH_SHORT).show(); + + Intent intent = new Intent(this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + finish(); + } catch (Exception e) { + Toast.makeText(this, "Erro ao terminar sessão: " + e.getMessage(), Toast.LENGTH_LONG).show(); + android.util.Log.e("LogOut", "Error during sign out", e); + } + } + private void showUrlInputDialog() { androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(this); builder.setTitle("Inserir URL da Imagem"); diff --git a/app/src/main/res/layout/activity_profile_dashboard.xml b/app/src/main/res/layout/activity_profile_dashboard.xml index 3b9dcbb..34e9eb2 100644 --- a/app/src/main/res/layout/activity_profile_dashboard.xml +++ b/app/src/main/res/layout/activity_profile_dashboard.xml @@ -186,6 +186,20 @@ app:cornerRadius="14dp" android:text="Histórico de Reservas" android:textAllCaps="false" + android:textSize="16sp" + android:layout_marginBottom="32dp" /> + + +