Compare commits
2 Commits
a33741ba06
...
948921a424
| Author | SHA1 | Date | |
|---|---|---|---|
| 948921a424 | |||
| 2db6544284 |
@@ -42,6 +42,8 @@ dependencies {
|
|||||||
implementation("com.google.firebase:firebase-firestore")
|
implementation("com.google.firebase:firebase-firestore")
|
||||||
implementation("com.google.firebase:firebase-auth")
|
implementation("com.google.firebase:firebase-auth")
|
||||||
implementation(libs.firebase.database)
|
implementation(libs.firebase.database)
|
||||||
|
implementation(libs.glide)
|
||||||
|
implementation(libs.firebase.storage)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.ext.junit)
|
androidTestImplementation(libs.ext.junit)
|
||||||
androidTestImplementation(libs.espresso.core)
|
androidTestImplementation(libs.espresso.core)
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
|
||||||
|
<!-- Bluetooth permissions for energy/power stats and location accuracy -->
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
@@ -91,6 +96,11 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="O meu Perfil"
|
android:label="O meu Perfil"
|
||||||
android:theme="@style/Theme.Pap_teste" />
|
android:theme="@style/Theme.Pap_teste" />
|
||||||
|
<activity
|
||||||
|
android:name=".MinhasReservasActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:label="Minhas Reservas"
|
||||||
|
android:theme="@style/Theme.Pap_teste" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package com.example.pap_teste;
|
|||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.location.LocationListener;
|
import android.location.LocationListener;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
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.FirebaseDatabase;
|
||||||
import com.google.firebase.database.ValueEventListener;
|
import com.google.firebase.database.ValueEventListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class CheckInAntecipadoActivity extends AppCompatActivity implements LocationListener {
|
public class CheckInAntecipadoActivity extends AppCompatActivity implements LocationListener {
|
||||||
|
|
||||||
private TextView txtDistancia, txtStatus;
|
private TextView txtDistancia, txtStatus, txtEndereco;
|
||||||
private Button btnConfirmarChegada;
|
private Button btnConfirmarChegada, btnAbrirMapa;
|
||||||
private LocationManager locationManager;
|
private LocationManager locationManager;
|
||||||
private DatabaseReference databaseReference;
|
private DatabaseReference databaseReference;
|
||||||
|
|
||||||
private double restaurantLat, restaurantLon;
|
private double restaurantLat, restaurantLon;
|
||||||
private int securityDistance = 500; // default 500m
|
private int securityDistance = 500; // default 500m
|
||||||
private boolean settingsLoaded = false;
|
private boolean settingsLoaded = false;
|
||||||
|
private String restaurantAddress;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -49,7 +55,9 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca
|
|||||||
|
|
||||||
txtDistancia = findViewById(R.id.txtDistancia);
|
txtDistancia = findViewById(R.id.txtDistancia);
|
||||||
txtStatus = findViewById(R.id.txtStatusDistancia);
|
txtStatus = findViewById(R.id.txtStatusDistancia);
|
||||||
|
txtEndereco = findViewById(R.id.txtEnderecoRestaurante);
|
||||||
btnConfirmarChegada = findViewById(R.id.btnConfirmarChegada);
|
btnConfirmarChegada = findViewById(R.id.btnConfirmarChegada);
|
||||||
|
btnAbrirMapa = findViewById(R.id.btnAbrirMapa);
|
||||||
Button back = findViewById(R.id.btnVoltar);
|
Button back = findViewById(R.id.btnVoltar);
|
||||||
|
|
||||||
if (back != null) {
|
if (back != null) {
|
||||||
@@ -65,12 +73,37 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca
|
|||||||
}
|
}
|
||||||
|
|
||||||
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
||||||
startLocationUpdates();
|
if (hasRequiredPermissions()) {
|
||||||
|
startLocationUpdates();
|
||||||
|
} else {
|
||||||
|
txtStatus.setText("Permissões em falta para localização/proximidade.");
|
||||||
|
}
|
||||||
|
|
||||||
btnConfirmarChegada.setOnClickListener(v -> {
|
btnConfirmarChegada.setOnClickListener(v -> {
|
||||||
Toast.makeText(this, "Chegada confirmada com sucesso!", Toast.LENGTH_LONG).show();
|
Toast.makeText(this, "Chegada confirmada com sucesso!", Toast.LENGTH_LONG).show();
|
||||||
finish();
|
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) {
|
private void loadRestaurantSettings(String restaurantId) {
|
||||||
@@ -79,17 +112,26 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca
|
|||||||
@Override
|
@Override
|
||||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
if (snapshot.exists()) {
|
if (snapshot.exists()) {
|
||||||
Double lat = snapshot.child("latitude").getValue(Double.class);
|
restaurantAddress = snapshot.child("address").getValue(String.class);
|
||||||
Double lon = snapshot.child("longitude").getValue(Double.class);
|
|
||||||
Integer dist = snapshot.child("securityDistance").getValue(Integer.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;
|
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 {
|
} else {
|
||||||
txtStatus.setText("Aviso: Definições do restaurante não encontradas. Usando valores padrão.");
|
txtStatus.setText("Aviso: Definições do restaurante não encontradas.");
|
||||||
settingsLoaded = true; // Use defaults
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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<android.location.Address> 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() {
|
private void startLocationUpdates() {
|
||||||
if (ActivityCompat.checkSelfPermission(this,
|
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||||
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.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -143,7 +199,9 @@ public class CheckInAntecipadoActivity extends AppCompatActivity implements Loca
|
|||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
locationManager.removeUpdates(this);
|
if (locationManager != null) {
|
||||||
|
locationManager.removeUpdates(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -99,5 +99,12 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
findViewById(R.id.btnNovaReserva)
|
findViewById(R.id.btnNovaReserva)
|
||||||
.setOnClickListener(v -> startActivity(new Intent(this, NovaReservaActivity.class)));
|
.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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,11 @@ import java.util.Map;
|
|||||||
|
|
||||||
public class DefinicoesAdminActivity extends AppCompatActivity {
|
public class DefinicoesAdminActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private EditText inputRadius, inputLatitude, inputLongitude;
|
private EditText inputRadius, inputAddress;
|
||||||
|
private android.widget.Spinner spinnerCategory;
|
||||||
private DatabaseReference databaseReference;
|
private DatabaseReference databaseReference;
|
||||||
private String documentId;
|
private String documentId;
|
||||||
|
private String[] categories = {"Carnes", "Massas", "Sushi", "Pizzas", "Sobremesas"};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -47,8 +49,14 @@ public class DefinicoesAdminActivity extends AppCompatActivity {
|
|||||||
databaseReference = FirebaseDatabase.getInstance().getReference().child("users");
|
databaseReference = FirebaseDatabase.getInstance().getReference().child("users");
|
||||||
|
|
||||||
inputRadius = findViewById(R.id.inputRadius);
|
inputRadius = findViewById(R.id.inputRadius);
|
||||||
inputLatitude = findViewById(R.id.inputLatitude);
|
inputAddress = findViewById(R.id.inputAddress);
|
||||||
inputLongitude = findViewById(R.id.inputLongitude);
|
spinnerCategory = findViewById(R.id.spinnerCategory);
|
||||||
|
|
||||||
|
android.widget.ArrayAdapter<String> 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 btnSave = findViewById(R.id.btnSaveSettings);
|
||||||
Button btnBack = findViewById(R.id.btnVoltar);
|
Button btnBack = findViewById(R.id.btnVoltar);
|
||||||
|
|
||||||
@@ -73,13 +81,20 @@ public class DefinicoesAdminActivity extends AppCompatActivity {
|
|||||||
Object val = snapshot.child("securityDistance").getValue();
|
Object val = snapshot.child("securityDistance").getValue();
|
||||||
inputRadius.setText(val != null ? val.toString() : "");
|
inputRadius.setText(val != null ? val.toString() : "");
|
||||||
}
|
}
|
||||||
if (snapshot.hasChild("latitude")) {
|
if (snapshot.hasChild("address")) {
|
||||||
Object val = snapshot.child("latitude").getValue();
|
String addr = snapshot.child("address").getValue(String.class);
|
||||||
inputLatitude.setText(val != null ? val.toString() : "");
|
inputAddress.setText(addr != null ? addr : "");
|
||||||
}
|
}
|
||||||
if (snapshot.hasChild("longitude")) {
|
if (snapshot.hasChild("category")) {
|
||||||
Object val = snapshot.child("longitude").getValue();
|
String cat = snapshot.child("category").getValue(String.class);
|
||||||
inputLongitude.setText(val != null ? val.toString() : "");
|
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;
|
return;
|
||||||
|
|
||||||
String radiusStr = inputRadius.getText().toString().trim();
|
String radiusStr = inputRadius.getText().toString().trim();
|
||||||
String latStr = inputLatitude.getText().toString().trim();
|
String addressStr = inputAddress.getText().toString().trim();
|
||||||
String lonStr = inputLongitude.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();
|
Toast.makeText(this, "Preencha todos os campos.", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int radius = Integer.parseInt(radiusStr);
|
int radius = Integer.parseInt(radiusStr);
|
||||||
double lat = Double.parseDouble(latStr);
|
|
||||||
double lon = Double.parseDouble(lonStr);
|
|
||||||
|
|
||||||
Map<String, Object> updates = new HashMap<>();
|
Map<String, Object> updates = new HashMap<>();
|
||||||
updates.put("securityDistance", radius);
|
updates.put("securityDistance", radius);
|
||||||
updates.put("latitude", lat);
|
updates.put("address", addressStr);
|
||||||
updates.put("longitude", lon);
|
updates.put("category", selectedCategory);
|
||||||
|
|
||||||
databaseReference.child(documentId).updateChildren(updates)
|
databaseReference.child(documentId).updateChildren(updates)
|
||||||
.addOnSuccessListener(aVoid -> {
|
.addOnSuccessListener(aVoid -> {
|
||||||
@@ -123,7 +136,7 @@ public class DefinicoesAdminActivity extends AppCompatActivity {
|
|||||||
e -> Toast.makeText(this, "Falha ao guardar definições.", Toast.LENGTH_SHORT).show());
|
e -> Toast.makeText(this, "Falha ao guardar definições.", Toast.LENGTH_SHORT).show());
|
||||||
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
Toast.makeText(this, "Valores inválidos.", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Raio inválido.", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public class DetalhesReservasActivity extends AppCompatActivity {
|
public class DetalhesReservasActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private final List<ReservaItem> reservas = new ArrayList<>();
|
private final List<com.example.pap_teste.models.Reserva> reservas = new ArrayList<>();
|
||||||
private ArrayAdapter<String> adapter;
|
private ArrayAdapter<String> adapter;
|
||||||
private ListView listReservas;
|
private ListView listReservas;
|
||||||
private TextView txtInfo;
|
private TextView txtInfo;
|
||||||
@@ -27,6 +27,8 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
|||||||
private TextView txtMensagem;
|
private TextView txtMensagem;
|
||||||
private Button btnConfirmar, btnRecusar, btnApagar;
|
private Button btnConfirmar, btnRecusar, btnApagar;
|
||||||
private int selectedIndex = -1;
|
private int selectedIndex = -1;
|
||||||
|
private String restaurantEmail;
|
||||||
|
private com.google.firebase.database.DatabaseReference databaseReference;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -39,10 +41,14 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
|||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
restaurantEmail = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL);
|
||||||
|
if (restaurantEmail == null)
|
||||||
|
restaurantEmail = "sabor_arte@restaurante.com";
|
||||||
|
|
||||||
bindViews();
|
bindViews();
|
||||||
seedReservasDemo();
|
|
||||||
setupList();
|
setupList();
|
||||||
setupActions();
|
setupActions();
|
||||||
|
loadReservas();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindViews() {
|
private void bindViews() {
|
||||||
@@ -62,17 +68,36 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void seedReservasDemo() {
|
private void loadReservas() {
|
||||||
reservas.add(new ReservaItem("Ana Ribeiro", "Mesa 12", "20h00", 4, "Aniversário", "Confirmada"));
|
databaseReference = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reservas");
|
||||||
reservas.add(new ReservaItem("Bruno Costa", "Mesa 03", "21h15", 2, "Preferência por janela", "Pendente"));
|
databaseReference.orderByChild("restauranteEmail").equalTo(restaurantEmail)
|
||||||
reservas.add(new ReservaItem("Carla Silva", "Mesa 07", "19h30", 3, "Levar bolo para a mesa", "Pendente"));
|
.addValueEventListener(new com.google.firebase.database.ValueEventListener() {
|
||||||
reservas.add(new ReservaItem("Duarte Neves", "Mesa 01", "22h00", 2, "", "Concluída"));
|
@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() {
|
private void setupList() {
|
||||||
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_activated_1);
|
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_activated_1);
|
||||||
listReservas.setAdapter(adapter);
|
listReservas.setAdapter(adapter);
|
||||||
refreshList();
|
|
||||||
|
|
||||||
listReservas.setOnItemClickListener((parent, view, position, id) -> {
|
listReservas.setOnItemClickListener((parent, view, position, id) -> {
|
||||||
selectedIndex = position;
|
selectedIndex = position;
|
||||||
@@ -83,10 +108,10 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
|||||||
private void setupActions() {
|
private void setupActions() {
|
||||||
if (btnConfirmar != null) {
|
if (btnConfirmar != null) {
|
||||||
btnConfirmar.setOnClickListener(v -> {
|
btnConfirmar.setOnClickListener(v -> {
|
||||||
ReservaItem item = reservas.get(selectedIndex);
|
com.example.pap_teste.models.Reserva item = reservas.get(selectedIndex);
|
||||||
if ("Pendente".equals(item.estado)) {
|
if ("Pendente".equals(item.getEstado())) {
|
||||||
atualizarEstadoSelecionado("Confirmada");
|
atualizarEstadoSelecionado("Confirmada");
|
||||||
} else if ("Confirmada".equals(item.estado)) {
|
} else if ("Confirmada".equals(item.getEstado())) {
|
||||||
atualizarEstadoSelecionado("Concluída");
|
atualizarEstadoSelecionado("Concluída");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -123,14 +148,17 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
|||||||
.setTitle("Apagar Reserva")
|
.setTitle("Apagar Reserva")
|
||||||
.setMessage("Tem a certeza que deseja apagar esta reserva?")
|
.setMessage("Tem a certeza que deseja apagar esta reserva?")
|
||||||
.setPositiveButton("Apagar", (dialog, which) -> {
|
.setPositiveButton("Apagar", (dialog, which) -> {
|
||||||
reservas.remove(selectedIndex);
|
String idReserva = reservas.get(selectedIndex).getId();
|
||||||
selectedIndex = -1;
|
databaseReference.child(idReserva).removeValue().addOnCompleteListener(task -> {
|
||||||
txtInfo.setText("Selecione uma reserva");
|
if (task.isSuccessful()) {
|
||||||
txtNotas.setText("");
|
selectedIndex = -1;
|
||||||
txtEstado.setText("Estado:");
|
txtInfo.setText("Selecione uma reserva");
|
||||||
txtMensagem.setText("Reserva apagada com sucesso.");
|
txtNotas.setText("");
|
||||||
toggleButtons(null);
|
txtEstado.setText("Estado:");
|
||||||
refreshList();
|
txtMensagem.setText("Reserva apagada com sucesso.");
|
||||||
|
toggleButtons(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.setNegativeButton("Voltar", null)
|
.setNegativeButton("Voltar", null)
|
||||||
.show();
|
.show();
|
||||||
@@ -142,21 +170,25 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservaItem item = reservas.get(selectedIndex);
|
com.example.pap_teste.models.Reserva item = reservas.get(selectedIndex);
|
||||||
item.estado = novoEstado;
|
databaseReference.child(item.getId()).child("estado").setValue(novoEstado).addOnCompleteListener(task -> {
|
||||||
txtMensagem.setText(String.format("Reserva de %s marcada como %s.", item.nomeCliente, novoEstado));
|
if (task.isSuccessful()) {
|
||||||
mostrarDetalhe(item);
|
txtMensagem
|
||||||
refreshList();
|
.setText(String.format("Reserva de %s marcada como %s.", item.getClienteEmail(), novoEstado));
|
||||||
|
mostrarDetalhe(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mostrarDetalhe(ReservaItem item) {
|
private void mostrarDetalhe(com.example.pap_teste.models.Reserva item) {
|
||||||
txtInfo.setText(String.format("%s • %s • %s • %dp", item.nomeCliente, item.mesa, item.hora, item.pessoas));
|
txtInfo.setText(String.format("%s • %s • %s • %dp", item.getClienteEmail(), item.getRestauranteName(),
|
||||||
txtNotas.setText(item.notas);
|
item.getHora(), item.getPessoas()));
|
||||||
txtEstado.setText(String.format("Estado: %s", item.estado));
|
txtNotas.setText("Data: " + item.getData());
|
||||||
|
txtEstado.setText(String.format("Estado: %s", item.getEstado()));
|
||||||
toggleButtons(item);
|
toggleButtons(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toggleButtons(ReservaItem item) {
|
private void toggleButtons(com.example.pap_teste.models.Reserva item) {
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
btnConfirmar.setVisibility(android.view.View.GONE);
|
btnConfirmar.setVisibility(android.view.View.GONE);
|
||||||
btnRecusar.setVisibility(android.view.View.GONE);
|
btnRecusar.setVisibility(android.view.View.GONE);
|
||||||
@@ -164,7 +196,7 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (item.estado) {
|
switch (item.getEstado()) {
|
||||||
case "Pendente":
|
case "Pendente":
|
||||||
btnConfirmar.setText("Confirmar");
|
btnConfirmar.setText("Confirmar");
|
||||||
btnConfirmar.setVisibility(android.view.View.VISIBLE);
|
btnConfirmar.setVisibility(android.view.View.VISIBLE);
|
||||||
@@ -192,28 +224,11 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
private void refreshList() {
|
private void refreshList() {
|
||||||
adapter.clear();
|
adapter.clear();
|
||||||
for (ReservaItem item : reservas) {
|
for (com.example.pap_teste.models.Reserva item : reservas) {
|
||||||
String resumo = String.format("%s - %s (%s) • %s", item.hora, item.mesa, item.estado, item.nomeCliente);
|
String resumo = String.format("%s - %s (%s) • %s", item.getHora(), item.getData(), item.getEstado(),
|
||||||
|
item.getClienteEmail());
|
||||||
adapter.add(resumo);
|
adapter.add(resumo);
|
||||||
}
|
}
|
||||||
adapter.notifyDataSetChanged();
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,11 @@ public class EstablishmentDashboardActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
btnGerirMesas.setOnClickListener(v -> startActivity(new Intent(this, GerirMesasActivity.class)));
|
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 -> {
|
btnSettings.setOnClickListener(v -> {
|
||||||
Intent intent = new Intent(this, DefinicoesAdminActivity.class);
|
Intent intent = new Intent(this, DefinicoesAdminActivity.class);
|
||||||
|
|||||||
@@ -12,6 +12,21 @@ import android.widget.Button;
|
|||||||
|
|
||||||
public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
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
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -23,44 +38,168 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
rvRestaurants = findViewById(R.id.rvRestaurants);
|
||||||
|
scrollReservaDetails = findViewById(R.id.scrollReservaDetails);
|
||||||
|
txtTitle = findViewById(R.id.txtTituloExplorar);
|
||||||
|
|
||||||
Button back = findViewById(R.id.btnVoltar);
|
Button back = findViewById(R.id.btnVoltar);
|
||||||
if (back != null) {
|
if (back != null) {
|
||||||
back.setOnClickListener(v -> finish());
|
back.setOnClickListener(v -> handleBackNavigation());
|
||||||
}
|
}
|
||||||
|
|
||||||
setupRestaurantList();
|
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() {
|
private void setupRestaurantList() {
|
||||||
String filter = getIntent().getStringExtra("category_filter");
|
String filter = getIntent().getStringExtra("category_filter");
|
||||||
android.widget.TextView txtTitle = findViewById(R.id.txtTituloExplorar);
|
java.util.List<com.example.pap_teste.models.Restaurant> restaurantsList = new java.util.ArrayList<>();
|
||||||
if (filter != null && txtTitle != null) {
|
com.google.firebase.database.DatabaseReference usersRef = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users");
|
||||||
txtTitle.setText("Explorar: " + filter);
|
|
||||||
}
|
com.google.firebase.database.Query query = usersRef;
|
||||||
|
|
||||||
androidx.recyclerview.widget.RecyclerView rv = findViewById(R.id.rvRestaurants);
|
|
||||||
java.util.List<com.example.pap_teste.models.Restaurant> 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<com.example.pap_teste.models.Restaurant> filteredList = new java.util.ArrayList<>();
|
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
for (com.example.pap_teste.models.Restaurant r : allRestaurants) {
|
query = usersRef.orderByChild("category").equalTo(filter);
|
||||||
if (r.getCategory().equalsIgnoreCase(filter)) {
|
|
||||||
filteredList.add(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
filteredList.addAll(allRestaurants);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RestaurantAdapter adapter = new RestaurantAdapter(filteredList);
|
query.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
||||||
rv.setAdapter(adapter);
|
@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<String> 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<String> 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<String> 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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ public class FavoritosActivity extends AppCompatActivity {
|
|||||||
private void setupFavoritesList() {
|
private void setupFavoritesList() {
|
||||||
androidx.recyclerview.widget.RecyclerView rv = findViewById(R.id.rvFavoritos);
|
androidx.recyclerview.widget.RecyclerView rv = findViewById(R.id.rvFavoritos);
|
||||||
java.util.List<com.example.pap_teste.models.Restaurant> list = new java.util.ArrayList<>();
|
java.util.List<com.example.pap_teste.models.Restaurant> 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("Sabor & Arte", "Tradicional", "sabor_arte@restaurante.com", true));
|
||||||
list.add(new com.example.pap_teste.models.Restaurant("O Chuveiro", "Mariscos", 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);
|
rv.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import androidx.core.content.ContextCompat;
|
|||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
import androidx.activity.result.contract.ActivityResultContracts;
|
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.DatabaseReference;
|
||||||
import com.google.firebase.database.FirebaseDatabase;
|
import com.google.firebase.database.FirebaseDatabase;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
@@ -68,16 +71,16 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private FirebaseAuth firebaseAuth;
|
private FirebaseAuth firebaseAuth;
|
||||||
private DatabaseReference databaseReference;
|
private DatabaseReference databaseReference;
|
||||||
|
|
||||||
private final ActivityResultLauncher<String[]> locationPermissionRequest = registerForActivityResult(
|
private final ActivityResultLauncher<String[]> permissionRequest = registerForActivityResult(
|
||||||
new ActivityResultContracts.RequestMultiplePermissions(), result -> {
|
new ActivityResultContracts.RequestMultiplePermissions(), result -> {
|
||||||
Boolean fineLocationGranted = result.getOrDefault(
|
Boolean fineLocationGranted = result.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false);
|
||||||
Manifest.permission.ACCESS_FINE_LOCATION, false);
|
Boolean bluetoothScanGranted = true;
|
||||||
Boolean coarseLocationGranted = result.getOrDefault(
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
Manifest.permission.ACCESS_COARSE_LOCATION, false);
|
bluetoothScanGranted = result.getOrDefault(Manifest.permission.BLUETOOTH_SCAN, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (fineLocationGranted != null && fineLocationGranted) {
|
if (fineLocationGranted != null && fineLocationGranted) {
|
||||||
// Precise location access granted.
|
// Precise location access granted.
|
||||||
} else if (coarseLocationGranted != null && coarseLocationGranted) {
|
|
||||||
// Only approximate location access granted.
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "A permissão de localização é necessária para o check-in.", Toast.LENGTH_LONG)
|
Toast.makeText(this, "A permissão de localização é necessária para o check-in.", Toast.LENGTH_LONG)
|
||||||
.show();
|
.show();
|
||||||
@@ -103,26 +106,32 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
setupTypeToggle();
|
setupTypeToggle();
|
||||||
setupActionToggle();
|
setupActionToggle();
|
||||||
setupPrimaryAction();
|
setupPrimaryAction();
|
||||||
checkLocationPermissions();
|
checkPermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkLocationPermissions() {
|
private void checkPermissions() {
|
||||||
if (ContextCompat.checkSelfPermission(this,
|
List<String> permissionsNeeded = new ArrayList<>();
|
||||||
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) {
|
||||||
|
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)
|
new AlertDialog.Builder(this)
|
||||||
.setTitle("Partilha de localização")
|
.setTitle("Permissões Necessárias")
|
||||||
.setMessage(
|
.setMessage("Para o correto funcionamento do check-in e serviços de proximidade, precisamos de algumas permissões.")
|
||||||
"Para permitir o check-in antecipado, precisamos de saber a sua distância ao restaurante. Deseja permitir a partilha de localização?")
|
.setPositiveButton("Configurar", (dialog, which) -> {
|
||||||
.setPositiveButton("Sim", (dialog, which) -> {
|
permissionRequest.launch(permissionsNeeded.toArray(new String[0]));
|
||||||
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();
|
|
||||||
})
|
})
|
||||||
|
.setNegativeButton("Agora Não", null)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package com.example.pap_teste;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.activity.EdgeToEdge;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.example.pap_teste.models.Reserva;
|
||||||
|
import com.google.firebase.database.DataSnapshot;
|
||||||
|
import com.google.firebase.database.DatabaseError;
|
||||||
|
import com.google.firebase.database.DatabaseReference;
|
||||||
|
import com.google.firebase.database.FirebaseDatabase;
|
||||||
|
import com.google.firebase.database.ValueEventListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MinhasReservasActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private RecyclerView rvMinhasReservas;
|
||||||
|
private ReservaAdapter adapter;
|
||||||
|
private final List<Reserva> reservaList = new ArrayList<>();
|
||||||
|
private DatabaseReference databaseReference;
|
||||||
|
private String clientEmail;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
EdgeToEdge.enable(this);
|
||||||
|
setContentView(R.layout.activity_minhas_reservas);
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.minhasReservasRoot), (v, insets) -> {
|
||||||
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
|
return insets;
|
||||||
|
});
|
||||||
|
|
||||||
|
clientEmail = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL);
|
||||||
|
if (clientEmail == null) {
|
||||||
|
com.google.firebase.auth.FirebaseUser user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
|
||||||
|
if (user != null) {
|
||||||
|
clientEmail = user.getEmail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback for testing if still null
|
||||||
|
if (clientEmail == null) {
|
||||||
|
clientEmail = "cliente@teste.com";
|
||||||
|
}
|
||||||
|
|
||||||
|
rvMinhasReservas = findViewById(R.id.rvMinhasReservas);
|
||||||
|
Button btnVoltar = findViewById(R.id.btnVoltar);
|
||||||
|
btnVoltar.setOnClickListener(v -> finish());
|
||||||
|
|
||||||
|
setupAdapter();
|
||||||
|
loadReservations();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupAdapter() {
|
||||||
|
adapter = new ReservaAdapter(reservaList, new ReservaAdapter.OnReservaActionListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckIn(Reserva reserva) {
|
||||||
|
Intent intent = new Intent(MinhasReservasActivity.this, CheckInAntecipadoActivity.class);
|
||||||
|
intent.putExtra("restaurant_email", reserva.getRestauranteEmail());
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancel(Reserva reserva) {
|
||||||
|
cancelReservation(reserva);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
rvMinhasReservas.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadReservations() {
|
||||||
|
databaseReference = FirebaseDatabase.getInstance().getReference("reservas");
|
||||||
|
databaseReference.orderByChild("clienteEmail").equalTo(clientEmail)
|
||||||
|
.addValueEventListener(new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
reservaList.clear();
|
||||||
|
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
|
||||||
|
Reserva reserva = dataSnapshot.getValue(Reserva.class);
|
||||||
|
if (reserva != null) {
|
||||||
|
reservaList.add(reserva);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@NonNull DatabaseError error) {
|
||||||
|
Toast.makeText(MinhasReservasActivity.this, "Erro ao carregar reservas.", Toast.LENGTH_SHORT)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelReservation(Reserva reserva) {
|
||||||
|
databaseReference.child(reserva.getId()).child("estado").setValue("Cancelada")
|
||||||
|
.addOnCompleteListener(task -> {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
Toast.makeText(this, "Reserva cancelada.", Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "Erro ao cancelar reserva.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,18 @@ import android.widget.Button;
|
|||||||
|
|
||||||
public class NovaReservaActivity extends AppCompatActivity {
|
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
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -24,14 +36,110 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
return insets;
|
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);
|
Button back = findViewById(R.id.btnVoltar);
|
||||||
if (back != null) {
|
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<com.example.pap_teste.models.FoodCategory> 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<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");
|
||||||
|
|
||||||
|
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() {
|
private void setupReservationOptions() {
|
||||||
// Dates
|
// Dates
|
||||||
RecyclerView rvDates = findViewById(R.id.rvDates);
|
RecyclerView rvDates = findViewById(R.id.rvDates);
|
||||||
@@ -41,7 +149,7 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
dates.add("Quarta, 12 Mar");
|
dates.add("Quarta, 12 Mar");
|
||||||
dates.add("Quinta, 13 Mar");
|
dates.add("Quinta, 13 Mar");
|
||||||
dates.add("Sexta, 14 Mar");
|
dates.add("Sexta, 14 Mar");
|
||||||
rvDates.setAdapter(new ReservationOptionAdapter(dates));
|
rvDates.setAdapter(new ReservationOptionAdapter(dates, date -> selectedDate = date));
|
||||||
|
|
||||||
// Times
|
// Times
|
||||||
RecyclerView rvTimes = findViewById(R.id.rvTimes);
|
RecyclerView rvTimes = findViewById(R.id.rvTimes);
|
||||||
@@ -52,7 +160,7 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
times.add("20:00");
|
times.add("20:00");
|
||||||
times.add("21:00");
|
times.add("21:00");
|
||||||
times.add("22:00");
|
times.add("22:00");
|
||||||
rvTimes.setAdapter(new ReservationOptionAdapter(times));
|
rvTimes.setAdapter(new ReservationOptionAdapter(times, time -> selectedTime = time));
|
||||||
|
|
||||||
// Party Size
|
// Party Size
|
||||||
RecyclerView rvParty = findViewById(R.id.rvPartySize);
|
RecyclerView rvParty = findViewById(R.id.rvPartySize);
|
||||||
@@ -63,6 +171,53 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
party.add("4 pessoas");
|
party.add("4 pessoas");
|
||||||
party.add("5 pessoas");
|
party.add("5 pessoas");
|
||||||
party.add("6+ 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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ import androidx.core.graphics.Insets;
|
|||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
|
import 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.DatabaseReference;
|
||||||
import com.google.firebase.database.FirebaseDatabase;
|
import com.google.firebase.database.FirebaseDatabase;
|
||||||
|
|
||||||
@@ -22,8 +29,9 @@ import java.util.Map;
|
|||||||
public class ProfileDashboardActivity extends AppCompatActivity {
|
public class ProfileDashboardActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private EditText inputName, inputPhone, inputEmailEdit;
|
private EditText inputName, inputPhone, inputEmailEdit;
|
||||||
private String email, documentId;
|
private String email, documentId, photoUrl;
|
||||||
private DatabaseReference databaseReference;
|
private DatabaseReference databaseReference;
|
||||||
|
private ImageView imgProfile;
|
||||||
private androidx.activity.result.ActivityResultLauncher<Intent> imagePickerLauncher;
|
private androidx.activity.result.ActivityResultLauncher<Intent> imagePickerLauncher;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -49,6 +57,7 @@ public class ProfileDashboardActivity extends AppCompatActivity {
|
|||||||
inputName = findViewById(R.id.inputProfileName);
|
inputName = findViewById(R.id.inputProfileName);
|
||||||
inputPhone = findViewById(R.id.inputProfilePhone);
|
inputPhone = findViewById(R.id.inputProfilePhone);
|
||||||
inputEmailEdit = findViewById(R.id.inputProfileEmail);
|
inputEmailEdit = findViewById(R.id.inputProfileEmail);
|
||||||
|
imgProfile = findViewById(R.id.imgProfile);
|
||||||
|
|
||||||
if (currentName != null) {
|
if (currentName != null) {
|
||||||
inputName.setText(currentName);
|
inputName.setText(currentName);
|
||||||
@@ -65,17 +74,25 @@ public class ProfileDashboardActivity extends AppCompatActivity {
|
|||||||
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
|
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
|
||||||
android.net.Uri imageUri = result.getData().getData();
|
android.net.Uri imageUri = result.getData().getData();
|
||||||
if (imageUri != null) {
|
if (imageUri != null) {
|
||||||
Toast.makeText(this, "Foto selecionada (Simulação: Seria feito o upload)",
|
uploadImageToFirebase(imageUri);
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
// In a real app, you'd upload this to Firebase Storage.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
findViewById(R.id.cardProfileBig).setOnClickListener(v -> {
|
findViewById(R.id.cardProfileBig).setOnClickListener(v -> {
|
||||||
Intent intent = new Intent(Intent.ACTION_PICK);
|
String[] options = {"Galeria", "URL da Imagem"};
|
||||||
intent.setType("image/*");
|
androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(this);
|
||||||
imagePickerLauncher.launch(intent);
|
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);
|
Button btnSave = findViewById(R.id.btnSaveProfile);
|
||||||
@@ -91,10 +108,32 @@ public class ProfileDashboardActivity extends AppCompatActivity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
btnRes.setOnClickListener(v -> {
|
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() {
|
private void fetchAdditionalProfileData() {
|
||||||
if (documentId == null)
|
if (documentId == null)
|
||||||
return;
|
return;
|
||||||
@@ -109,10 +148,33 @@ public class ProfileDashboardActivity extends AppCompatActivity {
|
|||||||
String dbEmail = snapshot.child("email").getValue(String.class);
|
String dbEmail = snapshot.child("email").getValue(String.class);
|
||||||
if (dbEmail != null)
|
if (dbEmail != null)
|
||||||
inputEmailEdit.setText(dbEmail);
|
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() {
|
private void saveProfile() {
|
||||||
if (documentId == null)
|
if (documentId == null)
|
||||||
return;
|
return;
|
||||||
@@ -130,6 +192,9 @@ public class ProfileDashboardActivity extends AppCompatActivity {
|
|||||||
updates.put("displayName", newName);
|
updates.put("displayName", newName);
|
||||||
updates.put("phone", newPhone);
|
updates.put("phone", newPhone);
|
||||||
updates.put("email", newEmail);
|
updates.put("email", newEmail);
|
||||||
|
if (photoUrl != null) {
|
||||||
|
updates.put("photoUrl", photoUrl);
|
||||||
|
}
|
||||||
|
|
||||||
databaseReference.child(documentId).updateChildren(updates)
|
databaseReference.child(documentId).updateChildren(updates)
|
||||||
.addOnSuccessListener(aVoid -> {
|
.addOnSuccessListener(aVoid -> {
|
||||||
|
|||||||
82
app/src/main/java/com/example/pap_teste/ReservaAdapter.java
Normal file
82
app/src/main/java/com/example/pap_teste/ReservaAdapter.java
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package com.example.pap_teste;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.example.pap_teste.models.Reserva;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ReservaAdapter extends RecyclerView.Adapter<ReservaAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
public interface OnReservaActionListener {
|
||||||
|
void onCheckIn(Reserva reserva);
|
||||||
|
|
||||||
|
void onCancel(Reserva reserva);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<Reserva> reservas;
|
||||||
|
private final OnReservaActionListener listener;
|
||||||
|
|
||||||
|
public ReservaAdapter(List<Reserva> reservas, OnReservaActionListener listener) {
|
||||||
|
this.reservas = reservas;
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_reserva_cliente, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
Reserva reserva = reservas.get(position);
|
||||||
|
holder.txtRestaurante.setText(reserva.getRestauranteName());
|
||||||
|
holder.txtDataHora.setText(reserva.getData() + " às " + reserva.getHora() + " • " + reserva.getPessoas() + "p");
|
||||||
|
holder.txtStatus.setText("Estado: " + reserva.getEstado());
|
||||||
|
|
||||||
|
// Enable check-in only if confirmed
|
||||||
|
holder.btnCheckIn.setEnabled("Confirmada".equals(reserva.getEstado()));
|
||||||
|
|
||||||
|
// Show cancel only if not concluded or already cancelled/refused
|
||||||
|
boolean canCancel = "Pendente".equals(reserva.getEstado()) || "Confirmada".equals(reserva.getEstado());
|
||||||
|
holder.btnCancelar.setVisibility(canCancel ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
holder.btnCheckIn.setOnClickListener(v -> {
|
||||||
|
if (listener != null)
|
||||||
|
listener.onCheckIn(reserva);
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.btnCancelar.setOnClickListener(v -> {
|
||||||
|
if (listener != null)
|
||||||
|
listener.onCancel(reserva);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return reservas.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView txtRestaurante, txtDataHora, txtStatus;
|
||||||
|
Button btnCheckIn, btnCancelar;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
txtRestaurante = itemView.findViewById(R.id.txtReservaRestaurante);
|
||||||
|
txtDataHora = itemView.findViewById(R.id.txtReservaDataHora);
|
||||||
|
txtStatus = itemView.findViewById(R.id.txtReservaStatus);
|
||||||
|
btnCheckIn = itemView.findViewById(R.id.btnCheckIn);
|
||||||
|
btnCancelar = itemView.findViewById(R.id.btnCancelar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.example.pap_teste;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ReservationOptionAdapter extends RecyclerView.Adapter<ReservationOptionAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
public interface OnOptionSelectedListener {
|
||||||
|
void onOptionSelected(String option);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<String> options;
|
||||||
|
private final OnOptionSelectedListener listener;
|
||||||
|
private int selectedPosition = -1;
|
||||||
|
|
||||||
|
public ReservationOptionAdapter(List<String> options, OnOptionSelectedListener listener) {
|
||||||
|
this.options = options;
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_reservation_option, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
String option = options.get(position);
|
||||||
|
holder.txtValue.setText(option);
|
||||||
|
|
||||||
|
boolean isSelected = position == selectedPosition;
|
||||||
|
holder.cardRoot.setCardBackgroundColor(isSelected ? 0xFFFF6B6B : 0xFFFFFFFF);
|
||||||
|
holder.txtValue.setTextColor(isSelected ? 0xFFFFFFFF : 0xFF000000);
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(v -> {
|
||||||
|
int previousSelected = selectedPosition;
|
||||||
|
selectedPosition = holder.getAdapterPosition();
|
||||||
|
notifyItemChanged(previousSelected);
|
||||||
|
notifyItemChanged(selectedPosition);
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onOptionSelected(option);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return options.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView txtValue;
|
||||||
|
androidx.cardview.widget.CardView cardRoot;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
txtValue = itemView.findViewById(R.id.txtOptionValue);
|
||||||
|
cardRoot = itemView.findViewById(R.id.cardOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.example.pap_teste;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.example.pap_teste.models.Restaurant;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
public interface OnRestaurantClickListener {
|
||||||
|
void onRestaurantClick(Restaurant restaurant);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<Restaurant> restaurants;
|
||||||
|
private final OnRestaurantClickListener listener;
|
||||||
|
|
||||||
|
public RestaurantAdapter(List<Restaurant> restaurants, OnRestaurantClickListener listener) {
|
||||||
|
this.restaurants = restaurants;
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_restaurant, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
Restaurant restaurant = restaurants.get(position);
|
||||||
|
holder.txtName.setText(restaurant.getName());
|
||||||
|
holder.txtCategory.setText(restaurant.getCategory());
|
||||||
|
|
||||||
|
updateFavoriteIcon(holder.btnFavorite, restaurant.isFavorite());
|
||||||
|
|
||||||
|
holder.btnFavorite.setOnClickListener(v -> {
|
||||||
|
restaurant.setFavorite(!restaurant.isFavorite());
|
||||||
|
updateFavoriteIcon(holder.btnFavorite, restaurant.isFavorite());
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(v -> {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onRestaurantClick(restaurant);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateFavoriteIcon(ImageButton btn, boolean isFavorite) {
|
||||||
|
if (isFavorite) {
|
||||||
|
btn.setImageResource(android.R.drawable.btn_star_big_on);
|
||||||
|
} else {
|
||||||
|
btn.setImageResource(android.R.drawable.btn_star_big_off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return restaurants.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView txtName, txtCategory;
|
||||||
|
ImageButton btnFavorite;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
txtName = itemView.findViewById(R.id.txtRestaurantName);
|
||||||
|
txtCategory = itemView.findViewById(R.id.txtRestaurantCategory);
|
||||||
|
btnFavorite = itemView.findViewById(R.id.btnFavorite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
92
app/src/main/java/com/example/pap_teste/models/Reserva.java
Normal file
92
app/src/main/java/com/example/pap_teste/models/Reserva.java
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package com.example.pap_teste.models;
|
||||||
|
|
||||||
|
public class Reserva {
|
||||||
|
private String id;
|
||||||
|
private String clienteEmail;
|
||||||
|
private String restauranteName;
|
||||||
|
private String restauranteEmail;
|
||||||
|
private String data;
|
||||||
|
private String hora;
|
||||||
|
private int pessoas;
|
||||||
|
private String estado; // Pendente, Confirmada, Concluída, Cancelada, Recusada
|
||||||
|
|
||||||
|
public Reserva() {
|
||||||
|
// Required for Firebase
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reserva(String id, String clienteEmail, String restauranteName, String restauranteEmail, String data,
|
||||||
|
String hora, int pessoas, String estado) {
|
||||||
|
this.id = id;
|
||||||
|
this.clienteEmail = clienteEmail;
|
||||||
|
this.restauranteName = restauranteName;
|
||||||
|
this.restauranteEmail = restauranteEmail;
|
||||||
|
this.data = data;
|
||||||
|
this.hora = hora;
|
||||||
|
this.pessoas = pessoas;
|
||||||
|
this.estado = estado;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClienteEmail() {
|
||||||
|
return clienteEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClienteEmail(String clienteEmail) {
|
||||||
|
this.clienteEmail = clienteEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRestauranteName() {
|
||||||
|
return restauranteName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRestauranteName(String restauranteName) {
|
||||||
|
this.restauranteName = restauranteName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRestauranteEmail() {
|
||||||
|
return restauranteEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRestauranteEmail(String restauranteEmail) {
|
||||||
|
this.restauranteEmail = restauranteEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHora() {
|
||||||
|
return hora;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHora(String hora) {
|
||||||
|
this.hora = hora;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPessoas() {
|
||||||
|
return pessoas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPessoas(int pessoas) {
|
||||||
|
this.pessoas = pessoas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEstado() {
|
||||||
|
return estado;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEstado(String estado) {
|
||||||
|
this.estado = estado;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.example.pap_teste.models;
|
||||||
|
|
||||||
|
public class Restaurant {
|
||||||
|
private String name;
|
||||||
|
private String category;
|
||||||
|
private String email;
|
||||||
|
private String address;
|
||||||
|
private boolean isFavorite;
|
||||||
|
|
||||||
|
public Restaurant() {
|
||||||
|
// Required for Firebase
|
||||||
|
}
|
||||||
|
|
||||||
|
public Restaurant(String name, String category, String email, boolean isFavorite) {
|
||||||
|
this.name = name;
|
||||||
|
this.category = category;
|
||||||
|
this.email = email;
|
||||||
|
this.isFavorite = isFavorite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCategory() {
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategory(String category) {
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(String address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFavorite() {
|
||||||
|
return isFavorite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFavorite(boolean favorite) {
|
||||||
|
isFavorite = favorite;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
app/src/main/res/drawable/cat_pizzas.png
Normal file
BIN
app/src/main/res/drawable/cat_pizzas.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 732 KiB |
BIN
app/src/main/res/drawable/cat_sobremesas.png
Normal file
BIN
app/src/main/res/drawable/cat_sobremesas.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 548 KiB |
@@ -73,16 +73,42 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtEnderecoRestaurante"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="32dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="A carregar morada..."
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textColor="#333"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/txtStatusDistancia"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnAbrirMapa"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="Ver no Mapa"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/txtEnderecoRestaurante"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btnConfirmarChegada"
|
android:id="@+id/btnConfirmarChegada"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="32dp"
|
android:layout_marginHorizontal="32dp"
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="16dp"
|
||||||
android:text="Confirmar Chegada"
|
android:text="Confirmar Chegada"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
app:layout_constraintTop_toBottomOf="@id/txtStatusDistancia"
|
app:layout_constraintTop_toBottomOf="@id/btnAbrirMapa"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
|||||||
@@ -234,6 +234,30 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/cardMinhasReservas"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardElevation="2dp">
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/btnMinhasReservas"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="?attr/selectableItemBackground">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Minhas Reservas"
|
||||||
|
android:textColor="#000"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
|
||||||
<!-- Status Section -->
|
<!-- Status Section -->
|
||||||
|
|||||||
@@ -87,30 +87,35 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="20dp"
|
||||||
android:text="Localização do Restaurante"
|
android:text="Informação do Restaurante"
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/inputLatitude"
|
android:id="@+id/inputAddress"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:hint="Latitude (Ex: 38.7223)"
|
android:hint="Morada (Ex: Rua Estreita, 12)"
|
||||||
android:inputType="numberDecimal|numberSigned"
|
android:inputType="textPostalAddress"
|
||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:background="@android:drawable/editbox_background_normal" />
|
android:background="@android:drawable/editbox_background_normal" />
|
||||||
|
|
||||||
<EditText
|
<TextView
|
||||||
android:id="@+id/inputLongitude"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="12dp"
|
||||||
android:hint="Longitude (Ex: -9.1393)"
|
android:text="Categoria"
|
||||||
android:inputType="numberDecimal|numberSigned"
|
android:textColor="#5F5F5F"
|
||||||
android:padding="12dp"
|
android:textSize="14sp" />
|
||||||
android:background="@android:drawable/editbox_background_normal" />
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spinnerCategory"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:minHeight="48dp" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btnSaveSettings"
|
android:id="@+id/btnSaveSettings"
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="24dp"
|
android:paddingBottom="24dp"
|
||||||
|
android:visibility="visible"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
@@ -46,6 +47,106 @@
|
|||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
tools:listitem="@layout/item_restaurant" />
|
tools:listitem="@layout/item_restaurant" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@+id/scrollReservaDetails"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/txtTituloExplorar">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="32dp">
|
||||||
|
|
||||||
|
<!-- Section: Date -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="Escolha a data"
|
||||||
|
android:textColor="#000"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvDates"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
|
<!-- Section: Time -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:text="Escolha o horário"
|
||||||
|
android:textColor="#000"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvTimes"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
|
<!-- Section: Party size -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:text="Número de pessoas"
|
||||||
|
android:textColor="#000"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvPartySize"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnConfirmarReserva"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="55dp"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:background="@drawable/btn_primary"
|
||||||
|
android:text="Confirmar Reserva"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="#FFF"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
48
app/src/main/res/layout/activity_minhas_reservas.xml
Normal file
48
app/src/main/res/layout/activity_minhas_reservas.xml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/minhasReservasRoot"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#F7F7F7"
|
||||||
|
tools:context=".MinhasReservasActivity">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnVoltar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="Voltar"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtTituloMinhasReservas"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Minhas Reservas"
|
||||||
|
android:textColor="#000"
|
||||||
|
android:textSize="22sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/btnVoltar"
|
||||||
|
android:layout_marginTop="24dp" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvMinhasReservas"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/txtTituloMinhasReservas"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -32,12 +32,37 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:layout_marginTop="32dp" />
|
android:layout_marginTop="32dp" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvCategories"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/txtTituloNovaReserva"
|
||||||
|
tools:listitem="@layout/item_food_category" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvRestaurants"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/txtTituloNovaReserva"
|
||||||
|
tools:listitem="@layout/item_restaurant" />
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:id="@+id/scrollNovaReserva"
|
android:id="@+id/scrollNovaReserva"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:fillViewport="true"
|
android:fillViewport="true"
|
||||||
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|||||||
@@ -43,11 +43,11 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent">
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
<ImageView
|
<ImageView
|
||||||
|
android:id="@+id/imgProfile"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@drawable/circle_bg"
|
android:src="@drawable/circle_bg" />
|
||||||
android:padding="20dp" />
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|||||||
@@ -1,34 +1,37 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="120dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="140dp"
|
android:layout_height="100dp"
|
||||||
android:layout_margin="8dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginVertical="8dp"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
app:cardElevation="2dp">
|
app:cardElevation="2dp">
|
||||||
|
|
||||||
<LinearLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:padding="16dp">
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="8dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imgCategory"
|
|
||||||
android:layout_width="80dp"
|
|
||||||
android:layout_height="80dp"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:src="@drawable/ic_launcher_background" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtCategoryName"
|
android:id="@+id/txtCategoryName"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_toStartOf="@id/imgCategory"
|
||||||
android:text="Categoria"
|
android:text="Categoria"
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="14sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
</LinearLayout>
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imgCategory"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@drawable/ic_launcher_background" />
|
||||||
|
</RelativeLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|||||||
73
app/src/main/res/layout/item_reserva_cliente.xml
Normal file
73
app/src/main/res/layout/item_reserva_cliente.xml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginVertical="8dp"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardElevation="2dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtReservaRestaurante"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Nome do Restaurante"
|
||||||
|
android:textColor="#000"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtReservaDataHora"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text="Hoje às 20:00"
|
||||||
|
android:textColor="#757575"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtReservaStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="Estado: Pendente"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnCheckIn"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
android:text="Check-in"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:background="@drawable/btn_primary"
|
||||||
|
android:textColor="#FFF" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnCancelar"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:text="Cancelar"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:background="@drawable/btn_light_border"
|
||||||
|
android:textColor="#C62828" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
21
app/src/main/res/layout/item_reservation_option.xml
Normal file
21
app/src/main/res/layout/item_reservation_option.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/cardOption"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
app:cardCornerRadius="12dp"
|
||||||
|
app:cardElevation="2dp"
|
||||||
|
app:cardBackgroundColor="#FFFFFF">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtOptionValue"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="24dp"
|
||||||
|
android:paddingVertical="12dp"
|
||||||
|
android:text="Option"
|
||||||
|
android:textColor="#000"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
53
app/src/main/res/layout/item_restaurant.xml
Normal file
53
app/src/main/res/layout/item_restaurant.xml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginVertical="8dp"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardElevation="2dp">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_toStartOf="@id/btnFavorite"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtRestaurantName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Restaurant Name"
|
||||||
|
android:textColor="#000"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtRestaurantCategory"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text="Category"
|
||||||
|
android:textColor="#757575"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btnFavorite"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:src="@android:drawable/btn_star_big_off" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
@@ -11,6 +11,8 @@ constraintlayout = "2.2.1"
|
|||||||
firebaseBom = "33.7.0"
|
firebaseBom = "33.7.0"
|
||||||
googleServices = "4.4.2"
|
googleServices = "4.4.2"
|
||||||
firebaseDatabase = "22.0.1"
|
firebaseDatabase = "22.0.1"
|
||||||
|
glide = "4.16.0"
|
||||||
|
firebaseStorage = "21.0.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
@@ -23,6 +25,8 @@ activity = { group = "androidx.activity", name = "activity", version.ref = "acti
|
|||||||
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||||
firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebaseBom" }
|
firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebaseBom" }
|
||||||
firebase-database = { group = "com.google.firebase", name = "firebase-database", version.ref = "firebaseDatabase" }
|
firebase-database = { group = "com.google.firebase", name = "firebase-database", version.ref = "firebaseDatabase" }
|
||||||
|
glide = { group = "com.github.bumptech.glide", name = "glide", version.ref = "glide" }
|
||||||
|
firebase-storage = { group = "com.google.firebase", name = "firebase-storage", version.ref = "firebaseStorage" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|||||||
Reference in New Issue
Block a user