diff --git a/app/build.gradle b/app/build.gradle index 7a66e29..fb9c3cb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -88,4 +88,6 @@ dependencies { implementation "org.kodein.di:kodein-di-framework-android-core:$KODEIN_VERSION" / * jxl * / implementation "net.sourceforge.jexcelapi:jxl:$JEXCEL_VERSION" + / * calendar view * / + implementation 'com.applandeo:material-calendar-view:1.7.0' } diff --git a/app/src/main/java/com/appttude/h_mal/farmr/base/BaseFragment.kt b/app/src/main/java/com/appttude/h_mal/farmr/base/BaseFragment.kt index a74edba..f937d1a 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/base/BaseFragment.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/base/BaseFragment.kt @@ -29,13 +29,6 @@ abstract class BaseFragment(@LayoutRes contentLayoutId: Int) var mActivity: BaseActivity? = null - private var shortAnimationDuration by Delegates.notNull() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - shortAnimationDuration = resources.getInteger(android.R.integer.config_shortAnimTime) - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) mActivity = requireActivity() as BaseActivity diff --git a/app/src/main/java/com/appttude/h_mal/farmr/base/BaseListAdapter.kt b/app/src/main/java/com/appttude/h_mal/farmr/base/BaseListAdapter.kt index 6dc275c..8359767 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/base/BaseListAdapter.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/base/BaseListAdapter.kt @@ -12,7 +12,7 @@ import com.appttude.h_mal.farmr.utils.show abstract class BaseListAdapter( diff: DiffUtil.ItemCallback, private val layoutId: Int, - private val emptyView: View + private val emptyView: View? ) : ListAdapter(diff) { override fun onCreateViewHolder( @@ -49,8 +49,8 @@ abstract class BaseListAdapter( } fun checkEmpty() { - if (itemCount == 0) emptyView.show() - else emptyView.hide() + if (itemCount == 0) emptyView?.show() + else emptyView?.hide() } }) } diff --git a/app/src/main/java/com/appttude/h_mal/farmr/base/ChildFragment.kt b/app/src/main/java/com/appttude/h_mal/farmr/base/ChildFragment.kt new file mode 100644 index 0000000..9f43adb --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/farmr/base/ChildFragment.kt @@ -0,0 +1,68 @@ +package com.appttude.h_mal.farmr.base + +import android.os.Bundle +import android.view.View +import androidx.annotation.LayoutRes +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider +import androidx.navigation.NavDirections +import com.appttude.h_mal.farmr.model.ViewState +import com.appttude.h_mal.farmr.utils.getGenericClassAt +import com.appttude.h_mal.farmr.utils.navigateTo +import com.appttude.h_mal.farmr.viewmodel.ApplicationViewModelFactory +import org.kodein.di.KodeinAware +import org.kodein.di.android.x.kodein +import org.kodein.di.generic.instance +import java.io.IOException + +@Suppress("EmptyMethod", "EmptyMethod") +abstract class ChildFragment(@LayoutRes contentLayoutId: Int) : + Fragment(contentLayoutId), KodeinAware { + + override val kodein by kodein() + private val factory by instance() + + lateinit var viewModel: V + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + viewModel = + ViewModelProvider(requireParentFragment().requireParentFragment(), factory)[getGenericClassAt(0).java] + configureObserver() + } + + private fun configureObserver() { + viewModel.uiState.observe(viewLifecycleOwner) { + when (it) { + is ViewState.HasStarted -> onStarted() + is ViewState.HasData<*> -> onSuccess(it.data) + is ViewState.HasError<*> -> onFailure(it.error) + } + } + } + + /** + * Called in case of starting operation liveData in viewModel + */ + open fun onStarted() {} + + /** + * Called in case of success or some data emitted from the liveData in viewModel + */ + open fun onSuccess(data: Any?) {} + + /** + * Called in case of failure or some error emitted from the liveData in viewModel + */ + open fun onFailure(error: Any?) {} + + + fun navigateParent(navArg: Any) { + val fragment = requireParentFragment().requireParentFragment() + when(navArg) { + is Int -> (fragment).navigateTo(navArg) + is NavDirections -> (fragment).navigateTo(navArg) + else -> { throw IOException("${navArg::class} is not a valid navigation argment") } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/farmr/data/Repository.kt b/app/src/main/java/com/appttude/h_mal/farmr/data/Repository.kt index db97694..e0f3cdf 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/data/Repository.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/data/Repository.kt @@ -20,5 +20,5 @@ interface Repository { timeIn: String?, timeOut: String?, type: String? - ) + ): Boolean } \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/farmr/data/RepositoryImpl.kt b/app/src/main/java/com/appttude/h_mal/farmr/data/RepositoryImpl.kt index 3af7652..d9e3262 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/data/RepositoryImpl.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/data/RepositoryImpl.kt @@ -64,8 +64,8 @@ class RepositoryImpl( timeIn: String?, timeOut: String?, type: String? - ) { - preferenceProvider.saveFilteringDetails(description, timeIn, timeOut, type) + ): Boolean { + return preferenceProvider.saveFilteringDetails(description, timeIn, timeOut, type) } } \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/farmr/data/prefs/PreferencesProvider.kt b/app/src/main/java/com/appttude/h_mal/farmr/data/prefs/PreferencesProvider.kt index 11481c1..1e0cec7 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/data/prefs/PreferencesProvider.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/data/prefs/PreferencesProvider.kt @@ -44,13 +44,13 @@ class PreferenceProvider( timeIn: String?, timeOut: String?, type: String? - ) { - preference.edit() + ): Boolean { + return preference.edit() .putString(DESCRIPTION, description) .putString(DATE_IN, timeIn) .putString(DATE_OUT, timeOut) .putString(TYPE, type) - .apply() + .commit() } fun getFilteringDetails(): Map { diff --git a/app/src/main/java/com/appttude/h_mal/farmr/ui/CalendarFragment.kt b/app/src/main/java/com/appttude/h_mal/farmr/ui/CalendarFragment.kt new file mode 100644 index 0000000..c60c3a9 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/farmr/ui/CalendarFragment.kt @@ -0,0 +1,54 @@ +package com.appttude.h_mal.farmr.ui + +import android.os.Bundle +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import com.applandeo.materialcalendarview.CalendarView +import com.applandeo.materialcalendarview.EventDay +import com.appttude.h_mal.farmr.R +import com.appttude.h_mal.farmr.base.ChildFragment +import com.appttude.h_mal.farmr.data.legacydb.ShiftObject +import com.appttude.h_mal.farmr.utils.tryGet +import com.appttude.h_mal.farmr.viewmodel.MainViewModel +import java.util.Calendar + +class CalendarFragment : ChildFragment(R.layout.fragment_calendar) { + private lateinit var shiftListView: RecyclerView + private lateinit var calendarView: CalendarView + + private lateinit var mAdapter: ShiftListAdapter + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + shiftListView = view.findViewById(R.id.shifts_available_recycler) + calendarView = view.findViewById(R.id.calendarView) + + mAdapter = ShiftListAdapter(this, null, viewModel) + shiftListView.adapter = mAdapter + + calendarView.setOnDayClickListener { populateShiftListsForDay(it.calendar) } + } + + override fun onResume() { + super.onResume() + viewModel.refreshLiveData() + } + + override fun onSuccess(data: Any?) { + super.onSuccess(data) + if (data is List<*>) { + val events: List? = viewModel.retrieveEvents() + calendarView.setEvents(events) + + tryGet { calendarView.firstSelectedDate }?.let { + populateShiftListsForDay(it) + } + } + } + + private fun populateShiftListsForDay(calendar: Calendar) { + val data: List? = viewModel.getShiftsOnTheDay(calendar) + mAdapter.submitList(data) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/farmr/ui/FragmentList.kt b/app/src/main/java/com/appttude/h_mal/farmr/ui/FragmentList.kt new file mode 100644 index 0000000..f0afc55 --- /dev/null +++ b/app/src/main/java/com/appttude/h_mal/farmr/ui/FragmentList.kt @@ -0,0 +1,46 @@ +package com.appttude.h_mal.farmr.ui + +import android.os.Bundle +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import com.appttude.h_mal.farmr.R +import com.appttude.h_mal.farmr.base.ChildFragment +import com.appttude.h_mal.farmr.data.legacydb.ShiftObject +import com.appttude.h_mal.farmr.model.Success +import com.appttude.h_mal.farmr.utils.displayToast +import com.appttude.h_mal.farmr.utils.navigateTo +import com.appttude.h_mal.farmr.viewmodel.MainViewModel +import com.google.android.material.floatingactionbutton.FloatingActionButton + + +class FragmentList : ChildFragment(R.layout.fragment_list) { + private lateinit var productListView: RecyclerView + private lateinit var emptyView: View + private lateinit var mAdapter: ShiftListAdapter + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + emptyView = view.findViewById(R.id.empty_view) + productListView = view.findViewById(R.id.list_item_view) + + mAdapter = ShiftListAdapter(this, emptyView, viewModel) + productListView.adapter = mAdapter + } + + override fun onStart() { + super.onStart() + viewModel.refreshLiveData() + } + + override fun onSuccess(data: Any?) { + super.onSuccess(data) + if (data is List<*>) { + @Suppress("UNCHECKED_CAST") + mAdapter.submitList(data as List) + } else if (data is Success) { + displayToast(data.successMessage) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/farmr/ui/FragmentMain.kt b/app/src/main/java/com/appttude/h_mal/farmr/ui/FragmentMain.kt index a827b98..64ecf1d 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/ui/FragmentMain.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/ui/FragmentMain.kt @@ -9,29 +9,26 @@ import android.view.MenuItem import android.view.View import androidx.activity.OnBackPressedCallback import androidx.core.content.FileProvider -import androidx.recyclerview.widget.RecyclerView +import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.ui.setupWithNavController import com.appttude.h_mal.farmr.R import com.appttude.h_mal.farmr.base.BaseFragment -import com.appttude.h_mal.farmr.data.legacydb.ShiftObject import com.appttude.h_mal.farmr.model.Order import com.appttude.h_mal.farmr.model.Sortable -import com.appttude.h_mal.farmr.model.Success import com.appttude.h_mal.farmr.utils.createDialog -import com.appttude.h_mal.farmr.utils.displayToast import com.appttude.h_mal.farmr.utils.navigateTo import com.appttude.h_mal.farmr.viewmodel.MainViewModel +import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.floatingactionbutton.FloatingActionButton import java.io.File import kotlin.system.exitProcess class FragmentMain : BaseFragment(R.layout.fragment_main) { - private lateinit var productListView: RecyclerView - private lateinit var emptyView: View - private lateinit var mAdapter: ShiftListAdapter - private lateinit var onBackPressed: OnBackPressedCallback + lateinit var navView: BottomNavigationView + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Inflate the layout for this fragment @@ -47,7 +44,6 @@ class FragmentMain : BaseFragment(R.layout.fragment_main) { override fun onResume() { super.onResume() - setTitle("Shift List") onBackPressed.isEnabled = true } @@ -55,43 +51,39 @@ class FragmentMain : BaseFragment(R.layout.fragment_main) { override fun onPause() { super.onPause() onBackPressed.isEnabled = false + + viewModel.saveBottomBarState(navView.selectedItemId) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - emptyView = view.findViewById(R.id.empty_view) - productListView = view.findViewById(R.id.list_item_view) + navView = view.findViewById(R.id.bottom_bar) + val navHost = childFragmentManager.findFragmentById(R.id.sub_container) as NavHostFragment - mAdapter = ShiftListAdapter(this, emptyView, viewModel) - productListView.adapter = mAdapter + val navController = navHost.navController + navController.setGraph(R.navigation.home_navigation) + + navView.setOnNavigationItemSelectedListener { + setTitle(it.title.toString()) + true + } + navView.setupWithNavController(navController) + + viewModel.getBottomBarState()?.let { + navView.selectedItemId = it + } view.findViewById(R.id.fab1).setOnClickListener { navigateTo(R.id.main_to_addItem) } } - override fun onStart() { - super.onStart() - viewModel.refreshLiveData() - } - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { // Inflate the menu; this adds items to the action bar if it is present. inflater.inflate(R.menu.menu_main, menu) } - override fun onSuccess(data: Any?) { - super.onSuccess(data) - if (data is List<*>) { - @Suppress("UNCHECKED_CAST") - mAdapter.submitList(data as List) - } - if (data is Success) { - displayToast(data.successMessage) - } - } - override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.delete_all -> { diff --git a/app/src/main/java/com/appttude/h_mal/farmr/ui/ShiftListAdapter.kt b/app/src/main/java/com/appttude/h_mal/farmr/ui/ShiftListAdapter.kt index 5853a68..70723a4 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/ui/ShiftListAdapter.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/ui/ShiftListAdapter.kt @@ -8,14 +8,13 @@ import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView import androidx.appcompat.widget.PopupMenu -import androidx.fragment.app.Fragment import androidx.recyclerview.widget.DiffUtil import com.appttude.h_mal.farmr.R import com.appttude.h_mal.farmr.base.BaseListAdapter +import com.appttude.h_mal.farmr.base.ChildFragment import com.appttude.h_mal.farmr.data.legacydb.ShiftObject import com.appttude.h_mal.farmr.model.ShiftType import com.appttude.h_mal.farmr.utils.formatToTwoDpString -import com.appttude.h_mal.farmr.utils.navigateTo import com.appttude.h_mal.farmr.viewmodel.MainViewModel @@ -23,8 +22,8 @@ const val PIECE_ITEM = 500 const val HOURLY_ITEM = 501 class ShiftListAdapter( - private val fragment: Fragment, - emptyView: View, + private val fragment: ChildFragment<*>, + emptyView: View?, private val viewModel: MainViewModel ) : BaseListAdapter(diffCallBack, R.layout.list_item_1, emptyView) { @@ -62,7 +61,7 @@ class ShiftListAdapter( view.setOnClickListener { // Navigate to further info val nav = FragmentMainDirections.mainToFurtherInfo(data.id) - fragment.navigateTo(nav) + fragment.navigateParent(nav) } editView.setOnClickListener { //creating a popup menu @@ -76,7 +75,7 @@ class ShiftListAdapter( R.id.update -> { // Navigate to edit val nav = FragmentMainDirections.mainToAddItem(data.id) - fragment.navigateTo(nav) + fragment.navigateParent(nav) return@setOnMenuItemClickListener true } diff --git a/app/src/main/java/com/appttude/h_mal/farmr/utils/Formatting.kt b/app/src/main/java/com/appttude/h_mal/farmr/utils/Formatting.kt index 8595869..f3453fe 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/utils/Formatting.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/utils/Formatting.kt @@ -48,6 +48,13 @@ fun String.convertDateString(format: String = DATE_FORMAT): Date? { return formatter.parse(this) } +fun String.convertToCalendar(format: String = DATE_FORMAT): Calendar? { + val date = convertDateString(format) + val calendar = Calendar.getInstance() + calendar.time = date ?: return null + return calendar +} + /** * turns "HH:mm" into an hour and minutes pair * diff --git a/app/src/main/java/com/appttude/h_mal/farmr/utils/GenericsUtil.kt b/app/src/main/java/com/appttude/h_mal/farmr/utils/GenericsUtil.kt index cb0d32c..0dbcd89 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/utils/GenericsUtil.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/utils/GenericsUtil.kt @@ -20,7 +20,7 @@ fun Any.getGenericClassAt(position: Int): KClass = * var s: String? * i.validate{!i.isNullOrEmpty()} { print("string is empty") } */ -inline fun T.validateField(validate: (T) -> Boolean, onError: () -> Unit) { +inline fun T.validateField(validate: (T) -> Boolean, onError: () -> Unit) { if (!validate.invoke(this)) { onError.invoke() } @@ -30,9 +30,25 @@ inline fun T.validateField(validate: (T) -> Boolean, onError: () -> Uni * Returns a list of all elements sorted according to the specified comparator. In order of ascending or descending * The sort is stable. It means that equal elements preserve their order relative to each other after sorting. */ -inline fun > Iterable.sortedByOrder(order: Order = Order.ASCENDING, crossinline selector: (T) -> R?): List { +inline fun > Iterable.sortedByOrder( + order: Order = Order.ASCENDING, + crossinline selector: (T) -> R? +): List { return when (order) { Order.ASCENDING -> sortedWith(compareBy(selector)) Order.DESCENDING -> sortedWith(compareByDescending(selector)) } +} + +/** + * Tries to retrieve a variable that may throw an exception + * + * @Returns variable if successful else null + */ +inline fun tryGet(validate: () -> T?): T? { + return try { + validate.invoke() + } catch (e: Exception) { + null + } } \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/farmr/utils/NavigationUtils.kt b/app/src/main/java/com/appttude/h_mal/farmr/utils/NavigationUtils.kt index 7193e42..9accd0e 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/utils/NavigationUtils.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/utils/NavigationUtils.kt @@ -5,6 +5,7 @@ import androidx.fragment.app.Fragment import androidx.navigation.NavDirections import androidx.navigation.Navigation import com.appttude.h_mal.farmr.R +import com.appttude.h_mal.farmr.base.ChildFragment fun Fragment.navigateToFragment(newFragment: Fragment) { childFragmentManager.beginTransaction() diff --git a/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/MainViewModel.kt b/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/MainViewModel.kt index d63fca2..dbaf239 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/MainViewModel.kt @@ -1,8 +1,12 @@ package com.appttude.h_mal.farmr.viewmodel +import android.graphics.Color +import android.graphics.drawable.Drawable import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Observer +import com.applandeo.materialcalendarview.EventDay +import com.appttude.h_mal.farmr.R import com.appttude.h_mal.farmr.data.Repository import com.appttude.h_mal.farmr.data.legacydb.ShiftObject import com.appttude.h_mal.farmr.data.legacydb.ShiftsContract.ShiftsEntry.COLUMN_SHIFT_BREAK @@ -21,6 +25,7 @@ import com.appttude.h_mal.farmr.model.ShiftType import com.appttude.h_mal.farmr.model.Sortable import com.appttude.h_mal.farmr.model.Success import com.appttude.h_mal.farmr.utils.convertDateString +import com.appttude.h_mal.farmr.utils.convertToCalendar import com.appttude.h_mal.farmr.utils.formatAsCurrencyString import com.appttude.h_mal.farmr.utils.sortedByOrder import jxl.Workbook @@ -30,6 +35,7 @@ import jxl.write.WritableWorkbook import jxl.write.WriteException import java.io.File import java.io.IOException +import java.util.Calendar import java.util.Locale @@ -43,6 +49,8 @@ class MainViewModel( private var mSort: Sortable = Sortable.ID private var mOrder: Order = Order.ASCENDING + private var selectedItemId: Int? = null + private val observer = Observer> { it?.let { val result = it.applyFilters().sortList(mSort, mOrder) @@ -199,9 +207,8 @@ class MainViewModel( } fun clearFilters() { - super.setFiltrationDetails(null, null, null, null) - onSuccess(Success("Filters have been cleared")) - refreshLiveData() + val result = super.setFiltrationDetails(null, null, null, null) + if (result) refreshLiveData() } fun createExcelSheet(file: File): File? { @@ -283,4 +290,25 @@ class MainViewModel( return null } + fun retrieveEvents(): List? { + val shiftList = shiftLiveData.value ?: return null + return shiftList.applyFilters().mapNotNull { + it.date.convertToCalendar() + ?.let { d -> EventDay(d, R.drawable.baseline_list_alt_24, Color.parseColor("#228B22")) } + } + } + + fun getShiftsOnTheDay(calendar: Calendar): List? { + val shiftList = shiftLiveData.value ?: return null + return shiftList.filter { it.date.convertToCalendar()?.compareTo(calendar) == 0 } + } + + fun saveBottomBarState(selectedItemId: Int) { + this.selectedItemId = selectedItemId + } + + fun getBottomBarState(): Int? { + return selectedItemId + } + } \ No newline at end of file diff --git a/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/ShiftViewModel.kt b/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/ShiftViewModel.kt index abcc710..a4761d7 100644 --- a/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/ShiftViewModel.kt +++ b/app/src/main/java/com/appttude/h_mal/farmr/viewmodel/ShiftViewModel.kt @@ -18,25 +18,13 @@ open class ShiftViewModel( */ fun getCurrentShift(id: Long) = repository.readSingleShiftFromDatabase(id) - /** - * Lambda function that will invoke onError(...) on failure - * but update live data when successful - */ - private inline fun doTry(operation: () -> Unit) { - try { - operation.invoke() - } catch (e: Exception) { - onError(e) - } - } - open fun setFiltrationDetails( description: String?, dateFrom: String?, dateTo: String?, type: String? - ) { - repository.setFilteringDetailsInPrefs(description, dateFrom, dateTo, type) + ): Boolean { + return repository.setFilteringDetailsInPrefs(description, dateFrom, dateTo, type) } open fun getFiltrationDetails(): FilterStore { diff --git a/app/src/main/res/drawable/baseline_calendar_month_24.xml b/app/src/main/res/drawable/baseline_calendar_month_24.xml new file mode 100644 index 0000000..b89360f --- /dev/null +++ b/app/src/main/res/drawable/baseline_calendar_month_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/baseline_list_alt_24.xml b/app/src/main/res/drawable/baseline_list_alt_24.xml new file mode 100644 index 0000000..57fd027 --- /dev/null +++ b/app/src/main/res/drawable/baseline_list_alt_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/fragment_calendar.xml b/app/src/main/res/layout/fragment_calendar.xml new file mode 100644 index 0000000..ae7485a --- /dev/null +++ b/app/src/main/res/layout/fragment_calendar.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_list.xml b/app/src/main/res/layout/fragment_list.xml new file mode 100644 index 0000000..dbb12ec --- /dev/null +++ b/app/src/main/res/layout/fragment_list.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index 8bf6a22..bd040fa 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -1,34 +1,39 @@ - - - + android:layout_height="0dp" + app:layout_constraintBottom_toTopOf="@id/bottom_bar" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:layout="@layout/fragment_calendar" /> + + - - - + diff --git a/app/src/main/res/menu/bottom_navigation_menu.xml b/app/src/main/res/menu/bottom_navigation_menu.xml new file mode 100644 index 0000000..4ce7d48 --- /dev/null +++ b/app/src/main/res/menu/bottom_navigation_menu.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/home_navigation.xml b/app/src/main/res/navigation/home_navigation.xml new file mode 100644 index 0000000..429438e --- /dev/null +++ b/app/src/main/res/navigation/home_navigation.xml @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d406702..b8934f8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -103,4 +103,7 @@ £ Delete shift Update Shift + Floating action button + Shifts + Calendar