Added sorting, freshness precentage, fullscreen view for products on shelf

This commit is contained in:
leca 2024-10-17 03:01:58 +03:00
parent fd7feb72eb
commit 28da5408a1
10 changed files with 251 additions and 73 deletions

View File

@ -15,6 +15,9 @@ import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.net.URLEncoder import java.net.URLEncoder
import java.security.MessageDigest import java.security.MessageDigest
import java.time.Duration
import java.time.LocalDate
import java.time.format.DateTimeFormatter
fun getImageUri(activity: Activity, imageFile: File): Uri? { fun getImageUri(activity: Activity, imageFile: File): Uri? {
return FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + "." + activity.localClassName + ".provider", imageFile) return FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + "." + activity.localClassName + ".provider", imageFile)
@ -69,4 +72,18 @@ fun getActivity(context: Context?): Activity? {
} }
return null return null
}
@RequiresApi(Build.VERSION_CODES.O)
fun calculateProductFreshness(dateOfProduction: String, dateOfExpiry: String): Double {
val dateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("d.M.yyyy")
val fresh = LocalDate.parse(dateOfProduction, dateFormatter)
val expired = LocalDate.parse(dateOfExpiry, dateFormatter)
val shelfLife = Duration.between(fresh.atStartOfDay(), expired.atStartOfDay()).toDays()
val today = LocalDate.parse(LocalDate.now().format(dateFormatter), dateFormatter)
val daysBeforeExpiry = Duration.between(today.atStartOfDay(), expired.atStartOfDay()).toDays()
return daysBeforeExpiry / shelfLife.toDouble()
} }

View File

