diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 72bf4c7..5d7a6cb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,7 +4,9 @@ plugins { android { namespace = "com.campusaula.edbole.kanban_clone_android" - compileSdk = 36 + compileSdk { + version = release(36) + } defaultConfig { applicationId = "com.campusaula.edbole.KanbanCloneAndroid" @@ -42,6 +44,7 @@ dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") + // Networking: OkHttp + Retrofit implementation("com.squareup.okhttp3:okhttp:4.11.0") implementation("com.squareup.okhttp3:logging-interceptor:4.11.0") implementation("com.squareup.retrofit2:retrofit:2.9.0") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d5f2638..9bd5106 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,18 +18,6 @@ - - - - diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/kanban/Task.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/kanban/Task.kt index 87f99c5..aea0031 100644 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/kanban/Task.kt +++ b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/kanban/Task.kt @@ -3,15 +3,15 @@ package com.campusaula.edbole.kanban_clone_android.kanban import com.google.gson.annotations.SerializedName enum class TaskStatus { - @SerializedName("pending") + @SerializedName("PENDING") PENDING, - @SerializedName("in_progress") + @SerializedName("IN_PROGRESS") IN_PROGRESS, - @SerializedName("completed") + @SerializedName("COMPLETED") COMPLETED, - @SerializedName("failed") + @SerializedName("FAILED") FAILED, - @SerializedName("stashed") + @SerializedName("STASHED") STASHED } @@ -19,7 +19,7 @@ class Task { val id: Int = 0 val title: String = "" val description: String = "" - var status: TaskStatus = TaskStatus.PENDING + val status: TaskStatus = TaskStatus.PENDING val project: Project? = null } @@ -36,14 +36,3 @@ data class TaskBase( @SerializedName("status") val status: TaskStatus ) - -data class TaskUpdate( - @SerializedName("title") - val title : String?, - - @SerializedName("description") - val description : String?, - - @SerializedName("status") - val status: TaskStatus? -) diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/network/ApiService.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/network/ApiService.kt index 296b6a1..6d9184b 100644 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/network/ApiService.kt +++ b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/network/ApiService.kt @@ -40,18 +40,6 @@ interface ApiService { @GET("projects/{project_id}/users/") suspend fun getProjectUsers(@Path("project_id") projectId: Int): Response> - @POST("projects/{project_id}/users/") - suspend fun addProjectCollaborator( - @Path("project_id") projectId: Int, - @Body email: Map - ): Response - - @DELETE("projects/{project_id}/users/{user_id}/") - suspend fun removeProjectCollaborator( - @Path("project_id") projectId: Int, - @Path("user_id") userId: Int - ): Response - @POST("projects/") suspend fun createProject(@Body projectCreate: ProjectCreate): Response @@ -69,17 +57,4 @@ interface ApiService { @POST("projects/{project_id}/tasks/") suspend fun createTask(@Path("project_id") projectId: Int, @Body taskBase: TaskBase): Response - @PUT("projects/{project_id}/tasks/{task_id}/") - suspend fun updateProjectTask( - @Path("project_id") projectId: Int, - @Path("task_id") taskId: Int, - @Body taskUpdate: TaskUpdate - ): Response - - @DELETE("projects/{project_id}/tasks/{task_id}/") - suspend fun deleteProjectTask( - @Path("project_id") projectId: Int, - @Path("task_id") taskId: Int - ): Response - } diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/CollaboratorAddActivity.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/CollaboratorAddActivity.kt deleted file mode 100644 index e68042e..0000000 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/CollaboratorAddActivity.kt +++ /dev/null @@ -1,126 +0,0 @@ -package com.campusaula.edbole.kanban_clone_android.ui - -import android.content.Intent -import android.os.Bundle -import android.util.Log -import android.util.Patterns -import android.widget.Button -import android.widget.EditText -import android.widget.Toast -import androidx.activity.enableEdgeToEdge -import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import androidx.lifecycle.lifecycleScope -import com.campusaula.edbole.kanban_clone_android.R -import com.campusaula.edbole.kanban_clone_android.network.ApiService -import com.campusaula.edbole.kanban_clone_android.network.RetrofitInstance -import com.google.android.material.floatingactionbutton.FloatingActionButton -import kotlinx.coroutines.launch - -class CollaboratorAddActivity : AppCompatActivity() { - - private lateinit var api: ApiService - - private lateinit var returnActionButton: FloatingActionButton - private lateinit var collaboratorEmailInput: EditText - private lateinit var addCollaboratorButton: Button - - private var projectId: Int = -1 - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContentView(R.layout.activity_collaborator_add) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } - - api = RetrofitInstance.getRetrofit(applicationContext).create(ApiService::class.java) - - // Get project ID from intent - projectId = intent.getIntExtra("project_id", -1) - - if (projectId == -1) { - Toast.makeText(this, "Error: Invalid project ID", Toast.LENGTH_SHORT).show() - finish() - return - } - - // Initialize views - returnActionButton = findViewById(R.id.returnActionButton) - collaboratorEmailInput = findViewById(R.id.collaboratorEmailInput) - addCollaboratorButton = findViewById(R.id.addCollaboratorButton) - - // Set up button listeners - returnActionButton.setOnClickListener { - finish() - - val intent = Intent(this@CollaboratorAddActivity, ProjectDetailActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - - } - - addCollaboratorButton.setOnClickListener { - addCollaborator() - } - } - - private fun addCollaborator() { - val user_email = collaboratorEmailInput.text.toString().trim() - - // Validate email - if (user_email.isEmpty()) { - Toast.makeText(this, "Email cannot be empty", Toast.LENGTH_SHORT).show() - return - } - - if (!Patterns.EMAIL_ADDRESS.matcher(user_email).matches()) { - Toast.makeText(this, "Please enter a valid email address", Toast.LENGTH_SHORT).show() - return - } - - lifecycleScope.launch { - try { - Log.d("CollaboratorAddActivity", "Adding collaborator: $user_email") - val emailBody = mapOf("user_email" to user_email) - val response = api.addProjectCollaborator(projectId, emailBody) - - if (response.isSuccessful) { - Log.d("CollaboratorAddActivity", "Collaborator added successfully") - Toast.makeText( - this@CollaboratorAddActivity, - "Collaborator added successfully", - Toast.LENGTH_SHORT - ).show() - setResult(RESULT_OK) - finish() - - // Reopen ProjectDetailActivity to show the new collaborator - val intent = Intent(this@CollaboratorAddActivity, ProjectDetailActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - } else { - val errorBody = response.errorBody()?.string() - Log.e("CollaboratorAddActivity", "Error adding collaborator: $errorBody") - Toast.makeText( - this@CollaboratorAddActivity, - "Error adding collaborator: ${response.code()}", - Toast.LENGTH_SHORT - ).show() - } - } catch (e: Exception) { - Log.e("CollaboratorAddActivity", "Exception adding collaborator: ${e.message}") - Toast.makeText( - this@CollaboratorAddActivity, - "Failed to add collaborator: ${e.message}", - Toast.LENGTH_SHORT - ).show() - } - } - } -} - diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/CreateProjectActivity.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/CreateProjectActivity.kt index 521add0..a0e80e4 100644 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/CreateProjectActivity.kt +++ b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/CreateProjectActivity.kt @@ -3,8 +3,9 @@ package com.campusaula.edbole.kanban_clone_android.ui import android.content.Intent import android.os.Bundle import android.util.Log +import android.widget.AutoCompleteTextView import android.widget.Button -import android.widget.EditText +import android.widget.MultiAutoCompleteTextView import android.widget.Toast import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity @@ -24,8 +25,8 @@ class CreateProjectActivity : AppCompatActivity() { private lateinit var api: ApiService private lateinit var returnActionButton : FloatingActionButton - private lateinit var newProjectName : EditText - private lateinit var newProjectDescription : EditText + private lateinit var newProjectName : AutoCompleteTextView + private lateinit var newProjectDescription : AutoCompleteTextView private lateinit var newProjectCreateButton : Button override fun onCreate(savedInstanceState: Bundle?) { @@ -41,63 +42,47 @@ class CreateProjectActivity : AppCompatActivity() { api = RetrofitInstance.getRetrofit(applicationContext).create(ApiService::class.java) returnActionButton = findViewById(R.id.returnActionButton) - returnActionButton.setOnClickListener { - finish() - - val intent = Intent(this@CreateProjectActivity, MainActivity::class.java) - startActivity(intent) - } + returnActionButton.setOnClickListener { finish() } newProjectName = findViewById(R.id.newProjectName) newProjectDescription = findViewById(R.id.newProjectDescription) newProjectCreateButton = findViewById(R.id.newProjectCreateButton) newProjectCreateButton.setOnClickListener { - val projectName = newProjectName.text.toString().trim() - val projectDescription = newProjectDescription.text.toString().trim() + val projectName = newProjectName.text.toString() + val projectDescription = newProjectDescription.text.toString() - if (projectName.isEmpty()) { - Toast.makeText(this, "Project name cannot be empty", Toast.LENGTH_SHORT).show() + if (projectName.isEmpty() || projectDescription.isEmpty()) { + Toast + .makeText(this, "Please fill in all fields", Toast.LENGTH_SHORT) + .show() return@setOnClickListener } lifecycleScope.launch { - try { - Log.d("CreateProjectActivity", "Creating project: $projectName") - val projectCreate = ProjectCreate(projectName, projectDescription) - val response = api.createProject(projectCreate) - if (response.isSuccessful) { - Log.d("CreateProjectActivity", "Project created successfully: ${response.body()}") - Toast.makeText( - this@CreateProjectActivity, - "Project created successfully", - Toast.LENGTH_SHORT - ).show() - finish() + val projectCreate : ProjectCreate = ProjectCreate(projectName, projectDescription) + val response = api.createProject(projectCreate) - // Volver a MainActivity para ver el nuevo proyecto - val intent = Intent(this@CreateProjectActivity, MainActivity::class.java) - startActivity(intent) - } else { - val errorBody = response.errorBody()?.string() - Log.e("CreateProjectActivity", "Error creating project: $errorBody") - Toast.makeText( - this@CreateProjectActivity, - "Error creating project: ${response.code()}", - Toast.LENGTH_SHORT - ).show() - } - } catch (e: Exception) { - Log.e("CreateProjectActivity", "Exception creating project: ${e.message}") - Toast.makeText( - this@CreateProjectActivity, - "Failed to create project: ${e.message}", - Toast.LENGTH_SHORT - ).show() + if (response.isSuccessful){ + Toast + .makeText(this@CreateProjectActivity, "Project created successfully", Toast.LENGTH_SHORT) + .show() + Log.d("CreateProjectActivity", "Created project: ${response.body()}") + startActivity(Intent(this@CreateProjectActivity, MainActivity::class.java)) + } else { + Log.e("CreateProjectActivity", "Error creating project: ${response.code()} - ${response.message()}") + Toast + .makeText(this@CreateProjectActivity, "Error creating project", Toast.LENGTH_SHORT) + .show() } + } + } + + + } } \ No newline at end of file diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/MainActivity.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/MainActivity.kt index 2dcfa11..fe71980 100644 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/MainActivity.kt +++ b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/MainActivity.kt @@ -15,7 +15,6 @@ import com.campusaula.edbole.kanban_clone_android.R import com.campusaula.edbole.kanban_clone_android.kanban.Project import com.campusaula.edbole.kanban_clone_android.network.ApiService import com.campusaula.edbole.kanban_clone_android.network.RetrofitInstance -import com.campusaula.edbole.kanban_clone_android.ui.adapters.ProjectItemAdapter import com.google.android.material.floatingactionbutton.FloatingActionButton import kotlinx.coroutines.launch @@ -82,9 +81,8 @@ class MainActivity : AppCompatActivity() { if (logoutResponse.isSuccessful) { // Clear cookies for the API host RetrofitInstance.clearCookiesForHost( - "10.0.2.2" + "10.0.2.2:8000" ) - // Navigate back to the login screen val intent = Intent(this@MainActivity, LoginActivity::class.java) diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectCollaboratorAdapter.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectCollaboratorAdapter.kt new file mode 100644 index 0000000..bc3cb26 --- /dev/null +++ b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectCollaboratorAdapter.kt @@ -0,0 +1,41 @@ +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 +) : RecyclerView.Adapter() { + + fun submitList(newList: List) { + 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 + + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectDetailActivity.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectDetailActivity.kt index 4db305c..3cb0662 100644 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectDetailActivity.kt +++ b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectDetailActivity.kt @@ -18,8 +18,6 @@ import com.campusaula.edbole.kanban_clone_android.kanban.Task import com.campusaula.edbole.kanban_clone_android.kanban.TaskStatus import com.campusaula.edbole.kanban_clone_android.network.ApiService import com.campusaula.edbole.kanban_clone_android.network.RetrofitInstance -import com.campusaula.edbole.kanban_clone_android.ui.adapters.ProjectCollaboratorAdapter -import com.campusaula.edbole.kanban_clone_android.ui.adapters.ProjectTaskAdapter import com.google.android.material.floatingactionbutton.FloatingActionButton import kotlinx.coroutines.launch @@ -30,14 +28,9 @@ class ProjectDetailActivity : AppCompatActivity() { private lateinit var returnActionButton: FloatingActionButton private lateinit var addTaskButton: Button private lateinit var addCollaboratorButton: Button - private lateinit var editProjectButton: Button - private lateinit var deleteProjectButton: Button - private lateinit var taskListRecycler: RecyclerView private lateinit var collaboratorListRecycler: RecyclerView - private lateinit var collaboratorListAdapter: ProjectCollaboratorAdapter - private lateinit var taskListAdapter: ProjectTaskAdapter - +// private lateinit var collaboratorListAdapter: CollaboratorListAdapter private lateinit var projectTitleText : TextView private lateinit var projectDescriptionText : TextView @@ -66,52 +59,23 @@ class ProjectDetailActivity : AppCompatActivity() { returnActionButton.setOnClickListener { finish() } addTaskButton = findViewById(R.id.addTaskButton) - addTaskButton.setOnClickListener { - val intent = Intent(this, TaskAddActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - finish() - } +// addTaskButton.setOnClickListener { +// val intent: Intent = Intent(this, CreateTaskActivity::class.java) +// intent.putExtra("project_id", projectId) +// startActivity(intent) +// } addCollaboratorButton = findViewById(R.id.addCollaboratorButton) - addCollaboratorButton.setOnClickListener { - val intent = Intent(this, CollaboratorAddActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - finish() - } - - taskListRecycler = findViewById(R.id.taskListRecycler) - taskListRecycler.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this) - taskListAdapter = ProjectTaskAdapter(emptyList(), api, projectId, { - updateCompletionRate() - }, { - finish() - }) - taskListRecycler.adapter = taskListAdapter +// addCollaboratorButton.setOnClickListener { +// val intent: Intent = Intent(this, AddCollaboratorActivity::class.java) +// intent.putExtra("project_id", projectId) +// startActivity(intent) +// } collaboratorListRecycler = findViewById(R.id.collaboratorListRecycler) +// collaboratorListAdapter = collaboratorListRecycler.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this) - collaboratorListAdapter = ProjectCollaboratorAdapter(emptyList(), api, projectId) { - updateCollaboratorList() - } - collaboratorListRecycler.adapter = collaboratorListAdapter - // Danger Zone buttons - editProjectButton = findViewById(R.id.editProjectButton) - editProjectButton.setOnClickListener { - val intent = Intent(this, ProjectEditActivity::class.java) - intent.putExtra("project_id", projectId) - intent.putExtra("project_name", projectTitleText.text.toString()) - intent.putExtra("project_description", projectDescriptionText.text.toString()) - startActivity(intent) - finish() - } - - deleteProjectButton = findViewById(R.id.deleteProjectButton) - deleteProjectButton.setOnClickListener { - deleteProject(projectId) - } if (projectId > 0) { Log.d("ProjectDetailActivity", "Received project ID: $projectId") @@ -130,22 +94,16 @@ class ProjectDetailActivity : AppCompatActivity() { projectDescriptionText.text = project.description var percentageFinished = 0.0; - val collaborators = project.users val tasks: List = project.tasks val totalTasks: Int = tasks.size + val perTaskPercentage = if (totalTasks > 0) (1.0 / totalTasks)*100 else 0.0 - var completedTasks = 0 for (task in tasks) { if (task.status == TaskStatus.COMPLETED) { - completedTasks++ + percentageFinished += perTaskPercentage } } - - percentageFinished = if (totalTasks > 0) (completedTasks.toDouble() / totalTasks.toDouble()) * 100 else 0.0 - completedPercentageText.text = "Completed: ${"%.2f".format(percentageFinished)}%" - - taskListAdapter.submitList(tasks.toMutableList()) - collaboratorListAdapter.submitList(collaborators.toMutableList()) + completedPercentageText.text = "Completed: ${"%.2f".format(percentageFinished * 100)}%" } else { @@ -166,90 +124,4 @@ class ProjectDetailActivity : AppCompatActivity() { } - - private fun updateCompletionRate() { - lifecycleScope.launch { - try { - val projectId = intent.getIntExtra("project_id", -1) - val projectResponse = api.getProjectById(projectId) - - if (projectResponse.isSuccessful && projectResponse.body() != null) { - val project = projectResponse.body()!! - val tasks: List = project.tasks - val totalTasks: Int = tasks.size - - var completedTasks = 0 - for (task in tasks) { - if (task.status == TaskStatus.COMPLETED) { - completedTasks++ - } - } - - val percentageFinished = if (totalTasks > 0) (completedTasks.toDouble() / totalTasks.toDouble()) * 100 else 0.0 - completedPercentageText.text = "Completed: ${"%.2f".format(percentageFinished)}%" - - // Actualizar la lista de tareas tambiƩn - taskListAdapter.submitList(tasks.toMutableList()) - } - } catch (e: Exception) { - Log.e("ProjectDetailActivity", "Error updating completion rate", e) - } - } - } - - private fun updateCollaboratorList() { - lifecycleScope.launch { - try { - val projectId = intent.getIntExtra("project_id", -1) - val projectResponse = api.getProjectById(projectId) - - if (projectResponse.isSuccessful && projectResponse.body() != null) { - val project = projectResponse.body()!! - val collaborators = project.users - - collaboratorListAdapter.submitList(collaborators.toMutableList()) - } - } catch (e: Exception) { - Log.e("ProjectDetailActivity", "Error updating collaborator list", e) - } - } - } - - private fun deleteProject(projectId: Int) { - lifecycleScope.launch { - try { - Log.d("ProjectDetailActivity", "Deleting project: $projectId") - val response = api.deleteProject(projectId) - - if (response.isSuccessful) { - Log.d("ProjectDetailActivity", "Project deleted successfully") - android.widget.Toast.makeText( - this@ProjectDetailActivity, - "Project deleted successfully", - android.widget.Toast.LENGTH_SHORT - ).show() - finish() - - // Volver a MainActivity - val intent = Intent(this@ProjectDetailActivity, MainActivity::class.java) - startActivity(intent) - } else { - val errorBody = response.errorBody()?.string() - Log.e("ProjectDetailActivity", "Error deleting project: $errorBody") - android.widget.Toast.makeText( - this@ProjectDetailActivity, - "Error deleting project: ${response.code()}", - android.widget.Toast.LENGTH_SHORT - ).show() - } - } catch (e: Exception) { - Log.e("ProjectDetailActivity", "Exception deleting project: ${e.message}") - android.widget.Toast.makeText( - this@ProjectDetailActivity, - "Failed to delete project: ${e.message}", - android.widget.Toast.LENGTH_SHORT - ).show() - } - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectEditActivity.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectEditActivity.kt deleted file mode 100644 index 0948826..0000000 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectEditActivity.kt +++ /dev/null @@ -1,134 +0,0 @@ -package com.campusaula.edbole.kanban_clone_android.ui - -import android.content.Intent -import android.os.Bundle -import android.util.Log -import android.widget.Button -import android.widget.EditText -import android.widget.Toast -import androidx.activity.enableEdgeToEdge -import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import androidx.lifecycle.lifecycleScope -import com.campusaula.edbole.kanban_clone_android.R -import com.campusaula.edbole.kanban_clone_android.kanban.ProjectCreate -import com.campusaula.edbole.kanban_clone_android.network.ApiService -import com.campusaula.edbole.kanban_clone_android.network.RetrofitInstance -import com.google.android.material.floatingactionbutton.FloatingActionButton -import kotlinx.coroutines.launch - -class ProjectEditActivity : AppCompatActivity() { - - private lateinit var api: ApiService - - private lateinit var returnActionButton: FloatingActionButton - private lateinit var projectNameInput: EditText - private lateinit var projectDescriptionInput: EditText - private lateinit var saveProjectButton: Button - - private var projectId: Int = -1 - private var currentName: String = "" - private var currentDescription: String = "" - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContentView(R.layout.activity_project_edit) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } - - api = RetrofitInstance.getRetrofit(applicationContext).create(ApiService::class.java) - - // Get project data from intent - projectId = intent.getIntExtra("project_id", -1) - currentName = intent.getStringExtra("project_name") ?: "" - currentDescription = intent.getStringExtra("project_description") ?: "" - - if (projectId == -1) { - Toast.makeText(this, "Error: Invalid project ID", Toast.LENGTH_SHORT).show() - finish() - return - } - - // Initialize views - returnActionButton = findViewById(R.id.returnActionButton) - projectNameInput = findViewById(R.id.projectNameInput) - projectDescriptionInput = findViewById(R.id.projectDescriptionInput) - saveProjectButton = findViewById(R.id.saveProjectButton) - - // Populate fields with current project data - projectNameInput.setText(currentName) - projectDescriptionInput.setText(currentDescription) - - // Set up button listeners - returnActionButton.setOnClickListener { - finish() - - val intent = Intent(this@ProjectEditActivity, ProjectDetailActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - } - - saveProjectButton.setOnClickListener { - saveProject() - } - } - - private fun saveProject() { - val newName = projectNameInput.text.toString().trim() - val newDescription = projectDescriptionInput.text.toString().trim() - - if (newName.isEmpty()) { - Toast.makeText(this, "Project name cannot be empty", Toast.LENGTH_SHORT).show() - return - } - - lifecycleScope.launch { - try { - Log.d("ProjectEditActivity", "Updating project: $projectId") - val projectCreate = ProjectCreate( - name = newName, - description = newDescription - ) - - val response = api.updateProject(projectId, projectCreate) - - if (response.isSuccessful) { - Log.d("ProjectEditActivity", "Project updated successfully") - Toast.makeText( - this@ProjectEditActivity, - "Project updated successfully", - Toast.LENGTH_SHORT - ).show() - setResult(RESULT_OK) - finish() - - // Reopen ProjectDetailActivity to show the updated project - val intent = Intent(this@ProjectEditActivity, ProjectDetailActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - } else { - val errorBody = response.errorBody()?.string() - Log.e("ProjectEditActivity", "Error updating project: $errorBody") - Toast.makeText( - this@ProjectEditActivity, - "Error updating project: ${response.code()}", - Toast.LENGTH_SHORT - ).show() - } - } catch (e: Exception) { - Log.e("ProjectEditActivity", "Exception updating project: ${e.message}") - Toast.makeText( - this@ProjectEditActivity, - "Failed to update project: ${e.message}", - Toast.LENGTH_SHORT - ).show() - } - } - } -} - diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/adapters/ProjectItemAdapter.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectItemAdapter.kt similarity index 95% rename from app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/adapters/ProjectItemAdapter.kt rename to app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectItemAdapter.kt index b2b3219..062b84b 100644 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/adapters/ProjectItemAdapter.kt +++ b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/ProjectItemAdapter.kt @@ -1,4 +1,4 @@ -package com.campusaula.edbole.kanban_clone_android.ui.adapters +package com.campusaula.edbole.kanban_clone_android.ui import android.view.LayoutInflater import android.view.View @@ -41,4 +41,4 @@ class ProjectItemAdapter( descriptionTextView.text = project.description } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/TaskAddActivity.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/TaskAddActivity.kt deleted file mode 100644 index 37d764c..0000000 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/TaskAddActivity.kt +++ /dev/null @@ -1,136 +0,0 @@ -package com.campusaula.edbole.kanban_clone_android.ui - -import android.content.Intent -import android.os.Bundle -import android.util.Log -import android.widget.Button -import android.widget.EditText -import android.widget.Spinner -import android.widget.Toast -import androidx.activity.enableEdgeToEdge -import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import androidx.lifecycle.lifecycleScope -import com.campusaula.edbole.kanban_clone_android.R -import com.campusaula.edbole.kanban_clone_android.kanban.TaskBase -import com.campusaula.edbole.kanban_clone_android.kanban.TaskStatus -import com.campusaula.edbole.kanban_clone_android.network.ApiService -import com.campusaula.edbole.kanban_clone_android.network.RetrofitInstance -import com.google.android.material.floatingactionbutton.FloatingActionButton -import kotlinx.coroutines.launch - -class TaskAddActivity : AppCompatActivity() { - - private lateinit var api: ApiService - - private lateinit var returnActionButton: FloatingActionButton - private lateinit var taskTitleInput: EditText - private lateinit var taskDescriptionInput: EditText - private lateinit var taskStatusSpinner: Spinner - private lateinit var createTaskButton: Button - - private var projectId: Int = -1 - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContentView(R.layout.activity_task_add) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } - - api = RetrofitInstance.getRetrofit(applicationContext).create(ApiService::class.java) - - // Get project ID from intent - projectId = intent.getIntExtra("project_id", -1) - - if (projectId == -1) { - Toast.makeText(this, "Error: Invalid project ID", Toast.LENGTH_SHORT).show() - finish() - return - } - - // Initialize views - returnActionButton = findViewById(R.id.returnActionButton) - taskTitleInput = findViewById(R.id.taskTitleInput) - taskDescriptionInput = findViewById(R.id.taskDescriptionInput) - taskStatusSpinner = findViewById(R.id.taskStatusSpinner) - createTaskButton = findViewById(R.id.createTaskButton) - - // Set default status to PENDING (index 0) - taskStatusSpinner.setSelection(0) - - // Set up button listeners - returnActionButton.setOnClickListener { - finish() - - val intent = Intent(this@TaskAddActivity, ProjectDetailActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - } - - createTaskButton.setOnClickListener { - createTask() - } - } - - private fun createTask() { - val title = taskTitleInput.text.toString().trim() - val description = taskDescriptionInput.text.toString().trim() - val status = TaskStatus.entries[taskStatusSpinner.selectedItemPosition] - - if (title.isEmpty()) { - Toast.makeText(this, "Title cannot be empty", Toast.LENGTH_SHORT).show() - return - } - - lifecycleScope.launch { - try { - Log.d("TaskAddActivity", "Creating task: $title") - val taskBase = TaskBase( - id = 0, // ID will be assigned by the server - title = title, - description = description, - status = status - ) - - val response = api.createTask(projectId, taskBase) - - if (response.isSuccessful) { - Log.d("TaskAddActivity", "Task created successfully") - Toast.makeText( - this@TaskAddActivity, - "Task created successfully", - Toast.LENGTH_SHORT - ).show() - setResult(RESULT_OK) - finish() - - // Reopen ProjectDetailActivity to show the new task - val intent = Intent(this@TaskAddActivity, ProjectDetailActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - } else { - val errorBody = response.errorBody()?.string() - Log.e("TaskAddActivity", "Error creating task: $errorBody") - Toast.makeText( - this@TaskAddActivity, - "Error creating task: ${response.code()}", - Toast.LENGTH_SHORT - ).show() - } - } catch (e: Exception) { - Log.e("TaskAddActivity", "Exception creating task: ${e.message}") - Toast.makeText( - this@TaskAddActivity, - "Failed to create task: ${e.message}", - Toast.LENGTH_SHORT - ).show() - } - } - } -} - diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/TaskEditActivity.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/TaskEditActivity.kt deleted file mode 100644 index 51aa741..0000000 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/TaskEditActivity.kt +++ /dev/null @@ -1,189 +0,0 @@ -package com.campusaula.edbole.kanban_clone_android.ui - -import android.content.Intent -import android.os.Bundle -import android.util.Log -import android.widget.Button -import android.widget.EditText -import android.widget.Spinner -import android.widget.Toast -import androidx.activity.enableEdgeToEdge -import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import androidx.lifecycle.lifecycleScope -import com.campusaula.edbole.kanban_clone_android.R -import com.campusaula.edbole.kanban_clone_android.kanban.TaskStatus -import com.campusaula.edbole.kanban_clone_android.kanban.TaskUpdate -import com.campusaula.edbole.kanban_clone_android.network.ApiService -import com.campusaula.edbole.kanban_clone_android.network.RetrofitInstance -import com.google.android.material.floatingactionbutton.FloatingActionButton -import kotlinx.coroutines.launch - -class TaskEditActivity : AppCompatActivity() { - - private lateinit var api: ApiService - - private lateinit var returnActionButton: FloatingActionButton - private lateinit var taskTitleInput: EditText - private lateinit var taskDescriptionInput: EditText - private lateinit var taskStatusSpinner: Spinner - private lateinit var saveTaskButton: Button - private lateinit var deleteTaskButton: Button - - private var projectId: Int = -1 - private var taskId: Int = -1 - private var currentTitle: String = "" - private var currentDescription: String = "" - private var currentStatus: TaskStatus = TaskStatus.PENDING - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContentView(R.layout.activity_task_edit) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } - - api = RetrofitInstance.getRetrofit(applicationContext).create(ApiService::class.java) - - // Get task and project IDs from intent - projectId = intent.getIntExtra("project_id", -1) - taskId = intent.getIntExtra("task_id", -1) - currentTitle = intent.getStringExtra("task_title") ?: "" - currentDescription = intent.getStringExtra("task_description") ?: "" - val statusString = intent.getStringExtra("task_status") ?: "PENDING" - currentStatus = TaskStatus.valueOf(statusString) - - if (projectId == -1 || taskId == -1) { - Toast.makeText(this, "Error: Invalid task or project ID", Toast.LENGTH_SHORT).show() - finish() - } - - // Initialize views - returnActionButton = findViewById(R.id.returnActionButton) - taskTitleInput = findViewById(R.id.taskTitleInput) - taskDescriptionInput = findViewById(R.id.taskDescriptionInput) - taskStatusSpinner = findViewById(R.id.taskStatusSpinner) - saveTaskButton = findViewById(R.id.saveTaskButton) - deleteTaskButton = findViewById(R.id.deleteTaskButton) - - // Populate fields with current task data - taskTitleInput.setText(currentTitle) - taskDescriptionInput.setText(currentDescription) - taskStatusSpinner.setSelection(TaskStatus.entries.indexOf(currentStatus)) - - // Set up button listeners - returnActionButton.setOnClickListener { - finish() - - val intent = Intent(this@TaskEditActivity, ProjectDetailActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - } - - saveTaskButton.setOnClickListener { - saveTask() - } - - deleteTaskButton.setOnClickListener { - deleteTask() - } - } - - private fun saveTask() { - val newTitle = taskTitleInput.text.toString().trim() - val newDescription = taskDescriptionInput.text.toString().trim() - val newStatus = TaskStatus.entries[taskStatusSpinner.selectedItemPosition] - - if (newTitle.isEmpty()) { - Toast.makeText(this, "Title cannot be empty", Toast.LENGTH_SHORT).show() - return - } - - lifecycleScope.launch { - try { - Log.d("TaskEditActivity", "Updating task: $taskId") - val taskUpdate = TaskUpdate( - title = if (newTitle != currentTitle) newTitle else null, - description = if (newDescription != currentDescription) newDescription else null, - status = if (newStatus != currentStatus) newStatus else null - ) - - val response = api.updateProjectTask(projectId, taskId, taskUpdate) - - if (response.isSuccessful) { - Log.d("TaskEditActivity", "Task updated successfully") - Toast.makeText( - this@TaskEditActivity, - "Task updated successfully", - Toast.LENGTH_SHORT - ).show() - setResult(RESULT_OK) - finish() - val intent = Intent(this@TaskEditActivity, ProjectDetailActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - } else { - val errorBody = response.errorBody()?.string() - Log.e("TaskEditActivity", "Error updating task: $errorBody") - Toast.makeText( - this@TaskEditActivity, - "Error updating task: ${response.code()}", - Toast.LENGTH_SHORT - ).show() - } - } catch (e: Exception) { - Log.e("TaskEditActivity", "Exception updating task: ${e.message}") - Toast.makeText( - this@TaskEditActivity, - "Failed to update task: ${e.message}", - Toast.LENGTH_SHORT - ).show() - } - } - } - - private fun deleteTask() { - lifecycleScope.launch { - try { - Log.d("TaskEditActivity", "Deleting task: $taskId") - val response = api.deleteProjectTask(projectId, taskId) - - if (response.isSuccessful) { - Log.d("TaskEditActivity", "Task deleted successfully") - Toast.makeText( - this@TaskEditActivity, - "Task deleted successfully", - Toast.LENGTH_SHORT - ).show() - setResult(RESULT_OK) - finish() - - // Reopen ProjectDetailActivity after deleting the task - val intent = Intent(this@TaskEditActivity, ProjectDetailActivity::class.java) - intent.putExtra("project_id", projectId) - startActivity(intent) - } else { - val errorBody = response.errorBody()?.string() - Log.e("TaskEditActivity", "Error deleting task: $errorBody") - Toast.makeText( - this@TaskEditActivity, - "Error deleting task: ${response.code()}", - Toast.LENGTH_SHORT - ).show() - } - } catch (e: Exception) { - Log.e("TaskEditActivity", "Exception deleting task: ${e.message}") - Toast.makeText( - this@TaskEditActivity, - "Failed to delete task: ${e.message}", - Toast.LENGTH_SHORT - ).show() - } - } - } -} - diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/adapters/ProjectCollaboratorAdapter.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/adapters/ProjectCollaboratorAdapter.kt deleted file mode 100644 index 96dbde5..0000000 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/adapters/ProjectCollaboratorAdapter.kt +++ /dev/null @@ -1,101 +0,0 @@ -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, - private val apiService: ApiService, - private val projectId: Int, - private val onCollaboratorRemoved: () -> Unit = {} -) : RecyclerView.Adapter() { - - private val adapterScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) - - fun submitList(newList: List) { - 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() - } - } - } - } - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/adapters/ProjectTaskAdapter.kt b/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/adapters/ProjectTaskAdapter.kt deleted file mode 100644 index ddb16db..0000000 --- a/app/src/main/java/com/campusaula/edbole/kanban_clone_android/ui/adapters/ProjectTaskAdapter.kt +++ /dev/null @@ -1,140 +0,0 @@ -package com.campusaula.edbole.kanban_clone_android.ui.adapters - -import android.content.Intent -import android.util.Log -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.AdapterView -import android.widget.Button -import android.widget.Spinner -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.Task -import com.campusaula.edbole.kanban_clone_android.kanban.TaskStatus -import com.campusaula.edbole.kanban_clone_android.kanban.TaskUpdate -import com.campusaula.edbole.kanban_clone_android.network.ApiService -import com.campusaula.edbole.kanban_clone_android.ui.TaskEditActivity -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 ProjectTaskAdapter( - private var tasks: List, - private val apiService: ApiService, - private val projectId: Int, - private val onTaskUpdated: () -> Unit = {}, - private val onEditTask: () -> Unit = {} -) : RecyclerView.Adapter() { - - private val adapterScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val view = LayoutInflater.from(parent.context).inflate(R.layout.item_task, parent, false) - return ViewHolder(view) - } - - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - holder.bind(tasks[position]) - } - - override fun getItemCount(): Int = tasks.size - - fun submitList(newList: List) { - tasks = newList - notifyDataSetChanged() - } - - // Cancelar el CoroutineScope cuando el adaptador ya no sea necesario - fun onDestroy() { - adapterScope.cancel() - } - - inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - private val taskTitleText: TextView = itemView.findViewById(R.id.taskTitleText) - private val taskDescriptionText: TextView = itemView.findViewById(R.id.taskDescriptionText) - private val editTaskButton: Button = itemView.findViewById(R.id.editTaskButton) - private val taskStatusPicker: Spinner = itemView.findViewById(R.id.taskStatusDropdown) - - fun bind(task: Task) { - taskTitleText.text = task.title - taskDescriptionText.text = task.description - - editTaskButton.setOnClickListener { - val intent = Intent(itemView.context, TaskEditActivity::class.java) - intent.putExtra("project_id", projectId) - intent.putExtra("task_id", task.id) - intent.putExtra("task_title", task.title) - intent.putExtra("task_description", task.description) - intent.putExtra("task_status", task.status.name) - itemView.context.startActivity(intent) - onEditTask() // Cerrar la actividad - } - - taskStatusPicker.setSelection(TaskStatus.entries.indexOf(task.status)) - - taskStatusPicker.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onItemSelected( - parent: AdapterView<*>?, - view: View?, - position: Int, - id: Long - ) { - val selectedStatus: TaskStatus = TaskStatus.entries[position] - task.status = selectedStatus - - adapterScope.launch { - try { - Log.d("ProjectTaskAdapter", "Sending PUT request for task: ${task.id}") - Log.d("ProjectTaskAdapter", "Project ID: $projectId") - Log.d("ProjectTaskAdapter", "TaskUpdate data: ${TaskUpdate(null, null, task.status)}") - - val response = apiService.updateProjectTask( - projectId, - task.id, - TaskUpdate(null, null, task.status) - ) - - if (response.isSuccessful) { - Log.d("ProjectTaskAdapter", "Task updated successfully: ${task.id}") - withContext(Dispatchers.Main) { - onTaskUpdated() - notifyDataSetChanged() - } - } else { - val errorBody = response.errorBody()?.string() - Log.e("ProjectTaskAdapter", "Error response: $errorBody") - withContext(Dispatchers.Main) { - Toast.makeText( - itemView.context, - "Error updating task: ${response.code()} - $errorBody", - Toast.LENGTH_SHORT - ).show() - } - } - } catch (e: Exception) { - Log.e("ProjectTaskAdapter", "Exception updating task: ${e.message}") - withContext(Dispatchers.Main) { - Toast.makeText( - itemView.context, - "Failed to update task: ${e.message}", - Toast.LENGTH_SHORT - ).show() - } - } - } - } - - override fun onNothingSelected(parent: AdapterView<*>?) { - // No action needed - } - } - - } - } -} diff --git a/app/src/main/res/layout/activity_collaborator_add.xml b/app/src/main/res/layout/activity_collaborator_add.xml deleted file mode 100644 index b31ddce..0000000 --- a/app/src/main/res/layout/activity_collaborator_add.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - -