diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ed1e5f2..ad20d54 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -42,6 +42,8 @@ dependencies { implementation("com.google.firebase:firebase-firestore") implementation("com.google.firebase:firebase-auth") implementation(libs.firebase.database) + implementation(libs.glide) + implementation(libs.firebase.storage) testImplementation(libs.junit) androidTestImplementation(libs.ext.junit) androidTestImplementation(libs.espresso.core) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7cab3cb..4449370 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,11 @@ + + + + + + diff --git a/app/src/main/java/com/example/pap_teste/CheckInAntecipadoActivity.java b/app/src/main/java/com/example/pap_teste/CheckInAntecipadoActivity.java index 25f826c..982bb43 100644 --- a/app/src/main/java/com/example/pap_teste/CheckInAntecipadoActivity.java +++ b/app/src/main/java/com/example/pap_teste/CheckInAntecipadoActivity.java @@ -2,10 +2,12 @@ package com.example.pap_teste; import android.Manifest; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; +import android.os.Build; import android.os.Bundle; import android.widget.Button; import android.widget.TextView; @@ -25,16 +27,20 @@ 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.List; + public class CheckInAntecipadoActivity extends AppCompatActivity implements LocationListener { - private TextView txtDistancia, txtStatus; - private Button btnConfirmarChegada; + private TextView txtDistancia, txtStatus, txtEndereco; + private Button btnConfirmarChegada, btnAbrirMapa; private LocationManager locationManager; private DatabaseReference databaseReference; private double restaurantLat, restaurantLon; private int securityDistance = 500; // default 500m private boolean settingsLoaded = false; + private String restaurantAddress; @Override protected void onCreate(Bundle savedInstanceState) { @@ -49,7 +55,9 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca txtDistancia = findViewById(R.id.txtDistancia); txtStatus = findViewById(R.id.txtStatusDistancia); + txtEndereco = findViewById(R.id.txtEnderecoRestaurante); btnConfirmarChegada = findViewById(R.id.btnConfirmarChegada); + btnAbrirMapa = findViewById(R.id.btnAbrirMapa); Button back = findViewById(R.id.btnVoltar); if (back != null) { @@ -65,12 +73,37 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca } locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); - startLocationUpdates(); + if (hasRequiredPermissions()) { + startLocationUpdates(); + } else { + txtStatus.setText("Permissões em falta para localização/proximidade."); + } btnConfirmarChegada.setOnClickListener(v -> { Toast.makeText(this, "Chegada confirmada com sucesso!", Toast.LENGTH_LONG).show(); finish(); }); + + btnAbrirMapa.setOnClickListener(v -> { + if (restaurantAddress != null) { + try { + String uri = "geo:0,0?q=" + java.net.URLEncoder.encode(restaurantAddress, "UTF-8"); + Intent intent = new Intent(Intent.ACTION_VIEW, android.net.Uri.parse(uri)); + startActivity(intent); + } catch (Exception e) { + Toast.makeText(this, "Erro ao abrir mapa.", Toast.LENGTH_SHORT).show(); + } + } + }); + } + + private boolean hasRequiredPermissions() { + 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; + return fineLocation && btScan; + } + return fineLocation; } private void loadRestaurantSettings(String restaurantId) { @@ -79,17 +112,26 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if (snapshot.exists()) { - Double lat = snapshot.child("latitude").getValue(Double.class); - Double lon = snapshot.child("longitude").getValue(Double.class); + restaurantAddress = snapshot.child("address").getValue(String.class); Integer dist = snapshot.child("securityDistance").getValue(Integer.class); - - restaurantLat = lat != null ? lat : 0.0; - restaurantLon = lon != null ? lon : 0.0; securityDistance = dist != null ? dist : 500; - settingsLoaded = true; + + if (restaurantAddress != null) { + txtEndereco.setText("Morada: " + restaurantAddress); + geocodeAddress(restaurantAddress); + } else { + txtEndereco.setText("Morada não disponível."); + // Fallback to old lat/lon if they exist + Double lat = snapshot.child("latitude").getValue(Double.class); + Double lon = snapshot.child("longitude").getValue(Double.class); + if (lat != null && lon != null) { + restaurantLat = lat; + restaurantLon = lon; + settingsLoaded = true; + } + } } else { - txtStatus.setText("Aviso: Definições do restaurante não encontradas. Usando valores padrão."); - settingsLoaded = true; // Use defaults + txtStatus.setText("Aviso: Definições do restaurante não encontradas."); } } @@ -100,12 +142,26 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca }); } + private void geocodeAddress(String address) { + new Thread(() -> { + try { + android.location.Geocoder geocoder = new android.location.Geocoder(this); + List addresses = geocoder.getFromLocationName(address, 1); + if (addresses != null && !addresses.isEmpty()) { + restaurantLat = addresses.get(0).getLatitude(); + restaurantLon = addresses.get(0).getLongitude(); + settingsLoaded = true; + } else { + runOnUiThread(() -> txtStatus.setText("Erro: Não foi possível localizar a morada no mapa.")); + } + } catch (Exception e) { + runOnUiThread(() -> txtStatus.setText("Erro ao obter coordenadas da morada.")); + } + }).start(); + } + private void startLocationUpdates() { - if (ActivityCompat.checkSelfPermission(this, - Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && - ActivityCompat.checkSelfPermission(this, - Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - txtStatus.setText("Permissão de localização negada."); + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } try { @@ -143,7 +199,9 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca @Override protected void onStop() { super.onStop(); - locationManager.removeUpdates(this); + if (locationManager != null) { + locationManager.removeUpdates(this); + } } @Override 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 d4ff8a9..d371d00 100644 --- a/app/src/main/java/com/example/pap_teste/ClientDashboardActivity.java +++ b/app/src/main/java/com/example/pap_teste/ClientDashboardActivity.java @@ -99,5 +99,12 @@ public class ClientDashboardActivity extends AppCompatActivity { 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); + }); } } diff --git a/app/src/main/java/com/example/pap_teste/DefinicoesAdminActivity.java b/app/src/main/java/com/example/pap_teste/DefinicoesAdminActivity.java index 7acce4e..61c9584 100644 --- a/app/src/main/java/com/example/pap_teste/DefinicoesAdminActivity.java +++ b/app/src/main/java/com/example/pap_teste/DefinicoesAdminActivity.java @@ -24,9 +24,11 @@ import java.util.Map; public class DefinicoesAdminActivity extends AppCompatActivity { - private EditText inputRadius, inputLatitude, inputLongitude; + private EditText inputRadius, inputAddress; + private android.widget.Spinner spinnerCategory; private DatabaseReference databaseReference; private String documentId; + private String[] categories = {"Carnes", "Massas", "Sushi", "Pizzas", "Sobremesas"}; @Override protected void onCreate(Bundle savedInstanceState) { @@ -47,8 +49,14 @@ public class DefinicoesAdminActivity extends AppCompatActivity { databaseReference = FirebaseDatabase.getInstance().getReference().child("users"); inputRadius = findViewById(R.id.inputRadius); - inputLatitude = findViewById(R.id.inputLatitude); - inputLongitude = findViewById(R.id.inputLongitude); + inputAddress = findViewById(R.id.inputAddress); + spinnerCategory = findViewById(R.id.spinnerCategory); + + android.widget.ArrayAdapter adapter = new android.widget.ArrayAdapter<>(this, + android.R.layout.simple_spinner_item, categories); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinnerCategory.setAdapter(adapter); + Button btnSave = findViewById(R.id.btnSaveSettings); Button btnBack = findViewById(R.id.btnVoltar); @@ -73,13 +81,20 @@ public class DefinicoesAdminActivity extends AppCompatActivity { Object val = snapshot.child("securityDistance").getValue(); inputRadius.setText(val != null ? val.toString() : ""); } - if (snapshot.hasChild("latitude")) { - Object val = snapshot.child("latitude").getValue(); - inputLatitude.setText(val != null ? val.toString() : ""); + if (snapshot.hasChild("address")) { + String addr = snapshot.child("address").getValue(String.class); + inputAddress.setText(addr != null ? addr : ""); } - if (snapshot.hasChild("longitude")) { - Object val = snapshot.child("longitude").getValue(); - inputLongitude.setText(val != null ? val.toString() : ""); + if (snapshot.hasChild("category")) { + String cat = snapshot.child("category").getValue(String.class); + if (cat != null) { + for (int i = 0; i < categories.length; i++) { + if (categories[i].equalsIgnoreCase(cat)) { + spinnerCategory.setSelection(i); + break; + } + } + } } } } @@ -96,23 +111,21 @@ public class DefinicoesAdminActivity extends AppCompatActivity { return; String radiusStr = inputRadius.getText().toString().trim(); - String latStr = inputLatitude.getText().toString().trim(); - String lonStr = inputLongitude.getText().toString().trim(); + String addressStr = inputAddress.getText().toString().trim(); + String selectedCategory = spinnerCategory.getSelectedItem().toString(); - if (TextUtils.isEmpty(radiusStr) || TextUtils.isEmpty(latStr) || TextUtils.isEmpty(lonStr)) { + if (TextUtils.isEmpty(radiusStr) || TextUtils.isEmpty(addressStr)) { Toast.makeText(this, "Preencha todos os campos.", Toast.LENGTH_SHORT).show(); return; } try { int radius = Integer.parseInt(radiusStr); - double lat = Double.parseDouble(latStr); - double lon = Double.parseDouble(lonStr); Map updates = new HashMap<>(); updates.put("securityDistance", radius); - updates.put("latitude", lat); - updates.put("longitude", lon); + updates.put("address", addressStr); + updates.put("category", selectedCategory); databaseReference.child(documentId).updateChildren(updates) .addOnSuccessListener(aVoid -> { @@ -123,7 +136,7 @@ public class DefinicoesAdminActivity extends AppCompatActivity { e -> Toast.makeText(this, "Falha ao guardar definições.", Toast.LENGTH_SHORT).show()); } catch (NumberFormatException e) { - Toast.makeText(this, "Valores inválidos.", Toast.LENGTH_SHORT).show(); + Toast.makeText(this, "Raio inválido.", Toast.LENGTH_SHORT).show(); } } } diff --git a/app/src/main/java/com/example/pap_teste/DetalhesReservasActivity.java b/app/src/main/java/com/example/pap_teste/DetalhesReservasActivity.java index 2fa0d74..79fc1ad 100644 --- a/app/src/main/java/com/example/pap_teste/DetalhesReservasActivity.java +++ b/app/src/main/java/com/example/pap_teste/DetalhesReservasActivity.java @@ -18,7 +18,7 @@ import java.util.List; public class DetalhesReservasActivity extends AppCompatActivity { - private final List reservas = new ArrayList<>(); + private final List reservas = new ArrayList<>(); private ArrayAdapter adapter; private ListView listReservas; private TextView txtInfo; @@ -27,6 +27,8 @@ public class DetalhesReservasActivity extends AppCompatActivity { private TextView txtMensagem; private Button btnConfirmar, btnRecusar, btnApagar; private int selectedIndex = -1; + private String restaurantEmail; + private com.google.firebase.database.DatabaseReference databaseReference; @Override protected void onCreate(Bundle savedInstanceState) { @@ -39,10 +41,14 @@ public class DetalhesReservasActivity extends AppCompatActivity { return insets; }); + restaurantEmail = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL); + if (restaurantEmail == null) + restaurantEmail = "sabor_arte@restaurante.com"; + bindViews(); - seedReservasDemo(); setupList(); setupActions(); + loadReservas(); } private void bindViews() { @@ -62,17 +68,36 @@ public class DetalhesReservasActivity extends AppCompatActivity { } } - private void seedReservasDemo() { - reservas.add(new ReservaItem("Ana Ribeiro", "Mesa 12", "20h00", 4, "Aniversário", "Confirmada")); - reservas.add(new ReservaItem("Bruno Costa", "Mesa 03", "21h15", 2, "Preferência por janela", "Pendente")); - reservas.add(new ReservaItem("Carla Silva", "Mesa 07", "19h30", 3, "Levar bolo para a mesa", "Pendente")); - reservas.add(new ReservaItem("Duarte Neves", "Mesa 01", "22h00", 2, "", "Concluída")); + private void loadReservas() { + databaseReference = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reservas"); + databaseReference.orderByChild("restauranteEmail").equalTo(restaurantEmail) + .addValueEventListener(new com.google.firebase.database.ValueEventListener() { + @Override + public void onDataChange( + @androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) { + reservas.clear(); + for (com.google.firebase.database.DataSnapshot data : snapshot.getChildren()) { + com.example.pap_teste.models.Reserva r = data + .getValue(com.example.pap_teste.models.Reserva.class); + if (r != null) { + reservas.add(r); + } + } + refreshList(); + } + + @Override + public void onCancelled( + @androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) { + Toast.makeText(DetalhesReservasActivity.this, "Erro ao carregar reservas.", Toast.LENGTH_SHORT) + .show(); + } + }); } private void setupList() { adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_activated_1); listReservas.setAdapter(adapter); - refreshList(); listReservas.setOnItemClickListener((parent, view, position, id) -> { selectedIndex = position; @@ -83,10 +108,10 @@ public class DetalhesReservasActivity extends AppCompatActivity { private void setupActions() { if (btnConfirmar != null) { btnConfirmar.setOnClickListener(v -> { - ReservaItem item = reservas.get(selectedIndex); - if ("Pendente".equals(item.estado)) { + com.example.pap_teste.models.Reserva item = reservas.get(selectedIndex); + if ("Pendente".equals(item.getEstado())) { atualizarEstadoSelecionado("Confirmada"); - } else if ("Confirmada".equals(item.estado)) { + } else if ("Confirmada".equals(item.getEstado())) { atualizarEstadoSelecionado("Concluída"); } }); @@ -123,14 +148,17 @@ public class DetalhesReservasActivity extends AppCompatActivity { .setTitle("Apagar Reserva") .setMessage("Tem a certeza que deseja apagar esta reserva?") .setPositiveButton("Apagar", (dialog, which) -> { - reservas.remove(selectedIndex); - selectedIndex = -1; - txtInfo.setText("Selecione uma reserva"); - txtNotas.setText(""); - txtEstado.setText("Estado:"); - txtMensagem.setText("Reserva apagada com sucesso."); - toggleButtons(null); - refreshList(); + String idReserva = reservas.get(selectedIndex).getId(); + databaseReference.child(idReserva).removeValue().addOnCompleteListener(task -> { + if (task.isSuccessful()) { + selectedIndex = -1; + txtInfo.setText("Selecione uma reserva"); + txtNotas.setText(""); + txtEstado.setText("Estado:"); + txtMensagem.setText("Reserva apagada com sucesso."); + toggleButtons(null); + } + }); }) .setNegativeButton("Voltar", null) .show(); @@ -142,21 +170,25 @@ public class DetalhesReservasActivity extends AppCompatActivity { return; } - ReservaItem item = reservas.get(selectedIndex); - item.estado = novoEstado; - txtMensagem.setText(String.format("Reserva de %s marcada como %s.", item.nomeCliente, novoEstado)); - mostrarDetalhe(item); - refreshList(); + com.example.pap_teste.models.Reserva item = reservas.get(selectedIndex); + databaseReference.child(item.getId()).child("estado").setValue(novoEstado).addOnCompleteListener(task -> { + if (task.isSuccessful()) { + txtMensagem + .setText(String.format("Reserva de %s marcada como %s.", item.getClienteEmail(), novoEstado)); + mostrarDetalhe(item); + } + }); } - private void mostrarDetalhe(ReservaItem item) { - txtInfo.setText(String.format("%s • %s • %s • %dp", item.nomeCliente, item.mesa, item.hora, item.pessoas)); - txtNotas.setText(item.notas); - txtEstado.setText(String.format("Estado: %s", item.estado)); + private void mostrarDetalhe(com.example.pap_teste.models.Reserva item) { + txtInfo.setText(String.format("%s • %s • %s • %dp", item.getClienteEmail(), item.getRestauranteName(), + item.getHora(), item.getPessoas())); + txtNotas.setText("Data: " + item.getData()); + txtEstado.setText(String.format("Estado: %s", item.getEstado())); toggleButtons(item); } - private void toggleButtons(ReservaItem item) { + private void toggleButtons(com.example.pap_teste.models.Reserva item) { if (item == null) { btnConfirmar.setVisibility(android.view.View.GONE); btnRecusar.setVisibility(android.view.View.GONE); @@ -164,7 +196,7 @@ public class DetalhesReservasActivity extends AppCompatActivity { return; } - switch (item.estado) { + switch (item.getEstado()) { case "Pendente": btnConfirmar.setText("Confirmar"); btnConfirmar.setVisibility(android.view.View.VISIBLE); @@ -192,28 +224,11 @@ public class DetalhesReservasActivity extends AppCompatActivity { private void refreshList() { adapter.clear(); - for (ReservaItem item : reservas) { - String resumo = String.format("%s - %s (%s) • %s", item.hora, item.mesa, item.estado, item.nomeCliente); + for (com.example.pap_teste.models.Reserva item : reservas) { + String resumo = String.format("%s - %s (%s) • %s", item.getHora(), item.getData(), item.getEstado(), + item.getClienteEmail()); adapter.add(resumo); } adapter.notifyDataSetChanged(); } - - private static class ReservaItem { - String nomeCliente; - String mesa; - String hora; - int pessoas; - String notas; - String estado; - - ReservaItem(String nomeCliente, String mesa, String hora, int pessoas, String notas, String estado) { - this.nomeCliente = nomeCliente; - this.mesa = mesa; - this.hora = hora; - this.pessoas = pessoas; - this.notas = notas; - this.estado = estado; - } - } } diff --git a/app/src/main/java/com/example/pap_teste/EstablishmentDashboardActivity.java b/app/src/main/java/com/example/pap_teste/EstablishmentDashboardActivity.java index af69294..c14b834 100644 --- a/app/src/main/java/com/example/pap_teste/EstablishmentDashboardActivity.java +++ b/app/src/main/java/com/example/pap_teste/EstablishmentDashboardActivity.java @@ -52,7 +52,11 @@ public class EstablishmentDashboardActivity extends AppCompatActivity { btnGerirMesas.setOnClickListener(v -> startActivity(new Intent(this, GerirMesasActivity.class))); - btnDetails.setOnClickListener(v -> startActivity(new Intent(this, DetalhesReservasActivity.class))); + btnDetails.setOnClickListener(v -> { + Intent intent = new Intent(this, DetalhesReservasActivity.class); + intent.putExtra(MainActivity.EXTRA_EMAIL, getIntent().getStringExtra(MainActivity.EXTRA_EMAIL)); + startActivity(intent); + }); btnSettings.setOnClickListener(v -> { Intent intent = new Intent(this, DefinicoesAdminActivity.class); diff --git a/app/src/main/java/com/example/pap_teste/ExplorarRestaurantesActivity.java b/app/src/main/java/com/example/pap_teste/ExplorarRestaurantesActivity.java index ee44498..e83cbc3 100644 --- a/app/src/main/java/com/example/pap_teste/ExplorarRestaurantesActivity.java +++ b/app/src/main/java/com/example/pap_teste/ExplorarRestaurantesActivity.java @@ -12,6 +12,21 @@ import android.widget.Button; public class ExplorarRestaurantesActivity extends AppCompatActivity { + private enum State { + LIST, DETAILS + } + + private State currentState = State.LIST; + private com.example.pap_teste.models.Restaurant selectedRestaurant = null; + + private android.view.View scrollReservaDetails; + private androidx.recyclerview.widget.RecyclerView rvRestaurants; + private android.widget.TextView txtTitle; + + private String selectedDate = null; + private String selectedTime = null; + private int selectedPartySize = 0; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -23,44 +38,168 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity { return insets; }); + rvRestaurants = findViewById(R.id.rvRestaurants); + scrollReservaDetails = findViewById(R.id.scrollReservaDetails); + txtTitle = findViewById(R.id.txtTituloExplorar); + Button back = findViewById(R.id.btnVoltar); if (back != null) { - back.setOnClickListener(v -> finish()); + back.setOnClickListener(v -> handleBackNavigation()); } setupRestaurantList(); + updateViewState(); + } + + private void handleBackNavigation() { + if (currentState == State.DETAILS) { + currentState = State.LIST; + updateViewState(); + } else { + finish(); + } + } + + private void updateViewState() { + rvRestaurants.setVisibility(currentState == State.LIST ? android.view.View.VISIBLE : android.view.View.GONE); + scrollReservaDetails + .setVisibility(currentState == State.DETAILS ? android.view.View.VISIBLE : android.view.View.GONE); + + if (currentState == State.LIST) { + String filter = getIntent().getStringExtra("category_filter"); + txtTitle.setText(filter != null ? "Explorar: " + filter : "Explorar restaurantes"); + } else { + txtTitle.setText("Reserva: " + (selectedRestaurant != null ? selectedRestaurant.getName() : "")); + setupReservationOptions(); + } } private void setupRestaurantList() { String filter = getIntent().getStringExtra("category_filter"); - android.widget.TextView txtTitle = findViewById(R.id.txtTituloExplorar); - if (filter != null && txtTitle != null) { - txtTitle.setText("Explorar: " + filter); - } - - androidx.recyclerview.widget.RecyclerView rv = findViewById(R.id.rvRestaurants); - java.util.List allRestaurants = new java.util.ArrayList<>(); - allRestaurants.add(new com.example.pap_teste.models.Restaurant("Sabor & Arte", "Tradicional", true)); - allRestaurants.add(new com.example.pap_teste.models.Restaurant("Pizzeria Bella", "Pizzas", false)); - allRestaurants.add(new com.example.pap_teste.models.Restaurant("Sushi Zen", "Sushi", false)); - allRestaurants.add(new com.example.pap_teste.models.Restaurant("O Chuveiro", "Frutos do Mar", true)); - allRestaurants.add(new com.example.pap_teste.models.Restaurant("Hamburgueria Real", "Carnes", false)); - allRestaurants.add(new com.example.pap_teste.models.Restaurant("Churrascaria Gaúcha", "Carnes", false)); - allRestaurants.add(new com.example.pap_teste.models.Restaurant("Sushi House", "Sushi", false)); - allRestaurants.add(new com.example.pap_teste.models.Restaurant("Doce Momento", "Sobremesas", false)); - - java.util.List filteredList = new java.util.ArrayList<>(); + java.util.List restaurantsList = new java.util.ArrayList<>(); + com.google.firebase.database.DatabaseReference usersRef = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users"); + + com.google.firebase.database.Query query = usersRef; if (filter != null) { - for (com.example.pap_teste.models.Restaurant r : allRestaurants) { - if (r.getCategory().equalsIgnoreCase(filter)) { - filteredList.add(r); - } - } - } else { - filteredList.addAll(allRestaurants); + query = usersRef.orderByChild("category").equalTo(filter); } - RestaurantAdapter adapter = new RestaurantAdapter(filteredList); - rv.setAdapter(adapter); + query.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() { + @Override + public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) { + 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); + String email = ds.child("email").getValue(String.class); + String cat = ds.child("category").getValue(String.class); + + // If no category filter in query, we might need a client-side filter if the index isn't used + // but here we use the query. Actually if filter is null we get all, but we need to ensure they are ESTAB + if (name != null && email != null) { + restaurantsList.add(new com.example.pap_teste.models.Restaurant(name, cat, email, false)); + } + } + } + + RestaurantAdapter adapter = new RestaurantAdapter(restaurantsList, restaurant -> { + selectedRestaurant = restaurant; + currentState = State.DETAILS; + updateViewState(); + }); + rvRestaurants.setAdapter(adapter); + } + + @Override + public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) { + android.widget.Toast.makeText(ExplorarRestaurantesActivity.this, "Erro ao carregar restaurantes.", android.widget.Toast.LENGTH_SHORT).show(); + } + }); + } + + private void setupReservationOptions() { + // Dates + androidx.recyclerview.widget.RecyclerView rvDates = findViewById(R.id.rvDates); + java.util.List dates = new java.util.ArrayList<>(); + dates.add("Hoje"); + dates.add("Amanhã"); + dates.add("Quarta, 12 Mar"); + dates.add("Quinta, 13 Mar"); + dates.add("Sexta, 14 Mar"); + rvDates.setAdapter(new ReservationOptionAdapter(dates, date -> selectedDate = date)); + + // Times + androidx.recyclerview.widget.RecyclerView rvTimes = findViewById(R.id.rvTimes); + java.util.List times = new java.util.ArrayList<>(); + times.add("12:00"); + times.add("13:00"); + times.add("19:00"); + times.add("20:00"); + times.add("21:00"); + times.add("22:00"); + rvTimes.setAdapter(new ReservationOptionAdapter(times, time -> selectedTime = time)); + + // Party Size + androidx.recyclerview.widget.RecyclerView rvParty = findViewById(R.id.rvPartySize); + java.util.List party = new java.util.ArrayList<>(); + party.add("1 pessoa"); + party.add("2 pessoas"); + party.add("3 pessoas"); + party.add("4 pessoas"); + party.add("5 pessoas"); + party.add("6+ pessoas"); + rvParty.setAdapter(new ReservationOptionAdapter(party, size -> { + try { + selectedPartySize = Integer.parseInt(size.split(" ")[0].replace("+", "")); + } catch (Exception e) { + selectedPartySize = 6; + } + })); + + findViewById(R.id.btnConfirmarReserva).setOnClickListener(v -> saveReservation()); + } + + private void saveReservation() { + if (selectedDate == null || selectedTime == null || selectedPartySize == 0) { + android.widget.Toast.makeText(this, "Por favor, selecione data, hora e número de pessoas.", + android.widget.Toast.LENGTH_SHORT).show(); + return; + } + + String userEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null + ? com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail() + : "cliente@teste.com"; + + com.google.firebase.database.DatabaseReference ref = com.google.firebase.database.FirebaseDatabase.getInstance() + .getReference("reservas"); + String id = ref.push().getKey(); + + com.example.pap_teste.models.Reserva reserva = new com.example.pap_teste.models.Reserva( + id, + userEmail, + selectedRestaurant.getName(), + selectedRestaurant.getEmail(), + selectedDate, + selectedTime, + selectedPartySize, + "Pendente"); + + if (id != null) { + ref.child(id).setValue(reserva).addOnCompleteListener(task -> { + if (task.isSuccessful()) { + android.widget.Toast + .makeText(this, "Reserva solicitada com sucesso!", android.widget.Toast.LENGTH_SHORT) + .show(); + finish(); + } else { + android.widget.Toast.makeText(this, "Erro ao salvar reserva.", android.widget.Toast.LENGTH_SHORT) + .show(); + } + }); + } } } diff --git a/app/src/main/java/com/example/pap_teste/FavoritosActivity.java b/app/src/main/java/com/example/pap_teste/FavoritosActivity.java index 4990ef4..b243ba8 100644 --- a/app/src/main/java/com/example/pap_teste/FavoritosActivity.java +++ b/app/src/main/java/com/example/pap_teste/FavoritosActivity.java @@ -34,10 +34,10 @@ public class FavoritosActivity extends AppCompatActivity { private void setupFavoritesList() { androidx.recyclerview.widget.RecyclerView rv = findViewById(R.id.rvFavoritos); java.util.List list = new java.util.ArrayList<>(); - list.add(new com.example.pap_teste.models.Restaurant("Sabor & Arte", "Tradicional", true)); - list.add(new com.example.pap_teste.models.Restaurant("O Chuveiro", "Mariscos", true)); + list.add(new com.example.pap_teste.models.Restaurant("Sabor & Arte", "Tradicional", "sabor_arte@restaurante.com", true)); + list.add(new com.example.pap_teste.models.Restaurant("O Chuveiro", "Mariscos", "chuveiro@restaurante.com", true)); - RestaurantAdapter adapter = new RestaurantAdapter(list); + RestaurantAdapter adapter = new RestaurantAdapter(list, null); rv.setAdapter(adapter); } } diff --git a/app/src/main/java/com/example/pap_teste/MainActivity.java b/app/src/main/java/com/example/pap_teste/MainActivity.java index fa462b5..c59057c 100644 --- a/app/src/main/java/com/example/pap_teste/MainActivity.java +++ b/app/src/main/java/com/example/pap_teste/MainActivity.java @@ -19,6 +19,7 @@ import androidx.core.content.ContextCompat; import androidx.appcompat.app.AlertDialog; import android.Manifest; import android.content.pm.PackageManager; +import android.os.Build; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; @@ -28,7 +29,9 @@ import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; public class MainActivity extends AppCompatActivity { @@ -68,16 +71,16 @@ public class MainActivity extends AppCompatActivity { private FirebaseAuth firebaseAuth; private DatabaseReference databaseReference; - private final ActivityResultLauncher locationPermissionRequest = registerForActivityResult( + private final ActivityResultLauncher permissionRequest = registerForActivityResult( new ActivityResultContracts.RequestMultiplePermissions(), result -> { - Boolean fineLocationGranted = result.getOrDefault( - Manifest.permission.ACCESS_FINE_LOCATION, false); - Boolean coarseLocationGranted = result.getOrDefault( - Manifest.permission.ACCESS_COARSE_LOCATION, false); + Boolean fineLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false); + Boolean bluetoothScanGranted = true; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + bluetoothScanGranted = result.getOrDefault(Manifest.permission.BLUETOOTH_SCAN, false); + } + if (fineLocationGranted != null && fineLocationGranted) { // Precise location access granted. - } else if (coarseLocationGranted != null && coarseLocationGranted) { - // Only approximate location access granted. } else { Toast.makeText(this, "A permissão de localização é necessária para o check-in.", Toast.LENGTH_LONG) .show(); @@ -103,26 +106,32 @@ public class MainActivity extends AppCompatActivity { setupTypeToggle(); setupActionToggle(); setupPrimaryAction(); - checkLocationPermissions(); + checkPermissions(); } - private void checkLocationPermissions() { - if (ContextCompat.checkSelfPermission(this, - Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + private void checkPermissions() { + List permissionsNeeded = new ArrayList<>(); + 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) { + permissionsNeeded.add(Manifest.permission.BLUETOOTH_SCAN); + } + if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + permissionsNeeded.add(Manifest.permission.BLUETOOTH_CONNECT); + } + } + + if (!permissionsNeeded.isEmpty()) { new AlertDialog.Builder(this) - .setTitle("Partilha de localização") - .setMessage( - "Para permitir o check-in antecipado, precisamos de saber a sua distância ao restaurante. Deseja permitir a partilha de localização?") - .setPositiveButton("Sim", (dialog, which) -> { - locationPermissionRequest.launch(new String[] { - Manifest.permission.ACCESS_FINE_LOCATION, - Manifest.permission.ACCESS_COARSE_LOCATION - }); - }) - .setNegativeButton("Não", (dialog, which) -> { - Toast.makeText(this, "A localização foi recusada. O check-in poderá não funcionar.", - Toast.LENGTH_SHORT).show(); + .setTitle("Permissões Necessárias") + .setMessage("Para o correto funcionamento do check-in e serviços de proximidade, precisamos de algumas permissões.") + .setPositiveButton("Configurar", (dialog, which) -> { + permissionRequest.launch(permissionsNeeded.toArray(new String[0])); }) + .setNegativeButton("Agora Não", null) .show(); } } 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 a6a30f8..0d9736a 100644 --- a/app/src/main/java/com/example/pap_teste/NovaReservaActivity.java +++ b/app/src/main/java/com/example/pap_teste/NovaReservaActivity.java @@ -13,6 +13,18 @@ import android.widget.Button; public class NovaReservaActivity extends AppCompatActivity { + private enum State { + CATEGORIES, RESTAURANTS, DETAILS + } + + private State currentState = State.CATEGORIES; + private String selectedCategory = null; + private com.example.pap_teste.models.Restaurant selectedRestaurant = null; + + private androidx.recyclerview.widget.RecyclerView rvCategories, rvRestaurants; + private android.view.View scrollNovaReserva; + private android.widget.TextView txtTitle; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -24,14 +36,110 @@ public class NovaReservaActivity extends AppCompatActivity { return insets; }); + rvCategories = findViewById(R.id.rvCategories); + rvRestaurants = findViewById(R.id.rvRestaurants); + scrollNovaReserva = findViewById(R.id.scrollNovaReserva); + txtTitle = findViewById(R.id.txtTituloNovaReserva); + Button back = findViewById(R.id.btnVoltar); if (back != null) { - back.setOnClickListener(v -> finish()); + back.setOnClickListener(v -> handleBackNavigation()); } - setupReservationOptions(); + setupCategories(); + updateViewState(); } + private void handleBackNavigation() { + if (currentState == State.RESTAURANTS) { + currentState = State.CATEGORIES; + updateViewState(); + } else if (currentState == State.DETAILS) { + currentState = State.RESTAURANTS; + updateViewState(); + } else { + finish(); + } + } + + private void updateViewState() { + rvCategories + .setVisibility(currentState == State.CATEGORIES ? android.view.View.VISIBLE : android.view.View.GONE); + rvRestaurants + .setVisibility(currentState == State.RESTAURANTS ? android.view.View.VISIBLE : android.view.View.GONE); + scrollNovaReserva + .setVisibility(currentState == State.DETAILS ? android.view.View.VISIBLE : android.view.View.GONE); + + if (currentState == State.CATEGORIES) { + txtTitle.setText("Escolha o tema"); + } else if (currentState == State.RESTAURANTS) { + txtTitle.setText("Restaurantes: " + selectedCategory); + } else { + txtTitle.setText("Reserva: " + (selectedRestaurant != null ? selectedRestaurant.getName() : "")); + setupReservationOptions(); + } + } + + private void setupCategories() { + java.util.List cats = new java.util.ArrayList<>(); + cats.add(new com.example.pap_teste.models.FoodCategory("Carnes", R.drawable.cat_carnes)); + cats.add(new com.example.pap_teste.models.FoodCategory("Massas", R.drawable.cat_massas)); + cats.add(new com.example.pap_teste.models.FoodCategory("Sushi", R.drawable.cat_sushi)); + cats.add(new com.example.pap_teste.models.FoodCategory("Pizzas", R.drawable.cat_pizzas)); + cats.add(new com.example.pap_teste.models.FoodCategory("Sobremesas", R.drawable.cat_sobremesas)); + + rvCategories.setLayoutManager(new androidx.recyclerview.widget.LinearLayoutManager(this)); + rvCategories.setAdapter(new FoodCategoryAdapter(cats, category -> { + selectedCategory = category.getName(); + currentState = State.RESTAURANTS; + setupRestaurants(); + updateViewState(); + })); + } + + 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"); + + 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) { + 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); + + if (name != null && email != null) { + filteredList.add(new com.example.pap_teste.models.Restaurant(name, cat, email, false)); + } + } + } + + 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) { + android.widget.Toast.makeText(NovaReservaActivity.this, "Erro ao carregar restaurantes.", android.widget.Toast.LENGTH_SHORT).show(); + } + }); + } + + private String selectedDate = null; + private String selectedTime = null; + private int selectedPartySize = 0; + private void setupReservationOptions() { // Dates RecyclerView rvDates = findViewById(R.id.rvDates); @@ -41,7 +149,7 @@ public class NovaReservaActivity extends AppCompatActivity { dates.add("Quarta, 12 Mar"); dates.add("Quinta, 13 Mar"); dates.add("Sexta, 14 Mar"); - rvDates.setAdapter(new ReservationOptionAdapter(dates)); + rvDates.setAdapter(new ReservationOptionAdapter(dates, date -> selectedDate = date)); // Times RecyclerView rvTimes = findViewById(R.id.rvTimes); @@ -52,7 +160,7 @@ public class NovaReservaActivity extends AppCompatActivity { times.add("20:00"); times.add("21:00"); times.add("22:00"); - rvTimes.setAdapter(new ReservationOptionAdapter(times)); + rvTimes.setAdapter(new ReservationOptionAdapter(times, time -> selectedTime = time)); // Party Size RecyclerView rvParty = findViewById(R.id.rvPartySize); @@ -63,6 +171,53 @@ public class NovaReservaActivity extends AppCompatActivity { party.add("4 pessoas"); party.add("5 pessoas"); party.add("6+ pessoas"); - rvParty.setAdapter(new ReservationOptionAdapter(party)); + rvParty.setAdapter(new ReservationOptionAdapter(party, size -> { + try { + selectedPartySize = Integer.parseInt(size.split(" ")[0].replace("+", "")); + } catch (Exception e) { + selectedPartySize = 6; + } + })); + + findViewById(R.id.btnConfirmarReserva).setOnClickListener(v -> saveReservation()); + } + + private void saveReservation() { + if (selectedDate == null || selectedTime == null || selectedPartySize == 0) { + android.widget.Toast.makeText(this, "Por favor, selecione data, hora e número de pessoas.", + android.widget.Toast.LENGTH_SHORT).show(); + return; + } + + String userEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null + ? com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail() + : "cliente@teste.com"; + com.google.firebase.database.DatabaseReference ref = com.google.firebase.database.FirebaseDatabase.getInstance() + .getReference("reservas"); + String id = ref.push().getKey(); + + com.example.pap_teste.models.Reserva reserva = new com.example.pap_teste.models.Reserva( + id, + userEmail, + selectedRestaurant.getName(), + selectedRestaurant.getEmail(), + selectedDate, + selectedTime, + selectedPartySize, + "Pendente"); + + if (id != null) { + ref.child(id).setValue(reserva).addOnCompleteListener(task -> { + if (task.isSuccessful()) { + android.widget.Toast + .makeText(this, "Reserva solicitada com sucesso!", android.widget.Toast.LENGTH_SHORT) + .show(); + finish(); + } else { + android.widget.Toast.makeText(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 ac32dad..21e02e8 100644 --- a/app/src/main/java/com/example/pap_teste/ProfileDashboardActivity.java +++ b/app/src/main/java/com/example/pap_teste/ProfileDashboardActivity.java @@ -13,6 +13,13 @@ import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import android.view.View; +import android.net.Uri; +import android.widget.ImageView; +import com.bumptech.glide.Glide; +import com.google.firebase.storage.FirebaseStorage; +import com.google.firebase.storage.StorageReference; +import java.util.UUID; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; @@ -22,8 +29,9 @@ import java.util.Map; public class ProfileDashboardActivity extends AppCompatActivity { private EditText inputName, inputPhone, inputEmailEdit; - private String email, documentId; + private String email, documentId, photoUrl; private DatabaseReference databaseReference; + private ImageView imgProfile; private androidx.activity.result.ActivityResultLauncher imagePickerLauncher; @Override @@ -49,6 +57,7 @@ public class ProfileDashboardActivity extends AppCompatActivity { inputName = findViewById(R.id.inputProfileName); inputPhone = findViewById(R.id.inputProfilePhone); inputEmailEdit = findViewById(R.id.inputProfileEmail); + imgProfile = findViewById(R.id.imgProfile); if (currentName != null) { inputName.setText(currentName); @@ -65,17 +74,25 @@ public class ProfileDashboardActivity extends AppCompatActivity { if (result.getResultCode() == RESULT_OK && result.getData() != null) { android.net.Uri imageUri = result.getData().getData(); if (imageUri != null) { - Toast.makeText(this, "Foto selecionada (Simulação: Seria feito o upload)", - Toast.LENGTH_SHORT).show(); - // In a real app, you'd upload this to Firebase Storage. + uploadImageToFirebase(imageUri); } } }); findViewById(R.id.cardProfileBig).setOnClickListener(v -> { - Intent intent = new Intent(Intent.ACTION_PICK); - intent.setType("image/*"); - imagePickerLauncher.launch(intent); + String[] options = {"Galeria", "URL da Imagem"}; + androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(this); + builder.setTitle("Escolher Foto de Perfil"); + builder.setItems(options, (dialog, which) -> { + if (which == 0) { + Intent intent = new Intent(Intent.ACTION_PICK); + intent.setType("image/*"); + imagePickerLauncher.launch(intent); + } else { + showUrlInputDialog(); + } + }); + builder.show(); }); Button btnSave = findViewById(R.id.btnSaveProfile); @@ -91,10 +108,32 @@ public class ProfileDashboardActivity extends AppCompatActivity { }); btnRes.setOnClickListener(v -> { - startActivity(new Intent(this, DetalhesReservasActivity.class)); + startActivity(new Intent(this, MinhasReservasActivity.class)); }); } + private void showUrlInputDialog() { + androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(this); + builder.setTitle("Inserir URL da Imagem"); + + final EditText input = new EditText(this); + input.setInputType(android.text.InputType.TYPE_TEXT_VARIATION_URI); + input.setHint("https://exemplo.com/foto.jpg"); + builder.setView(input); + + builder.setPositiveButton("Confirmar", (dialog, which) -> { + String url = input.getText().toString().trim(); + if (!TextUtils.isEmpty(url)) { + this.photoUrl = url; + Glide.with(this).load(photoUrl).circleCrop().into(imgProfile); + Toast.makeText(this, "URL definida!", Toast.LENGTH_SHORT).show(); + } + }); + builder.setNegativeButton("Cancelar", (dialog, which) -> dialog.cancel()); + + builder.show(); + } + private void fetchAdditionalProfileData() { if (documentId == null) return; @@ -109,10 +148,33 @@ public class ProfileDashboardActivity extends AppCompatActivity { String dbEmail = snapshot.child("email").getValue(String.class); if (dbEmail != null) inputEmailEdit.setText(dbEmail); + + photoUrl = snapshot.child("photoUrl").getValue(String.class); + if (photoUrl != null && !photoUrl.isEmpty()) { + Glide.with(this).load(photoUrl).circleCrop().into(imgProfile); + } } }); } + private void uploadImageToFirebase(Uri imageUri) { + if (documentId == null) + return; + + StorageReference storageRef = FirebaseStorage.getInstance().getReference() + .child("profile_pics/" + UUID.randomUUID().toString()); + + storageRef.putFile(imageUri).addOnSuccessListener(taskSnapshot -> { + storageRef.getDownloadUrl().addOnSuccessListener(uri -> { + photoUrl = uri.toString(); + Glide.with(this).load(photoUrl).circleCrop().into(imgProfile); + Toast.makeText(this, "Foto carregada!", Toast.LENGTH_SHORT).show(); + }); + }).addOnFailureListener(e -> { + Toast.makeText(this, "Falha no upload.", Toast.LENGTH_SHORT).show(); + }); + } + private void saveProfile() { if (documentId == null) return; @@ -130,6 +192,9 @@ public class ProfileDashboardActivity extends AppCompatActivity { updates.put("displayName", newName); updates.put("phone", newPhone); updates.put("email", newEmail); + if (photoUrl != null) { + updates.put("photoUrl", photoUrl); + } databaseReference.child(documentId).updateChildren(updates) .addOnSuccessListener(aVoid -> { diff --git a/app/src/main/res/layout/activity_checkin_antecipado.xml b/app/src/main/res/layout/activity_checkin_antecipado.xml index d7e5c7d..e8dcbf9 100644 --- a/app/src/main/res/layout/activity_checkin_antecipado.xml +++ b/app/src/main/res/layout/activity_checkin_antecipado.xml @@ -73,16 +73,42 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> + + +