forked from github/wulkanowy-mirror
Add option to excuse a whole day
This commit is contained in:
parent
d5c17285c1
commit
7effb7aca2
@ -88,9 +88,12 @@ class AttendanceRepository @Inject constructor(
|
|||||||
return attendanceDb.updateAll(timetable)
|
return attendanceDb.updateAll(timetable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmName("excuseForAbsenceLessons")
|
||||||
suspend fun excuseForAbsence(
|
suspend fun excuseForAbsence(
|
||||||
student: Student, semester: Semester,
|
student: Student,
|
||||||
absenceList: List<Attendance>, reason: String? = null
|
semester: Semester,
|
||||||
|
absenceList: List<Attendance>,
|
||||||
|
reason: String? = null
|
||||||
) {
|
) {
|
||||||
val items = absenceList.map { attendance ->
|
val items = absenceList.map { attendance ->
|
||||||
Absent(
|
Absent(
|
||||||
@ -102,4 +105,22 @@ class AttendanceRepository @Inject constructor(
|
|||||||
.switchSemester(semester)
|
.switchSemester(semester)
|
||||||
.excuseForAbsence(items, reason)
|
.excuseForAbsence(items, reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmName("excuseForAbsenceDays")
|
||||||
|
suspend fun excuseForAbsence(
|
||||||
|
student: Student,
|
||||||
|
semester: Semester,
|
||||||
|
days: List<LocalDate>,
|
||||||
|
reason: String? = null
|
||||||
|
) {
|
||||||
|
val items = days.map { day ->
|
||||||
|
Absent(
|
||||||
|
date = LocalDateTime.of(day, LocalTime.of(0, 0)),
|
||||||
|
timeId = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
sdk.init(student)
|
||||||
|
.switchSemester(semester)
|
||||||
|
.excuseForAbsence(items, reason)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,14 @@ package io.github.wulkanowy.ui.modules.attendance
|
|||||||
|
|
||||||
import android.content.DialogInterface.BUTTON_POSITIVE
|
import android.content.DialogInterface.BUTTON_POSITIVE
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.view.View.*
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.View.GONE
|
||||||
|
import android.view.View.INVISIBLE
|
||||||
|
import android.view.View.VISIBLE
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@ -123,6 +129,7 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
attendanceNextButton.setOnClickListener { presenter.onNextDay() }
|
attendanceNextButton.setOnClickListener { presenter.onNextDay() }
|
||||||
|
|
||||||
attendanceExcuseButton.setOnClickListener { presenter.onExcuseButtonClick() }
|
attendanceExcuseButton.setOnClickListener { presenter.onExcuseButtonClick() }
|
||||||
|
attendanceExcuseDayButton.setOnClickListener { presenter.onExcuseDayButtonClick() }
|
||||||
|
|
||||||
attendanceNavContainer.elevation = requireContext().dpToPx(3f)
|
attendanceNavContainer.elevation = requireContext().dpToPx(3f)
|
||||||
}
|
}
|
||||||
@ -215,6 +222,10 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
binding.attendanceExcuseButton.isVisible = show
|
binding.attendanceExcuseButton.isVisible = show
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showExcuseDayButton(show: Boolean) {
|
||||||
|
binding.attendanceExcuseDayButton.isVisible = show
|
||||||
|
}
|
||||||
|
|
||||||
override fun showAttendanceDialog(lesson: Attendance) {
|
override fun showAttendanceDialog(lesson: Attendance) {
|
||||||
(activity as? MainActivity)?.showDialogFragment(AttendanceDialog.newInstance(lesson))
|
(activity as? MainActivity)?.showDialogFragment(AttendanceDialog.newInstance(lesson))
|
||||||
}
|
}
|
||||||
@ -257,11 +268,18 @@ 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) {
|
override fun startSendMessageIntent(date: LocalDate, lessons: String, reason: String) {
|
||||||
val reasonFullText = getString(
|
val reasonFullText = if (lessons.isEmpty()) {
|
||||||
R.string.attendance_excuse_formula,
|
getString(
|
||||||
|
R.string.attendance_excuse_day_formula,
|
||||||
|
date,
|
||||||
|
if (reason.isNotBlank()) " ${getString(R.string.attendance_excuse_reason)} " else "",
|
||||||
|
reason.ifBlank { "" }
|
||||||
|
)
|
||||||
|
} else getString(
|
||||||
|
R.string.attendance_excuse_lessons_formula,
|
||||||
date,
|
date,
|
||||||
numbers,
|
lessons,
|
||||||
if (reason.isNotBlank()) " ${getString(R.string.attendance_excuse_reason)} " else "",
|
if (reason.isNotBlank()) " ${getString(R.string.attendance_excuse_reason)} " else "",
|
||||||
reason.ifBlank { "" }
|
reason.ifBlank { "" }
|
||||||
)
|
)
|
||||||
|
@ -38,6 +38,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
private lateinit var lastError: Throwable
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
private val attendanceToExcuseList = mutableListOf<Attendance>()
|
private val attendanceToExcuseList = mutableListOf<Attendance>()
|
||||||
|
private var isWholeDayExcusable = false
|
||||||
|
|
||||||
private var isVulcanExcusedFunctionEnabled = false
|
private var isVulcanExcusedFunctionEnabled = false
|
||||||
|
|
||||||
@ -129,6 +130,14 @@ class AttendancePresenter @Inject constructor(
|
|||||||
|
|
||||||
fun onExcuseButtonClick() {
|
fun onExcuseButtonClick() {
|
||||||
view?.startActionMode()
|
view?.startActionMode()
|
||||||
|
|
||||||
|
if (isWholeDayExcusable) {
|
||||||
|
view?.showExcuseDayButton(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onExcuseDayButtonClick() {
|
||||||
|
view?.showExcuseDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onExcuseCheckboxSelect(attendanceItem: Attendance, checked: Boolean) {
|
fun onExcuseCheckboxSelect(attendanceItem: Attendance, checked: Boolean) {
|
||||||
@ -152,7 +161,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
fun onExcuseDialogSubmit(reason: String) {
|
fun onExcuseDialogSubmit(reason: String) {
|
||||||
view?.finishActionMode()
|
view?.finishActionMode()
|
||||||
|
|
||||||
if (attendanceToExcuseList.isEmpty()) return
|
if (attendanceToExcuseList.isEmpty() && !isWholeDayExcusable) return
|
||||||
|
|
||||||
if (isVulcanExcusedFunctionEnabled) {
|
if (isVulcanExcusedFunctionEnabled) {
|
||||||
excuseAbsence(
|
excuseAbsence(
|
||||||
@ -163,8 +172,8 @@ class AttendancePresenter @Inject constructor(
|
|||||||
val attendanceToExcuseNumbers = attendanceToExcuseList.map { it.number }
|
val attendanceToExcuseNumbers = attendanceToExcuseList.map { it.number }
|
||||||
|
|
||||||
view?.startSendMessageIntent(
|
view?.startSendMessageIntent(
|
||||||
date = attendanceToExcuseList[0].date,
|
date = currentDate ?: attendanceToExcuseList[0].date,
|
||||||
numbers = attendanceToExcuseNumbers.joinToString(", "),
|
lessons = attendanceToExcuseNumbers.joinToString(", "),
|
||||||
reason = reason
|
reason = reason
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -174,6 +183,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
view?.apply {
|
view?.apply {
|
||||||
showExcuseCheckboxes(true)
|
showExcuseCheckboxes(true)
|
||||||
showExcuseButton(false)
|
showExcuseButton(false)
|
||||||
|
showExcuseDayButton(false)
|
||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
showDayNavigation(false)
|
showDayNavigation(false)
|
||||||
}
|
}
|
||||||
@ -185,6 +195,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
view?.apply {
|
view?.apply {
|
||||||
showExcuseCheckboxes(false)
|
showExcuseCheckboxes(false)
|
||||||
showExcuseButton(true)
|
showExcuseButton(true)
|
||||||
|
showExcuseDayButton(false)
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
showDayNavigation(true)
|
showDayNavigation(true)
|
||||||
}
|
}
|
||||||
@ -217,7 +228,10 @@ class AttendancePresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
.logResourceStatus("load attendance")
|
.logResourceStatus("load attendance")
|
||||||
.onResourceLoading {
|
.onResourceLoading {
|
||||||
view?.showExcuseButton(false)
|
view?.apply {
|
||||||
|
showExcuseButton(false)
|
||||||
|
showExcuseDayButton(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.mapResourceData {
|
.mapResourceData {
|
||||||
if (prefRepository.isShowPresent) {
|
if (prefRepository.isShowPresent) {
|
||||||
@ -240,15 +254,16 @@ class AttendancePresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onResourceIntermediate { view?.showRefresh(true) }
|
.onResourceIntermediate { view?.showRefresh(true) }
|
||||||
.onResourceSuccess {
|
.onResourceSuccess { items ->
|
||||||
isVulcanExcusedFunctionEnabled = it.any { item -> item.excusable }
|
isVulcanExcusedFunctionEnabled = items.any { item -> item.excusable }
|
||||||
val anyExcusables = it.any { it.isExcusableOrNotExcused }
|
isWholeDayExcusable = items.all { it.isExcusableOrNotExcused }
|
||||||
|
val anyExcusables = items.any { it.isExcusableOrNotExcused }
|
||||||
view?.showExcuseButton(anyExcusables && (isParent || isVulcanExcusedFunctionEnabled))
|
view?.showExcuseButton(anyExcusables && (isParent || isVulcanExcusedFunctionEnabled))
|
||||||
|
|
||||||
analytics.logEvent(
|
analytics.logEvent(
|
||||||
"load_data",
|
"load_data",
|
||||||
"type" to "attendance",
|
"type" to "attendance",
|
||||||
"items" to it.size
|
"items" to items.size
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.onResourceNotLoading {
|
.onResourceNotLoading {
|
||||||
@ -301,7 +316,19 @@ class AttendancePresenter @Inject constructor(
|
|||||||
resourceFlow {
|
resourceFlow {
|
||||||
val student = studentRepository.getCurrentStudent()
|
val student = studentRepository.getCurrentStudent()
|
||||||
val semester = semesterRepository.getCurrentSemester(student)
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
attendanceRepository.excuseForAbsence(student, semester, toExcuseList, reason)
|
if (toExcuseList.isEmpty()) {
|
||||||
|
attendanceRepository.excuseForAbsence(
|
||||||
|
student = student,
|
||||||
|
semester = semester,
|
||||||
|
days = listOfNotNull(currentDate),
|
||||||
|
reason = reason
|
||||||
|
)
|
||||||
|
} else attendanceRepository.excuseForAbsence(
|
||||||
|
student = student,
|
||||||
|
semester = semester,
|
||||||
|
absenceList = toExcuseList,
|
||||||
|
reason = reason
|
||||||
|
)
|
||||||
}.onEach {
|
}.onEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
is Resource.Loading -> view?.run {
|
is Resource.Loading -> view?.run {
|
||||||
@ -309,6 +336,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
showProgress(true)
|
showProgress(true)
|
||||||
showContent(false)
|
showContent(false)
|
||||||
showExcuseButton(false)
|
showExcuseButton(false)
|
||||||
|
showExcuseDayButton(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
@ -317,6 +345,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
attendanceToExcuseList.clear()
|
attendanceToExcuseList.clear()
|
||||||
view?.run {
|
view?.run {
|
||||||
showExcuseButton(false)
|
showExcuseButton(false)
|
||||||
|
showExcuseDayButton(false)
|
||||||
showMessage(excuseSuccessString)
|
showMessage(excuseSuccessString)
|
||||||
showContent(true)
|
showContent(true)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
|
@ -48,6 +48,8 @@ interface AttendanceView : BaseView {
|
|||||||
|
|
||||||
fun showExcuseButton(show: Boolean)
|
fun showExcuseButton(show: Boolean)
|
||||||
|
|
||||||
|
fun showExcuseDayButton(show: Boolean)
|
||||||
|
|
||||||
fun showAttendanceDialog(lesson: Attendance)
|
fun showAttendanceDialog(lesson: Attendance)
|
||||||
|
|
||||||
fun showDatePickerDialog(selectedDate: LocalDate)
|
fun showDatePickerDialog(selectedDate: LocalDate)
|
||||||
@ -56,7 +58,7 @@ interface AttendanceView : BaseView {
|
|||||||
|
|
||||||
fun openSummaryView()
|
fun openSummaryView()
|
||||||
|
|
||||||
fun startSendMessageIntent(date: LocalDate, numbers: String, reason: String)
|
fun startSendMessageIntent(date: LocalDate, lessons: String, reason: String)
|
||||||
|
|
||||||
fun startActionMode()
|
fun startActionMode()
|
||||||
|
|
||||||
|
@ -69,6 +69,19 @@
|
|||||||
app:icon="@drawable/ic_all_done_all"
|
app:icon="@drawable/ic_all_done_all"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
android:id="@+id/attendanceExcuseDayButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:text="@string/attendance_excuse_day_title"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:icon="@drawable/ic_all_done_all"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/attendanceError"
|
android:id="@+id/attendanceError"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -274,8 +274,10 @@
|
|||||||
<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_day_title">Excuse entire day</string>
|
||||||
<string name="attendance_excuse_reason" translatable="false">z powodu</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>
|
<string name="attendance_excuse_lessons_formula" translatable="false">Dzień dobry,\nProszę o usprawiedliwienie mojego dziecka w dniu %s z lekcji %s%s%s.\n\nPozdrawiam.</string>
|
||||||
|
<string name="attendance_excuse_day_formula" translatable="false">Dzień dobry,\nProszę o usprawiedliwienie mojego dziecka w dniu %s%s%s.\n\nPozdrawiam.</string>
|
||||||
<plurals name="attendance_notify_new_items_title">
|
<plurals name="attendance_notify_new_items_title">
|
||||||
<item quantity="one">New attendance</item>
|
<item quantity="one">New attendance</item>
|
||||||
<item quantity="other">New attendance</item>
|
<item quantity="other">New attendance</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user