Skip to content

Commit

Permalink
Select and Delete items (#49)
Browse files Browse the repository at this point in the history
* incomplete draft of splitting home fragment

* Split home fragment and implemented select/delete

* addressed pr comments + added parcelable interface

* put uncommon methods from parent Home to children

* Rename Fragments

* Merge everything nicely

---------

Co-authored-by: ldbonkowski <lbonkows@ualberta.ca>
  • Loading branch information
Sami-Jagirdar and ldbonkowski authored Nov 10, 2023
1 parent 0017939 commit 9807ac1
Show file tree
Hide file tree
Showing 18 changed files with 680 additions and 42 deletions.
3 changes: 2 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ dependencies {
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.10.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.navigation:navigation-fragment:2.7.4")
implementation("androidx.navigation:navigation-fragment:2.7.5")
implementation("androidx.core:core:1.12.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
Expand Down
65 changes: 65 additions & 0 deletions app/src/main/java/com/example/househomey/DeleteItemsFragment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.example.househomey;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;

import java.util.ArrayList;

/**
* A Dialog popup fragment that handles confirmation of deletion of items
* @author Sami Jagirdar
*/
public class DeleteItemsFragment extends DialogFragment {

private final DeleteCallBack listener;
private final ArrayList<Item> selectedItems;

/**
* Constructor for the Delete Items confirmation dialog fragment
* @param deleteCallBack context in which the dialog fragment is attached
* @param selectedItems items selected to be deleted
*/
public DeleteItemsFragment(DeleteCallBack deleteCallBack, ArrayList<Item> selectedItems) {
this.listener = deleteCallBack;
this.selectedItems = selectedItems;
}

/**
* Called to create and return the delete items confirmation dialog
* @param savedInstanceState The last saved instance state of the Fragment,
* or null if this is a freshly created Fragment.
*
* @return The confirm deletion dialog to be displayed
*/
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
View view = getLayoutInflater().inflate(R.layout.fragment_delete_items, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());

return builder
.setView(view)
.setTitle(listener.DialogTitle(selectedItems))
.setNegativeButton("Cancel",null)
.setPositiveButton("OK",(dialog,which)->{
listener.onOKPressed(selectedItems);
}).create();
}

/**
* A Callback interface for handling deletion of items in the applicable context
* @see SelectFragment
*/
public interface DeleteCallBack {
void onOKPressed(ArrayList<Item> selectedItems);
String DialogTitle(ArrayList<Item> selectedItems);
}
}
44 changes: 31 additions & 13 deletions app/src/main/java/com/example/househomey/HomeFragment.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package com.example.househomey;

import static com.example.househomey.utils.FragmentUtils.navigateToFragmentPage;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.TextView;

import androidx.fragment.app.Fragment;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.example.househomey.filter.model.DateFilter;
import com.example.househomey.filter.model.KeywordFilter;
Expand All @@ -29,29 +31,31 @@
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;

import java.util.Date;
import java.util.ArrayList;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import java.util.ArrayList;
import java.util.Set;

/**
* This fragment represents the home screen containing the primary list of the user's inventory
* @author Owen Cooke, Jared Drueco, Lukas Bonkowski
* This fragment is a child of the home fragment containing the list of the user's inventory
* This fragment represents a state where items are selectable
* @see HomeFragment
* @author Owen Cooke, Jared Drueco, Lukas Bonkowski, Sami Jagirdar
*/
public class HomeFragment extends Fragment implements FilterCallback {
private CollectionReference itemRef;
private ListView itemListView;
private ArrayList<Item> itemList = new ArrayList<>();
private ArrayList<Item> filteredItemList = new ArrayList<>();
private ItemAdapter itemAdapter;
private Set<Filter> appliedFilters = new HashSet<>();
private ArrayAdapter<Item> itemAdapter;
private TextView listCountView;
private TextView listSumView;
private BigDecimal listSum = new BigDecimal("0.00");
private int listCount = 0;

/**
* @param inflater The LayoutInflater object that can be used to inflate
Expand All @@ -62,21 +66,36 @@ public class HomeFragment extends Fragment implements FilterCallback {
* @param savedInstanceState If non-null, this fragment is being re-constructed
* from a previous saved state as given here.
* @return the home fragment view containing the inventory list
* in its base state where items are not selectable
*/
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
this.itemRef = ((MainActivity) requireActivity()).getItemRef();
// Inflate the fragment's layout
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
rootView.findViewById(R.id.base_toolbar).setVisibility(View.VISIBLE);
rootView.findViewById(R.id.select_toolbar).setVisibility(View.GONE);

listCountView = rootView.findViewById(R.id.total_count_text);
listSumView = rootView.findViewById(R.id.total_value_text);

itemRef.addSnapshotListener(this::setupItemListener);
itemListView = rootView.findViewById(R.id.item_list);
itemAdapter = new ItemAdapter(getContext(), filteredItemList);
itemListView.setAdapter(itemAdapter);

itemRef.addSnapshotListener(this::setupItemListener);
itemAdapter.setSelectState(false);


final Button selectButton = rootView.findViewById(R.id.select_items_button);
selectButton.setOnClickListener(v -> {
SelectFragment selectStateFragment = new SelectFragment();
Bundle args = new Bundle();
args.putParcelableArrayList("itemList", itemList);
args.putInt("listCount", listCount);
args.putString("listSum", listSum.toString());
selectStateFragment.setArguments(args);
navigateToFragmentPage(getContext(), selectStateFragment);
});

View filterButton = rootView.findViewById(R.id.filter_dropdown_button);
filterButton.setOnClickListener(this::showFilterMenu);
Expand All @@ -97,7 +116,6 @@ private void setupItemListener(QuerySnapshot querySnapshots, FirebaseFirestoreEx
return;
}
if (querySnapshots != null) {

itemList.clear();
for (QueryDocumentSnapshot doc: querySnapshots) {
Map<String, Object> data = new HashMap<>(doc.getData());
Expand Down Expand Up @@ -210,8 +228,8 @@ private void applyFilters() {
* list is modified.
*/
private void updateListData() {
BigDecimal listSum = new BigDecimal(0.00);
int listCount = filteredItemList.size();
listSum = new BigDecimal("0.00");
listCount = filteredItemList.size();
for (int i = 0; i < listCount; i++) {
listSum = listSum.add(filteredItemList.get(i).getCost());
}
Expand Down
92 changes: 84 additions & 8 deletions app/src/main/java/com/example/househomey/Item.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.example.househomey;

import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;

import com.google.firebase.Timestamp;
Expand All @@ -14,10 +17,10 @@

/**
* This class represents an inventory item with a variety of properties
* @author Lukas Bonkowski, Matthew Neufeld, Owen Cooke
* @author Lukas Bonkowski, Matthew Neufeld, Owen Cooke, Sami Jagirdar
* @see ItemAdapter
*/
public class Item implements Serializable {
public class Item implements Serializable, Parcelable {
private String id;
private String description;
private Date acquisitionDate;
Expand All @@ -29,7 +32,8 @@ public class Item implements Serializable {

/**
* This constructs a new item from a Map of data with a reference to its Firestore document
* @param id The id of this object's document in the firestore database
*
* @param id The id of this object's document in the firestore database
* @param data The data from that document to initialize the instance
* @throws NullPointerException if a null required field is given
*/
Expand Down Expand Up @@ -57,6 +61,7 @@ public Item(String id, @NonNull Map<String, Object> data) {

/**
* Convenient getter for map of properties to be used for Firestore queries
*
* @return A Map containing all the properties of this object as key-value pairs
*/
public Map<String, Object> getData() {
Expand Down Expand Up @@ -86,6 +91,7 @@ public Map<String, Object> getData() {

/**
* Getter for id
*
* @return The id of this item in firestore
*/
public String getId() {
Expand All @@ -94,6 +100,7 @@ public String getId() {

/**
* Getter for acquisitionDate
*
* @return The acquisition date of this item
*/
public Date getAcquisitionDate() {
Expand All @@ -102,6 +109,7 @@ public Date getAcquisitionDate() {

/**
* Getter for description
*
* @return The brief description of this item
*/
public String getDescription() {
Expand All @@ -111,6 +119,7 @@ public String getDescription() {

/**
* Getter for cost
*
* @return The cost of this item
*/
public BigDecimal getCost() {
Expand All @@ -119,25 +128,92 @@ public BigDecimal getCost() {

/**
* Getter for make
*
* @return make of the item
*/
public String getMake() { return make; }
public String getMake() {
return make;
}

/**
* Getter for model
*
* @return model of the item
*/
public String getModel() { return model; }
public String getModel() {
return model;
}

/**
* Getter for serial number
*
* @return serial number of the item
*/
public String getSerialNumber() { return serialNumber; }
public String getSerialNumber() {
return serialNumber;
}

/**
* Getter for comment
*
* @return comment for the item
*/
public String getComment() { return comment; }
}
public String getComment() {
return comment;
}


//Creating the Parcelable CREATOR and
//Implementing the Parcelable Interface below
public static final Parcelable.Creator<Item> CREATOR = new Parcelable.Creator<Item>() {
public Item createFromParcel(Parcel in) {
return new Item(in);
}
public Item[] newArray(int size) {
return new Item[size];
}
};

/**
* This method determines how an item object is written to a Parcel
* @param out The Parcel in which the object should be written.
* @param flags Additional flags about how the object should be written.
* May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
*/
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(id);
out.writeString(description);
out.writeLong(acquisitionDate.getTime());
out.writeString(make); //Note: You can pass null values to Parcel
out.writeString(model);
out.writeString(serialNumber);
out.writeString(comment);
out.writeSerializable(cost.toString());
}

/**
* Constructs an item object by reading its attributes from a Parcel object
* @param in The parcel object that reads the data
*/
protected Item(Parcel in) {
this.id = in.readString();
this.description = in.readString();
this.acquisitionDate = new Date(in.readLong());
this.make = in.readString();
this.model = in.readString();
this.serialNumber = in.readString();
this.comment = in.readString();
this.cost = new BigDecimal(in.readString()).setScale(2, RoundingMode.HALF_UP);
}

/**
* Interface method that provides the CONTENTS_FILE_DESCRIPTOR
* for when a FileDescriptor object is to be put in a Parcelable
* @return 0 since we don't use FileDescriptor objects in this project
*/
@Override
public int describeContents() {
return 0;
}
}
Loading

0 comments on commit 9807ac1

Please sign in to comment.