diff --git a/app/src/main/java/com/jusiCool/jusicool_android/JusiCool_Android_NavHost.kt b/app/src/main/java/com/jusiCool/jusicool_android/JusiCool_Android_NavHost.kt index f1379d64..08573069 100644 --- a/app/src/main/java/com/jusiCool/jusicool_android/JusiCool_Android_NavHost.kt +++ b/app/src/main/java/com/jusiCool/jusicool_android/JusiCool_Android_NavHost.kt @@ -36,10 +36,10 @@ import com.jusiCool.presentation.search.screen.searchRoute import com.jusiCool.presentation.splash.screen.splashRoute import com.jusiCool.presentation.stockDetail.screen.navigateToStockDetail import com.jusiCool.presentation.stockDetail.screen.stockDetailRoute -import com.jusiCool.presentation.stockBuying.screen.stockBuyingRoute -import com.jusiCool.presentation.stockReservationBuying.screen.stockReservationBuyingRoute +import com.jusiCool.presentation.stockBuy.screen.stockBuyingRoute +import com.jusiCool.presentation.stockReservationBuy.screen.stockReservationBuyRoute import com.jusiCool.presentation.stockReservationSelling.screen.stockReservationSellingRoute -import com.jusiCool.presentation.stockReservationBuying.screen.stockSell.screen.stockSellingRoute +import com.jusiCool.presentation.stockSell.screen.stockSellingRoute @Composable fun JusiCool_Android_NavHost( @@ -107,7 +107,7 @@ fun JusiCool_Android_NavHost( navigateToOrderHistory = navController::navigateToOrderHistory, ) - stockReservationBuyingRoute( + stockReservationBuyRoute( navigateToStockDetail = navController::navigateToStockDetail, navigateToOrderHistory = navController::navigateToOrderHistory, ) diff --git a/presentation/src/main/java/com/jusiCool/presentation/stockBuying/screen/StockBuyingScreen.kt b/presentation/src/main/java/com/jusiCool/presentation/stockBuy/screen/StockBuyingScreen.kt similarity index 99% rename from presentation/src/main/java/com/jusiCool/presentation/stockBuying/screen/StockBuyingScreen.kt rename to presentation/src/main/java/com/jusiCool/presentation/stockBuy/screen/StockBuyingScreen.kt index e5e2915c..793b7a69 100644 --- a/presentation/src/main/java/com/jusiCool/presentation/stockBuying/screen/StockBuyingScreen.kt +++ b/presentation/src/main/java/com/jusiCool/presentation/stockBuy/screen/StockBuyingScreen.kt @@ -1,4 +1,4 @@ -package com.jusiCool.presentation.stockBuying.screen +package com.jusiCool.presentation.stockBuy.screen import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement diff --git a/presentation/src/main/java/com/jusiCool/presentation/stockBuying/viewModel/.gitkeep b/presentation/src/main/java/com/jusiCool/presentation/stockBuying/viewModel/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuy/screen/StockReservationBuyScreen.kt b/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuy/screen/StockReservationBuyScreen.kt new file mode 100644 index 00000000..5d297c7e --- /dev/null +++ b/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuy/screen/StockReservationBuyScreen.kt @@ -0,0 +1,256 @@ +package com.jusiCool.presentation.stockReservationBuy.screen + +import androidx.activity.ComponentActivity +import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.mutableLongStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusManager +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable +import com.example.design_system.component.button.ButtonState +import com.example.design_system.component.button.JDSButton +import com.example.design_system.component.modifier.clickableSingle.clickableSingle +import com.example.design_system.component.textfield.JDSTextField +import com.example.design_system.component.topbar.JDSArrowTopBar +import com.example.design_system.icon_image.icon.LeftArrowIcon +import com.example.design_system.icon_image.icon.RightArrowIcon +import com.example.design_system.icon_image.image.CostImage +import com.example.design_system.theme.JDSTypography +import com.example.design_system.theme.JusiCoolAndroidTheme +import com.example.design_system.theme.color.JDSColor +import com.jusiCool.presentation.main.component.EntireStocksData +import com.jusiCool.presentation.main.component.MyAccountData +import com.jusiCool.presentation.main.screen.tempMyAccountData +import com.jusiCool.presentation.stockReservationBuy.viewmodel.StockReservationBuyViewModel +import com.jusiCool.presentation.utill.formatStockPrice + +const val stockReservationBuyRoute = "stockReservationBuyRoute" + +fun NavController.navigationToStockReservationBuy(id: String) { + this.navigate("${stockReservationBuyRoute}/${id}") +} + +fun NavGraphBuilder.stockReservationBuyRoute( + navigateToStockDetail: (String) -> Unit, + navigateToOrderHistory: () -> Unit, +) { + composable("$stockReservationBuyRoute}/{id}") { backStackEntry -> + val id = backStackEntry.arguments?.getString("id") + if (id != null) { + StockReservationBuyRoute( + id = id, + navigateToStockDetail = navigateToStockDetail, + navigateToOrderHistory = navigateToOrderHistory + ) + } + } +} + +@Composable +internal fun StockReservationBuyRoute( + modifier: Modifier = Modifier, + viewModel: StockReservationBuyViewModel = hiltViewModel(LocalContext.current as ComponentActivity), + id: String, + navigateToStockDetail: (String) -> Unit, + navigateToOrderHistory: () -> Unit, +) { + val focusManager = LocalFocusManager.current + + StockReservationBuyScreen( + modifier = modifier, + id = id, + myAccountData = tempMyAccountData, + entireStocksData = EntireStocksData("", "", 10000, 8160, 6, 4.9f), + navigateToStockDetail = navigateToStockDetail, + navigateToOrderHistory = navigateToOrderHistory, + focusManager = focusManager, + postStock = viewModel.postStock.longValue, + postReserveStock = viewModel.postReserveStock.longValue, + postBuyStock = {num, goal_price -> + viewModel.postBuyStock( + stockId = id, + num = num, + goal_price = goal_price + ) + viewModel.postStock.longValue = 0 + viewModel.postReserveStock.longValue = 0 + } + ) +} + +@Composable +internal fun StockReservationBuyScreen( + modifier: Modifier = Modifier, + id: String, + myAccountData: MyAccountData, + entireStocksData: EntireStocksData, + postBuyStock: (num: Long, goal_price: Long) -> Unit, + navigateToStockDetail: (String) -> Unit, + navigateToOrderHistory: () -> Unit, + focusManager: FocusManager, + postStock: Long, + postReserveStock: Long +) { + val (stockReservationTextState, setStockReservationTextState) = remember { mutableLongStateOf(postStock) } + val (stockTextState, setStockTextState) = remember { mutableLongStateOf(postReserveStock) } + val (pager, setPager) = remember { mutableStateOf(1) } + + CompositionLocalProvider(LocalFocusManager provides focusManager) { + JusiCoolAndroidTheme { colors, _ -> + Column( + modifier = modifier + .fillMaxSize() + .background(color = colors.WHITE) + .pointerInput(Unit) { + detectTapGestures { + focusManager.clearFocus() + } + }, + horizontalAlignment = Alignment.CenterHorizontally + ) { + JDSArrowTopBar( + startIcon = { + LeftArrowIcon(modifier = Modifier.clickableSingle { + if (pager == 2) setPager(1) + else navigateToStockDetail(id) + }) + }, + betweenText = "주식 구매" + ) + + when (pager) { + 1 -> { + Spacer(modifier = Modifier.height(40.dp)) + + JDSTextField( + modifier = Modifier.padding(horizontal = 24.dp), + textState = stockReservationTextState.toString(), + placeHolder = "예약 금액을 달성했을 때 주식을 구매해요", + label = "예약 금액을 입력하세요", + helperText = "지금 주식 가격: ${entireStocksData.myStockPrice.formatStockPrice()} P", + onTextChange = { setStockReservationTextState(it.toLong()) } + ) + + Spacer(modifier = Modifier.weight(1f)) + + JDSButton( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 32.dp), + state = if (stockReservationTextState == 0L) ButtonState.Disable else ButtonState.Enable, + text = "다음", + onClick = { setPager(2) } + ) + } + + 2 -> { + Spacer(modifier = Modifier.height(40.dp)) + + JDSTextField( + modifier = Modifier.padding(horizontal = 24.dp), + textState = stockTextState.toString(), + placeHolder = "최대 N주 구매 가능", + label = "몇 주 구매할까요?", + helperText = "보유 포인트 ${myAccountData.point.formatStockPrice()} P", + placerHolderShare = true, + onTextChange = { setStockTextState(it.toLong()) } + ) + + Spacer(modifier = Modifier.weight(1f)) + + JDSButton( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp, vertical = 32.dp), + state = if (stockTextState == 0L) ButtonState.Disable else ButtonState.Enable, + text = "구매 하기", + onClick = { + postBuyStock( + stockTextState, + stockReservationTextState + ) + setPager(3) + } + ) + } + + 3 -> { + Column( + modifier = modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(modifier = Modifier.height(120.dp)) + + CostImage(modifier = Modifier.size(177.dp)) + + Text( + text = "${entireStocksData.stockName} ${stockTextState.toInt().formatStockPrice()}주\n" + + "${(stockTextState.toInt() * stockReservationTextState.toInt()).formatStockPrice()}P 구매 예약 성공", + style = JDSTypography.subTitle, + color = JDSColor.Black, + textAlign = TextAlign.Center + ) + + Spacer(modifier = Modifier.height(16.dp)) + + Row( + modifier = Modifier.clickableSingle { navigateToOrderHistory() }, + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "구매 내역 보러가기", + style = JDSTypography.label, + color = JDSColor.GRAY600 + ) + + RightArrowIcon() + } + } + } + } + } + } + } +} + + +@Preview +@Composable +fun StockReservationBuyingScreenPreview() { + StockReservationBuyScreen( + id = "", + myAccountData = tempMyAccountData, + entireStocksData = EntireStocksData("", "", 10000, 8160, 23, 9.3f), + navigateToStockDetail = {}, + navigateToOrderHistory = {}, + focusManager = LocalFocusManager.current, + postStock = 0, + postReserveStock = 0, + postBuyStock = {_, _ ->} + ) +} \ No newline at end of file diff --git a/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuy/viewmodel/StockReservationBuyViewModel.kt b/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuy/viewmodel/StockReservationBuyViewModel.kt new file mode 100644 index 00000000..5bb20d3f --- /dev/null +++ b/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuy/viewmodel/StockReservationBuyViewModel.kt @@ -0,0 +1,52 @@ +package com.jusiCool.presentation.stockReservationBuy.viewmodel + +import androidx.compose.runtime.mutableLongStateOf +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.jusiCool.domain.model.stock.request.BuyStockRequestModel +import com.jusiCool.domain.usecase.stock.BuyStockReserveUseCase +import com.jusiCool.presentation.utill.Event +import com.jusiCool.presentation.utill.errorHandling +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class StockReservationBuyViewModel @Inject constructor( + private val buyStockReserveUseCase: BuyStockReserveUseCase +) : ViewModel() { + + private val _buyStockReserveResponse = MutableStateFlow>(Event.Loading) + val buyStockReserveResponse = _buyStockReserveResponse.asStateFlow() + + var postStock = mutableLongStateOf(0) + private set + + var postReserveStock = mutableLongStateOf(0) + private set + + fun postBuyStock( + stockId: String, + num: Long, + goal_price: Long, + ) = viewModelScope.launch { + buyStockReserveUseCase( + stockId = stockId, + body = BuyStockRequestModel( + num = num, + goal_price = goal_price + ) + ).onSuccess { + it.catch { remoteError -> + _buyStockReserveResponse.value = remoteError.errorHandling() + }.collect { + _buyStockReserveResponse.value = Event.Success() + } + }.onFailure { error -> + _buyStockReserveResponse.value = error.errorHandling() + } + } +} \ No newline at end of file diff --git a/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuying/screen/StockReservationBuying.kt b/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuying/screen/StockReservationBuying.kt deleted file mode 100644 index 9214af6f..00000000 --- a/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuying/screen/StockReservationBuying.kt +++ /dev/null @@ -1,206 +0,0 @@ -package com.jusiCool.presentation.stockReservationBuying.screen - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.compose.composable -import com.example.design_system.component.button.ButtonState -import com.example.design_system.component.button.JDSButton -import com.example.design_system.component.modifier.clickableSingle.clickableSingle -import com.example.design_system.component.textfield.JDSTextField -import com.example.design_system.component.topbar.JDSArrowTopBar -import com.example.design_system.icon_image.icon.LeftArrowIcon -import com.example.design_system.icon_image.icon.RightArrowIcon -import com.example.design_system.icon_image.image.CostImage -import com.example.design_system.theme.JDSTypography -import com.example.design_system.theme.color.JDSColor -import com.jusiCool.presentation.main.component.EntireStocksData -import com.jusiCool.presentation.main.component.MyAccountData -import com.jusiCool.presentation.main.screen.tempMyAccountData -import com.jusiCool.presentation.utill.formatStockPrice - -const val stockReservationBuyingRoute = "stockReservationBuyingRoute" - -fun NavController.navigationToStockReservationBuying(id: String) { - this.navigate("$stockReservationBuyingRoute/$id") -} - -fun NavGraphBuilder.stockReservationBuyingRoute( - navigateToStockDetail: (String) -> Unit, - navigateToOrderHistory: () -> Unit, -) { - composable("$stockReservationBuyingRoute/{id}") { backStackEntry -> - val id = backStackEntry.arguments?.getString("id") ?: "" - StockReservationBuyingRoute( - id = id, - navigateToStockDetail = navigateToStockDetail, - navigateToOrderHistory = navigateToOrderHistory - ) - } -} - -@Composable -internal fun StockReservationBuyingRoute( - modifier: Modifier = Modifier, - id: String, - navigateToStockDetail: (String) -> Unit, - navigateToOrderHistory: () -> Unit, -) { - StockReservationBuyingScreen( - modifier = modifier, - id = id, - myAccountData = tempMyAccountData, - entireStocksData = EntireStocksData(id = "1L", "마이크로소프트", 1231, 10000, 8160, 7.9f), - navigateToStockDetail = navigateToStockDetail, - navigateToOrderHistory = navigateToOrderHistory - ) -} - -@Composable -internal fun StockReservationBuyingScreen( - modifier: Modifier = Modifier, - id: String, - myAccountData: MyAccountData, - entireStocksData: EntireStocksData, - navigateToStockDetail: (String) -> Unit, - navigateToOrderHistory: () -> Unit, -) { - val (stockReservationTextState, setStockReservationTextState) = remember { mutableStateOf("") } - val (stockTextState, setStockTextState) = remember { mutableStateOf("") } - val (pager, setPager) = remember { mutableIntStateOf(1) } - - Column( - modifier = modifier - .fillMaxSize() - .background(color = JDSColor.WHITE), - horizontalAlignment = Alignment.CenterHorizontally - ) { - JDSArrowTopBar( - startIcon = { - LeftArrowIcon(modifier = Modifier.clickableSingle { - if (pager == 2) setPager(1) - else navigateToStockDetail(id) - }) - }, - betweenText = "주식 구매" - ) - - when (pager) { - 1 -> { - Spacer(modifier = Modifier.height(40.dp)) - - JDSTextField( - modifier = Modifier.padding(horizontal = 24.dp), - textState = stockReservationTextState, - placeHolder = "예약 금액을 달성했을 때 주식을 구매해요", - label = "예약 금액을 입력하세요", - helperText = "지금 주식 가격: ${entireStocksData.myStockPrice.formatStockPrice()} P", - onTextChange = setStockReservationTextState - ) - - Spacer(modifier = Modifier.weight(1f)) - - JDSButton( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 20.dp, vertical = 32.dp), - state = if (stockReservationTextState.isEmpty()) ButtonState.Disable else ButtonState.Enable, - text = "다음", - onClick = { setPager(2) } - ) - } - - 2 -> { - Spacer(modifier = Modifier.height(40.dp)) - - JDSTextField( - modifier = Modifier.padding(horizontal = 24.dp), - textState = stockTextState, - placeHolder = "최대 N주 구매 가능", - label = "몇 주 구매할까요?", - helperText = "보유 포인트 ${myAccountData.point.formatStockPrice()} P", - placerHolderShare = true, - onTextChange = setStockTextState - ) - - Spacer(modifier = Modifier.weight(1f)) - - JDSButton( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 20.dp, vertical = 32.dp), - state = if (stockTextState.isEmpty()) ButtonState.Disable else ButtonState.Enable, - text = "구매 하기", - onClick = { setPager(3) } - ) - } - - 3 -> { - Column( - modifier = modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Spacer(modifier = Modifier.height(120.dp)) - - CostImage(modifier = Modifier.size(177.dp)) - - Text( - text = "${entireStocksData.stockName} ${stockTextState.formatStockPrice()}주\n" + - "${(stockTextState.toInt() * stockReservationTextState.toInt()).formatStockPrice()}P 구매 예약 성공", - style = JDSTypography.subTitle, - color = JDSColor.Black, - textAlign = TextAlign.Center - ) - - Spacer(modifier = Modifier.height(16.dp)) - - Row( - modifier = Modifier.clickableSingle { navigateToOrderHistory() }, - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = "구매 내역 보러가기", - style = JDSTypography.label, - color = JDSColor.GRAY600 - ) - - RightArrowIcon() - } - } - } - } - } -} - - -@Preview -@Composable -fun StockReservationBuyingScreenPreview() { - StockReservationBuyingScreen( - myAccountData = tempMyAccountData, - entireStocksData = EntireStocksData(id = "1L", "마이크로소프트", 1231, 10000, 8160, 7.9f), - navigateToStockDetail = {}, - navigateToOrderHistory = {}, - id = "1L" - ) -} \ No newline at end of file diff --git a/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuying/screen/stockSell/screen/StockSellScreen.kt b/presentation/src/main/java/com/jusiCool/presentation/stockSell/screen/StockSellScreen.kt similarity index 97% rename from presentation/src/main/java/com/jusiCool/presentation/stockReservationBuying/screen/stockSell/screen/StockSellScreen.kt rename to presentation/src/main/java/com/jusiCool/presentation/stockSell/screen/StockSellScreen.kt index 2cf97b8e..c337585a 100644 --- a/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuying/screen/stockSell/screen/StockSellScreen.kt +++ b/presentation/src/main/java/com/jusiCool/presentation/stockSell/screen/StockSellScreen.kt @@ -1,4 +1,4 @@ -package com.jusiCool.presentation.stockReservationBuying.screen.stockSell.screen +package com.jusiCool.presentation.stockSell.screen import androidx.activity.ComponentActivity import androidx.compose.foundation.background @@ -38,7 +38,7 @@ import com.example.design_system.theme.color.JDSColor import com.jusiCool.domain.model.user.response.GetMyStockModel import com.jusiCool.presentation.main.component.EntireStocksData import com.jusiCool.presentation.main.viewModel.MainViewModel -import com.jusiCool.presentation.stockReservationBuying.screen.stockSell.viewModel.StockSellViewModel +import com.jusiCool.presentation.stockSell.viewModel.StockSellViewModel import com.jusiCool.presentation.utill.formatStockPrice const val stockSellingRoute = "stockSellingRoute" diff --git a/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuying/screen/stockSell/viewModel/StockSellViewModel.kt b/presentation/src/main/java/com/jusiCool/presentation/stockSell/viewModel/StockSellViewModel.kt similarity index 94% rename from presentation/src/main/java/com/jusiCool/presentation/stockReservationBuying/screen/stockSell/viewModel/StockSellViewModel.kt rename to presentation/src/main/java/com/jusiCool/presentation/stockSell/viewModel/StockSellViewModel.kt index 41446cad..95262a08 100644 --- a/presentation/src/main/java/com/jusiCool/presentation/stockReservationBuying/screen/stockSell/viewModel/StockSellViewModel.kt +++ b/presentation/src/main/java/com/jusiCool/presentation/stockSell/viewModel/StockSellViewModel.kt @@ -1,4 +1,4 @@ -package com.jusiCool.presentation.stockReservationBuying.screen.stockSell.viewModel +package com.jusiCool.presentation.stockSell.viewModel import androidx.compose.runtime.mutableLongStateOf import androidx.lifecycle.ViewModel