Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ dependencies {
implementation(libs.androidx.material3)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.recyclerview)
implementation(libs.androidx.cardview)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
Expand Down
175 changes: 151 additions & 24 deletions app/src/main/java/com/example/jlaja/AddBillActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,74 +4,201 @@ import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import android.widget.Spinner
import android.widget.*
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import java.io.Serializable

data class Item(val name: String, val unitPrice: Double, val memberPortions: MutableMap<String, Int> = mutableMapOf()) : Serializable

class AddBillActivity : AppCompatActivity() {

private lateinit var billNameEditText: EditText
private lateinit var billAmountEditText: EditText
private lateinit var billNameTextView: TextView
private lateinit var billAmountTextView: TextView
private lateinit var paidBySpinner: Spinner
private lateinit var membersRecyclerView: RecyclerView
private lateinit var membersAdapter: MembersAdapter
private lateinit var saveBillButton: Button
private lateinit var addItemButton: Button
private lateinit var itemsRecyclerView: RecyclerView
private lateinit var itemsAdapter: ItemsAdapter
private lateinit var spinnerAdapter: ArrayAdapter<String>

private val membersList = mutableListOf<String>()
private val memberAmounts = mutableMapOf<String, Double>() // Track each member's current amount
private val itemsList = mutableListOf<Item>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_bill)

// Initialize views
billNameEditText = findViewById(R.id.bill_name_edittext)
billAmountEditText = findViewById(R.id.bill_amount_edittext)
billNameTextView = findViewById(R.id.bill_name_textview)
billAmountTextView = findViewById(R.id.bill_amount_textview)
paidBySpinner = findViewById(R.id.paid_by_spinner)
membersRecyclerView = findViewById(R.id.members_recycler_view)
saveBillButton = findViewById(R.id.save_bill_button)
addItemButton = findViewById(R.id.add_item_button)
itemsRecyclerView = findViewById(R.id.items_recycler_view)

// Set up RecyclerView
membersRecyclerView.layoutManager = LinearLayoutManager(this)
membersAdapter = MembersAdapter(membersList)
membersAdapter = MembersAdapter(membersList, memberAmounts)
membersRecyclerView.adapter = membersAdapter

// Initialize Spinner adapter with an empty list (since no members are added yet)
itemsRecyclerView.layoutManager = LinearLayoutManager(this)
itemsAdapter = ItemsAdapter(itemsList)
itemsRecyclerView.adapter = itemsAdapter

spinnerAdapter = ArrayAdapter(this@AddBillActivity, android.R.layout.simple_spinner_item, membersList)
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
paidBySpinner.adapter = spinnerAdapter

// Button to add members
val billName = intent.getStringExtra("bill_name")
billNameTextView.text = billName ?: "Unknown Bill"



val addMembersButton: Button = findViewById(R.id.button2)
addMembersButton.setOnClickListener {
showAddMemberDialog()
}

// Set up save button click listener
addItemButton.setOnClickListener {
showAddItemDialog()
}

saveBillButton.setOnClickListener {
saveBill()
}
}

private fun calculateTotalAmount(): Double {
// Calculate the total amount based on all items
return itemsList.sumOf { it.unitPrice }
}

private fun calculateMemberShare(member: String): Double {
var totalShare = 0.0

// Calculate how much this member should pay based on portions
for (item in itemsList) {
val totalPortions = item.memberPortions.values.sum() // Total portions for this item
val memberPortion = item.memberPortions[member] ?: 0 // Portion for the current member

// Calculate member's share for this item
if (totalPortions > 0) {
totalShare += (memberPortion.toDouble() / totalPortions) * item.unitPrice
}
}

return totalShare
}

private fun updateMemberAmounts() {
// Recalculate each member's amount and update the display
membersList.forEach { member ->
memberAmounts[member] = calculateMemberShare(member)
}
membersAdapter.notifyDataSetChanged() // Refresh the members display
}

private fun showAddItemDialog() {
val dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_item, null)
val itemNameEditText = dialogView.findViewById<EditText>(R.id.item_name_edittext)
val itemPriceEditText = dialogView.findViewById<EditText>(R.id.item_price_edittext)

AlertDialog.Builder(this)
.setTitle("Enter Item Details")
.setView(dialogView)
.setPositiveButton("Add") { dialog, _ ->
val itemName = itemNameEditText.text.toString().trim()
val itemPrice = itemPriceEditText.text.toString().toDoubleOrNull() ?: 0.0

if (itemName.isNotEmpty() && itemPrice > 0) {
val item = Item(itemName, itemPrice)
itemsList.add(item)
itemsAdapter.notifyItemInserted(itemsList.size - 1)

// Show the portion assignment dialog for the newly added item
assignPortionsDialog(item)

// Update the total amount displayed and member amounts
updateTotalAmountDisplay()
updateMemberAmounts()
}
dialog.dismiss()
}
.setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() }
.show()
}

private fun updateTotalAmountDisplay() {
val totalAmount = calculateTotalAmount()
billAmountTextView.text = String.format("%.2f", totalAmount)
}

private fun assignPortionsDialog(item: Item) {
val dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_portion_assignment, null)
val portionsContainer = dialogView.findViewById<LinearLayout>(R.id.portions_container)

// Dynamically add portion input for each member
membersList.forEach { member ->
val memberRow = LayoutInflater.from(this).inflate(R.layout.portion_item, portionsContainer, false)
val memberNameText = memberRow.findViewById<TextView>(R.id.member_name_textview)
val portionEditText = memberRow.findViewById<EditText>(R.id.portion_edittext)

memberNameText.text = member
portionsContainer.addView(memberRow)
}

