Added sorting, freshness precentage, fullscreen view for products on shelf
This commit is contained in:
parent
fd7feb72eb
commit
28da5408a1
|
@ -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)
|
||||||
|
@ -70,3 +73,17 @@ 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()
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||||
|
updateContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
super.onCreate(savedInstanceState)
|
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,6 +126,9 @@ class ShelfFragment : Fragment() {
|
||||||
|
|
||||||
val product = Product(productId, abstractProductId, amount, dateOfProduction, dateOfExpiry)
|
val product = Product(productId, abstractProductId, amount, dateOfProduction, dateOfExpiry)
|
||||||
|
|
||||||
|
if (binding.spinner.selectedItem == "Freshness") {
|
||||||
|
products.add(product)
|
||||||
|
} else {
|
||||||
val productView = ProductView(
|
val productView = ProductView(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
requireContext(),
|
requireContext(),
|
||||||
|
@ -79,6 +140,21 @@ class ShelfFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
products.sortWith(compareByDescending { it.freshness })
|
||||||
|
|
||||||
|
for (product in products.iterator()) {
|
||||||
|
val productView = ProductView(
|
||||||
|
requireActivity(),
|
||||||
|
requireContext(),
|
||||||
|
product
|
||||||
|
)
|
||||||
|
activity!!.runOnUiThread {
|
||||||
|
grv?.addView(productView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateInProgress = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeSelected() {
|
fun removeSelected() {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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">
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,30 @@
|
||||||
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">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
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
|
<androidx.gridlayout.widget.GridLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
|
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
|
||||||
|
@ -13,4 +34,5 @@
|
||||||
|
|
||||||
</androidx.gridlayout.widget.GridLayout>
|
</androidx.gridlayout.widget.GridLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
|
@ -5,9 +5,29 @@
|
||||||
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">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
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
|
<androidx.gridlayout.widget.GridLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
|
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
|
||||||
|
@ -15,4 +35,5 @@
|
||||||
|
|
||||||
</androidx.gridlayout.widget.GridLayout>
|
</androidx.gridlayout.widget.GridLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue