This commit is contained in:
2026-04-16 10:34:55 +01:00
parent 740680e9fb
commit 404f28da15
13 changed files with 527 additions and 118 deletions

View File

@@ -5,6 +5,9 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_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 -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />

View File

@@ -51,6 +51,11 @@ public class AddStaffActivity extends AppCompatActivity {
btnAddZone = findViewById(R.id.btnAddZone);
mesaSpinner = findViewById(R.id.mesaSpinner);
Button btnVoltarAddStaff = findViewById(R.id.btnVoltarAddStaff);
if (btnVoltarAddStaff != null) {
btnVoltarAddStaff.setOnClickListener(v -> finish());
}
zones = new ArrayList<>();
zones.add("Sala");
zones.add("Esplanada");

View File

@@ -56,6 +56,7 @@ public class ClientDashboardActivity extends AppCompatActivity {
fetchProfilePicture();
setupCategories();
setupActions();
loadNextReservation();
}
private void updateGreeting() {
@@ -106,17 +107,6 @@ public class ClientDashboardActivity extends AppCompatActivity {
findViewById(R.id.btnVoltar).setOnClickListener(v -> finish());
findViewById(R.id.btnCheckIn).setOnClickListener(v -> {
boolean hasLocationPermission = androidx.core.app.ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == android.content.pm.PackageManager.PERMISSION_GRANTED;
if (!hasLocationPermission) {
android.widget.Toast.makeText(this, "Dê permissões de localização para aceder ao check-in.", android.widget.Toast.LENGTH_SHORT).show();
} else {
Intent intent = new Intent(this, CheckInAntecipadoActivity.class);
intent.putExtra("restaurant_email", "sabor_arte@restaurante.com");
startActivity(intent);
}
});
findViewById(R.id.btnPartilhar).setOnClickListener(
v -> startActivity(new Intent(this, PartilharReservaActivity.class)));
@@ -130,4 +120,105 @@ public class ClientDashboardActivity extends AppCompatActivity {
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) {}
});
}
}

View File

@@ -79,7 +79,7 @@ public class DetalhesReservasActivity extends AppCompatActivity {
for (com.google.firebase.database.DataSnapshot data : snapshot.getChildren()) {
com.example.pap_teste.models.Reserva r = data
.getValue(com.example.pap_teste.models.Reserva.class);
if (r != null) {
if (r != null && r.getEstado() != null && !"Arquivada".equals(r.getEstado())) {
reservas.add(r);
}
}
@@ -145,24 +145,38 @@ public class DetalhesReservasActivity extends AppCompatActivity {
return;
new androidx.appcompat.app.AlertDialog.Builder(this)
.setTitle("Apagar Reserva")
.setMessage("Tem a certeza que deseja apagar esta reserva?")
.setPositiveButton("Apagar", (dialog, which) -> {
String idReserva = reservas.get(selectedIndex).getId();
.setTitle("Apagar/Arquivar Reserva")
.setMessage("Tem a certeza que deseja limpar esta reserva da lista?")
.setPositiveButton("Sim", (dialog, which) -> {
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 -> {
if (task.isSuccessful()) {
clearSelectionAndShowMessage();
}
});
}
})
.setNegativeButton("Voltar", null)
.show();
}
private void clearSelectionAndShowMessage() {
selectedIndex = -1;
txtInfo.setText("Selecione uma reserva");
txtNotas.setText("");
txtEstado.setText("Estado:");
txtMensagem.setText("Reserva apagada com sucesso.");
txtMensagem.setText("Reserva processada e apagada da vista.");
toggleButtons(null);
}
});
})
.setNegativeButton("Voltar", null)
.show();
}
private void atualizarEstadoSelecionado(String novoEstado) {
if (selectedIndex < 0 || selectedIndex >= reservas.size()) {

View File

@@ -64,12 +64,19 @@ public class EstablishmentDashboardActivity extends AppCompatActivity {
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) {
btnBack.setOnClickListener(v -> finish());
}
loadProximasReservas();
loadEstatisticas();
}
private void loadProximasReservas() {
@@ -83,6 +90,11 @@ public class EstablishmentDashboardActivity extends AppCompatActivity {
}
}
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() {
@@ -93,7 +105,7 @@ public class EstablishmentDashboardActivity extends AppCompatActivity {
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 && "Confirmada".equals(r.getEstado())) {
if (r != null && r.getEstado() != null && (r.getEstado().startsWith("Confirmada") || r.getEstado().equals("Concluída")) && todayDate.equals(r.getData())) {
found = true;
addReservaView(llProximasReservas, r);
}
@@ -141,4 +153,71 @@ public class EstablishmentDashboardActivity extends AppCompatActivity {
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) {
}
});
}
}

View File

