Implemented chips for selecting dietary preferences

This commit is contained in:
denizk0461
2023-04-18 10:25:45 +02:00
parent 56cdc4c5ee
commit c385da4287
11 changed files with 299 additions and 24 deletions
@@ -15,7 +15,7 @@ class StwParser {
private var categoryId = 0
private var itemId = 0
fun parse(onFinish: () -> Unit) {
fun parse(onRefreshUpdate: (status: Int) -> Unit, onFinish: () -> Unit) {
dateId = 0
canteenId = 0
categoryId = 0
@@ -36,6 +36,7 @@ class StwParser {
// STEP: fetch every canteen
links.forEach { link ->
// TODO implement onRefresh(Int)
parseFromPage(link, Dependencies.repo)
}
}
@@ -47,10 +48,8 @@ class StwParser {
dateId = 0
val doc = Jsoup.connect(url).get()
val t = doc.getElementsByClass("pane-title")[1].text()
repo.insert(OfferCanteen(canteenId, t)) // TODO canteen name
Log.d("eek!3", t)
repo.insert(OfferCanteen(canteenId, doc.getElementsByClass("pane-title")[1].text()))
// STEP: get each day
doc.getElementsByClass("food-plan").forEach { dayPlan ->
@@ -41,6 +41,24 @@ interface EventDAO {
)
val allOffers: LiveData<List<CanteenOffer>>
@Query(
"SELECT * FROM offer_item " +
"JOIN offer_category ON offer_item.categoryId = offer_category.id " +
"JOIN offer_canteen ON offer_category.canteenId = offer_canteen.id " +
"JOIN offer_date ON offer_category.dateId = offer_date.id " +
"WHERE isFair = :isFair AND isFish = :isFish AND isPoultry = :isPoultry " +
"AND isLamb = :isLamb AND isVital = :isVital AND isBeef = :isBeef " +
"AND isPork = :isPork AND isVegan = :isVegan AND isVegetarian = :isVegetarian " +
"AND isGame = :isGame "
)
fun getOffersByPreference(
isFair: Boolean, isFish: Boolean, isPoultry: Boolean, isLamb: Boolean, isVital: Boolean,
isBeef: Boolean, isPork: Boolean, isVegan: Boolean, isVegetarian: Boolean, isGame: Boolean
): LiveData<List<CanteenOffer>>
@get:Query("SELECT id FROM offer_date")
val updateObserver: LiveData<List<Int>>
@Query("DELETE FROM offer_date")
fun nukeOfferDates()
@@ -2,11 +2,13 @@ package com.denizk0461.studip.db
import android.app.Application
import androidx.lifecycle.LiveData
import androidx.preference.PreferenceManager
import com.denizk0461.studip.model.*
class EventRepository(app: Application) {
class EventRepository(private val app: Application) {
private val dao: EventDAO = EventDatabase.getInstance(app.applicationContext).dao()
private val prefs = PreferenceManager.getDefaultSharedPreferences(app)
val allEvents: LiveData<List<StudIPEvent>> = dao.allEvents
@@ -16,6 +18,65 @@ class EventRepository(app: Application) {
val allOffers: LiveData<List<CanteenOffer>> = dao.allOffers
// is this better than List.filter?
fun getOffersByPreference(prefs: DietaryPrefObject = getDietaryPrefs()): LiveData<List<CanteenOffer>> {
return if (isPreferenceSet()) {
dao.getOffersByPreference(
isFair = prefs.isFair,
isFish = prefs.isFish,
isPoultry = prefs.isPoultry,
isLamb = prefs.isLamb,
isVital = prefs.isVital,
isBeef = prefs.isBeef,
isPork = prefs.isPork,
isVegan = prefs.isVegan,
isVegetarian = prefs.isVegetarian,
isGame = prefs.isGame,
)
} else {
dao.allOffers
}
}
private fun getDietaryPrefs(): DietaryPrefObject {
return DietaryPrefObject(
isFair = prefs.getBoolean(DietaryPreferences.FAIR.value, false),
isFish = prefs.getBoolean(DietaryPreferences.FISH.value, false),
isPoultry = prefs.getBoolean(DietaryPreferences.POULTRY.value, false),
isLamb = prefs.getBoolean(DietaryPreferences.LAMB.value, false),
isVital = prefs.getBoolean(DietaryPreferences.VITAL.value, false),
isBeef = prefs.getBoolean(DietaryPreferences.BEEF.value, false),
isPork = prefs.getBoolean(DietaryPreferences.PORK.value, false),
isVegan = prefs.getBoolean(DietaryPreferences.VEGAN.value, false),
isVegetarian = prefs.getBoolean(DietaryPreferences.VEGETARIAN.value, false),
isGame = prefs.getBoolean(DietaryPreferences.GAME.value, false),
)
}
private fun isPreferenceSet(): Boolean {
getDietaryPrefs().also { p ->
if (p.isFair) return true
if (p.isFish) return true
if (p.isPoultry) return true
if (p.isLamb) return true
if (p.isVital) return true
if (p.isBeef) return true
if (p.isPork) return true
if (p.isVegan) return true
if (p.isVegetarian) return true
if (p.isGame) return true
}
return false
}
fun setPreference(pref: DietaryPreferences, newValue: Boolean) {
prefs.edit().putBoolean(pref.value, newValue).apply()
}
fun getPreference(pref: DietaryPreferences): Boolean =
prefs.getBoolean(pref.value, false)
// fun insertOffers(offers: List<CanteenOffer>) { dao.insertOffers(offers) }
fun nukeOffers() {
dao.nukeOfferItems()
@@ -4,11 +4,14 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.children
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.denizk0461.studip.adapter.CanteenOfferPageAdapter
import com.denizk0461.studip.databinding.FragmentCanteenBinding
import com.denizk0461.studip.model.DietaryPreferences
import com.denizk0461.studip.viewmodel.CanteenViewModel
import com.google.android.material.chip.Chip
import com.google.android.material.tabs.TabLayoutMediator
class CanteenFragment : Fragment() {
@@ -32,6 +35,45 @@ class CanteenFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
/* Since this removes the view before immediately adding it back, this method causes a
* flicker. Note for the future: implement a more efficient / better-looking method.
*
* TODO order the chips alphabetically
*/
for (chip in binding.chipsPreference.children) {
val nChip = chip as Chip
nChip.setOnCheckedChangeListener { buttonView, _ ->
val index = binding.chipsPreference.indexOfChild(buttonView)
binding.chipsPreference.removeView(buttonView)
binding.chipsPreference.addView(buttonView, index)
}
}
val chipMap = mapOf<Chip, DietaryPreferences>(
binding.chipPrefFair to DietaryPreferences.FAIR,
binding.chipPrefFish to DietaryPreferences.FISH,
binding.chipPrefPoultry to DietaryPreferences.POULTRY,
binding.chipPrefLamb to DietaryPreferences.LAMB,
binding.chipPrefVital to DietaryPreferences.VITAL,
binding.chipPrefBeef to DietaryPreferences.BEEF,
binding.chipPrefPork to DietaryPreferences.PORK,
binding.chipPrefVegetarian to DietaryPreferences.VEGETARIAN,
binding.chipPrefVegan to DietaryPreferences.VEGAN,
binding.chipPrefGame to DietaryPreferences.GAME,
)
chipMap.forEach { chip, pref ->
chip.isChecked = getPreference(pref)
chip.setOnCheckedChangeListener { _, newValue ->
setPreference(pref, newValue)
}
}
binding.chipPrefFair
binding.chipPrefFair.setOnCheckedChangeListener { _, newValue ->
setPreference(DietaryPreferences.FAIR, newValue)
}
viewPagerAdapter = CanteenOfferPageAdapter(listOf(), 0)
binding.viewPager.adapter = viewPagerAdapter
@@ -49,9 +91,11 @@ class CanteenFragment : Fragment() {
}
binding.swipeRefreshLayout.setOnRefreshListener {
viewModel.fetchOffers {
viewModel.fetchOffers(onRefreshUpdate = { status ->
}, onFinish = {
// binding.swipeRefreshLayout.isRefreshing = false
}
})
}
}
@@ -67,4 +111,12 @@ class CanteenFragment : Fragment() {
super.onDestroyView()
_binding = null
}
private fun setPreference(pref: DietaryPreferences, newValue: Boolean) {
viewModel.setPreference(pref, newValue)
// notifyDataSetChanged?
}
private fun getPreference(pref: DietaryPreferences): Boolean =
viewModel.getPreference(pref)
}
@@ -0,0 +1,14 @@
package com.denizk0461.studip.model
data class DietaryPrefObject(
val isFair: Boolean,
val isFish: Boolean,
val isPoultry: Boolean,
val isLamb: Boolean,
val isVital: Boolean,
val isBeef: Boolean,
val isPork: Boolean,
val isVegan: Boolean,
val isVegetarian: Boolean,
val isGame: Boolean,
)
@@ -0,0 +1,14 @@
package com.denizk0461.studip.model
enum class DietaryPreferences(val value: String) {
FAIR("isFair"),
FISH("isFish"),
POULTRY("isPoultry"),
LAMB("isLamb"),
VITAL("isVital"),
BEEF("isBeef"),
PORK("isPork"),
VEGAN("isVegan"),
VEGETARIAN("isVegetarian"),
GAME("isGame"),
}
@@ -4,6 +4,7 @@ import android.app.Application
import androidx.lifecycle.LiveData
import com.denizk0461.studip.data.StwParser
import com.denizk0461.studip.model.CanteenOffer
import com.denizk0461.studip.model.DietaryPreferences
class CanteenViewModel(app: Application) : TemplateViewModel(app) {
@@ -11,8 +12,14 @@ class CanteenViewModel(app: Application) : TemplateViewModel(app) {
val allOffers: LiveData<List<CanteenOffer>> = repo.allOffers
fun getOffersByPreference(): LiveData<List<CanteenOffer>> =
repo.getOffersByPreference()
// fun insertOffers(offers: List<CanteenOffer>) { doAsync { repo.insertOffers(offers) }}
fun nukeOffers() { doAsync { repo.nukeOffers() }}
fun fetchOffers(onFinish: () -> Unit) { doAsync { parser.parse(onFinish) }}
fun fetchOffers(onRefreshUpdate: (status: Int) -> Unit, onFinish: () -> Unit) { doAsync { parser.parse(onRefreshUpdate, onFinish) }}
fun setPreference(pref: DietaryPreferences, newValue: Boolean) { repo.setPreference(pref, newValue) }
fun getPreference(pref: DietaryPreferences): Boolean = repo.getPreference(pref)
}