diff --git a/.idea/misc.xml b/.idea/misc.xml index e5021065b96bbcdfd50bfa808fd8ff3223695964..b46548a11b5bbd1305215630066b0323f7ab0337 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ -<?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK"> diff --git a/app/src/main/java/com/example/taskmanagement/auth/ProfileFragment.kt b/app/src/main/java/com/example/taskmanagement/auth/ProfileFragment.kt index 76bbde046c27450e0d432fd90ebc987349630a63..bc08714d676c5bbc07e78fbab253f4f4dd5e7537 100644 --- a/app/src/main/java/com/example/taskmanagement/auth/ProfileFragment.kt +++ b/app/src/main/java/com/example/taskmanagement/auth/ProfileFragment.kt @@ -26,7 +26,6 @@ import com.example.taskmanagement.task.HomeFragment import com.google.firebase.auth.FirebaseAuth import com.google.firebase.firestore.DocumentSnapshot import com.google.firebase.firestore.FirebaseFirestore -import com.google.firebase.firestore.QuerySnapshot import java.io.File import java.io.FileOutputStream import java.io.IOException @@ -82,9 +81,14 @@ class ProfileFragment : Fragment() { binding.assignedTasksList.adapter = taskAdapter binding.assignedTasksList.isNestedScrollingEnabled = true - loadUserData() loadProfileImage() + setupListeners() + loadUserDataByRole() + return binding.root + } + + private fun setupListeners() { binding.buttonEditProfile.setOnClickListener { findNavController().navigate(R.id.action_profileFragment_to_editProfileFragment) } @@ -99,8 +103,6 @@ class ProfileFragment : Fragment() { binding.profileImage.setOnClickListener { checkPermissions() } - - return binding.root } private fun checkPermissions() { @@ -129,7 +131,6 @@ class ProfileFragment : Fragment() { } } - private fun openGallery() { pickImageLauncher.launch("image/*") } @@ -150,8 +151,7 @@ class ProfileFragment : Fragment() { context, getString(R.string.error_saving_profile_image), Toast.LENGTH_SHORT - ) - .show() + ).show() } } @@ -173,129 +173,307 @@ class ProfileFragment : Fragment() { binding.profileImage.setImageBitmap(circularBitmap) } - - private fun loadUserData() { - val userId = firebaseAuth!!.currentUser!!.email - + private fun loadUserDataByRole() { val sharedPrefs = requireContext().getSharedPreferences("TaskManagerPrefs", Context.MODE_PRIVATE) val role = sharedPrefs.getString("role", "defaultRole") - if (role == "PM") { - binding.taskListAssigned.visibility = View.GONE + + when (role) { + "PM" -> loadDataForPM() + "PL" -> loadDataForPL() + "Dev" -> loadDataForDEV() + else -> Toast.makeText( + context, + getString(R.string.user_role_not_found), + Toast.LENGTH_SHORT + ).show() } + } - if (userId != null) { - firestore!!.collection("usersData") - .document(userId) - .get() - .addOnSuccessListener { document: DocumentSnapshot -> - val firstName = document.getString("firstName") - val lastName = document.getString("lastName") - val skills = document.getString("skills") - - if (!firstName.isNullOrEmpty() && !lastName.isNullOrEmpty()) { - binding.userName.text = getString(R.string.user_name, firstName, userId) - binding.welcomeMessage.text = getString(R.string.welcome_message, firstName) - - } else { - val email = firebaseAuth!!.currentUser!!.email - binding.userName.text = email - binding.welcomeMessage.text = getString(R.string.welcome_message, email) - } + private fun loadDataForPM() { + binding.statistics.visibility = View.GONE + loadBasicUserData() + loadTasksCreatedByPM() + } + + private fun loadDataForPL() { + loadBasicUserData() + loadTasksAssignedToPL() + loadSubTaskStatistics("PL") + } + + private fun loadDataForDEV() { + loadBasicUserData() + loadTasksAssignedToDev() + loadSubTaskStatistics("Dev") + } - binding.skillsList.text = skills ?: "Nessuna skill disponibile" + private fun loadBasicUserData() { + val userId = firebaseAuth!!.currentUser!!.email + + firestore!!.collection("usersData") + .document(userId!!) + .get() + .addOnSuccessListener { document: DocumentSnapshot -> + val firstName = document.getString("firstName") + val lastName = document.getString("lastName") + val skills = document.getString("skills") + + if (!firstName.isNullOrEmpty() && !lastName.isNullOrEmpty()) { + binding.userName.text = getString(R.string.user_name, firstName, userId) + binding.welcomeMessage.text = getString(R.string.welcome_message, firstName) + } else { + val email = firebaseAuth!!.currentUser!!.email + binding.userName.text = email + binding.welcomeMessage.text = getString(R.string.welcome_message, email) } - .addOnFailureListener { - Toast.makeText( - context, - getString(R.string.error_loading_users), - Toast.LENGTH_SHORT - ).show() + + binding.skillsList.text = skills ?: getString(R.string.no_skills_available) + } + .addOnFailureListener { + Toast.makeText( + context, + getString(R.string.error_loading_users), + Toast.LENGTH_SHORT + ).show() + } + } + + private fun loadTasksCreatedByPM() { + val userId = firebaseAuth!!.currentUser!!.email + + firestore!!.collection("tasks") + .whereEqualTo("createdBy", userId) // Filtra i task creati dal PM + .get() + .addOnSuccessListener { tasksSnapshot -> + taskList.clear() + + for (task in tasksSnapshot) { + val taskName = task.getString("name") + if (!taskName.isNullOrEmpty()) { + taskList.add(taskName) + } } - } + + taskAdapter!!.notifyDataSetChanged() + listViewHeight(binding.assignedTasksList) + } + .addOnFailureListener { + Toast.makeText( + context, + getString(R.string.error_loading_tasks), + Toast.LENGTH_SHORT + ).show() + } + } + + private fun loadTasksAssignedToPL() { + val userId = firebaseAuth!!.currentUser!!.email + firestore!!.collection("tasks") .whereEqualTo("assignedTo", userId) .get() - .addOnSuccessListener { queryDocumentSnapshots: QuerySnapshot -> + .addOnSuccessListener { tasksSnapshot -> taskList.clear() - for (snapshot in queryDocumentSnapshots) { - val taskName = snapshot.getString("name") - if (taskName != null) { + + for (task in tasksSnapshot) { + val taskName = task.getString("name") + if (!taskName.isNullOrEmpty()) { taskList.add(taskName) } } taskAdapter!!.notifyDataSetChanged() listViewHeight(binding.assignedTasksList) + if (tasksSnapshot.isEmpty) { + Toast.makeText( + context, + getString(R.string.error_loading_tasks), + Toast.LENGTH_SHORT + ).show() + } } .addOnFailureListener { Toast.makeText(context, getString(R.string.error_loading_tasks), Toast.LENGTH_SHORT) .show() - } + } + + + private fun loadTasksAssignedToDev() { + val userId = firebaseAuth!!.currentUser!!.email firestore!!.collection("tasks") - .whereEqualTo("assignedTo", userId) .get() .addOnSuccessListener { tasksSnapshot -> - var completedCount = 0 - var assignedCount = 0 - var toDoCount = 0 - - val taskCount = tasksSnapshot.size() + taskList.clear() var tasksProcessed = 0 - if (taskCount == 0) { - updateStatistics(completedCount, assignedCount, toDoCount) - return@addOnSuccessListener - } - for (task in tasksSnapshot) { val taskId = task.id - val subTaskQuery = if (role == "PL") { - firestore!!.collection("tasks").document(taskId).collection("subTasks") - } else { - firestore!!.collection("tasks") - .document(taskId) - .collection("subTasks") - .whereEqualTo("assignedTo", userId) - } - - subTaskQuery.get() + firestore!!.collection("tasks") + .document(taskId) + .collection("subTasks") + .whereEqualTo("assignedTo", userId) + .get() .addOnSuccessListener { subTasksSnapshot -> for (subTask in subTasksSnapshot) { - val subTaskStatus = subTask.getLong("status")?.toInt() - when (subTaskStatus) { - 2 -> completedCount++ - 1 -> assignedCount++ - 0 -> toDoCount++ + val subTaskName = subTask.getString("name") + if (subTaskName != null) { + taskList.add(subTaskName) } } tasksProcessed++ - - if (tasksProcessed == taskCount) { - updateStatistics(completedCount, assignedCount, toDoCount) + if (tasksProcessed == tasksSnapshot.size()) { + taskAdapter!!.notifyDataSetChanged() + listViewHeight(binding.assignedTasksList) } } .addOnFailureListener { + tasksProcessed++ + if (tasksProcessed == tasksSnapshot.size()) { + taskAdapter!!.notifyDataSetChanged() + listViewHeight(binding.assignedTasksList) + } Log.e( "ProfileFragment", - "Errore nel recupero dei sottotask per il task $taskId" + "Errore caricamento dei sottotask per il task $taskId" ) - tasksProcessed++ - if (tasksProcessed == taskCount) { - updateStatistics(completedCount, assignedCount, toDoCount) - } } } + + if (tasksSnapshot.isEmpty) { + taskAdapter!!.notifyDataSetChanged() + listViewHeight(binding.assignedTasksList) + } } .addOnFailureListener { Toast.makeText(context, getString(R.string.error_loading_tasks), Toast.LENGTH_SHORT) .show() } + } + + + private fun loadSubTaskStatistics(role: String) { + val userId = firebaseAuth!!.currentUser!!.email + if (role == "Dev") { + firestore!!.collection("tasks") + .get() + .addOnSuccessListener { tasksSnapshot -> + var completedCount = 0 + var assignedCount = 0 + var toDoCount = 0 + + var tasksProcessed = 0 + val taskCount = tasksSnapshot.size() + + if (taskCount == 0) { + updateStatistics(completedCount, assignedCount, toDoCount) + return@addOnSuccessListener + } + + for (task in tasksSnapshot) { + val taskId = task.id + + firestore!!.collection("tasks") + .document(taskId) + .collection("subTasks") + .whereEqualTo("assignedTo", userId) + .get() + .addOnSuccessListener { subTasksSnapshot -> + for (subTask in subTasksSnapshot) { + val subTaskStatus = subTask.getLong("status")?.toInt() + when (subTaskStatus) { + 2 -> completedCount++ + 1 -> assignedCount++ + 0 -> toDoCount++ + } + } + + tasksProcessed++ + + if (tasksProcessed == taskCount) { + updateStatistics(completedCount, assignedCount, toDoCount) + } + } + .addOnFailureListener { + tasksProcessed++ + if (tasksProcessed == taskCount) { + updateStatistics(completedCount, assignedCount, toDoCount) + } + } + } + } + .addOnFailureListener { + Toast.makeText( + context, + getString(R.string.error_loading_tasks), + Toast.LENGTH_SHORT + ) + .show() + } + } else { + firestore!!.collection("tasks") + .whereEqualTo("assignedTo", userId) + .get() + .addOnSuccessListener { tasksSnapshot -> + var completedCount = 0 + var assignedCount = 0 + var toDoCount = 0 + val taskCount = tasksSnapshot.size() + var tasksProcessed = 0 + if (taskCount == 0) { + updateStatistics(completedCount, assignedCount, toDoCount) + return@addOnSuccessListener + } + + for (task in tasksSnapshot) { + val taskId = task.id + + val subTaskQuery = + firestore!!.collection("tasks").document(taskId).collection("subTasks") + + subTaskQuery.get() + .addOnSuccessListener { subTasksSnapshot -> + for (subTask in subTasksSnapshot) { + val subTaskStatus = subTask.getLong("status")?.toInt() + when (subTaskStatus) { + 2 -> completedCount++ + 1 -> assignedCount++ + 0 -> toDoCount++ + } + } + + tasksProcessed++ + + if (tasksProcessed == taskCount) { + updateStatistics(completedCount, assignedCount, toDoCount) + } + } + .addOnFailureListener { + Log.e( + "ProfileFragment", + "Errore nel recupero dei sottotask per il task $taskId" + ) + tasksProcessed++ + if (tasksProcessed == taskCount) { + updateStatistics(completedCount, assignedCount, toDoCount) + } + } + } + } + .addOnFailureListener { + Toast.makeText( + context, + getString(R.string.error_loading_tasks), + Toast.LENGTH_SHORT + ) + .show() + } + } } private fun updateStatistics(completed: Int, assigned: Int, toDo: Int) { diff --git a/app/src/main/java/com/example/taskmanagement/task/HomeFragment.kt b/app/src/main/java/com/example/taskmanagement/task/HomeFragment.kt index c6149b111fc07500015a260470ff4b6aa21933fb..80cfec860fe640c9b4939995badd29af28cdab7d 100644 --- a/app/src/main/java/com/example/taskmanagement/task/HomeFragment.kt +++ b/app/src/main/java/com/example/taskmanagement/task/HomeFragment.kt @@ -291,7 +291,6 @@ class HomeFragment : Fragment() { val sharedPrefs = requireContext().getSharedPreferences("TaskManagerPrefs", Context.MODE_PRIVATE) val role = sharedPrefs.getString("role", "defaultRole") - Log.d("HomeFragment", "Role: $role") if (role == "PM") { return diff --git a/app/src/main/java/com/example/taskmanagement/task/ModifySubTaskFragment.kt b/app/src/main/java/com/example/taskmanagement/task/ModifySubTaskFragment.kt index a3a461eaf3cb5d1369ef0834ecd5296474b8fd82..f73d2912b03462d6aa1a82579bdd9ed2b99cf383 100644 --- a/app/src/main/java/com/example/taskmanagement/task/ModifySubTaskFragment.kt +++ b/app/src/main/java/com/example/taskmanagement/task/ModifySubTaskFragment.kt @@ -69,6 +69,9 @@ class ModifySubTaskFragment : Fragment() { } private fun loadSubtaskData() { + val sharedPrefs = + requireContext().getSharedPreferences("TaskManagerPrefs", Context.MODE_PRIVATE) + val role = sharedPrefs.getString("role", "defaultRole") db.collection("tasks") .document(taskId ?: "") .collection("subTasks") @@ -79,10 +82,7 @@ class ModifySubTaskFragment : Fragment() { val subtask = document.toObject(SubTask::class.java) subtask?.let { val currentUserEmail = mAuth.currentUser?.email - Log.e("ModifySubTaskFragment", "Current User Email: $currentUserEmail") - Log.e("ModifySubTaskFragment", "Subtask Created By: ${subtask.createdBy}") - Log.e("ModifySubTaskFragment", "Subtask Assigned To: ${subtask.assignedTo}") - if (currentUserEmail == subtask.createdBy || currentUserEmail == subtask.assignedTo) { + if (currentUserEmail == subtask.createdBy || currentUserEmail == subtask.assignedTo || role == "PL") { populateFields(it) } else { Toast.makeText( @@ -214,7 +214,7 @@ class ModifySubTaskFragment : Fragment() { ) binding.statusDropdown.setAdapter(adapter) if (status in statusOptions.indices) { - binding.priorityDropdown.setText(statusOptions[status], false) + binding.statusDropdown.setText(statusOptions[status], false) } } diff --git a/app/src/main/java/com/example/taskmanagement/task/SearchFragment.kt b/app/src/main/java/com/example/taskmanagement/task/SearchFragment.kt index d2705bbc5de81f87e140d540ca562c7395a1897c..91d8df71e3cb2d52e0b4cfdd90748b403b8e088e 100644 --- a/app/src/main/java/com/example/taskmanagement/task/SearchFragment.kt +++ b/app/src/main/java/com/example/taskmanagement/task/SearchFragment.kt @@ -310,6 +310,12 @@ class SearchFragment : Fragment() { } private fun onTaskClick(task: Task) { + val sharedPrefs = + requireContext().getSharedPreferences("TaskManagerPrefs", Context.MODE_PRIVATE) + val role = sharedPrefs.getString("role", "defaultRole") + if (role == "PM") { + return + } val taskId = taskIdMap[task.name] Log.e("SearchFragment", "Task ID: $taskId") val bundle = Bundle().apply { diff --git a/app/src/main/res/layout/fragment_add_sub_task.xml b/app/src/main/res/layout/fragment_add_sub_task.xml index 4176d5b8fd5b7fb7ae4c9cafb27a9f4cce25e991..7c33adc26cd4aa77e51982bb7ebd9c39452bfbd3 100644 --- a/app/src/main/res/layout/fragment_add_sub_task.xml +++ b/app/src/main/res/layout/fragment_add_sub_task.xml @@ -72,7 +72,8 @@ <com.google.android.material.textfield.TextInputEditText android:id="@+id/subtaskName" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + android:inputType="textCapSentences" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout @@ -85,7 +86,8 @@ <com.google.android.material.textfield.TextInputEditText android:id="@+id/subtaskDescription" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + android:inputType="textCapSentences" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout diff --git a/app/src/main/res/layout/fragment_add_task.xml b/app/src/main/res/layout/fragment_add_task.xml index 204f2183a4332420b4f53bfe9155105592070051..79584c54b54ab12187ec25df49409b2308a4113a 100644 --- a/app/src/main/res/layout/fragment_add_task.xml +++ b/app/src/main/res/layout/fragment_add_task.xml @@ -70,6 +70,7 @@ <com.google.android.material.textfield.TextInputEditText android:id="@+id/taskName" + android:inputType="textCapSentences" android:layout_width="match_parent" android:layout_height="wrap_content" /> </com.google.android.material.textfield.TextInputLayout> @@ -79,10 +80,12 @@ style="@style/Widget.Material3.TextInputLayout.FilledBox" android:layout_width="match_parent" android:layout_height="wrap_content" - android:hint="@string/task_description"> + android:hint="@string/task_description" + > <com.google.android.material.textfield.TextInputEditText android:id="@+id/taskDescription" + android:inputType="textCapSentences" android:layout_width="match_parent" android:layout_height="wrap_content" /> </com.google.android.material.textfield.TextInputLayout> diff --git a/app/src/main/res/layout/fragment_chat.xml b/app/src/main/res/layout/fragment_chat.xml index 7dc7e0a4e3917cce8ad465c442ab4a3111ffbb48..af9b0a475b2a56a3e5b66b0535c87c1f7852aab4 100644 --- a/app/src/main/res/layout/fragment_chat.xml +++ b/app/src/main/res/layout/fragment_chat.xml @@ -69,7 +69,7 @@ android:layout_weight="1" android:autofillHints="" android:hint="@string/write_a_message" - android:inputType="text" + android:inputType="textCapSentences" android:padding="8dp" /> <Button diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml index 9a7898131d41f6b41defeecac536197e344dc5f6..3183c7530ac285265e565b8b38d1fa10cde4c94d 100644 --- a/app/src/main/res/layout/fragment_profile.xml +++ b/app/src/main/res/layout/fragment_profile.xml @@ -113,6 +113,7 @@ </LinearLayout> <LinearLayout + android:id="@+id/statistics" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" @@ -189,7 +190,7 @@ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/complete" + android:text="@string/completed" android:textColor="@color/black" /> <TextView diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index cd11bf37d5f5ec92a7b71abc74c78d9fda0fc17e..48f32a31ef21c1e9526116395be686864361db81 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -7,7 +7,6 @@ android:fitsSystemWindows="true" tools:context=".task.SearchFragment"> - <!-- Titolo del Fragment --> <TextView android:id="@+id/fragmentTitle" android:layout_width="wrap_content" @@ -29,6 +28,7 @@ android:layout_marginTop="8dp" android:layout_marginEnd="16dp" android:contentDescription="@string/find_tasks" + android:inputType="textCapSentences" android:queryHint="@string/find_tasks" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/fragment_search_sub.xml b/app/src/main/res/layout/fragment_search_sub.xml index 7368cb780c75d7215aae8d65c9f2823c69a5225a..f87d7b4ebb8763233692b8b4a58663d8c4275f53 100644 --- a/app/src/main/res/layout/fragment_search_sub.xml +++ b/app/src/main/res/layout/fragment_search_sub.xml @@ -39,7 +39,8 @@ android:id="@+id/search_view" android:layout_width="0dp" android:layout_height="wrap_content" - android:queryHint="Cerca Task" + android:inputType="textCapSentences" + android:queryHint="@string/find_tasks" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/fragmentTitle" /> diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index fa1a42fb5990253db9014e069e76cb65259b4ce7..e32b9a0e22f2e937ec75597c3b79e971620484e4 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -175,5 +175,7 @@ <string name="error_loading_profile_image">Errore caricamento immagine profilo</string> <string name="task_id_not_found">Task ID non trovato</string> <string name="error_not_authorized">Non sei autorizzato a modificare questo sottotask.</string> + <string name="no_skills_available">No skills presenti</string> + <string name="assigned">Assegnati</string> </resources> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e1f43428d54c30cd50a28665be03cde8e96ba677..66fb91497f6cdf2ede63a719a4ab8eed5d626a1d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -119,7 +119,7 @@ <string name="error_retrieving_role">Error retrieving role</string> <string name="failed_to_add_subtask">Failed to add subtask: %1$s</string> <string name="subtask_added_successfully">Subtask added successfully</string> - <string name="assigned" translatable="false">Assigned</string> + <string name="assigned">Assigned</string> <string name="high">High</string> <string name="medium">Medium</string> <string name="low">Low</string> @@ -196,5 +196,6 @@ <string name="error_loading_profile_image">Error loading profile image</string> <string name="task_id_not_found">Task ID not found</string> <string name="error_not_authorized">Not authorized</string> + <string name="no_skills_available">No skills available</string> </resources> \ No newline at end of file