This commit is contained in:
2026-03-10 17:12:51 +00:00
parent 7ad72ad334
commit a33741ba06
11 changed files with 328 additions and 93 deletions

View File

@@ -42,10 +42,13 @@ public class ClientDashboardActivity extends AppCompatActivity {
profileLauncher = registerForActivityResult(
new androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == RESULT_OK) {
android.widget.Toast.makeText(this,
"Perfil atualizado. Reinicie para ver mudanças.",
android.widget.Toast.LENGTH_SHORT).show();
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
String updatedName = result.getData()
.getStringExtra(MainActivity.EXTRA_DISPLAY_NAME);
if (updatedName != null) {
displayName = updatedName;
updateGreeting();
}
}
});
@@ -64,10 +67,14 @@ public class ClientDashboardActivity extends AppCompatActivity {
cats.add(new FoodCategory("Carnes", R.drawable.cat_carnes));
cats.add(new FoodCategory("Massas", R.drawable.cat_massas));
cats.add(new FoodCategory("Sushi", R.drawable.cat_sushi));
cats.add(new FoodCategory("Pizzas", R.drawable.ic_launcher_background));
cats.add(new FoodCategory("Sobremesas", R.drawable.ic_launcher_background));
cats.add(new FoodCategory("Pizzas", R.drawable.cat_pizzas));
cats.add(new FoodCategory("Sobremesas", R.drawable.cat_sobremesas));
FoodCategoryAdapter adapter = new FoodCategoryAdapter(cats);
FoodCategoryAdapter adapter = new FoodCategoryAdapter(cats, category -> {
Intent intent = new Intent(this, ExplorarRestaurantesActivity.class);
intent.putExtra("category_filter", category.getName());
startActivity(intent);
});
rv.setAdapter(adapter);
}
@@ -92,8 +99,5 @@ public class ClientDashboardActivity extends AppCompatActivity {
findViewById(R.id.btnNovaReserva)
.setOnClickListener(v -> startActivity(new Intent(this, NovaReservaActivity.class)));
findViewById(R.id.btnExplorar).setOnClickListener(
v -> startActivity(new Intent(this, ExplorarRestaurantesActivity.class)));
}
}

View File

@@ -27,10 +27,40 @@ public class ExplorarRestaurantesActivity extends AppCompatActivity {
if (back != null) {
back.setOnClickListener(v -> finish());
}
setupRestaurantList();
}
private void setupRestaurantList() {
String filter = getIntent().getStringExtra("category_filter");
android.widget.TextView txtTitle = findViewById(R.id.txtTituloExplorar);
if (filter != null && txtTitle != null) {
txtTitle.setText("Explorar: " + filter);
}
androidx.recyclerview.widget.RecyclerView rv = findViewById(R.id.rvRestaurants);
java.util.List<com.example.pap_teste.models.Restaurant> allRestaurants = new java.util.ArrayList<>();
allRestaurants.add(new com.example.pap_teste.models.Restaurant("Sabor & Arte", "Tradicional", true));
allRestaurants.add(new com.example.pap_teste.models.Restaurant("Pizzeria Bella", "Pizzas", false));
allRestaurants.add(new com.example.pap_teste.models.Restaurant("Sushi Zen", "Sushi", false));
allRestaurants.add(new com.example.pap_teste.models.Restaurant("O Chuveiro", "Frutos do Mar", true));
allRestaurants.add(new com.example.pap_teste.models.Restaurant("Hamburgueria Real", "Carnes", false));
allRestaurants.add(new com.example.pap_teste.models.Restaurant("Churrascaria Gaúcha", "Carnes", false));
allRestaurants.add(new com.example.pap_teste.models.Restaurant("Sushi House", "Sushi", false));
allRestaurants.add(new com.example.pap_teste.models.Restaurant("Doce Momento", "Sobremesas", false));
java.util.List<com.example.pap_teste.models.Restaurant> filteredList = new java.util.ArrayList<>();
if (filter != null) {
for (com.example.pap_teste.models.Restaurant r : allRestaurants) {
if (r.getCategory().equalsIgnoreCase(filter)) {
filteredList.add(r);
}
}
} else {
filteredList.addAll(allRestaurants);
}
RestaurantAdapter adapter = new RestaurantAdapter(filteredList);
rv.setAdapter(adapter);
}
}

View File

@@ -27,10 +27,17 @@ public class FavoritosActivity extends AppCompatActivity {
if (back != null) {
back.setOnClickListener(v -> finish());
}
setupFavoritesList();
}
private void setupFavoritesList() {
androidx.recyclerview.widget.RecyclerView rv = findViewById(R.id.rvFavoritos);
java.util.List<com.example.pap_teste.models.Restaurant> list = new java.util.ArrayList<>();
list.add(new com.example.pap_teste.models.Restaurant("Sabor & Arte", "Tradicional", true));
list.add(new com.example.pap_teste.models.Restaurant("O Chuveiro", "Mariscos", true));
RestaurantAdapter adapter = new RestaurantAdapter(list);
rv.setAdapter(adapter);
}
}

View File

