From 700d8cdd113ec88acbf0e79d1a69a5f893e93c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sat, 13 Jul 2024 01:10:58 +0700 Subject: [PATCH 01/35] misc --- .../com/prm/tasksboard/taskboards/entity/TaskItem.kt | 11 +++++++++++ .../tasksboard/taskboards/view/TaskboardsActivity.kt | 6 +++--- app/src/main/res/layout/activity_taskboards.xml | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt b/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt new file mode 100644 index 0000000..1361495 --- /dev/null +++ b/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt @@ -0,0 +1,11 @@ +package com.prm.tasksboard.taskboards.entity + +data class TaskItem( + var taskId: String = "", + var boardId: String = "", + var title: String = "", // Changed from name to title + var description: String = "", + var status: String = "", + var dueDate: String = "", // Added dueDate field + var priority: String = "" // Added priority field +) \ No newline at end of file diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt index d1c9c31..df9561b 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt @@ -26,7 +26,7 @@ class TaskboardsActivity : AppCompatActivity() { private lateinit var viewPager: ViewPager2 private lateinit var tabLayout: TabLayout private lateinit var boardPagerAdapter: BoardPagerAdapter - private lateinit var addBoardButton: Button + private lateinit var addTaskButton: Button private lateinit var menuButton: MaterialButton private lateinit var emptyView: TextView private var tabLayoutMediator: TabLayoutMediator? = null @@ -50,7 +50,7 @@ class TaskboardsActivity : AppCompatActivity() { viewPager = findViewById(R.id.viewPager) tabLayout = findViewById(R.id.tabLayout) - addBoardButton = findViewById(R.id.addBoardButton) + addTaskButton = findViewById(R.id.addTaskButton) menuButton = findViewById(R.id.menuButton) emptyView = findViewById(R.id.emptyView) @@ -64,7 +64,7 @@ class TaskboardsActivity : AppCompatActivity() { setTabLayoutListeners() updateEmptyViewVisibility() - addBoardButton.setOnClickListener { + addTaskButton.setOnClickListener { createNewBoard() } diff --git a/app/src/main/res/layout/activity_taskboards.xml b/app/src/main/res/layout/activity_taskboards.xml index df07478..e0507df 100644 --- a/app/src/main/res/layout/activity_taskboards.xml +++ b/app/src/main/res/layout/activity_taskboards.xml @@ -19,11 +19,11 @@ android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="0dp" - app:layout_constraintBottom_toTopOf="@+id/addBoardButton" + app:layout_constraintBottom_toTopOf="@+id/addTaskButton" app:layout_constraintTop_toBottomOf="@id/tabLayout" /> Date: Sat, 13 Jul 2024 01:10:58 +0700 Subject: [PATCH 02/35] misc --- .../com/prm/tasksboard/taskboards/entity/TaskItem.kt | 11 +++++++++++ app/src/main/res/layout/activity_taskboards.xml | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt b/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt new file mode 100644 index 0000000..1361495 --- /dev/null +++ b/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt @@ -0,0 +1,11 @@ +package com.prm.tasksboard.taskboards.entity + +data class TaskItem( + var taskId: String = "", + var boardId: String = "", + var title: String = "", // Changed from name to title + var description: String = "", + var status: String = "", + var dueDate: String = "", // Added dueDate field + var priority: String = "" // Added priority field +) \ No newline at end of file diff --git a/app/src/main/res/layout/activity_taskboards.xml b/app/src/main/res/layout/activity_taskboards.xml index df07478..e0507df 100644 --- a/app/src/main/res/layout/activity_taskboards.xml +++ b/app/src/main/res/layout/activity_taskboards.xml @@ -19,11 +19,11 @@ android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="0dp" - app:layout_constraintBottom_toTopOf="@+id/addBoardButton" + app:layout_constraintBottom_toTopOf="@+id/addTaskButton" app:layout_constraintTop_toBottomOf="@id/tabLayout" /> Date: Sat, 13 Jul 2024 14:49:18 +0700 Subject: [PATCH 03/35] Update activity_taskboards.xml --- app/src/main/res/layout/activity_taskboards.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/activity_taskboards.xml b/app/src/main/res/layout/activity_taskboards.xml index e0507df..df07478 100644 --- a/app/src/main/res/layout/activity_taskboards.xml +++ b/app/src/main/res/layout/activity_taskboards.xml @@ -19,11 +19,11 @@ android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="0dp" - app:layout_constraintBottom_toTopOf="@+id/addTaskButton" + app:layout_constraintBottom_toTopOf="@+id/addBoardButton" app:layout_constraintTop_toBottomOf="@id/tabLayout" /> Date: Sat, 13 Jul 2024 18:29:13 +0700 Subject: [PATCH 04/35] modify TaskItem data class --- .../tasksboard/taskboards/entity/TaskItem.kt | 19 ++-- .../taskboards/firestore/DatabaseHandler.kt | 49 +++++++-- .../tasksboard/taskboards/view/TaskAdapter.kt | 35 ++++++ .../taskboards/view/TaskboardsActivity.kt | 102 +++++++++++++++++- .../main/res/layout/activity_taskboards.xml | 8 ++ app/src/main/res/layout/task_item.xml | 30 ++++++ 6 files changed, 226 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt create mode 100644 app/src/main/res/layout/task_item.xml diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt b/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt index 1361495..eaad2ae 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt @@ -1,11 +1,16 @@ package com.prm.tasksboard.taskboards.entity +import com.google.firebase.Timestamp +import com.google.firebase.firestore.PropertyName + data class TaskItem( - var taskId: String = "", - var boardId: String = "", - var title: String = "", // Changed from name to title - var description: String = "", - var status: String = "", - var dueDate: String = "", // Added dueDate field - var priority: String = "" // Added priority field + @get:PropertyName("task_id") @set:PropertyName("task_id") var taskId: String = "", + @get:PropertyName("title") @set:PropertyName("title") var title: String = "", + @get:PropertyName("description") @set:PropertyName("description") var description: String = "", + @get:PropertyName("status") @set:PropertyName("status") var status: String = "", + @get:PropertyName("due_date") @set:PropertyName("due_date") var dueDate: String = "", + @get:PropertyName("priority") @set:PropertyName("priority") var priority: String = "", + @get:PropertyName("created_at") @set:PropertyName("created_at") var createdAt: Timestamp? = null, + @get:PropertyName("user_id") @set:PropertyName("user_id") var userId: String = "", + @get:PropertyName("board_id") @set:PropertyName("board_id") var boardId: String = "" // Add this field ) \ No newline at end of file diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt b/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt index 244a5c9..f9a8962 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt @@ -2,33 +2,37 @@ package com.prm.tasksboard.taskboards.firestore import android.util.Log import com.google.android.gms.tasks.Task +import com.google.firebase.Timestamp import com.google.firebase.auth.FirebaseAuth import com.google.firebase.firestore.QuerySnapshot import com.google.firebase.firestore.ktx.firestore import com.google.firebase.ktx.Firebase import com.prm.tasksboard.taskboards.entity.BoardItem +import com.prm.tasksboard.taskboards.entity.TaskItem class DatabaseHandler { private val db = Firebase.firestore private val loggedInUserId = FirebaseAuth.getInstance().currentUser?.uid ?: "" - fun addBoardItem(boardItem: BoardItem) { - // Firestore generates a unique ID for the new document + fun addBoardItem(boardItem: BoardItem, callback: (String) -> Unit) { val docRef = db.collection("boards").document() - boardItem.boardId = docRef.id // Assign the Firestore-generated ID to the boardItem + boardItem.boardId = docRef.id + boardItem.userId = loggedInUserId + boardItem.createdAt = Timestamp.now() // Set created_at to current time docRef.set(boardItem) .addOnSuccessListener { - Log.d("FirestoreAdd", "BoardItem successfully added with ID: ${docRef.id}") + callback(docRef.id) // Invoke the callback with the new board's ID } .addOnFailureListener { e -> - Log.w("FirestoreAdd", "Error adding BoardItem", e) + Log.w("DatabaseHandler", "Error adding BoardItem", e) } } fun getBoardItemsByUserId(): Task { return db.collection("boards") - .whereEqualTo("user_id", loggedInUserId).orderBy("created_at") + .whereEqualTo("user_id", loggedInUserId) + .orderBy("created_at") .get() .addOnSuccessListener { result -> for (document in result) { @@ -65,7 +69,7 @@ class DatabaseHandler { } fun checkFirestoreConnection() { - db.collection("boards") // Replace "known_collection" with your actual collection name + db.collection("boards") .whereEqualTo("user_id", loggedInUserId).limit(1) .get() .addOnSuccessListener { documents -> @@ -79,4 +83,33 @@ class DatabaseHandler { Log.w("FirestoreCheck", "Error connecting to Firestore: ", exception) } } -} + + fun addTaskItem(taskItem: TaskItem, boardId: String, callback: () -> Unit) { + val newTaskRef = db.collection("boards").document(boardId).collection("tasks").document() + taskItem.taskId = newTaskRef.id + taskItem.userId = loggedInUserId + taskItem.createdAt = Timestamp.now() // Set created_at to current time + + newTaskRef.set(taskItem) + .addOnSuccessListener { + Log.d("FirestoreAdd", "TaskItem successfully added with ID: ${taskItem.taskId}") + callback() + } + .addOnFailureListener { e -> + Log.w("FirestoreAdd", "Error adding TaskItem", e) + } + } + + fun getTasksByBoardId(boardId: String, callback: (List) -> Unit) { + db.collection("boards").document(boardId).collection("tasks") + .whereEqualTo("user_id", loggedInUserId) // Ensure tasks are for the logged-in user + .get() + .addOnSuccessListener { documents -> + val tasks = documents.toObjects(TaskItem::class.java) + callback(tasks) + } + .addOnFailureListener { exception -> + Log.w("DatabaseHandler", "Error getting tasks by board ID", exception) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt new file mode 100644 index 0000000..716db9b --- /dev/null +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt @@ -0,0 +1,35 @@ +package com.prm.tasksboard.taskboards.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.prm.tasksboard.R +import com.prm.tasksboard.taskboards.entity.TaskItem + +class TaskAdapter(private var tasks: List) : RecyclerView.Adapter() { + + class TaskViewHolder(view: View) : RecyclerView.ViewHolder(view) { + fun bind(task: TaskItem) { + itemView.findViewById(R.id.taskTitle).text = task.title + itemView.findViewById(R.id.taskDescription).text = task.description + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.task_item, parent, false) + return TaskViewHolder(view) + } + + override fun onBindViewHolder(holder: TaskViewHolder, position: Int) { + holder.bind(tasks[position]) + } + + override fun getItemCount() = tasks.size + + fun updateTasks(newTasks: List) { + tasks = newTasks + notifyDataSetChanged() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt index 1333d45..bcd98f9 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt @@ -8,6 +8,7 @@ import android.widget.Button import android.widget.EditText import android.widget.PopupMenu import android.widget.TextView +import android.widget.Toast import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat @@ -20,7 +21,12 @@ import com.google.firebase.Timestamp import com.google.firebase.auth.FirebaseAuth import com.prm.tasksboard.R import com.prm.tasksboard.taskboards.entity.BoardItem +import com.prm.tasksboard.taskboards.entity.TaskItem import com.prm.tasksboard.taskboards.firestore.DatabaseHandler +import java.util.UUID +import androidx.recyclerview.widget.RecyclerView +import com.prm.tasksboard.taskboards.adapter.TaskAdapter +import androidx.recyclerview.widget.LinearLayoutManager class TaskboardsActivity : AppCompatActivity() { private lateinit var viewPager: ViewPager2 @@ -67,7 +73,7 @@ class TaskboardsActivity : AppCompatActivity() { fetchAndDisplayBoards() addBoardButton.setOnClickListener { - createNewBoard() + showAddTaskDialog() // Correctly placed inside onCreate } menuButton.setOnClickListener { @@ -99,6 +105,17 @@ class TaskboardsActivity : AppCompatActivity() { } } + private fun countUserTasksAndShow() { + // Assuming the current board ID is needed to fetch tasks. Adjust if tasks are not board-specific. + val currentBoardId = boardList.getOrNull(viewPager.currentItem)?.boardId ?: return + dbHandler.getTasksByBoardId(currentBoardId) { tasks -> + val message = "This user currently has ${tasks.size} task(s)" + runOnUiThread { + Toast.makeText(this@TaskboardsActivity, message, Toast.LENGTH_LONG).show() + } + } + } + private fun setWindowInsetsListener() { ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) @@ -126,6 +143,76 @@ class TaskboardsActivity : AppCompatActivity() { emptyView.visibility = if (boardList.isEmpty()) View.VISIBLE else View.GONE } + private fun showAddTaskDialog() { + val builder = AlertDialog.Builder(this) + builder.setTitle("Add New Task") + + val input = EditText(this) + input.hint = "Enter task name" + builder.setView(input) + + builder.setPositiveButton("OK") { _, _ -> + val taskName = input.text.toString() + addNewTask(taskName) + } + builder.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() } + + builder.show() + } + + private fun addNewTask(taskName: String) { + if (boardList.isEmpty()) { + val newBoard = BoardItem( + createdAt = Timestamp.now(), + name = "Default Board", + updatedAt = Timestamp.now(), + userId = loggedInUserId + ) + // Asynchronously add the new board and get its ID + dbHandler.addBoardItem(newBoard) { newBoardId -> + boardList.add(newBoard.copy(boardId = newBoardId)) + setupTabLayoutWithViewPager() + updateEmptyViewVisibility() + addTaskToBoard(taskName, newBoardId, loggedInUserId) + } + } else { + val currentBoardId = boardList[viewPager.currentItem].boardId + addTaskToBoard(taskName, currentBoardId, loggedInUserId) + } + } + + private fun addTaskToBoard(taskName: String, boardId: String, userId: String) { + val newTask = TaskItem( + taskId = UUID.randomUUID().toString(), + boardId = boardId, + title = taskName, + description = "", + status = "Pending", + dueDate = "", + priority = "Normal", + userId = loggedInUserId // Assign the logged-in user's ID to the task + ) + dbHandler.addTaskItem(newTask, boardId) { + displayTasks(boardId) + } + } + + private fun displayTasks(boardId: String) { + // Fetch tasks associated with the boardId and current user ID + dbHandler.getTasksByBoardId(boardId) { tasks: List -> + // Check if the RecyclerView is already set up + val recyclerView = findViewById(R.id.tasksRecyclerView) + if (recyclerView.adapter == null) { + // If not, set up the RecyclerView with LinearLayoutManager and TaskAdapter + recyclerView.layoutManager = LinearLayoutManager(this@TaskboardsActivity) + recyclerView.adapter = TaskAdapter(tasks) + } else { + // If the RecyclerView is already set up, update the adapter's data + (recyclerView.adapter as TaskAdapter).updateTasks(tasks) + } + } + } + private fun createNewBoard() { // Create a new BoardItem val newBoard = BoardItem( @@ -137,7 +224,8 @@ class TaskboardsActivity : AppCompatActivity() { // Add it to your boardList boardList.add(newBoard) // Add it to Firestore - dbHandler.addBoardItem(newBoard) + dbHandler.addBoardItem(newBoard) { newBoardId -> + } if (boardList.size == 1) { // If this is the first board being added viewPager.adapter = boardPagerAdapter setupTabLayoutWithViewPager() // Re-setup TabLayout with ViewPager @@ -197,8 +285,18 @@ class TaskboardsActivity : AppCompatActivity() { // Notify adapter about the range of items inserted boardPagerAdapter.notifyItemRangeInserted(startPosition, newItems.size) setupTabLayoutWithViewPager() + // After setting up the ViewPager and TabLayout, fetch and display tasks for the current board + displayTasksForCurrentBoard() } updateEmptyViewVisibility() } } + + private fun displayTasksForCurrentBoard() { + // Ensure there's at least one board to fetch tasks for + if (boardList.isNotEmpty()) { + val currentBoardId = boardList[viewPager.currentItem].boardId + displayTasks(currentBoardId) + } + } } diff --git a/app/src/main/res/layout/activity_taskboards.xml b/app/src/main/res/layout/activity_taskboards.xml index df07478..334f0ad 100644 --- a/app/src/main/res/layout/activity_taskboards.xml +++ b/app/src/main/res/layout/activity_taskboards.xml @@ -54,4 +54,12 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/task_item.xml b/app/src/main/res/layout/task_item.xml new file mode 100644 index 0000000..a76f1d8 --- /dev/null +++ b/app/src/main/res/layout/task_item.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file From 9cb441b3c8e2d9f322f191cb0f1eba9c516fd78d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sat, 13 Jul 2024 19:52:36 +0700 Subject: [PATCH 05/35] fix add board button --- .../taskboards/firestore/DatabaseHandler.kt | 10 ++++++++ .../tasksboard/taskboards/view/TaskAdapter.kt | 24 ++++++++++++++----- .../taskboards/view/TaskboardsActivity.kt | 17 +++++++------ app/src/main/res/layout/board_item.xml | 1 + app/src/main/res/layout/task_item.xml | 24 +++++++++---------- 5 files changed, 51 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt b/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt index f9a8962..1294e3d 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt @@ -100,6 +100,16 @@ class DatabaseHandler { } } + fun deleteTaskItem(boardId: String, taskId: String, callback: () -> Unit) { + db.collection("boards").document(boardId).collection("tasks").document(taskId) + .delete() + .addOnSuccessListener { + Log.d("FirestoreDelete", "Task $taskId successfully deleted!") + callback() + } + .addOnFailureListener { e -> Log.w("FirestoreDelete", "Error deleting task", e) } + } + fun getTasksByBoardId(boardId: String, callback: (List) -> Unit) { db.collection("boards").document(boardId).collection("tasks") .whereEqualTo("user_id", loggedInUserId) // Ensure tasks are for the logged-in user diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt index 716db9b..b9bb40e 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt @@ -1,19 +1,31 @@ -package com.prm.tasksboard.taskboards.adapter +package com.prm.tasksboard.taskboards.view import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.CheckBox import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.prm.tasksboard.R import com.prm.tasksboard.taskboards.entity.TaskItem -class TaskAdapter(private var tasks: List) : RecyclerView.Adapter() { +class TaskAdapter(private var tasks: List, private val onTaskFinished: (TaskItem) -> Unit) : RecyclerView.Adapter() { class TaskViewHolder(view: View) : RecyclerView.ViewHolder(view) { - fun bind(task: TaskItem) { - itemView.findViewById(R.id.taskTitle).text = task.title - itemView.findViewById(R.id.taskDescription).text = task.description + fun bind(task: TaskItem, onTaskFinished: (TaskItem) -> Unit) { + val titleView = itemView.findViewById(R.id.taskTitle) + val checkBox = itemView.findViewById(R.id.taskCheckBox) + + titleView.text = task.title + checkBox.setOnCheckedChangeListener(null) // Clear previous listeners + checkBox.isChecked = task.status == "Finished" + checkBox.setOnCheckedChangeListener { _, isChecked -> + if (isChecked) { + // Update task status to "Finished" before deletion + task.status = "Finished" + onTaskFinished(task) + } + } } } @@ -23,7 +35,7 @@ class TaskAdapter(private var tasks: List) : RecyclerView.Adapter -> - // Check if the RecyclerView is already set up + // Sort tasks by createdAt timestamp or any other criteria if needed + val sortedTasks = tasks.sortedBy { it.createdAt } val recyclerView = findViewById(R.id.tasksRecyclerView) + val taskAdapter = TaskAdapter(sortedTasks) { task: TaskItem -> + dbHandler.deleteTaskItem(task.boardId, task.taskId) { + // Fetch and display tasks again to update the UI + displayTasks(boardId) + } + } if (recyclerView.adapter == null) { - // If not, set up the RecyclerView with LinearLayoutManager and TaskAdapter recyclerView.layoutManager = LinearLayoutManager(this@TaskboardsActivity) - recyclerView.adapter = TaskAdapter(tasks) + recyclerView.adapter = taskAdapter } else { - // If the RecyclerView is already set up, update the adapter's data - (recyclerView.adapter as TaskAdapter).updateTasks(tasks) + (recyclerView.adapter as TaskAdapter).updateTasks(sortedTasks) } } } diff --git a/app/src/main/res/layout/board_item.xml b/app/src/main/res/layout/board_item.xml index 86c1461..7c9c87f 100644 --- a/app/src/main/res/layout/board_item.xml +++ b/app/src/main/res/layout/board_item.xml @@ -4,6 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="8dp" + android:visibility="gone" app:cardCornerRadius="8dp"> - + app:layout_constraintBottom_toBottomOf="parent"/> + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintStart_toEndOf="@id/taskCheckBox" + app:layout_constraintTop_toTopOf="parent" + tools:text="Task Title" /> \ No newline at end of file From 3189410bf49fb45e65b8924ce4d239475b6b95cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sat, 13 Jul 2024 20:26:53 +0700 Subject: [PATCH 06/35] fix add board button to add to 1 board --- .../taskboards/view/TaskboardsActivity.kt | 58 ++++++++++++++----- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt index 81f8702..d26c7ed 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt @@ -8,7 +8,6 @@ import android.widget.Button import android.widget.EditText import android.widget.PopupMenu import android.widget.TextView -import android.widget.Toast import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat @@ -47,6 +46,19 @@ class TaskboardsActivity : AppCompatActivity() { tabLayoutMediator?.attach() } + private fun setupViewPagerAndTabs() { + // Assuming boardList is already populated + boardPagerAdapter = BoardPagerAdapter(boardList) + viewPager.adapter = boardPagerAdapter + + // Setup TabLayoutMediator after setting the adapter + tabLayoutMediator?.detach() // Detach existing TabLayoutMediator if any + tabLayoutMediator = TabLayoutMediator(tabLayout, viewPager) { tab, position -> + tab.text = boardList[position].name + } + tabLayoutMediator?.attach() + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() @@ -102,17 +114,17 @@ class TaskboardsActivity : AppCompatActivity() { } popupMenu.show() } + setupViewPagerPageChangeCallback() } - private fun countUserTasksAndShow() { - // Assuming the current board ID is needed to fetch tasks. Adjust if tasks are not board-specific. - val currentBoardId = boardList.getOrNull(viewPager.currentItem)?.boardId ?: return - dbHandler.getTasksByBoardId(currentBoardId) { tasks -> - val message = "This user currently has ${tasks.size} task(s)" - runOnUiThread { - Toast.makeText(this@TaskboardsActivity, message, Toast.LENGTH_LONG).show() + private fun setupViewPagerPageChangeCallback() { + viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + super.onPageSelected(position) + // Fetch and display tasks for the newly selected board + displayTasks(boardList[position].boardId) } - } + }) } private fun setWindowInsetsListener() { @@ -169,9 +181,15 @@ class TaskboardsActivity : AppCompatActivity() { ) // Asynchronously add the new board and get its ID dbHandler.addBoardItem(newBoard) { newBoardId -> - boardList.add(newBoard.copy(boardId = newBoardId)) + val updatedBoard = newBoard.copy(boardId = newBoardId) + boardList.add(updatedBoard) + // Update ViewPager adapter with the new board + viewPager.adapter = boardPagerAdapter + viewPager.adapter?.notifyDataSetChanged() + // Re-setup TabLayout with ViewPager after updating the adapter setupTabLayoutWithViewPager() updateEmptyViewVisibility() + // Now add the task to the newly created board addTaskToBoard(taskName, newBoardId, loggedInUserId) } } else { @@ -198,8 +216,10 @@ class TaskboardsActivity : AppCompatActivity() { private fun displayTasks(boardId: String) { dbHandler.getTasksByBoardId(boardId) { tasks: List -> + // Filter tasks to only include those that match the current board's ID + val filteredTasks = tasks.filter { it.boardId == boardId } // Sort tasks by createdAt timestamp or any other criteria if needed - val sortedTasks = tasks.sortedBy { it.createdAt } + val sortedTasks = filteredTasks.sortedBy { it.createdAt } val recyclerView = findViewById(R.id.tasksRecyclerView) val taskAdapter = TaskAdapter(sortedTasks) { task: TaskItem -> dbHandler.deleteTaskItem(task.boardId, task.taskId) { @@ -241,15 +261,16 @@ class TaskboardsActivity : AppCompatActivity() { private fun deleteBoard() { val currentItem = viewPager.currentItem // Delete the board from firestore - dbHandler.deleteBoardItem(boardList[viewPager.currentItem].boardId) + dbHandler.deleteBoardItem(boardList[currentItem].boardId) // Remove the board from your boardList - boardList.removeAt(viewPager.currentItem) + boardList.removeAt(currentItem) // Notify the adapter that the dataset has changed - boardPagerAdapter.notifyItemRemoved(viewPager.currentItem) + boardPagerAdapter.notifyItemRemoved(currentItem) if (boardList.isEmpty()) { viewPager.adapter = null tabLayoutMediator?.detach() // Detach TabLayoutMediator if no items are left tabLayoutMediator = null // Clear the TabLayoutMediator reference + clearAndHideTaskList() // Clear and hide the task list } else { boardPagerAdapter.notifyItemRemoved(currentItem) setupTabLayoutWithViewPager() // Re-setup TabLayout with ViewPager @@ -257,6 +278,14 @@ class TaskboardsActivity : AppCompatActivity() { updateEmptyViewVisibility() } + private fun clearAndHideTaskList() { + // Find the RecyclerView and clear its adapter + val recyclerView = findViewById(R.id.tasksRecyclerView) + recyclerView.adapter = null + // Optionally, update visibility or show a placeholder + emptyView.visibility = View.VISIBLE + } + private fun showRenameDialog(position: Int) { val builder = AlertDialog.Builder(this) builder.setTitle("Rename Board") @@ -291,6 +320,7 @@ class TaskboardsActivity : AppCompatActivity() { // After setting up the ViewPager and TabLayout, fetch and display tasks for the current board displayTasksForCurrentBoard() } + setupViewPagerAndTabs() updateEmptyViewVisibility() } } From 13e93092c9eceb6e675fd3155a6b4e8962984739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sat, 13 Jul 2024 22:44:55 +0700 Subject: [PATCH 07/35] misc --- .../com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt index d26c7ed..e778db7 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt @@ -274,6 +274,7 @@ class TaskboardsActivity : AppCompatActivity() { } else { boardPagerAdapter.notifyItemRemoved(currentItem) setupTabLayoutWithViewPager() // Re-setup TabLayout with ViewPager + displayTasksForCurrentBoard() } updateEmptyViewVisibility() } From 85718817157e5d52fa52370d32ccf1f9bb9a1bba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sat, 13 Jul 2024 23:05:59 +0700 Subject: [PATCH 08/35] added option for add task --- .../taskboards/view/TaskboardsActivity.kt | 41 ++++++++++++++++--- app/src/main/res/layout/dialog_add_task.xml | 40 ++++++++++++++++++ app/src/main/res/menu/priority_menu.xml | 11 +++++ 3 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 app/src/main/res/layout/dialog_add_task.xml create mode 100644 app/src/main/res/menu/priority_menu.xml diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt index e778db7..a30b933 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt @@ -25,6 +25,8 @@ import com.prm.tasksboard.taskboards.firestore.DatabaseHandler import java.util.UUID import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.LinearLayoutManager +import java.util.Calendar +import android.app.DatePickerDialog class TaskboardsActivity : AppCompatActivity() { private lateinit var viewPager: ViewPager2 @@ -155,16 +157,45 @@ class TaskboardsActivity : AppCompatActivity() { } private fun showAddTaskDialog() { + val dialogView = layoutInflater.inflate(R.layout.dialog_add_task, null) + val taskNameInput = dialogView.findViewById(R.id.taskNameInput) + val taskDescriptionInput = dialogView.findViewById(R.id.taskDescriptionInput) + val selectDueDate = dialogView.findViewById(R.id.selectDueDate) + val selectPriority = dialogView.findViewById(R.id.selectPriority) + val builder = AlertDialog.Builder(this) + builder.setView(dialogView) builder.setTitle("Add New Task") - val input = EditText(this) - input.hint = "Enter task name" - builder.setView(input) + selectDueDate.setOnClickListener { + val calendar = Calendar.getInstance() + val year = calendar.get(Calendar.YEAR) + val month = calendar.get(Calendar.MONTH) + val day = calendar.get(Calendar.DAY_OF_MONTH) + val datePickerDialog = DatePickerDialog(this, { _, year, monthOfYear, dayOfMonth -> + val dueDate = "$dayOfMonth/${monthOfYear + 1}/$year" + selectDueDate.text = dueDate + }, year, month, day) + datePickerDialog.datePicker.minDate = System.currentTimeMillis() - 1000 + datePickerDialog.show() + } + + selectPriority.setOnClickListener { + val popupMenu = PopupMenu(this, it) + popupMenu.menuInflater.inflate(R.menu.priority_menu, popupMenu.menu) + popupMenu.setOnMenuItemClickListener { menuItem -> + when (menuItem.itemId) { + R.id.high_priority -> selectPriority.text = "High" + R.id.medium_priority -> selectPriority.text = "Medium" + R.id.low_priority -> selectPriority.text = "Low" + } + true + } + popupMenu.show() + } builder.setPositiveButton("OK") { _, _ -> - val taskName = input.text.toString() - addNewTask(taskName) + // Handle the task addition here } builder.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() } diff --git a/app/src/main/res/layout/dialog_add_task.xml b/app/src/main/res/layout/dialog_add_task.xml new file mode 100644 index 0000000..720a6e2 --- /dev/null +++ b/app/src/main/res/layout/dialog_add_task.xml @@ -0,0 +1,40 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/priority_menu.xml b/app/src/main/res/menu/priority_menu.xml new file mode 100644 index 0000000..ee2b427 --- /dev/null +++ b/app/src/main/res/menu/priority_menu.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file From f78b52fb7307c6ec075f452caacfdc2ad1e0a121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sat, 13 Jul 2024 23:38:35 +0700 Subject: [PATCH 09/35] Revert "added option for add task" This reverts commit 85718817157e5d52fa52370d32ccf1f9bb9a1bba. --- .../taskboards/view/TaskboardsActivity.kt | 41 +++---------------- app/src/main/res/layout/dialog_add_task.xml | 40 ------------------ app/src/main/res/menu/priority_menu.xml | 11 ----- 3 files changed, 5 insertions(+), 87 deletions(-) delete mode 100644 app/src/main/res/layout/dialog_add_task.xml delete mode 100644 app/src/main/res/menu/priority_menu.xml diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt index a30b933..e778db7 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt @@ -25,8 +25,6 @@ import com.prm.tasksboard.taskboards.firestore.DatabaseHandler import java.util.UUID import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.LinearLayoutManager -import java.util.Calendar -import android.app.DatePickerDialog class TaskboardsActivity : AppCompatActivity() { private lateinit var viewPager: ViewPager2 @@ -157,45 +155,16 @@ class TaskboardsActivity : AppCompatActivity() { } private fun showAddTaskDialog() { - val dialogView = layoutInflater.inflate(R.layout.dialog_add_task, null) - val taskNameInput = dialogView.findViewById(R.id.taskNameInput) - val taskDescriptionInput = dialogView.findViewById(R.id.taskDescriptionInput) - val selectDueDate = dialogView.findViewById(R.id.selectDueDate) - val selectPriority = dialogView.findViewById(R.id.selectPriority) - val builder = AlertDialog.Builder(this) - builder.setView(dialogView) builder.setTitle("Add New Task") - selectDueDate.setOnClickListener { - val calendar = Calendar.getInstance() - val year = calendar.get(Calendar.YEAR) - val month = calendar.get(Calendar.MONTH) - val day = calendar.get(Calendar.DAY_OF_MONTH) - val datePickerDialog = DatePickerDialog(this, { _, year, monthOfYear, dayOfMonth -> - val dueDate = "$dayOfMonth/${monthOfYear + 1}/$year" - selectDueDate.text = dueDate - }, year, month, day) - datePickerDialog.datePicker.minDate = System.currentTimeMillis() - 1000 - datePickerDialog.show() - } - - selectPriority.setOnClickListener { - val popupMenu = PopupMenu(this, it) - popupMenu.menuInflater.inflate(R.menu.priority_menu, popupMenu.menu) - popupMenu.setOnMenuItemClickListener { menuItem -> - when (menuItem.itemId) { - R.id.high_priority -> selectPriority.text = "High" - R.id.medium_priority -> selectPriority.text = "Medium" - R.id.low_priority -> selectPriority.text = "Low" - } - true - } - popupMenu.show() - } + val input = EditText(this) + input.hint = "Enter task name" + builder.setView(input) builder.setPositiveButton("OK") { _, _ -> - // Handle the task addition here + val taskName = input.text.toString() + addNewTask(taskName) } builder.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() } diff --git a/app/src/main/res/layout/dialog_add_task.xml b/app/src/main/res/layout/dialog_add_task.xml deleted file mode 100644 index 720a6e2..0000000 --- a/app/src/main/res/layout/dialog_add_task.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/priority_menu.xml b/app/src/main/res/menu/priority_menu.xml deleted file mode 100644 index ee2b427..0000000 --- a/app/src/main/res/menu/priority_menu.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - \ No newline at end of file From 050bd3ced66f55a97dbf9d92991ea47b1d15987f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sat, 13 Jul 2024 23:51:43 +0700 Subject: [PATCH 10/35] add desc when adding task --- .../taskboards/view/TaskboardsActivity.kt | 22 ++++++++++--------- app/src/main/res/layout/dialog_add_task.xml | 21 ++++++++++++++++++ 2 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 app/src/main/res/layout/dialog_add_task.xml diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt index e778db7..c359197 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt @@ -158,20 +158,22 @@ class TaskboardsActivity : AppCompatActivity() { val builder = AlertDialog.Builder(this) builder.setTitle("Add New Task") - val input = EditText(this) - input.hint = "Enter task name" - builder.setView(input) + val view = layoutInflater.inflate(R.layout.dialog_add_task, null) + val taskNameInput = view.findViewById(R.id.taskNameInput) + val taskDescriptionInput = view.findViewById(R.id.taskDescriptionInput) + builder.setView(view) builder.setPositiveButton("OK") { _, _ -> - val taskName = input.text.toString() - addNewTask(taskName) + val taskName = taskNameInput.text.toString() + val taskDescription = taskDescriptionInput.text.toString() + addNewTask(taskName, taskDescription) } builder.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() } builder.show() } - private fun addNewTask(taskName: String) { + private fun addNewTask(taskName: String, taskDescription: String) { if (boardList.isEmpty()) { val newBoard = BoardItem( createdAt = Timestamp.now(), @@ -190,20 +192,20 @@ class TaskboardsActivity : AppCompatActivity() { setupTabLayoutWithViewPager() updateEmptyViewVisibility() // Now add the task to the newly created board - addTaskToBoard(taskName, newBoardId, loggedInUserId) + addTaskToBoard(taskName, newBoardId, loggedInUserId, taskDescription) } } else { val currentBoardId = boardList[viewPager.currentItem].boardId - addTaskToBoard(taskName, currentBoardId, loggedInUserId) + addTaskToBoard(taskName, currentBoardId, loggedInUserId, taskDescription) } } - private fun addTaskToBoard(taskName: String, boardId: String, userId: String) { + private fun addTaskToBoard(taskName: String, boardId: String, userId: String, description: String) { val newTask = TaskItem( taskId = UUID.randomUUID().toString(), boardId = boardId, title = taskName, - description = "", + description = description, // Now correctly references the parameter status = "Pending", dueDate = "", priority = "Normal", diff --git a/app/src/main/res/layout/dialog_add_task.xml b/app/src/main/res/layout/dialog_add_task.xml new file mode 100644 index 0000000..0062d65 --- /dev/null +++ b/app/src/main/res/layout/dialog_add_task.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file From a8d271346cdf3e575af4f450100356ba30cbada4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sun, 14 Jul 2024 00:00:37 +0700 Subject: [PATCH 11/35] add due date when adding task --- .../taskboards/view/TaskboardsActivity.kt | 26 +++++++++++++++++++ app/src/main/res/layout/dialog_add_task.xml | 10 +++++++ 2 files changed, 36 insertions(+) diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt index c359197..0422102 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt @@ -1,6 +1,7 @@ package com.prm.tasksboard.taskboards.view import android.app.AlertDialog +import android.app.DatePickerDialog import android.os.Bundle import android.view.View import android.view.ViewGroup @@ -25,6 +26,9 @@ import com.prm.tasksboard.taskboards.firestore.DatabaseHandler import java.util.UUID import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.LinearLayoutManager +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale class TaskboardsActivity : AppCompatActivity() { private lateinit var viewPager: ViewPager2 @@ -161,6 +165,28 @@ class TaskboardsActivity : AppCompatActivity() { val view = layoutInflater.inflate(R.layout.dialog_add_task, null) val taskNameInput = view.findViewById(R.id.taskNameInput) val taskDescriptionInput = view.findViewById(R.id.taskDescriptionInput) + val dueDateTextView = view.findViewById(R.id.dueDateTextView) + + var selectedDueDate = "" + + dueDateTextView.setOnClickListener { + val calendar = Calendar.getInstance() + val year = calendar.get(Calendar.YEAR) + val month = calendar.get(Calendar.MONTH) + val day = calendar.get(Calendar.DAY_OF_MONTH) + val datePickerDialog = DatePickerDialog(this, { _, year, monthOfYear, dayOfMonth -> + // Format the selected date and display it on the TextView + val selectedDate = Calendar.getInstance() + selectedDate.set(year, monthOfYear, dayOfMonth) + val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) + selectedDueDate = dateFormat.format(selectedDate.time) + dueDateTextView.text = selectedDueDate + }, year, month, day) + + datePickerDialog.datePicker.minDate = System.currentTimeMillis() - 1000 // Disallow past dates + datePickerDialog.show() + } + builder.setView(view) builder.setPositiveButton("OK") { _, _ -> diff --git a/app/src/main/res/layout/dialog_add_task.xml b/app/src/main/res/layout/dialog_add_task.xml index 0062d65..225d5b8 100644 --- a/app/src/main/res/layout/dialog_add_task.xml +++ b/app/src/main/res/layout/dialog_add_task.xml @@ -18,4 +18,14 @@ android:hint="Enter task description" android:inputType="textMultiLine" /> + + \ No newline at end of file From 0f390ed0c8e7ca413d3016a695b0d80970042725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sun, 14 Jul 2024 00:05:16 +0700 Subject: [PATCH 12/35] add priority when adding task --- .../taskboards/view/TaskboardsActivity.kt | 15 +++++++++++++++ app/src/main/res/layout/dialog_add_task.xml | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt index 0422102..671fd89 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt @@ -166,8 +166,10 @@ class TaskboardsActivity : AppCompatActivity() { val taskNameInput = view.findViewById(R.id.taskNameInput) val taskDescriptionInput = view.findViewById(R.id.taskDescriptionInput) val dueDateTextView = view.findViewById(R.id.dueDateTextView) + val priorityTextView = view.findViewById(R.id.priorityTextView) var selectedDueDate = "" + var selectedPriority = "" dueDateTextView.setOnClickListener { val calendar = Calendar.getInstance() @@ -187,6 +189,19 @@ class TaskboardsActivity : AppCompatActivity() { datePickerDialog.show() } + priorityTextView.setOnClickListener { + val popupMenu = PopupMenu(this, priorityTextView) + popupMenu.menu.add("High") + popupMenu.menu.add("Medium") + popupMenu.menu.add("Low") + popupMenu.setOnMenuItemClickListener { item -> + selectedPriority = item.title.toString() + priorityTextView.text = selectedPriority + true + } + popupMenu.show() + } + builder.setView(view) builder.setPositiveButton("OK") { _, _ -> diff --git a/app/src/main/res/layout/dialog_add_task.xml b/app/src/main/res/layout/dialog_add_task.xml index 225d5b8..f7234e1 100644 --- a/app/src/main/res/layout/dialog_add_task.xml +++ b/app/src/main/res/layout/dialog_add_task.xml @@ -28,4 +28,14 @@ android:clickable="true" android:focusable="true" /> + + \ No newline at end of file From ee619572f1a7d24e9f70a8392303d47d612fb116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sun, 14 Jul 2024 00:33:40 +0700 Subject: [PATCH 13/35] add task details activity --- app/build.gradle.kts | 4 +++ app/src/main/AndroidManifest.xml | 1 + .../tasksboard/taskboards/view/TaskAdapter.kt | 15 +++++++-- .../taskboards/view/TaskDetailsActivity.kt | 27 ++++++++++++++++ .../main/res/layout/activity_task_detail.xml | 32 +++++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/prm/tasksboard/taskboards/view/TaskDetailsActivity.kt create mode 100644 app/src/main/res/layout/activity_task_detail.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8862093..3bb7360 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -18,6 +18,10 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } + buildFeatures { + viewBinding = true + } + buildTypes { release { isMinifyEnabled = false diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8eb8ef0..2d8aeb1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -28,6 +28,7 @@ + \ No newline at end of file diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt index b9bb40e..4c082d1 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt @@ -1,5 +1,6 @@ package com.prm.tasksboard.taskboards.view +import android.content.Intent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -12,7 +13,7 @@ import com.prm.tasksboard.taskboards.entity.TaskItem class TaskAdapter(private var tasks: List, private val onTaskFinished: (TaskItem) -> Unit) : RecyclerView.Adapter() { class TaskViewHolder(view: View) : RecyclerView.ViewHolder(view) { - fun bind(task: TaskItem, onTaskFinished: (TaskItem) -> Unit) { + fun bind(task: TaskItem, onTaskFinished: (TaskItem) -> Unit, context: android.content.Context) { val titleView = itemView.findViewById(R.id.taskTitle) val checkBox = itemView.findViewById(R.id.taskCheckBox) @@ -26,6 +27,16 @@ class TaskAdapter(private var tasks: List, private val onTaskFinished: onTaskFinished(task) } } + + itemView.setOnClickListener { + val intent = Intent(context, TaskDetailActivity::class.java).apply { + putExtra("taskName", task.title) + putExtra("taskDescription", task.description) + putExtra("taskDueDate", task.dueDate) + putExtra("taskPriority", task.priority) + } + context.startActivity(intent) + } } } @@ -35,7 +46,7 @@ class TaskAdapter(private var tasks: List, private val onTaskFinished: } override fun onBindViewHolder(holder: TaskViewHolder, position: Int) { - holder.bind(tasks[position], onTaskFinished) + holder.bind(tasks[position], onTaskFinished, holder.itemView.context) } override fun getItemCount() = tasks.size diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskDetailsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskDetailsActivity.kt new file mode 100644 index 0000000..a84b9be --- /dev/null +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskDetailsActivity.kt @@ -0,0 +1,27 @@ +package com.prm.tasksboard.taskboards.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.prm.tasksboard.databinding.ActivityTaskDetailBinding + +class TaskDetailActivity : AppCompatActivity() { + private lateinit var binding: ActivityTaskDetailBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityTaskDetailBinding.inflate(layoutInflater) + setContentView(binding.root) + + // Retrieve task details passed from the previous Activity + val taskName = intent.getStringExtra("taskName") + val taskDescription = intent.getStringExtra("taskDescription") + val taskDueDate = intent.getStringExtra("taskDueDate") + val taskPriority = intent.getStringExtra("taskPriority") + + // Set the task details to TextViews + binding.taskNameTextView.text = taskName + binding.taskDescriptionTextView.text = taskDescription + binding.taskDueDateTextView.text = taskDueDate + binding.taskPriorityTextView.text = taskPriority + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_task_detail.xml b/app/src/main/res/layout/activity_task_detail.xml new file mode 100644 index 0000000..be7ebe4 --- /dev/null +++ b/app/src/main/res/layout/activity_task_detail.xml @@ -0,0 +1,32 @@ + + + + + + + + + + \ No newline at end of file From d022fccb2a7477966661bdb5f8c8fa076241c3c8 Mon Sep 17 00:00:00 2001 From: niqqerlaptop Date: Sun, 14 Jul 2024 09:45:50 +0700 Subject: [PATCH 14/35] Edited entities to reflect fields in firestore db (removing redundant fields). Removed pressing the check box deletes the task. --- .../tasksboard/taskboards/entity/TaskItem.kt | 12 +- .../taskboards/firestore/DatabaseHandler.kt | 21 +- .../taskboards/view/BoardAdapter.kt | 27 --- .../taskboards/view/TaskboardsActivity.kt | 217 +++++++++--------- app/src/main/res/layout/board_item.xml | 6 +- 5 files changed, 133 insertions(+), 150 deletions(-) delete mode 100644 app/src/main/java/com/prm/tasksboard/taskboards/view/BoardAdapter.kt diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt b/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt index eaad2ae..d7b9a73 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/entity/TaskItem.kt @@ -4,13 +4,13 @@ import com.google.firebase.Timestamp import com.google.firebase.firestore.PropertyName data class TaskItem( - @get:PropertyName("task_id") @set:PropertyName("task_id") var taskId: String = "", + var taskId: String = "", @get:PropertyName("title") @set:PropertyName("title") var title: String = "", @get:PropertyName("description") @set:PropertyName("description") var description: String = "", @get:PropertyName("status") @set:PropertyName("status") var status: String = "", - @get:PropertyName("due_date") @set:PropertyName("due_date") var dueDate: String = "", + @get:PropertyName("due_date") @set:PropertyName("due_date") var dueDate: Timestamp, @get:PropertyName("priority") @set:PropertyName("priority") var priority: String = "", - @get:PropertyName("created_at") @set:PropertyName("created_at") var createdAt: Timestamp? = null, - @get:PropertyName("user_id") @set:PropertyName("user_id") var userId: String = "", - @get:PropertyName("board_id") @set:PropertyName("board_id") var boardId: String = "" // Add this field -) \ No newline at end of file + @get:PropertyName("created_at") @set:PropertyName("created_at") var createdAt: Timestamp, +) { + constructor() : this("", "", "", "", Timestamp.now(), "", Timestamp.now()) +} \ No newline at end of file diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt b/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt index 1294e3d..6789a5f 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/firestore/DatabaseHandler.kt @@ -87,9 +87,6 @@ class DatabaseHandler { fun addTaskItem(taskItem: TaskItem, boardId: String, callback: () -> Unit) { val newTaskRef = db.collection("boards").document(boardId).collection("tasks").document() taskItem.taskId = newTaskRef.id - taskItem.userId = loggedInUserId - taskItem.createdAt = Timestamp.now() // Set created_at to current time - newTaskRef.set(taskItem) .addOnSuccessListener { Log.d("FirestoreAdd", "TaskItem successfully added with ID: ${taskItem.taskId}") @@ -112,7 +109,6 @@ class DatabaseHandler { fun getTasksByBoardId(boardId: String, callback: (List) -> Unit) { db.collection("boards").document(boardId).collection("tasks") - .whereEqualTo("user_id", loggedInUserId) // Ensure tasks are for the logged-in user .get() .addOnSuccessListener { documents -> val tasks = documents.toObjects(TaskItem::class.java) @@ -122,4 +118,21 @@ class DatabaseHandler { Log.w("DatabaseHandler", "Error getting tasks by board ID", exception) } } + + fun updateTaskItem( + boardId: String, + taskId: String, + updatedFields: Map, + callback: () -> Unit + ) { + db.collection("boards").document(boardId).collection("tasks").document(taskId) + .update(updatedFields) + .addOnSuccessListener { + Log.d("FirestoreUpdate", "Task $taskId successfully updated!") + callback() + } + .addOnFailureListener { e -> + Log.w("FirestoreUpdate", "Error updating task", e) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/BoardAdapter.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/BoardAdapter.kt deleted file mode 100644 index c67c6ba..0000000 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/BoardAdapter.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.prm.tasksboard.taskboards.view - -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import com.prm.tasksboard.R -import com.prm.tasksboard.taskboards.entity.BoardItem - -class BoardAdapter(private val boardList: List) : - RecyclerView.Adapter() { - - class BoardViewHolder(view: View) : RecyclerView.ViewHolder(view) { - - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BoardViewHolder { - val view = LayoutInflater.from(parent.context).inflate(R.layout.board_item, parent, false) - return BoardViewHolder(view) - } - - override fun onBindViewHolder(holder: BoardViewHolder, position: Int) { - - } - - override fun getItemCount() = boardList.size -} diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt index 671fd89..e68d2ba 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskboardsActivity.kt @@ -13,6 +13,8 @@ import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.button.MaterialButton import com.google.android.material.tabs.TabLayout @@ -23,9 +25,6 @@ import com.prm.tasksboard.R import com.prm.tasksboard.taskboards.entity.BoardItem import com.prm.tasksboard.taskboards.entity.TaskItem import com.prm.tasksboard.taskboards.firestore.DatabaseHandler -import java.util.UUID -import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.LinearLayoutManager import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale @@ -158,6 +157,98 @@ class TaskboardsActivity : AppCompatActivity() { emptyView.visibility = if (boardList.isEmpty()) View.VISIBLE else View.GONE } + private fun createNewBoard() { + // Create a new BoardItem + val newBoard = BoardItem( + createdAt = Timestamp.now(), + name = "New Board #${boardList.size + 1}", + updatedAt = Timestamp.now(), + userId = loggedInUserId, + ) + // Add it to your boardList + boardList.add(newBoard) + // Add it to Firestore + dbHandler.addBoardItem(newBoard) { newBoardId -> + boardList[boardList.size - 1].boardId = newBoardId + } + if (boardList.size == 1) { // If this is the first board being added + viewPager.adapter = boardPagerAdapter + setupTabLayoutWithViewPager() // Re-setup TabLayout with ViewPager + } else { + boardPagerAdapter.notifyItemInserted(boardList.size - 1) + } + updateEmptyViewVisibility() + } + + private fun deleteBoard() { + val currentItem = viewPager.currentItem + // Delete the board from firestore + dbHandler.deleteBoardItem(boardList[currentItem].boardId) + // Remove the board from your boardList + boardList.removeAt(currentItem) + // Notify the adapter that the dataset has changed + boardPagerAdapter.notifyItemRemoved(currentItem) + if (boardList.isEmpty()) { + viewPager.adapter = null + tabLayoutMediator?.detach() // Detach TabLayoutMediator if no items are left + tabLayoutMediator = null // Clear the TabLayoutMediator reference + clearAndHideTaskList() // Clear and hide the task list + } else { + boardPagerAdapter.notifyItemRemoved(currentItem) + setupTabLayoutWithViewPager() // Re-setup TabLayout with ViewPager + displayTasksForCurrentBoard() + } + updateEmptyViewVisibility() + } + + private fun clearAndHideTaskList() { + // Find the RecyclerView and clear its adapter + val recyclerView = findViewById(R.id.tasksRecyclerView) + recyclerView.adapter = null + // Optionally, update visibility or show a placeholder + emptyView.visibility = View.VISIBLE + } + + private fun showRenameDialog(position: Int) { + val builder = AlertDialog.Builder(this) + builder.setTitle("Rename Board") + + val input = EditText(this) + input.setText(boardList[position].name) + builder.setView(input) + + builder.setPositiveButton("OK") { _, _ -> + val newName = input.text.toString() + boardList[position].name = newName + tabLayout.getTabAt(position)?.text = newName + boardPagerAdapter.notifyItemChanged(position) + } + builder.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() } + + builder.show() + } + + private fun fetchAndDisplayBoards() { + dbHandler.getBoardItemsByUserId().addOnSuccessListener { result -> + val startPosition = boardList.size // Track start position before adding new items + boardList.clear() // Optional: Clear existing items if refreshing the entire list + val newItems = result.map { document -> + document.toObject(BoardItem::class.java) + } + .sortedBy { it.createdAt } // Sort by createdAt timestamp or change it to another attribute like name + boardList.addAll(newItems) + if (boardList.isNotEmpty()) { + // Notify adapter about the range of items inserted + boardPagerAdapter.notifyItemRangeInserted(startPosition, newItems.size) + setupTabLayoutWithViewPager() + // After setting up the ViewPager and TabLayout, fetch and display tasks for the current board + displayTasksForCurrentBoard() + } + setupViewPagerAndTabs() + updateEmptyViewVisibility() + } + } + private fun showAddTaskDialog() { val builder = AlertDialog.Builder(this) builder.setTitle("Add New Task") @@ -218,9 +309,9 @@ class TaskboardsActivity : AppCompatActivity() { if (boardList.isEmpty()) { val newBoard = BoardItem( createdAt = Timestamp.now(), - name = "Default Board", + name = "New Board #${boardList.size + 1}", updatedAt = Timestamp.now(), - userId = loggedInUserId + userId = loggedInUserId, ) // Asynchronously add the new board and get its ID dbHandler.addBoardItem(newBoard) { newBoardId -> @@ -228,29 +319,29 @@ class TaskboardsActivity : AppCompatActivity() { boardList.add(updatedBoard) // Update ViewPager adapter with the new board viewPager.adapter = boardPagerAdapter - viewPager.adapter?.notifyDataSetChanged() + viewPager.adapter?.notifyItemInserted(boardList.size - 1) // Re-setup TabLayout with ViewPager after updating the adapter setupTabLayoutWithViewPager() updateEmptyViewVisibility() // Now add the task to the newly created board - addTaskToBoard(taskName, newBoardId, loggedInUserId, taskDescription) + addTaskToBoard(taskName, newBoardId, taskDescription) } } else { val currentBoardId = boardList[viewPager.currentItem].boardId - addTaskToBoard(taskName, currentBoardId, loggedInUserId, taskDescription) + addTaskToBoard(taskName, currentBoardId, taskDescription) } } - private fun addTaskToBoard(taskName: String, boardId: String, userId: String, description: String) { + private fun addTaskToBoard(taskName: String, boardId: String, description: String) { val newTask = TaskItem( - taskId = UUID.randomUUID().toString(), - boardId = boardId, title = taskName, description = description, // Now correctly references the parameter status = "Pending", - dueDate = "", + dueDate = Timestamp( + Calendar.getInstance().apply { add(Calendar.DAY_OF_MONTH, 1) }.time + ), // Due date is set to tomorrow priority = "Normal", - userId = loggedInUserId // Assign the logged-in user's ID to the task + createdAt = Timestamp.now(), ) dbHandler.addTaskItem(newTask, boardId) { displayTasks(boardId) @@ -259,16 +350,10 @@ class TaskboardsActivity : AppCompatActivity() { private fun displayTasks(boardId: String) { dbHandler.getTasksByBoardId(boardId) { tasks: List -> - // Filter tasks to only include those that match the current board's ID - val filteredTasks = tasks.filter { it.boardId == boardId } // Sort tasks by createdAt timestamp or any other criteria if needed - val sortedTasks = filteredTasks.sortedBy { it.createdAt } + val sortedTasks = tasks.sortedBy { it.createdAt } val recyclerView = findViewById(R.id.tasksRecyclerView) - val taskAdapter = TaskAdapter(sortedTasks) { task: TaskItem -> - dbHandler.deleteTaskItem(task.boardId, task.taskId) { - // Fetch and display tasks again to update the UI - displayTasks(boardId) - } + val taskAdapter = TaskAdapter(sortedTasks) { _: TaskItem -> } if (recyclerView.adapter == null) { recyclerView.layoutManager = LinearLayoutManager(this@TaskboardsActivity) @@ -279,96 +364,6 @@ class TaskboardsActivity : AppCompatActivity() { } } - private fun createNewBoard() { - // Create a new BoardItem - val newBoard = BoardItem( - createdAt = Timestamp.now(), - name = "New Board #${boardList.size + 1}", - updatedAt = Timestamp.now(), - userId = loggedInUserId, - ) - // Add it to your boardList - boardList.add(newBoard) - // Add it to Firestore - dbHandler.addBoardItem(newBoard) { newBoardId -> - } - if (boardList.size == 1) { // If this is the first board being added - viewPager.adapter = boardPagerAdapter - setupTabLayoutWithViewPager() // Re-setup TabLayout with ViewPager - } else { - boardPagerAdapter.notifyItemInserted(boardList.size - 1) - } - updateEmptyViewVisibility() - } - - private fun deleteBoard() { - val currentItem = viewPager.currentItem - // Delete the board from firestore - dbHandler.deleteBoardItem(boardList[currentItem].boardId) - // Remove the board from your boardList - boardList.removeAt(currentItem) - // Notify the adapter that the dataset has changed - boardPagerAdapter.notifyItemRemoved(currentItem) - if (boardList.isEmpty()) { - viewPager.adapter = null - tabLayoutMediator?.detach() // Detach TabLayoutMediator if no items are left - tabLayoutMediator = null // Clear the TabLayoutMediator reference - clearAndHideTaskList() // Clear and hide the task list - } else { - boardPagerAdapter.notifyItemRemoved(currentItem) - setupTabLayoutWithViewPager() // Re-setup TabLayout with ViewPager - displayTasksForCurrentBoard() - } - updateEmptyViewVisibility() - } - - private fun clearAndHideTaskList() { - // Find the RecyclerView and clear its adapter - val recyclerView = findViewById(R.id.tasksRecyclerView) - recyclerView.adapter = null - // Optionally, update visibility or show a placeholder - emptyView.visibility = View.VISIBLE - } - - private fun showRenameDialog(position: Int) { - val builder = AlertDialog.Builder(this) - builder.setTitle("Rename Board") - - val input = EditText(this) - input.setText(boardList[position].name) - builder.setView(input) - - builder.setPositiveButton("OK") { _, _ -> - val newName = input.text.toString() - boardList[position].name = newName - tabLayout.getTabAt(position)?.text = newName - boardPagerAdapter.notifyItemChanged(position) - } - builder.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() } - - builder.show() - } - - private fun fetchAndDisplayBoards() { - dbHandler.getBoardItemsByUserId().addOnSuccessListener { result -> - val startPosition = boardList.size // Track start position before adding new items - boardList.clear() // Optional: Clear existing items if refreshing the entire list - val newItems = result.map { document -> - document.toObject(BoardItem::class.java) - } - boardList.addAll(newItems) - if (boardList.isNotEmpty()) { - // Notify adapter about the range of items inserted - boardPagerAdapter.notifyItemRangeInserted(startPosition, newItems.size) - setupTabLayoutWithViewPager() - // After setting up the ViewPager and TabLayout, fetch and display tasks for the current board - displayTasksForCurrentBoard() - } - setupViewPagerAndTabs() - updateEmptyViewVisibility() - } - } - private fun displayTasksForCurrentBoard() { // Ensure there's at least one board to fetch tasks for if (boardList.isNotEmpty()) { diff --git a/app/src/main/res/layout/board_item.xml b/app/src/main/res/layout/board_item.xml index 7c9c87f..a251437 100644 --- a/app/src/main/res/layout/board_item.xml +++ b/app/src/main/res/layout/board_item.xml @@ -1,11 +1,13 @@ + android:visibility="visible" + app:cardCornerRadius="8dp" + tools:visibility="visible"> Date: Sun, 14 Jul 2024 14:58:09 +0700 Subject: [PATCH 15/35] Update board_item.xml --- app/src/main/res/layout/board_item.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/board_item.xml b/app/src/main/res/layout/board_item.xml index a251437..1a7ab3c 100644 --- a/app/src/main/res/layout/board_item.xml +++ b/app/src/main/res/layout/board_item.xml @@ -5,7 +5,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="8dp" - android:visibility="visible" + android:visibility="gone" app:cardCornerRadius="8dp" tools:visibility="visible"> From 85a6a91f1a52b95b27fa6bd74da7e9c6ec1a0b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20=C4=90=C3=ACnh=20Kh=C3=B4i?= Date: Sun, 14 Jul 2024 16:16:28 +0700 Subject: [PATCH 16/35] change task item to cardView --- .../tasksboard/taskboards/view/TaskAdapter.kt | 27 +++--- app/src/main/res/drawable/ic_arrow_down.xml | 9 ++ app/src/main/res/drawable/ic_arrow_right.xml | 10 ++ .../main/res/layout/activity_task_detail.xml | 62 ++++++++----- app/src/main/res/layout/task_item.xml | 91 ++++++++++++++----- app/src/main/res/values-night/colors.xml | 3 + app/src/main/res/values/colors.xml | 1 + 7 files changed, 141 insertions(+), 62 deletions(-) create mode 100644 app/src/main/res/drawable/ic_arrow_down.xml create mode 100644 app/src/main/res/drawable/ic_arrow_right.xml create mode 100644 app/src/main/res/values-night/colors.xml diff --git a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt index 4c082d1..e317db4 100644 --- a/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt +++ b/app/src/main/java/com/prm/tasksboard/taskboards/view/TaskAdapter.kt @@ -4,7 +4,8 @@ import android.content.Intent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.CheckBox +import android.widget.ImageView +import android.widget.LinearLayout import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.prm.tasksboard.R @@ -14,19 +15,11 @@ class TaskAdapter(private var tasks: List, private val onTaskFinished: class TaskViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind(task: TaskItem, onTaskFinished: (TaskItem) -> Unit, context: android.content.Context) { - val titleView = itemView.findViewById(R.id.taskTitle) - val checkBox = itemView.findViewById(R.id.taskCheckBox) + val titleView = itemView.findViewById(R.id.taskSummaryTextView) + val expandArrowImageView = itemView.findViewById(R.id.expandArrowImageView) + val taskDetailsLayout = itemView.findViewById(R.id.taskDetailsLayout) titleView.text = task.title - checkBox.setOnCheckedChangeListener(null) // Clear previous listeners - checkBox.isChecked = task.status == "Finished" - checkBox.setOnCheckedChangeListener { _, isChecked -> - if (isChecked) { - // Update task status to "Finished" before deletion - task.status = "Finished" - onTaskFinished(task) - } - } itemView.setOnClickListener { val intent = Intent(context, TaskDetailActivity::class.java).apply { @@ -37,6 +30,16 @@ class TaskAdapter(private var tasks: List, private val onTaskFinished: } context.startActivity(intent) } + + expandArrowImageView.setOnClickListener { + if (taskDetailsLayout.visibility == View.GONE) { + taskDetailsLayout.visibility = View.VISIBLE + expandArrowImageView.setImageResource(R.drawable.ic_arrow_down) + } else { + taskDetailsLayout.visibility = View.GONE + expandArrowImageView.setImageResource(R.drawable.ic_arrow_right) + } + } } } diff --git a/app/src/main/res/drawable/ic_arrow_down.xml b/app/src/main/res/drawable/ic_arrow_down.xml new file mode 100644 index 0000000..829a681 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_down.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_arrow_right.xml b/app/src/main/res/drawable/ic_arrow_right.xml new file mode 100644 index 0000000..e0fbdde --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_right.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_task_detail.xml b/app/src/main/res/layout/activity_task_detail.xml index be7ebe4..abd5ec2 100644 --- a/app/src/main/res/layout/activity_task_detail.xml +++ b/app/src/main/res/layout/activity_task_detail.xml @@ -1,32 +1,44 @@ - + android:layout_height="match_parent"> - + android:layout_height="match_parent" + android:orientation="vertical" + android:padding="16dp"> - + - + - + + + + +