forked from github/wulkanowy-mirror
Add "add homework" feature (#1564)
This commit is contained in:

committed by
GitHub

parent
1839d7cb8f
commit
e8075e30e4
@ -10,6 +10,7 @@ import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.databinding.FragmentHomeworkBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.homework.add.HomeworkAddDialog
|
||||
import io.github.wulkanowy.ui.modules.homework.details.HomeworkDetailsDialog
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
@ -64,6 +65,8 @@ class HomeworkFragment : BaseFragment<FragmentHomeworkBinding>(R.layout.fragment
|
||||
homeworkPreviousButton.setOnClickListener { presenter.onPreviousDay() }
|
||||
homeworkNextButton.setOnClickListener { presenter.onNextDay() }
|
||||
|
||||
openAddHomeworkButton.setOnClickListener { presenter.onHomeworkAddButtonClicked() }
|
||||
|
||||
homeworkNavContainer.setElevationCompat(requireContext().dpToPx(8f))
|
||||
}
|
||||
}
|
||||
@ -122,10 +125,14 @@ class HomeworkFragment : BaseFragment<FragmentHomeworkBinding>(R.layout.fragment
|
||||
binding.homeworkNextButton.visibility = if (show) VISIBLE else View.INVISIBLE
|
||||
}
|
||||
|
||||
override fun showTimetableDialog(homework: Homework) {
|
||||
override fun showHomeworkDialog(homework: Homework) {
|
||||
(activity as? MainActivity)?.showDialogFragment(HomeworkDetailsDialog.newInstance(homework))
|
||||
}
|
||||
|
||||
override fun showAddHomeworkDialog() {
|
||||
(activity as? MainActivity)?.showDialogFragment(HomeworkAddDialog())
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
|
||||
|
@ -78,7 +78,11 @@ class HomeworkPresenter @Inject constructor(
|
||||
|
||||
fun onHomeworkItemSelected(homework: Homework) {
|
||||
Timber.i("Select homework item ${homework.id}")
|
||||
view?.showTimetableDialog(homework)
|
||||
view?.showHomeworkDialog(homework)
|
||||
}
|
||||
|
||||
fun onHomeworkAddButtonClicked() {
|
||||
view?.showAddHomeworkDialog()
|
||||
}
|
||||
|
||||
private fun setBaseDateOnHolidays() {
|
||||
|
@ -33,5 +33,7 @@ interface HomeworkView : BaseView {
|
||||
|
||||
fun showNextButton(show: Boolean)
|
||||
|
||||
fun showTimetableDialog(homework: Homework)
|
||||
fun showHomeworkDialog(homework: Homework)
|
||||
|
||||
fun showAddHomeworkDialog()
|
||||
}
|
||||
|
@ -0,0 +1,124 @@
|
||||
package io.github.wulkanowy.ui.modules.homework.add
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import com.google.android.material.datepicker.CalendarConstraints
|
||||
import com.google.android.material.datepicker.MaterialDatePicker
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.databinding.DialogHomeworkAddBinding
|
||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import io.github.wulkanowy.utils.toLocalDateTime
|
||||
import io.github.wulkanowy.utils.toTimestamp
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class HomeworkAddDialog : BaseDialogFragment<DialogHomeworkAddBinding>(), HomeworkAddView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: HomeworkAddPresenter
|
||||
|
||||
private var date: LocalDate? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NO_TITLE, 0)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
) = DialogHomeworkAddBinding.inflate(inflater).apply { binding = this }.root
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
presenter.onAttachView(this)
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
with(binding) {
|
||||
homeworkDialogSubjectEdit.doOnTextChanged { _, _, _, _ ->
|
||||
homeworkDialogSubject.error = null
|
||||
homeworkDialogSubject.isErrorEnabled = false
|
||||
}
|
||||
homeworkDialogDateEdit.doOnTextChanged { _, _, _, _ ->
|
||||
homeworkDialogDate.error = null
|
||||
homeworkDialogDate.isErrorEnabled = false
|
||||
}
|
||||
homeworkDialogContentEdit.doOnTextChanged { _, _, _, _ ->
|
||||
homeworkDialogContent.error = null
|
||||
homeworkDialogContent.isErrorEnabled = false
|
||||
}
|
||||
homeworkDialogClose.setOnClickListener { dismiss() }
|
||||
homeworkDialogDateEdit.setOnClickListener { presenter.showDatePicker(date) }
|
||||
homeworkDialogAdd.setOnClickListener {
|
||||
presenter.onAddHomeworkClicked(
|
||||
subject = homeworkDialogSubjectEdit.text?.toString(),
|
||||
teacher = homeworkDialogTeacherEdit.text?.toString(),
|
||||
date = homeworkDialogDateEdit.text?.toString(),
|
||||
content = homeworkDialogContentEdit.text?.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun showSuccessMessage() {
|
||||
showMessage(getString(R.string.homework_add_success))
|
||||
}
|
||||
|
||||
override fun setErrorSubjectRequired() {
|
||||
with(binding.homeworkDialogSubject) {
|
||||
isErrorEnabled = true
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setErrorDateRequired() {
|
||||
with(binding.homeworkDialogDate) {
|
||||
isErrorEnabled = true
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setErrorContentRequired() {
|
||||
with(binding.homeworkDialogContent) {
|
||||
isErrorEnabled = true
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
override fun closeDialog() {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
override fun showDatePickerDialog(currentDate: LocalDate) {
|
||||
val constraintsBuilder = CalendarConstraints.Builder().apply {
|
||||
setStart(LocalDate.now().toEpochDay())
|
||||
}
|
||||
val datePicker =
|
||||
MaterialDatePicker.Builder.datePicker()
|
||||
.setCalendarConstraints(constraintsBuilder.build())
|
||||
.setSelection(currentDate.toTimestamp())
|
||||
.build()
|
||||
|
||||
datePicker.addOnPositiveButtonClickListener {
|
||||
date = it.toLocalDateTime().toLocalDate()
|
||||
binding.homeworkDialogDate.editText?.setText(date!!.toFormattedString())
|
||||
}
|
||||
|
||||
if (!parentFragmentManager.isStateSaved) {
|
||||
datePicker.show(this.parentFragmentManager, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
presenter.onDetachView()
|
||||
super.onDestroyView()
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package io.github.wulkanowy.ui.modules.homework.add
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.data.repositories.HomeworkRepository
|
||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.flowWithResource
|
||||
import io.github.wulkanowy.utils.toLocalDate
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
class HomeworkAddPresenter @Inject constructor(
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val homeworkRepository: HomeworkRepository,
|
||||
private val semesterRepository: SemesterRepository
|
||||
) : BasePresenter<HomeworkAddView>(errorHandler, studentRepository) {
|
||||
|
||||
override fun onAttachView(view: HomeworkAddView) {
|
||||
super.onAttachView(view)
|
||||
view.initView()
|
||||
Timber.i("Homework details view was initialized")
|
||||
}
|
||||
|
||||
fun showDatePicker(date: LocalDate?) {
|
||||
view?.showDatePickerDialog(date ?: LocalDate.now())
|
||||
}
|
||||
|
||||
fun onAddHomeworkClicked(subject: String?, teacher: String?, date: String?, content: String?) {
|
||||
var isError = false
|
||||
|
||||
if (subject.isNullOrBlank()) {
|
||||
view?.setErrorSubjectRequired()
|
||||
isError = true
|
||||
}
|
||||
|
||||
if (date.isNullOrBlank()) {
|
||||
view?.setErrorDateRequired()
|
||||
isError = true
|
||||
}
|
||||
|
||||
if (content.isNullOrBlank()) {
|
||||
view?.setErrorContentRequired()
|
||||
isError = true
|
||||
}
|
||||
|
||||
if (!isError) {
|
||||
saveHomework(subject!!, teacher.orEmpty(), date!!.toLocalDate(), content!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveHomework(subject: String, teacher: String, date: LocalDate, content: String) {
|
||||
flowWithResource {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
val entryDate = LocalDate.now()
|
||||
homeworkRepository.saveHomework(
|
||||
Homework(
|
||||
semesterId = semester.semesterId,
|
||||
studentId = student.studentId,
|
||||
date = date,
|
||||
entryDate = entryDate,
|
||||
subject = subject,
|
||||
content = content,
|
||||
teacher = teacher,
|
||||
teacherSymbol = "",
|
||||
attachments = emptyList(),
|
||||
).apply { isAddedByUser = true }
|
||||
)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Homework insert start")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Homework insert: Success")
|
||||
view?.run {
|
||||
showSuccessMessage()
|
||||
closeDialog()
|
||||
}
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Homework insert result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.launch("add_homework")
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package io.github.wulkanowy.ui.modules.homework.add
|
||||
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import java.time.LocalDate
|
||||
|
||||
interface HomeworkAddView : BaseView {
|
||||
|
||||
fun initView()
|
||||
|
||||
fun showSuccessMessage()
|
||||
|
||||
fun setErrorSubjectRequired()
|
||||
|
||||
fun setErrorDateRequired()
|
||||
|
||||
fun setErrorContentRequired()
|
||||
|
||||
fun closeDialog()
|
||||
|
||||
fun showDatePickerDialog(currentDate: LocalDate)
|
||||
}
|
@ -5,10 +5,12 @@ import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.databinding.ItemHomeworkDialogAttachmentBinding
|
||||
import io.github.wulkanowy.databinding.ItemHomeworkDialogAttachmentsHeaderBinding
|
||||
import io.github.wulkanowy.databinding.ItemHomeworkDialogDetailsBinding
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -37,6 +39,8 @@ class HomeworkDetailsAdapter @Inject constructor() :
|
||||
|
||||
var onFullScreenExitClickListener = {}
|
||||
|
||||
var onDeleteClickListener: (homework: Homework) -> Unit = {}
|
||||
|
||||
override fun getItemCount() = 1 + if (attachments.isNotEmpty()) attachments.size + 1 else 0
|
||||
|
||||
override fun getItemViewType(position: Int) = when (position) {
|
||||
@ -49,9 +53,15 @@ class HomeworkDetailsAdapter @Inject constructor() :
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
|
||||
return when (viewType) {
|
||||
ViewType.ATTACHMENTS_HEADER.id -> AttachmentsHeaderViewHolder(ItemHomeworkDialogAttachmentsHeaderBinding.inflate(inflater, parent, false))
|
||||
ViewType.ATTACHMENT.id -> AttachmentViewHolder(ItemHomeworkDialogAttachmentBinding.inflate(inflater, parent, false))
|
||||
else -> DetailsViewHolder(ItemHomeworkDialogDetailsBinding.inflate(inflater, parent, false))
|
||||
ViewType.ATTACHMENTS_HEADER.id -> AttachmentsHeaderViewHolder(
|
||||
ItemHomeworkDialogAttachmentsHeaderBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
ViewType.ATTACHMENT.id -> AttachmentViewHolder(
|
||||
ItemHomeworkDialogAttachmentBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
else -> DetailsViewHolder(
|
||||
ItemHomeworkDialogDetailsBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,12 +73,15 @@ class HomeworkDetailsAdapter @Inject constructor() :
|
||||
}
|
||||
|
||||
private fun bindDetailsViewHolder(holder: DetailsViewHolder) {
|
||||
val noDataString = holder.binding.root.context.getString(R.string.all_no_data)
|
||||
|
||||
with(holder.binding) {
|
||||
homeworkDialogDate.text = homework?.date?.toFormattedString()
|
||||
homeworkDialogEntryDate.text = homework?.entryDate?.toFormattedString()
|
||||
homeworkDialogSubject.text = homework?.subject
|
||||
homeworkDialogTeacher.text = homework?.teacher
|
||||
homeworkDialogContent.text = homework?.content
|
||||
homeworkDialogSubject.text = homework?.subject.ifNullOrBlank { noDataString }
|
||||
homeworkDialogTeacher.text = homework?.teacher.ifNullOrBlank { noDataString }
|
||||
homeworkDialogContent.text = homework?.content.ifNullOrBlank { noDataString }
|
||||
homeworkDialogDelete.visibility = if (homework?.isAddedByUser == true) VISIBLE else GONE
|
||||
homeworkDialogFullScreen.visibility = if (isHomeworkFullscreen) GONE else VISIBLE
|
||||
homeworkDialogFullScreenExit.visibility = if (isHomeworkFullscreen) VISIBLE else GONE
|
||||
homeworkDialogFullScreen.setOnClickListener {
|
||||
@ -81,6 +94,9 @@ class HomeworkDetailsAdapter @Inject constructor() :
|
||||
homeworkDialogFullScreenExit.visibility = GONE
|
||||
onFullScreenExitClickListener()
|
||||
}
|
||||
homeworkDialogDelete.setOnClickListener {
|
||||
onDeleteClickListener(homework!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,9 @@ class HomeworkDetailsDialog : BaseDialogFragment<DialogHomeworkBinding>(), Homew
|
||||
@Inject
|
||||
lateinit var detailsAdapter: HomeworkDetailsAdapter
|
||||
|
||||
override val homeworkDeleteSuccess: String
|
||||
get() = getString(R.string.homework_delete_success)
|
||||
|
||||
private lateinit var homework: Homework
|
||||
|
||||
companion object {
|
||||
@ -82,12 +85,17 @@ class HomeworkDetailsDialog : BaseDialogFragment<DialogHomeworkBinding>(), Homew
|
||||
dialog?.window?.setLayout(WRAP_CONTENT, WRAP_CONTENT)
|
||||
presenter.isHomeworkFullscreen = false
|
||||
}
|
||||
onDeleteClickListener = { homework -> presenter.deleteHomework(homework) }
|
||||
isHomeworkFullscreen = presenter.isHomeworkFullscreen
|
||||
homework = this@HomeworkDetailsDialog.homework
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun closeDialog() {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
override fun updateMarkAsDoneLabel(isDone: Boolean) {
|
||||
binding.homeworkDialogRead.text =
|
||||
view?.context?.getString(if (isDone) R.string.homework_mark_as_undone else R.string.homework_mark_as_done)
|
||||
|
@ -33,6 +33,25 @@ class HomeworkDetailsPresenter @Inject constructor(
|
||||
Timber.i("Homework details view was initialized")
|
||||
}
|
||||
|
||||
fun deleteHomework(homework: Homework) {
|
||||
flowWithResource { homeworkRepository.deleteHomework(homework) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Homework delete start")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Homework delete: Success")
|
||||
view?.run {
|
||||
showMessage(homeworkDeleteSuccess)
|
||||
closeDialog()
|
||||
}
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Homework delete result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.launch("delete")
|
||||
}
|
||||
|
||||
fun toggleDone(homework: Homework) {
|
||||
flowWithResource { homeworkRepository.toggleDone(homework) }.onEach {
|
||||
when (it.status) {
|
||||
|
@ -4,7 +4,11 @@ import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface HomeworkDetailsView : BaseView {
|
||||
|
||||
val homeworkDeleteSuccess: String
|
||||
|
||||
fun initView()
|
||||
|
||||
fun closeDialog()
|
||||
|
||||
fun updateMarkAsDoneLabel(isDone: Boolean)
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ class LoginAdvancedFragment :
|
||||
override fun setErrorUsernameRequired() {
|
||||
with(binding.loginFormUsernameLayout) {
|
||||
requestFocus()
|
||||
error = getString(R.string.login_field_required)
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +191,7 @@ class LoginAdvancedFragment :
|
||||
override fun setErrorPassRequired(focus: Boolean) {
|
||||
with(binding.loginFormPassLayout) {
|
||||
if (focus) requestFocus()
|
||||
error = getString(R.string.login_field_required)
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ class LoginAdvancedFragment :
|
||||
override fun setErrorPinRequired() {
|
||||
with(binding.loginFormPinLayout) {
|
||||
requestFocus()
|
||||
error = getString(R.string.login_field_required)
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,7 +226,7 @@ class LoginAdvancedFragment :
|
||||
override fun setErrorSymbolRequired() {
|
||||
with(binding.loginFormSymbolLayout) {
|
||||
requestFocus()
|
||||
error = getString(R.string.login_field_required)
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,7 +240,7 @@ class LoginAdvancedFragment :
|
||||
override fun setErrorTokenRequired() {
|
||||
with(binding.loginFormTokenLayout) {
|
||||
requestFocus()
|
||||
error = getString(R.string.login_field_required)
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
||||
|
||||
override fun setErrorUsernameRequired() {
|
||||
with(binding.loginFormUsernameLayout) {
|
||||
error = getString(R.string.login_field_required)
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +141,7 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
||||
|
||||
override fun setErrorPassRequired(focus: Boolean) {
|
||||
with(binding.loginFormPassLayout) {
|
||||
error = getString(R.string.login_field_required)
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ class LoginRecoverFragment :
|
||||
override fun setErrorNameRequired() {
|
||||
with(bindingLocal.loginRecoverNameLayout) {
|
||||
requestFocus()
|
||||
error = getString(R.string.login_field_required)
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ class LoginSymbolFragment :
|
||||
override fun setErrorSymbolRequire() {
|
||||
binding.loginSymbolNameLayout.apply {
|
||||
requestFocus()
|
||||
error = getString(R.string.login_field_required)
|
||||
error = getString(R.string.error_field_required)
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user