Moved adapters to their own package and create collaborator item

This commit is contained in:
Marta Borgia Leiva 2026-02-12 11:42:14 +01:00
parent 421ffd5dc9
commit e9e2ac3d2a
6 changed files with 159 additions and 46 deletions

View file

@ -1,41 +0,0 @@
package com.campusaula.edbole.kanban_clone_android.ui
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.campusaula.edbole.kanban_clone_android.kanban.User
class ProjectCollaboratorAdapter(
private var collaborators: List<User>
) : RecyclerView.Adapter<ProjectCollaboratorAdapter.ViewHolder>() {
fun submitList(newList: List<User>) {
collaborators = newList.toMutableList()
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_collaborator, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(collaborators[position])
}
override fun getItemCount(): Int = collaborators.size
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val collaboratorNameText: TextView = itemView.findViewById(R.id.collaboratorNameText)
private val removeCollaboratorButton: Button = itemView.findViewById(R.id.removeCollaboratorButton)
fun bind(collaborator: User) {
collaboratorNameText.text = collaborator.name
}
}
}
}

View file

@ -0,0 +1,101 @@
package com.campusaula.edbole.kanban_clone_android.ui.adapters
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.campusaula.edbole.kanban_clone_android.R
import com.campusaula.edbole.kanban_clone_android.kanban.User
import com.campusaula.edbole.kanban_clone_android.network.ApiService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class ProjectCollaboratorAdapter(
private var collaborators: List<User>,
private val apiService: ApiService,
private val projectId: Int,
private val onCollaboratorRemoved: () -> Unit = {}
) : RecyclerView.Adapter<ProjectCollaboratorAdapter.ViewHolder>() {
private val adapterScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
fun submitList(newList: List<User>) {
collaborators = newList.toMutableList()
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_collaborator, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(collaborators[position])
}
override fun getItemCount(): Int = collaborators.size
fun onDestroy() {
adapterScope.cancel("Adapter destroyed")
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val collaboratorNameText: TextView = itemView.findViewById(R.id.collaboratorNameText)
private val collaboratorEmailText: TextView = itemView.findViewById(R.id.collaboratorEmailText)
private val removeCollaboratorButton: Button = itemView.findViewById(R.id.removeCollaboratorButton)
fun bind(collaborator: User) {
collaboratorNameText.text = collaborator.name
collaboratorEmailText.text = collaborator.email
removeCollaboratorButton.setOnClickListener {
adapterScope.launch {
try {
Log.d("ProjectCollaboratorAdapter", "Removing collaborator: ${collaborator.id}")
val response = apiService.removeProjectCollaborator(projectId, collaborator.id)
if (response.isSuccessful) {
Log.d("ProjectCollaboratorAdapter", "Collaborator removed successfully: ${collaborator.id}")
withContext(Dispatchers.Main) {
Toast.makeText(
itemView.context,
"Collaborator removed: ${collaborator.name}",
Toast.LENGTH_SHORT
).show()
onCollaboratorRemoved()
}
} else {
val errorBody = response.errorBody()?.string()
Log.e("ProjectCollaboratorAdapter", "Error removing collaborator: $errorBody")
withContext(Dispatchers.Main) {
Toast.makeText(
itemView.context,
"Error removing collaborator: ${response.code()}",
Toast.LENGTH_SHORT
).show()
}
}
} catch (e: Exception) {
Log.e("ProjectCollaboratorAdapter", "Exception removing collaborator: ${e.message}")
withContext(Dispatchers.Main) {
Toast.makeText(
itemView.context,
"Failed to remove collaborator: ${e.message}",
Toast.LENGTH_SHORT
).show()
}
}
}
}
}
}
}

View file

@ -1,4 +1,4 @@
package com.campusaula.edbole.kanban_clone_android.ui package com.campusaula.edbole.kanban_clone_android.ui.adapters
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -41,4 +41,4 @@ class ProjectItemAdapter(
descriptionTextView.text = project.description descriptionTextView.text = project.description
} }
} }
} }

View file

@ -55,4 +55,4 @@
app:layout_constraintHorizontal_bias="0.5" app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
style="@style/Widget.Material3.Button.TextButton" /> style="@style/Widget.Material3.Button.TextButton" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -35,7 +35,7 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:layout_editor_absoluteX="1dp" tools:layout_editor_absoluteX="0dp"
app:layout_constraintTop_toBottomOf="@+id/logoutButton" app:layout_constraintTop_toBottomOf="@+id/logoutButton"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:id="@+id/projectsRecyclerView" /> android:id="@+id/projectsRecyclerView" />
@ -51,4 +51,4 @@
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_horizontal|end"
android:layout_margin="8dp"
android:id="@+id/linearLayout">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="4dp">
<TextView
android:id="@+id/collaboratorNameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Collaborator Name"
android:textSize="18dp"
android:textStyle="bold" />
<TextView
android:text="example@email.com"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/collaboratorEmailText"
android:textStyle="italic" />
</LinearLayout>
<Button
android:id="@+id/removeCollaboratorButton"
android:layout_width="50dp"
android:layout_height="wrap_content"
style="@style/Widget.Material3.Button.Icon"
app:icon="@android:drawable/ic_delete"
android:backgroundTint="@color/transparent_red"
app:iconTint="@color/danger_red"
android:layout_marginEnd="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.333" />
</androidx.constraintlayout.widget.ConstraintLayout>