AlertDialog.Builder(this)
.setTitle("Assign Portions for ${item.name}")
.setView(dialogView)
.setPositiveButton("Save") { dialog, _ ->
for (i in 0 until portionsContainer.childCount) {
val row = portionsContainer.getChildAt(i)
val memberName = membersList[i]
val portionText = row.findViewById<EditText>(R.id.portion_edittext).text.toString()
val portion = portionText.toIntOrNull() ?: 0

item.memberPortions[memberName] = portion
}
itemsAdapter.notifyDataSetChanged()

// Update member amounts after assigning portions
updateMemberAmounts()
dialog.dismiss()
}
.setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() }
.show()
}

private fun saveBill() {
val billName = billNameEditText.text.toString().trim()
val billAmount = billAmountEditText.text.toString().trim()
//fix this nanti
val billName = billNameTextView.text.toString().trim()
val paidBy = paidBySpinner.selectedItem?.toString() ?: ""

if (billName.isNotEmpty() && billAmount.isNotEmpty()) {
if (billName.isNotEmpty()) {
val totalAmount = calculateTotalAmount()
val memberShares = membersList.associateWith { member ->
calculateMemberShare(member)
}

val bill = Bill(
name = billName,
amount = totalAmount,
totalAmount = totalAmount,
paidBy = paidBy,
memberShares = memberShares,
itemsList = itemsList
)

// Return the bill details to TripDetailsActivity
val resultIntent = Intent()
resultIntent.putExtra("bill_name", billName)
resultIntent.putExtra("bill_amount", billAmount)
resultIntent.putExtra("paid_by", paidBy)
resultIntent.putStringArrayListExtra("members", ArrayList(membersList))
resultIntent.putExtra("bill", bill) // Serialize the Bill object
setResult(Activity.RESULT_OK, resultIntent)
finish() // Close the activity
finish()
}
}

Expand All @@ -85,11 +212,11 @@ class AddBillActivity : AppCompatActivity() {
.setPositiveButton("Add") { dialog, _ ->
val memberName = memberNameEditText.text.toString().trim()
if (memberName.isNotEmpty()) {
// Add the new member to the list
membersList.add(memberName)
memberAmounts[memberName] = 0.0 // Initialize member's share to zero
membersAdapter.notifyItemInserted(membersList.size - 1)

// Update the Spinner to reflect the new member added
// Update PaidBy Spinner
spinnerAdapter.notifyDataSetChanged()
}
dialog.dismiss()
Expand Down
71 changes: 58 additions & 13 deletions app/src/main/java/com/example/jlaja/BillAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,73 @@ package com.example.jlaja
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import java.io.Serializable

// Adapter class for RecyclerView to display the list of bills
class BillsAdapter(private val billsList: List<String>) : RecyclerView.Adapter<BillsAdapter.BillViewHolder>() {
// Updated Bill data class with memberShares as a Map
data class Bill(
val name: String = "default bill",
val amount: Double = 0.0,
val totalAmount: Double = 0.0,
val paidBy: String = "ye",
val memberShares: Map<String, Double> = emptyMap(), // Member shares map
val itemsList: List<Item> = emptyList()
) : Serializable

class BillsAdapter(private val bills: List<Bill>) : RecyclerView.Adapter<BillsAdapter.BillViewHolder>() {

// ViewHolder class to hold references to the views for each item
class BillViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val billNameTextView: TextView = itemView.findViewById(R.id.bill_name_textview)
private val totalAmountTextView: TextView = itemView.findViewById(R.id.total_amount_textview)
private val paidByTextView: TextView = itemView.findViewById(R.id.paid_by_textview)
private val membersSharesContainer: LinearLayout = itemView.findViewById(R.id.members_shares_container)

// Bind the bill details to the views
fun bind(bill: Bill) {
// Set the bill information
billNameTextView.text = bill.name
totalAmountTextView.text = "Total amount: $${"%.2f".format(bill.amount)}"
paidByTextView.text = "Paid By: ${bill.paidBy}"

// Clear any previous member share views to avoid duplication
membersSharesContainer.removeAllViews()

// Dynamically create and add views for each member's share
bill.memberShares.forEach { (memberName, shareAmount) ->
val memberShareView = LayoutInflater.from(itemView.context)
.inflate(R.layout.item_member_share, membersSharesContainer, false)

// Find the TextViews in the member share view and set the data
val memberNameTextView = memberShareView.findViewById<TextView>(R.id.member_name_textview)
val memberShareTextView = memberShareView.findViewById<TextView>(R.id.member_share_textview)

// Set the member's name and share amount
memberNameTextView.text = memberName
memberShareTextView.text = "Owes: $${"%.2f".format(shareAmount)}"




// Add the view to the members' container layout
membersSharesContainer.addView(memberShareView)
}
}
}

// Create a new view for each item
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BillViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_bill, parent, false)
return BillViewHolder(view)
}

// Bind the data to each view item
override fun onBindViewHolder(holder: BillViewHolder, position: Int) {
holder.bind(billsList[position])
holder.bind(bills[position])
}

override fun getItemCount(): Int = billsList.size

class BillViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val billTextView: TextView = itemView.findViewById(R.id.bill_textview)

fun bind(billDetails: String) {
billTextView.text = billDetails
}
}
}
// Return the total number of items
override fun getItemCount(): Int = bills.size
}
3 changes: 3 additions & 0 deletions app/src/main/java/com/example/jlaja/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
Expand Down Expand Up @@ -60,6 +61,8 @@ class MainActivity : AppCompatActivity() {
val tripName = tripNameEditText.text.toString().trim()
if (tripName.isNotEmpty()) {
addNewTrip(tripName) // Add the trip with the user-defined name
} else {
Toast.makeText(this, "Trip name cannot be empty", Toast.LENGTH_SHORT).show()
}
dialog.dismiss()
}
Expand Down
Loading