@@ -26,6 +26,17 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
private String selectedDate = null;
private String selectedTime = null;
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
protected void onCreate(Bundle savedInstanceState) {
@@ -119,7 +130,6 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
}
});
}
private androidx.activity.result.ActivityResultLauncher<android.content.Intent> photoPickerLauncher;
private void setupReservationOptions() {
android.widget.Button btnDate = findViewById(R.id.btnSelectDate);
@@ -147,19 +157,6 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
btnVerAvaliacoes.setOnClickListener(v -> showReviewsDialog());
if (photoPickerLauncher == null) {
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);
}
}
});
}
btnUploadFoto.setOnClickListener(v -> {
android.content.Intent intent = new android.content.Intent(android.content.Intent.ACTION_PICK);
intent.setType("image/*");
@@ -238,13 +235,28 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
.setPositiveButton("Enviar", (dialog, which) -> {
String revText = input.getText().toString().trim();
if (!revText.isEmpty()) {
String userEmail = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null
? com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser().getEmail()
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", userEmail);
review.put("author", authorName);
review.put("text", revText);
com.google.firebase.database.FirebaseDatabase.getInstance().getReference("reviews")
@@ -254,10 +266,6 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
}
});
}
})
.setNegativeButton("Cancelar", null)
.show();
}
private void saveReservation() {
android.widget.EditText etPartySize = findViewById(R.id.etPartySize);

View File

@@ -160,6 +160,11 @@ public class GestaoStaffActivity extends AppCompatActivity {
btnAtribuir.setOnClickListener(v -> guardarAtribuicao());
}
Button btnEliminar = findViewById(R.id.btnEliminarStaff);
if (btnEliminar != null) {
btnEliminar.setOnClickListener(v -> eliminarStaff());
}
if (floatingActionButton != null) {
floatingActionButton.setOnClickListener(new View.OnClickListener() {
@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) {
for (Staff item : staffList) {
if (item.getName().equalsIgnoreCase(nome)) {

View File

@@ -88,10 +88,79 @@ public class ListaEsperaActivity extends AppCompatActivity {
}
private void setupActions() {
btnConfirmar.setOnClickListener(v -> atualizarEstadoSelecionado("Confirmada"));
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;

View File

@@ -127,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()) {
new AlertDialog.Builder(this)
.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) -> {
permissionRequest.launch(permissionsNeeded.toArray(new String[0]));
})

View File

@@ -5,69 +5,147 @@
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F7F7F7"
tools:context=".AddStaffActivity">
<EditText
android:id="@+id/nammeEditText"
android:layout_width="0dp"
<!-- Top Bar with Back Button -->
<Button
android:id="@+id/btnVoltarAddStaff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:hint="Name"
android:inputType="text"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="16dp"
android:background="@android:color/transparent"
android:text="Voltar"
android:textAllCaps="false"
android:textColor="#FF5252"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="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
android:id="@+id/zoneLayout"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginTop="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="@+id/nammeEditText"
app:layout_constraintStart_toStartOf="@+id/nammeEditText"
app:layout_constraintTop_toBottomOf="@+id/nammeEditText">
android:gravity="center_vertical">
<Spinner
android:id="@+id/zonaSpinner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="50dp"
android:layout_weight="1"
android:minHeight="48dp" />
android:background="@drawable/input_bg" />
<Button
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_height="wrap_content"
android:text="+" />
</LinearLayout>
android:layout_marginTop="20dp"
android:text="Mesa a Atribuir"
android:textColor="#333"
android:textSize="14sp"
android:textStyle="bold" />
<LinearLayout
android:id="@+id/mesaLayout"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="@+id/zoneLayout"
app:layout_constraintStart_toStartOf="@+id/zoneLayout"
app:layout_constraintTop_toBottomOf="@+id/zoneLayout">
android:layout_marginTop="8dp"
android:orientation="horizontal">
<Spinner
android:id="@+id/mesaSpinner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:minHeight="48dp" />
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/input_bg" />
</LinearLayout>
<Button
android:id="@+id/addButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="32dp"
android:background="@drawable/btn_primary"
android:text="Adicionar Membro"
android:textAllCaps="false"
android:textColor="#FFFFFF"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -69,10 +69,12 @@
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:id="@+id/cardReservasHoje"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:foreground="?attr/selectableItemBackground"
app:cardBackgroundColor="#FFFFFF"
app:cardCornerRadius="16dp"
app:cardElevation="3dp">
@@ -92,10 +94,11 @@
android:textSize="12sp" />
<TextView
android:id="@+id/txtReservasHojeDash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="32"
android:text="00"
android:textColor="#000"
android:textSize="28sp"
android:textStyle="bold" />
@@ -127,10 +130,11 @@
android:textSize="12sp" />
<TextView
android:id="@+id/txtMesasLivresDash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="08"
android:text="00"
android:textColor="#000"
android:textSize="28sp"
android:textStyle="bold" />
@@ -161,10 +165,11 @@
android:textSize="12sp" />
<TextView
android:id="@+id/txtListaEsperaDash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="05"
android:text="00"
android:textColor="#000"
android:textSize="28sp"
android:textStyle="bold" />

View File

@@ -91,6 +91,16 @@
android:textAllCaps="false"
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
android:id="@+id/txtMensagemStaff"
android:layout_width="match_parent"