Compare commits
5 Commits
948921a424
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 404f28da15 | |||
| 740680e9fb | |||
| fa9ba84d5c | |||
| a921553f2b | |||
| 88ef4b6796 |
8
.idea/deploymentTargetSelector.xml
generated
8
.idea/deploymentTargetSelector.xml
generated
@@ -4,6 +4,14 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
<DropdownSelection timestamp="2026-04-14T16:06:26.670067Z">
|
||||||
|
<Target type="DEFAULT_BOOT">
|
||||||
|
<handle>
|
||||||
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=b93659d0e5dd" />
|
||||||
|
</handle>
|
||||||
|
</Target>
|
||||||
|
</DropdownSelection>
|
||||||
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<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" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||||
|
|
||||||
<!-- Bluetooth permissions for energy/power stats and location accuracy -->
|
<!-- 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" android:maxSdkVersion="30" />
|
||||||
@@ -16,9 +19,9 @@
|
|||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@drawable/na_mesa"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@drawable/na_mesa"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.Pap_teste">
|
android:theme="@style/Theme.Pap_teste">
|
||||||
<activity
|
<activity
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ public class AddStaffActivity extends AppCompatActivity {
|
|||||||
btnAddZone = findViewById(R.id.btnAddZone);
|
btnAddZone = findViewById(R.id.btnAddZone);
|
||||||
mesaSpinner = findViewById(R.id.mesaSpinner);
|
mesaSpinner = findViewById(R.id.mesaSpinner);
|
||||||
|
|
||||||
|
Button btnVoltarAddStaff = findViewById(R.id.btnVoltarAddStaff);
|
||||||
|
if (btnVoltarAddStaff != null) {
|
||||||
|
btnVoltarAddStaff.setOnClickListener(v -> finish());
|
||||||
|
}
|
||||||
|
|
||||||
zones = new ArrayList<>();
|
zones = new ArrayList<>();
|
||||||
zones.add("Sala");
|
zones.add("Sala");
|
||||||
zones.add("Esplanada");
|
zones.add("Esplanada");
|
||||||
|
|||||||
@@ -53,22 +53,41 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
updateGreeting();
|
updateGreeting();
|
||||||
|
fetchProfilePicture();
|
||||||
setupCategories();
|
setupCategories();
|
||||||
setupActions();
|
setupActions();
|
||||||
|
loadNextReservation();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGreeting() {
|
private void updateGreeting() {
|
||||||
txtGreeting.setText(String.format("Olá, %s", displayName != null ? displayName : "convidado"));
|
txtGreeting.setText(String.format("Olá, %s", displayName != null ? displayName : "convidado"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fetchProfilePicture() {
|
||||||
|
if (email == null) return;
|
||||||
|
String documentId = email.replace(".", "_").replace("@", "_at_");
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference()
|
||||||
|
.child("users").child(documentId).child("photoUrl")
|
||||||
|
.get().addOnSuccessListener(snapshot -> {
|
||||||
|
if (!isDestroyed() && snapshot.exists()) {
|
||||||
|
String photoUrl = snapshot.getValue(String.class);
|
||||||
|
if (photoUrl != null && !photoUrl.isEmpty()) {
|
||||||
|
android.widget.ImageView imgProfile = findViewById(R.id.imgProfile);
|
||||||
|
com.bumptech.glide.Glide.with(this).load(photoUrl).circleCrop().into(imgProfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void setupCategories() {
|
private void setupCategories() {
|
||||||
RecyclerView rv = findViewById(R.id.rvCategories);
|
RecyclerView rv = findViewById(R.id.rvCategories);
|
||||||
List<FoodCategory> cats = new ArrayList<>();
|
List<FoodCategory> cats = new ArrayList<>();
|
||||||
cats.add(new FoodCategory("Carnes", R.drawable.cat_carnes));
|
cats.add(new FoodCategory("Carnes", R.drawable.cat_carnes));
|
||||||
cats.add(new FoodCategory("Massas", R.drawable.cat_massas));
|
cats.add(new FoodCategory("Massas", R.drawable.cat_massas));
|
||||||
cats.add(new FoodCategory("Sushi", R.drawable.cat_sushi));
|
cats.add(new FoodCategory("Sushi", R.drawable.cat_sushi));
|
||||||
cats.add(new FoodCategory("Pizzas", R.drawable.cat_pizzas));
|
// Using circle_bg as placeholder for missing images
|
||||||
cats.add(new FoodCategory("Sobremesas", R.drawable.cat_sobremesas));
|
cats.add(new FoodCategory("Pizzas", R.drawable.circle_bg));
|
||||||
|
cats.add(new FoodCategory("Sobremesas", R.drawable.circle_bg));
|
||||||
|
|
||||||
FoodCategoryAdapter adapter = new FoodCategoryAdapter(cats, category -> {
|
FoodCategoryAdapter adapter = new FoodCategoryAdapter(cats, category -> {
|
||||||
Intent intent = new Intent(this, ExplorarRestaurantesActivity.class);
|
Intent intent = new Intent(this, ExplorarRestaurantesActivity.class);
|
||||||
@@ -88,12 +107,6 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
findViewById(R.id.btnVoltar).setOnClickListener(v -> finish());
|
findViewById(R.id.btnVoltar).setOnClickListener(v -> finish());
|
||||||
|
|
||||||
findViewById(R.id.btnCheckIn).setOnClickListener(v -> {
|
|
||||||
Intent intent = new Intent(this, CheckInAntecipadoActivity.class);
|
|
||||||
intent.putExtra("restaurant_email", "sabor_arte@restaurante.com");
|
|
||||||
startActivity(intent);
|
|
||||||
});
|
|
||||||
|
|
||||||
findViewById(R.id.btnPartilhar).setOnClickListener(
|
findViewById(R.id.btnPartilhar).setOnClickListener(
|
||||||
v -> startActivity(new Intent(this, PartilharReservaActivity.class)));
|
v -> startActivity(new Intent(this, PartilharReservaActivity.class)));
|
||||||
|
|
||||||
@@ -107,4 +120,105 @@ public class ClientDashboardActivity extends AppCompatActivity {
|
|||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadNextReservation() {
|
||||||
|
if (email == null) return;
|
||||||
|
com.google.firebase.database.DatabaseReference ref = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reservas");
|
||||||
|
ref.orderByChild("clienteEmail").equalTo(email).addValueEventListener(new com.google.firebase.database.ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
com.example.pap_teste.models.Reserva proxima = null;
|
||||||
|
long timeProx = Long.MAX_VALUE;
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm", java.util.Locale.getDefault());
|
||||||
|
|
||||||
|
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
||||||
|
com.example.pap_teste.models.Reserva r = ds.getValue(com.example.pap_teste.models.Reserva.class);
|
||||||
|
if (r != null && (r.getEstado().startsWith("Confirmada") || r.getEstado().equals("Pendente"))) {
|
||||||
|
try {
|
||||||
|
java.util.Date rDate = sdf.parse(r.getData() + " " + r.getHora());
|
||||||
|
if (rDate != null) {
|
||||||
|
long rTime = rDate.getTime();
|
||||||
|
// Consider reservations from the last 2 hours and in the future
|
||||||
|
if (rTime >= currentTime - 2L * 60 * 60 * 1000) {
|
||||||
|
if (rTime < timeProx) {
|
||||||
|
timeProx = rTime;
|
||||||
|
proxima = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView txtTitle = findViewById(R.id.txtResTitle);
|
||||||
|
TextView txtTime = findViewById(R.id.txtResTime);
|
||||||
|
Button btnCheckIn = findViewById(R.id.btnCheckIn);
|
||||||
|
Button btnPartilhar = findViewById(R.id.btnPartilhar);
|
||||||
|
|
||||||
|
if (proxima != null) {
|
||||||
|
txtTitle.setText(proxima.getRestauranteName());
|
||||||
|
|
||||||
|
// Formatting to show "Hoje", "Amanhã" or the date itself
|
||||||
|
String dateStr = proxima.getData();
|
||||||
|
try {
|
||||||
|
java.util.Date rDate = sdf.parse(proxima.getData() + " " + proxima.getHora());
|
||||||
|
if (rDate != null) {
|
||||||
|
java.util.Calendar cal = java.util.Calendar.getInstance();
|
||||||
|
cal.setTime(rDate);
|
||||||
|
|
||||||
|
java.util.Calendar today = java.util.Calendar.getInstance();
|
||||||
|
|
||||||
|
java.util.Calendar tmr = java.util.Calendar.getInstance();
|
||||||
|
tmr.add(java.util.Calendar.DAY_OF_YEAR, 1);
|
||||||
|
|
||||||
|
if (cal.get(java.util.Calendar.YEAR) == today.get(java.util.Calendar.YEAR) && cal.get(java.util.Calendar.DAY_OF_YEAR) == today.get(java.util.Calendar.DAY_OF_YEAR)) {
|
||||||
|
dateStr = "Hoje";
|
||||||
|
} else if (cal.get(java.util.Calendar.YEAR) == tmr.get(java.util.Calendar.YEAR) && cal.get(java.util.Calendar.DAY_OF_YEAR) == tmr.get(java.util.Calendar.DAY_OF_YEAR)) {
|
||||||
|
dateStr = "Amanhã";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
txtTime.setText(String.format("%s às %s • %d pessoas", dateStr, proxima.getHora(), proxima.getPessoas()));
|
||||||
|
btnCheckIn.setVisibility(android.view.View.VISIBLE);
|
||||||
|
btnPartilhar.setVisibility(android.view.View.VISIBLE);
|
||||||
|
|
||||||
|
String encodedEmail = proxima.getRestauranteEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users").child(encodedEmail)
|
||||||
|
.child("logoUrl").get().addOnSuccessListener(s -> {
|
||||||
|
if (!isDestroyed() && s.exists() && s.getValue() != null) {
|
||||||
|
android.widget.ImageView imgResIcon = findViewById(R.id.imgResIcon);
|
||||||
|
com.bumptech.glide.Glide.with(ClientDashboardActivity.this).load(s.getValue(String.class)).circleCrop().into(imgResIcon);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
com.example.pap_teste.models.Reserva finalProxima = proxima;
|
||||||
|
btnCheckIn.setOnClickListener(v -> {
|
||||||
|
boolean hasLocationPermission = androidx.core.app.ActivityCompat.checkSelfPermission(ClientDashboardActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION) == android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
|
if (!hasLocationPermission) {
|
||||||
|
android.widget.Toast.makeText(ClientDashboardActivity.this, "Dê permissões de localização para aceder ao check-in.", android.widget.Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
Intent intent = new Intent(ClientDashboardActivity.this, CheckInAntecipadoActivity.class);
|
||||||
|
intent.putExtra("restaurant_email", finalProxima.getRestauranteEmail());
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
txtTitle.setText("Sem reservas ativas");
|
||||||
|
txtTime.setText("Explore os restaurantes e reserve!");
|
||||||
|
btnCheckIn.setVisibility(android.view.View.GONE);
|
||||||
|
btnPartilhar.setVisibility(android.view.View.GONE);
|
||||||
|
android.widget.ImageView imgResIcon = findViewById(R.id.imgResIcon);
|
||||||
|
imgResIcon.setImageResource(R.drawable.circle_bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onCancelled(com.google.firebase.database.DatabaseError error) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,26 @@ import com.google.firebase.database.ValueEventListener;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.content.Intent;
|
||||||
|
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 androidx.activity.result.ActivityResultLauncher;
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts;
|
||||||
|
|
||||||
public class DefinicoesAdminActivity extends AppCompatActivity {
|
public class DefinicoesAdminActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private EditText inputRadius, inputAddress;
|
private EditText inputRadius, inputAddress;
|
||||||
private android.widget.Spinner spinnerCategory;
|
private android.widget.Spinner spinnerCategory;
|
||||||
|
private ImageView imgLogo;
|
||||||
private DatabaseReference databaseReference;
|
private DatabaseReference databaseReference;
|
||||||
private String documentId;
|
private String documentId;
|
||||||
private String[] categories = {"Carnes", "Massas", "Sushi", "Pizzas", "Sobremesas"};
|
private String photoUrl;
|
||||||
|
private ActivityResultLauncher<Intent> imagePickerLauncher;
|
||||||
|
private String[] categories = {"Carnes", "Massas", "Sushi", "Pizzas", "Sobremesas", "Italiana", "Moderna"};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -51,6 +64,7 @@ public class DefinicoesAdminActivity extends AppCompatActivity {
|
|||||||
inputRadius = findViewById(R.id.inputRadius);
|
inputRadius = findViewById(R.id.inputRadius);
|
||||||
inputAddress = findViewById(R.id.inputAddress);
|
inputAddress = findViewById(R.id.inputAddress);
|
||||||
spinnerCategory = findViewById(R.id.spinnerCategory);
|
spinnerCategory = findViewById(R.id.spinnerCategory);
|
||||||
|
imgLogo = findViewById(R.id.imgRestaurantLogo);
|
||||||
|
|
||||||
android.widget.ArrayAdapter<String> adapter = new android.widget.ArrayAdapter<>(this,
|
android.widget.ArrayAdapter<String> adapter = new android.widget.ArrayAdapter<>(this,
|
||||||
android.R.layout.simple_spinner_item, categories);
|
android.R.layout.simple_spinner_item, categories);
|
||||||
@@ -59,16 +73,79 @@ public class DefinicoesAdminActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
Button btnSave = findViewById(R.id.btnSaveSettings);
|
Button btnSave = findViewById(R.id.btnSaveSettings);
|
||||||
Button btnBack = findViewById(R.id.btnVoltar);
|
Button btnBack = findViewById(R.id.btnVoltar);
|
||||||
|
Button btnChangeLogo = findViewById(R.id.btnChangeLogo);
|
||||||
|
|
||||||
if (btnBack != null) {
|
if (btnBack != null) {
|
||||||
btnBack.setOnClickListener(v -> finish());
|
btnBack.setOnClickListener(v -> finish());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imagePickerLauncher = registerForActivityResult(
|
||||||
|
new ActivityResultContracts.StartActivityForResult(),
|
||||||
|
result -> {
|
||||||
|
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
|
||||||
|
Uri imageUri = result.getData().getData();
|
||||||
|
if (imageUri != null) {
|
||||||
|
uploadImageToFirebase(imageUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
btnChangeLogo.setOnClickListener(v -> {
|
||||||
|
String[] options = {"Galeria", "URL da Imagem"};
|
||||||
|
new androidx.appcompat.app.AlertDialog.Builder(this)
|
||||||
|
.setTitle("Escolher Logótipo")
|
||||||
|
.setItems(options, (dialog, which) -> {
|
||||||
|
if (which == 0) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_PICK);
|
||||||
|
intent.setType("image/*");
|
||||||
|
imagePickerLauncher.launch(intent);
|
||||||
|
} else {
|
||||||
|
showUrlInputDialog();
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
});
|
||||||
|
|
||||||
loadCurrentSettings();
|
loadCurrentSettings();
|
||||||
|
|
||||||
btnSave.setOnClickListener(v -> saveSettings());
|
btnSave.setOnClickListener(v -> saveSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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(imgLogo);
|
||||||
|
Toast.makeText(this, "Logótipo definido!", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton("Cancelar", (dialog, which) -> dialog.cancel());
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadImageToFirebase(Uri imageUri) {
|
||||||
|
if (documentId == null) return;
|
||||||
|
|
||||||
|
StorageReference storageRef = FirebaseStorage.getInstance().getReference()
|
||||||
|
.child("restaurant_logos/" + UUID.randomUUID().toString());
|
||||||
|
|
||||||
|
storageRef.putFile(imageUri).addOnSuccessListener(taskSnapshot -> {
|
||||||
|
storageRef.getDownloadUrl().addOnSuccessListener(uri -> {
|
||||||
|
photoUrl = uri.toString();
|
||||||
|
Glide.with(this).load(photoUrl).circleCrop().into(imgLogo);
|
||||||
|
});
|
||||||
|
}).addOnFailureListener(e -> {
|
||||||
|
Toast.makeText(this, "Falha no upload: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void loadCurrentSettings() {
|
private void loadCurrentSettings() {
|
||||||
if (documentId == null)
|
if (documentId == null)
|
||||||
return;
|
return;
|
||||||
@@ -96,6 +173,12 @@ public class DefinicoesAdminActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (snapshot.hasChild("logoUrl")) {
|
||||||
|
photoUrl = snapshot.child("logoUrl").getValue(String.class);
|
||||||
|
if (photoUrl != null && !photoUrl.isEmpty()) {
|
||||||
|
Glide.with(DefinicoesAdminActivity.this).load(photoUrl).circleCrop().into(imgLogo);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +209,9 @@ public class DefinicoesAdminActivity extends AppCompatActivity {
|
|||||||
updates.put("securityDistance", radius);
|
updates.put("securityDistance", radius);
|
||||||
updates.put("address", addressStr);
|
updates.put("address", addressStr);
|
||||||
updates.put("category", selectedCategory);
|
updates.put("category", selectedCategory);
|
||||||
|
if (photoUrl != null) {
|
||||||
|
updates.put("logoUrl", photoUrl);
|
||||||
|
}
|
||||||
|
|
||||||
databaseReference.child(documentId).updateChildren(updates)
|
databaseReference.child(documentId).updateChildren(updates)
|
||||||
.addOnSuccessListener(aVoid -> {
|
.addOnSuccessListener(aVoid -> {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
|||||||
for (com.google.firebase.database.DataSnapshot data : snapshot.getChildren()) {
|
for (com.google.firebase.database.DataSnapshot data : snapshot.getChildren()) {
|
||||||
com.example.pap_teste.models.Reserva r = data
|
com.example.pap_teste.models.Reserva r = data
|
||||||
.getValue(com.example.pap_teste.models.Reserva.class);
|
.getValue(com.example.pap_teste.models.Reserva.class);
|
||||||
if (r != null) {
|
if (r != null && r.getEstado() != null && !"Arquivada".equals(r.getEstado())) {
|
||||||
reservas.add(r);
|
reservas.add(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,24 +145,38 @@ public class DetalhesReservasActivity extends AppCompatActivity {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
new androidx.appcompat.app.AlertDialog.Builder(this)
|
new androidx.appcompat.app.AlertDialog.Builder(this)
|
||||||
.setTitle("Apagar Reserva")
|
.setTitle("Apagar/Arquivar Reserva")
|
||||||
.setMessage("Tem a certeza que deseja apagar esta reserva?")
|
.setMessage("Tem a certeza que deseja limpar esta reserva da lista?")
|
||||||
.setPositiveButton("Apagar", (dialog, which) -> {
|
.setPositiveButton("Sim", (dialog, which) -> {
|
||||||
String idReserva = reservas.get(selectedIndex).getId();
|
com.example.pap_teste.models.Reserva r = reservas.get(selectedIndex);
|
||||||
|
String idReserva = r.getId();
|
||||||
|
|
||||||
|
if ("Concluída".equals(r.getEstado()) || r.getEstado().startsWith("Confirmada")) {
|
||||||
|
databaseReference.child(idReserva).child("estado").setValue("Arquivada").addOnCompleteListener(task -> {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
clearSelectionAndShowMessage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
databaseReference.child(idReserva).removeValue().addOnCompleteListener(task -> {
|
databaseReference.child(idReserva).removeValue().addOnCompleteListener(task -> {
|
||||||
if (task.isSuccessful()) {
|
if (task.isSuccessful()) {
|
||||||
|
clearSelectionAndShowMessage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton("Voltar", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearSelectionAndShowMessage() {
|
||||||
selectedIndex = -1;
|
selectedIndex = -1;
|
||||||
txtInfo.setText("Selecione uma reserva");
|
txtInfo.setText("Selecione uma reserva");
|
||||||
txtNotas.setText("");
|
txtNotas.setText("");
|
||||||
txtEstado.setText("Estado:");
|
txtEstado.setText("Estado:");
|
||||||
txtMensagem.setText("Reserva apagada com sucesso.");
|
txtMensagem.setText("Reserva processada e apagada da vista.");
|
||||||
toggleButtons(null);
|
toggleButtons(null);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
})
|
|
||||||
.setNegativeButton("Voltar", null)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void atualizarEstadoSelecionado(String novoEstado) {
|
private void atualizarEstadoSelecionado(String novoEstado) {
|
||||||
if (selectedIndex < 0 || selectedIndex >= reservas.size()) {
|
if (selectedIndex < 0 || selectedIndex >= reservas.size()) {
|
||||||
|
|||||||
@@ -64,9 +64,160 @@ public class EstablishmentDashboardActivity extends AppCompatActivity {
|
|||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
findViewById(R.id.cardReservasHoje).setOnClickListener(v -> {
|
||||||
|
Intent intent = new Intent(this, DetalhesReservasActivity.class);
|
||||||
|
intent.putExtra(MainActivity.EXTRA_EMAIL, getIntent().getStringExtra(MainActivity.EXTRA_EMAIL));
|
||||||
|
startActivity(intent);
|
||||||
|
});
|
||||||
|
|
||||||
if (btnBack != null) {
|
if (btnBack != null) {
|
||||||
|
|
||||||
btnBack.setOnClickListener(v -> finish());
|
btnBack.setOnClickListener(v -> finish());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadProximasReservas();
|
||||||
|
loadEstatisticas();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadProximasReservas() {
|
||||||
|
android.widget.LinearLayout llProximasReservas = findViewById(R.id.llProximasReservas);
|
||||||
|
String email = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL);
|
||||||
|
if (email == null) {
|
||||||
|
if (com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null) {
|
||||||
|
email = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail();
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
java.util.Calendar cal = java.util.Calendar.getInstance();
|
||||||
|
String todayDate = cal.get(java.util.Calendar.DAY_OF_MONTH) + "/" +
|
||||||
|
(cal.get(java.util.Calendar.MONTH) + 1) + "/" +
|
||||||
|
cal.get(java.util.Calendar.YEAR);
|
||||||
|
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reservas")
|
||||||
|
.orderByChild("restauranteEmail").equalTo(email)
|
||||||
|
.addValueEventListener(new com.google.firebase.database.ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
llProximasReservas.removeAllViews();
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
||||||
|
com.example.pap_teste.models.Reserva r = ds.getValue(com.example.pap_teste.models.Reserva.class);
|
||||||
|
if (r != null && r.getEstado() != null && (r.getEstado().startsWith("Confirmada") || r.getEstado().equals("Concluída")) && todayDate.equals(r.getData())) {
|
||||||
|
found = true;
|
||||||
|
addReservaView(llProximasReservas, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
TextView empty = new TextView(EstablishmentDashboardActivity.this);
|
||||||
|
empty.setText("Não há reservas confirmadas para hoje.");
|
||||||
|
empty.setTextColor(android.graphics.Color.parseColor("#5F5F5F"));
|
||||||
|
empty.setTextSize(14f);
|
||||||
|
llProximasReservas.addView(empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addReservaView(android.widget.LinearLayout container, com.example.pap_teste.models.Reserva r) {
|
||||||
|
TextView title = new TextView(this);
|
||||||
|
title.setText(String.format("%s - %s", r.getHora(), r.getData()));
|
||||||
|
title.setTextColor(android.graphics.Color.BLACK);
|
||||||
|
title.setTextSize(16f);
|
||||||
|
title.setTypeface(null, android.graphics.Typeface.BOLD);
|
||||||
|
|
||||||
|
TextView subtitle = new TextView(this);
|
||||||
|
subtitle.setText(String.format("Cliente: %s • %d pessoas", r.getClienteEmail(), r.getPessoas()));
|
||||||
|
subtitle.setTextColor(android.graphics.Color.parseColor("#5F5F5F"));
|
||||||
|
subtitle.setTextSize(14f);
|
||||||
|
|
||||||
|
android.widget.LinearLayout.LayoutParams params = new android.widget.LinearLayout.LayoutParams(
|
||||||
|
android.widget.LinearLayout.LayoutParams.MATCH_PARENT, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||||
|
subtitle.setLayoutParams(params);
|
||||||
|
|
||||||
|
android.view.View divider = new android.view.View(this);
|
||||||
|
android.widget.LinearLayout.LayoutParams divParams = new android.widget.LinearLayout.LayoutParams(
|
||||||
|
android.widget.LinearLayout.LayoutParams.MATCH_PARENT, 2);
|
||||||
|
divParams.setMargins(0, 24, 0, 24);
|
||||||
|
divider.setLayoutParams(divParams);
|
||||||
|
divider.setBackgroundColor(android.graphics.Color.parseColor("#EEEEEE"));
|
||||||
|
|
||||||
|
container.addView(title);
|
||||||
|
container.addView(subtitle);
|
||||||
|
container.addView(divider);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadEstatisticas() {
|
||||||
|
TextView txtReservasHoje = findViewById(R.id.txtReservasHojeDash);
|
||||||
|
TextView txtMesasLivres = findViewById(R.id.txtMesasLivresDash);
|
||||||
|
TextView txtListaEspera = findViewById(R.id.txtListaEsperaDash);
|
||||||
|
|
||||||
|
String email = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL);
|
||||||
|
if (email == null) {
|
||||||
|
if (com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null) {
|
||||||
|
email = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail();
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final String finalEmail = email;
|
||||||
|
|
||||||
|
java.util.Calendar cal = java.util.Calendar.getInstance();
|
||||||
|
String todayDate = cal.get(java.util.Calendar.DAY_OF_MONTH) + "/" +
|
||||||
|
(cal.get(java.util.Calendar.MONTH) + 1) + "/" +
|
||||||
|
cal.get(java.util.Calendar.YEAR);
|
||||||
|
|
||||||
|
com.google.firebase.database.DatabaseReference refReservas = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reservas");
|
||||||
|
refReservas.orderByChild("restauranteEmail").equalTo(finalEmail)
|
||||||
|
.addValueEventListener(new com.google.firebase.database.ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
int reservasHoje = 0;
|
||||||
|
int listaEspera = 0;
|
||||||
|
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
||||||
|
com.example.pap_teste.models.Reserva r = ds.getValue(com.example.pap_teste.models.Reserva.class);
|
||||||
|
if (r != null && r.getEstado() != null) {
|
||||||
|
if ((r.getEstado().startsWith("Confirmada") || r.getEstado().equals("Concluída") || r.getEstado().equals("Arquivada")) && todayDate.equals(r.getData())) {
|
||||||
|
reservasHoje++;
|
||||||
|
} else if ("Pendente".equals(r.getEstado())) {
|
||||||
|
listaEspera++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (txtReservasHoje != null) txtReservasHoje.setText(String.format(java.util.Locale.US, "%02d", reservasHoje));
|
||||||
|
if (txtListaEspera != null) txtListaEspera.setText(String.format(java.util.Locale.US, "%02d", listaEspera));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("Mesas")
|
||||||
|
.addValueEventListener(new com.google.firebase.database.ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
int mesasLivres = 0;
|
||||||
|
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
||||||
|
com.example.pap_teste.models.Mesa mesa = ds.getValue(com.example.pap_teste.models.Mesa.class);
|
||||||
|
if (mesa != null && finalEmail.equals(mesa.getRestauranteEmail())) {
|
||||||
|
if ("Livre".equalsIgnoreCase(mesa.getEstado())) {
|
||||||
|
mesasLivres++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (txtMesasLivres != null) txtMesasLivres.setText(String.format(java.util.Locale.US, "%02d", mesasLivres));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,18 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
private String selectedDate = null;
|
private String selectedDate = null;
|
||||||
private String selectedTime = null;
|
private String selectedTime = null;
|
||||||
private int selectedPartySize = 0;
|
|
||||||
|
private final androidx.activity.result.ActivityResultLauncher<android.content.Intent> photoPickerLauncher = registerForActivityResult(
|
||||||
|
new androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult(),
|
||||||
|
result -> {
|
||||||
|
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
|
||||||
|
android.net.Uri imageUri = result.getData().getData();
|
||||||
|
if (imageUri != null) {
|
||||||
|
uploadRestaurantPhoto(imageUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -97,11 +108,10 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
if (name == null) name = ds.child("displayName").getValue(String.class);
|
if (name == null) name = ds.child("displayName").getValue(String.class);
|
||||||
String email = ds.child("email").getValue(String.class);
|
String email = ds.child("email").getValue(String.class);
|
||||||
String cat = ds.child("category").getValue(String.class);
|
String cat = ds.child("category").getValue(String.class);
|
||||||
|
String logoUrl = ds.child("logoUrl").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) {
|
if (name != null && email != null) {
|
||||||
restaurantsList.add(new com.example.pap_teste.models.Restaurant(name, cat, email, false));
|
restaurantsList.add(new com.example.pap_teste.models.Restaurant(name, cat, email, false, logoUrl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,49 +132,149 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupReservationOptions() {
|
private void setupReservationOptions() {
|
||||||
// Dates
|
android.widget.Button btnDate = findViewById(R.id.btnSelectDate);
|
||||||
androidx.recyclerview.widget.RecyclerView rvDates = findViewById(R.id.rvDates);
|
android.widget.Button btnTime = findViewById(R.id.btnSelectTime);
|
||||||
java.util.List<String> dates = new java.util.ArrayList<>();
|
android.widget.Button btnVerAvaliacoes = findViewById(R.id.btnVerAvaliacoes);
|
||||||
dates.add("Hoje");
|
android.widget.Button btnUploadFoto = findViewById(R.id.btnUploadFoto);
|
||||||
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
|
btnDate.setOnClickListener(v -> {
|
||||||
androidx.recyclerview.widget.RecyclerView rvTimes = findViewById(R.id.rvTimes);
|
java.util.Calendar cal = java.util.Calendar.getInstance();
|
||||||
java.util.List<String> times = new java.util.ArrayList<>();
|
new android.app.DatePickerDialog(this, (view, year, month, dayOfMonth) -> {
|
||||||
times.add("12:00");
|
selectedDate = dayOfMonth + "/" + (month + 1) + "/" + year;
|
||||||
times.add("13:00");
|
btnDate.setText(selectedDate);
|
||||||
times.add("19:00");
|
}, cal.get(java.util.Calendar.YEAR), cal.get(java.util.Calendar.MONTH), cal.get(java.util.Calendar.DAY_OF_MONTH)).show();
|
||||||
times.add("20:00");
|
});
|
||||||
times.add("21:00");
|
|
||||||
times.add("22:00");
|
|
||||||
rvTimes.setAdapter(new ReservationOptionAdapter(times, time -> selectedTime = time));
|
|
||||||
|
|
||||||
// Party Size
|
btnTime.setOnClickListener(v -> {
|
||||||
androidx.recyclerview.widget.RecyclerView rvParty = findViewById(R.id.rvPartySize);
|
java.util.Calendar cal = java.util.Calendar.getInstance();
|
||||||
java.util.List<String> party = new java.util.ArrayList<>();
|
new android.app.TimePickerDialog(this, (view, hourOfDay, minute) -> {
|
||||||
party.add("1 pessoa");
|
selectedTime = String.format(java.util.Locale.getDefault(), "%02d:%02d", hourOfDay, minute);
|
||||||
party.add("2 pessoas");
|
btnTime.setText(selectedTime);
|
||||||
party.add("3 pessoas");
|
}, cal.get(java.util.Calendar.HOUR_OF_DAY), cal.get(java.util.Calendar.MINUTE), true).show();
|
||||||
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());
|
findViewById(R.id.btnConfirmarReserva).setOnClickListener(v -> saveReservation());
|
||||||
|
|
||||||
|
btnVerAvaliacoes.setOnClickListener(v -> showReviewsDialog());
|
||||||
|
|
||||||
|
btnUploadFoto.setOnClickListener(v -> {
|
||||||
|
android.content.Intent intent = new android.content.Intent(android.content.Intent.ACTION_PICK);
|
||||||
|
intent.setType("image/*");
|
||||||
|
photoPickerLauncher.launch(intent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadRestaurantPhoto(android.net.Uri imageUri) {
|
||||||
|
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||||
|
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
com.google.firebase.storage.StorageReference storageRef = com.google.firebase.storage.FirebaseStorage.getInstance().getReference()
|
||||||
|
.child("restaurant_photos/" + encodedEmail + "/" + java.util.UUID.randomUUID().toString());
|
||||||
|
|
||||||
|
storageRef.putFile(imageUri).addOnSuccessListener(taskSnapshot -> {
|
||||||
|
storageRef.getDownloadUrl().addOnSuccessListener(uri -> {
|
||||||
|
String photoUrl = uri.toString();
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("photos").child(encodedEmail)
|
||||||
|
.push().child("url").setValue(photoUrl).addOnCompleteListener(task -> {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
android.widget.Toast.makeText(this, "Foto adicionada com sucesso!", android.widget.Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).addOnFailureListener(e -> {
|
||||||
|
android.widget.Toast.makeText(this, "Falha no upload: " + e.getMessage(), android.widget.Toast.LENGTH_LONG).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showReviewsDialog() {
|
||||||
|
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||||
|
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
|
||||||
|
com.google.firebase.database.DatabaseReference reviewsRef = com.google.firebase.database.FirebaseDatabase.getInstance()
|
||||||
|
.getReference("reviews").child(encodedEmail);
|
||||||
|
|
||||||
|
reviewsRef.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
java.util.List<String> reviewsList = new java.util.ArrayList<>();
|
||||||
|
for (com.google.firebase.database.DataSnapshot dst : snapshot.getChildren()) {
|
||||||
|
String author = dst.child("author").getValue(String.class);
|
||||||
|
String text = dst.child("text").getValue(String.class);
|
||||||
|
if (author != null && text != null) {
|
||||||
|
reviewsList.add(author + "\n" + text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] reviewsArray = reviewsList.toArray(new String[0]);
|
||||||
|
androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(ExplorarRestaurantesActivity.this)
|
||||||
|
.setTitle("Avaliações")
|
||||||
|
.setItems(reviewsArray, null)
|
||||||
|
.setPositiveButton("Fechar", null)
|
||||||
|
.setNeutralButton("Adicionar", (dialog, which) -> addReviewDialog());
|
||||||
|
|
||||||
|
if (reviewsList.isEmpty()) {
|
||||||
|
builder.setMessage("Ainda sem avaliações.");
|
||||||
|
}
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
||||||
|
android.widget.Toast.makeText(ExplorarRestaurantesActivity.this, "Erro ao carregar avaliações.", android.widget.Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addReviewDialog() {
|
||||||
|
if (selectedRestaurant == null || selectedRestaurant.getEmail() == null) return;
|
||||||
|
|
||||||
|
android.widget.EditText input = new android.widget.EditText(this);
|
||||||
|
input.setHint("Escreva a sua avaliação aqui...");
|
||||||
|
new androidx.appcompat.app.AlertDialog.Builder(this)
|
||||||
|
.setTitle("Adicionar Avaliação")
|
||||||
|
.setView(input)
|
||||||
|
.setPositiveButton("Enviar", (dialog, which) -> {
|
||||||
|
String revText = input.getText().toString().trim();
|
||||||
|
if (!revText.isEmpty()) {
|
||||||
|
com.google.firebase.auth.FirebaseUser currentUser = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
|
||||||
|
if (currentUser != null && currentUser.getEmail() != null) {
|
||||||
|
String userDoc = currentUser.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("users").child(userDoc).get().addOnSuccessListener(snapshot -> {
|
||||||
|
String authorName = snapshot.exists() && snapshot.child("displayName").getValue(String.class) != null
|
||||||
|
? snapshot.child("displayName").getValue(String.class)
|
||||||
|
: "Visitante";
|
||||||
|
submitReviewToFirebase(authorName, revText);
|
||||||
|
}).addOnFailureListener(e -> submitReviewToFirebase("Visitante", revText));
|
||||||
|
} else {
|
||||||
|
submitReviewToFirebase("Visitante", revText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton("Cancelar", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void submitReviewToFirebase(String authorName, String revText) {
|
||||||
|
String encodedEmail = selectedRestaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
java.util.Map<String, Object> review = new java.util.HashMap<>();
|
||||||
|
review.put("author", authorName);
|
||||||
|
review.put("text", revText);
|
||||||
|
|
||||||
|
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reviews")
|
||||||
|
.child(encodedEmail).push().setValue(review).addOnCompleteListener(task -> {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
android.widget.Toast.makeText(this, "Avaliação enviada!", android.widget.Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveReservation() {
|
private void saveReservation() {
|
||||||
if (selectedDate == null || selectedTime == null || selectedPartySize == 0) {
|
android.widget.EditText etPartySize = findViewById(R.id.etPartySize);
|
||||||
|
int partySize = 0;
|
||||||
|
try {
|
||||||
|
partySize = Integer.parseInt(etPartySize.getText().toString());
|
||||||
|
} catch (Exception e) {}
|
||||||
|
|
||||||
|
if (selectedDate == null || selectedTime == null || partySize == 0) {
|
||||||
android.widget.Toast.makeText(this, "Por favor, selecione data, hora e número de pessoas.",
|
android.widget.Toast.makeText(this, "Por favor, selecione data, hora e número de pessoas.",
|
||||||
android.widget.Toast.LENGTH_SHORT).show();
|
android.widget.Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
@@ -185,7 +295,7 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
|
|||||||
selectedRestaurant.getEmail(),
|
selectedRestaurant.getEmail(),
|
||||||
selectedDate,
|
selectedDate,
|
||||||
selectedTime,
|
selectedTime,
|
||||||
selectedPartySize,
|
partySize,
|
||||||
"Pendente");
|
"Pendente");
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
|
|||||||
@@ -3,15 +3,33 @@ package com.example.pap_teste;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import androidx.activity.EdgeToEdge;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.core.graphics.Insets;
|
import androidx.core.graphics.Insets;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.example.pap_teste.models.Restaurant;
|
||||||
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
import com.google.firebase.auth.FirebaseUser;
|
||||||
|
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 FavoritosActivity extends AppCompatActivity {
|
public class FavoritosActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private androidx.recyclerview.widget.RecyclerView rv;
|
||||||
|
private RestaurantAdapter adapter;
|
||||||
|
private List<Restaurant> list;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -28,16 +46,39 @@ public class FavoritosActivity extends AppCompatActivity {
|
|||||||
back.setOnClickListener(v -> finish());
|
back.setOnClickListener(v -> finish());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv = findViewById(R.id.rvFavoritos);
|
||||||
|
list = new ArrayList<>();
|
||||||
|
adapter = new RestaurantAdapter(list, null);
|
||||||
|
rv.setAdapter(adapter);
|
||||||
|
|
||||||
setupFavoritesList();
|
setupFavoritesList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupFavoritesList() {
|
private void setupFavoritesList() {
|
||||||
androidx.recyclerview.widget.RecyclerView rv = findViewById(R.id.rvFavoritos);
|
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||||
java.util.List<com.example.pap_teste.models.Restaurant> list = new java.util.ArrayList<>();
|
if (user != null && user.getEmail() != null) {
|
||||||
list.add(new com.example.pap_teste.models.Restaurant("Sabor & Arte", "Tradicional", "sabor_arte@restaurante.com", true));
|
String encodedUserEmail = user.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
list.add(new com.example.pap_teste.models.Restaurant("O Chuveiro", "Mariscos", "chuveiro@restaurante.com", true));
|
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("users")
|
||||||
|
.child(encodedUserEmail).child("favorites");
|
||||||
|
|
||||||
RestaurantAdapter adapter = new RestaurantAdapter(list, null);
|
favRef.addValueEventListener(new ValueEventListener() {
|
||||||
rv.setAdapter(adapter);
|
@Override
|
||||||
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
list.clear();
|
||||||
|
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||||
|
Restaurant restaurant = ds.getValue(Restaurant.class);
|
||||||
|
if (restaurant != null) {
|
||||||
|
list.add(restaurant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@NonNull DatabaseError error) {
|
||||||
|
Toast.makeText(FavoritosActivity.this, "Erro ao carregar favoritos.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.google.firebase.database.DatabaseError;
|
|||||||
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 com.google.firebase.database.ValueEventListener;
|
import com.google.firebase.database.ValueEventListener;
|
||||||
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -86,9 +87,12 @@ public class GerirMesasActivity extends AppCompatActivity {
|
|||||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
mesas.clear();
|
mesas.clear();
|
||||||
adapter.clear();
|
adapter.clear();
|
||||||
|
String currentUserEmail = FirebaseAuth.getInstance().getCurrentUser() != null
|
||||||
|
? FirebaseAuth.getInstance().getCurrentUser().getEmail()
|
||||||
|
: "";
|
||||||
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
|
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
|
||||||
Mesa mesa = postSnapshot.getValue(Mesa.class);
|
Mesa mesa = postSnapshot.getValue(Mesa.class);
|
||||||
if (mesa != null) {
|
if (mesa != null && (mesa.getRestauranteEmail() == null || mesa.getRestauranteEmail().equals(currentUserEmail))) {
|
||||||
// Ensure the ID is set from the snapshot key if it's missing in the value
|
// Ensure the ID is set from the snapshot key if it's missing in the value
|
||||||
mesa.setId(postSnapshot.getKey());
|
mesa.setId(postSnapshot.getKey());
|
||||||
mesas.add(mesa);
|
mesas.add(mesa);
|
||||||
@@ -184,10 +188,13 @@ public class GerirMesasActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
Mesa existente = findMesa(numero);
|
Mesa existente = findMesa(numero);
|
||||||
String mesaId;
|
String mesaId;
|
||||||
|
String currentUserEmail = FirebaseAuth.getInstance().getCurrentUser() != null
|
||||||
|
? FirebaseAuth.getInstance().getCurrentUser().getEmail()
|
||||||
|
: "";
|
||||||
|
|
||||||
if (existente == null) {
|
if (existente == null) {
|
||||||
mesaId = mDatabase.push().getKey();
|
mesaId = mDatabase.push().getKey();
|
||||||
Mesa novaMesa = new Mesa(mesaId, numero, capacidade, estado);
|
Mesa novaMesa = new Mesa(mesaId, numero, capacidade, estado, currentUserEmail);
|
||||||
if (mesaId != null) {
|
if (mesaId != null) {
|
||||||
mDatabase.child(mesaId).setValue(novaMesa);
|
mDatabase.child(mesaId).setValue(novaMesa);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,6 +160,11 @@ public class GestaoStaffActivity extends AppCompatActivity {
|
|||||||
btnAtribuir.setOnClickListener(v -> guardarAtribuicao());
|
btnAtribuir.setOnClickListener(v -> guardarAtribuicao());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button btnEliminar = findViewById(R.id.btnEliminarStaff);
|
||||||
|
if (btnEliminar != null) {
|
||||||
|
btnEliminar.setOnClickListener(v -> eliminarStaff());
|
||||||
|
}
|
||||||
|
|
||||||
if (floatingActionButton != null) {
|
if (floatingActionButton != null) {
|
||||||
floatingActionButton.setOnClickListener(new View.OnClickListener() {
|
floatingActionButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -216,6 +221,38 @@ public class GestaoStaffActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void eliminarStaff() {
|
||||||
|
String nome = "";
|
||||||
|
if (spinnerNomeStaff.getSelectedItem() != null) {
|
||||||
|
nome = spinnerNomeStaff.getSelectedItem().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nome.isEmpty()) {
|
||||||
|
Toast.makeText(this, "Selecione um funcionário primeiro.", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Staff staffToDelete = findByNome(nome);
|
||||||
|
if (staffToDelete != null) {
|
||||||
|
new androidx.appcompat.app.AlertDialog.Builder(this)
|
||||||
|
.setTitle("Eliminar Staff")
|
||||||
|
.setMessage("Tem a certeza que deseja eliminar o funcionário " + staffToDelete.getName() + "?")
|
||||||
|
.setPositiveButton("Eliminar", (dialog, which) -> {
|
||||||
|
staffRef.child(staffToDelete.getId()).removeValue()
|
||||||
|
.addOnSuccessListener(aVoid -> {
|
||||||
|
txtMensagemStaff.setText(staffToDelete.getName() + " foi eliminado.");
|
||||||
|
})
|
||||||
|
.addOnFailureListener(e -> {
|
||||||
|
Toast.makeText(this, "Erro ao eliminar: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.setNegativeButton("Cancelar", null)
|
||||||
|
.show();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "Staff não encontrado.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Staff findByNome(String nome) {
|
private Staff findByNome(String nome) {
|
||||||
for (Staff item : staffList) {
|
for (Staff item : staffList) {
|
||||||
if (item.getName().equalsIgnoreCase(nome)) {
|
if (item.getName().equalsIgnoreCase(nome)) {
|
||||||
|
|||||||
@@ -10,8 +10,32 @@ import androidx.core.view.WindowInsetsCompat;
|
|||||||
|
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
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 ListaEsperaActivity extends AppCompatActivity {
|
public class ListaEsperaActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private final List<Reserva> reservasPendentes = new ArrayList<>();
|
||||||
|
private ArrayAdapter<String> adapter;
|
||||||
|
private ListView listReservas;
|
||||||
|
private TextView txtInfo, txtNotas, txtMensagem;
|
||||||
|
private Button btnConfirmar, btnRecusar;
|
||||||
|
private int selectedIndex = -1;
|
||||||
|
private String restaurantEmail;
|
||||||
|
private DatabaseReference databaseReference;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -23,11 +47,199 @@ public class ListaEsperaActivity extends AppCompatActivity {
|
|||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
restaurantEmail = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL);
|
||||||
|
if (restaurantEmail == null) {
|
||||||
|
// Se o extra não chegou, falha segura
|
||||||
|
if (com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null) {
|
||||||
|
restaurantEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail();
|
||||||
|
} else {
|
||||||
|
restaurantEmail = "sabor_arte@restaurante.com";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bindViews();
|
||||||
|
setupList();
|
||||||
|
setupActions();
|
||||||
|
loadReservasPendentes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindViews() {
|
||||||
|
listReservas = findViewById(R.id.listReservasP);
|
||||||
|
txtInfo = findViewById(R.id.txtReservaInfoP);
|
||||||
|
txtNotas = findViewById(R.id.txtReservaNotasP);
|
||||||
|
txtMensagem = findViewById(R.id.txtMensagemReservaP);
|
||||||
|
btnConfirmar = findViewById(R.id.btnConfirmarReservaP);
|
||||||
|
btnRecusar = findViewById(R.id.btnRecusarReservaP);
|
||||||
|
|
||||||
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 -> finish());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupList() {
|
||||||
|
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_activated_1);
|
||||||
|
listReservas.setAdapter(adapter);
|
||||||
|
|
||||||
|
listReservas.setOnItemClickListener((parent, view, position, id) -> {
|
||||||
|
selectedIndex = position;
|
||||||
|
mostrarDetalhe(reservasPendentes.get(position));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupActions() {
|
||||||
|
btnConfirmar.setOnClickListener(v -> mostrarMesasDisponiveis());
|
||||||
|
btnRecusar.setOnClickListener(v -> showRecusarDialog());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mostrarMesasDisponiveis() {
|
||||||
|
if (selectedIndex < 0 || selectedIndex >= reservasPendentes.size()) {
|
||||||
|
Toast.makeText(this, "Selecione uma reserva.", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Reserva item = reservasPendentes.get(selectedIndex);
|
||||||
|
|
||||||
|
DatabaseReference mesasRef = FirebaseDatabase.getInstance().getReference("Mesas");
|
||||||
|
mesasRef.orderByChild("restauranteEmail").equalTo(restaurantEmail).addListenerForSingleValueEvent(new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull DataSnapshot snapshot) {
|
||||||
|
List<com.example.pap_teste.models.Mesa> mesasLivres = new ArrayList<>();
|
||||||
|
for (DataSnapshot ds : snapshot.getChildren()) {
|
||||||
|
com.example.pap_teste.models.Mesa m = ds.getValue(com.example.pap_teste.models.Mesa.class);
|
||||||
|
if (m != null && m.getEstado() != null && m.getEstado().equalsIgnoreCase("Livre")) {
|
||||||
|
m.setId(ds.getKey());
|
||||||
|
mesasLivres.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesasLivres.isEmpty()) {
|
||||||
|
new androidx.appcompat.app.AlertDialog.Builder(ListaEsperaActivity.this)
|
||||||
|
.setTitle("Sem mesas disponíveis")
|
||||||
|
.setMessage("Não há mesas livres registadas. Deseja confirmar a reserva mesmo assim (sem lugar reservado)?")
|
||||||
|
.setPositiveButton("Sim", (dialog, which) -> atualizarEstadoSelecionado("Confirmada"))
|
||||||
|
.setNegativeButton("Não", null)
|
||||||
|
.show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] mesaOptions = new String[mesasLivres.size()];
|
||||||
|
for (int i = 0; i < mesasLivres.size(); i++) {
|
||||||
|
com.example.pap_teste.models.Mesa m = mesasLivres.get(i);
|
||||||
|
mesaOptions[i] = String.format("Mesa %d (%d lugares)", m.getNumero(), m.getCapacidade());
|
||||||
|
}
|
||||||
|
|
||||||
|
new androidx.appcompat.app.AlertDialog.Builder(ListaEsperaActivity.this)
|
||||||
|
.setTitle("Atribuir Mesa")
|
||||||
|
.setItems(mesaOptions, (dialog, which) -> {
|
||||||
|
com.example.pap_teste.models.Mesa selecionada = mesasLivres.get(which);
|
||||||
|
confirmarReservaComMesa(item, selecionada);
|
||||||
|
})
|
||||||
|
.setNegativeButton("Cancelar", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull DatabaseError error) {
|
||||||
|
Toast.makeText(ListaEsperaActivity.this, "Erro ao carregar mesas.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void confirmarReservaComMesa(Reserva reserva, com.example.pap_teste.models.Mesa mesa) {
|
||||||
|
String novoEstado = "Confirmada (Mesa " + mesa.getNumero() + ")";
|
||||||
|
databaseReference.child(reserva.getId()).child("estado").setValue(novoEstado).addOnCompleteListener(task -> {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
FirebaseDatabase.getInstance().getReference("Mesas").child(mesa.getId()).child("estado").setValue("Reservada")
|
||||||
|
.addOnCompleteListener(t2 -> {
|
||||||
|
Toast.makeText(this, "Reserva aceite e mesa atribuída com sucesso.", Toast.LENGTH_SHORT).show();
|
||||||
|
selectedIndex = -1;
|
||||||
|
toggleButtons(null);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "Erro ao confirmar reserva.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showRecusarDialog() {
|
||||||
|
if (selectedIndex < 0) return;
|
||||||
|
|
||||||
|
String[] motivos = { "Sem espaço no restaurante", "Fora de horas", "Reserva duplicada", "Outro" };
|
||||||
|
new androidx.appcompat.app.AlertDialog.Builder(this)
|
||||||
|
.setTitle("Motivo da Recusa")
|
||||||
|
.setItems(motivos, (dialog, which) -> {
|
||||||
|
atualizarEstadoSelecionado("Recusada (" + motivos[which] + ")");
|
||||||
|
})
|
||||||
|
.setNegativeButton("Voltar", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void atualizarEstadoSelecionado(String novoEstado) {
|
||||||
|
if (selectedIndex < 0 || selectedIndex >= reservasPendentes.size()) {
|
||||||
|
Toast.makeText(this, "Selecione uma reserva para avaliar.", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reserva item = reservasPendentes.get(selectedIndex);
|
||||||
|
databaseReference.child(item.getId()).child("estado").setValue(novoEstado).addOnCompleteListener(task -> {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
Toast.makeText(this, "Reserva avaliada com sucesso.", Toast.LENGTH_SHORT).show();
|
||||||
|
selectedIndex = -1;
|
||||||
|
toggleButtons(null);
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "Erro ao alterar estado da reserva.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mostrarDetalhe(Reserva item) {
|
||||||
|
txtInfo.setText(String.format("%s • %s", item.getClienteEmail(), item.getHora()));
|
||||||
|
txtNotas.setText(String.format("Data: %s • Pessoas: %d", item.getData(), item.getPessoas()));
|
||||||
|
toggleButtons(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleButtons(Reserva item) {
|
||||||
|
if (item == null) {
|
||||||
|
btnConfirmar.setVisibility(android.view.View.GONE);
|
||||||
|
btnRecusar.setVisibility(android.view.View.GONE);
|
||||||
|
txtInfo.setText("Selecione uma reserva");
|
||||||
|
txtNotas.setText("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
btnConfirmar.setVisibility(android.view.View.VISIBLE);
|
||||||
|
btnRecusar.setVisibility(android.view.View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadReservasPendentes() {
|
||||||
|
databaseReference = FirebaseDatabase.getInstance().getReference("reservas");
|
||||||
|
databaseReference.orderByChild("restauranteEmail").equalTo(restaurantEmail)
|
||||||
|
.addValueEventListener(new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull DataSnapshot snapshot) {
|
||||||
|
reservasPendentes.clear();
|
||||||
|
for (DataSnapshot data : snapshot.getChildren()) {
|
||||||
|
Reserva r = data.getValue(Reserva.class);
|
||||||
|
if (r != null && "Pendente".equals(r.getEstado())) {
|
||||||
|
reservasPendentes.add(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refreshList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull DatabaseError error) {
|
||||||
|
Toast.makeText(ListaEsperaActivity.this, "Erro ao carregar lista de espera.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshList() {
|
||||||
|
adapter.clear();
|
||||||
|
for (Reserva item : reservasPendentes) {
|
||||||
|
adapter.add(String.format("%s - %dp • %s", item.getHora(), item.getPessoas(), item.getClienteEmail()));
|
||||||
|
}
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private EditText inputEstablishmentName;
|
private EditText inputEstablishmentName;
|
||||||
private EditText inputEstablishmentEmail;
|
private EditText inputEstablishmentEmail;
|
||||||
private EditText inputEstablishmentPhone;
|
private EditText inputEstablishmentPhone;
|
||||||
|
private android.widget.TextView txtForgotPassword;
|
||||||
|
private android.widget.ImageView iconPasswordVisibility;
|
||||||
|
private boolean isPasswordVisible = false;
|
||||||
private boolean hasCreatedAccount;
|
private boolean hasCreatedAccount;
|
||||||
private FirebaseAuth firebaseAuth;
|
private FirebaseAuth firebaseAuth;
|
||||||
private DatabaseReference databaseReference;
|
private DatabaseReference databaseReference;
|
||||||
@@ -124,10 +127,20 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
permissionsNeeded.add(Manifest.permission.READ_MEDIA_IMAGES);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
permissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!permissionsNeeded.isEmpty()) {
|
if (!permissionsNeeded.isEmpty()) {
|
||||||
new AlertDialog.Builder(this)
|
new AlertDialog.Builder(this)
|
||||||
.setTitle("Permissões Necessárias")
|
.setTitle("Permissões Necessárias")
|
||||||
.setMessage("Para o correto funcionamento do check-in e serviços de proximidade, precisamos de algumas permissões.")
|
.setMessage("Para o correto funcionamento do check-in, serviços de proximidade e fotos da galeria, precisamos de algumas permissões.")
|
||||||
.setPositiveButton("Configurar", (dialog, which) -> {
|
.setPositiveButton("Configurar", (dialog, which) -> {
|
||||||
permissionRequest.launch(permissionsNeeded.toArray(new String[0]));
|
permissionRequest.launch(permissionsNeeded.toArray(new String[0]));
|
||||||
})
|
})
|
||||||
@@ -149,6 +162,50 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
inputEstablishmentName = findViewById(R.id.inputEstablishmentName);
|
inputEstablishmentName = findViewById(R.id.inputEstablishmentName);
|
||||||
inputEstablishmentEmail = findViewById(R.id.inputEstablishmentEmail);
|
inputEstablishmentEmail = findViewById(R.id.inputEstablishmentEmail);
|
||||||
inputEstablishmentPhone = findViewById(R.id.inputEstablishmentPhone);
|
inputEstablishmentPhone = findViewById(R.id.inputEstablishmentPhone);
|
||||||
|
txtForgotPassword = findViewById(R.id.txtForgotPassword);
|
||||||
|
iconPasswordVisibility = findViewById(R.id.iconPasswordVisibility);
|
||||||
|
|
||||||
|
setupPasswordFeatures();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupPasswordFeatures() {
|
||||||
|
iconPasswordVisibility.setOnClickListener(v -> {
|
||||||
|
isPasswordVisible = !isPasswordVisible;
|
||||||
|
if (isPasswordVisible) {
|
||||||
|
inputPassword.setInputType(android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
|
||||||
|
iconPasswordVisibility.setImageResource(R.drawable.ic_visibility);
|
||||||
|
} else {
|
||||||
|
inputPassword.setInputType(android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||||
|
iconPasswordVisibility.setImageResource(R.drawable.ic_visibility_off);
|
||||||
|
}
|
||||||
|
inputPassword.setSelection(inputPassword.getText().length());
|
||||||
|
});
|
||||||
|
|
||||||
|
txtForgotPassword.setOnClickListener(v -> {
|
||||||
|
String email = inputEmail.getText().toString().trim();
|
||||||
|
if (TextUtils.isEmpty(email)) {
|
||||||
|
Toast.makeText(this, "Por favor, introduza o seu email primeiro.", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle("Recuperar palavra-passe")
|
||||||
|
.setMessage("Deseja enviar um email de recuperação para " + email + "?")
|
||||||
|
.setPositiveButton("Sim", (dialog, which) -> {
|
||||||
|
if (firebaseAuth != null) {
|
||||||
|
firebaseAuth.sendPasswordResetEmail(email)
|
||||||
|
.addOnCompleteListener(task -> {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
Toast.makeText(MainActivity.this, "Email de recuperação enviado!", Toast.LENGTH_LONG).show();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(MainActivity.this, "Falha ao enviar email. Verifique se o endereço está correto.", Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton("Não", null)
|
||||||
|
.show();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupTypeToggle() {
|
private void setupTypeToggle() {
|
||||||
@@ -217,6 +274,10 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
inputEstablishmentName.setVisibility(creatingAccount && isEstablishment ? View.VISIBLE : View.GONE);
|
inputEstablishmentName.setVisibility(creatingAccount && isEstablishment ? View.VISIBLE : View.GONE);
|
||||||
inputEstablishmentEmail.setVisibility(creatingAccount && isEstablishment ? View.VISIBLE : View.GONE);
|
inputEstablishmentEmail.setVisibility(creatingAccount && isEstablishment ? View.VISIBLE : View.GONE);
|
||||||
inputEstablishmentPhone.setVisibility(creatingAccount && isEstablishment ? View.VISIBLE : View.GONE);
|
inputEstablishmentPhone.setVisibility(creatingAccount && isEstablishment ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
if (txtForgotPassword != null) {
|
||||||
|
txtForgotPassword.setVisibility(creatingAccount ? View.GONE : View.VISIBLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handlePrimaryAction() {
|
private void handlePrimaryAction() {
|
||||||
|
|||||||
@@ -138,57 +138,124 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
private String selectedDate = null;
|
private String selectedDate = null;
|
||||||
private String selectedTime = null;
|
private String selectedTime = null;
|
||||||
private int selectedPartySize = 0;
|
|
||||||
|
|
||||||
private void setupReservationOptions() {
|
private void setupReservationOptions() {
|
||||||
// Dates
|
android.widget.Button btnDate = findViewById(R.id.btnSelectDate);
|
||||||
RecyclerView rvDates = findViewById(R.id.rvDates);
|
android.widget.Button btnTime = findViewById(R.id.btnSelectTime);
|
||||||
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
|
btnDate.setOnClickListener(v -> {
|
||||||
RecyclerView rvTimes = findViewById(R.id.rvTimes);
|
java.util.Calendar cal = java.util.Calendar.getInstance();
|
||||||
java.util.List<String> times = new java.util.ArrayList<>();
|
new android.app.DatePickerDialog(this, (view, year, month, dayOfMonth) -> {
|
||||||
times.add("12:00");
|
selectedDate = dayOfMonth + "/" + (month + 1) + "/" + year;
|
||||||
times.add("13:00");
|
btnDate.setText(selectedDate);
|
||||||
times.add("19:00");
|
}, cal.get(java.util.Calendar.YEAR), cal.get(java.util.Calendar.MONTH), cal.get(java.util.Calendar.DAY_OF_MONTH)).show();
|
||||||
times.add("20:00");
|
});
|
||||||
times.add("21:00");
|
|
||||||
times.add("22:00");
|
|
||||||
rvTimes.setAdapter(new ReservationOptionAdapter(times, time -> selectedTime = time));
|
|
||||||
|
|
||||||
// Party Size
|
btnTime.setOnClickListener(v -> {
|
||||||
RecyclerView rvParty = findViewById(R.id.rvPartySize);
|
java.util.Calendar cal = java.util.Calendar.getInstance();
|
||||||
java.util.List<String> party = new java.util.ArrayList<>();
|
new android.app.TimePickerDialog(this, (view, hourOfDay, minute) -> {
|
||||||
party.add("1 pessoa");
|
selectedTime = String.format(java.util.Locale.getDefault(), "%02d:%02d", hourOfDay, minute);
|
||||||
party.add("2 pessoas");
|
btnTime.setText(selectedTime);
|
||||||
party.add("3 pessoas");
|
}, cal.get(java.util.Calendar.HOUR_OF_DAY), cal.get(java.util.Calendar.MINUTE), true).show();
|
||||||
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());
|
findViewById(R.id.btnConfirmarReserva).setOnClickListener(v -> saveReservation());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveReservation() {
|
private void saveReservation() {
|
||||||
if (selectedDate == null || selectedTime == null || selectedPartySize == 0) {
|
android.widget.EditText etPartySize = findViewById(R.id.etPartySize);
|
||||||
|
int val = 0;
|
||||||
|
try {
|
||||||
|
val = Integer.parseInt(etPartySize.getText().toString());
|
||||||
|
} catch (Exception e) {}
|
||||||
|
final int partySize = val;
|
||||||
|
|
||||||
|
if (selectedDate == null || selectedTime == null || partySize == 0) {
|
||||||
android.widget.Toast.makeText(this, "Por favor, selecione data, hora e número de pessoas.",
|
android.widget.Toast.makeText(this, "Por favor, selecione data, hora e número de pessoas.",
|
||||||
android.widget.Toast.LENGTH_SHORT).show();
|
android.widget.Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String restEmail = selectedRestaurant.getEmail();
|
||||||
|
|
||||||
|
com.google.firebase.database.DatabaseReference mesasRef = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("Mesas");
|
||||||
|
|
||||||
|
mesasRef.addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
int totalMesas = 0;
|
||||||
|
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
||||||
|
com.example.pap_teste.models.Mesa m = ds.getValue(com.example.pap_teste.models.Mesa.class);
|
||||||
|
if (m != null && restEmail.equals(m.getRestauranteEmail())) {
|
||||||
|
totalMesas++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalMesas == 0) {
|
||||||
|
proceedWithReservation(partySize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkReservationsAndSave(totalMesas, partySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
||||||
|
proceedWithReservation(partySize);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkReservationsAndSave(int totalMesas, final int partySize) {
|
||||||
|
String restEmail = selectedRestaurant.getEmail();
|
||||||
|
com.google.firebase.database.DatabaseReference reservasRef = com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reservas");
|
||||||
|
|
||||||
|
reservasRef.orderByChild("restauranteEmail").equalTo(restEmail).addListenerForSingleValueEvent(new com.google.firebase.database.ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@androidx.annotation.NonNull com.google.firebase.database.DataSnapshot snapshot) {
|
||||||
|
int ocupadas = 0;
|
||||||
|
java.util.Map<String, Integer> ocupacaoPorHora = new java.util.HashMap<>();
|
||||||
|
|
||||||
|
for (com.google.firebase.database.DataSnapshot ds : snapshot.getChildren()) {
|
||||||
|
com.example.pap_teste.models.Reserva r = ds.getValue(com.example.pap_teste.models.Reserva.class);
|
||||||
|
if (r != null && selectedDate.equals(r.getData()) && !"Cancelada".equals(r.getEstado()) && !"Recusada".equals(r.getEstado())) {
|
||||||
|
int count = ocupacaoPorHora.getOrDefault(r.getHora(), 0) + 1;
|
||||||
|
ocupacaoPorHora.put(r.getHora(), count);
|
||||||
|
if (selectedTime.equals(r.getHora())) {
|
||||||
|
ocupadas++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ocupadas >= totalMesas) {
|
||||||
|
String sugestao = "";
|
||||||
|
String[] horasComuns = {"12:00", "12:30", "13:00", "13:30", "14:00", "19:00", "19:30", "20:00", "20:30", "21:00", "21:30", "22:00"};
|
||||||
|
for (String h : horasComuns) {
|
||||||
|
if (ocupacaoPorHora.getOrDefault(h, 0) < totalMesas && !h.equals(selectedTime)) {
|
||||||
|
sugestao = h;
|
||||||
|
break; // Encontramos a primeira sugestão livre
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String msg = "Não há mesas disponíveis para as " + selectedTime + ".";
|
||||||
|
if (!sugestao.isEmpty()) {
|
||||||
|
msg += " Sugestão: tente reservar para as " + sugestao + ".";
|
||||||
|
} else {
|
||||||
|
msg += " Tente para outro dia.";
|
||||||
|
}
|
||||||
|
android.widget.Toast.makeText(NovaReservaActivity.this, msg, android.widget.Toast.LENGTH_LONG).show();
|
||||||
|
} else {
|
||||||
|
proceedWithReservation(partySize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@androidx.annotation.NonNull com.google.firebase.database.DatabaseError error) {
|
||||||
|
proceedWithReservation(partySize);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void proceedWithReservation(int partySize) {
|
||||||
String userEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null
|
String userEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null
|
||||||
? com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail()
|
? com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail()
|
||||||
: "cliente@teste.com";
|
: "cliente@teste.com";
|
||||||
@@ -203,18 +270,18 @@ public class NovaReservaActivity extends AppCompatActivity {
|
|||||||
selectedRestaurant.getEmail(),
|
selectedRestaurant.getEmail(),
|
||||||
selectedDate,
|
selectedDate,
|
||||||
selectedTime,
|
selectedTime,
|
||||||
selectedPartySize,
|
partySize,
|
||||||
"Pendente");
|
"Pendente");
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
ref.child(id).setValue(reserva).addOnCompleteListener(task -> {
|
ref.child(id).setValue(reserva).addOnCompleteListener(task -> {
|
||||||
if (task.isSuccessful()) {
|
if (task.isSuccessful()) {
|
||||||
android.widget.Toast
|
android.widget.Toast
|
||||||
.makeText(this, "Reserva solicitada com sucesso!", android.widget.Toast.LENGTH_SHORT)
|
.makeText(NovaReservaActivity.this, "Reserva solicitada com sucesso!", android.widget.Toast.LENGTH_SHORT)
|
||||||
.show();
|
.show();
|
||||||
finish();
|
finish();
|
||||||
} else {
|
} else {
|
||||||
android.widget.Toast.makeText(this, "Erro ao salvar reserva.", android.widget.Toast.LENGTH_SHORT)
|
android.widget.Toast.makeText(NovaReservaActivity.this, "Erro ao salvar reserva.", android.widget.Toast.LENGTH_SHORT)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -168,10 +168,21 @@ public class ProfileDashboardActivity extends AppCompatActivity {
|
|||||||
storageRef.getDownloadUrl().addOnSuccessListener(uri -> {
|
storageRef.getDownloadUrl().addOnSuccessListener(uri -> {
|
||||||
photoUrl = uri.toString();
|
photoUrl = uri.toString();
|
||||||
Glide.with(this).load(photoUrl).circleCrop().into(imgProfile);
|
Glide.with(this).load(photoUrl).circleCrop().into(imgProfile);
|
||||||
Toast.makeText(this, "Foto carregada!", Toast.LENGTH_SHORT).show();
|
|
||||||
|
// Salvar a nova URL da foto imediatamente na DB
|
||||||
|
Map<String, Object> photoUpdate = new HashMap<>();
|
||||||
|
photoUpdate.put("photoUrl", photoUrl);
|
||||||
|
databaseReference.child(documentId).updateChildren(photoUpdate).addOnCompleteListener(dbTask -> {
|
||||||
|
if (dbTask.isSuccessful()) {
|
||||||
|
Toast.makeText(this, "Foto atualizada com sucesso!", Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "Foto enviada, mas não foi possível atualizar o perfil.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}).addOnFailureListener(e -> {
|
}).addOnFailureListener(e -> {
|
||||||
Toast.makeText(this, "Falha no upload.", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Falha no upload: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
||||||
|
android.util.Log.e("ProfileUpload", "Upload failed", e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,27 @@ public class ReservaAdapter extends RecyclerView.Adapter<ReservaAdapter.ViewHold
|
|||||||
holder.txtStatus.setText("Estado: " + reserva.getEstado());
|
holder.txtStatus.setText("Estado: " + reserva.getEstado());
|
||||||
|
|
||||||
// Enable check-in only if confirmed
|
// Enable check-in only if confirmed
|
||||||
holder.btnCheckIn.setEnabled("Confirmada".equals(reserva.getEstado()));
|
boolean isConfirmed = "Confirmada".equals(reserva.getEstado());
|
||||||
|
boolean hasLocationPermission = androidx.core.app.ActivityCompat.checkSelfPermission(holder.itemView.getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
|
|
||||||
|
if (isConfirmed) {
|
||||||
|
if (hasLocationPermission) {
|
||||||
|
holder.btnCheckIn.setEnabled(true);
|
||||||
|
if (holder.txtLocationWarning != null) {
|
||||||
|
holder.txtLocationWarning.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
holder.btnCheckIn.setEnabled(false);
|
||||||
|
if (holder.txtLocationWarning != null) {
|
||||||
|
holder.txtLocationWarning.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
holder.btnCheckIn.setEnabled(false);
|
||||||
|
if (holder.txtLocationWarning != null) {
|
||||||
|
holder.txtLocationWarning.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Show cancel only if not concluded or already cancelled/refused
|
// Show cancel only if not concluded or already cancelled/refused
|
||||||
boolean canCancel = "Pendente".equals(reserva.getEstado()) || "Confirmada".equals(reserva.getEstado());
|
boolean canCancel = "Pendente".equals(reserva.getEstado()) || "Confirmada".equals(reserva.getEstado());
|
||||||
@@ -67,7 +87,7 @@ public class ReservaAdapter extends RecyclerView.Adapter<ReservaAdapter.ViewHold
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
TextView txtRestaurante, txtDataHora, txtStatus;
|
TextView txtRestaurante, txtDataHora, txtStatus, txtLocationWarning;
|
||||||
Button btnCheckIn, btnCancelar;
|
Button btnCheckIn, btnCancelar;
|
||||||
|
|
||||||
public ViewHolder(@NonNull View itemView) {
|
public ViewHolder(@NonNull View itemView) {
|
||||||
@@ -77,6 +97,7 @@ public class ReservaAdapter extends RecyclerView.Adapter<ReservaAdapter.ViewHold
|
|||||||
txtStatus = itemView.findViewById(R.id.txtReservaStatus);
|
txtStatus = itemView.findViewById(R.id.txtReservaStatus);
|
||||||
btnCheckIn = itemView.findViewById(R.id.btnCheckIn);
|
btnCheckIn = itemView.findViewById(R.id.btnCheckIn);
|
||||||
btnCancelar = itemView.findViewById(R.id.btnCancelar);
|
btnCancelar = itemView.findViewById(R.id.btnCancelar);
|
||||||
|
txtLocationWarning = itemView.findViewById(R.id.txtLocationWarning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,23 +4,19 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ReservationOptionAdapter extends RecyclerView.Adapter<ReservationOptionAdapter.ViewHolder> {
|
public class ReservationOptionAdapter extends RecyclerView.Adapter<ReservationOptionAdapter.ViewHolder> {
|
||||||
|
private List<String> options;
|
||||||
|
private OnOptionClickListener listener;
|
||||||
|
|
||||||
public interface OnOptionSelectedListener {
|
public interface OnOptionClickListener {
|
||||||
void onOptionSelected(String option);
|
void onOptionClick(String option);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<String> options;
|
public ReservationOptionAdapter(List<String> options, OnOptionClickListener listener) {
|
||||||
private final OnOptionSelectedListener listener;
|
|
||||||
private int selectedPosition = -1;
|
|
||||||
|
|
||||||
public ReservationOptionAdapter(List<String> options, OnOptionSelectedListener listener) {
|
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
@@ -28,26 +24,17 @@ public class ReservationOptionAdapter extends RecyclerView.Adapter<ReservationOp
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_reservation_option, parent, false);
|
View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
|
||||||
return new ViewHolder(view);
|
return new ViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
String option = options.get(position);
|
String option = options.get(position);
|
||||||
holder.txtValue.setText(option);
|
holder.text1.setText(option);
|
||||||
|
|
||||||
boolean isSelected = position == selectedPosition;
|
|
||||||
holder.cardRoot.setCardBackgroundColor(isSelected ? 0xFFFF6B6B : 0xFFFFFFFF);
|
|
||||||
holder.txtValue.setTextColor(isSelected ? 0xFFFFFFFF : 0xFF000000);
|
|
||||||
|
|
||||||
holder.itemView.setOnClickListener(v -> {
|
holder.itemView.setOnClickListener(v -> {
|
||||||
int previousSelected = selectedPosition;
|
|
||||||
selectedPosition = holder.getAdapterPosition();
|
|
||||||
notifyItemChanged(previousSelected);
|
|
||||||
notifyItemChanged(selectedPosition);
|
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onOptionSelected(option);
|
listener.onOptionClick(option);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -58,13 +45,10 @@ public class ReservationOptionAdapter extends RecyclerView.Adapter<ReservationOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
TextView txtValue;
|
TextView text1;
|
||||||
androidx.cardview.widget.CardView cardRoot;
|
|
||||||
|
|
||||||
public ViewHolder(@NonNull View itemView) {
|
public ViewHolder(@NonNull View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
txtValue = itemView.findViewById(R.id.txtOptionValue);
|
text1 = itemView.findViewById(android.R.id.text1);
|
||||||
cardRoot = itemView.findViewById(R.id.cardOption);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,18 +10,24 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.example.pap_teste.models.Restaurant;
|
import com.example.pap_teste.models.Restaurant;
|
||||||
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
import com.google.firebase.auth.FirebaseUser;
|
||||||
|
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.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.ViewHolder> {
|
public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.ViewHolder> {
|
||||||
|
private List<Restaurant> restaurants;
|
||||||
|
private OnRestaurantClickListener listener;
|
||||||
|
|
||||||
public interface OnRestaurantClickListener {
|
public interface OnRestaurantClickListener {
|
||||||
void onRestaurantClick(Restaurant restaurant);
|
void onRestaurantClick(Restaurant restaurant);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<Restaurant> restaurants;
|
|
||||||
private final OnRestaurantClickListener listener;
|
|
||||||
|
|
||||||
public RestaurantAdapter(List<Restaurant> restaurants, OnRestaurantClickListener listener) {
|
public RestaurantAdapter(List<Restaurant> restaurants, OnRestaurantClickListener listener) {
|
||||||
this.restaurants = restaurants;
|
this.restaurants = restaurants;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
@@ -37,28 +43,60 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
Restaurant restaurant = restaurants.get(position);
|
Restaurant restaurant = restaurants.get(position);
|
||||||
holder.txtName.setText(restaurant.getName());
|
holder.text1.setText(restaurant.getName());
|
||||||
holder.txtCategory.setText(restaurant.getCategory());
|
holder.text2.setText(restaurant.getCategory() + (restaurant.isAvailable() ? " - Disponível" : " - Indisponível"));
|
||||||
|
|
||||||
updateFavoriteIcon(holder.btnFavorite, restaurant.isFavorite());
|
if (restaurant.getLogoUrl() != null && !restaurant.getLogoUrl().isEmpty()) {
|
||||||
|
com.bumptech.glide.Glide.with(holder.itemView.getContext())
|
||||||
holder.btnFavorite.setOnClickListener(v -> {
|
.load(restaurant.getLogoUrl())
|
||||||
restaurant.setFavorite(!restaurant.isFavorite());
|
.circleCrop()
|
||||||
updateFavoriteIcon(holder.btnFavorite, restaurant.isFavorite());
|
.into(holder.imgThumb);
|
||||||
});
|
} else {
|
||||||
|
holder.imgThumb.setImageResource(R.mipmap.ic_launcher);
|
||||||
|
}
|
||||||
|
|
||||||
holder.itemView.setOnClickListener(v -> {
|
holder.itemView.setOnClickListener(v -> {
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onRestaurantClick(restaurant);
|
listener.onRestaurantClick(restaurant);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||||
|
if (user != null && user.getEmail() != null && restaurant.getEmail() != null) {
|
||||||
|
String encodedUserEmail = user.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
String encodedRestEmail = restaurant.getEmail().replace(".", "_").replace("@", "_at_");
|
||||||
|
DatabaseReference favRef = FirebaseDatabase.getInstance().getReference("users")
|
||||||
|
.child(encodedUserEmail).child("favorites").child(encodedRestEmail);
|
||||||
|
|
||||||
|
favRef.addValueEventListener(new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
if (snapshot.exists()) {
|
||||||
|
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_on);
|
||||||
|
} else {
|
||||||
|
holder.btnFavorite.setImageResource(android.R.drawable.btn_star_big_off);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFavoriteIcon(ImageButton btn, boolean isFavorite) {
|
@Override
|
||||||
if (isFavorite) {
|
public void onCancelled(@NonNull DatabaseError error) { }
|
||||||
btn.setImageResource(android.R.drawable.btn_star_big_on);
|
});
|
||||||
|
|
||||||
|
holder.btnFavorite.setOnClickListener(v -> {
|
||||||
|
favRef.addListenerForSingleValueEvent(new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
if (snapshot.exists()) {
|
||||||
|
favRef.removeValue();
|
||||||
} else {
|
} else {
|
||||||
btn.setImageResource(android.R.drawable.btn_star_big_off);
|
favRef.setValue(restaurant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@NonNull DatabaseError error) { }
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,14 +106,15 @@ public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Vi
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
TextView txtName, txtCategory;
|
TextView text1, text2;
|
||||||
ImageButton btnFavorite;
|
ImageButton btnFavorite;
|
||||||
|
android.widget.ImageView imgThumb;
|
||||||
public ViewHolder(@NonNull View itemView) {
|
public ViewHolder(@NonNull View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
txtName = itemView.findViewById(R.id.txtRestaurantName);
|
text1 = itemView.findViewById(R.id.txtRestaurantName);
|
||||||
txtCategory = itemView.findViewById(R.id.txtRestaurantCategory);
|
text2 = itemView.findViewById(R.id.txtRestaurantCategory);
|
||||||
btnFavorite = itemView.findViewById(R.id.btnFavorite);
|
btnFavorite = itemView.findViewById(R.id.btnFavorite);
|
||||||
|
imgThumb = itemView.findViewById(R.id.imgRestaurantThumb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,16 +5,18 @@ public class Mesa {
|
|||||||
private int numero;
|
private int numero;
|
||||||
private int capacidade;
|
private int capacidade;
|
||||||
private String estado;
|
private String estado;
|
||||||
|
private String restauranteEmail;
|
||||||
|
|
||||||
public Mesa() {
|
public Mesa() {
|
||||||
// Default constructor required for calls to DataSnapshot.getValue(Mesa.class)
|
// Default constructor required for calls to DataSnapshot.getValue(Mesa.class)
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mesa(String id, int numero, int capacidade, String estado) {
|
public Mesa(String id, int numero, int capacidade, String estado, String restauranteEmail) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.numero = numero;
|
this.numero = numero;
|
||||||
this.capacidade = capacidade;
|
this.capacidade = capacidade;
|
||||||
this.estado = estado;
|
this.estado = estado;
|
||||||
|
this.restauranteEmail = restauranteEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
@@ -49,6 +51,14 @@ public class Mesa {
|
|||||||
this.estado = estado;
|
this.estado = estado;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRestauranteEmail() {
|
||||||
|
return restauranteEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRestauranteEmail(String restauranteEmail) {
|
||||||
|
this.restauranteEmail = restauranteEmail;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Mesa " + numero;
|
return "Mesa " + numero;
|
||||||
|
|||||||
@@ -4,57 +4,37 @@ public class Restaurant {
|
|||||||
private String name;
|
private String name;
|
||||||
private String category;
|
private String category;
|
||||||
private String email;
|
private String email;
|
||||||
private String address;
|
private boolean available;
|
||||||
private boolean isFavorite;
|
private String logoUrl;
|
||||||
|
|
||||||
|
// No-argument constructor required for Firebase
|
||||||
public Restaurant() {
|
public Restaurant() {
|
||||||
// Required for Firebase
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Restaurant(String name, String category, String email, boolean isFavorite) {
|
public Restaurant(String name, String category, String email, boolean available) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.category = category;
|
this.category = category;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.isFavorite = isFavorite;
|
this.available = available;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public Restaurant(String name, String category, String email, boolean available, String logoUrl) {
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
|
||||||
|
|
||||||
public String getCategory() {
|
|
||||||
return category;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCategory(String category) {
|
|
||||||
this.category = category;
|
this.category = category;
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmail() {
|
|
||||||
return email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmail(String email) {
|
|
||||||
this.email = email;
|
this.email = email;
|
||||||
|
this.available = available;
|
||||||
|
this.logoUrl = logoUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAddress() {
|
public String getName() { return name; }
|
||||||
return address;
|
public String getCategory() { return category; }
|
||||||
}
|
public String getEmail() { return email; }
|
||||||
|
public boolean isAvailable() { return available; }
|
||||||
|
public String getLogoUrl() { return logoUrl; }
|
||||||
|
|
||||||
public void setAddress(String address) {
|
public void setName(String name) { this.name = name; }
|
||||||
this.address = address;
|
public void setCategory(String category) { this.category = category; }
|
||||||
}
|
public void setEmail(String email) { this.email = email; }
|
||||||
|
public void setAvailable(boolean available) { this.available = available; }
|
||||||
public boolean isFavorite() {
|
public void setLogoUrl(String logoUrl) { this.logoUrl = logoUrl; }
|
||||||
return isFavorite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFavorite(boolean favorite) {
|
|
||||||
isFavorite = favorite;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
9
app/src/main/res/drawable/ic_visibility.xml
Normal file
9
app/src/main/res/drawable/ic_visibility.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#757575"
|
||||||
|
android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 5.99,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
|
||||||
|
</vector>
|
||||||
9
app/src/main/res/drawable/ic_visibility_off.xml
Normal file
9
app/src/main/res/drawable/ic_visibility_off.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#757575"
|
||||||
|
android:pathData="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 5.99,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z"/>
|
||||||
|
</vector>
|
||||||
@@ -5,69 +5,147 @@
|
|||||||
android:id="@+id/main"
|
android:id="@+id/main"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:background="#F7F7F7"
|
||||||
tools:context=".AddStaffActivity">
|
tools:context=".AddStaffActivity">
|
||||||
|
|
||||||
<EditText
|
<!-- Top Bar with Back Button -->
|
||||||
android:id="@+id/nammeEditText"
|
<Button
|
||||||
android:layout_width="0dp"
|
android:id="@+id/btnVoltarAddStaff"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:background="@android:color/transparent"
|
||||||
android:ems="10"
|
android:text="Voltar"
|
||||||
android:hint="Name"
|
android:textAllCaps="false"
|
||||||
android:inputType="text"
|
android:textColor="#FF5252"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
android:textSize="16sp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtAdicionarTitulo"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:text="Novo Funcionário"
|
||||||
|
android:textColor="#000"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/btnVoltarAddStaff" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtAdicionarDesc"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="Introduza os dados e atribuições deste membro:"
|
||||||
|
android:textColor="#666666"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/txtAdicionarTitulo" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:background="#FFFFFF"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="20dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/txtAdicionarDesc">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Nome do Funcionário"
|
||||||
|
android:textColor="#333"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/nammeEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:background="@drawable/input_bg"
|
||||||
|
android:hint="Ex: João Silva"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
android:paddingHorizontal="16dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:text="Zona de Trabalho"
|
||||||
|
android:textColor="#333"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/zoneLayout"
|
android:id="@+id/zoneLayout"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="8dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
app:layout_constraintEnd_toEndOf="@+id/nammeEditText"
|
android:gravity="center_vertical">
|
||||||
app:layout_constraintStart_toStartOf="@+id/nammeEditText"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/nammeEditText">
|
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:id="@+id/zonaSpinner"
|
android:id="@+id/zonaSpinner"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:minHeight="48dp" />
|
android:background="@drawable/input_bg" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btnAddZone"
|
android:id="@+id/btnAddZone"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:background="@drawable/btn_primary"
|
||||||
|
android:text="+"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="+" />
|
android:layout_marginTop="20dp"
|
||||||
</LinearLayout>
|
android:text="Mesa a Atribuir"
|
||||||
|
android:textColor="#333"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/mesaLayout"
|
android:id="@+id/mesaLayout"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="8dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal">
|
||||||
app:layout_constraintEnd_toEndOf="@+id/zoneLayout"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/zoneLayout"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/zoneLayout">
|
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:id="@+id/mesaSpinner"
|
android:id="@+id/mesaSpinner"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:layout_weight="1"
|
android:background="@drawable/input_bg" />
|
||||||
android:minHeight="48dp" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/addButton"
|
android:id="@+id/addButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:text="Button"
|
android:layout_marginTop="32dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:background="@drawable/btn_primary"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
android:text="Adicionar Membro"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -25,8 +25,7 @@
|
|||||||
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="8dp" />
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|||||||
@@ -43,6 +43,26 @@
|
|||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imgRestaurantLogo"
|
||||||
|
android:layout_width="120dp"
|
||||||
|
android:layout_height="120dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:src="@android:drawable/ic_menu_gallery"
|
||||||
|
android:background="#E0E0E0" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnChangeLogo"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="Alterar Logótipo"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:backgroundTint="#2E7D32"
|
||||||
|
android:textColor="#FFFFFF" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -69,10 +69,12 @@
|
|||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/cardReservasHoje"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:foreground="?attr/selectableItemBackground"
|
||||||
app:cardBackgroundColor="#FFFFFF"
|
app:cardBackgroundColor="#FFFFFF"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="16dp"
|
||||||
app:cardElevation="3dp">
|
app:cardElevation="3dp">
|
||||||
@@ -92,10 +94,11 @@
|
|||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/txtReservasHojeDash"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="32"
|
android:text="00"
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="28sp"
|
android:textSize="28sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
@@ -127,10 +130,11 @@
|
|||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/txtMesasLivresDash"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="08"
|
android:text="00"
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="28sp"
|
android:textSize="28sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
@@ -161,10 +165,11 @@
|
|||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/txtListaEsperaDash"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="05"
|
android:text="00"
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="28sp"
|
android:textSize="28sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
@@ -191,6 +196,7 @@
|
|||||||
app:cardElevation="3dp">
|
app:cardElevation="3dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/llProximasReservas"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -199,38 +205,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="20h00 - Mesa 14"
|
android:text="A procurar próximas reservas..."
|
||||||
android:textColor="#000"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="Cliente: Ana Ribeiro • 4 pessoas"
|
|
||||||
android:textColor="#5F5F5F"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:layout_marginVertical="12dp"
|
|
||||||
android:background="#EEEEEE" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="21h15 - Mesa 03"
|
|
||||||
android:textColor="#000"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="Cliente: Bruno Costa • 2 pessoas"
|
|
||||||
android:textColor="#5F5F5F"
|
android:textColor="#5F5F5F"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -65,71 +65,104 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="32dp">
|
android:paddingBottom="32dp">
|
||||||
|
|
||||||
<!-- Section: Date -->
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingHorizontal="24dp"
|
||||||
|
android:layout_marginTop="16dp">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnVerAvaliacoes"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:text="Avaliações"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:backgroundTint="#FFFFFF"
|
||||||
|
android:textColor="#1976D2"
|
||||||
|
app:strokeColor="#1976D2"
|
||||||
|
app:strokeWidth="1dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnUploadFoto"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:text="Adicionar Foto"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:backgroundTint="#FFFFFF"
|
||||||
|
android:textColor="#E53935"
|
||||||
|
app:strokeColor="#E53935"
|
||||||
|
app:strokeWidth="1dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingHorizontal="24dp"
|
||||||
|
android:layout_marginTop="16dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="24dp"
|
android:text="Data da reserva"
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="Escolha a data"
|
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<Button
|
||||||
android:id="@+id/rvDates"
|
android:id="@+id/btnSelectDate"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:clipToPadding="false"
|
android:background="@drawable/btn_light_border"
|
||||||
android:orientation="horizontal"
|
android:text="Selecionar Data"
|
||||||
android:paddingStart="16dp"
|
android:textAllCaps="false"
|
||||||
android:paddingEnd="16dp"
|
android:textColor="#5F5F5F" />
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
|
||||||
|
|
||||||
<!-- Section: Time -->
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:text="Escolha o horário"
|
android:text="Hora da reserva"
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<Button
|
||||||
android:id="@+id/rvTimes"
|
android:id="@+id/btnSelectTime"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:clipToPadding="false"
|
android:background="@drawable/btn_light_border"
|
||||||
android:orientation="horizontal"
|
android:text="Selecionar Hora"
|
||||||
android:paddingStart="16dp"
|
android:textAllCaps="false"
|
||||||
android:paddingEnd="16dp"
|
android:textColor="#5F5F5F" />
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
|
||||||
|
|
||||||
<!-- Section: Party size -->
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:text="Número de pessoas"
|
android:text="Número de pessoas"
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<EditText
|
||||||
android:id="@+id/rvPartySize"
|
android:id="@+id/etPartySize"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:clipToPadding="false"
|
android:background="@drawable/btn_light_border"
|
||||||
android:orientation="horizontal"
|
android:inputType="number"
|
||||||
android:paddingStart="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
android:paddingEnd="16dp"
|
android:hint="Ex: 2"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
android:textColor="#000" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btnConfirmarReserva"
|
android:id="@+id/btnConfirmarReserva"
|
||||||
|
|||||||
@@ -91,6 +91,16 @@
|
|||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="#FFFFFF" />
|
android:textColor="#FFFFFF" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnEliminarStaff"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:text="Eliminar Funcionário"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="#FF5252" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtMensagemStaff"
|
android:id="@+id/txtMensagemStaff"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -45,6 +45,92 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/listReservasP"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:background="#FFFFFF"
|
||||||
|
android:elevation="2dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/txtDescricaoListaEspera"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/detalhesCardP" />
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/detalhesCardP"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
app:cardCornerRadius="12dp"
|
||||||
|
app:cardElevation="4dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtReservaInfoP"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Selecione uma reserva"
|
||||||
|
android:textColor="#000"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtReservaNotasP"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text=""
|
||||||
|
android:textColor="#5F5F5F"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtMensagemReservaP"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text=""
|
||||||
|
android:textColor="#1976D2"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="italic" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnConfirmarReservaP"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:backgroundTint="#4CAF50"
|
||||||
|
android:text="Aceitar"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="#FFF"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnRecusarReservaP"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:backgroundTint="#E53935"
|
||||||
|
android:text="Recusar"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="#FFF"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -153,8 +153,7 @@
|
|||||||
android:background="@drawable/input_bg"
|
android:background="@drawable/input_bg"
|
||||||
android:hint="Email"
|
android:hint="Email"
|
||||||
android:inputType="textEmailAddress"
|
android:inputType="textEmailAddress"
|
||||||
android:padding="12dp"
|
android:padding="12dp" />
|
||||||
android:text="EstabelecimentoPap@gmail.com" />
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/inputOwnerPhone"
|
android:id="@+id/inputOwnerPhone"
|
||||||
@@ -200,16 +199,46 @@
|
|||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/inputPassword"
|
android:id="@+id/inputPassword"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:background="@drawable/input_bg"
|
android:background="@drawable/input_bg"
|
||||||
android:hint="Palavra-passe"
|
android:hint="Palavra-passe"
|
||||||
android:inputType="textPassword"
|
android:inputType="textPassword"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="48dp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iconPasswordVisibility"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:text="PaP@P.1" />
|
android:src="@drawable/ic_visibility_off"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtForgotPassword"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:text="Esqueceu-se da palavra-passe?"
|
||||||
|
android:textColor="#1976D2"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btnFinalCriarConta"
|
android:id="@+id/btnFinalCriarConta"
|
||||||
|
|||||||
@@ -74,71 +74,70 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="32dp">
|
android:paddingBottom="32dp">
|
||||||
|
|
||||||
<!-- Section: Date -->
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingHorizontal="24dp"
|
||||||
|
android:layout_marginTop="16dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="24dp"
|
android:text="Data da reserva"
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="Escolha a data"
|
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<Button
|
||||||
android:id="@+id/rvDates"
|
android:id="@+id/btnSelectDate"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:clipToPadding="false"
|
android:background="@drawable/btn_light_border"
|
||||||
android:orientation="horizontal"
|
android:text="Selecionar Data"
|
||||||
android:paddingStart="16dp"
|
android:textAllCaps="false"
|
||||||
android:paddingEnd="16dp"
|
android:textColor="#5F5F5F" />
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
|
||||||
|
|
||||||
<!-- Section: Time -->
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:text="Escolha o horário"
|
android:text="Hora da reserva"
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<Button
|
||||||
android:id="@+id/rvTimes"
|
android:id="@+id/btnSelectTime"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:clipToPadding="false"
|
android:background="@drawable/btn_light_border"
|
||||||
android:orientation="horizontal"
|
android:text="Selecionar Hora"
|
||||||
android:paddingStart="16dp"
|
android:textAllCaps="false"
|
||||||
android:paddingEnd="16dp"
|
android:textColor="#5F5F5F" />
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
|
||||||
|
|
||||||
<!-- Section: Party size -->
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:text="Número de pessoas"
|
android:text="Número de pessoas"
|
||||||
android:textColor="#000"
|
android:textColor="#000"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<EditText
|
||||||
android:id="@+id/rvPartySize"
|
android:id="@+id/etPartySize"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:clipToPadding="false"
|
android:background="@drawable/btn_light_border"
|
||||||
android:orientation="horizontal"
|
android:inputType="number"
|
||||||
android:paddingStart="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
android:paddingEnd="16dp"
|
android:hint="Ex: 2"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
android:textColor="#000" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btnConfirmarReserva"
|
android:id="@+id/btnConfirmarReserva"
|
||||||
|
|||||||
@@ -69,5 +69,16 @@
|
|||||||
android:background="@drawable/btn_light_border"
|
android:background="@drawable/btn_light_border"
|
||||||
android:textColor="#C62828" />
|
android:textColor="#C62828" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtLocationWarning"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="Dê permissões de localização para aceder ao check-in."
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textColor="#D32F2F"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:visibility="gone" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
<?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>
|
|
||||||
@@ -13,11 +13,22 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="16dp">
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imgRestaurantThumb"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_toEndOf="@id/imgRestaurantThumb"
|
||||||
android:layout_toStartOf="@id/btnFavorite"
|
android:layout_toStartOf="@id/btnFavorite"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "9.0.1"
|
agp = "9.1.0"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.3.0"
|
junitVersion = "1.3.0"
|
||||||
espressoCore = "3.7.0"
|
espressoCore = "3.7.0"
|
||||||
|
|||||||
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,7 +1,7 @@
|
|||||||
#Tue Feb 24 17:05:40 WET 2026
|
#Tue Feb 24 17:05:40 WET 2026
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=a17ddd85a26b6a7f5ddb71ff8b05fc5104c0202c6e64782429790c933686c806
|
distributionSha256Sum=b266d5ff6b90eada6dc3b20cb090e3731302e553a27c5d3e4df1f0d76beaff06
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
Reference in New Issue
Block a user