Cupcake/app/src/main/java/com/example/cupcake/ui/OrderViewModel.kt
2023-05-09 17:14:45 -04:00

119 lines
3.9 KiB
Kotlin

/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.cupcake.ui
import androidx.lifecycle.ViewModel
import com.example.cupcake.data.OrderUiState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import java.text.NumberFormat
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
/** Price for a single cupcake */
private const val PRICE_PER_CUPCAKE = 2.00
/** Additional cost for same day pickup of an order */
private const val PRICE_FOR_SAME_DAY_PICKUP = 3.00
/**
* [OrderViewModel] holds information about a cupcake order in terms of quantity, flavor, and
* pickup date. It also knows how to calculate the total price based on these order details.
*/
class OrderViewModel : ViewModel() {
/**
* Cupcake state for this order
*/
private val _uiState = MutableStateFlow(OrderUiState(pickupOptions = pickupOptions()))
val uiState: StateFlow<OrderUiState> = _uiState.asStateFlow()
/**
* Set the quantity [numberCupcakes] of cupcakes for this order's state and update the price
*/
fun setQuantity(numberCupcakes: Int) {
_uiState.update { currentState ->
currentState.copy(
quantity = numberCupcakes,
price = calculatePrice(quantity = numberCupcakes)
)
}
}
/**
* Set the [desiredFlavor] of cupcakes for this order's state.
* Only 1 flavor can be selected for the whole order.
*/
fun setFlavor(desiredFlavor: String) {
_uiState.update { currentState ->
currentState.copy(flavor = desiredFlavor)
}
}
/**
* Set the [pickupDate] for this order's state and update the price
*/
fun setDate(pickupDate: String) {
_uiState.update { currentState ->
currentState.copy(
date = pickupDate,
price = calculatePrice(pickupDate = pickupDate)
)
}
}
/**
* Reset the order state
*/
fun resetOrder() {
_uiState.value = OrderUiState(pickupOptions = pickupOptions())
}
/**
* Returns the calculated price based on the order details.
*/
private fun calculatePrice(
quantity: Int = _uiState.value.quantity,
pickupDate: String = _uiState.value.date
): String {
var calculatedPrice = quantity * PRICE_PER_CUPCAKE
// If the user selected the first option (today) for pickup, add the surcharge
if (pickupOptions()[0] == pickupDate) {
calculatedPrice += PRICE_FOR_SAME_DAY_PICKUP
}
val formattedPrice = NumberFormat.getCurrencyInstance().format(calculatedPrice)
return formattedPrice
}
/**
* Returns a list of date options starting with the current date and the following 3 dates.
*/
private fun pickupOptions(): List<String> {
val dateOptions = mutableListOf<String>()
val formatter = SimpleDateFormat("E MMM d", Locale.getDefault())
val calendar = Calendar.getInstance()
// add current date and the following 3 dates.
repeat(4) {
dateOptions.add(formatter.format(calendar.time))
calendar.add(Calendar.DATE, 1)
}
return dateOptions
}
}