feat(notifications): Fetch corresponding invitations
This commit is contained in:
parent
ac36100c74
commit
046da599b7
|
@ -14,6 +14,7 @@ import com.p_vacho.neat_calendar.MyApplication
|
||||||
import com.p_vacho.neat_calendar.R
|
import com.p_vacho.neat_calendar.R
|
||||||
import com.p_vacho.neat_calendar.adapters.NotificationAdapter
|
import com.p_vacho.neat_calendar.adapters.NotificationAdapter
|
||||||
import com.p_vacho.neat_calendar.api.RetrofitClient
|
import com.p_vacho.neat_calendar.api.RetrofitClient
|
||||||
|
import com.p_vacho.neat_calendar.api.models.InvitationResponse
|
||||||
import com.p_vacho.neat_calendar.api.models.NotificationResponse
|
import com.p_vacho.neat_calendar.api.models.NotificationResponse
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -24,6 +25,7 @@ class NotificationsActivity : AppCompatActivity() {
|
||||||
private lateinit var btnBack: ImageButton
|
private lateinit var btnBack: ImageButton
|
||||||
|
|
||||||
private lateinit var notifications: MutableList<NotificationResponse>
|
private lateinit var notifications: MutableList<NotificationResponse>
|
||||||
|
private lateinit var invitations: MutableMap<String, InvitationResponse> // invitation id -> invitation
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -43,7 +45,10 @@ class NotificationsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
notifications = fetchNotifications().toMutableList()
|
notifications = fetchNotifications().toMutableList()
|
||||||
rvNotifications.adapter = NotificationAdapter(notifications, ::handleNotificationAction, ::handleNotificationClick)
|
invitations = fetchInvitations().toMutableMap()
|
||||||
|
rvNotifications.adapter = NotificationAdapter(notifications, ::handleNotificationAction, ::handleNotificationClick) {
|
||||||
|
notification -> invitations[notification.data]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btnBack.setOnClickListener { finish() }
|
btnBack.setOnClickListener { finish() }
|
||||||
|
@ -64,6 +69,19 @@ class NotificationsActivity : AppCompatActivity() {
|
||||||
return notifications
|
return notifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchInvitations(): Map<String, InvitationResponse> {
|
||||||
|
val userId = (application as MyApplication).tokenManager.userId
|
||||||
|
if (userId == null) {
|
||||||
|
finish()
|
||||||
|
return emptyMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
val fetchedInvitations = withContext(Dispatchers.IO) {
|
||||||
|
RetrofitClient.invitationService.getIncomingInvitations(userId)
|
||||||
|
}
|
||||||
|
return fetchedInvitations.associateBy { it.id }
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleNotificationAction(notification: NotificationResponse, action: NotificationAdapter.Action, position: Int) {
|
private fun handleNotificationAction(notification: NotificationResponse, action: NotificationAdapter.Action, position: Int) {
|
||||||
when (action) {
|
when (action) {
|
||||||
NotificationAdapter.Action.ACCEPT -> {
|
NotificationAdapter.Action.ACCEPT -> {
|
||||||
|
|
|
@ -3,11 +3,11 @@ package com.p_vacho.neat_calendar.adapters
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Button
|
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.p_vacho.neat_calendar.R
|
import com.p_vacho.neat_calendar.R
|
||||||
|
import com.p_vacho.neat_calendar.api.models.InvitationResponse
|
||||||
import com.p_vacho.neat_calendar.api.models.NotificationResponse
|
import com.p_vacho.neat_calendar.api.models.NotificationResponse
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
|
@ -17,6 +17,7 @@ class NotificationAdapter(
|
||||||
private val notifications: MutableList<NotificationResponse>,
|
private val notifications: MutableList<NotificationResponse>,
|
||||||
private val onActionClick: (NotificationResponse, Action, Int) -> Unit,
|
private val onActionClick: (NotificationResponse, Action, Int) -> Unit,
|
||||||
private val onNotificationClick: (NotificationResponse, Int) -> Unit,
|
private val onNotificationClick: (NotificationResponse, Int) -> Unit,
|
||||||
|
private val getInvitationData: (NotificationResponse) -> InvitationResponse?,
|
||||||
) : RecyclerView.Adapter<NotificationAdapter.NotificationViewHolder>() {
|
) : RecyclerView.Adapter<NotificationAdapter.NotificationViewHolder>() {
|
||||||
|
|
||||||
enum class Action {
|
enum class Action {
|
||||||
|
@ -42,8 +43,6 @@ class NotificationAdapter(
|
||||||
override fun onBindViewHolder(holder: NotificationViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: NotificationViewHolder, position: Int) {
|
||||||
val notification = notifications[position]
|
val notification = notifications[position]
|
||||||
|
|
||||||
holder.message.text = notification.message
|
|
||||||
|
|
||||||
// Format and set the creation time
|
// Format and set the creation time
|
||||||
val formattedTime = formatNotificationTime(notification.created_at)
|
val formattedTime = formatNotificationTime(notification.created_at)
|
||||||
holder.notificationTime.text = formattedTime
|
holder.notificationTime.text = formattedTime
|
||||||
|
@ -53,17 +52,46 @@ class NotificationAdapter(
|
||||||
|
|
||||||
// Handle invitation actions
|
// Handle invitation actions
|
||||||
if (notification.event_type == "invitation") {
|
if (notification.event_type == "invitation") {
|
||||||
holder.invitationActions.visibility = View.VISIBLE
|
val invitation = getInvitationData(notification)
|
||||||
holder.acceptButton.setOnClickListener {
|
|
||||||
onActionClick(notification, Action.ACCEPT, position)
|
// TODO: Consider fetching the user names here to show
|
||||||
}
|
// TODO: Localize
|
||||||
holder.declineButton.setOnClickListener {
|
if (invitation != null) {
|
||||||
onActionClick(notification, Action.DECLINE, position)
|
if (notification.message == "new-invitation") {
|
||||||
}
|
holder.message.setText("You have received an event invitation")
|
||||||
holder.viewEventButton.setOnClickListener {
|
} else if (notification.message == "invitation-accepted") {
|
||||||
onActionClick(notification, Action.VIEW_EVENT, position)
|
holder.message.setText("Your event invitation has been accepted")
|
||||||
|
} else if (notification.message == "invitation-declined") {
|
||||||
|
holder.message.setText("Your event invitation has been declined")
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.invitationActions.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
holder.acceptButton.setOnClickListener {
|
||||||
|
onActionClick(notification, Action.ACCEPT, position)
|
||||||
|
}
|
||||||
|
holder.declineButton.setOnClickListener {
|
||||||
|
onActionClick(notification, Action.DECLINE, position)
|
||||||
|
}
|
||||||
|
holder.viewEventButton.setOnClickListener {
|
||||||
|
onActionClick(notification, Action.VIEW_EVENT, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (notification.message == "new-invitation") {
|
||||||
|
holder.message.setText("You have received an event invitation [invitation deleted]")
|
||||||
|
} else if (notification.message == "invitation-accepted") {
|
||||||
|
holder.message.setText("Your event invitation has been accepted [invitation deleted]")
|
||||||
|
} else if (notification.message == "invitation-declined") {
|
||||||
|
holder.message.setText("Your event invitation has been declined [invitation deleted]")
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.invitationActions.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
holder.message.text = notification.message
|
||||||
|
|
||||||
holder.invitationActions.visibility = View.GONE
|
holder.invitationActions.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,18 @@
|
||||||
package com.p_vacho.neat_calendar.api.models
|
package com.p_vacho.neat_calendar.api.models
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
|
||||||
data class InvitationRequest(
|
data class InvitationRequest(
|
||||||
val event_id: String,
|
val event_id: String,
|
||||||
val invitee_id: String,
|
val invitee_id: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class InvitationResponse(
|
||||||
|
val id: String,
|
||||||
|
val invitor_id: String,
|
||||||
|
val invitee_id: String,
|
||||||
|
val event_id: String,
|
||||||
|
val status: String, // "accepted" / "declined" / "pending"
|
||||||
|
val sent_at: OffsetDateTime,
|
||||||
|
val responded_at: OffsetDateTime?,
|
||||||
)
|
)
|
|
@ -1,10 +1,29 @@
|
||||||
package com.p_vacho.neat_calendar.api.services
|
package com.p_vacho.neat_calendar.api.services
|
||||||
|
|
||||||
import com.p_vacho.neat_calendar.api.models.InvitationRequest
|
import com.p_vacho.neat_calendar.api.models.InvitationRequest
|
||||||
|
import com.p_vacho.neat_calendar.api.models.InvitationResponse
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
import retrofit2.http.Path
|
||||||
|
|
||||||
interface InvitationsService {
|
interface InvitationsService {
|
||||||
@POST("invitations")
|
@POST("invitations")
|
||||||
suspend fun createInvitation(@Body invitationData: InvitationRequest)
|
suspend fun createInvitation(@Body invitationData: InvitationRequest): InvitationResponse
|
||||||
|
|
||||||
|
@GET("invitations/{invitation_id}")
|
||||||
|
suspend fun getInvitation(@Path("invitation_id") invitiationId: String): InvitationResponse
|
||||||
|
|
||||||
|
@GET("users/{user_id}/invitations")
|
||||||
|
suspend fun getInvitations(@Path("user_id") userId: String): List<InvitationResponse>
|
||||||
|
|
||||||
|
@GET("users/{user_id}/invitations/incoming")
|
||||||
|
suspend fun getIncomingInvitations(@Path("user_id") userId: String): List<InvitationResponse>
|
||||||
|
|
||||||
|
@POST("invitations/{invitation_id}/accept")
|
||||||
|
suspend fun acceptInvitation(@Path("invitation_id") invitationId: String): Unit
|
||||||
|
|
||||||
|
@POST("invitations/{invitation_id}/decline")
|
||||||
|
suspend fun declineInvitation(@Path("invitation_id") invitationId: String): Unit
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue