...
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
// src/main/kotlin/ui/MarketSection.kt
|
||||
package ui
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.TabRowDefaults.tabIndicatorOffset
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import model.RankingStock
|
||||
import model.RankingType
|
||||
import network.KisTradeService
|
||||
|
||||
@Composable
|
||||
fun MarketSection(
|
||||
tradeService: KisTradeService,
|
||||
onStockSelect: (code: String, name: String, isDomestic: Boolean) -> Unit
|
||||
) {
|
||||
var selectedTab by remember { mutableStateOf(RankingType.VOLUME) }
|
||||
var isDomestic by remember { mutableStateOf(true) }
|
||||
var rankingList by remember { mutableStateOf<List<RankingStock>>(emptyList()) }
|
||||
var isLoading by remember { mutableStateOf(false) }
|
||||
|
||||
// 탭 또는 국가 변경 시 데이터 로드
|
||||
LaunchedEffect(selectedTab, isDomestic) {
|
||||
isLoading = true
|
||||
tradeService.fetchMarketRanking(selectedTab, isDomestic).onSuccess {
|
||||
rankingList = it
|
||||
}.onFailure {
|
||||
rankingList = emptyList()
|
||||
}
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
// [1] 상단 타이틀 및 국내/해외 토글
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text("시장 랭킹 (TOP 20)", style = MaterialTheme.typography.subtitle1, fontWeight = FontWeight.Bold)
|
||||
|
||||
// 국내/해외 전환 스위치 방식
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(if (isDomestic) "국내" else "해외", fontSize = 12.sp, fontWeight = FontWeight.Medium)
|
||||
Switch(
|
||||
checked = !isDomestic,
|
||||
onCheckedChange = { isDomestic = !it },
|
||||
colors = SwitchDefaults.colors(checkedThumbColor = Color(0xFF0E62CF))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// [2] 랭킹 타입 탭 (상승, 하락, 거래량 등)
|
||||
ScrollableTabRow(
|
||||
selectedTabIndex = selectedTab.ordinal,
|
||||
backgroundColor = Color.Transparent,
|
||||
contentColor = Color.Black,
|
||||
edgePadding = 0.dp,
|
||||
indicator = { tabPositions ->
|
||||
TabRowDefaults.Indicator(
|
||||
Modifier.tabIndicatorOffset(tabPositions[selectedTab.ordinal]),
|
||||
color = Color(0xFFE03E2D)
|
||||
)
|
||||
}
|
||||
) {
|
||||
RankingType.values().forEach { type ->
|
||||
Tab(
|
||||
selected = selectedTab == type,
|
||||
onClick = { selectedTab = type },
|
||||
text = { Text(type.title, fontSize = 12.sp) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
// [3] 랭킹 리스트
|
||||
if (isLoading) {
|
||||
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
CircularProgressIndicator(strokeWidth = 2.dp)
|
||||
}
|
||||
} else {
|
||||
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||
items(rankingList.withIndex().toList()) { (index, stock) ->
|
||||
MarketStockItemRow(index + 1, stock) {
|
||||
onStockSelect(stock.code, stock.name, isDomestic)
|
||||
}
|
||||
Divider(color = Color(0xFFF5F5F5), thickness = 0.5.dp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user