Created help class for displaying diolog and removed redundent code

This commit is contained in:
Alex
2026-04-05 18:38:46 -06:00
parent 6d990fbc63
commit c99d9d21f0
8 changed files with 150 additions and 157 deletions

View File

@@ -6,14 +6,13 @@ import android.util.Log;
import android.view.*; import android.view.*;
import android.widget.*; import android.widget.*;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import com.example.petstoremobile.R; import com.example.petstoremobile.R;
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
import com.example.petstoremobile.api.*; import com.example.petstoremobile.api.*;
import com.example.petstoremobile.dtos.*; import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils; import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.SpinnerUtils; import com.example.petstoremobile.utils.SpinnerUtils;
@@ -84,8 +83,7 @@ public class AdoptionDetailFragment extends Fragment {
* Configures the spinner for adoption status. * Configures the spinner for adoption status.
*/ */
private void setupSpinners() { private void setupSpinners() {
spinnerStatus.setAdapter(new BlackTextArrayAdapter<>(requireContext(), SpinnerUtils.setupStringSpinner(requireContext(), spinnerStatus, STATUSES);
android.R.layout.simple_spinner_item, STATUSES));
} }
/** /**
@@ -172,12 +170,7 @@ public class AdoptionDetailFragment extends Fragment {
btnDelete.setVisibility(View.VISIBLE); btnDelete.setVisibility(View.VISIBLE);
// Pre-fill status // Pre-fill status
String status = a.getString("adoptionStatus", "Pending"); SpinnerUtils.setSelectionByValue(spinnerStatus, a.getString("adoptionStatus", "Pending"));
for (int i = 0; i < STATUSES.length; i++) {
if (STATUSES[i].equals(status)) {
spinnerStatus.setSelection(i); break;
}
}
} else { } else {
tvMode.setText("Add Adoption"); tvMode.setText("Add Adoption");
btnDelete.setVisibility(View.GONE); btnDelete.setVisibility(View.GONE);
@@ -247,18 +240,15 @@ public class AdoptionDetailFragment extends Fragment {
* Shows a confirmation dialog before deleting an adoption request. * Shows a confirmation dialog before deleting an adoption request.
*/ */
private void confirmDelete() { private void confirmDelete() {
new AlertDialog.Builder(requireContext()) DialogUtils.showDeleteConfirmDialog(requireContext(), "Adoption", () ->
.setTitle("Delete Adoption?") adoptionApi.deleteAdoption(adoptionId)
.setPositiveButton("Yes", (d, w) -> .enqueue(new Callback<Void>() {
adoptionApi.deleteAdoption(adoptionId) public void onResponse(Call<Void> c, Response<Void> r) { navigateBack(); }
.enqueue(new Callback<Void>() { public void onFailure(Call<Void> c, Throwable t) {
public void onResponse(Call<Void> c, Response<Void> r) { navigateBack(); } Toast.makeText(getContext(), "Delete failed",
public void onFailure(Call<Void> c, Throwable t) { Toast.LENGTH_SHORT).show();
Toast.makeText(getContext(), "Delete failed", }
Toast.LENGTH_SHORT).show(); }));
}
}))
.setNegativeButton("No", null).show();
} }
/** /**

View File

@@ -6,14 +6,13 @@ import android.util.Log;
import android.view.*; import android.view.*;
import android.widget.*; import android.widget.*;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import com.example.petstoremobile.R; import com.example.petstoremobile.R;
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
import com.example.petstoremobile.api.*; import com.example.petstoremobile.api.*;
import com.example.petstoremobile.dtos.*; import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils; import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.SpinnerUtils; import com.example.petstoremobile.utils.SpinnerUtils;
@@ -317,7 +316,7 @@ public class AppointmentDetailFragment extends Fragment {
0 0
); );
if (selected.before(Calendar.getInstance())) { if (selected.before(Calendar.getInstance())) {
showErrorDialog("Invalid Time", DialogUtils.showInfoDialog(requireContext(), "Invalid Time",
"Booked appointments must be in the future. " + "Booked appointments must be in the future. " +
"Please select a future date and time."); "Please select a future date and time.");
return; return;
@@ -368,7 +367,7 @@ public class AppointmentDetailFragment extends Fragment {
// Show proper dialog based on error type // Show proper dialog based on error type
if (errorBody.toLowerCase().contains("future")) { if (errorBody.toLowerCase().contains("future")) {
showErrorDialog("Invalid Date/Time", DialogUtils.showInfoDialog(requireContext(), "Invalid Date/Time",
"Booked appointments must be scheduled in the future. " + "Booked appointments must be scheduled in the future. " +
"Please select a future date and time."); "Please select a future date and time.");
} else if (errorBody.toLowerCase().contains("not available") || } else if (errorBody.toLowerCase().contains("not available") ||
@@ -379,7 +378,7 @@ public class AppointmentDetailFragment extends Fragment {
} }
} catch (Exception e) { } catch (Exception e) {
Log.e("APPT_SAVE", "Failed to read error body"); Log.e("APPT_SAVE", "Failed to read error body");
showErrorDialog("Error", "Something went wrong. Please try again."); DialogUtils.showInfoDialog(requireContext(), "Error", "Something went wrong. Please try again.");
} }
} }
} }
@@ -395,7 +394,7 @@ public class AppointmentDetailFragment extends Fragment {
* Shows a specialized dialog when a time slot is not available. * Shows a specialized dialog when a time slot is not available.
*/ */
private void showNoAvailabilityDialog() { private void showNoAvailabilityDialog() {
new AlertDialog.Builder(requireContext()) new androidx.appcompat.app.AlertDialog.Builder(requireContext())
.setTitle("No Availability") .setTitle("No Availability")
.setMessage("This time slot is already booked for the selected service and store. Please choose a different time or date.") .setMessage("This time slot is already booked for the selected service and store. Please choose a different time or date.")
.setPositiveButton("Change Time", (d, w) -> d.dismiss()) .setPositiveButton("Change Time", (d, w) -> d.dismiss())
@@ -404,32 +403,18 @@ public class AppointmentDetailFragment extends Fragment {
.show(); .show();
} }
/**
* Shows a generic error dialog with a title and message.
*/
private void showErrorDialog(String title, String message) {
new AlertDialog.Builder(requireContext())
.setTitle(title)
.setMessage(message)
.setPositiveButton("OK", null)
.show();
}
/** /**
* Shows a confirmation dialog and handles the deletion of an appointment. * Shows a confirmation dialog and handles the deletion of an appointment.
*/ */
private void confirmDelete() { private void confirmDelete() {
new AlertDialog.Builder(requireContext()) DialogUtils.showDeleteConfirmDialog(requireContext(), "Appointment", () ->
.setTitle("Delete Appointment?") appointmentApi.deleteAppointment(appointmentId)
.setPositiveButton("Yes", (d, w) -> .enqueue(new Callback<Void>() {
appointmentApi.deleteAppointment(appointmentId) public void onResponse(Call<Void> c, Response<Void> r) { navigateBack(); }
.enqueue(new Callback<Void>() { public void onFailure(Call<Void> c, Throwable t) {
public void onResponse(Call<Void> c, Response<Void> r) { navigateBack(); } Toast.makeText(getContext(), "Delete failed", Toast.LENGTH_SHORT).show();
public void onFailure(Call<Void> c, Throwable t) { }
Toast.makeText(getContext(), "Delete failed", Toast.LENGTH_SHORT).show(); }));
}
}))
.setNegativeButton("No", null).show();
} }
/** /**

View File

@@ -3,7 +3,6 @@ package com.example.petstoremobile.fragments.listfragments.detailfragments;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
@@ -21,6 +20,7 @@ import com.example.petstoremobile.R;
import com.example.petstoremobile.api.PetApi; import com.example.petstoremobile.api.PetApi;
import com.example.petstoremobile.dtos.PetDTO; import com.example.petstoremobile.dtos.PetDTO;
import com.example.petstoremobile.utils.ActivityLogger; import com.example.petstoremobile.utils.ActivityLogger;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils; import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.InputValidator; import com.example.petstoremobile.utils.InputValidator;
import com.example.petstoremobile.utils.SpinnerUtils; import com.example.petstoremobile.utils.SpinnerUtils;
@@ -144,34 +144,26 @@ public class PetDetailFragment extends Fragment {
* Displays a confirmation dialog and handles the deletion of a pet. * Displays a confirmation dialog and handles the deletion of a pet.
*/ */
private void deletePet() { private void deletePet() {
//Alert the user to confirm the delete DialogUtils.showDeleteConfirmDialog(requireContext(), "Pet", () ->
new AlertDialog.Builder(requireContext()) petApi.deletePet((long) petId).enqueue(new Callback<Void>() {
.setTitle("Delete Pet") @Override
.setMessage("Are you sure you want to delete " + etPetName.getText().toString() + "?") public void onResponse(Call<Void> call, Response<Void> response) {
.setPositiveButton("Delete", (dialog, which) -> { if (response.isSuccessful()) {
//if they say yes then delete the pet ActivityLogger.logChange(requireContext(), "Pet", "DELETED", petId);
petApi.deletePet((long) petId).enqueue(new Callback<Void>() { Toast.makeText(getContext(), "Pet deleted successfully!", Toast.LENGTH_SHORT).show();
@Override navigateBack();
public void onResponse(Call<Void> call, Response<Void> response) { } else {
if (response.isSuccessful()) { ErrorUtils.showErrorMessage(getContext(), response, "Failed to delete pet");
ActivityLogger.logChange(requireContext(), "Pet", "DELETED", petId);
Toast.makeText(getContext(), "Pet deleted successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to delete pet");
}
} }
}
@Override @Override
public void onFailure(Call<Void> call, Throwable t) { public void onFailure(Call<Void> call, Throwable t) {
ActivityLogger.logException(requireContext(), "PetDetailFragment.deletePet", new Exception(t)); ActivityLogger.logException(requireContext(), "PetDetailFragment.deletePet", new Exception(t));
Log.e("PetDetailFragment", "Error deleting pet", t); Log.e("PetDetailFragment", "Error deleting pet", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
} }
}); }));
})
.setNegativeButton("Cancel", null)
.show();
} }
/** /**

View File

@@ -11,11 +11,11 @@ import androidx.navigation.fragment.NavHostFragment;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.example.petstoremobile.R; import com.example.petstoremobile.R;
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
import com.example.petstoremobile.api.*; import com.example.petstoremobile.api.*;
import com.example.petstoremobile.api.auth.TokenManager; import com.example.petstoremobile.api.auth.TokenManager;
import com.example.petstoremobile.dtos.*; import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.viewmodels.ProductViewModel; import com.example.petstoremobile.viewmodels.ProductViewModel;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils; import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.FileUtils; import com.example.petstoremobile.utils.FileUtils;
import com.example.petstoremobile.utils.GlideUtils; import com.example.petstoremobile.utils.GlideUtils;
@@ -286,17 +286,14 @@ public class ProductDetailFragment extends Fragment {
* Displays a confirmation dialog before deleting the product. * Displays a confirmation dialog before deleting the product.
*/ */
private void confirmDelete() { private void confirmDelete() {
new androidx.appcompat.app.AlertDialog.Builder(requireContext()) DialogUtils.showDeleteConfirmDialog(requireContext(), "Product", () ->
.setTitle("Delete Product?") viewModel.deleteProduct(prodId).observe(getViewLifecycleOwner(), resource -> {
.setPositiveButton("Yes", (d, w) -> if (resource != null && resource.status == com.example.petstoremobile.utils.Resource.Status.SUCCESS) {
viewModel.deleteProduct(prodId).observe(getViewLifecycleOwner(), resource -> { navigateBack();
if (resource != null && resource.status == com.example.petstoremobile.utils.Resource.Status.SUCCESS) { } else if (resource != null && resource.status == com.example.petstoremobile.utils.Resource.Status.ERROR) {
navigateBack(); Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
} else if (resource != null && resource.status == com.example.petstoremobile.utils.Resource.Status.ERROR) { }
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show(); }));
}
}))
.setNegativeButton("No", null).show();
} }
/** /**

View File

@@ -5,14 +5,13 @@ import android.util.Log;
import android.view.*; import android.view.*;
import android.widget.*; import android.widget.*;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import com.example.petstoremobile.R; import com.example.petstoremobile.R;
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
import com.example.petstoremobile.api.*; import com.example.petstoremobile.api.*;
import com.example.petstoremobile.dtos.*; import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils; import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.InputValidator; import com.example.petstoremobile.utils.InputValidator;
import com.example.petstoremobile.utils.SpinnerUtils; import com.example.petstoremobile.utils.SpinnerUtils;
@@ -201,20 +200,17 @@ public class ProductSupplierDetailFragment extends Fragment {
* Shows a confirmation dialog before deleting a product-supplier relationship. * Shows a confirmation dialog before deleting a product-supplier relationship.
*/ */
private void confirmDelete() { private void confirmDelete() {
new AlertDialog.Builder(requireContext()) DialogUtils.showDeleteConfirmDialog(requireContext(), "Product Supplier", () ->
.setTitle("Delete?") productSupplierApi.deleteProductSupplier(editProductId, editSupplierId)
.setPositiveButton("Yes", (d, w) -> .enqueue(new Callback<Void>() {
productSupplierApi.deleteProductSupplier(editProductId, editSupplierId) public void onResponse(Call<Void> c, Response<Void> r) {
.enqueue(new Callback<Void>() { navigateBack();
public void onResponse(Call<Void> c, Response<Void> r) { }
navigateBack(); public void onFailure(Call<Void> c, Throwable t) {
} Toast.makeText(getContext(), "Delete failed",
public void onFailure(Call<Void> c, Throwable t) { Toast.LENGTH_SHORT).show();
Toast.makeText(getContext(), "Delete failed", }
Toast.LENGTH_SHORT).show(); }));
}
}))
.setNegativeButton("No", null).show();
} }
/** /**

View File

@@ -2,7 +2,6 @@ package com.example.petstoremobile.fragments.listfragments.detailfragments;
import android.os.Bundle; import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
@@ -19,6 +18,7 @@ import com.example.petstoremobile.R;
import com.example.petstoremobile.api.ServiceApi; import com.example.petstoremobile.api.ServiceApi;
import com.example.petstoremobile.dtos.ServiceDTO; import com.example.petstoremobile.dtos.ServiceDTO;
import com.example.petstoremobile.utils.ActivityLogger; import com.example.petstoremobile.utils.ActivityLogger;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils; import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.InputValidator; import com.example.petstoremobile.utils.InputValidator;
@@ -134,33 +134,26 @@ public class ServiceDetailFragment extends Fragment {
* Displays a confirmation dialog and handles the deletion of a service. * Displays a confirmation dialog and handles the deletion of a service.
*/ */
private void deleteService() { private void deleteService() {
//Alert the user to confirm the delete DialogUtils.showDeleteConfirmDialog(requireContext(), "Service", () ->
new AlertDialog.Builder(requireContext()) serviceApi.deleteService((long) serviceId).enqueue(new Callback<Void>() {
.setTitle("Delete Service") @Override
.setMessage("Are you sure you want to delete " + etServiceName.getText().toString() + "?") public void onResponse(Call<Void> call, Response<Void> response) {
.setPositiveButton("Delete", (dialog, which) -> { if (response.isSuccessful()) {
serviceApi.deleteService((long) serviceId).enqueue(new Callback<Void>() { ActivityLogger.logChange(requireContext(), "Service", "DELETED", serviceId);
@Override Toast.makeText(getContext(), "Service deleted successfully!", Toast.LENGTH_SHORT).show();
public void onResponse(Call<Void> call, Response<Void> response) { navigateBack();
if (response.isSuccessful()) { } else {
ActivityLogger.logChange(requireContext(), "Service", "DELETED", serviceId); ErrorUtils.showErrorMessage(getContext(), response, "Failed to delete service");
Toast.makeText(getContext(), "Service deleted successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to delete service");
}
} }
}
@Override @Override
public void onFailure(Call<Void> call, Throwable t) { public void onFailure(Call<Void> call, Throwable t) {
ActivityLogger.logException(requireContext(), "ServiceDetailFragment.deleteService", new Exception(t)); ActivityLogger.logException(requireContext(), "ServiceDetailFragment.deleteService", new Exception(t));
Log.e("ServiceDetailFragment", "Error deleting service", t); Log.e("ServiceDetailFragment", "Error deleting service", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
} }
}); }));
})
.setNegativeButton("Cancel", null)
.show();
} }
/** /**

View File

@@ -2,7 +2,6 @@ package com.example.petstoremobile.fragments.listfragments.detailfragments;
import android.os.Bundle; import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
@@ -19,6 +18,7 @@ import com.example.petstoremobile.R;
import com.example.petstoremobile.api.SupplierApi; import com.example.petstoremobile.api.SupplierApi;
import com.example.petstoremobile.dtos.SupplierDTO; import com.example.petstoremobile.dtos.SupplierDTO;
import com.example.petstoremobile.utils.ActivityLogger; import com.example.petstoremobile.utils.ActivityLogger;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils; import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.InputValidator; import com.example.petstoremobile.utils.InputValidator;
import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.utils.UIUtils;
@@ -138,33 +138,26 @@ public class SupplierDetailFragment extends Fragment {
* Displays a confirmation dialog and handles the deletion of a supplier. * Displays a confirmation dialog and handles the deletion of a supplier.
*/ */
private void deleteSupplier() { private void deleteSupplier() {
//Alert the user to confirm the delete DialogUtils.showDeleteConfirmDialog(requireContext(), "Supplier", () ->
new AlertDialog.Builder(requireContext()) supplierApi.deleteSupplier((long) supId).enqueue(new Callback<Void>() {
.setTitle("Delete Supplier") @Override
.setMessage("Are you sure you want to delete " + etSupCompany.getText().toString() + "?") public void onResponse(Call<Void> call, Response<Void> response) {
.setPositiveButton("Delete", (dialog, which) -> { if (response.isSuccessful()) {
supplierApi.deleteSupplier((long) supId).enqueue(new Callback<Void>() { ActivityLogger.logChange(requireContext(), "Supplier", "DELETED", supId);
@Override Toast.makeText(getContext(), "Supplier deleted successfully!", Toast.LENGTH_SHORT).show();
public void onResponse(Call<Void> call, Response<Void> response) { navigateBack();
if (response.isSuccessful()) { } else {
ActivityLogger.logChange(requireContext(), "Supplier", "DELETED", supId); ErrorUtils.showErrorMessage(getContext(), response, "Failed to delete supplier");
Toast.makeText(getContext(), "Supplier deleted successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to delete supplier");
}
} }
}
@Override @Override
public void onFailure(Call<Void> call, Throwable t) { public void onFailure(Call<Void> call, Throwable t) {
ActivityLogger.logException(requireContext(), "SupplierDetailFragment.deleteSupplier", new Exception(t)); ActivityLogger.logException(requireContext(), "SupplierDetailFragment.deleteSupplier", new Exception(t));
Log.e("SupplierDetailFragment", "Error deleting supplier", t); Log.e("SupplierDetailFragment", "Error deleting supplier", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
} }
}); }));
})
.setNegativeButton("Cancel", null)
.show();
} }
/** /**

View File

@@ -0,0 +1,47 @@
package com.example.petstoremobile.utils;
import android.content.Context;
import androidx.appcompat.app.AlertDialog;
/**
* Utility class for creating and displaying common dialogs.
*/
public class DialogUtils {
/**
* Interface for handling dialog button clicks.
*/
public interface DialogCallback {
void onConfirm();
}
/**
* Shows a confirmation dialog with "Yes" and "No" buttons.
*/
public static void showConfirmDialog(Context context, String title, String message, DialogCallback callback) {
new AlertDialog.Builder(context)
.setTitle(title)
.setMessage(message)
.setPositiveButton("Yes", (dialog, which) -> callback.onConfirm())
.setNegativeButton("No", null)
.show();
}
/**
* Shows a delete confirmation dialog.
*/
public static void showDeleteConfirmDialog(Context context, String itemName, DialogCallback callback) {
showConfirmDialog(context, "Delete " + itemName + "?", "Are you sure you want to delete this " + itemName.toLowerCase() + "? This action cannot be undone.", callback);
}
/**
* Shows a simple information or error dialog with an "OK" button.
*/
public static void showInfoDialog(Context context, String title, String message) {
new AlertDialog.Builder(context)
.setTitle(title)
.setMessage(message)
.setPositiveButton("OK", null)
.show();
}
}