@@ -15,10 +15,16 @@ import java.util.List;
public class FoodCategoryAdapter extends RecyclerView.Adapter<FoodCategoryAdapter.ViewHolder> {
private final List<FoodCategory> categories;
public interface OnCategoryClickListener {
void onCategoryClick(FoodCategory category);
}
public FoodCategoryAdapter(List<FoodCategory> categories) {
private final List<FoodCategory> categories;
private final OnCategoryClickListener listener;
public FoodCategoryAdapter(List<FoodCategory> categories, OnCategoryClickListener listener) {
this.categories = categories;
this.listener = listener;
}
@NonNull
@@ -35,6 +41,12 @@ public class FoodCategoryAdapter extends RecyclerView.Adapter<FoodCategoryAdapte
if (category.getImageResId() != 0) {
holder.imgCategory.setImageResource(category.getImageResId());
}
holder.itemView.setOnClickListener(v -> {
if (listener != null) {
listener.onCategoryClick(category);
}
});
}
@Override

View File

@@ -1,6 +1,7 @@
package com.example.pap_teste;
import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
@@ -27,10 +28,41 @@ public class NovaReservaActivity extends AppCompatActivity {
if (back != null) {
back.setOnClickListener(v -> finish());
}
setupReservationOptions();
}
private void setupReservationOptions() {
// Dates
RecyclerView rvDates = findViewById(R.id.rvDates);
java.util.List<String> dates = new java.util.ArrayList<>();
dates.add("Hoje");
dates.add("Amanhã");
dates.add("Quarta, 12 Mar");
dates.add("Quinta, 13 Mar");
dates.add("Sexta, 14 Mar");
rvDates.setAdapter(new ReservationOptionAdapter(dates));
// Times
RecyclerView rvTimes = findViewById(R.id.rvTimes);
java.util.List<String> times = new java.util.ArrayList<>();
times.add("12:00");
times.add("13:00");
times.add("19:00");
times.add("20:00");
times.add("21:00");
times.add("22:00");
rvTimes.setAdapter(new ReservationOptionAdapter(times));
// Party Size
RecyclerView rvParty = findViewById(R.id.rvPartySize);
java.util.List<String> party = new java.util.ArrayList<>();
party.add("1 pessoa");
party.add("2 pessoas");
party.add("3 pessoas");
party.add("4 pessoas");
party.add("5 pessoas");
party.add("6+ pessoas");
rvParty.setAdapter(new ReservationOptionAdapter(party));
}
}

View File

@@ -1,5 +1,6 @@
package com.example.pap_teste;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.Button;
@@ -20,9 +21,10 @@ import java.util.Map;
public class ProfileDashboardActivity extends AppCompatActivity {
private EditText inputName;
private EditText inputName, inputPhone, inputEmailEdit;
private String email, documentId;
private DatabaseReference databaseReference;
private androidx.activity.result.ActivityResultLauncher<Intent> imagePickerLauncher;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -45,9 +47,36 @@ public class ProfileDashboardActivity extends AppCompatActivity {
databaseReference = FirebaseDatabase.getInstance().getReference().child("users");
inputName = findViewById(R.id.inputProfileName);
inputPhone = findViewById(R.id.inputProfilePhone);
inputEmailEdit = findViewById(R.id.inputProfileEmail);
if (currentName != null) {
inputName.setText(currentName);
}
if (email != null) {
inputEmailEdit.setText(email);
}
fetchAdditionalProfileData();
imagePickerLauncher = 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) {
Toast.makeText(this, "Foto selecionada (Simulação: Seria feito o upload)",
Toast.LENGTH_SHORT).show();
// In a real app, you'd upload this to Firebase Storage.
}
}
});
findViewById(R.id.cardProfileBig).setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
imagePickerLauncher.launch(intent);
});
Button btnSave = findViewById(R.id.btnSaveProfile);
Button btnBack = findViewById(R.id.btnVoltar);
@@ -55,17 +84,32 @@ public class ProfileDashboardActivity extends AppCompatActivity {
Button btnRes = findViewById(R.id.btnMinhasReservas);
btnBack.setOnClickListener(v -> finish());
btnSave.setOnClickListener(v -> saveProfile());
btnFavs.setOnClickListener(v -> {
Toast.makeText(this, "A abrir Favoritos...", Toast.LENGTH_SHORT).show();
// startActivity(new Intent(this, FavoritosActivity.class));
startActivity(new Intent(this, FavoritosActivity.class));
});
btnRes.setOnClickListener(v -> {
Toast.makeText(this, "A abrir Reservas...", Toast.LENGTH_SHORT).show();
// startActivity(new Intent(this, DetalhesReservasActivity.class));
startActivity(new Intent(this, DetalhesReservasActivity.class));
});
}
private void fetchAdditionalProfileData() {
if (documentId == null)
return;
databaseReference.child(documentId).get().addOnSuccessListener(snapshot -> {
if (snapshot.exists()) {
String phone = snapshot.child("ownerPhone").getValue(String.class);
if (phone == null)
phone = snapshot.child("phone").getValue(String.class);
if (phone != null)
inputPhone.setText(phone);
String dbEmail = snapshot.child("email").getValue(String.class);
if (dbEmail != null)
inputEmailEdit.setText(dbEmail);
}
});
}
@@ -74,6 +118,9 @@ public class ProfileDashboardActivity extends AppCompatActivity {
return;
String newName = inputName.getText().toString().trim();
String newPhone = inputPhone.getText().toString().trim();
String newEmail = inputEmailEdit.getText().toString().trim();
if (TextUtils.isEmpty(newName)) {
Toast.makeText(this, "Indique um nome.", Toast.LENGTH_SHORT).show();
return;
@@ -81,11 +128,15 @@ public class ProfileDashboardActivity extends AppCompatActivity {
Map<String, Object> updates = new HashMap<>();
updates.put("displayName", newName);
updates.put("phone", newPhone);
updates.put("email", newEmail);
databaseReference.child(documentId).updateChildren(updates)
.addOnSuccessListener(aVoid -> {
Toast.makeText(this, "Perfil atualizado!", Toast.LENGTH_SHORT).show();
setResult(RESULT_OK);
Intent resultIntent = new Intent();
resultIntent.putExtra(MainActivity.EXTRA_DISPLAY_NAME, newName);
setResult(RESULT_OK, resultIntent);
finish();
})
.addOnFailureListener(

View File

@@ -208,14 +208,12 @@
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="12dp"
android:columnCount="2"
android:rowCount="1">
android:columnCount="1">
<androidx.cardview.widget.CardView
android:id="@+id/cardNewRes"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="2dp">
@@ -231,30 +229,7 @@
android:layout_height="wrap_content"
android:text="Reservar"
android:textColor="#000"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/cardExplore"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_columnWeight="1"
android:layout_margin="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="2dp">
<LinearLayout
android:id="@+id/btnExplorar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:background="?attr/selectableItemBackground">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Explorar"
android:textColor="#000"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -32,18 +32,19 @@
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="32dp" />
<TextView
android:id="@+id/txtDescricaoExplorar"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvRestaurants"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="12dp"
android:text="Ecrã dedicado a descobrir restaurantes recomendados, próximos de si e filtrados por preferência."
android:textSize="14sp"
android:textColor="#4D4D4D"
app:layout_constraintTop_toBottomOf="@id/txtTituloExplorar"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:clipToPadding="false"
android:paddingBottom="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintTop_toBottomOf="@id/txtTituloExplorar"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_restaurant" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -32,18 +32,19 @@
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="32dp" />
<TextView
android:id="@+id/txtDescricaoFavoritos"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvFavoritos"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="12dp"
android:text="Aqui serão listados os restaurantes que o cliente marcar como favorito."
android:textSize="14sp"
android:textColor="#4D4D4D"
app:layout_constraintTop_toBottomOf="@id/txtTituloFavoritos"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:clipToPadding="false"
android:paddingBottom="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintTop_toBottomOf="@id/txtTituloFavoritos"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_restaurant" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -32,18 +32,104 @@
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="32dp" />
<TextView
android:id="@+id/txtDescricaoNovaReserva"
<ScrollView
android:id="@+id/scrollNovaReserva"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="12dp"
android:text="Aqui poderá configurar uma nova reserva (data, hora, número de pessoas, restaurante, etc.)."
android:textSize="14sp"
android:textColor="#4D4D4D"
app:layout_constraintTop_toBottomOf="@id/txtTituloNovaReserva"
android:layout_height="0dp"
android:layout_marginTop="24dp"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintTop_toBottomOf="@id/txtTituloNovaReserva">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="32dp">
<!-- Section: Date -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="16dp"
android:text="Escolha a data"
android:textColor="#000"
android:textSize="16sp"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvDates"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingEnd="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<!-- Section: Time -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:text="Escolha o horário"
android:textColor="#000"
android:textSize="16sp"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvTimes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingEnd="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<!-- Section: Party size -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:text="Número de pessoas"
android:textColor="#000"
android:textSize="16sp"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvPartySize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingEnd="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<Button
android:id="@+id/btnConfirmarReserva"
android:layout_width="match_parent"
android:layout_height="55dp"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="32dp"
android:background="@drawable/btn_primary"
android:text="Confirmar Reserva"
android:textAllCaps="false"
android:textColor="#FFF"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -73,11 +73,47 @@
android:padding="12dp"
android:background="@drawable/input_bg" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Telemóvel"
android:textColor="#8A8A8A"
android:textSize="12sp" />
<EditText
android:id="@+id/inputProfilePhone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:hint="O seu número"
android:inputType="phone"
android:padding="12dp"
android:background="@drawable/input_bg" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Email"
android:textColor="#8A8A8A"
android:textSize="12sp" />
<EditText
android:id="@+id/inputProfileEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:hint="O seu email"
android:inputType="textEmailAddress"
android:padding="12dp"
android:background="@drawable/input_bg" />
<Button
android:id="@+id/btnSaveProfile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginTop="24dp"
android:background="@drawable/btn_primary"
android:text="Guardar Alterações"
android:textAllCaps="false"