commit 34571fee7169dccb5be99ce65b5de57b1a77e83c Author: hmalik144 Date: Mon Nov 4 02:01:44 2019 +1100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b75303 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..cb22ebb --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dictionaries/h_mal.xml b/.idea/dictionaries/h_mal.xml new file mode 100644 index 0000000..d9162d2 --- /dev/null +++ b/.idea/dictionaries/h_mal.xml @@ -0,0 +1,7 @@ + + + + mandetory + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..7ac24c7 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..703e5d4 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..f9d1297 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..4cf4064 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,50 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.appttude.h_mal.days_left_kotlin" + minSdkVersion 23 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.0.0' + implementation 'com.google.android.material:material:1.0.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'androidx.vectordrawable:vectordrawable:1.0.0' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'com.google.android.gms:play-services-auth:17.0.0' + implementation 'com.google.firebase:firebase-core:17.2.0' + implementation 'com.google.firebase:firebase-auth:19.1.0' + implementation 'com.google.firebase:firebase-storage:19.1.0' + implementation 'com.google.firebase:firebase-database:19.1.0' + implementation 'com.firebaseui:firebase-ui-database:1.1.1' + implementation 'com.google.firebase:firebase-functions:19.0.1' + implementation 'com.google.firebase:firebase-analytics:17.2.0' + implementation 'com.google.code.gson:gson:2.3.1' + implementation 'com.squareup.picasso:picasso:2.71828' + implementation 'androidx.annotation:annotation:1.1.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' +} + +apply plugin: 'com.google.gms.google-services' diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000..b50033b --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,69 @@ +{ + "project_info": { + "project_number": "640643168912", + "firebase_url": "https://farmr-8a496.firebaseio.com", + "project_id": "farmr-8a496", + "storage_bucket": "farmr-8a496.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:640643168912:android:34c3a70dd882364a", + "android_client_info": { + "package_name": "com.appttude.h_mal.days_left" + } + }, + "oauth_client": [ + { + "client_id": "640643168912-0ssmglfad3vi7f6pok33rrjalm5phlq4.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyA4PcycGfWC3SBUxWqK2qMr9bEpwB3SWaY" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "640643168912-0ssmglfad3vi7f6pok33rrjalm5phlq4.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:640643168912:android:ef74534912ef190a2bb615", + "android_client_info": { + "package_name": "com.appttude.h_mal.days_left_kotlin" + } + }, + "oauth_client": [ + { + "client_id": "640643168912-0ssmglfad3vi7f6pok33rrjalm5phlq4.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyA4PcycGfWC3SBUxWqK2qMr9bEpwB3SWaY" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "640643168912-0ssmglfad3vi7f6pok33rrjalm5phlq4.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/appttude/h_mal/days_left_kotlin/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/appttude/h_mal/days_left_kotlin/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..d7b766e --- /dev/null +++ b/app/src/androidTest/java/com/appttude/h_mal/days_left_kotlin/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.appttude.h_mal.days_left_kotlin + +import androidx.test.InstrumentationRegistry +import androidx.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getTargetContext() + assertEquals("com.appttude.h_mal.days_left_kotlin", appContext.packageName) + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..1cda917 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AbnListAdapter.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AbnListAdapter.kt new file mode 100644 index 0000000..b399193 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AbnListAdapter.kt @@ -0,0 +1,29 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import com.appttude.h_mal.days_left_kotlin.Objects.AbnObject +import kotlinx.android.synthetic.main.abn_list_item.view.* + +class AbnListAdapter(context: Context, objects: List) : + ArrayAdapter(context, 0, objects){ + + + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + var view: View? = convertView + if (view == null) { + view = LayoutInflater.from(context).inflate(R.layout.abn_list_item, parent, false)!! + } + + val currentObject = getItem(position) + + view.farm_name.text = currentObject?.companyName + view.abn_text.text = currentObject?.abn + view.postcode_text.text = currentObject?.postCode.toString() + + return view + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddEmployerFragment.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddEmployerFragment.kt new file mode 100644 index 0000000..34e1a54 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddEmployerFragment.kt @@ -0,0 +1,134 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.content.Context +import android.net.Uri +import android.os.Bundle +import android.util.Log +import android.view.* +import android.view.inputmethod.InputMethodManager +import android.widget.* +import androidx.fragment.app.Fragment +import com.appttude.h_mal.days_left_kotlin.Objects.AbnObject +import com.google.android.gms.tasks.Task +import com.google.firebase.functions.FirebaseFunctions +import com.google.firebase.functions.FirebaseFunctionsException +import com.google.gson.Gson +import com.google.gson.JsonObject +import kotlinx.android.synthetic.main.activity_add_item.* +import kotlinx.android.synthetic.main.fragment_add_employer.* +import org.json.JSONArray +import java.util.HashMap +import androidx.core.content.ContextCompat.getSystemService + + + +class AddEmployerFragment : Fragment() { + val TAG = "AddEmployer" + + lateinit var searchView: SearchView + lateinit var mFunctions: FirebaseFunctions + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mFunctions = FirebaseFunctions.getInstance() + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + setHasOptionsMenu(true) + + return inflater.inflate(R.layout.fragment_add_employer, container, false) + } + + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + inflater?.inflate(R.menu.menu_search, menu) + val searchItem = menu?.findItem(R.id.app_bar_search) + + searchView = searchItem?.actionView as SearchView + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener{ + override fun onQueryTextChange(newText: String?): Boolean { + return true + } + + override fun onQueryTextSubmit(query: String?): Boolean { + val imm = activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(view?.getWindowToken(), 0) + + query?.let { + abnLookUp(it).addOnCompleteListener{ task -> + spinning_pb.visibility = View.GONE + if (task.isSuccessful){ + val jsonArray = task.result + var abnList = ArrayList() + + jsonArray?.let { + for (i in 0 until it.size){ + + val item = hashIntoObj(it.get(i) as Map) +// val abnobj = item.values as AbnObject + abnList.add(item) + } + } + + if (abnList.size > 0){ + list_view.adapter = AbnListAdapter(context!!, abnList) + empty_list.visibility = View.GONE + }else{ + empty_list.visibility = View.VISIBLE + } + + }else{ + val e = task.exception + if (e is FirebaseFunctionsException) { + val ffe = e as FirebaseFunctionsException? + val code = ffe!!.code + val details = ffe.details as String + + Log.e(code.toString(),details) + } + + Log.w(TAG, "addMessage:onFailure", e) + Toast.makeText(context, "An error occurred.", Toast.LENGTH_SHORT).show() + } + } + } + + return true + } + }) + super.onCreateOptionsMenu(menu, inflater) + } + + fun abnLookUp(input : String) : Task> { + spinning_pb.visibility = View.VISIBLE + // Create the arguments to the callable function. + val data = HashMap() + data["input"] = input + data["push"] = true + + return mFunctions + .getHttpsCallable("abnLooKUp") + .call(data) + .continueWith{ task -> + // This continuation runs on either success or failure, but if the task + // has failed then getResult() will throw an Exception which will be + // propagated down. + val result = task.result?.data as ArrayList<*> + + Log.i(TAG, "then: " + result.toString()) + + result + } + } + + fun hashIntoObj(map: Map): AbnObject { + val abn = map.getValue("abn") as String + val companyName = map.getValue("companyName") as String + val postCode = map.getValue("postCode") as Int + val state = map.getValue("state") as String + + return AbnObject(abn, companyName, postCode, state) + } +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddItemActivity.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddItemActivity.kt new file mode 100644 index 0000000..6f0545b --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddItemActivity.kt @@ -0,0 +1,47 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.content.DialogInterface +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import androidx.appcompat.app.AlertDialog +import com.appttude.h_mal.days_left_kotlin.AddShiftActivity.Companion.EMPLOYERREQUEST +import com.appttude.h_mal.days_left_kotlin.AddShiftActivity.Companion.REQUEST +import com.appttude.h_mal.days_left_kotlin.AddShiftActivity.Companion.TASK_CONSTANT +import kotlinx.android.synthetic.main.activity_add_item.* + +class AddItemActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_add_item) + + setSupportActionBar(toolbar) + + val requestCode = intent.getIntExtra(REQUEST, EMPLOYERREQUEST) + + if (requestCode == EMPLOYERREQUEST) { + supportFragmentManager.beginTransaction().replace(R.id.container, AddEmployerFragment()).addToBackStack("Employer").commit() + } else { + val taskObject = intent.getSerializableExtra(TASK_CONSTANT) + val addTaskFragment = AddTaskFragment() + if (taskObject != null) { + val bundle = Bundle() + bundle.putSerializable(TASK_CONSTANT, taskObject) + addTaskFragment.arguments = bundle + } + supportFragmentManager.beginTransaction().replace(R.id.container, addTaskFragment).addToBackStack("Task").commit() + } + } + + override fun onBackPressed() { + + AlertDialog.Builder(this) + .setTitle("Leave?") + .setMessage("Are you sure you return to previous?") + .setNegativeButton(android.R.string.no, null) + .setPositiveButton(android.R.string.yes, DialogInterface.OnClickListener { + arg0, arg1 -> finish() }) + .create().show() + + } +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddShiftActivity.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddShiftActivity.kt new file mode 100644 index 0000000..54083c4 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddShiftActivity.kt @@ -0,0 +1,585 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.app.AlertDialog +import android.content.Context +import android.content.DialogInterface +import android.content.Intent +import android.graphics.Typeface +import android.os.Build +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.text.TextUtils +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.animation.AnimationUtils +import android.widget.* +import androidx.cardview.widget.CardView +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.EMPLOYER_FIREBASE +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.PIECE +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.SHIFT_FIREBASE +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.SHIFT_ID +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.TASK_FIREBASE +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.USER_FIREBASE +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.auth +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.mDatabase +import com.appttude.h_mal.days_left_kotlin.Objects.AbnObject +import com.appttude.h_mal.days_left_kotlin.Objects.ShiftObject +import com.appttude.h_mal.days_left_kotlin.Objects.TaskObject +import com.appttude.h_mal.days_left_kotlin.Objects.TimeObject +import com.google.android.gms.tasks.Task +import com.google.firebase.database.DataSnapshot +import com.google.firebase.database.DatabaseError +import com.google.firebase.database.DatabaseReference +import com.google.firebase.database.ValueEventListener +import kotlinx.android.synthetic.main.activity_add_shift.* +import kotlinx.android.synthetic.main.activity_add_shift.date +import kotlinx.android.synthetic.main.activity_add_shift.search_button +import kotlinx.android.synthetic.main.activity_add_shift.units +import kotlinx.android.synthetic.main.dialog_previous_abns_used.* +import kotlinx.android.synthetic.main.dialog_previous_abns_used.view.* +import kotlinx.android.synthetic.main.fragment_add_task.* +import java.sql.Time +import java.text.SimpleDateFormat +import java.util.* +import kotlin.collections.ArrayList +import kotlinx.android.synthetic.main.list_item.time as time1 + +class AddShiftActivity : AppCompatActivity() { + companion object{ + val EMPLOYERREQUEST = 339 + val TASKREQUEST = 445 + val REQUEST = "request" + val EMPLOYER_CONSTANT = "employer" + val TASK_CONSTANT = "task" + } + + var timeObject: TimeObject? = null + var abnObject: AbnObject? = null + var taskObject: TaskObject? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_add_shift) + + select_employer_card.setOnClickListener(employerListener) + select_task_card.setOnClickListener(taskListener) + select_times_card.setOnClickListener{ + val timeDialogClass = TimeDialogClass(this@AddShiftActivity) + timeDialogClass.create()?.show() + } + + date.isFocusable = false + date.setOnClickListener { + lateinit var dateDialog: DateDialog + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + dateDialog = DateDialog(date, this@AddShiftActivity) + dateDialog.show() + } + + } + + search_button.setOnClickListener(submitListener) + + intent.getStringExtra(SHIFT_ID)?.let { + progress_bar.visibility = View.VISIBLE + + mDatabase.child(USER_FIREBASE).child(auth.uid!!).child(SHIFT_FIREBASE).child(it) + .addListenerForSingleValueEvent(object : ValueEventListener{ + override fun onCancelled(p0: DatabaseError) { + progress_bar.visibility = View.GONE + } + + override fun onDataChange(dataSnapshot: DataSnapshot) { + progress_bar.visibility = View.GONE + val shiftObject:ShiftObject? = dataSnapshot.getValue(ShiftObject::class.java) + + shiftObject?.let {shift -> + abnObject = shift.abnObject + taskObject = shift.taskObject + + shift.timeObject?.timeIn?.let { + timeObject = shift.timeObject + setTimeSummary() + Toast.makeText(baseContext,"toasted",Toast.LENGTH_SHORT) + } + + if (shift.taskObject?.workType.equals(PIECE)) { + units.setText(shift.unitsCount.toString()) + } + + date.setText(shiftObject.shiftDate) + + setTaskCard() + setEmployerCard() + } + } + }) + } + } + + internal val submitListener: View.OnClickListener = View.OnClickListener { + if (timeObject == null){ + + Toast.makeText(baseContext,"Time information missing",Toast.LENGTH_SHORT).show() + return@OnClickListener + } + if (abnObject == null){ + + Toast.makeText(baseContext,"Employer information missing",Toast.LENGTH_SHORT).show() + return@OnClickListener + } + if (taskObject == null){ + + Toast.makeText(baseContext,"Task information missing",Toast.LENGTH_SHORT).show() + return@OnClickListener + } + if (date.text.isBlank()){ + + Toast.makeText(baseContext,"Date missing",Toast.LENGTH_SHORT).show() + return@OnClickListener + } + if (taskObject?.workType == PIECE && units.text.isEmpty()){ + + Toast.makeText(baseContext,"Units information missing",Toast.LENGTH_SHORT).show() + return@OnClickListener + } + + var shiftobj = ShiftObject() + + shiftobj.abnObject = abnObject + shiftobj.taskObject = taskObject as TaskObject + shiftobj.timeObject = timeObject as TimeObject + shiftobj.shiftDate = date.text.toString() + shiftobj.dateTimeAdded = getDateTimeString() + shiftobj.unitsCount = units.text.toString().toFloat() + + val shiftReference: DatabaseReference + val ShiftID = intent.getStringExtra(SHIFT_ID) + + if (ShiftID != null) { + shiftReference = mDatabase.child(USER_FIREBASE).child(auth.uid!!).child(SHIFT_FIREBASE).child(ShiftID) + //Updating a shift + } else { + shiftReference = mDatabase.child(USER_FIREBASE).child(auth.uid!!).child(SHIFT_FIREBASE).push() + //Pushing a brand new shift + } + + progress_bar.visibility = View.VISIBLE + shiftReference.setValue(shiftobj).addOnCompleteListener{task -> + Log.i("Firebase", "onComplete: " + task.getResult()!!) + if (task.isSuccessful()) { + finish() + }else{ + Toast.makeText(baseContext,"Could not submit shift", Toast.LENGTH_SHORT).show() + } + progress_bar.visibility = View.GONE + } + } + + internal var employerListener: View.OnClickListener = View.OnClickListener { + progress_bar.visibility = (View.VISIBLE) + + turnShiftsIntoRecentlyUsed().let { + if (it.isNotEmpty()){ + val dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_previous_abns_used, null) + + val abnListAdapter = AbnListAdapter(this, it) + + dialogView.list_item_list_dialog.setAdapter(abnListAdapter) + + val builder = AlertDialog.Builder(this) + builder.setView(dialogView) + + val alertDialog = builder.create() + alertDialog.show() + + dialogView.button_list_dialog.setOnClickListener(View.OnClickListener { + startActivity() + alertDialog.dismiss() + }) + + dialogView.list_item_list_dialog.setOnItemClickListener(AdapterView.OnItemClickListener { parent, view, position, id -> + abnObject = it.get(position) + setEmployerCard() + alertDialog.dismiss() + }) + progress_bar.setVisibility(View.GONE) + }else{ + startActivity() + } + } + } + + internal var taskListener: View.OnClickListener = View.OnClickListener { + progress_bar.visibility = (View.VISIBLE) + + val cont: Context = this + + if (abnObject != null) { + mDatabase.child(EMPLOYER_FIREBASE).child(abnObject!!.abn!!).child(TASK_FIREBASE) + .addListenerForSingleValueEvent(object : ValueEventListener{ + override fun onCancelled(p0: DatabaseError) { + + } + + override fun onDataChange(p0: DataSnapshot) { + var list = ArrayList() + p0.exists().let { + + for (snapshot in p0.children){ + list.add(snapshot.getValue(TaskObject::class.java)!!) + } + } + + val dialogView = LayoutInflater.from(cont).inflate(R.layout.dialog_previous_abns_used, null) + + val dialogListAdapter = DialogListAdapter(cont, list) + dialogView.list_item_list_dialog.setAdapter(dialogListAdapter) + + val builder = AlertDialog.Builder(cont) + builder.setView(dialogView) + + val alertDialog = builder.create() + alertDialog.show() + + dialogView.button_list_dialog.setOnClickListener(View.OnClickListener { + val intent = Intent(cont, AddItemActivity::class.java) + intent.putExtra(REQUEST, TASKREQUEST) + startActivityForResult(intent, TASKREQUEST) + alertDialog.dismiss() + }) + + dialogView.list_item_list_dialog.setOnItemClickListener(AdapterView.OnItemClickListener { parent, view, position, id -> + taskObject = list.get(position) + setTaskCard() + alertDialog.dismiss() + }) + progress_bar.setVisibility(View.GONE) + } + }) + } else { + val intent = Intent(this@AddShiftActivity, AddItemActivity::class.java) + intent.putExtra(REQUEST, TASKREQUEST) + taskObject?.let { + intent.putExtra(TASK_CONSTANT, it) + } + startActivityForResult(intent, TASKREQUEST) + } + } + + fun setEmployerCard() { + if (lable_1.visibility == View.VISIBLE) { + toggleViewVisibility(select_employer_card) + } + + employer_name.text = abnObject?.companyName + val loc = abnObject?.state + " " + abnObject?.postCode + employer_location.text = loc + } + + fun setTaskCard() { + if (lable_2.getVisibility() == View.VISIBLE) { + toggleViewVisibility(select_task_card) + } + + task.text = taskObject?.task + + var summary = taskObject?.workType + " - $" + taskObject?.rate + " /" + if (taskObject?.workType.equals("Piece Rate")) { + summary = summary + "Unit" + + units.visibility = View.VISIBLE + select_times_card.visibility = (View.VISIBLE) + } else { + summary = summary + "Hour" + + units.visibility = View.GONE + select_times_card.visibility = (View.VISIBLE) + } + + task_summary.setText(summary) + } + + private fun toggleViewVisibility(cardView: CardView) { + when (cardView.getId()) { + R.id.select_employer_card -> { + setVisibility(employer_layout) + setVisibility(lable_1) + } + R.id.select_task_card -> { + setVisibility(task_layout) + setVisibility(lable_2) + } + R.id.select_times_card -> { + setVisibility(time_layout) + setVisibility(lable_3) + } + } + + } + + private fun setVisibility (view: View) { + val vis: Int + if (view.visibility == View.VISIBLE) { + vis = View.GONE + } else { + vis = View.VISIBLE + } + + view.visibility = vis + } + + private fun turnShiftsIntoRecentlyUsed() : List{ + val uniqueList = mutableMapOf() + MainActivity.shiftList.forEach { + uniqueList.put(it.abnObject?.abn!!, it.abnObject!!) + } + + return uniqueList.values.toList() + } + + private fun startActivity() { + val intent = Intent(this, AddItemActivity::class.java) + intent.putExtra(REQUEST, EMPLOYERREQUEST) + startActivityForResult(intent, EMPLOYERREQUEST) + } + + internal inner class TimeDialogClass(context: Context?) : + AlertDialog.Builder(context) { + + private var timePickerTimePicker: TimePicker? = null + private var startTimeTextView: TextView? = null + private var finishTimeTextView: TextView? = null + private var breakEditText: EditText? = null + + private var currentTag: String? = null + private var alertDialog: AlertDialog? = null + private var breakInt: Int = 0 + + + var timeSelect: View.OnClickListener = View.OnClickListener { v -> + + currentTag = v.tag as String + val timeString: String? + + if (currentTag == "start") { + timeString = timeObject?.timeIn + toggleTextButtons(true) + + } else { + timeString = timeObject?.timeOut + toggleTextButtons(false) + } + + if (timeString != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + timePickerTimePicker!!.hour = getTime(timeString)[0] + timePickerTimePicker!!.minute = getTime(timeString)[1] + } + } else { + val calendar = Calendar.getInstance() + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + timePickerTimePicker!!.hour = calendar.get(Calendar.HOUR_OF_DAY) + timePickerTimePicker!!.minute = calendar.get(Calendar.MINUTE) + } + + } + } + + init { + if (timeObject?.timeIn == null && timeObject?.timeOut == null){ + timeObject = TimeObject() + } + + setView(null) + } + + override fun setView(view: View?): AlertDialog.Builder { + val view = View.inflate(context, R.layout.dialog_add_times, null) + + currentTag = "start" + + startTimeTextView = view!!.findViewById(R.id.from_date) + finishTimeTextView = view.findViewById(R.id.to_date) + timePickerTimePicker = view.findViewById(R.id.time_picker) + breakEditText = view.findViewById(R.id.breaktime) + val okText: TextView = view.findViewById(R.id.ok) + + timePickerTimePicker!!.setIs24HourView(true) + + initialiseTime() + + okText.setOnClickListener { + if (timeObject?.timeIn != null && timeObject?.timeOut != null) { + timeObject?.hours = calculateDuration() + timeObject?.breakEpoch = breakInt + + Toast.makeText(context, convertTimeFloat(timeObject?.hours!!), Toast.LENGTH_SHORT).show() + + if (lable_3.visibility == View.VISIBLE) { + toggleViewVisibility(select_times_card) + } + + time.text = convertTimeFloat(timeObject?.hours!!) + + setTimeSummary() + } + + alertDialog!!.dismiss() + } + + breakEditText!!.setText(timeObject?.breakEpoch.toString()) + + startTimeTextView!!.tag = "start" + finishTimeTextView!!.tag = "finish" + + startTimeTextView!!.setOnClickListener(timeSelect) + finishTimeTextView!!.setOnClickListener(timeSelect) + + timePickerTimePicker!!.setOnTimeChangedListener{view, hourOfDay, minute -> + val ddTime = String.format("%02d", hourOfDay) + ":" + String.format("%02d", minute) + + if (currentTag == "start") { + timeObject!!.timeIn = ddTime + } else { + timeObject!!.timeOut = ddTime + } + } + toggleTextButtons(true) + + return super.setView(view) + } + + override fun create(): AlertDialog? { + alertDialog = super.create() + + return alertDialog + } + + override fun setNegativeButton(textId: Int, listener: DialogInterface.OnClickListener): AlertDialog.Builder { + return super.setNegativeButton( + android.R.string.cancel + ) { dialog, which -> dialog.dismiss() } + } + + private fun getTime(s: String): IntArray { + + return intArrayOf(Integer.parseInt(s.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0]), + Integer.parseInt(s.split( + ":".toRegex() + ).dropLastWhile { it.isEmpty() }.toTypedArray()[1] + ) + ) + } + + private fun initialiseTime(){ + val timeString = timeObject?.timeIn + + if (timeString != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + timePickerTimePicker!!.hour = getTime(timeString)[0] + timePickerTimePicker!!.minute = getTime(timeString)[1] + } + } else { + val calendar = Calendar.getInstance() + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + timePickerTimePicker!!.hour = calendar.get(Calendar.HOUR_OF_DAY) + timePickerTimePicker!!.minute = calendar.get(Calendar.MINUTE) + } + + } + } + + private fun calculateDuration(): Float { + val startTime = timeObject?.timeIn + val finishTime = timeObject?.timeOut + val breakText = breakEditText!!.text.toString().trim { it <= ' ' } + + val hoursIn = getTime(startTime!!)[0] + val hoursOut = getTime(finishTime!!)[0] + val minutesIn = getTime(startTime)[1] + val minutesOut = getTime(finishTime)[1] + + breakInt = 0 + if (!TextUtils.isEmpty(breakText)) { + breakInt = Integer.parseInt(breakText) + } + val duration: Float + + if (hoursOut > hoursIn) { + duration = + hoursOut.toFloat() + minutesOut.toFloat() / 60 - (hoursIn.toFloat() + minutesIn.toFloat() / 60) - breakInt.toFloat() / 60 + } else { + duration = + hoursOut.toFloat() + minutesOut.toFloat() / 60 - (hoursIn.toFloat() + minutesIn.toFloat() / 60) - breakInt.toFloat() / 60 + 24 + } + + val s = String.format("%.2f", duration) + return java.lang.Float.parseFloat(s) + } + + private fun toggleTextButtons(top: Boolean) { + setFadeAnimation(startTimeTextView!!) + setFadeAnimation(finishTimeTextView!!) + + if (top) { + startTimeTextView!!.setTypeface(null, Typeface.BOLD) + finishTimeTextView!!.setTypeface(null, Typeface.NORMAL) + + startTimeTextView!!.setBackgroundColor(context.resources.getColor(R.color.one)) + finishTimeTextView!!.setBackgroundColor(context.resources.getColor(android.R.color.white)) + } else { + finishTimeTextView!!.setTypeface(null, Typeface.BOLD) + startTimeTextView!!.setTypeface(null, Typeface.NORMAL) + + finishTimeTextView!!.setBackgroundColor(context.resources.getColor(R.color.one)) + startTimeTextView!!.setBackgroundColor(context.resources.getColor(android.R.color.white)) + } + } + + private fun setFadeAnimation(view: View) { + val bottomUp = AnimationUtils.loadAnimation( + context, + R.anim.fade_in + ) + + view.animation = bottomUp + } + + + } + + private fun convertTimeFloat(timeIn: Float): String { + val hour = timeIn.toInt() + val minutes = (timeIn - hour).toInt() * 60 + + return hour.toString() + "hours " + minutes.toString() + "mins" + } + + private fun setTimeSummary() { + if (lable_3.visibility == View.VISIBLE) { + toggleViewVisibility(select_times_card) + } + + val s = timeObject?.timeIn + " - " + timeObject?.timeOut + time_summary.text = s + if (timeObject!!.breakEpoch > 0) { + break_holder.visibility = View.VISIBLE + break_summary.text = timeObject!!.breakEpoch.toString() + " minutes" + } else { + break_holder.visibility = View.GONE + } + + time.setText(convertTimeFloat(timeObject!!.hours)) + } + + fun getDateTimeString(): String { + val cal = Calendar.getInstance() + val sdf = SimpleDateFormat("dd/MM/yyyy hh:mm:ss", Locale.ENGLISH) + + return sdf.format(cal.time) + } +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddTaskFragment.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddTaskFragment.kt new file mode 100644 index 0000000..54a61ad --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/AddTaskFragment.kt @@ -0,0 +1,255 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.app.Activity +import android.app.AlertDialog +import android.content.Context +import android.content.DialogInterface +import android.content.Intent +import android.graphics.Color +import android.net.Uri +import android.os.Bundle +import android.text.TextUtils +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup +import android.widget.* +import com.appttude.h_mal.days_left_kotlin.AddShiftActivity.Companion.TASK_CONSTANT +import com.appttude.h_mal.days_left_kotlin.Objects.TaskObject +import kotlinx.android.synthetic.main.fragment_add_task.* +import java.lang.Float + +class AddTaskFragment : Fragment() { + lateinit var taskList: Array + lateinit var strings: Array + lateinit var workTypeArray: Array + var current = "" + var previous = "" + var product = "" + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + initialiseArrayString() + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + + return inflater.inflate(R.layout.fragment_add_task, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + if (arguments != null) { + val bundle = arguments + val taskObject = bundle?.getSerializable(TASK_CONSTANT) as TaskObject + spinner_one.setSelection(getSpinnerOneSelection(taskObject.workType!!)) + pay_rate.setText(taskObject.rate.toString()) + spinner_Two.setSelection(getSpinnerTwoSelection(taskObject.task!!)) + } + + setupSpinnerOne() + setupSpinnerTwo() + + search_button.setOnClickListener(submit) + } + + private fun initialiseArrayString() { + taskList = resources.getStringArray(R.array.task_list) + strings = arrayOf(taskList[0], taskList[1] + product, taskList[2], taskList[3]) + } + + private fun setupSpinnerOne() { + workTypeArray = resources.getStringArray(R.array.work_type) + val spinnerArrayAdapter = object : ArrayAdapter( + context, android.R.layout.simple_spinner_item, + workTypeArray + ) { + override fun isEnabled(position: Int): Boolean { + return position != 0 + } + + override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { + val view = super.getDropDownView(position, convertView, parent) + val tv = view as TextView + if (position == 0) { + // Set the hint text color gray + tv.setTextColor(Color.GRAY) + } else { + tv.setTextColor(Color.BLACK) + } + return view + } + + + } + spinnerArrayAdapter.setDropDownViewResource( + android.R.layout + .simple_spinner_dropdown_item + ) + spinner_one.adapter = spinnerArrayAdapter + spinner_one.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { + when (position) { + 1 -> unit_text.text = "per Unit" + 2 -> unit_text.text = "per Hour" + else -> { + } + } + } + + override fun onNothingSelected(parent: AdapterView<*>) { + + } + } + } + + private fun setupSpinnerTwo() { + val spinnerArrayAdapter = object : ArrayAdapter( + context, android.R.layout.simple_spinner_item, + strings + ) { + override fun isEnabled(position: Int): Boolean { + return position != 0 + } + + override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { + val view = super.getDropDownView(position, convertView, parent) + val tv = view as TextView + if (position == 0) { + tv.setTextColor(Color.GRAY) + } else { + tv.setTextColor(Color.BLACK) + } + return view + } + } + spinnerArrayAdapter.setDropDownViewResource( + android.R.layout + .simple_spinner_dropdown_item + ) + spinner_Two.adapter = spinnerArrayAdapter + + val listener = SpinnerInteractionListener() + + spinner_Two.onItemSelectedListener = listener + spinner_Two.setOnTouchListener(listener) + } + + inner class SpinnerInteractionListener : AdapterView.OnItemSelectedListener, View.OnTouchListener { + + internal var userSelect = false + + override fun onTouch(v: View, event: MotionEvent): Boolean { + userSelect = true + return false + } + + override fun onItemSelected(parent: AdapterView<*>, view: View, pos: Int, id: Long) { + if (userSelect) { + Toast.makeText(context, "current = $pos", Toast.LENGTH_SHORT).show() + + previous = current + current = parent.getItemAtPosition(pos) as String + + if (pos == 1) { + val edittext = EditText(context) + edittext.hint = "Product Harvested?" + val builder = AlertDialog.Builder(context) + builder.setView(edittext) + builder.setNegativeButton(android.R.string.cancel) { dialog, which -> + spinner_Two.setSelection(getPosition(previous)) + dialog.dismiss() + }.setPositiveButton(android.R.string.ok) { dialog, which -> + val text = edittext.text.toString() + if (!TextUtils.isEmpty(text)) { + product = " $text" + initialiseArrayString() + setupSpinnerTwo() + spinner_Two.setSelection(1) + } + dialog.dismiss() + }.setOnCancelListener { + + } + builder.setCancelable(false).create().show() + } + + userSelect = false + } + } + + override fun onNothingSelected(parent: AdapterView<*>) { + + } + + } + + internal var submit: View.OnClickListener = View.OnClickListener { + val workType = spinner_one.selectedItem as String + var rate = pay_rate.text.toString().trim({ it <= ' ' }) + val task = spinner_Two.selectedItem as String + if (workType != strings[0] && + !TextUtils.isEmpty(rate) && + task != taskList[0] + ) { + if ((spinner_Two.selectedItem as String).contains(workTypeArray[1]) && task == workTypeArray[1]) { + Toast.makeText(context, "Insert A product Harvested", Toast.LENGTH_SHORT).show() + } else { + rate = String.format("%.2f", java.lang.Float.valueOf(rate)) + val taskObject = TaskObject(workType, Float.valueOf(rate), task) + + val returnIntent = Intent() + returnIntent.putExtra("TaskObject", taskObject) + activity?.setResult(Activity.RESULT_OK, returnIntent) + activity?.finish() + } + + } else { + Toast.makeText(context, "Insert All Required data", Toast.LENGTH_SHORT).show() + } + } + + private fun getSpinnerOneSelection(s: String): Int { + return when (s) { + "Hourly" -> 1 + "Piece Rate" -> 2 + else -> { + 0 + } + } + } + + private fun getSpinnerTwoSelection(s: String): Int { + val strings = resources.getStringArray(R.array.task_list) + var i = 1 + for (string in strings) { + + if (s.contains(string)) { + return i + } + i++ + } + + return 0 + } + + private fun getPosition(previous: String?): Int { + var i = 0 + if (previous != null) { + for (s in strings) { + if (previous.contains(s)) { + break + } + i++ + + } + } + + return i + } +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/ArcAnimation.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/ArcAnimation.kt new file mode 100644 index 0000000..0c17ada --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/ArcAnimation.kt @@ -0,0 +1,17 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.view.animation.Animation +import android.view.animation.Transformation + +class ArcAnimation(val arcView: CircleView, val newAngle : Float) : Animation(){ + + var oldAngle: Float = arcView.getArcAngle() + + override fun applyTransformation(interpolatedTime: Float, t: Transformation?) { + super.applyTransformation(interpolatedTime, t) + val angle = 0 + (newAngle - oldAngle) * interpolatedTime + + arcView.setArcAngle(angle) + arcView.requestLayout() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/BarAnimation.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/BarAnimation.kt new file mode 100644 index 0000000..2c1bfaa --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/BarAnimation.kt @@ -0,0 +1,16 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.view.animation.Animation +import android.view.animation.Transformation + +class BarAnimation(val barView: BarView, val targetWidth: Int, val startWidth : Int) : Animation(){ + + override fun applyTransformation(interpolatedTime: Float, t: Transformation?) { + super.applyTransformation(interpolatedTime, t) + + val newWidth = (startWidth + targetWidth * interpolatedTime).toInt() + + barView.getLayoutParams().width = newWidth + barView.requestLayout() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/BarView.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/BarView.kt new file mode 100644 index 0000000..c8bf513 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/BarView.kt @@ -0,0 +1,82 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.RectF +import android.util.AttributeSet +import android.view.View + +class BarView(context: Context?, attrs: AttributeSet?) : View(context, attrs){ + + private var topRect: RectF = RectF() + private var bottomRect: RectF = RectF() + private var hardEdge: RectF = RectF() + + private var colourOne: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private var colourTwo: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + + private var cover:Float + + init { + colourOne.color = Color.BLUE + colourTwo.color = Color.GREEN + cover = 0.toFloat() + } + + override fun onDraw(canvas: Canvas?) { + super.onDraw(canvas) + + topRect.centerX() + topRect.centerY() + topRect.left = 0f + topRect.top = 0f + topRect.right = width.toFloat() + topRect.bottom = height.toFloat() + + canvas?.drawRoundRect(topRect, 20f, 20f, colourOne) + + bottomRect.centerX() + bottomRect.centerY() + if (cover < 0.05f) { + cover = 0.05f + } + bottomRect.left = (width - 20) * cover + bottomRect.top = 0f + bottomRect.right = width.toFloat() + bottomRect.bottom = height.toFloat() + + canvas?.drawRoundRect(bottomRect, 20f, 20f, colourTwo) + + hardEdge.centerX() + hardEdge.centerY() + hardEdge.top = bottomRect.top + hardEdge.bottom = bottomRect.bottom + + hardEdge.left = bottomRect.left + hardEdge.right = hardEdge.left + 60 + + canvas?.drawRoundRect(hardEdge, 0f, 0f, colourTwo) + } + + fun getCover(): Float { + return cover + } + + fun setCover(cover: Float) { + this.cover = cover + } + + fun setCover(total: Float, number: Float) { + this.cover = number / total + } + + fun setColourOne(colour: Int) { + colourOne.color = colour + } + + fun setColourTwo(colour: Int) { + colourTwo.color = colour + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/ChangeUserDetailsActivity.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/ChangeUserDetailsActivity.kt new file mode 100644 index 0000000..6ebad01 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/ChangeUserDetailsActivity.kt @@ -0,0 +1,175 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.app.AlertDialog +import android.content.DialogInterface +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.text.InputType +import android.text.TextUtils +import android.util.Log +import android.widget.EditText +import android.widget.LinearLayout +import android.widget.Toast +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.auth +import com.google.android.gms.tasks.OnCompleteListener +import com.google.android.gms.tasks.OnFailureListener +import com.google.android.gms.tasks.Task +import com.google.firebase.auth.EmailAuthProvider +import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.auth.UserProfileChangeRequest +import kotlinx.android.synthetic.main.activity_change_user_details.* + +class ChangeUserDetailsActivity : AppCompatActivity() { + + private val TAG = "ChangeDetailsActivity" + + var user = auth.currentUser + + private val EMAIL_CONSTANT = "Email Address" + private val PW_CONSTANT = "Password" + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_change_user_details) + + change_profile_name.setOnClickListener{ + val dialog = AlertDialog.Builder(this@ChangeUserDetailsActivity) + dialog.setTitle("Update Username") + + val titleBox = EditText(this@ChangeUserDetailsActivity) + titleBox.setText(user?.getDisplayName()) + dialog.setView(titleBox) + dialog.setPositiveButton( + "Update" + ) { dialog, which -> + updateProfile(titleBox.text.toString().trim { it <= ' ' }) + } + dialog.create().show() + } + + change_email.setOnClickListener{ + showDialog(EMAIL_CONSTANT) + } + + change_pw.setOnClickListener{ + showDialog(PW_CONSTANT) + } + + } + + private fun updateProfile(profileName: String) { + val profileUpdatesBuilder = UserProfileChangeRequest.Builder() + + if (!TextUtils.isEmpty(profileName)) { + profileUpdatesBuilder.setDisplayName(profileName) + } + + val profileUpdates = profileUpdatesBuilder.build() + + user?.updateProfile(profileUpdates) + ?.addOnCompleteListener { task -> + if (task.isSuccessful) { + Log.i(TAG, "User profile updated.") + // viewController.reloadDrawer(); + } + } + ?.addOnFailureListener { + Toast.makeText(this@ChangeUserDetailsActivity, "Update Failed", Toast.LENGTH_SHORT).show() + } + } + + private fun changeCredentials(email: String, password: String, changeText: String, selector: String) { + //todo: change to function + + // Get auth credentials from the user for re-authentication + val credential = EmailAuthProvider + .getCredential(email, password) // Current Login Credentials \\ + // Prompt the user to re-provide their sign-in credentials + user?.reauthenticate(credential) + ?.addOnCompleteListener { + Log.d(TAG, "User re-authenticated.") + + user = FirebaseAuth.getInstance().currentUser + if (selector == EMAIL_CONSTANT) { + + user?.updateEmail(changeText)!! + .addOnCompleteListener { task -> + if (task.isSuccessful) { + Log.d(TAG, "User email address updated.") + Toast.makeText( + this@ChangeUserDetailsActivity, + "Email Update Successful", + Toast.LENGTH_SHORT + ).show() + + // viewController.reloadDrawer(); + } else { + Toast.makeText( + this@ChangeUserDetailsActivity, + "Email Update Unsuccessful", + Toast.LENGTH_SHORT + ).show() + } + } + } + if (selector == PW_CONSTANT) { + user?.updatePassword(changeText)!! + .addOnCompleteListener { task -> + if (task.isSuccessful) { + Log.d(TAG, "User email address updated.") + Toast.makeText( + this@ChangeUserDetailsActivity, + "Password Update Successful", + Toast.LENGTH_SHORT + ).show() + } else { + Toast.makeText( + this@ChangeUserDetailsActivity, + "Password Update Unsuccessful", + Toast.LENGTH_SHORT + ).show() + } + } + } + } + } + + private fun showDialog(update: String) { + //Make new Dialog + val dialog = AlertDialog.Builder(this@ChangeUserDetailsActivity) + dialog.setTitle("Update $update") + + val layout = LinearLayout(this@ChangeUserDetailsActivity) + layout.orientation = LinearLayout.VERTICAL + layout.setPadding(28, 0, 56, 0) + + val box1 = EditText(this@ChangeUserDetailsActivity) + box1.hint = "Current Email Address" + box1.inputType = InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS + layout.addView(box1) // Notice this is an add method + + val box2 = EditText(this@ChangeUserDetailsActivity) + box2.hint = "Current Password" + box2.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + layout.addView(box2) // Another add method + + val box3 = EditText(this@ChangeUserDetailsActivity) + if (update == PW_CONSTANT) { + box3.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + } else { + box3.inputType = InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS + } + box3.hint = "New $update" + layout.addView(box3) // Another add method + + dialog.setView(layout) + dialog.setPositiveButton("Update") { dialog, which -> + val email = box1.text.toString().trim { it <= ' ' } + val password = box2.text.toString().trim { it <= ' ' } + val textThree = box3.text.toString().trim { it <= ' ' } + + changeCredentials(email, password, textThree, update) + } + dialog.create().show() + } +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/CircleView.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/CircleView.kt new file mode 100644 index 0000000..09c450a --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/CircleView.kt @@ -0,0 +1,76 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.content.Context +import android.graphics.* +import android.util.AttributeSet +import android.view.DragEvent +import android.view.View + +class CircleView(context: Context?, attrs: AttributeSet?) : View(context, attrs){ + + private var arcAngle: Float = 0.toFloat() + private var mRect: RectF = RectF() + private var mRect2: RectF = RectF() + private var mPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private var paint2: Paint = Paint() + private var thinkness: Int = 0 + + init { + paint2.isAntiAlias = true + paint2.color = Color.TRANSPARENT + paint2.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, widthMeasureSpec) + } + + override fun onDraw(canvas: Canvas?) { + super.onDraw(canvas) + + if (thinkness == 0) { + thinkness = 35 + } + + + mRect.centerX() + mRect.centerY() + mRect.left = 10f + mRect.top = 10f + mRect.right = (width - 10).toFloat() + mRect.bottom = (width - 10).toFloat() + + mRect2.centerX() + mRect2.centerY() + mRect2.left = mRect.left + thinkness + mRect2.top = mRect.top + thinkness + mRect2.right = mRect.right - thinkness + mRect2.bottom = mRect.bottom - thinkness + + setBackgroundColor(Color.TRANSPARENT) + if (mPaint.getColor() == 0) { + mPaint.setColor(Color.BLUE) + } + + setLayerType(LAYER_TYPE_SOFTWARE, null) + + canvas?.drawArc(mRect, 270f, arcAngle, true, mPaint) + canvas?.drawOval(mRect2, paint2) + } + + fun setPaintColor(color: Int) { + mPaint.setColor(color) + } + + fun setThickness(thickness: Int) { + this.thinkness = thickness + } + + fun getArcAngle(): Float { + return arcAngle + } + + fun setArcAngle(arcAngle: Float) { + this.arcAngle = arcAngle + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/CustomDialog.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/CustomDialog.kt new file mode 100644 index 0000000..dba0f95 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/CustomDialog.kt @@ -0,0 +1,126 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.content.Context +import android.content.DialogInterface +import android.graphics.Typeface +import android.os.Build +import android.view.View +import android.view.animation.AnimationUtils +import android.widget.DatePicker +import androidx.appcompat.app.AlertDialog +import kotlinx.android.synthetic.main.date_selector_dialog.* +import kotlinx.android.synthetic.main.date_selector_dialog.view.* +import java.text.DecimalFormat +import java.util.* + +class CustomDialog(context: Context): AlertDialog(context){ + companion object{ + lateinit var dateSelectionFrom:String + lateinit var dateSelectionTo:String + } + + lateinit var currentTag:String + + init { + init() + } + + fun init(){ + setTitle("Select Dates:") + val dialogView = View.inflate(context, R.layout.date_selector_dialog, null) + //get date picker + val datePicker = dialogView.date_picker + //set onclick listener + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + datePicker.setOnDateChangedListener(dateChangedListener) + } + + toggleTextButtons(true) + + from_date.setOnClickListener(onClickListener) + to_date.setOnClickListener(onClickListener) + + val calendar = Calendar.getInstance() + val dateString = retrieveDateString( + calendar.get(Calendar.YEAR), + calendar.get(Calendar.MONTH) + 1, + calendar.get(Calendar.DAY_OF_MONTH) + ) + + dateSelectionFrom = dateString + dateSelectionTo = dateString + + create() + } + + internal var dateChangedListener: DatePicker.OnDateChangedListener = + DatePicker.OnDateChangedListener { view, year, monthOfYear, dayOfMonth -> + var monthOfYear = monthOfYear + monthOfYear = monthOfYear + 1 + if (currentTag == "from") { + dateSelectionFrom = retrieveDateString(year, monthOfYear, dayOfMonth) + } else { + dateSelectionTo = retrieveDateString(year, monthOfYear, dayOfMonth) + } + } + + internal var onClickListener: View.OnClickListener = View.OnClickListener { v -> + currentTag = v.tag as String + + if (currentTag == "from") { + toggleTextButtons(true) + setDateOnDatePicker(dateSelectionFrom, v as DatePicker) + + } else { + toggleTextButtons(false) + setDateOnDatePicker(dateSelectionTo,v as DatePicker) + } + } + + private fun retrieveDateString(year: Int, monthOfYear: Int, dayOfMonth: Int): String { + val mFormat = DecimalFormat("00") + + val monthString = mFormat.format(monthOfYear.toLong()) + val dayString = mFormat.format(dayOfMonth.toLong()) + + return "$year-$monthString-$dayString" + } + + private fun setDateOnDatePicker(dateString: String, datePicker: DatePicker) { + /* 2019-06-04 */ + val year = Integer.parseInt(dateString.substring(0, 4)) + val month = Integer.parseInt(dateString.substring(5, 7)) - 1 + val day = Integer.parseInt(dateString.substring(8)) + + datePicker.init(year, month, day, dateChangedListener) + + } + + private fun toggleTextButtons(top: Boolean) { + setFadeAnimation(from_date) + setFadeAnimation(to_date) + + if (top) { + from_date.setTypeface(null, Typeface.BOLD) + to_date.setTypeface(null, Typeface.NORMAL) + + from_date.setBackgroundColor(context?.getColor(R.color.one)!!) + to_date.setBackgroundColor(context?.getColor(android.R.color.white)!!) + } else { + to_date.setTypeface(null, Typeface.BOLD) + from_date.setTypeface(null, Typeface.NORMAL) + + to_date.setBackgroundColor(context?.getColor(R.color.one)!!) + from_date.setBackgroundColor(context?.getColor(android.R.color.white)!!) + } + } + + private fun setFadeAnimation(view: View) { + val bottomUp = AnimationUtils.loadAnimation( + context, + R.anim.fade_in + ) + + view.animation = bottomUp + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/DateDialog.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/DateDialog.kt new file mode 100644 index 0000000..435cde3 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/DateDialog.kt @@ -0,0 +1,81 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.app.DatePickerDialog +import android.content.Context +import android.os.Build +import android.text.TextUtils +import android.util.Log +import android.widget.DatePicker +import android.widget.EditText +import android.widget.Toast +import androidx.annotation.RequiresApi +import kotlinx.android.synthetic.main.activity_add_shift.* +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +@RequiresApi(Build.VERSION_CODES.N) +class DateDialog(editText: EditText, context: Context) : DatePickerDialog(context) { + + internal var mYear: Int = 0 + internal var mMonth: Int = 0 + internal var mDay: Int = 0 + + init { + val dateString = editText.text.toString() + + var javaDate: Date? = null + + if (dateString.isNotBlank()) { + val calendar = Calendar.getInstance() + mYear = calendar.get(Calendar.YEAR) + mMonth = calendar.get(Calendar.MONTH) + mDay = calendar.get(Calendar.DAY_OF_MONTH) + } else { + try { + val sdfrmt = SimpleDateFormat("dd/MM/yyyy") + sdfrmt.isLenient = false + javaDate = sdfrmt.parse(dateString) + } catch (e: ParseException) { + e.printStackTrace() + } finally { + if (javaDate != null) { + mYear = Integer.parseInt(dateString.substring(6, dateString.length)) + mMonth = Integer.parseInt(dateString.substring(3, 5)) - 1 + mDay = Integer.parseInt(dateString.substring(0, 2)) + } else { + val calendar = Calendar.getInstance() + mYear = calendar.get(Calendar.YEAR) + mMonth = calendar.get(Calendar.MONTH) + mDay = calendar.get(Calendar.DAY_OF_MONTH) + } + } + + } + + Log.i( + this.javaClass.simpleName, "init: year =" + mYear + + "month = " + mMonth + + "day = " + mDay + ) + + + updateDate(mYear, mMonth, mDay) + + setOnDateSetListener{ view, year, month, dayOfMonth -> + mYear = year + mMonth = month + 1 + mDay = dayOfMonth + + val dateString = mYear.toString() + "-" + String.format("%02d", mMonth) + "-" + String.format("%02d", mDay) + + Toast.makeText(context,dateString,Toast.LENGTH_SHORT).show() + editText.setText(dateString) + + } + + this.setTitle(getContext().getString(R.string.set_date)) + this.show() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/DialogListAdapter.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/DialogListAdapter.kt new file mode 100644 index 0000000..dbb961c --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/DialogListAdapter.kt @@ -0,0 +1,38 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import com.appttude.h_mal.days_left_kotlin.Objects.TaskObject +import kotlinx.android.synthetic.main.task_list_item.* +import kotlinx.android.synthetic.main.task_list_item.view.* + +class DialogListAdapter(context: Context, objects: MutableList) : + ArrayAdapter(context, 0, objects){ + + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + var view: View? = convertView + if (view == null) { + view = LayoutInflater.from(context).inflate(R.layout.task_list_item, parent, false)!! + } + + val currentTask = getItem(position) + + view.task.text = currentTask?.task + var summary = currentTask?.workType + " - $" + currentTask?.rate + " /" + + if (currentTask?.workType.equals("Piece Rate")) { + summary = "$summary Unit" + view.task_image.setImageResource(R.drawable.piece) + } else if(currentTask?.workType.equals("Hourly")){ + summary = "$summary Hour" + view.task_image.setImageResource(R.drawable.task) + } + + view.task_summary.setText(summary) + + return view + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FireAdapter.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FireAdapter.kt new file mode 100644 index 0000000..b25943a --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FireAdapter.kt @@ -0,0 +1,77 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.app.Activity +import android.view.View +import android.widget.LinearLayout +import android.widget.TextView +import com.appttude.h_mal.days_left_kotlin.Objects.ShiftObject +import com.firebase.ui.database.FirebaseListAdapter +import com.google.firebase.database.Query +import kotlinx.android.synthetic.main.list_item.view.* +import kotlinx.android.synthetic.main.list_item.* + +class FireAdapter(activity: Activity?, modelClass: Class?, modelLayout: Int, ref: Query?) : + FirebaseListAdapter(activity, modelClass, modelLayout, ref) { + + override fun populateView(v: View?, model: ShiftObject?, position: Int) { + v?.farm_name?.text = model?.abnObject?.abn + v?.date?.text = model?.shiftDate + v?.task_name?.text = model?.taskObject?.task + v?.type?.text = model?.taskObject?.workType + val locationString:String = model?.abnObject?.state + " - " + model?.abnObject?.postCode + v?.location?.text = locationString + + v?.farm_name?.text = model?.abnObject?.companyName + + var s = model?.taskObject?.workType + " - $" + model?.taskObject?.rate + "/" + + if (model?.taskObject?.workType == FirebaseClass.HOURLY){ + s = "$s Hour" + v?.time_holder?.visibility = View.VISIBLE + v?.units_holder?.visibility = View.GONE + + val time = model.timeObject?.timeIn + " - " + model.timeObject!!.timeOut + v?.time?.text = time + + model.timeObject!!.breakEpoch.let { mins -> + val breakHolder = v?.break_holder + if (mins > 0){ + breakHolder?.visibility = View.VISIBLE + v?.break_time?.text = getBreakTimeString(model.timeObject!!.breakEpoch) + }else{ + breakHolder?.visibility = View.GONE + } + } + }else{ + s = "$s Unit" + v?.time_holder?.visibility = View.GONE + v?.units_holder?.visibility = View.VISIBLE + + v?.units?.text = model?.unitsCount.toString() + } + + v?.type?.text = s + } + + private fun getBreakTimeString(breakMins: Int): String { + val hoursFloat = (breakMins / 60).toFloat() + + val hoursInt = Math.floor(hoursFloat.toDouble()).toInt() + val minsInt = breakMins - hoursInt * 60 + + var s = "" + if (hoursInt > 0) { + s = "$hoursInt h " + } + + if (minsInt > 0) { + s = "$s$minsInt m" + } + + return s + } + + fun getId(i: Int): String? { + return getRef(i).key + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FirebaseClass.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FirebaseClass.kt new file mode 100644 index 0000000..4521009 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FirebaseClass.kt @@ -0,0 +1,27 @@ +package com.appttude.h_mal.days_left_kotlin + +import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.database.DatabaseReference +import com.google.firebase.database.FirebaseDatabase + +class FirebaseClass { + companion object { + val mDatabase: DatabaseReference = FirebaseDatabase.getInstance().getReference() + var auth: FirebaseAuth = FirebaseAuth.getInstance() + + val USER_FIREBASE = "users" + val EMPLOYER_FIREBASE = "employers" + val SHIFT_FIREBASE = "shifts" + val TASK_FIREBASE = "taskList" + + val SHIFT_ID = "shift_id" + + val PIECE = "Piece Rate" + val HOURLY = "Hourly" + + } + + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FragmentList.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FragmentList.kt new file mode 100644 index 0000000..77632d4 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FragmentList.kt @@ -0,0 +1,235 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.app.AlertDialog +import android.content.Context +import android.content.DialogInterface +import android.content.DialogInterface.BUTTON_POSITIVE +import android.content.Intent +import android.graphics.Typeface +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.view.* +import android.view.animation.AnimationUtils +import androidx.fragment.app.Fragment +import android.widget.AdapterView +import android.widget.DatePicker +import android.widget.TextView +import android.widget.Toast +import com.appttude.h_mal.days_left_kotlin.CustomDialog.Companion.dateSelectionFrom +import com.appttude.h_mal.days_left_kotlin.CustomDialog.Companion.dateSelectionTo +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.SHIFT_FIREBASE +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.SHIFT_ID +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.USER_FIREBASE +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.auth +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.mDatabase +import com.appttude.h_mal.days_left_kotlin.Objects.AbnObject +import com.appttude.h_mal.days_left_kotlin.Objects.ShiftObject +import com.google.firebase.database.DatabaseReference +import com.google.firebase.database.FirebaseDatabase +import com.google.firebase.database.Query +import kotlinx.android.synthetic.main.date_selector_dialog.* +import kotlinx.android.synthetic.main.date_selector_dialog.view.* +import kotlinx.android.synthetic.main.dialog_previous_abns_used.* +import kotlinx.android.synthetic.main.dialog_previous_abns_used.view.* +import kotlinx.android.synthetic.main.dialog_search_employer.* +import kotlinx.android.synthetic.main.fragment_list.* +import java.lang.ref.PhantomReference +import java.text.DecimalFormat +import java.util.* +import kotlin.collections.ArrayList + +class FragmentList : androidx.fragment.app.Fragment() { + + + lateinit var reference : DatabaseReference + lateinit var fireAdapter:FireAdapter + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + reference = mDatabase.child(USER_FIREBASE).child(auth.uid!!).child(SHIFT_FIREBASE) + reference.keepSynced(true) + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_list, container, false); + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + //set custom firebase adapter on listview + fireAdapter = FireAdapter(activity, ShiftObject::class.java,R.layout.list_item,reference) + page_two_list.adapter = fireAdapter + + page_two_list.setOnItemClickListener(object : AdapterView.OnItemClickListener{ + override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + val refId = fireAdapter.getId(position) + val intent = Intent(activity, AddShiftActivity::class.java) + intent.putExtra(SHIFT_ID, refId) + startActivity(intent) + } + }) + + page_two_list.setOnItemLongClickListener(object : AdapterView.OnItemLongClickListener{ + override fun onItemLongClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long): Boolean { + val builder = AlertDialog.Builder(context) + builder.setTitle("Are you sure you want to delete?") + builder.setNegativeButton(android.R.string.no, null) + builder.setPositiveButton( + android.R.string.yes + ) { dialog, which -> + + fireAdapter.getRef(position).removeValue() + } + builder.create().show() + + return false + } + }) + } + + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + super.onCreateOptionsMenu(menu, inflater) + inflater?.inflate(R.menu.menu_list_fragment, menu) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + when (item?.getItemId()) { + R.id.app_bar_filter -> { + filterData() + return false + } + R.id.app_bar_soft -> { + sortData() + return false + } + } + return false + } + + private fun sortData() { + val grpname = arrayOf("Name", "Date Added", "Date of shift") + val checkedItem = -1 + + val alt_bld = AlertDialog.Builder(context) + alt_bld.setTitle("Sort by:") + alt_bld.setSingleChoiceItems(grpname, checkedItem) { dialog, item -> + when (item) { + 0 -> { + val q1 = reference.orderByChild("abnObject/companyName").equalTo("GREEN CLOUD NURSERY") + fireAdapter = FireAdapter(activity, ShiftObject::class.java, R.layout.list_item, q1) + } + 1 -> fireAdapter = FireAdapter( + activity, + ShiftObject::class.java, + R.layout.list_item, + reference.orderByChild("dateTimeAdded") + ) + 2 -> fireAdapter = FireAdapter( + activity, + ShiftObject::class.java, + R.layout.list_item, + reference.orderByChild("shiftDate") + ) + } + page_two_list.adapter = fireAdapter + dialog.dismiss() + } + alt_bld.create().show() + } + + private fun filterData(){ + val groupName = arrayOf("Name", "Date Added", "Shift Type") + val checkedItem = -1 + + val builder = AlertDialog.Builder(context) + builder.setTitle("Filter by:") + builder.setSingleChoiceItems(groupName,checkedItem, DialogInterface.OnClickListener{dialog, item -> + dialog.dismiss() + + when(item) { + 0 -> { + val dialogBuilder = AlertDialog.Builder(context) + dialogBuilder.setTitle("Select Employer:") + //get layout + val dialogView = View.inflate(context, R.layout.dialog_previous_abns_used, null) + //hide button + dialogView.button_list_dialog.visibility = View.GONE + //get listview + val listView = dialogView.list_item_list_dialog + //get unique abn objects + val uniqueAbnObjects= turnToUniqueAbnObject(MainActivity.shiftList) + //populate list in view + listView.adapter = AbnListAdapter(context!!,uniqueAbnObjects as MutableList) + //on item click listener + listView.setOnItemClickListener(AdapterView.OnItemClickListener{parent, view, position, id -> + applyFilter(uniqueAbnObjects[position].abn!!,null) + }) + //set view on dialog + dialogBuilder.setView(dialogView) + + dialogBuilder.create().show() + + } + 1 -> { + val customDialog = CustomDialog(context!!) + + customDialog.setButton(BUTTON_POSITIVE, getContext()?.getString(android.R.string.yes), + DialogInterface.OnClickListener{ dialogNew, which -> + //interface results back + if (dateSelectionFrom != dateSelectionTo) { + applyFilter(dateSelectionFrom, dateSelectionTo) + } + + customDialog.dismiss() + }) + + customDialog.create() + } + 2 -> { + val typeDialog = AlertDialog.Builder(context) + val typeString = arrayOf("Hourly", "Piece Rate") + + typeDialog.setSingleChoiceItems( + arrayOf("Hourly", "Piece Rate"), -1 + ) { dialog, which -> + val q1 = reference.orderByChild("taskObject/workType").equalTo(typeString[which]) + + fireAdapter = FireAdapter(activity, ShiftObject::class.java, R.layout.list_item, q1) + page_two_list.adapter = fireAdapter + } + typeDialog.create().show() + } + } + }) + } + + fun turnToUniqueAbnObject(shifts : ArrayList): List{ + val abnList = mutableListOf() + + shifts.forEach{shiftObject -> + shiftObject.abnObject?.let { abnList.add(it) } + } + + return abnList.distinct() + } + + fun applyFilter(arg1: String, arg2: String?) { + val q1: Query + if (arg2 == null) { + q1 = reference.orderByChild("abnObject/abn").equalTo(arg1) + } else { + q1 = reference.orderByChild("shiftDate").startAt(arg1).endAt(arg2) + } + + fireAdapter = FireAdapter(activity, ShiftObject::class.java, R.layout.list_item, q1) + page_two_list.adapter = fireAdapter + } + + +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FragmentTools.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FragmentTools.kt new file mode 100644 index 0000000..848a801 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/FragmentTools.kt @@ -0,0 +1,190 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.Manifest +import android.app.ProgressDialog +import android.content.ActivityNotFoundException +import android.content.Intent +import android.content.pm.PackageManager +import android.os.AsyncTask +import android.os.Bundle +import android.os.Environment +import android.util.Log +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ProgressBar +import android.widget.Toast +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import androidx.core.content.ContextCompat.checkSelfPermission +import androidx.core.content.FileProvider +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.auth +import com.google.android.gms.tasks.Continuation +import com.google.android.gms.tasks.OnCompleteListener +import com.google.android.gms.tasks.Task +import com.google.firebase.functions.FirebaseFunctions +import com.google.firebase.functions.FirebaseFunctionsException +import com.google.firebase.functions.HttpsCallableResult +import com.google.firebase.storage.FirebaseStorage +import kotlinx.android.synthetic.main.fragment_tools.* +import java.io.File +import java.net.URL +import java.util.HashMap + +class FragmentTools : Fragment() { + + private val TAG = "FragmentTools" + + val mFunctions = FirebaseFunctions.getInstance() + val storage = FirebaseStorage.getInstance() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_tools, container, false) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + compile.setOnClickListener(onClickListener) + + summary_button.setOnClickListener(onClickListener) + } + + internal val onClickListener = View.OnClickListener { view -> + requestPermissions().let { + if (it) { + if (view.id == R.id.compile){ + writeToExcel().addOnCompleteListener(complete) + }else if(view.id == R.id.summary_button){ + writeToExcelVisa().addOnCompleteListener(complete) + } + } + } + + } + + internal val complete = OnCompleteListener{task -> + if (!task.isSuccessful) { + val e = task.exception + if (e is FirebaseFunctionsException) { + val ffe = e as FirebaseFunctionsException? + val code = ffe!!.code + val details = ffe.details + } + + Log.w(TAG, "addMessage:onFailure", e) + Toast.makeText(context, "An error occurred.", Toast.LENGTH_SHORT).show() + + }else{ + // [START_EXCLUDE] + val result = task.result as String + Log.i(TAG, "onComplete: $result") + + val strings = result.split("/").toTypedArray() + + val fbstore = storage.reference.child(result) + + val savePath = Environment.getExternalStorageDirectory().toString() + "/DaysLeftTemp" + val file = File(savePath) + if (!file.exists()) { + file.mkdirs() + } + + val myFile = File(savePath, strings.last()) + + fbstore.getFile(myFile).addOnSuccessListener { + // Local temp file has been created + val data = + FileProvider.getUriForFile(context!!, BuildConfig.APPLICATION_ID + ".provider", myFile) + activity?.grantUriPermission( + activity?.getPackageName(), + data, + Intent.FLAG_GRANT_READ_URI_PERMISSION + ) + val intent1 = Intent(Intent.ACTION_VIEW) + .setDataAndType(data, "application/vnd.ms-excel") + .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + + try { + activity?.startActivity(intent1) + } catch (e: ActivityNotFoundException) { + Toast.makeText(activity, "No Application Available to View Excel", Toast.LENGTH_SHORT) + .show() + } + + + }.addOnFailureListener { + // Handle any errors + + } + } + } + + fun writeToExcel(): Task { + // Create the arguments to the callable function. + val data = HashMap() + data["push"] = true + + return mFunctions + .getHttpsCallable("writeFireToExcel") + .call(data) + .continueWith{ task -> + // This continuation runs on either success or failure, but if the task + // has failed then getResult() will throw an Exception which will be + // propagated down. + + val result = task.result?.data as String + + Log.i(TAG, "then: " + result) + + result + } + } + + fun writeToExcelVisa(): Task { + // Create the arguments to the callable function. + val data = HashMap() + data["push"] = true + + return mFunctions + .getHttpsCallable("writeFireToExcelVisa") + .call(data) + .continueWith{ task -> + // This continuation runs on either success or failure, but if the task + // has failed then getResult() will throw an Exception which will be + // propagated down. + //todo: change to file + val result = task.result?.data as String + + Log.i(TAG, "then: " + result) + + result + } + } + + fun requestPermissions() : Boolean{ + if (checkSelfPermission(context!!, Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + Toast.makeText(context,"not granted",Toast.LENGTH_SHORT).show() + + requestPermissions( + arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), + 443) + + return false + }else{ + + return true + } + + + } +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/HomeFragment.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/HomeFragment.kt new file mode 100644 index 0000000..216c3e0 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/HomeFragment.kt @@ -0,0 +1,34 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.content.Context +import android.net.Uri +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kotlinx.android.synthetic.main.fragment_home.* +import kotlinx.android.synthetic.main.fragment_home.view.* + + +class HomeFragment : androidx.fragment.app.Fragment() { + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + // Inflate the layout for this fragment + val view : View = inflater.inflate(R.layout.fragment_home, container, false) + + view.recycler.adapter = context?.let { RecAdapter(it,MainActivity.shiftList) } + + view.recycler.setLayoutManager(LinearLayoutManager(context)) + view.recycler.setHasFixedSize(true) + + return view + } + + +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/ForgotPassword.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/ForgotPassword.kt new file mode 100644 index 0000000..703de70 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/ForgotPassword.kt @@ -0,0 +1,50 @@ +package com.appttude.h_mal.days_left_kotlin.Login + +import android.os.Bundle +import android.util.Log +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import com.appttude.h_mal.days_left_kotlin.Login.FullscreenActivity.Companion.fragmentManagerLogin +import com.appttude.h_mal.days_left_kotlin.R +import com.google.firebase.auth.FirebaseAuth +import kotlinx.android.synthetic.main.fragment_forgot_password.* + + +class ForgotPassword : Fragment() { + + internal var TAG = "forgotPasswordFragment" + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_forgot_password, container, false) + + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + reset_pw_sign_up.setOnClickListener{ + resetPassword(reset_pw.text.toString().trim()) + } + } + + private fun resetPassword(emailAddress: String) { + val auth = FirebaseAuth.getInstance() + + auth.sendPasswordResetEmail(emailAddress) + .addOnCompleteListener { task -> + if (task.isSuccessful) { + Log.d(TAG, "Email sent.") + + fragmentManagerLogin.popBackStack() + } else { + Toast.makeText(context, "Could not reset Password", Toast.LENGTH_SHORT).show() + } + } + } +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/FullscreenActivity.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/FullscreenActivity.kt new file mode 100644 index 0000000..29ca47c --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/FullscreenActivity.kt @@ -0,0 +1,73 @@ +package com.appttude.h_mal.days_left_kotlin.Login + +import android.content.Context +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.widget.Toast +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentTransaction +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.auth +import com.appttude.h_mal.days_left_kotlin.R +import com.google.firebase.auth.FirebaseAuth +import java.util.regex.Pattern + +class FullscreenActivity : AppCompatActivity() { + companion object { + lateinit var fragmentManagerLogin : FragmentManager + + fun isPasswordValid(password: String, context:Context): Boolean { + var validityScore = 0 + var str = "" + + if (password.length > 6){ + validityScore = validityScore + 1 + }else{ + str = str + "more than 6 characters, " + } + + if (password.toLowerCase() == password){ + validityScore = validityScore + 1 + }else{ + str = str + "uppercase character, " + } + + if (Pattern.compile( "[0-9]" ).matcher( password ).find()){ + validityScore = validityScore + 1 + }else{ + str = str + "number" + } + + if(validityScore == 3){ + return true + }else{ + Toast.makeText(context,"Password Requires : $str", Toast.LENGTH_SHORT).show() + return false + } + + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_fullscreen) + + auth = FirebaseAuth.getInstance() + + fragmentManagerLogin = supportFragmentManager + + fragmentManagerLogin.beginTransaction().replace( + R.id.container, + SplashFragment() + ).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) + .commit() + } + + override fun onBackPressed() { + super.onBackPressed() + if (fragmentManagerLogin.fragments.size > 1) { + fragmentManagerLogin.popBackStack() + } + } + + +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/LoginFragment.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/LoginFragment.kt new file mode 100644 index 0000000..038925e --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/LoginFragment.kt @@ -0,0 +1,119 @@ +package com.appttude.h_mal.days_left_kotlin.Login + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.annotation.TargetApi +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.text.TextUtils +import android.view.KeyEvent +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.EditorInfo +import android.widget.TextView +import android.widget.Toast +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.auth +import com.appttude.h_mal.days_left_kotlin.Login.FullscreenActivity.Companion.fragmentManagerLogin +import com.appttude.h_mal.days_left_kotlin.Login.FullscreenActivity.Companion.isPasswordValid +import com.appttude.h_mal.days_left_kotlin.MainActivity +import com.appttude.h_mal.days_left_kotlin.R +import com.google.android.gms.tasks.OnCompleteListener +import com.google.firebase.auth.AuthResult +import com.google.firebase.auth.FirebaseAuth +import kotlinx.android.synthetic.main.fragment_login.* + + +class LoginFragment : Fragment() { + + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_login, container, false) + + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + password.setOnEditorActionListener(TextView.OnEditorActionListener { textView, id, keyEvent -> + if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) { + attemptLogin() + return@OnEditorActionListener true + } + false + }) + + forgot.setOnClickListener{ + fragmentManagerLogin.beginTransaction() + .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_in) + .replace(R.id.container, ForgotPassword()) + .addToBackStack("forgot_pw").commit() + } + + register_button.setOnClickListener { + fragmentManagerLogin.beginTransaction() + .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_in) + .replace(R.id.container, Register()) + .addToBackStack("register") + .commit() + } + + email_sign_in_button.setOnClickListener{ + attemptLogin() + } + } + + private fun attemptLogin() { + + // Reset errors. + email.setError(null) + password.setError(null) + + // Store values at the time of the login attempt. + var cancel = false + var focusView: View? = null + + // Check for a valid password, if the user entered one. +// if (!TextUtils.isEmpty(password.text)) { +// password.setError(getString(R.string.error_invalid_password)) +// focusView = password +// cancel = true +// } + + // Check for a valid email address. +// if (!isPasswordValid(email.text.toString(), context!!)) { +// email.setError(getString(R.string.error_field_required)) +// focusView = email +// cancel = true +// } + + if (cancel) { + // There was an error; don't attempt login and focus the first + // form field with an error. + focusView!!.requestFocus() + } else { + // Show a progress spinner, and kick off a background task to + // perform the user login attempt. + login_progress.visibility = View.VISIBLE + auth.signInWithEmailAndPassword(email.text.toString(), password.text.toString()) + .addOnCompleteListener{ task -> + login_progress.visibility = View.GONE + if (task.isSuccessful) { + val intent = Intent(context, MainActivity::class.java) + startActivity(intent) + activity?.finish() + } else { + Toast.makeText(context, getString(R.string.login_failed), Toast.LENGTH_SHORT).show() + } + } + } + } + +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/Register.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/Register.kt new file mode 100644 index 0000000..33deac3 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/Register.kt @@ -0,0 +1,103 @@ +package com.appttude.h_mal.days_left_kotlin.Login + +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.text.TextUtils +import android.util.Log +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.auth +import com.appttude.h_mal.days_left_kotlin.Login.FullscreenActivity.Companion.isPasswordValid +import com.appttude.h_mal.days_left_kotlin.MainActivity +import com.appttude.h_mal.days_left_kotlin.R +import kotlinx.android.synthetic.main.fragment_login.* +import kotlinx.android.synthetic.main.fragment_register.* +import java.util.regex.Pattern + + +class Register : Fragment() { + + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_register, container, false); + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + email_sign_up.setOnClickListener{ + var cancel = false + var focusView: View? = null + + if (TextUtils.isEmpty(name_register.text)) { + name_register.setError(getString(R.string.error_field_required)) + focusView = name_register + cancel = true + } + + if (TextUtils.isEmpty(email_register.text)) { + email_register.setError(getString(R.string.error_field_required)) + focusView = email + cancel = true + } + + if (TextUtils.isEmpty(password_top.text)) { + password_top.setError(getString(R.string.error_field_required)) + focusView = password_top + cancel = true + } + + if (TextUtils.isEmpty(password_bottom.text)) { + password_bottom.setError(getString(R.string.error_field_required)) + focusView = password_bottom + cancel = true + } + + if (!TextUtils.isEmpty(password_top.text) && !isPasswordValid(password_top.text.toString(), this.context!!)) { + password_top.setError(getString(R.string.error_invalid_password)) + focusView = password_top + cancel = true + } + + if (password_top.text != password_bottom.text) { + password_bottom.setError(getString(R.string.no_match_password)) + focusView = password_bottom + cancel = true + } + + if (cancel) { + // There was an error; don't attempt login and focus the first + // form field with an error. + focusView!!.requestFocus() + } else { + pb.visibility = View.VISIBLE + //create user + auth.createUserWithEmailAndPassword(email.text.toString(), password_top.text.toString()) + .addOnCompleteListener{task -> + pb.visibility = View.GONE + if (!task.isSuccessful) { + Toast.makeText(context, "Authentication failed." + task.exception!!, + Toast.LENGTH_SHORT + ).show() + } else { + val intent = Intent(context, MainActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + startActivity(intent) + activity?.finish() + } + } + + } + + } + } + +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/SplashFragment.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/SplashFragment.kt new file mode 100644 index 0000000..0c17cd3 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Login/SplashFragment.kt @@ -0,0 +1,50 @@ +package com.appttude.h_mal.days_left_kotlin.Login + +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.auth +import com.appttude.h_mal.days_left_kotlin.Login.FullscreenActivity.Companion.fragmentManagerLogin +import com.appttude.h_mal.days_left_kotlin.MainActivity +import com.appttude.h_mal.days_left_kotlin.R + + +class SplashFragment : Fragment() { + + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_blank, container, false) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + val handler = Handler() + handler.postDelayed({ + //check if logged in + val user = auth.getCurrentUser() + + if (user == null) { + + fragmentManagerLogin + .beginTransaction() + .replace(R.id.container, LoginFragment()) + .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) + .commit() + + } else { + val intent = Intent(context, MainActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + startActivity(intent) + activity!!.finish() + } + }, 500) + } +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/MainActivity.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/MainActivity.kt new file mode 100644 index 0000000..9b3929b --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/MainActivity.kt @@ -0,0 +1,193 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.view.View +import android.widget.ProgressBar +import android.widget.Toast +import androidx.appcompat.app.ActionBarDrawerToggle +import com.google.android.material.bottomnavigation.BottomNavigationView +import androidx.fragment.app.FragmentManager +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.GravityCompat +import androidx.drawerlayout.widget.DrawerLayout +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.SHIFT_FIREBASE +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.USER_FIREBASE +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.auth +import com.appttude.h_mal.days_left_kotlin.FirebaseClass.Companion.mDatabase +import com.appttude.h_mal.days_left_kotlin.Login.FullscreenActivity +import com.appttude.h_mal.days_left_kotlin.Objects.AbnObject +import com.appttude.h_mal.days_left_kotlin.Objects.ShiftObject +import com.google.android.material.navigation.NavigationView +import com.google.firebase.database.DataSnapshot +import com.google.firebase.database.DatabaseError +import com.google.firebase.database.ValueEventListener +import com.squareup.picasso.Picasso +import kotlinx.android.synthetic.main.activity_drawer_main.* +import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.nav_header_main.view.* + +class MainActivity : AppCompatActivity() { + companion object{ + var shiftList = ArrayList() + } + + lateinit var fragmentManager: FragmentManager + lateinit var progBar: ProgressBar + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_drawer_main) + //initialising views as val + + val toolBar: androidx.appcompat.widget.Toolbar = toolbar + progBar = progressBar2 + + //setup backstack change listener + fragmentManager = supportFragmentManager + fragmentManager.addOnBackStackChangedListener(backStackChangedListener) + + //set toolbar + setSupportActionBar(toolBar) + + //setup fab + fab.setOnClickListener{ + val intent = Intent(this, AddShiftActivity::class.java) + startActivity(intent) + } + + //setup drawer layout + val drawer: DrawerLayout = drawer_layout + val toggle = ActionBarDrawerToggle(this,drawer,toolBar,R.string.navigation_drawer_open, R.string.navigation_drawer_close) + drawer.addDrawerListener(toggle) + toggle.syncState() + + //setup naviation view + val navigationView: NavigationView = nav_view + navigationView.setNavigationItemSelectedListener { menuItem -> + + menuItem.itemId.let { id -> + if (id == R.id.nav_camera){ + val intent = Intent(this,ChangeUserDetailsActivity::class.java) + startActivity(intent) + } + } + + drawer.closeDrawer(GravityCompat.START) + + true + } + + //Setup drawer + SetupDrawer(navigationView) + + //initialise data for fragments + initiateFragment() + } + + private val onNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item -> + when (item.itemId) { + R.id.navigation_home -> { + fragmentManager.beginTransaction().replace(R.id.container,HomeFragment()).commit() + return@OnNavigationItemSelectedListener true + } + R.id.navigation_list -> { + fragmentManager.beginTransaction().replace(R.id.container,FragmentList()).commit() + return@OnNavigationItemSelectedListener true + } + R.id.navigation_tools -> { + fragmentManager.beginTransaction().replace(R.id.container,FragmentTools()).commit() + return@OnNavigationItemSelectedListener true + } + } + false + } + + private val backStackChangedListener = FragmentManager.OnBackStackChangedListener { + fragmentManager.fragments.get(0).javaClass.simpleName.let {fragmentName -> + lateinit var name:String + + when (fragmentName){ + "HomeFragment" -> { + name = "Home" + } + "ListFragment" -> { + name = "List" + } + "ToolsFragment" -> { + name = "Tools" + } + else -> { + name = getString(R.string.app_name) + } + } + + setTitle(name) + } + } + + override fun setTitle(title: CharSequence?) { + toolbar.setTitle(title) + } + + fun SetupDrawer(navigationView: NavigationView){ + val header: View = navigationView.getHeaderView(0) + + checkNotNull(auth).currentUser.let { user -> + checkNotNull(user?.email).let {email -> + header.driver_email.setText(email) + } + checkNotNull(user?.displayName).let {name -> + header.driver_name.setText(name) + } + + Picasso.get().load(user?.photoUrl).placeholder(R.mipmap.ic_launcher_round) + .into(header.profileImage) + } + + logout.setOnClickListener{ + auth.signOut() + val intent = Intent(this, FullscreenActivity::class.java) + startActivity(intent) + finish() + } + } + + fun initiateFragment(){ + val uid = auth.uid as String + progBar.visibility = View.VISIBLE + + mDatabase.child(USER_FIREBASE).child(uid).child(SHIFT_FIREBASE).addValueEventListener(object : ValueEventListener { + override fun onCancelled(p0: DatabaseError) { + progBar.visibility = View.GONE + } + + override fun onDataChange(p0: DataSnapshot) { + progBar.visibility = View.GONE + + if(shiftList.isNotEmpty()){ + shiftList.clear() + } + + for(postSnapshot in p0.children){ + shiftList.add(postSnapshot.getValue(ShiftObject::class.java)!!) + } + + Log.i("firebase", "shiftlist count = " + shiftList.size) + + if (shiftList.size > 0){ + //apply navigation listener on bottom bar navigation view + navigation.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener) + //add first fragment + fragmentManager.beginTransaction().replace(R.id.container,HomeFragment()).commit() + navigation.setSelectedItemId(R.id.navigation_home) + }else{ + Toast.makeText(getBaseContext() , "Cannot load data", Toast.LENGTH_SHORT).show() + } + + } + }) + } + +} diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/AbnObject.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/AbnObject.kt new file mode 100644 index 0000000..08ca1e9 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/AbnObject.kt @@ -0,0 +1,9 @@ +package com.appttude.h_mal.days_left_kotlin.Objects + +data class AbnObject( + var abn: String? = "", + var companyName: String? = "", + var postCode: Int = 0, + var state: String? = "" +) + diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/ShiftObject.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/ShiftObject.kt new file mode 100644 index 0000000..48a1eb3 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/ShiftObject.kt @@ -0,0 +1,12 @@ +package com.appttude.h_mal.days_left_kotlin.Objects + +import java.io.Serializable + +data class ShiftObject( + var shiftDate: String = "", + var dateTimeAdded: String = "", + var abnObject: AbnObject? = AbnObject(), + var taskObject: TaskObject? = TaskObject(), + var unitsCount: Float? = 0f, + var timeObject: TimeObject? = TimeObject() +) \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/TaskObject.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/TaskObject.kt new file mode 100644 index 0000000..ad4f0b7 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/TaskObject.kt @@ -0,0 +1,9 @@ +package com.appttude.h_mal.days_left_kotlin.Objects + +import java.io.Serializable + +data class TaskObject ( + var workType: String? = "", + var rate: Float = 0.toFloat(), + var task: String? = "" +) : Serializable \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/TimeObject.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/TimeObject.kt new file mode 100644 index 0000000..3c0a504 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/Objects/TimeObject.kt @@ -0,0 +1,8 @@ +package com.appttude.h_mal.days_left_kotlin.Objects + +data class TimeObject( + var timeIn: String? = null, + var timeOut: String? = null, + var breakEpoch: Int = 0, + var hours: Float = 0f +) \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/PreviouslyUsedItemsClass.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/PreviouslyUsedItemsClass.kt new file mode 100644 index 0000000..7c5a2b9 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/PreviouslyUsedItemsClass.kt @@ -0,0 +1,18 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.app.Activity +import android.widget.ProgressBar +import com.google.firebase.database.DataSnapshot +import com.google.firebase.database.DatabaseError +import com.google.firebase.database.ValueEventListener + +class PreviouslyUsedItemsClass(progressBar: ProgressBar, activity: Activity) : ValueEventListener { + + override fun onCancelled(p0: DatabaseError) { + + } + + override fun onDataChange(p0: DataSnapshot) { + p0.key + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/days_left_kotlin/RecAdapter.kt b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/RecAdapter.kt new file mode 100644 index 0000000..30112a0 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/days_left_kotlin/RecAdapter.kt @@ -0,0 +1,289 @@ +package com.appttude.h_mal.days_left_kotlin + +import android.content.Context +import android.os.Build +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewTreeObserver +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.appttude.h_mal.days_left_kotlin.Objects.ShiftObject +import java.util.HashSet + +class RecAdapter(val context: Context, val shiftList : List) : RecyclerView.Adapter(){ + + var uniqueEntries: Int = 0 + var typeCount: IntArray + + init { + uniqueEntries = countDistinct() + typeCount = countShiftType() + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + when (viewType) { + 1 -> { + val itemOne = LayoutInflater.from(context).inflate(R.layout.item_one, parent, false) + return ItemOne(itemOne) + } + 2 -> { + val itemTwo = LayoutInflater.from(context).inflate(R.layout.item_two, parent, false) + return ItemTwo(itemTwo) + } + 3 -> { + val itemThree = + LayoutInflater.from(context).inflate(R.layout.item_three, parent, false) + return ItemThree(itemThree) + } + else -> { + val itemThree = + LayoutInflater.from(context).inflate(R.layout.item_three, parent, false) + return ItemThree(itemThree) + } + } + + + } + + override fun getItemCount(): Int { + return 5 + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (holder.itemViewType) { + 1 -> { + val viewHolderCurrent = holder as ItemOne + + val arcView = viewHolderCurrent.arc + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + arcView.setPaintColor(context.getColor(R.color.two)) + } + + val days = uniqueEntries + + val complete = 360 * days / 88 + + viewHolderCurrent.days.text = days.toString() + + val animation = ArcAnimation(arcView, complete.toFloat()) + animation.setDuration(600) + arcView.startAnimation(animation) + } + 2 -> { + val viewTwo = holder as ItemTwo + + val barView = viewTwo.barView + val linearLayout = viewTwo.linearLayout + + val cover = typeCount[1].toFloat() / shiftList.size + + barView.setCover(cover) + + barView.setColourOne(context.getColor(R.color.four)) + barView.setColourTwo(context.getColor(R.color.three)) + + viewTwo.pcText.text = typeCount[1].toString() + viewTwo.hrText.text = typeCount[0].toString() + + // viewTwo.textholder.setPadding(60,0,60,0); + // viewTwo.bottomTextholder.setPadding(60,0,60,0); + + linearLayout.viewTreeObserver.addOnGlobalLayoutListener(object : + ViewTreeObserver.OnGlobalLayoutListener { + override fun onGlobalLayout() { + + val barAnimation = BarAnimation(barView, linearLayout.width, 0) + barAnimation.setDuration(600) + barView.setAnimation(barAnimation) + linearLayout.viewTreeObserver.removeOnGlobalLayoutListener(this) + } + }) + } + + 3 -> { + val viewCounting = holder as ItemThree + + val cardTitle = viewCounting.cardTitle + val cardIcon = viewCounting.cardIcon + val units = viewCounting.units + val totalEarned = viewCounting.totalEarned + val top = viewCounting.textholderTop + val bottom = viewCounting.textholderBottom + + // top.setPadding(60,0,60,0); + // bottom.setPadding(60,0,60,0); + // cardIcon.setPadding(0,0,10,0); + + if (position == 2) { + cardTitle.text = "Hourly" + cardIcon.setImageResource(R.drawable.clock_icon) + val hours = String.format("%.2f", calculateHours()) + units.text = "$hours Hours" + + val total = String.format("%.2f", calculateAccumulatedPay(0)) + totalEarned.text = "$$total" + } + if (position == 3) { + cardTitle.text = "Piece" + cardTitle.setTextColor(context.resources.getColor(R.color.three)) + cardIcon.setImageResource(R.drawable.piece) + cardIcon.rotation = 270f + val pieces = String.format("%.2f", calculateUnits()) + units.text = "$pieces Units" + val total = String.format("%.2f", calculateAccumulatedPay(1)) + totalEarned.text = "$$total" + } + if (position == 4) { + cardTitle.visibility = View.GONE + cardIcon.visibility = View.GONE + + val total = String.format("%.2f", calculateAccumulatedPay(3)) + totalEarned.text = "$$total" + + viewCounting.textholderTop.visibility = View.GONE + } + } + } + } + + override fun getItemViewType(position: Int): Int { + when (position) { + 0 -> return 1 + 1 -> return 2 + 2 -> return 3 + 3 -> return 3 + 4 -> return 3 + else -> { + return 0 + } + } + } + + internal inner class ItemOne(itemView: View) : RecyclerView.ViewHolder(itemView) { + + var arc: CircleView + var days: TextView + + init { + arc = itemView.findViewById(R.id.arc_view) as CircleView + days = itemView.findViewById(R.id.days_completed) + } + } + + internal inner class ItemTwo (itemView: View) : RecyclerView.ViewHolder(itemView) { + + var barView: BarView + var linearLayout: LinearLayout + var pcText: TextView + var hrText: TextView + + init { + barView = itemView.findViewById(R.id.bar) as BarView + linearLayout = itemView.findViewById(R.id.lin) + pcText = itemView.findViewById(R.id.pc_amount_text) + hrText = itemView.findViewById(R.id.hr_amount_text) + } + } + + internal inner class ItemThree(itemView: View) : RecyclerView.ViewHolder(itemView) { + + val cardTitle: TextView + val cardIcon: ImageView + val units: TextView + val totalEarned: TextView + val textholderTop: LinearLayout + val textholderBottom: LinearLayout + + init { + cardTitle = itemView.findViewById(R.id.card_title) + cardIcon = itemView.findViewById(R.id.card_icon) + units = itemView.findViewById(R.id.units) + totalEarned = itemView.findViewById(R.id.total_earned) + textholderTop = itemView.findViewById(R.id.text_holder) + textholderBottom = itemView.findViewById(R.id.text_holder_two) + } + } + + private fun calculateHours(): Float { + var hours = 0f + for (shiftObject in shiftList) { + if (shiftObject.taskObject?.workType.equals("Hourly")) { + hours = hours + shiftObject.timeObject!!.hours - shiftObject.timeObject!!.breakEpoch + } + } + + return hours + } + + private fun calculateUnits(): Float { + var units = 0f + for (shiftObject in shiftList) { + if (shiftObject.taskObject?.workType.equals("Piece Rate")) { + units += + shiftObject.unitsCount!! + } + } + + return units + } + + private fun calculateAccumulatedPay(type: Int): Float { + var pay = 0f + + for (shiftObject in shiftList) { + when (type){ + 0 -> { + if (shiftObject.taskObject?.workType == "Hourly") { + pay += shiftObject.taskObject?.rate?.times((shiftObject.timeObject!!.hours - shiftObject.timeObject!!.breakEpoch)) + ?: pay + } + } + 1 -> { + if (shiftObject.taskObject?.workType == "Piece Rate") { + pay += shiftObject.taskObject?.rate?.times(shiftObject.unitsCount!!) ?: pay + } + } + else -> { + if (shiftObject.taskObject?.workType == "Hourly") { + pay += shiftObject.taskObject?.rate?.times((shiftObject.timeObject!!.hours - shiftObject.timeObject!!.breakEpoch)) + ?: pay + } else { + pay += shiftObject.taskObject?.rate?.times(shiftObject.unitsCount!!) ?: pay + } + } + } + + } + + return pay + } + + private fun countDistinct(): Int { + val hs = HashSet() + + for (i in shiftList.indices) { + + hs.add(shiftList.get(i).shiftDate) + } + + return hs.size + } + + private fun countShiftType(): IntArray { + var i = 0 + var j = 0 + + for (shiftObject in shiftList) { + if (shiftObject.taskObject?.workType.equals("Hourly")) { + i++ + } else { + j++ + } + } + + return intArrayOf(i, j) + } +} \ No newline at end of file diff --git a/app/src/main/res/anim/activity_open_enter.xml b/app/src/main/res/anim/activity_open_enter.xml new file mode 100644 index 0000000..2e89d0f --- /dev/null +++ b/app/src/main/res/anim/activity_open_enter.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/activity_open_exit.xml b/app/src/main/res/anim/activity_open_exit.xml new file mode 100644 index 0000000..9e37353 --- /dev/null +++ b/app/src/main/res/anim/activity_open_exit.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/fade_in.xml b/app/src/main/res/anim/fade_in.xml new file mode 100644 index 0000000..fdca929 --- /dev/null +++ b/app/src/main/res/anim/fade_in.xml @@ -0,0 +1,4 @@ + + diff --git a/app/src/main/res/drawable-hdpi/clouds_countryside_cropland_442116.jpg b/app/src/main/res/drawable-hdpi/clouds_countryside_cropland_442116.jpg new file mode 100644 index 0000000..7bb36aa Binary files /dev/null and b/app/src/main/res/drawable-hdpi/clouds_countryside_cropland_442116.jpg differ diff --git a/app/src/main/res/drawable-hdpi/splash.png b/app/src/main/res/drawable-hdpi/splash.png new file mode 100644 index 0000000..3d0dfb3 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/splash.png differ diff --git a/app/src/main/res/drawable-mdpi/clouds_countryside_cropland_442116.jpg b/app/src/main/res/drawable-mdpi/clouds_countryside_cropland_442116.jpg new file mode 100644 index 0000000..04ae1bd Binary files /dev/null and b/app/src/main/res/drawable-mdpi/clouds_countryside_cropland_442116.jpg differ diff --git a/app/src/main/res/drawable-mdpi/splash.png b/app/src/main/res/drawable-mdpi/splash.png new file mode 100644 index 0000000..85fa078 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/splash.png differ diff --git a/app/src/main/res/drawable-v24/cardviewoutline.xml b/app/src/main/res/drawable-v24/cardviewoutline.xml new file mode 100644 index 0000000..d2640f1 --- /dev/null +++ b/app/src/main/res/drawable-v24/cardviewoutline.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable-v24/side_nav_bar.xml b/app/src/main/res/drawable-v24/side_nav_bar.xml new file mode 100644 index 0000000..1bc79a1 --- /dev/null +++ b/app/src/main/res/drawable-v24/side_nav_bar.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/clouds_countryside_cropland_442116.jpg b/app/src/main/res/drawable-xhdpi/clouds_countryside_cropland_442116.jpg new file mode 100644 index 0000000..4dab427 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/clouds_countryside_cropland_442116.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/search_button.xml b/app/src/main/res/drawable-xhdpi/search_button.xml new file mode 100644 index 0000000..8daba54 --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/search_button.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/splash.png b/app/src/main/res/drawable-xhdpi/splash.png new file mode 100644 index 0000000..642a33e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/splash.png differ diff --git a/app/src/main/res/drawable-xxhdpi/clouds_countryside_cropland_442116.jpg b/app/src/main/res/drawable-xxhdpi/clouds_countryside_cropland_442116.jpg new file mode 100644 index 0000000..c5d0833 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/clouds_countryside_cropland_442116.jpg differ diff --git a/app/src/main/res/drawable-xxhdpi/splash.png b/app/src/main/res/drawable-xxhdpi/splash.png new file mode 100644 index 0000000..b31bd01 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/splash.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/clouds_countryside_cropland_442116.jpg b/app/src/main/res/drawable-xxxhdpi/clouds_countryside_cropland_442116.jpg new file mode 100644 index 0000000..e940296 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/clouds_countryside_cropland_442116.jpg differ diff --git a/app/src/main/res/drawable-xxxhdpi/splash.png b/app/src/main/res/drawable-xxxhdpi/splash.png new file mode 100644 index 0000000..2e15f20 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/splash.png differ diff --git a/app/src/main/res/drawable/box_icon.png b/app/src/main/res/drawable/box_icon.png new file mode 100644 index 0000000..9f0faff Binary files /dev/null and b/app/src/main/res/drawable/box_icon.png differ diff --git a/app/src/main/res/drawable/break_time.png b/app/src/main/res/drawable/break_time.png new file mode 100644 index 0000000..3d805d6 Binary files /dev/null and b/app/src/main/res/drawable/break_time.png differ diff --git a/app/src/main/res/drawable/cardviewoutline.xml b/app/src/main/res/drawable/cardviewoutline.xml new file mode 100644 index 0000000..061cba7 --- /dev/null +++ b/app/src/main/res/drawable/cardviewoutline.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/checkmark.png b/app/src/main/res/drawable/checkmark.png new file mode 100644 index 0000000..3a248c2 Binary files /dev/null and b/app/src/main/res/drawable/checkmark.png differ diff --git a/app/src/main/res/drawable/clock_icon.png b/app/src/main/res/drawable/clock_icon.png new file mode 100644 index 0000000..954a4eb Binary files /dev/null and b/app/src/main/res/drawable/clock_icon.png differ diff --git a/app/src/main/res/drawable/gradient_background.xml b/app/src/main/res/drawable/gradient_background.xml new file mode 100644 index 0000000..155ea60 --- /dev/null +++ b/app/src/main/res/drawable/gradient_background.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_dashboard_black_24dp.xml b/app/src/main/res/drawable/ic_dashboard_black_24dp.xml new file mode 100644 index 0000000..46fc8de --- /dev/null +++ b/app/src/main/res/drawable/ic_dashboard_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_filter_list_black_24dp.xml b/app/src/main/res/drawable/ic_filter_list_black_24dp.xml new file mode 100644 index 0000000..5d4ec18 --- /dev/null +++ b/app/src/main/res/drawable/ic_filter_list_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_black_24dp.xml b/app/src/main/res/drawable/ic_home_black_24dp.xml new file mode 100644 index 0000000..f8bb0b5 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_list_black_24dp.xml b/app/src/main/res/drawable/ic_list_black_24dp.xml new file mode 100644 index 0000000..4c2fb88 --- /dev/null +++ b/app/src/main/res/drawable/ic_list_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_notifications_black_24dp.xml b/app/src/main/res/drawable/ic_notifications_black_24dp.xml new file mode 100644 index 0000000..78b75c3 --- /dev/null +++ b/app/src/main/res/drawable/ic_notifications_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_search_black_24dp.xml b/app/src/main/res/drawable/ic_search_black_24dp.xml new file mode 100644 index 0000000..affc7ba --- /dev/null +++ b/app/src/main/res/drawable/ic_search_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_settings_applications_black_24dp.xml b/app/src/main/res/drawable/ic_settings_applications_black_24dp.xml new file mode 100644 index 0000000..968166e --- /dev/null +++ b/app/src/main/res/drawable/ic_settings_applications_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_sort_black_24dp.xml b/app/src/main/res/drawable/ic_sort_black_24dp.xml new file mode 100644 index 0000000..b3e29ab --- /dev/null +++ b/app/src/main/res/drawable/ic_sort_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/marker.png b/app/src/main/res/drawable/marker.png new file mode 100644 index 0000000..2c1ade0 Binary files /dev/null and b/app/src/main/res/drawable/marker.png differ diff --git a/app/src/main/res/drawable/piece.png b/app/src/main/res/drawable/piece.png new file mode 100644 index 0000000..f851aa3 Binary files /dev/null and b/app/src/main/res/drawable/piece.png differ diff --git a/app/src/main/res/drawable/round_edit_text.xml b/app/src/main/res/drawable/round_edit_text.xml new file mode 100644 index 0000000..3e019e8 --- /dev/null +++ b/app/src/main/res/drawable/round_edit_text.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/secondcardview.xml b/app/src/main/res/drawable/secondcardview.xml new file mode 100644 index 0000000..3a9a9a2 --- /dev/null +++ b/app/src/main/res/drawable/secondcardview.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/spash_drawable.xml b/app/src/main/res/drawable/spash_drawable.xml new file mode 100644 index 0000000..3a0ef19 --- /dev/null +++ b/app/src/main/res/drawable/spash_drawable.xml @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/app/src/main/res/drawable/task.png b/app/src/main/res/drawable/task.png new file mode 100644 index 0000000..5fc67f9 Binary files /dev/null and b/app/src/main/res/drawable/task.png differ diff --git a/app/src/main/res/drawable/yes_button.xml b/app/src/main/res/drawable/yes_button.xml new file mode 100644 index 0000000..1042b23 --- /dev/null +++ b/app/src/main/res/drawable/yes_button.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/abn_list_item.xml b/app/src/main/res/layout/abn_list_item.xml new file mode 100644 index 0000000..fb736df --- /dev/null +++ b/app/src/main/res/layout/abn_list_item.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_add_item.xml b/app/src/main/res/layout/activity_add_item.xml new file mode 100644 index 0000000..4e0ae20 --- /dev/null +++ b/app/src/main/res/layout/activity_add_item.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_add_shift.xml b/app/src/main/res/layout/activity_add_shift.xml new file mode 100644 index 0000000..d138aca --- /dev/null +++ b/app/src/main/res/layout/activity_add_shift.xml @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_change_user_details.xml b/app/src/main/res/layout/activity_change_user_details.xml new file mode 100644 index 0000000..4834d84 --- /dev/null +++ b/app/src/main/res/layout/activity_change_user_details.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + +