Skip to content

Commit 936b711

Browse files
committed
Project Completed
1 parent d2d7721 commit 936b711

File tree

81 files changed

+2126
-835
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+2126
-835
lines changed

app/src/main/AndroidManifest.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77

88
<application
99
android:allowBackup="true"
10-
android:icon="@mipmap/ic_launcher"
10+
android:icon="@mipmap/app_icon"
1111
android:label="@string/app_name"
1212
android:networkSecurityConfig="@xml/network_security_config"
13-
android:roundIcon="@mipmap/ic_launcher_round"
13+
android:roundIcon="@mipmap/app_icon_round"
1414
android:supportsRtl="true"
1515
android:theme="@style/SplashScreenTheme"
1616
android:windowSoftInputMode="adjustResize">

app/src/main/app_icon-playstore.png

15 KB
Loading
15 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.finals.foodrunner.adapter.order_history_adapter
2+
3+
import android.view.LayoutInflater
4+
import android.view.ViewGroup
5+
import androidx.recyclerview.widget.RecyclerView
6+
import com.finals.foodrunner.databinding.CartItemBinding
7+
import com.finals.foodrunner.objects.FoodItem
8+
9+
10+
class InnerOrderedFoodAdapter(val list: List<FoodItem>) :
11+
RecyclerView.Adapter<InnerOrderedFoodAdapter.ViewHolder>() {
12+
inner class ViewHolder(val binding: CartItemBinding) : RecyclerView.ViewHolder(binding.root) {
13+
14+
fun bind(foodItem: FoodItem){
15+
binding.apply {
16+
name.text=foodItem.name
17+
price.text=foodItem.cost
18+
}
19+
}
20+
}
21+
22+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
23+
val binding = CartItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
24+
return ViewHolder(binding)
25+
}
26+
27+
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
28+
if(position!=RecyclerView.NO_POSITION){
29+
val currElement = list[position]
30+
holder.bind(currElement)
31+
}
32+
}
33+
34+
override fun getItemCount() = list.size
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.finals.foodrunner.adapter.order_history_adapter
2+
3+
import android.view.LayoutInflater
4+
import android.view.ViewGroup
5+
import androidx.recyclerview.widget.DiffUtil
6+
import androidx.recyclerview.widget.LinearLayoutManager
7+
import androidx.recyclerview.widget.ListAdapter
8+
import androidx.recyclerview.widget.RecyclerView
9+
import com.finals.foodrunner.databinding.OrderHistoryElementBinding
10+
import com.finals.foodrunner.objects.OrderHistoryElement
11+
12+
class OrderedFoodAdapter :ListAdapter<OrderHistoryElement, OrderedFoodAdapter.ViewHolder>(
13+
OrderHistoryComparator()
14+
) {
15+
inner class ViewHolder(val binding: OrderHistoryElementBinding) :
16+
RecyclerView.ViewHolder(binding.root) {
17+
18+
fun bind(orderHistoryElement: OrderHistoryElement) {
19+
val adapter = InnerOrderedFoodAdapter(orderHistoryElement.food_items)
20+
binding.apply {
21+
restaurantName.setText(orderHistoryElement.restaurant_name)
22+
dateOfOrder.setText(orderHistoryElement.order_placed_at)
23+
24+
foodList.apply {
25+
this.adapter = adapter
26+
layoutManager = LinearLayoutManager(itemView.context)
27+
setHasFixedSize(true)
28+
29+
}
30+
}
31+
}
32+
}
33+
34+
class OrderHistoryComparator : DiffUtil.ItemCallback<OrderHistoryElement>() {
35+
override fun areItemsTheSame(
36+
oldItem: OrderHistoryElement,
37+
newItem: OrderHistoryElement
38+
) = oldItem.order_id == newItem.order_id
39+
40+
override fun areContentsTheSame(
41+
oldItem: OrderHistoryElement,
42+
newItem: OrderHistoryElement
43+
) = oldItem == newItem
44+
45+
}
46+
47+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
48+
val binding =
49+
OrderHistoryElementBinding.inflate(LayoutInflater.from(parent.context), parent, false)
50+
return ViewHolder(binding)
51+
}
52+
53+
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
54+
val curr = getItem(position);
55+
if (curr != null) {
56+
holder.bind(curr)
57+
}
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.finals.foodrunner.objects
2+
3+
data class FoodItem(
4+
val cost: String,
5+
val food_item_id: String,
6+
val name: String
7+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.finals.foodrunner.objects
2+
3+
data class OrderHistoryElement(
4+
val food_items: List<FoodItem>,
5+
val order_id: String,
6+
val order_placed_at: String,
7+
val restaurant_name: String,
8+
val total_cost: String
9+
)

app/src/main/java/com/finals/foodrunner/objects/User.kt

+32-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,35 @@ data class User(
1010
val email: String?,
1111
val mobile_number:Long,
1212
val address: String?
13-
)
13+
):Parcelable {
14+
constructor(parcel: Parcel) : this(
15+
parcel.readLong(),
16+
parcel.readString(),
17+
parcel.readString(),
18+
parcel.readLong(),
19+
parcel.readString()
20+
) {
21+
}
22+
23+
override fun writeToParcel(parcel: Parcel, flags: Int) {
24+
parcel.writeLong(user_id)
25+
parcel.writeString(name)
26+
parcel.writeString(email)
27+
parcel.writeLong(mobile_number)
28+
parcel.writeString(address)
29+
}
30+
31+
override fun describeContents(): Int {
32+
return 0
33+
}
34+
35+
companion object CREATOR : Parcelable.Creator<User> {
36+
override fun createFromParcel(parcel: Parcel): User {
37+
return User(parcel)
38+
}
39+
40+
override fun newArray(size: Int): Array<User?> {
41+
return arrayOfNulls(size)
42+
}
43+
}
44+
}