@ -1,7 +1,10 @@
package org.foxarmy.barcodescannerforemployees.dataclasses package org.foxarmy.barcodescannerforemployees.dataclasses
import android.os.Build
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
import androidx.annotation.RequiresApi
import org.foxarmy.barcodescannerforemployees.calculateProductFreshness
class Product() : Parcelable { class Product() : Parcelable {
var id = 0 var id = 0
@ -9,13 +12,16 @@ class Product() : Parcelable {
var amount = 0 var amount = 0
var dateOfProduction = "01.01.1970" var dateOfProduction = "01.01.1970"
var dateOfExpiry = "01.01.1970" var dateOfExpiry = "01.01.1970"
var freshness: Double = 0.0
@RequiresApi(Build.VERSION_CODES.O)
constructor(id: Int, abstractProductId: Int, amount: Int, dateOfProduction: String, dateOfExpiry: String) : this() { constructor(id: Int, abstractProductId: Int, amount: Int, dateOfProduction: String, dateOfExpiry: String) : this() {
this.id = id this.id = id
this.abstractProductId = abstractProductId this.abstractProductId = abstractProductId
this.amount = amount this.amount = amount
this.dateOfProduction = dateOfProduction this.dateOfProduction = dateOfProduction
this.dateOfExpiry = dateOfExpiry this.dateOfExpiry = dateOfExpiry
this.freshness = calculateProductFreshness(dateOfProduction, dateOfExpiry)
} }
constructor(parcel: Parcel) : this() { constructor(parcel: Parcel) : this() {
@ -24,6 +30,7 @@ class Product() : Parcelable {
amount = parcel.readInt() amount = parcel.readInt()
dateOfProduction = parcel.readString()!! dateOfProduction = parcel.readString()!!
dateOfExpiry = parcel.readString()!! dateOfExpiry = parcel.readString()!!
freshness = parcel.readDouble()
} }
override fun writeToParcel(parcel: Parcel, flags: Int) { override fun writeToParcel(parcel: Parcel, flags: Int) {
@ -32,6 +39,7 @@ class Product() : Parcelable {
parcel.writeInt(amount) parcel.writeInt(amount)
parcel.writeString(dateOfProduction) parcel.writeString(dateOfProduction)
parcel.writeString(dateOfExpiry) parcel.writeString(dateOfExpiry)
parcel.writeDouble(freshness)
} }
override fun describeContents(): Int { override fun describeContents(): Int {

View File

@ -12,10 +12,10 @@ import androidx.core.content.ContextCompat
import androidx.core.view.children import androidx.core.view.children
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import org.foxarmy.barcodescannerforemployees.CategoriesContract import org.foxarmy.barcodescannerforemployees.CategoriesContract
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
import org.foxarmy.barcodescannerforemployees.DBStorageController import org.foxarmy.barcodescannerforemployees.DBStorageController
import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.R
import org.foxarmy.barcodescannerforemployees.activities.AddCategoryActivity import org.foxarmy.barcodescannerforemployees.activities.AddCategoryActivity
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
import org.foxarmy.barcodescannerforemployees.views.CategoryView import org.foxarmy.barcodescannerforemployees.views.CategoryView
class CategoriesFragment : Fragment() { class CategoriesFragment : Fragment() {
@ -61,8 +61,6 @@ class CategoriesFragment : Fragment() {
ContextCompat.startActivity(context!!, addCategoryIntent, extras) ContextCompat.startActivity(context!!, addCategoryIntent, extras)
} }
} }
} }
fun updateContent() { fun updateContent() {

View File

@ -5,31 +5,57 @@ import android.provider.BaseColumns
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.ImageView import android.widget.ImageView
import android.widget.Toast import android.widget.Toast
import androidx.core.view.children import androidx.core.view.children
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.gridlayout.widget.GridLayout import androidx.gridlayout.widget.GridLayout
import org.foxarmy.barcodescannerforemployees.AbstractProductContract
import org.foxarmy.barcodescannerforemployees.DBStorageController import org.foxarmy.barcodescannerforemployees.DBStorageController
import org.foxarmy.barcodescannerforemployees.ProductContract import org.foxarmy.barcodescannerforemployees.ProductContract
import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.R
import org.foxarmy.barcodescannerforemployees.databinding.FragmentShelfBinding
import org.foxarmy.barcodescannerforemployees.dataclasses.Product import org.foxarmy.barcodescannerforemployees.dataclasses.Product
import org.foxarmy.barcodescannerforemployees.views.ProductView import org.foxarmy.barcodescannerforemployees.views.ProductView
import kotlin.concurrent.thread import kotlin.concurrent.thread
class ShelfFragment : Fragment() { class ShelfFragment : Fragment() {
private lateinit var binding: FragmentShelfBinding
private var updateInProgress = false
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View {
binding = FragmentShelfBinding.inflate(layoutInflater)
return inflater.inflate(R.layout.fragment_shelf, container, false) fillUpSortBySpinner()
}
override fun onCreate(savedInstanceState: Bundle?) { binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
super.onCreate(savedInstanceState) override fun onNothingSelected(parent: AdapterView<*>?) {
updateContent()
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
updateContent()
}
}
updateContent() updateContent()
return binding.root
}
private fun fillUpSortBySpinner() {
val sorts = mutableListOf("Name", "Category", "Freshness", "Date of production", "Date of expiry")
val arrayAdapter =
ArrayAdapter(requireContext(), androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, sorts)
arrayAdapter.setDropDownViewResource(androidx.appcompat.R.layout.support_simple_spinner_dropdown_item)
binding.spinner.adapter = arrayAdapter
} }
override fun onResume() { override fun onResume() {
@ -40,6 +66,8 @@ class ShelfFragment : Fragment() {
fun updateContent() { fun updateContent() {
thread { thread {
if (updateInProgress) return@thread
updateInProgress = true
val grv = view?.findViewById<GridLayout>(R.id.contentGridLayout) val grv = view?.findViewById<GridLayout>(R.id.contentGridLayout)
activity!!.runOnUiThread { activity!!.runOnUiThread {
grv?.removeAllViews() grv?.removeAllViews()
@ -54,7 +82,37 @@ class ShelfFragment : Fragment() {
ProductContract.ProductEntry.EXPIRY_DATE, ProductContract.ProductEntry.EXPIRY_DATE,
) )
val cursor = db.query(ProductContract.ProductEntry.TABLE_NAME, projection, null, null, null, null, null) var orderBy: String = ""
when (binding.spinner.selectedItem) {
"Name" -> {
orderBy =
"(SELECT ${AbstractProductContract.AbstractProductEntry.PRODUCT_NAME} FROM ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} WHERE ${BaseColumns._ID} = ${ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID}) ASC"
}
"Category" -> {
orderBy =
"(SELECT ${AbstractProductContract.AbstractProductEntry.CATEGORY} FROM ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} WHERE ${BaseColumns._ID} = ${ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID}) ASC"
}
// Wow, I wrote this on first try but unfortunately SQLite can't do that :(
// I'll leave it here as a memory.
// "Freshness" -> {
// orderBy =
// "(SELECT ( (julianday(${ProductContract.ProductEntry.EXPIRY_DATE}) - julianday('now', 'localtime')) / (julianday(${ProductContract.ProductEntry.EXPIRY_DATE}) - julianday(${ProductContract.ProductEntry.DATE_OF_PRODUCTION})) )) ASC"
// }
"Date of production" -> {
orderBy = "${ProductContract.ProductEntry.DATE_OF_PRODUCTION} ASC"
}
"Date of expiry" -> {
orderBy = "${ProductContract.ProductEntry.EXPIRY_DATE} ASC"
}
}
val cursor = db.query(ProductContract.ProductEntry.TABLE_NAME, projection, null, null, null, null, orderBy)
val products = mutableListOf<Product>()
with(cursor) { with(cursor) {
while (moveToNext()) { while (moveToNext()) {
@ -68,16 +126,34 @@ class ShelfFragment : Fragment() {
val product = Product(productId, abstractProductId, amount, dateOfProduction, dateOfExpiry) val product = Product(productId, abstractProductId, amount, dateOfProduction, dateOfExpiry)
val productView = ProductView( if (binding.spinner.selectedItem == "Freshness") {
requireActivity(), products.add(product)
requireContext(), } else {
product val productView = ProductView(
) requireActivity(),
activity!!.runOnUiThread { requireContext(),
grv?.addView(productView) product
)
activity!!.runOnUiThread {
grv?.addView(productView)
}
} }
} }
} }
products.sortWith(compareByDescending { it.freshness })
for (product in products.iterator()) {
val productView = ProductView(
requireActivity(),
requireContext(),
product
)
activity!!.runOnUiThread {
grv?.addView(productView)
}
}
updateInProgress = false
} }
} }
@ -92,7 +168,6 @@ class ShelfFragment : Fragment() {
view.findViewById<ImageView>(R.id.productPicture).setImageURI(null) view.findViewById<ImageView>(R.id.productPicture).setImageURI(null)
} }
if (view.isProductSelected) { if (view.isProductSelected) {
// db.eraseAbstractProduct(db.writableDatabase, view.abstractProduct.id, requireContext())
db.eraseProduct(db.writableDatabase, view.product.id) db.eraseProduct(db.writableDatabase, view.product.id)
deleted = true deleted = true
} }

View File

@ -3,19 +3,22 @@ package org.foxarmy.barcodescannerforemployees.fragments
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.provider.BaseColumns import android.provider.BaseColumns
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.ImageView import android.widget.ImageView
import android.widget.Toast import android.widget.Toast
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.children import androidx.core.view.children
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.gridlayout.widget.GridLayout
import org.foxarmy.barcodescannerforemployees.AbstractProductContract import org.foxarmy.barcodescannerforemployees.AbstractProductContract
import org.foxarmy.barcodescannerforemployees.DBStorageController import org.foxarmy.barcodescannerforemployees.DBStorageController
import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.R
import org.foxarmy.barcodescannerforemployees.activities.AddAbstractProductActivity import org.foxarmy.barcodescannerforemployees.activities.AddAbstractProductActivity
import org.foxarmy.barcodescannerforemployees.databinding.FragmentStorageBinding
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
import org.foxarmy.barcodescannerforemployees.generateThumbnailForImage import org.foxarmy.barcodescannerforemployees.generateThumbnailForImage
import org.foxarmy.barcodescannerforemployees.views.AbstractProductView import org.foxarmy.barcodescannerforemployees.views.AbstractProductView
@ -23,11 +26,27 @@ import kotlin.concurrent.thread
class StorageFragment : Fragment() { class StorageFragment : Fragment() {
private lateinit var binding: FragmentStorageBinding
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View {
return inflater.inflate(R.layout.fragment_storage, container, false) binding = FragmentStorageBinding.inflate(inflater)
fillUpSortBySpinner()
binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {
updateContent()
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
updateContent()
}
}
return binding.root
} }
override fun onResume() { override fun onResume() {
@ -36,20 +55,21 @@ class StorageFragment : Fragment() {
updateContent() updateContent()
} }
override fun onStop() { private fun fillUpSortBySpinner() {
super.onStop() val sorts = mutableListOf("Name", "Category")
val grv = view?.findViewById<GridLayout>(R.id.contentGridLayout) val arrayAdapter = ArrayAdapter(requireContext(), androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, sorts)
grv?.removeAllViews() arrayAdapter.setDropDownViewResource(androidx.appcompat.R.layout.support_simple_spinner_dropdown_item)
binding.spinner.adapter = arrayAdapter
} }
fun removeSelected() { fun removeSelected() {
thread { thread {
val grv = view?.findViewById<GridLayout>(R.id.contentGridLayout) val grv = binding.contentGridLayout
val db = DBStorageController(requireContext()) val db = DBStorageController(requireContext())
var deleted = false var deleted = false
for (view: AbstractProductView in grv?.children!!.iterator() as Iterator<AbstractProductView>) { for (view: AbstractProductView in grv.children.iterator() as Iterator<AbstractProductView>) {
activity!!.runOnUiThread { activity!!.runOnUiThread {
view.findViewById<ImageView>(R.id.productPicture).setImageURI(null) view.findViewById<ImageView>(R.id.productPicture).setImageURI(null)
} }
@ -69,9 +89,9 @@ class StorageFragment : Fragment() {
} }
fun updateSelected() { fun updateSelected() {
val grv = view?.findViewById<GridLayout>(R.id.contentGridLayout) val grv = binding.contentGridLayout
for (view: AbstractProductView in grv?.children!!.iterator() as Iterator<AbstractProductView>) { for (view: AbstractProductView in grv.children.iterator() as Iterator<AbstractProductView>) {
if (view.isProductSelected) { if (view.isProductSelected) {
val addProductIntent = Intent(requireContext(), AddAbstractProductActivity::class.java) val addProductIntent = Intent(requireContext(), AddAbstractProductActivity::class.java)
val extras = Bundle() val extras = Bundle()
@ -84,9 +104,9 @@ class StorageFragment : Fragment() {
fun updateContent() { fun updateContent() {
thread { thread {
val grv:GridLayout? = view?.findViewById(R.id.contentGridLayout) val grv = binding.contentGridLayout
activity!!.runOnUiThread{ activity!!.runOnUiThread{
grv?.removeAllViews() grv.removeAllViews()
} }
val db = DBStorageController(requireContext()).readableDatabase val db = DBStorageController(requireContext()).readableDatabase
@ -99,7 +119,18 @@ class StorageFragment : Fragment() {
AbstractProductContract.AbstractProductEntry.CATEGORY AbstractProductContract.AbstractProductEntry.CATEGORY
) )
val cursor = db.query(AbstractProductContract.AbstractProductEntry.TABLE_NAME, projection, null, null, null, null, null) var orderBy: String = ""
Log.d("QWERTYUIOP", binding.spinner.selectedItem.toString())
when(binding.spinner.selectedItem) {
"Name" -> {
orderBy = "${AbstractProductContract.AbstractProductEntry.PRODUCT_NAME} ASC"
}
"Category" -> {
orderBy = "${AbstractProductContract.AbstractProductEntry.CATEGORY} ASC"
}
}
val cursor = db.query(AbstractProductContract.AbstractProductEntry.TABLE_NAME, projection, null, null, null, null, orderBy)
with (cursor) { with (cursor) {
while(moveToNext()) { while(moveToNext()) {
@ -121,7 +152,7 @@ class StorageFragment : Fragment() {
) )
activity!!.runOnUiThread{ activity!!.runOnUiThread{
grv?.addView(abstractProduct) grv.addView(abstractProduct)
} }
} }
} }

View File

@ -2,11 +2,12 @@ package org.foxarmy.barcodescannerforemployees.views
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.GradientDrawable import android.graphics.drawable.GradientDrawable
import android.os.Build import android.os.Build
import android.os.Bundle
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
@ -14,20 +15,17 @@ import android.widget.TextView
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.startActivity
import androidx.core.graphics.blue import androidx.core.graphics.blue
import androidx.core.graphics.green import androidx.core.graphics.green
import androidx.core.graphics.red import androidx.core.graphics.red
import androidx.core.math.MathUtils.clamp import androidx.core.math.MathUtils.clamp
import org.foxarmy.barcodescannerforemployees.DBStorageController import org.foxarmy.barcodescannerforemployees.*
import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.activities.FullscreenActivity
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
import org.foxarmy.barcodescannerforemployees.dataclasses.Product import org.foxarmy.barcodescannerforemployees.dataclasses.Product
import org.foxarmy.barcodescannerforemployees.getActivity
import org.foxarmy.barcodescannerforemployees.getImageUri
import java.io.File import java.io.File
import java.time.Duration import java.text.DecimalFormat
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import kotlin.concurrent.thread import kotlin.concurrent.thread
class ProductView: LinearLayout { class ProductView: LinearLayout {
@ -41,6 +39,8 @@ class ProductView: LinearLayout {
private lateinit var productAmountTextView: TextView private lateinit var productAmountTextView: TextView
private lateinit var productCategoryView: TextView private lateinit var productCategoryView: TextView
private lateinit var productLifeSpan: TextView private lateinit var productLifeSpan: TextView
private lateinit var productFreshnessTextView: TextView
private var backgroundColor: Int = 0xffffff private var backgroundColor: Int = 0xffffff
private var strokeColor: Int = 0x000000 private var strokeColor: Int = 0x000000
private lateinit var outline: GradientDrawable private lateinit var outline: GradientDrawable
@ -64,6 +64,7 @@ class ProductView: LinearLayout {
productAmountTextView = findViewById(R.id.amountView) productAmountTextView = findViewById(R.id.amountView)
productCategoryView = findViewById(R.id.categoryView) productCategoryView = findViewById(R.id.categoryView)
productLifeSpan = findViewById(R.id.dateSpan) productLifeSpan = findViewById(R.id.dateSpan)
productFreshnessTextView = findViewById(R.id.freshnessPercentTextView)
findViewById<ConstraintLayout>(R.id.productLayout).setOnLongClickListener { findViewById<ConstraintLayout>(R.id.productLayout).setOnLongClickListener {
isProductSelected = !isProductSelected isProductSelected = !isProductSelected
@ -71,6 +72,15 @@ class ProductView: LinearLayout {
true true
} }
productImageView.setOnClickListener {
val fullscreenIntent = Intent(activity, FullscreenActivity::class.java)
val extras = Bundle()
val abstractProduct = DBStorageController(context).findAbstractProductById(DBStorageController(context).readableDatabase, product.abstractProductId)
extras.putString("imagehash", abstractProduct!!.imageHash)
fullscreenIntent.putExtras(extras)
startActivity(context, fullscreenIntent, extras)
}
update() update()
} }
@ -90,7 +100,12 @@ class ProductView: LinearLayout {
productAmountTextView.text = product.amount.toString() productAmountTextView.text = product.amount.toString()
productCategoryView.text = DBStorageController(activity).getCategoryNameById(DBStorageController(activity).readableDatabase, linkedAbstractProduct.category) productCategoryView.text = DBStorageController(activity).getCategoryNameById(DBStorageController(activity).readableDatabase, linkedAbstractProduct.category)
productLifeSpan.text = "${product.dateOfProduction}-${product.dateOfExpiry}" productLifeSpan.text = "${product.dateOfProduction}-${product.dateOfExpiry}"
productFreshnessTextView.text =
if (product.freshness == Double.NEGATIVE_INFINITY || product.freshness == Double.POSITIVE_INFINITY) {
"Expired"
} else {
"${DecimalFormat("#.#").format(product.freshness*100)}%"
}
updateStroke() updateStroke()
} }
@ -118,17 +133,7 @@ class ProductView: LinearLayout {
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
fun evaluateColor(): Int { fun evaluateColor(): Int {
val dateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("d.M.yyyy") val freshnessPercentage = calculateProductFreshness(product.dateOfProduction, product.dateOfExpiry)
val fresh = LocalDate.parse(product.dateOfProduction, dateFormatter)
val expired = LocalDate.parse(product.dateOfExpiry, dateFormatter)
val shelfLife = Duration.between(fresh.atStartOfDay(), expired.atStartOfDay()).toDays()
val today = LocalDate.parse(LocalDate.now().format(dateFormatter), dateFormatter)
val daysBeforeExpiry = Duration.between(today.atStartOfDay(), expired.atStartOfDay()).toDays()
val freshnessPercentage: Double = daysBeforeExpiry / shelfLife.toDouble()
return calculateFreshnessGradient(freshnessPercentage) return calculateFreshnessGradient(freshnessPercentage)
} }
@ -153,9 +158,6 @@ class ProductView: LinearLayout {
val colorString = "#$redHex$greenHex$blueHex" val colorString = "#$redHex$greenHex$blueHex"
Log.d("QWERTYUIOP", "$red:$green:$blue")
Log.d("QWERTYUIOP", "$redHex-$greenHex-$blueHex")
Log.d("QWERTYUIOP", colorString)
return Color.parseColor(colorString) return Color.parseColor(colorString)
} }
@ -166,8 +168,6 @@ class ProductView: LinearLayout {
val red = c.red() * (1 - darkPercent) val red = c.red() * (1 - darkPercent)
val green = c.green() * (1 - darkPercent) val green = c.green() * (1 - darkPercent)
val blue = c.blue() * (1 - darkPercent) val blue = c.blue() * (1 - darkPercent)
Log.d("QWERTYUIOP", "....A:${c.red()}, ${c.green()}, ${c.blue()}")
Log.d("QWERTYUIOP", "....B:${red.toFloat()}, ${green.toFloat()}, ${blue.toFloat()}")
return Color.rgb(red.toFloat(), green.toFloat(), blue.toFloat()) return Color.rgb(red.toFloat(), green.toFloat(), blue.toFloat())
} }

View File

@ -1,7 +1,7 @@
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="200dp" xmlns:tools="http://schemas.android.com/tools" android:layout_width="190dp"
android:layout_height="wrap_content" app:barrierMargin="1dp" android:clickable="false" android:layout_height="wrap_content" app:barrierMargin="1dp" android:clickable="false"
android:outlineProvider="background" android:background="@drawable/outline"> android:outlineProvider="background" android:background="@drawable/outline">

View File

@ -3,14 +3,36 @@
xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<ScrollView <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.gridlayout.widget.GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
app:rowCount="100" android:nestedScrollingEnabled="true">
</androidx.gridlayout.widget.GridLayout> <TextView
</ScrollView> android:text="Sort by"
android:layout_width="wrap_content"
android:layout_height="0dp" android:id="@+id/sortByTextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/scrollView" android:textAlignment="center"
/>
<Spinner
android:layout_width="0dp"
android:layout_height="32dp" android:id="@+id/spinner"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/sortByTextView"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginStart="16dp"
/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" app:layout_constraintTop_toBottomOf="@+id/spinner"
android:layout_marginTop="32dp" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" android:id="@+id/scrollView">
<androidx.gridlayout.widget.GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
app:rowCount="100" android:nestedScrollingEnabled="true">
</androidx.gridlayout.widget.GridLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout> </FrameLayout>

View File

@ -5,14 +5,35 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/fragment_storage" android:id="@+id/fragment_storage"
tools:context=".fragments.StorageFragment"> tools:context=".fragments.StorageFragment">
<ScrollView <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.gridlayout.widget.GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
app:rowCount="100" android:nestedScrollingEnabled="true">
</androidx.gridlayout.widget.GridLayout> <TextView
</ScrollView> android:text="Sort by"
android:layout_width="wrap_content"
android:layout_height="0dp" android:id="@+id/sortByTextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="@+id/scrollView2"/>
<Spinner
android:layout_width="0dp"
android:layout_height="32dp" android:id="@+id/spinner"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/sortByTextView"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginStart="16dp"
/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/spinner"
android:id="@+id/scrollView2">
<androidx.gridlayout.widget.GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
app:rowCount="100" android:nestedScrollingEnabled="true">
</androidx.gridlayout.widget.GridLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout> </FrameLayout>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical"
android:layout_width="200dp" android:layout_width="190dp"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
@ -14,6 +14,12 @@
android:id="@+id/productPicture" android:id="@+id/productPicture"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:text="0%"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/freshnessPercentTextView"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="10dp"
app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="5dp"/>
<TextView <TextView
android:text="@string/sample_product_name" android:text="@string/sample_product_name"
android:layout_width="match_parent" android:layout_width="match_parent"