diff --git a/.gitignore b/.gitignore
index aa724b7..faf530b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,7 @@
*.iml
.gradle
/local.properties
-/.idea/caches
-/.idea/libraries
-/.idea/modules.xml
-/.idea/workspace.xml
-/.idea/navEditor.xml
-/.idea/assetWizardSettings.xml
+/.idea/
.DS_Store
/build
/captures
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml
deleted file mode 100644
index 4a53bee..0000000
--- a/.idea/AndroidProjectSystem.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/appInsightsSettings.xml b/.idea/appInsightsSettings.xml
deleted file mode 100644
index 371f2e2..0000000
--- a/.idea/appInsightsSettings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index b86273d..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
deleted file mode 100644
index b268ef3..0000000
--- a/.idea/deploymentTargetSelector.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 97f0a8e..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/migrations.xml b/.idea/migrations.xml
deleted file mode 100644
index f8051a6..0000000
--- a/.idea/migrations.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 74dd639..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index 16660f1..0000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/com/hyeon/dayroutine/MainActivity.kt b/app/src/main/java/com/hyeon/dayroutine/MainActivity.kt
index 1a1fe00..147f907 100644
--- a/app/src/main/java/com/hyeon/dayroutine/MainActivity.kt
+++ b/app/src/main/java/com/hyeon/dayroutine/MainActivity.kt
@@ -2,6 +2,7 @@ package com.hyeon.dayroutine
import android.os.Bundle
import androidx.activity.ComponentActivity
+import androidx.activity.SystemBarStyle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
@@ -10,38 +11,26 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.tooling.preview.Preview
+import com.hyeon.dayroutine.ui.home.HomeScreen
import com.hyeon.dayroutine.ui.theme.DayRoutineTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- enableEdgeToEdge()
+ enableEdgeToEdge(
+ statusBarStyle = SystemBarStyle.dark(
+ scrim = Color.Transparent.toArgb()
+ )
+ )
setContent {
DayRoutineTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
- Greeting(
- name = "Android",
- modifier = Modifier.padding(innerPadding)
- )
+ HomeScreen()
}
}
}
}
-}
-
-@Composable
-fun Greeting(name: String, modifier: Modifier = Modifier) {
- Text(
- text = "Hello $name!",
- modifier = modifier
- )
-}
-
-@Preview(showBackground = true)
-@Composable
-fun GreetingPreview() {
- DayRoutineTheme {
- Greeting("Android")
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/hyeon/dayroutine/ui/component/RoutineProgress.kt b/app/src/main/java/com/hyeon/dayroutine/ui/component/RoutineProgress.kt
new file mode 100644
index 0000000..b3ab257
--- /dev/null
+++ b/app/src/main/java/com/hyeon/dayroutine/ui/component/RoutineProgress.kt
@@ -0,0 +1,41 @@
+package com.hyeon.dayroutine.ui.component
+
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.LinearProgressIndicator
+import androidx.compose.material3.ProgressIndicatorDefaults.drawStopIndicator
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.geometry.CornerRadius
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.StrokeCap
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun RoutineProgress(
+ modifier: Modifier,
+ progress: Float
+) {
+ Canvas(
+ modifier = modifier
+ .fillMaxWidth()
+ .height(6.dp)
+ ) {
+ val radius = size.height / 2
+
+ drawRoundRect(
+ color = Color(0xFF33334a),
+ cornerRadius = CornerRadius(radius)
+ )
+
+ drawRoundRect(
+ color = Color(0xFF6c63ff),
+ cornerRadius = CornerRadius(radius),
+ size = Size(width = size.width * progress, height = size.height)
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hyeon/dayroutine/ui/home/AddRoutineBottomSheet.kt b/app/src/main/java/com/hyeon/dayroutine/ui/home/AddRoutineBottomSheet.kt
new file mode 100644
index 0000000..a3b37e5
--- /dev/null
+++ b/app/src/main/java/com/hyeon/dayroutine/ui/home/AddRoutineBottomSheet.kt
@@ -0,0 +1,328 @@
+package com.hyeon.dayroutine.ui.home
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.FlowRow
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.aspectRatio
+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.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ModalBottomSheet
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.SheetState
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+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 java.time.DayOfWeek
+import java.time.format.TextStyle
+import java.util.Locale
+import kotlin.collections.listOf
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun AddRoutineBottomSheet(
+ bottomSheetState: SheetState,
+ onDismiss: () -> Unit,
+) {
+ var text by remember { mutableStateOf("") }
+ var selectedIcon by remember { mutableStateOf("") }
+ var startTime by remember { mutableStateOf("") }
+ var durationTime by remember { mutableStateOf("") }
+ var selectedDates by remember { mutableStateOf(setOf()) }
+
+ ModalBottomSheet(
+ onDismissRequest = onDismiss,
+ sheetState = bottomSheetState,
+ shape = RoundedCornerShape(20.dp),
+ containerColor = Color(0xFF1a1a2e)
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 20.dp),
+ verticalArrangement = Arrangement.spacedBy(12.dp)
+ ) {
+ Text(
+ text = "새 루틴 추가",
+ color = Color.White,
+ fontSize = 18.sp,
+ fontWeight = FontWeight.Bold
+ )
+
+ RoutineNameEditBox(
+ text = text,
+ onValueChanged = { text = it }
+ )
+
+ RoutineIconSelector(
+ selectedIcon = selectedIcon,
+ onSelected = { selectedIcon = it }
+ )
+
+ RoutineTimeBox(
+ startTime = startTime,
+ durationTime = durationTime,
+ onStartTimeValueChanged = { startTime = it },
+ onDurationTimeValueChanged = { durationTime = it }
+ )
+
+ RoutineDateSelector(
+ selectedDates = selectedDates,
+ onSelected = { date ->
+ selectedDates = if (selectedDates.contains(date)) selectedDates - date else selectedDates + date
+ }
+ )
+
+ Button(
+ modifier = Modifier
+ .fillMaxWidth(),
+ contentPadding = PaddingValues(vertical = 12.dp),
+ shape = RoundedCornerShape(12.dp),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = Color(0xFF6c63ff)
+ ),
+ onClick = { /** 루틴 저장하기 **/ }
+ ) {
+ Text(
+ text = "루틴 저장하기",
+ color = Color.White,
+ fontSize = 18.sp,
+ fontWeight = FontWeight.Bold
+ )
+ }
+
+ }
+ }
+}
+
+@Composable
+fun RoutineNameEditBox(
+ text: String,
+ onValueChanged: (String) -> Unit
+) {
+ Text(
+ text = "루틴 이름",
+ color = Color.Gray,
+ fontSize = 12.sp,
+ )
+ /** Basic TextField로 디테일한 TextField 수정 **/
+ OutlinedTextField(
+ modifier = Modifier
+ .fillMaxWidth(),
+ value = text,
+ onValueChange = onValueChanged,
+ placeholder = {
+ Text(
+ text = "예) 스트레칭, 독서...",
+ color = Color(0xFF555577)
+ )
+ },
+ singleLine = true,
+ shape = RoundedCornerShape(20.dp),
+ )
+}
+
+@Composable
+fun RoutineIconSelector(
+ selectedIcon: String,
+ onSelected: (String) -> Unit
+) {
+ Text(
+ text = "아이콘",
+ color = Color.Gray,
+ fontSize = 12.sp,
+ )
+ BoxWithConstraints(
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ val itemMinWidth = 50.dp
+ val space = 8.dp
+
+ /** 전체너비 = 아이템너비 * n + spacing * (n-1)
+ * 전체너비 = 아이템너비 * n + spacing * n - spacing
+ * 전체너비 + spacing = n(아이템너비 + spacing)
+ *
+ * 아이템너비 * n = 전체너비 - spacing * (n-1)
+ * 아이템 너비 = (전체너비 + spacing - (spacing * n)) / n
+ * **/
+ val maxItems = ((maxWidth + space) / (itemMinWidth + space)).toInt()
+ val itemWidth = (maxWidth - space * (maxItems - 1)) / maxItems
+
+ FlowRow(
+ modifier = Modifier.fillMaxWidth(),
+ verticalArrangement = Arrangement.spacedBy(12.dp),
+ horizontalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ routineIconList.forEach { icon ->
+ Surface(
+ modifier = Modifier.size(itemWidth),
+ shape = RoundedCornerShape(10.dp),
+ color = if (icon == selectedIcon) Color(0xFF6c63ff) else Color((0xFF1a1a2e)),
+ border = if (icon == selectedIcon) BorderStroke(
+ width = 1.5.dp,
+ color = Color(0xFF6c63ff)
+ )
+ else BorderStroke(
+ width = 1.dp,
+ color = Color(0xFF2a2a3e)
+ ),
+ onClick = { onSelected(icon) }
+ ) {
+ Box(contentAlignment = Alignment.Center) {
+ Text(
+ text = icon,
+ )
+ }
+ }
+ }
+ }
+ }
+
+}
+
+private val routineIconList = listOf("🧘", "🏃", "📖", "✍️", "💊", "🥗", "💧", "🎯")
+
+@Composable
+fun RoutineTimeBox(
+ startTime: String,
+ durationTime: String,
+ onStartTimeValueChanged: (String) -> Unit,
+ onDurationTimeValueChanged: (String) -> Unit
+) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth(),
+ horizontalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ TimeEditBox(
+ modifier = Modifier.weight(1f),
+ timeLabel = "시작 시간",
+ timeText = startTime,
+ onValueChanged = onStartTimeValueChanged,
+ placeHolder = {
+ Text(
+ text = "오전 7:00",
+ fontSize = 14.sp,
+ color = Color(0xFF555577)
+ )
+ }
+ )
+
+ TimeEditBox(
+ modifier = Modifier.weight(1f),
+ timeLabel = "소요 시간",
+ timeText = durationTime,
+ onValueChanged = onDurationTimeValueChanged,
+ placeHolder = {
+ Text(
+ text = "10분",
+ fontSize = 14.sp,
+ color = Color(0xFF555577)
+ )
+ }
+ )
+ }
+}
+
+@Composable
+fun TimeEditBox(
+ modifier: Modifier = Modifier,
+ timeLabel: String,
+ timeText: String,
+ onValueChanged: (String) -> Unit,
+ placeHolder: @Composable () -> Unit
+) {
+ Column(
+ modifier = modifier.fillMaxWidth()
+ ) {
+ Text(
+ text = timeLabel,
+ color = Color.Gray,
+ fontSize = 12.sp,
+ )
+
+ Spacer(modifier = Modifier.height(12.dp))
+
+ OutlinedTextField(
+ value = timeText,
+ onValueChange = onValueChanged,
+ placeholder = placeHolder,
+ singleLine = true,
+ shape = RoundedCornerShape(20.dp)
+ )
+
+ }
+}
+
+@Composable
+fun RoutineDateSelector(
+ selectedDates: Set,
+ onSelected: (DayOfWeek) -> Unit
+) {
+ Column(
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Text(
+ text = "반복 요일",
+ color = Color.Gray,
+ fontSize = 12.sp,
+ )
+
+ Row(
+ modifier = Modifier
+ .fillMaxWidth(),
+ horizontalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ DayOfWeek.entries.forEach { date ->
+ Box(
+ modifier = Modifier
+ .weight(1f)
+ .aspectRatio(1f)
+ .background(
+ color = if (selectedDates.contains(date)) Color(0xFF6c63ff) else Color(0xFF1a1a2e),
+ shape = CircleShape
+ )
+ .border(
+ if (selectedDates.contains(date)) BorderStroke(width = 1.dp, color = Color(0xFF6c63ff))
+ else BorderStroke(width = 1.5.dp, color = Color(0xFF2a2a3e)),
+ shape = CircleShape
+ )
+ .clickable { onSelected(date) },
+ contentAlignment = Alignment.Center,
+ ) {
+ Text(
+ text = date.getDisplayName(TextStyle.SHORT, Locale.ENGLISH),
+ color = if (selectedDates.contains(date)) Color.White else Color.Gray,
+ fontWeight = FontWeight.Bold,
+ fontSize = 14.sp
+ )
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hyeon/dayroutine/ui/home/HomeScreen.kt b/app/src/main/java/com/hyeon/dayroutine/ui/home/HomeScreen.kt
new file mode 100644
index 0000000..4d545c2
--- /dev/null
+++ b/app/src/main/java/com/hyeon/dayroutine/ui/home/HomeScreen.kt
@@ -0,0 +1,425 @@
+package com.hyeon.dayroutine.ui.home
+
+import android.annotation.SuppressLint
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
+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.foundation.layout.statusBars
+import androidx.compose.foundation.layout.windowInsetsPadding
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Checkbox
+import androidx.compose.material3.CheckboxDefaults
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.material3.rememberModalBottomSheetState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.hyeon.dayroutine.domain.model.Routine
+import com.hyeon.dayroutine.ui.component.RoutineProgress
+import java.time.DayOfWeek
+import java.time.LocalDate
+import java.time.LocalTime
+import java.time.format.TextStyle
+import java.util.Locale
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun HomeScreen() {
+ val dayOfWeekList = testDayDate()
+ val dayChipGroupListState = rememberLazyListState()
+ var isShowBottomSheet by remember { mutableStateOf(false) }
+ val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
+
+ var checkTest by remember { mutableStateOf(false) }
+
+ Scaffold(
+ modifier = Modifier.fillMaxSize(),
+ containerColor = Color(0xFF13131f),
+ topBar = { TopBar() }
+ ) { innerPadding ->
+ Column(
+ modifier = Modifier
+ .padding(innerPadding)
+ .padding(horizontal = 12.dp, vertical = 20.dp)
+ ) {
+ DayChipGroupList(
+ dayChipGroupListState = dayChipGroupListState,
+ dayOfWeekList = dayOfWeekList,
+ ) { /** 해당 날짜 루틴 목록 업데이트 **/ }
+
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 12.dp),
+ horizontalArrangement = Arrangement.SpaceBetween
+ ) {
+ Text(
+ text = "루틴 목록",
+ color = Color.Gray,
+ fontSize = 14.sp
+ )
+
+ Text(
+ modifier = Modifier
+ .clickable{
+ isShowBottomSheet = true
+ },
+ text = "+ 추가",
+ color = Color(0xFF6c63ff),
+ fontSize = 14.sp,
+ fontWeight = FontWeight.Bold
+ )
+ }
+
+ RoutineList(
+ routineList = routines,
+ onClickRoutine = { /** 루틴 상세 페이지 이동 **/ },
+ isChecked = checkTest,
+ onChecked = { checkTest = it }
+ )
+
+ if (isShowBottomSheet) {
+ AddRoutineBottomSheet(
+ bottomSheetState = bottomSheetState
+ ) {
+ isShowBottomSheet = false
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun TopBar() {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(Color(0xFF1a1a2e))
+ .padding(horizontal = 12.dp, vertical = 12.dp)
+ .windowInsetsPadding(WindowInsets.statusBars),
+ ) {
+ Text(
+ text = "오늘의 루틴을 향하여🔥",
+ color = Color.Gray,
+ fontSize = 14.sp
+ )
+
+ Text(
+ text = "오늘의 루틴",
+ color = Color.White,
+ fontSize = 20.sp,
+ fontWeight = FontWeight.Bold
+ )
+
+ Spacer(Modifier.height(12.dp))
+
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(
+ color = Color(0xFF252540),
+ shape = RoundedCornerShape(12.dp)
+ )
+ .padding(horizontal = 14.dp, vertical = 12.dp)
+ ) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceBetween
+ ) {
+ Text(
+ text = "오늘의 진행률",
+ color = Color.Gray,
+ fontSize = 12.sp
+ )
+ Text(
+ text = "3/5 완료",
+ color = Color(0xFF8888aa),
+ fontSize = 12.sp,
+ fontWeight = FontWeight.Bold
+ )
+ }
+
+ Spacer(modifier = Modifier.height(6.dp))
+
+ RoutineProgress(
+ modifier = Modifier.fillMaxWidth(),
+ progress = 0.6f
+ )
+ }
+ }
+}
+
+@Composable
+fun DayChipGroupList(
+ dayChipGroupListState: LazyListState,
+ dayOfWeekList: List,
+ onDayClick: (DayItem) -> Unit
+) {
+ BoxWithConstraints {
+ val width = maxWidth
+ val density = LocalDensity.current
+
+ LazyRow(
+ state = dayChipGroupListState,
+ horizontalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ items(dayOfWeekList) {
+ DayOfWeekItem(
+ dayItem = it,
+ onDayClick = onDayClick
+ )
+ }
+ }
+
+ LaunchedEffect(Unit) {
+ val offset = with(density) {
+ ((width / 2) - (50 / 2).dp).toPx()
+ }
+
+ dayChipGroupListState.animateScrollToItem(
+ index = 5,
+ scrollOffset = -offset.toInt()
+ )
+ }
+ }
+}
+
+@Composable
+fun DayOfWeekItem(
+ dayItem: DayItem,
+ onDayClick: (DayItem) -> Unit
+) {
+ Column(
+ modifier = Modifier
+ .size(width = 50.dp, height = 60.dp)
+ .background(
+ if (dayItem.isToday) Color(0xFF6c63ff) else Color(0xFF1e1e30),
+ shape = RoundedCornerShape(6.dp)
+ )
+ .clickable {
+ onDayClick(dayItem)
+ },
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Text(
+ text = dayItem.dayOfWeek,
+ fontSize = 12.sp,
+ color = if (dayItem.isToday) Color(0xFFd4d0ff) else Color(0xFF555577)
+ )
+
+ Text(
+ text = dayItem.day.toString(),
+ fontSize = 12.sp,
+ fontWeight = FontWeight.Bold,
+ color = if (dayItem.isToday) Color(0xFFffffff) else Color(0xFFcccccc)
+ )
+
+ Box(
+ modifier = Modifier
+ .size(6.dp)
+ .clip(shape = CircleShape)
+ .background(color = if (dayItem.isToday) Color(0xFFa09fff) else Color(0xFF33334a))
+ )
+ }
+}
+
+@Composable
+fun RoutineList(
+ routineList: List,
+ onClickRoutine: (Routine) -> Unit,
+ isChecked: Boolean,
+ onChecked: (Boolean) -> Unit
+) {
+ LazyColumn(
+ modifier = Modifier.padding(top = 12.dp),
+ verticalArrangement = Arrangement.spacedBy(12.dp)
+ ) {
+ items(routineList) {
+ RoutineItem(
+ routineItem = it,
+ onClickRoutine = onClickRoutine,
+ isChecked = isChecked,
+ onChecked = onChecked,
+ )
+ }
+ }
+}
+
+@Composable
+fun RoutineItem(
+ routineItem: Routine,
+ onClickRoutine: (Routine) -> Unit,
+ isChecked: Boolean,
+ onChecked: (Boolean) -> Unit
+) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(color = Color(0xFF1a1a2e), shape = RoundedCornerShape(12.dp))
+ .border(width = 1.dp, color = Color(0xFF2a2a3e), shape = RoundedCornerShape(12.dp))
+ .padding(12.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ // TODO: 추후 이미지사용
+ Box(
+ modifier = Modifier
+ .padding(end = 8.dp)
+ .size(50.dp)
+ .background(color = Color.Red, shape = RoundedCornerShape(12.dp))
+ )
+
+ Column(
+ modifier = Modifier
+ .weight(1f)
+ .clickable{
+ onClickRoutine(routineItem)
+ },
+ verticalArrangement = Arrangement.spacedBy(4.dp),
+ ) {
+ Text(
+ text = "운동명",
+ fontWeight = FontWeight.Bold,
+ color = Color.White
+ )
+
+ Text(
+ text = "시작시간 및 소요시간",
+ fontSize = 12.sp,
+ color = Color.Gray
+ )
+ }
+
+ Checkbox(
+ checked = isChecked,
+ onCheckedChange = { onChecked(it) },
+ colors = CheckboxDefaults.colors(
+ checkedColor = Color(0xFF6c63ff),
+ checkmarkColor = Color.White
+ )
+ )
+
+ }
+
+}
+
+fun testDayDate(): List {
+ val today = LocalDate.now()
+ val range = -5..5
+
+ return range.map {
+ val day = today.plusDays(it.toLong())
+
+ DayItem(
+ dayOfWeek = day.dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.ENGLISH),
+ day = day.dayOfMonth,
+ isToday = it == 0
+ )
+ }
+}
+
+val routines = listOf(
+ Routine(
+ id = 1,
+ title = "스트레칭",
+ icon = "🧘",
+ startTime = LocalTime.of(7, 0),
+ repeatDays = listOf(
+ DayOfWeek.MONDAY,
+ DayOfWeek.TUESDAY,
+ DayOfWeek.WEDNESDAY,
+ DayOfWeek.THURSDAY,
+ DayOfWeek.FRIDAY
+ ),
+ createdAt = LocalDate.of(2025, 3, 1)
+ ),
+ Routine(
+ id = 2,
+ title = "독서",
+ icon = "📖",
+ startTime = LocalTime.of(7, 30),
+ repeatDays = listOf(
+ DayOfWeek.MONDAY,
+ DayOfWeek.WEDNESDAY,
+ DayOfWeek.FRIDAY
+ ),
+ createdAt = LocalDate.of(2025, 3, 1)
+ ),
+ Routine(
+ id = 3,
+ title = "모닝 커피",
+ icon = "☕",
+ startTime = LocalTime.of(8, 0),
+ repeatDays = DayOfWeek.entries.toList(), // 매일
+ createdAt = LocalDate.of(2025, 3, 5)
+ ),
+ Routine(
+ id = 4,
+ title = "조깅",
+ icon = "🏃",
+ startTime = LocalTime.of(8, 30),
+ repeatDays = listOf(
+ DayOfWeek.TUESDAY,
+ DayOfWeek.THURSDAY,
+ DayOfWeek.SATURDAY
+ ),
+ createdAt = LocalDate.of(2025, 3, 10)
+ ),
+ Routine(
+ id = 5,
+ title = "명상",
+ icon = "🧘",
+ startTime = LocalTime.of(9, 0),
+ repeatDays = listOf(
+ DayOfWeek.MONDAY,
+ DayOfWeek.WEDNESDAY,
+ DayOfWeek.FRIDAY,
+ DayOfWeek.SUNDAY
+ ),
+ createdAt = LocalDate.of(2025, 3, 15)
+ ),
+ Routine(
+ id = 6,
+ title = "일기 쓰기",
+ icon = "✍️",
+ startTime = LocalTime.of(22, 0),
+ repeatDays = DayOfWeek.entries.toList(), // 매일
+ createdAt = LocalDate.of(2025, 3, 20)
+ )
+)
+
+data class DayItem(
+ val dayOfWeek: String,
+ val day: Int,
+ val isToday: Boolean,
+)