diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000..995669b --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "476421715902", + "project_id": "namesa-429c1", + "storage_bucket": "namesa-429c1.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:476421715902:android:4147ab5f1cde601e1aebef", + "android_client_info": { + "package_name": "com.example.pap_teste" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyCPz7Pd3tJj3QkF7fV_vudCJythNsyR57k" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/src/main/java/com/example/pap_teste/AccountCreatedActivity.java b/app/src/main/java/com/example/pap_teste/AccountCreatedActivity.java new file mode 100644 index 0000000..e23c3c9 --- /dev/null +++ b/app/src/main/java/com/example/pap_teste/AccountCreatedActivity.java @@ -0,0 +1,67 @@ +package com.example.pap_teste; + +import android.content.Intent; +import android.os.Bundle; +import android.widget.Button; +import android.widget.TextView; + +import androidx.activity.EdgeToEdge; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +/** + * Tela de confirmação apresentada logo após a criação de conta. + * Exibe os dados básicos e direciona para a área correspondente + * (estabelecimento como admin, cliente como cliente). + */ +public class AccountCreatedActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EdgeToEdge.enable(this); + setContentView(R.layout.activity_account_created); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.accountCreatedRoot), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + + TextView txtWelcome = findViewById(R.id.txtWelcome); + TextView txtEmail = findViewById(R.id.txtEmail); + TextView txtRole = findViewById(R.id.txtRole); + Button btnContinue = findViewById(R.id.btnContinuar); + Button btnBack = findViewById(R.id.btnVoltar); + + String displayName = getIntent().getStringExtra(MainActivity.EXTRA_DISPLAY_NAME); + String email = getIntent().getStringExtra(MainActivity.EXTRA_EMAIL); + String accountType = getIntent().getStringExtra(MainActivity.EXTRA_ACCOUNT_TYPE); + String role = getIntent().getStringExtra(MainActivity.EXTRA_ROLE); + + txtWelcome.setText(displayName != null ? displayName : "Novo utilizador"); + txtEmail.setText(email != null ? email : "Email não informado"); + txtRole.setText(role != null ? role : "CLIENTE"); + + btnContinue.setOnClickListener(v -> { + boolean isEstablishment = "ESTABELECIMENTO".equalsIgnoreCase(accountType); + Intent nextScreen = new Intent( + this, + isEstablishment ? EstablishmentDashboardActivity.class : ClientDashboardActivity.class + ); + nextScreen.putExtra(MainActivity.EXTRA_ACTION_MODE, MainActivity.AccountAction.CRIAR.name()); + nextScreen.putExtra(MainActivity.EXTRA_DISPLAY_NAME, displayName); + nextScreen.putExtra(MainActivity.EXTRA_EMAIL, email); + nextScreen.putExtra(MainActivity.EXTRA_ACCOUNT_TYPE, accountType); + nextScreen.putExtra(MainActivity.EXTRA_ROLE, role); + startActivity(nextScreen); + finish(); + }); + + if (btnBack != null) { + btnBack.setOnClickListener(v -> finish()); + } + } +} + diff --git a/app/src/main/java/com/example/pap_teste/DetalhesReservasActivity.java b/app/src/main/java/com/example/pap_teste/DetalhesReservasActivity.java new file mode 100644 index 0000000..dbb6dcd --- /dev/null +++ b/app/src/main/java/com/example/pap_teste/DetalhesReservasActivity.java @@ -0,0 +1,145 @@ +package com.example.pap_teste; + +import android.os.Bundle; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.activity.EdgeToEdge; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +import java.util.ArrayList; +import java.util.List; + +public class DetalhesReservasActivity extends AppCompatActivity { + + private final List reservas = new ArrayList<>(); + private ArrayAdapter adapter; + private ListView listReservas; + private TextView txtInfo; + private TextView txtNotas; + private TextView txtEstado; + private TextView txtMensagem; + private int selectedIndex = -1; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EdgeToEdge.enable(this); + setContentView(R.layout.activity_detalhes_reservas); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.detalhesReservasRoot), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + + bindViews(); + seedReservasDemo(); + setupList(); + setupActions(); + } + + private void bindViews() { + listReservas = findViewById(R.id.listReservas); + txtInfo = findViewById(R.id.txtReservaInfo); + txtNotas = findViewById(R.id.txtReservaNotas); + txtEstado = findViewById(R.id.txtReservaEstado); + txtMensagem = findViewById(R.id.txtMensagemReserva); + + Button back = findViewById(R.id.btnVoltar); + if (back != null) { + back.setOnClickListener(v -> finish()); + } + } + + private void seedReservasDemo() { + reservas.add(new ReservaItem("Ana Ribeiro", "Mesa 12", "20h00", 4, "Aniversário", "Confirmada")); + reservas.add(new ReservaItem("Bruno Costa", "Mesa 03", "21h15", 2, "Preferência por janela", "Pendente")); + reservas.add(new ReservaItem("Carla Silva", "Mesa 07", "19h30", 3, "Levar bolo para a mesa", "Pendente")); + } + + private void setupList() { + adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_activated_1); + listReservas.setAdapter(adapter); + refreshList(); + + listReservas.setOnItemClickListener((parent, view, position, id) -> { + selectedIndex = position; + mostrarDetalhe(reservas.get(position)); + }); + } + + private void setupActions() { + Button btnConfirmar = findViewById(R.id.btnConfirmarReserva); + Button btnCancelar = findViewById(R.id.btnCancelarReserva); + + if (btnConfirmar != null) { + btnConfirmar.setOnClickListener(v -> atualizarEstadoSelecionado("Confirmada")); + } + + if (btnCancelar != null) { + btnCancelar.setOnClickListener(v -> atualizarEstadoSelecionado("Cancelada")); + } + } + + private void atualizarEstadoSelecionado(String novoEstado) { + if (selectedIndex < 0 || selectedIndex >= reservas.size()) { + Toast.makeText(this, "Selecione uma reserva para atualizar.", Toast.LENGTH_SHORT).show(); + return; + } + + ReservaItem item = reservas.get(selectedIndex); + item.estado = novoEstado; + txtMensagem.setText(String.format("Reserva de %s marcada como %s.", item.nomeCliente, novoEstado)); + mostrarDetalhe(item); + refreshList(); + } + + private void mostrarDetalhe(ReservaItem item) { + txtInfo.setText(String.format("%s • %s • %s • %dp", item.nomeCliente, item.mesa, item.hora, item.pessoas)); + txtNotas.setText(item.notas); + txtEstado.setText(String.format("Estado: %s", item.estado)); + } + + private void refreshList() { + adapter.clear(); + for (ReservaItem item : reservas) { + String resumo = String.format("%s - %s (%s) • %s", item.hora, item.mesa, item.estado, item.nomeCliente); + adapter.add(resumo); + } + adapter.notifyDataSetChanged(); + } + + private static class ReservaItem { + String nomeCliente; + String mesa; + String hora; + int pessoas; + String notas; + String estado; + + ReservaItem(String nomeCliente, String mesa, String hora, int pessoas, String notas, String estado) { + this.nomeCliente = nomeCliente; + this.mesa = mesa; + this.hora = hora; + this.pessoas = pessoas; + this.notas = notas; + this.estado = estado; + } + } +} + + + + + + + + + + diff --git a/app/src/main/java/com/example/pap_teste/GerirMesasActivity.java b/app/src/main/java/com/example/pap_teste/GerirMesasActivity.java new file mode 100644 index 0000000..07fa436 --- /dev/null +++ b/app/src/main/java/com/example/pap_teste/GerirMesasActivity.java @@ -0,0 +1,178 @@ +package com.example.pap_teste; + +import android.os.Bundle; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.activity.EdgeToEdge; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +import java.util.ArrayList; +import java.util.List; + +public class GerirMesasActivity extends AppCompatActivity { + + private final List mesas = new ArrayList<>(); + private ArrayAdapter adapter; + private ListView listMesas; + private EditText inputNumero; + private EditText inputCapacidade; + private Spinner spinnerEstado; + private TextView txtMensagem; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EdgeToEdge.enable(this); + setContentView(R.layout.activity_gerir_mesas); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.gerirMesasRoot), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + + bindViews(); + seedMesasDemo(); + setupList(); + setupFormActions(); + } + + private void bindViews() { + listMesas = findViewById(R.id.listMesas); + inputNumero = findViewById(R.id.inputMesaNumero); + inputCapacidade = findViewById(R.id.inputMesaCapacidade); + spinnerEstado = findViewById(R.id.spinnerEstadoMesa); + txtMensagem = findViewById(R.id.txtMensagemMesa); + + Button back = findViewById(R.id.btnVoltar); + if (back != null) { + back.setOnClickListener(v -> finish()); + } + + ArrayAdapter estadoAdapter = new ArrayAdapter<>( + this, + android.R.layout.simple_spinner_dropdown_item, + new String[]{"Livre", "Ocupada", "Reservada"} + ); + spinnerEstado.setAdapter(estadoAdapter); + } + + private void seedMesasDemo() { + mesas.add(new MesaItem(1, 4, "Livre")); + mesas.add(new MesaItem(2, 2, "Reservada")); + mesas.add(new MesaItem(3, 6, "Ocupada")); + mesas.add(new MesaItem(4, 4, "Livre")); + } + + private void setupList() { + adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_activated_1); + listMesas.setAdapter(adapter); + refreshList(); + + listMesas.setOnItemClickListener((parent, view, position, id) -> { + MesaItem item = mesas.get(position); + inputNumero.setText(String.valueOf(item.numero)); + inputCapacidade.setText(String.valueOf(item.capacidade)); + spinnerEstado.setSelection(getEstadoIndex(item.estado)); + txtMensagem.setText(String.format("Editar mesa %d", item.numero)); + }); + } + + private int getEstadoIndex(String estado) { + if ("Ocupada".equalsIgnoreCase(estado)) { + return 1; + } + if ("Reservada".equalsIgnoreCase(estado)) { + return 2; + } + return 0; + } + + private void setupFormActions() { + Button btnGuardar = findViewById(R.id.btnGuardarMesa); + if (btnGuardar != null) { + btnGuardar.setOnClickListener(v -> guardarMesa()); + } + } + + private void guardarMesa() { + String numeroStr = inputNumero.getText().toString().trim(); + String capacidadeStr = inputCapacidade.getText().toString().trim(); + String estado = (String) spinnerEstado.getSelectedItem(); + + if (numeroStr.isEmpty() || capacidadeStr.isEmpty() || estado == null) { + Toast.makeText(this, "Preencha número, capacidade e estado.", Toast.LENGTH_SHORT).show(); + return; + } + + int numero; + int capacidade; + try { + numero = Integer.parseInt(numeroStr); + capacidade = Integer.parseInt(capacidadeStr); + } catch (NumberFormatException e) { + Toast.makeText(this, "Use apenas números válidos.", Toast.LENGTH_SHORT).show(); + return; + } + + MesaItem existente = findMesa(numero); + if (existente == null) { + mesas.add(new MesaItem(numero, capacidade, estado)); + txtMensagem.setText(String.format("Mesa %d adicionada/atualizada.", numero)); + } else { + existente.capacidade = capacidade; + existente.estado = estado; + txtMensagem.setText(String.format("Mesa %d atualizada.", numero)); + } + + refreshList(); + } + + private MesaItem findMesa(int numero) { + for (MesaItem item : mesas) { + if (item.numero == numero) { + return item; + } + } + return null; + } + + private void refreshList() { + adapter.clear(); + for (MesaItem item : mesas) { + String resumo = String.format("Mesa %02d • %d lugares • %s", item.numero, item.capacidade, item.estado); + adapter.add(resumo); + } + adapter.notifyDataSetChanged(); + } + + private static class MesaItem { + int numero; + int capacidade; + String estado; + + MesaItem(int numero, int capacidade, String estado) { + this.numero = numero; + this.capacidade = capacidade; + this.estado = estado; + } + } +} + + + + + + + + + + diff --git a/app/src/main/java/com/example/pap_teste/GestaoStaffActivity.java b/app/src/main/java/com/example/pap_teste/GestaoStaffActivity.java index dbaae02..357d53b 100644 --- a/app/src/main/java/com/example/pap_teste/GestaoStaffActivity.java +++ b/app/src/main/java/com/example/pap_teste/GestaoStaffActivity.java @@ -1,6 +1,13 @@ package com.example.pap_teste; import android.os.Bundle; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; @@ -8,10 +15,18 @@ import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; -import android.widget.Button; +import java.util.ArrayList; +import java.util.List; public class GestaoStaffActivity extends AppCompatActivity { + private final List staffAssignments = new ArrayList<>(); + private ArrayAdapter staffAdapter; + private ListView listStaffMesas; + private EditText inputNomeStaff; + private Spinner spinnerMesaStaff; + private TextView txtMensagemStaff; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -27,6 +42,112 @@ public class GestaoStaffActivity extends AppCompatActivity { if (back != null) { back.setOnClickListener(v -> finish()); } + + bindViews(); + setupMesaSpinner(); + setupList(); + setupFormActions(); + } + + private void bindViews() { + listStaffMesas = findViewById(R.id.listStaffMesas); + inputNomeStaff = findViewById(R.id.inputNomeStaff); + spinnerMesaStaff = findViewById(R.id.spinnerMesaStaff); + txtMensagemStaff = findViewById(R.id.txtMensagemStaff); + } + + /** + * Preenche o spinner com uma lista simples de mesas (1–20). + * Mais tarde isto pode ser ligado às mesas reais configuradas em "Gerir Mesas". + */ + private void setupMesaSpinner() { + ArrayAdapter mesaAdapter = new ArrayAdapter<>( + this, + android.R.layout.simple_spinner_dropdown_item + ); + + for (int i = 1; i <= 20; i++) { + mesaAdapter.add(String.format("Mesa %02d", i)); + } + + spinnerMesaStaff.setAdapter(mesaAdapter); + } + + private void setupList() { + staffAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_activated_1); + listStaffMesas.setAdapter(staffAdapter); + refreshList(); + + listStaffMesas.setOnItemClickListener((parent, view, position, id) -> { + StaffAssignment item = staffAssignments.get(position); + inputNomeStaff.setText(item.nome); + int index = Math.max(0, Math.min(spinnerMesaStaff.getCount() - 1, item.mesaNumero - 1)); + spinnerMesaStaff.setSelection(index); + txtMensagemStaff.setText(String.format("A editar: %s (Mesa %02d)", item.nome, item.mesaNumero)); + }); + } + + private void setupFormActions() { + Button btnAtribuir = findViewById(R.id.btnAtribuirStaff); + if (btnAtribuir != null) { + btnAtribuir.setOnClickListener(v -> guardarAtribuicao()); + } + } + + private void guardarAtribuicao() { + String nome = inputNomeStaff != null ? inputNomeStaff.getText().toString().trim() : ""; + if (nome.isEmpty()) { + Toast.makeText(this, "Indique o nome do funcionário.", Toast.LENGTH_SHORT).show(); + return; + } + + if (spinnerMesaStaff == null || spinnerMesaStaff.getSelectedItem() == null) { + Toast.makeText(this, "Selecione uma mesa.", Toast.LENGTH_SHORT).show(); + return; + } + + int mesaNumero = spinnerMesaStaff.getSelectedItemPosition() + 1; + + StaffAssignment existente = findByNome(nome); + if (existente == null) { + staffAssignments.add(new StaffAssignment(nome, mesaNumero)); + txtMensagemStaff.setText(String.format("%s atribuído à mesa %02d.", nome, mesaNumero)); + } else { + existente.mesaNumero = mesaNumero; + txtMensagemStaff.setText(String.format("Mesa de %s atualizada para %02d.", nome, mesaNumero)); + } + + refreshList(); + } + + private StaffAssignment findByNome(String nome) { + for (StaffAssignment item : staffAssignments) { + if (item.nome.equalsIgnoreCase(nome)) { + return item; + } + } + return null; + } + + private void refreshList() { + if (staffAdapter == null) return; + + staffAdapter.clear(); + for (StaffAssignment item : staffAssignments) { + String resumo = String.format("%s • Mesa %02d", item.nome, item.mesaNumero); + staffAdapter.add(resumo); + } + staffAdapter.notifyDataSetChanged(); + } + + private static class StaffAssignment { + String nome; + int mesaNumero; + + StaffAssignment(String nome, int mesaNumero) { + this.nome = nome; + this.mesaNumero = mesaNumero; + } } } diff --git a/app/src/main/res/drawable/btn_primary.xml b/app/src/main/res/drawable/btn_primary.xml index 32b60b2..012165d 100644 --- a/app/src/main/res/drawable/btn_primary.xml +++ b/app/src/main/res/drawable/btn_primary.xml @@ -20,3 +20,11 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/tab_selected.xml b/app/src/main/res/drawable/tab_selected.xml index 93c30d2..96c13ef 100644 --- a/app/src/main/res/drawable/tab_selected.xml +++ b/app/src/main/res/drawable/tab_selected.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_account_created.xml b/app/src/main/res/layout/activity_account_created.xml new file mode 100644 index 0000000..1f6af6d --- /dev/null +++ b/app/src/main/res/layout/activity_account_created.xml @@ -0,0 +1,111 @@ + + + +