Compare commits

...

5 Commits

Author SHA1 Message Date
Mikołaj Pich
1591d494ab Merge branch 'develop' into feature/attendance-excuse-whole-day 2024-03-01 21:16:06 +01:00
Mikołaj Pich
1af44cf60a Merge branch 'develop' into feature/attendance-excuse-whole-day 2024-03-01 21:09:21 +01:00
Mikołaj Pich
28c234a8fd Move excuse whole day button to action bar 2024-02-29 23:48:44 +01:00
Mikołaj Pich
f8c9122686 Merge branch 'develop' into feature/attendance-excuse-whole-day 2024-02-29 23:13:12 +01:00
Mikołaj Pich
7effb7aca2 Add option to excuse a whole day 2024-02-25 18:14:39 +01:00
7 changed files with 90 additions and 19 deletions

View File

@ -88,9 +88,12 @@ class AttendanceRepository @Inject constructor(
return attendanceDb.updateAll(timetable)
}
@JvmName("excuseForAbsenceLessons")
suspend fun excuseForAbsence(
student: Student, semester: Semester,
absenceList: List<Attendance>, reason: String? = null
student: Student,
semester: Semester,
absenceList: List<Attendance>,
reason: String? = null
) {
val items = absenceList.map { attendance ->
Absent(
@ -102,4 +105,22 @@ class AttendanceRepository @Inject constructor(
.switchSemester(semester)
.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)
}
}

View File

@ -2,8 +2,14 @@ package io.github.wulkanowy.ui.modules.attendance
import android.content.DialogInterface.BUTTON_POSITIVE
import android.os.Bundle
import android.view.*
import android.view.View.*
import android.view.LayoutInflater
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.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
@ -63,6 +69,8 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
val inflater = mode.menuInflater
inflater.inflate(R.menu.context_menu_attendance, menu)
menu.findItem(R.id.excuseMenuDaySubmit).setVisible(presenter.isWholeDayExcusable)
return true
}
@ -78,6 +86,7 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
override fun onActionItemClicked(mode: ActionMode, menu: MenuItem): Boolean {
return when (menu.itemId) {
R.id.excuseMenuDaySubmit -> presenter.onExcuseDayButtonClick()
R.id.excuseMenuSubmit -> presenter.onExcuseSubmitButtonClick()
else -> false
}
@ -257,11 +266,18 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
actionMode = (activity as MainActivity?)?.startSupportActionMode(actionModeCallback)
}
override fun startSendMessageIntent(date: LocalDate, numbers: String, reason: String) {
val reasonFullText = getString(
R.string.attendance_excuse_formula,
override fun startSendMessageIntent(date: LocalDate, lessons: String, reason: String) {
val reasonFullText = if (lessons.isEmpty()) {
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,
numbers,
lessons,
if (reason.isNotBlank()) " ${getString(R.string.attendance_excuse_reason)} " else "",
reason.ifBlank { "" }
)

View File

@ -38,6 +38,7 @@ class AttendancePresenter @Inject constructor(
private lateinit var lastError: Throwable
private val attendanceToExcuseList = mutableListOf<Attendance>()
var isWholeDayExcusable = false
private var isVulcanExcusedFunctionEnabled = false
@ -131,6 +132,12 @@ class AttendancePresenter @Inject constructor(
view?.startActionMode()
}
fun onExcuseDayButtonClick(): Boolean {
view?.showExcuseDialog()
return true
}
fun onExcuseCheckboxSelect(attendanceItem: Attendance, checked: Boolean) {
if (checked) attendanceToExcuseList.add(attendanceItem)
else attendanceToExcuseList.remove(attendanceItem)
@ -152,7 +159,7 @@ class AttendancePresenter @Inject constructor(
fun onExcuseDialogSubmit(reason: String) {
view?.finishActionMode()
if (attendanceToExcuseList.isEmpty()) return
if (attendanceToExcuseList.isEmpty() && !isWholeDayExcusable) return
if (isVulcanExcusedFunctionEnabled) {
excuseAbsence(
@ -163,8 +170,8 @@ class AttendancePresenter @Inject constructor(
val attendanceToExcuseNumbers = attendanceToExcuseList.map { it.number }
view?.startSendMessageIntent(
date = attendanceToExcuseList[0].date,
numbers = attendanceToExcuseNumbers.joinToString(", "),
date = currentDate ?: attendanceToExcuseList[0].date,
lessons = attendanceToExcuseNumbers.joinToString(", "),
reason = reason
)
}
@ -217,7 +224,9 @@ class AttendancePresenter @Inject constructor(
}
.logResourceStatus("load attendance")
.onResourceLoading {
view?.showExcuseButton(false)
view?.apply {
showExcuseButton(false)
}
}
.mapResourceData {
if (prefRepository.isShowPresent) {
@ -240,15 +249,16 @@ class AttendancePresenter @Inject constructor(
}
}
.onResourceIntermediate { view?.showRefresh(true) }
.onResourceSuccess {
isVulcanExcusedFunctionEnabled = it.any { item -> item.excusable }
val anyExcusables = it.any { it.isExcusableOrNotExcused }
.onResourceSuccess { items ->
isVulcanExcusedFunctionEnabled = items.any { item -> item.excusable }
isWholeDayExcusable = items.all { it.isAbsenceExcusable }
val anyExcusables = items.any { it.isExcusableOrNotExcused }
view?.showExcuseButton(anyExcusables && (isParent || isVulcanExcusedFunctionEnabled))
analytics.logEvent(
"load_data",
"type" to "attendance",
"items" to it.size
"items" to items.size
)
}
.onResourceNotLoading {
@ -301,7 +311,19 @@ class AttendancePresenter @Inject constructor(
resourceFlow {
val student = studentRepository.getCurrentStudent()
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 {
when (it) {
is Resource.Loading -> view?.run {

View File

@ -56,7 +56,7 @@ interface AttendanceView : BaseView {
fun openSummaryView()
fun startSendMessageIntent(date: LocalDate, numbers: String, reason: String)
fun startSendMessageIntent(date: LocalDate, lessons: String, reason: String)
fun startActionMode()

View File

@ -19,6 +19,9 @@ private inline val AttendanceSummary.allAbsences: Double
inline val Attendance.isExcusableOrNotExcused: Boolean
get() = (excusable || ((absence || lateness) && !excused)) && excuseStatus == null
inline val Attendance.isAbsenceExcusable: Boolean
get() = (excusable && absence && !excused) && excuseStatus == null
fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences)
fun List<AttendanceSummary>.calculatePercentage(): Double {

View File

@ -2,6 +2,13 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/excuseMenuDaySubmit"
android:icon="@drawable/ic_all_done_all"
android:title="@string/attendance_excuse_day_title"
app:iconTint="@color/material_on_surface_emphasis_medium"
app:showAsAction="always" />
<item
android:id="@+id/excuseMenuSubmit"
android:icon="@drawable/ic_all_done"

View File

@ -274,8 +274,10 @@
<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_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_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">
<item quantity="one">New attendance</item>
<item quantity="other">New attendance</item>