mirror of
https://github.com/a-mayb3/KanbanCloneAndroid.git
synced 2026-03-21 10:05:39 +01:00
Task editing form
This commit is contained in:
parent
13ea6e4ef7
commit
421ffd5dc9
3 changed files with 333 additions and 6 deletions
|
|
@ -3,15 +3,15 @@ package com.campusaula.edbole.kanban_clone_android.kanban
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
enum class TaskStatus {
|
enum class TaskStatus {
|
||||||
@SerializedName("PENDING")
|
@SerializedName("pending")
|
||||||
PENDING,
|
PENDING,
|
||||||
@SerializedName("IN_PROGRESS")
|
@SerializedName("in_progress")
|
||||||
IN_PROGRESS,
|
IN_PROGRESS,
|
||||||
@SerializedName("COMPLETED")
|
@SerializedName("completed")
|
||||||
COMPLETED,
|
COMPLETED,
|
||||||
@SerializedName("FAILED")
|
@SerializedName("failed")
|
||||||
FAILED,
|
FAILED,
|
||||||
@SerializedName("STASHED")
|
@SerializedName("stashed")
|
||||||
STASHED
|
STASHED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -19,7 +19,7 @@ class Task {
|
||||||
val id: Int = 0
|
val id: Int = 0
|
||||||
val title: String = ""
|
val title: String = ""
|
||||||
val description: String = ""
|
val description: String = ""
|
||||||
val status: TaskStatus = TaskStatus.PENDING
|
var status: TaskStatus = TaskStatus.PENDING
|
||||||
val project: Project? = null
|
val project: Project? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,3 +36,14 @@ data class TaskBase(
|
||||||
@SerializedName("status")
|
@SerializedName("status")
|
||||||
val status: TaskStatus
|
val status: TaskStatus
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class TaskUpdate(
|
||||||
|
@SerializedName("title")
|
||||||
|
val title : String?,
|
||||||
|
|
||||||
|
@SerializedName("description")
|
||||||
|
val description : String?,
|
||||||
|
|
||||||
|
@SerializedName("status")
|
||||||
|
val status: TaskStatus?
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
127
app/src/main/res/layout/activity_task_edit.xml
Normal file
127
app/src/main/res/layout/activity_task_edit.xml
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
<?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:id="@+id/main"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.TaskEditActivity">
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/returnActionButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="@dimen/fab_margin_end"
|
||||||
|
android:layout_marginBottom="@dimen/fab_margin_bottom"
|
||||||
|
android:contentDescription="Return"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:srcCompat="@android:drawable/ic_menu_revert" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="@dimen/bottom_padding_for_fab">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/titleLabel"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Edit Task"
|
||||||
|
android:textSize="@dimen/text_size_title"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:padding="@dimen/padding_standard"
|
||||||
|
android:layout_marginTop="@dimen/margin_tiny" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/taskTitleLabel"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Title:"
|
||||||
|
android:textSize="@dimen/text_size_subtitle"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginTop="@dimen/margin_medium"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingRight="12dp" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/taskTitleInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="Enter task title"
|
||||||
|
android:inputType="text"
|
||||||
|
android:padding="@dimen/padding_standard"
|
||||||
|
android:layout_marginLeft="@dimen/margin_standard"
|
||||||
|
android:layout_marginRight="@dimen/margin_standard"
|
||||||
|
android:layout_marginTop="@dimen/margin_small" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/taskDescriptionLabel"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Description:"
|
||||||
|
android:textSize="@dimen/text_size_subtitle"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginTop="@dimen/margin_medium"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingRight="12dp" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/taskDescriptionInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="Enter task description"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:minLines="3"
|
||||||
|
android:maxLines="5"
|
||||||
|
android:padding="@dimen/padding_standard"
|
||||||
|
android:layout_marginLeft="@dimen/margin_standard"
|
||||||
|
android:layout_marginRight="@dimen/margin_standard"
|
||||||
|
android:layout_marginTop="@dimen/margin_small"
|
||||||
|
android:gravity="start|top" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/taskStatusLabel"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Status:"
|
||||||
|
android:textSize="@dimen/text_size_subtitle"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginTop="@dimen/margin_medium"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingRight="12dp" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/taskStatusSpinner"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:entries="@array/task_status_options"
|
||||||
|
android:padding="@dimen/padding_standard"
|
||||||
|
android:layout_marginLeft="@dimen/margin_standard"
|
||||||
|
android:layout_marginRight="@dimen/margin_standard"
|
||||||
|
android:layout_marginTop="@dimen/margin_small" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/saveTaskButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Save Changes"
|
||||||
|
android:backgroundTint="@color/primary_green"
|
||||||
|
android:layout_marginTop="@dimen/margin_large"
|
||||||
|
android:layout_marginLeft="@dimen/margin_standard"
|
||||||
|
android:layout_marginRight="@dimen/margin_standard" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/deleteTaskButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Delete Task"
|
||||||
|
android:backgroundTint="@color/danger_red"
|
||||||
|
android:layout_marginTop="@dimen/margin_medium"
|
||||||
|
android:layout_marginLeft="@dimen/margin_standard"
|
||||||
|
android:layout_marginRight="@dimen/margin_standard" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue