Skip to content

Commit

Permalink
체크리스트 메인화면 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
leesa-l committed Nov 5, 2023
1 parent dc01d5c commit 99aa30e
Show file tree
Hide file tree
Showing 33 changed files with 772 additions and 32 deletions.
4 changes: 3 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ chucker = "3.5.2"

# Coil
coil = "2.4.0"
coil-compose = "2.4.0"

# Lottie
lottie-compose = "6.1.0"
Expand Down Expand Up @@ -132,6 +133,7 @@ hilt-ext-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hi

#Coil
coil-core = { group = "io.coil-kt", name = "coil", version.ref = "coil" }
coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil-compose" }

#Lottie
lottie-compose = { group = "com.airbnb.android", name = "lottie-compose", version.ref = "lottie-compose" }
Expand Down Expand Up @@ -216,7 +218,7 @@ compose = [
"compose-test-uiManifest",
"compose-test-ui",
"compose-viewModel",
"compose-hiltViewModel"
"compose-hiltViewModel",
]

okhttp = [
Expand Down
1 change: 1 addition & 0 deletions presentation/checklist/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ dependencies {
implementation(project(":presentation:resource"))
implementation(project(":presentation:common"))
implementation(project(":presentation:deeplink"))
implementation(libs.coil.compose)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class CheckList : MVIComposeFragment<ChecklistIntent, ChecklistState, ChecklistE
override fun processEffect(effect: ChecklistEffect) {
when (effect) {
ChecklistEffect.NavigateToAddCategory -> {}
is ChecklistEffect.NavigateToLink -> {}
is ChecklistEffect.NavigateToCategory -> {}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import androidx.compose.runtime.Stable
import com.dkin.chevit.core.mvi.ViewEffect
import com.dkin.chevit.core.mvi.ViewIntent
import com.dkin.chevit.core.mvi.ViewState
import com.dkin.chevit.presentation.common.category.Category
import com.dkin.chevit.presentation.common.category.CategoryType

sealed interface ChecklistIntent : ViewIntent {
data class ChangeTemplateOpenSetting(val isOpen: Boolean) : ChecklistIntent
}

@Stable
Expand All @@ -15,7 +16,9 @@ data class ChecklistState(
val date: String,
val notice: Notice,
val weathers: List<Weather>,
val templates: List<Template>
val weatherDetailUrl: String,
val categories: List<Category>,
val isTemplateOpen: Boolean
) : ViewState {

data class Notice(
Expand All @@ -26,13 +29,14 @@ data class ChecklistState(
data class Weather(
val date: String,
val iconUrl: String,
val temp: String,
val temperature: String
)

data class Template(
data class Category(
val categoryId: Int,
val title: String,
val category: Category,
val remain: Int,
val categoryType: CategoryType,
val checked: Int,
val total: Int,
)

Expand All @@ -44,12 +48,27 @@ data class ChecklistState(
title = "[주의] 프랑스, 폭력시위 관련 안전유의 공지",
url = ""
),
weathers = listOf(),
templates = listOf()
weathers = listOf(
Weather(date = "7/16", iconUrl = "", temperature = "14°/25°"),
Weather(date = "7/17", iconUrl = "", temperature = "13°/22°"),
Weather(date = "7/18", iconUrl = "", temperature = "14°/21°"),
),
weatherDetailUrl = "",
categories = listOf(
Category(categoryId = 0, title = "필수 준비물", categoryType = CategoryType.REQUIRES, checked = 12, total = 32),
Category(categoryId = 1, title = "세면도구", categoryType = CategoryType.TOILETRIES, checked = 24, total = 24),
Category(categoryId = 2, title = "의류", categoryType = CategoryType.CLOTHES, checked = 24, total = 24),
Category(categoryId = 3, title = "등산", categoryType = CategoryType.CAMPING, checked = 12, total = 32),
Category(categoryId = 4, title = "전자기기", categoryType = CategoryType.ELECTRONICS, checked = 20, total = 40),
Category(categoryId = 5, title = "반려동물", categoryType = CategoryType.COMPANION_ANIMAL, checked = 24, total = 24),
),
isTemplateOpen = true
)
}
}

sealed interface ChecklistEffect : ViewEffect {
object NavigateToAddCategory : ChecklistEffect
data class NavigateToLink(val url: String) : ChecklistEffect
data class NavigateToCategory(val categoryId: Int) : ChecklistEffect
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,135 @@
package com.dkin.chevit.presentation.checklist

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
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.width
import androidx.compose.material3.Icon
import androidx.compose.material3.Switch
import androidx.compose.material3.SwitchDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
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.unit.dp
import com.dkin.chevit.presentation.checklist.component.ChecklistTopBar
import com.dkin.chevit.presentation.checklist.component.CountryInfo
import com.dkin.chevit.presentation.checklist.contents.CategoryEmptyContents
import com.dkin.chevit.presentation.checklist.contents.CategoryListContents
import com.dkin.chevit.presentation.resource.ChevitTheme
import com.dkin.chevit.presentation.resource.icon.ChevitIcon
import com.dkin.chevit.presentation.resource.icon.IconArrowDownLine
import com.dkin.chevit.presentation.resource.icon.IconArrowUpLine

@Composable
fun ChecklistScreen(
viewModel: ChecklistViewModel,
onClickBack: () -> Unit
) {
Column {

val checklistState by viewModel.state.collectAsState()
var showCountryInfo by remember { mutableStateOf(true) }

Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
ChecklistTopBar(
modifier = Modifier.fillMaxWidth(),
title = checklistState.title,
onClickBack = onClickBack
)
Text(
text = checklistState.date,
style = ChevitTheme.typhography.bodyLarge.copy(color = ChevitTheme.colors.textCaption),
)
Spacer(modifier = Modifier.height(16.dp))
if (showCountryInfo) {
CountryInfo(
notice = checklistState.notice,
weathers = checklistState.weathers,
weatherDetailUrl = checklistState.weatherDetailUrl,
onClickUrl = { url -> viewModel.onClickUrl(url) }
)
}
Column(modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
if (showCountryInfo) {
Icon(
modifier = Modifier.clickable { showCountryInfo = false },
imageVector = ChevitIcon.IconArrowUpLine,
contentDescription = "",
tint = ChevitTheme.colors.grey10,
)
Spacer(modifier = Modifier.height(12.dp))
} else {
Icon(
modifier = Modifier.clickable { showCountryInfo = true },
imageVector = ChevitIcon.IconArrowDownLine,
contentDescription = "",
tint = ChevitTheme.colors.grey10,
)
Spacer(modifier = Modifier.height(12.dp))
}
}
Box(
modifier = Modifier
.fillMaxWidth()
.height(4.dp)
.background(color = ChevitTheme.colors.grey0)
)
Spacer(modifier = Modifier.height(24.dp))
Row(modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), verticalAlignment = Alignment.CenterVertically) {
Text(
modifier = Modifier.weight(1f),
text = "체크리스트 템플릿",
style = ChevitTheme.typhography.headlineMedium.copy(color = ChevitTheme.colors.textPrimary),
)
if (checklistState.categories.isNotEmpty()) {
Text(
text = "공개",
style = ChevitTheme.typhography.bodyMedium.copy(color = ChevitTheme.colors.textSecondary),
)
Spacer(modifier = Modifier.width(6.dp))
Switch(
modifier = Modifier.size(width = 48.dp, height = 24.dp),
checked = checklistState.isTemplateOpen,
onCheckedChange = {
viewModel.dispatch(
ChecklistIntent.ChangeTemplateOpenSetting(
it
)
)
},
colors = SwitchDefaults.colors(
checkedThumbColor = ChevitTheme.colors.white,
checkedTrackColor = ChevitTheme.colors.blue7,
checkedBorderColor = Color.Unspecified,
uncheckedThumbColor = ChevitTheme.colors.white,
uncheckedTrackColor = ChevitTheme.colors.grey2,
uncheckedBorderColor = Color.Unspecified,
),
)
}
}
Spacer(modifier = Modifier.height(24.dp))
if (checklistState.categories.isEmpty()) {
CategoryEmptyContents()
} else {
CategoryListContents(
categories = checklistState.categories,
onClickCategory = { id -> viewModel.onClickCategory(id) },
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ class ChecklistViewModel @Inject constructor() :

override suspend fun processIntent(intent: ChecklistIntent) {
when (intent) {
else -> {}
is ChecklistIntent.ChangeTemplateOpenSetting -> {}
}
}

fun onClickUrl(url: String) {
setEffect { ChecklistEffect.NavigateToLink(url) }
}

fun onClickCategory(id: Int) {
setEffect { ChecklistEffect.NavigateToCategory(id) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.dkin.chevit.presentation.checklist.component

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.dkin.chevit.presentation.resource.ChevitTheme
import com.dkin.chevit.presentation.resource.icon.ChevitIcon
import com.dkin.chevit.presentation.resource.icon.IconArrowLeftLine
import com.dkin.chevit.presentation.resource.util.clickableNoRipple

@Composable
fun ChecklistTopBar(
modifier: Modifier = Modifier,
title: String,
onClickBack: () -> Unit,
) {
Box(
modifier = modifier
.height(58.dp)
.padding(vertical = 16.dp, horizontal = 24.dp),
contentAlignment = Alignment.Center
) {
Icon(
modifier = Modifier
.align(Alignment.CenterStart)
.clickableNoRipple { onClickBack() },
imageVector = ChevitIcon.IconArrowLeftLine,
contentDescription = "",
)
Text(
modifier = Modifier.align(Alignment.Center),
text = title,
textAlign = TextAlign.Center,
style = ChevitTheme.typhography.headlineMedium.copy(color = ChevitTheme.colors.textPrimary)
)
}
}
Loading

0 comments on commit 99aa30e

Please sign in to comment.