app/src/main/java/com/finals/foodrunner/room/RestaurantDao.kt

+27-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.finals.foodrunner.room
1+
package com.finals.foodrunner.room
22

33
import androidx.room.*
44
import com.finals.foodrunner.objects.Restaurant
@@ -12,26 +12,44 @@ interface RestaurantDao {
1212
suspend fun addRestaurant(list: List<Restaurant>)
1313

1414
@Query("DELETE FROM RESTAURANTS WHERE isFavourite!=1")
15-
suspend fun deleteAllRestaurants()
15+
suspend fun deleteUnFavouriteRestaurants()
16+
17+
@Query("DELETE FROM RESTAURANTS")
18+
suspend fun deleteAllRestaurants();
1619

1720
fun getAllRestaurants(searchQuery: String, sortBy: SORT_SCHEME): Flow<List<Restaurant>> {
1821
return when (sortBy) {
1922
SORT_SCHEME.SORT_BY_RATING -> getAllRestaurantSortByRating(searchQuery)
20-
SORT_SCHEME.SORT_BY_INC_COST-> getAllRestaurantSortByIncPrice(searchQuery)
23+
SORT_SCHEME.SORT_BY_INC_COST -> getAllRestaurantSortByIncPrice(searchQuery)
2124
SORT_SCHEME.SORT_BY_DES_COST -> getAllRestaurantSortByDecPrice(searchQuery)
2225
}.exhaustive
2326
}
24-
@Query("SELECT * FROM restaurants WHERE isFavourite==1")
25-
fun getFavouriteRestaurants():Flow<List<Restaurant>>
26-
2727
@Query("SELECT * FROM restaurants WHERE name LIKE '%' || :searchQuery || '%' ORDER BY rating DESC")
28-
fun getAllRestaurantSortByRating(searchQuery: String=""): Flow<List<Restaurant>>
28+
fun getAllRestaurantSortByRating(searchQuery: String = ""): Flow<List<Restaurant>>
2929

3030
@Query("SELECT * FROM restaurants WHERE name LIKE '%' || :searchQuery || '%' ORDER BY cost_for_one DESC")
31-
fun getAllRestaurantSortByDecPrice(searchQuery: String=""): Flow<List<Restaurant>>
31+
fun getAllRestaurantSortByDecPrice(searchQuery: String = ""): Flow<List<Restaurant>>
3232

3333
@Query("SELECT * FROM restaurants WHERE name LIKE '%' || :searchQuery || '%' ORDER BY cost_for_one ASC")
34-
fun getAllRestaurantSortByIncPrice(searchQuery: String=""): Flow<List<Restaurant>>
34+
fun getAllRestaurantSortByIncPrice(searchQuery: String = ""): Flow<List<Restaurant>>
35+
// _______________________________________________________________________________________________________________
36+
37+
38+
fun getFavRestaurants(searchQuery: String, sortBy: SORT_SCHEME): Flow<List<Restaurant>> {
39+
return when (sortBy) {
40+
SORT_SCHEME.SORT_BY_RATING -> getFavRestaurantSortByRating(searchQuery)
41+
SORT_SCHEME.SORT_BY_INC_COST -> getFavRestaurantSortByIncPrice(searchQuery)
42+
SORT_SCHEME.SORT_BY_DES_COST -> getFavRestaurantSortByDecPrice(searchQuery)
43+
}.exhaustive
44+
}
45+
@Query("SELECT * FROM restaurants WHERE isFavourite==1 and name LIKE '%' || :searchQuery || '%' ORDER BY rating DESC")
46+
fun getFavRestaurantSortByRating(searchQuery: String = ""): Flow<List<Restaurant>>
47+
48+
@Query("SELECT * FROM restaurants WHERE isFavourite==1 and name LIKE '%' || :searchQuery || '%' ORDER BY cost_for_one DESC")
49+
fun getFavRestaurantSortByDecPrice(searchQuery: String = ""): Flow<List<Restaurant>>
50+
51+
@Query("SELECT * FROM restaurants WHERE isFavourite==1 and name LIKE '%' || :searchQuery || '%' ORDER BY cost_for_one ASC")
52+
fun getFavRestaurantSortByIncPrice(searchQuery: String = ""): Flow<List<Restaurant>>
3553

3654
@Update
3755
suspend fun updateRestaurant(restaurant: Restaurant)

app/src/main/java/com/finals/foodrunner/ui/activity/ActivityViewModel.kt

+96-15
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,61 @@
11
package com.finals.foodrunner.ui.activity
22

3-
import androidx.lifecycle.LiveData
4-
import androidx.lifecycle.ViewModel
5-
import androidx.lifecycle.asLiveData
6-
import androidx.lifecycle.viewModelScope
3+
import androidx.lifecycle.*
4+
import com.finals.foodrunner.objects.OrderHistoryElement
75
import com.finals.foodrunner.objects.Restaurant
6+
import com.finals.foodrunner.objects.User
87
import com.finals.foodrunner.room.RestaurantDatabase
98
import com.finals.foodrunner.util.ConnectivityManager
109
import com.finals.foodrunner.util.SORT_SCHEME
10+
import com.finals.foodrunner.volley.OrderHistoryResponseInterface
1111
import com.finals.foodrunner.volley.RestaurantResponseInterface
1212
import com.finals.foodrunner.volley.VolleySingleton
1313
import com.finals.foodrunner.volley.getAllRestaurants
1414
import kotlinx.coroutines.CoroutineScope
1515
import kotlinx.coroutines.SupervisorJob
1616
import kotlinx.coroutines.channels.Channel
17-
import kotlinx.coroutines.flow.receiveAsFlow
17+
import kotlinx.coroutines.flow.*
1818
import kotlinx.coroutines.launch
1919

2020
class ActivityViewModel(
2121
private val volleySingleton: VolleySingleton,
2222
private val connectivityManager: ConnectivityManager,
2323
restaurantDatabase: RestaurantDatabase,
24-
) : ViewModel(), HomeViewModel,FavouriteViewModel {
24+
) : ViewModel(), HomeViewModel, FavouriteViewModel, OrderHistoryViewModel, ProfileViewModel {
2525
private val homeEventChannel = Channel<Event>()
26-
val homeEvents = homeEventChannel.receiveAsFlow().asLiveData()
2726
val restaurantDao = restaurantDatabase.restaurantDao()
28-
val allRestaurant = restaurantDao.getAllRestaurants("", SORT_SCHEME.SORT_BY_RATING).asLiveData()
29-
val favouriteRestaurants = restaurantDao.getFavouriteRestaurants().asLiveData()
27+
private val searchQueryHome = MutableStateFlow("")
28+
private val sortOrderHome = MutableStateFlow(SORT_SCHEME.SORT_BY_RATING)
29+
private val allRestaurantFlow =
30+
combine(searchQueryHome, sortOrderHome) { searchQuery, sortOrder ->
31+
Pair(searchQuery, sortOrder)
32+
}.flatMapLatest { (query, sortOrder) ->
33+
restaurantDao.getAllRestaurants(query, sortOrder)
34+
}
35+
private val allRestaurant = allRestaurantFlow.asLiveData()
36+
37+
private val searchQueryFav = MutableStateFlow("")
38+
private val sortOrderFav = MutableStateFlow(SORT_SCHEME.SORT_BY_RATING)
39+
private val favouriteRestaurantFlow =
40+
combine(searchQueryFav, sortOrderFav) { searchQueryFav, sortOrder ->
41+
Pair(searchQueryFav, sortOrder)
42+
}.flatMapLatest {(query,sortOrder)->
43+
restaurantDao.getFavRestaurants(query,sortOrder)
44+
}
45+
private val favouriteRestaurants = favouriteRestaurantFlow.asLiveData()
46+
val orderHistory = MutableLiveData<List<OrderHistoryElement>>()
47+
val orderHistoryEvent = Channel<Event>()
48+
private val currentUser = MutableLiveData<User>()
49+
val user: LiveData<User> = currentUser
50+
51+
52+
// ------------------------------------------------------------------------
3053

3154
init {
3255
viewModelScope.launch {
33-
restaurantDao.deleteAllRestaurants()
56+
restaurantDao.deleteUnFavouriteRestaurants()
3457
fetchAllRestaurants()
58+
fetchOrderHistory()
3559
}
3660
}
3761

@@ -64,7 +88,31 @@ class ActivityViewModel(
6488
}
6589
}
6690

67-
override fun getRestaurants(): LiveData<List<Restaurant>> =allRestaurant
91+
override suspend fun setCurrentUser(user: User) {
92+
this.currentUser.postValue(user)
93+
}
94+
95+
override fun setHomeSearchQuery(query: String) {
96+
this.searchQueryHome.value = query
97+
}
98+
99+
override suspend fun currentUser() = user
100+
override fun setFavSortOrder(sortScheme: SORT_SCHEME) {
101+
this.sortOrderFav.value=sortScheme
102+
}
103+
104+
override fun getFavSortOrder()=this.sortOrderFav.value
105+
override fun setFavSearchQuery(query: String) {
106+
searchQueryFav.value=query
107+
}
108+
109+
override fun getRestaurants(): LiveData<List<Restaurant>> = allRestaurant
110+
override fun getHomeEvents(): Flow<Event> = homeEventChannel.receiveAsFlow()
111+
override fun setHomeSortOrder(sortScheme: SORT_SCHEME) {
112+
sortOrderHome.value = sortScheme
113+
}
114+
115+
override fun getHomeSortOrder() = sortOrderHome.value
68116

69117
override fun changeFavouriteStatus(restaurant: Restaurant) {
70118
viewModelScope.launch {
@@ -73,13 +121,46 @@ class ActivityViewModel(
73121
}
74122
}
75123

76-
enum class Event {
77-
LOADED, LOADING, OFFLINE
78-
}
79124

80125
override fun getFavRestaurants(): LiveData<List<Restaurant>> = favouriteRestaurants
81126

82127
override fun unFavStatus(restaurant: Restaurant) {
83128
changeFavouriteStatus(restaurant)
84129
}
85-
}
130+
131+
132+
override suspend fun fetchOrderHistory() {
133+
if (connectivityManager.isOnline() && connectivityManager.checkConnectivity()) {
134+
orderHistoryEvent.send(Event.LOADING)
135+
com.finals.foodrunner.volley.getOrderHistory(
136+
userId = user.value?.user_id.toString(),
137+
volleySingleton = volleySingleton,
138+
object : OrderHistoryResponseInterface {
139+
override fun onResponse(orderHistoryElements: List<OrderHistoryElement>) {
140+
viewModelScope.launch {
141+
orderHistoryEvent.send(Event.LOADED)
142+
orderHistory.postValue(orderHistoryElements)
143+
}
144+
}
145+
146+
override fun onError(message: String) {
147+
viewModelScope.launch {
148+
orderHistoryEvent.send(Event.LOADED)
149+
}
150+
}
151+
152+
})
153+
} else {
154+
orderHistoryEvent.send(Event.OFFLINE)
155+
}
156+
157+
}
158+
159+
override fun getOrderHistory(): LiveData<List<OrderHistoryElement>> = orderHistory
160+
override fun getEvents(): LiveData<Event> = orderHistoryEvent.receiveAsFlow().asLiveData()
161+
162+
163+
enum class Event {
164+
LOADED, LOADING, OFFLINE
165+
}
166+
}

0 commit comments

Comments
 (0)