forked from github/wulkanowy-mirror
Add excuse function to "not excusable" account (#1429)
This commit is contained in:
parent
ea0fb00bde
commit
98dcc62bb7
@ -10,6 +10,7 @@ import io.github.wulkanowy.data.db.entities.Attendance
|
|||||||
import io.github.wulkanowy.data.enums.SentExcuseStatus
|
import io.github.wulkanowy.data.enums.SentExcuseStatus
|
||||||
import io.github.wulkanowy.databinding.ItemAttendanceBinding
|
import io.github.wulkanowy.databinding.ItemAttendanceBinding
|
||||||
import io.github.wulkanowy.utils.description
|
import io.github.wulkanowy.utils.description
|
||||||
|
import io.github.wulkanowy.utils.isExcusableOrNotExcused
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AttendanceAdapter @Inject constructor() :
|
class AttendanceAdapter @Inject constructor() :
|
||||||
@ -56,7 +57,7 @@ class AttendanceAdapter @Inject constructor() :
|
|||||||
attendanceItemExcuseInfo.visibility = View.VISIBLE
|
attendanceItemExcuseInfo.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
if (item.excusable && excuseActionMode) {
|
if (item.isExcusableOrNotExcused && excuseActionMode) {
|
||||||
attendanceItemNumber.visibility = View.GONE
|
attendanceItemNumber.visibility = View.GONE
|
||||||
attendanceItemExcuseCheckbox.visibility = View.VISIBLE
|
attendanceItemExcuseCheckbox.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,6 +24,7 @@ import io.github.wulkanowy.ui.base.BaseFragment
|
|||||||
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
|
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
|
||||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
|
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
||||||
import io.github.wulkanowy.ui.widgets.DividerItemDecoration
|
import io.github.wulkanowy.ui.widgets.DividerItemDecoration
|
||||||
import io.github.wulkanowy.utils.SchoolDaysValidator
|
import io.github.wulkanowy.utils.SchoolDaysValidator
|
||||||
import io.github.wulkanowy.utils.dpToPx
|
import io.github.wulkanowy.utils.dpToPx
|
||||||
@ -120,7 +121,9 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
attendanceSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
||||||
attendanceSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary))
|
attendanceSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary))
|
||||||
attendanceSwipe.setProgressBackgroundColorSchemeColor(
|
attendanceSwipe.setProgressBackgroundColorSchemeColor(
|
||||||
requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh)
|
requireContext().getThemeAttrColor(
|
||||||
|
R.attr.colorSwipeRefresh
|
||||||
|
)
|
||||||
)
|
)
|
||||||
attendanceErrorRetry.setOnClickListener { presenter.onRetry() }
|
attendanceErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||||
attendanceErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
attendanceErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||||
@ -253,8 +256,13 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||||
.create()
|
.create()
|
||||||
.apply {
|
.apply {
|
||||||
setButton(BUTTON_POSITIVE, getString(R.string.attendance_excuse_dialog_submit)) { _, _ ->
|
setButton(
|
||||||
presenter.onExcuseDialogSubmit(dialogBinding.excuseReason.text?.toString().orEmpty())
|
BUTTON_POSITIVE,
|
||||||
|
getString(R.string.attendance_excuse_dialog_submit)
|
||||||
|
) { _, _ ->
|
||||||
|
presenter.onExcuseDialogSubmit(
|
||||||
|
dialogBinding.excuseReason.text?.toString().orEmpty()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
@ -267,6 +275,17 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
actionMode = (activity as MainActivity?)?.startSupportActionMode(actionModeCallback)
|
actionMode = (activity as MainActivity?)?.startSupportActionMode(actionModeCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun startSendMessageIntent(date: LocalDate, numbers: String, reason: String) {
|
||||||
|
val reasonFullText = getString(
|
||||||
|
R.string.attendance_excuse_formula,
|
||||||
|
date,
|
||||||
|
numbers,
|
||||||
|
if (reason.isNotBlank()) " ${getString(R.string.attendance_excuse_reason)} " else "",
|
||||||
|
reason.ifBlank { "" }
|
||||||
|
)
|
||||||
|
startActivity(SendMessageActivity.getStartIntent(requireContext(), reasonFullText))
|
||||||
|
}
|
||||||
|
|
||||||
override fun showExcuseCheckboxes(show: Boolean) {
|
override fun showExcuseCheckboxes(show: Boolean) {
|
||||||
attendanceAdapter.apply {
|
attendanceAdapter.apply {
|
||||||
excuseActionMode = show
|
excuseActionMode = show
|
||||||
|
@ -15,6 +15,7 @@ import io.github.wulkanowy.utils.capitalise
|
|||||||
import io.github.wulkanowy.utils.flowWithResource
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
import io.github.wulkanowy.utils.flowWithResourceIn
|
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||||
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
|
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
|
||||||
|
import io.github.wulkanowy.utils.isExcusableOrNotExcused
|
||||||
import io.github.wulkanowy.utils.isHolidays
|
import io.github.wulkanowy.utils.isHolidays
|
||||||
import io.github.wulkanowy.utils.nextSchoolDay
|
import io.github.wulkanowy.utils.nextSchoolDay
|
||||||
import io.github.wulkanowy.utils.previousOrSameSchoolDay
|
import io.github.wulkanowy.utils.previousOrSameSchoolDay
|
||||||
@ -47,6 +48,8 @@ class AttendancePresenter @Inject constructor(
|
|||||||
|
|
||||||
private val attendanceToExcuseList = mutableListOf<Attendance>()
|
private val attendanceToExcuseList = mutableListOf<Attendance>()
|
||||||
|
|
||||||
|
private var isVulcanExcusedFunctionEnabled = false
|
||||||
|
|
||||||
fun onAttachView(view: AttendanceView, date: Long?) {
|
fun onAttachView(view: AttendanceView, date: Long?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.initView()
|
view.initView()
|
||||||
@ -148,7 +151,21 @@ class AttendancePresenter @Inject constructor(
|
|||||||
|
|
||||||
fun onExcuseDialogSubmit(reason: String) {
|
fun onExcuseDialogSubmit(reason: String) {
|
||||||
view?.finishActionMode()
|
view?.finishActionMode()
|
||||||
excuseAbsence(if (reason != "") reason else null, attendanceToExcuseList.toList())
|
|
||||||
|
if (isVulcanExcusedFunctionEnabled) {
|
||||||
|
excuseAbsence(
|
||||||
|
reason = reason.takeIf { it.isNotBlank() },
|
||||||
|
toExcuseList = attendanceToExcuseList.toList()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
val attendanceToExcuseNumbers = attendanceToExcuseList.map { it.number }
|
||||||
|
|
||||||
|
view?.startSendMessageIntent(
|
||||||
|
date = attendanceToExcuseList[0].date,
|
||||||
|
numbers = attendanceToExcuseNumbers.joinToString(", "),
|
||||||
|
reason = reason
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onPrepareActionMode(): Boolean {
|
fun onPrepareActionMode(): Boolean {
|
||||||
@ -188,8 +205,12 @@ class AttendancePresenter @Inject constructor(
|
|||||||
private fun loadData(forceRefresh: Boolean = false) {
|
private fun loadData(forceRefresh: Boolean = false) {
|
||||||
Timber.i("Loading attendance data started")
|
Timber.i("Loading attendance data started")
|
||||||
|
|
||||||
|
var isParent = false
|
||||||
|
|
||||||
flowWithResourceIn {
|
flowWithResourceIn {
|
||||||
val student = studentRepository.getCurrentStudent()
|
val student = studentRepository.getCurrentStudent()
|
||||||
|
isParent = student.isParent
|
||||||
|
|
||||||
val semester = semesterRepository.getCurrentSemester(student)
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
attendanceRepository.getAttendance(
|
attendanceRepository.getAttendance(
|
||||||
student,
|
student,
|
||||||
@ -227,12 +248,17 @@ class AttendancePresenter @Inject constructor(
|
|||||||
it.data?.filter { item -> !item.presence }.orEmpty()
|
it.data?.filter { item -> !item.presence }.orEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isVulcanExcusedFunctionEnabled =
|
||||||
|
filteredAttendance.any { item -> item.excusable }
|
||||||
|
|
||||||
view?.apply {
|
view?.apply {
|
||||||
updateData(filteredAttendance.sortedBy { item -> item.number })
|
updateData(filteredAttendance.sortedBy { item -> item.number })
|
||||||
showEmpty(filteredAttendance.isEmpty())
|
showEmpty(filteredAttendance.isEmpty())
|
||||||
showErrorView(false)
|
showErrorView(false)
|
||||||
showContent(filteredAttendance.isNotEmpty())
|
showContent(filteredAttendance.isNotEmpty())
|
||||||
showExcuseButton(filteredAttendance.any { item -> item.excusable })
|
showExcuseButton(filteredAttendance.any { item ->
|
||||||
|
(!isParent && isVulcanExcusedFunctionEnabled) || (isParent && item.isExcusableOrNotExcused)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
analytics.logEvent(
|
analytics.logEvent(
|
||||||
"load_data",
|
"load_data",
|
||||||
|
@ -54,6 +54,8 @@ interface AttendanceView : BaseView {
|
|||||||
|
|
||||||
fun openSummaryView()
|
fun openSummaryView()
|
||||||
|
|
||||||
|
fun startSendMessageIntent(date: LocalDate, numbers: String, reason: String)
|
||||||
|
|
||||||
fun startActionMode()
|
fun startActionMode()
|
||||||
|
|
||||||
fun showExcuseCheckboxes(show: Boolean)
|
fun showExcuseCheckboxes(show: Boolean)
|
||||||
|
@ -35,6 +35,8 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter, ActivitySendMessa
|
|||||||
companion object {
|
companion object {
|
||||||
private const val EXTRA_MESSAGE = "EXTRA_MESSAGE"
|
private const val EXTRA_MESSAGE = "EXTRA_MESSAGE"
|
||||||
|
|
||||||
|
private const val EXTRA_REASON = "EXTRA_REASON"
|
||||||
|
|
||||||
private const val EXTRA_REPLY = "EXTRA_REPLY"
|
private const val EXTRA_REPLY = "EXTRA_REPLY"
|
||||||
|
|
||||||
fun getStartIntent(context: Context) = Intent(context, SendMessageActivity::class.java)
|
fun getStartIntent(context: Context) = Intent(context, SendMessageActivity::class.java)
|
||||||
@ -44,6 +46,11 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter, ActivitySendMessa
|
|||||||
.putExtra(EXTRA_MESSAGE, message)
|
.putExtra(EXTRA_MESSAGE, message)
|
||||||
.putExtra(EXTRA_REPLY, reply)
|
.putExtra(EXTRA_REPLY, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getStartIntent(context: Context, reason: String): Intent {
|
||||||
|
return getStartIntent(context)
|
||||||
|
.putExtra(EXTRA_REASON, reason)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val isDropdownListVisible: Boolean
|
override val isDropdownListVisible: Boolean
|
||||||
@ -79,6 +86,7 @@ class SendMessageActivity : BaseActivity<SendMessagePresenter, ActivitySendMessa
|
|||||||
|
|
||||||
presenter.onAttachView(
|
presenter.onAttachView(
|
||||||
view = this,
|
view = this,
|
||||||
|
reason = intent.getSerializableExtra(EXTRA_REASON) as? String,
|
||||||
message = intent.getSerializableExtra(EXTRA_MESSAGE) as? Message,
|
message = intent.getSerializableExtra(EXTRA_MESSAGE) as? Message,
|
||||||
reply = intent.getSerializableExtra(EXTRA_REPLY) as? Boolean
|
reply = intent.getSerializableExtra(EXTRA_REPLY) as? Boolean
|
||||||
)
|
)
|
||||||
|
@ -40,7 +40,7 @@ class SendMessagePresenter @Inject constructor(
|
|||||||
|
|
||||||
private val messageUpdateChannel = Channel<Unit>()
|
private val messageUpdateChannel = Channel<Unit>()
|
||||||
|
|
||||||
fun onAttachView(view: SendMessageView, message: Message?, reply: Boolean?) {
|
fun onAttachView(view: SendMessageView, reason: String?, message: Message?, reply: Boolean?) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
view.initView()
|
view.initView()
|
||||||
initializeSubjectStream()
|
initializeSubjectStream()
|
||||||
@ -50,6 +50,10 @@ class SendMessagePresenter @Inject constructor(
|
|||||||
if (messageRepository.draftMessage != null && reply == null) {
|
if (messageRepository.draftMessage != null && reply == null) {
|
||||||
view.showMessageBackupDialog()
|
view.showMessageBackupDialog()
|
||||||
}
|
}
|
||||||
|
reason?.let {
|
||||||
|
setSubject("Usprawiedliwenie")
|
||||||
|
setContent(it)
|
||||||
|
}
|
||||||
message?.let {
|
message?.let {
|
||||||
setSubject(when (reply) {
|
setSubject(when (reply) {
|
||||||
true -> "RE: "
|
true -> "RE: "
|
||||||
|
@ -16,6 +16,9 @@ private inline val AttendanceSummary.allPresences: Double
|
|||||||
private inline val AttendanceSummary.allAbsences: Double
|
private inline val AttendanceSummary.allAbsences: Double
|
||||||
get() = absence.toDouble() + absenceExcused
|
get() = absence.toDouble() + absenceExcused
|
||||||
|
|
||||||
|
inline val Attendance.isExcusableOrNotExcused: Boolean
|
||||||
|
get() = excusable || ((absence || lateness) && !excused)
|
||||||
|
|
||||||
fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences)
|
fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences)
|
||||||
|
|
||||||
fun List<AttendanceSummary>.calculatePercentage(): Double {
|
fun List<AttendanceSummary>.calculatePercentage(): Double {
|
||||||
|
@ -192,6 +192,8 @@
|
|||||||
<string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
|
<string name="attendance_excuse_success">Absence excuse request sent successfully!</string>
|
||||||
<string name="attendance_excuse_no_selection">You must select at least one absence!</string>
|
<string name="attendance_excuse_no_selection">You must select at least one absence!</string>
|
||||||
<string name="attendance_excuse_title">Excuse</string>
|
<string name="attendance_excuse_title">Excuse</string>
|
||||||
|
<string name="attendance_excuse_reason" translatable="false">z powodu</string>
|
||||||
|
<string name="attendance_excuse_formula" translatable="false">Dzień dobry,\nProszę o usprawiedliwienie mojego dziecka w dniu %s z lekcji %s%s%s.\n\nPozdrawiam.</string>
|
||||||
|
|
||||||
|
|
||||||
<!--Attendance summary-->
|
<!--Attendance summary-->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user