2026-01-14 15:42:26 +09:00
|
|
|
// src/main/kotlin/ui/PeriodTrendCard.kt (신규/통합)
|
|
|
|
|
package ui
|
|
|
|
|
|
|
|
|
|
import androidx.compose.foundation.Canvas
|
|
|
|
|
import androidx.compose.foundation.layout.*
|
|
|
|
|
import androidx.compose.material.*
|
|
|
|
|
import androidx.compose.runtime.Composable
|
|
|
|
|
import androidx.compose.ui.Alignment
|
|
|
|
|
import androidx.compose.ui.Modifier
|
|
|
|
|
import androidx.compose.ui.geometry.Offset
|
|
|
|
|
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.CandleData
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
fun PeriodTrendCard(label: String, data: List<CandleData>, modifier: Modifier = Modifier) {
|
|
|
|
|
val avgPrice = if (data.isEmpty()) "0"
|
2026-01-22 16:21:18 +09:00
|
|
|
else String.format("%,d", data.map { it.stck_prpr.toDoubleOrNull() ?: 0.0 }.average().toLong())
|
2026-01-14 15:42:26 +09:00
|
|
|
|
|
|
|
|
Card(modifier = modifier.height(80.dp), elevation = 2.dp, backgroundColor = Color.White) {
|
|
|
|
|
Row(modifier = Modifier.padding(8.dp), verticalAlignment = Alignment.CenterVertically) {
|
|
|
|
|
// [좌측] 라벨 및 평균가
|
|
|
|
|
Column(modifier = Modifier.weight(0.4f)) {
|
|
|
|
|
Text(label, fontSize = 10.sp, color = Color.Gray)
|
|
|
|
|
Text(text = "${avgPrice}원", fontSize = 12.sp, fontWeight = FontWeight.Bold)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// [우측] 간소화된 그래프 (Sparkline)
|
|
|
|
|
Box(modifier = Modifier.weight(0.6f).fillMaxHeight()) {
|
|
|
|
|
if (data.isNotEmpty()) {
|
|
|
|
|
Canvas(modifier = Modifier.fillMaxSize()) {
|
2026-01-22 16:21:18 +09:00
|
|
|
val prices = data.map { it.stck_prpr.toDoubleOrNull() ?: 0.0 }
|
2026-01-14 15:42:26 +09:00
|
|
|
val max = prices.maxOrNull() ?: 1.0
|
|
|
|
|
val min = prices.minOrNull() ?: 0.0
|
|
|
|
|
val range = if (max == min) 1.0 else max - min
|
|
|
|
|
|
|
|
|
|
val stepX = size.width / (prices.size - 1).coerceAtLeast(1)
|
|
|
|
|
val points = prices.mapIndexed { i, p ->
|
|
|
|
|
Offset(i * stepX, (size.height - ((p - min) / range * size.height)).toFloat())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i in 0 until points.size - 1) {
|
|
|
|
|
drawLine(
|
|
|
|
|
color = if (prices.last() >= prices.first()) Color(0xFFE03E2D) else Color(0xFF0E62CF),
|
|
|
|
|
start = points[i],
|
|
|
|
|
end = points[i + 1],
|
|
|
|
|
strokeWidth = 2f
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|