diff --git a/core/designsystem/src/main/java/com/terning/core/designsystem/component/button/SortingButton.kt b/core/designsystem/src/main/java/com/terning/core/designsystem/component/button/SortingButton.kt index 324962c8..8cf9ac65 100644 --- a/core/designsystem/src/main/java/com/terning/core/designsystem/component/button/SortingButton.kt +++ b/core/designsystem/src/main/java/com/terning/core/designsystem/component/button/SortingButton.kt @@ -1,5 +1,6 @@ package com.terning.core.designsystem.component.button +import androidx.compose.foundation.Image import androidx.compose.foundation.border import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding @@ -11,11 +12,13 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import com.terning.core.designsystem.R import com.terning.core.designsystem.extension.noRippleClickable +import com.terning.core.designsystem.theme.Black import com.terning.core.designsystem.theme.Grey350 import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.type.SortBy @@ -27,36 +30,31 @@ fun SortingButton( onCLick: () -> Unit, ) { Row( - verticalAlignment = Alignment.CenterVertically, modifier = modifier - .border( - width = 1.dp, - color = Grey350, - shape = RoundedCornerShape(5.dp) - ) .noRippleClickable(onCLick), ) { - Icon( - imageVector = ImageVector.vectorResource(id = R.drawable.ic_down_18), - contentDescription = stringResource(id = R.string.sort_button_description), - tint = Grey350, - modifier = Modifier - .padding( - start = 7.dp, - end = 6.dp, - top = 5.dp, - bottom = 5.dp, - ) - .size(20.dp) - ) Text( text = stringResource( id = SortBy.entries[sortBy].sortBy ), style = TerningTheme.typography.button3, - color = Grey350, + color = Black, + modifier = Modifier + .padding( + top = 6.dp, + bottom = 6.dp, + ) + ) + Image( + painter = painterResource(id = R.drawable.ic_down_18), + contentDescription = stringResource(id = R.string.sort_button_description), modifier = Modifier - .padding(end = 11.dp) + .padding( + start = 2.dp, + end = 2.dp, + top = 6.dp, + bottom = 4.dp, + ) ) } -} +} \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/terning/core/designsystem/type/JobType.kt b/core/designsystem/src/main/java/com/terning/core/designsystem/type/JobType.kt new file mode 100644 index 00000000..37030eda --- /dev/null +++ b/core/designsystem/src/main/java/com/terning/core/designsystem/type/JobType.kt @@ -0,0 +1,36 @@ +package com.terning.core.designsystem.type + +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import com.terning.core.designsystem.R + +enum class JobType( + val stringValue: String, + @DrawableRes val drawableResId: Int, + @StringRes val stringResId: Int, +) { + PLAN("plan", R.drawable.ic_job_plan_24, R.string.job_type_plan), + MARKETING("marketing", R.drawable.ic_job_marketing_24, R.string.job_type_marketing), + SALES("sales", R.drawable.ic_job_sales_24, R.string.job_type_sales), + ADMIN("admin", R.drawable.ic_job_accounting_24, R.string.job_type_admin), + DESIGN("design", R.drawable.ic_job_design_24, R.string.job_type_design), + IT("it", R.drawable.ic_job_it_24, R.string.job_type_it), + RESEARCH("research", R.drawable.ic_job_research_24, R.string.job_type_research), + ETC("etc", R.drawable.ic_job_extra_24, R.string.job_type_etc), + TOTAL("total", R.drawable.ic_job_all_24, R.string.job_type_total), ; + + + companion object { + fun fromString(value: String?): JobType = when (value) { + "plan" -> PLAN + "marketing" -> MARKETING + "admin" -> ADMIN + "sales" -> SALES + "design" -> DESIGN + "it" -> IT + "research" -> RESEARCH + "etc" -> ETC + else -> TOTAL + } + } +} \ No newline at end of file diff --git a/core/designsystem/src/main/res/drawable/ic_job_accounting_24.xml b/core/designsystem/src/main/res/drawable/ic_job_accounting_24.xml new file mode 100644 index 00000000..a6e01c86 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_job_accounting_24.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_job_all_24.xml b/core/designsystem/src/main/res/drawable/ic_job_all_24.xml new file mode 100644 index 00000000..be926f90 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_job_all_24.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_job_design_24.xml b/core/designsystem/src/main/res/drawable/ic_job_design_24.xml new file mode 100644 index 00000000..f8c06562 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_job_design_24.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_job_extra_24.xml b/core/designsystem/src/main/res/drawable/ic_job_extra_24.xml new file mode 100644 index 00000000..2368d1f2 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_job_extra_24.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_job_it_24.xml b/core/designsystem/src/main/res/drawable/ic_job_it_24.xml new file mode 100644 index 00000000..73ce99d7 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_job_it_24.xml @@ -0,0 +1,44 @@ + + + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_job_marketing_24.xml b/core/designsystem/src/main/res/drawable/ic_job_marketing_24.xml new file mode 100644 index 00000000..7fded015 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_job_marketing_24.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_job_plan_24.xml b/core/designsystem/src/main/res/drawable/ic_job_plan_24.xml new file mode 100644 index 00000000..e3509dfe --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_job_plan_24.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_job_research_24.xml b/core/designsystem/src/main/res/drawable/ic_job_research_24.xml new file mode 100644 index 00000000..83d0f880 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_job_research_24.xml @@ -0,0 +1,41 @@ + + + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_job_sales_24.xml b/core/designsystem/src/main/res/drawable/ic_job_sales_24.xml new file mode 100644 index 00000000..25793d5e --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_job_sales_24.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml index 70126b08..ab956787 100644 --- a/core/designsystem/src/main/res/values/strings.xml +++ b/core/designsystem/src/main/res/values/strings.xml @@ -72,17 +72,22 @@ 닉네임은 12자리 이내로 설정해 주세요 - 필터링 재설정 - 재학 상태 - 저장하기 1학년 2학년 3학년 4학년 - 희망 근무 기간 1 ~ 3개월 4 ~ 6개월 7개월 이상 - 근무 시작 시기 + + 기획/전략 + 마케팅/홍보 + 사무/회계 + 인사/영업 + 디자인/예술 + 개발/IT + 연구/생산 + 기타 + 전체 직무 \ No newline at end of file diff --git a/data/home/src/main/java/com/terning/data/home/dto/request/ChangeFilterRequestDto.kt b/data/home/src/main/java/com/terning/data/home/dto/request/ChangeFilterRequestDto.kt index e476b414..126ddada 100644 --- a/data/home/src/main/java/com/terning/data/home/dto/request/ChangeFilterRequestDto.kt +++ b/data/home/src/main/java/com/terning/data/home/dto/request/ChangeFilterRequestDto.kt @@ -7,13 +7,15 @@ import kotlinx.serialization.Serializable @Serializable data class ChangeFilterRequestDto( @SerialName("grade") - val grade: String, + val grade: String?, @SerialName("workingPeriod") - val workingPeriod: String, + val workingPeriod: String?, @SerialName("startYear") - val startYear: Int, + val startYear: Int?, @SerialName("startMonth") - val startMonth: Int, + val startMonth: Int?, + @SerialName("jobType") + val jobType: String, ) fun ChangeFilteringRequestModel.toChangeFilterRequestDto(): ChangeFilterRequestDto = @@ -22,4 +24,5 @@ fun ChangeFilteringRequestModel.toChangeFilterRequestDto(): ChangeFilterRequestD workingPeriod = workingPeriod, startYear = startYear, startMonth = startMonth, + jobType = jobType, ) diff --git a/data/home/src/main/java/com/terning/data/home/dto/response/HomeFilteringInfoResponseDto.kt b/data/home/src/main/java/com/terning/data/home/dto/response/HomeFilteringInfoResponseDto.kt index 699a9a58..37bb4862 100644 --- a/data/home/src/main/java/com/terning/data/home/dto/response/HomeFilteringInfoResponseDto.kt +++ b/data/home/src/main/java/com/terning/data/home/dto/response/HomeFilteringInfoResponseDto.kt @@ -13,4 +13,6 @@ data class HomeFilteringInfoResponseDto( val startYear: Int?, @SerialName("startMonth") val startMonth: Int?, + @SerialName("jobType") + val jobType: String, ) diff --git a/data/home/src/main/java/com/terning/data/home/mapper/HomeFilteringInfoMapper.kt b/data/home/src/main/java/com/terning/data/home/mapper/HomeFilteringInfoMapper.kt index dc32a148..7ba34cb7 100644 --- a/data/home/src/main/java/com/terning/data/home/mapper/HomeFilteringInfoMapper.kt +++ b/data/home/src/main/java/com/terning/data/home/mapper/HomeFilteringInfoMapper.kt @@ -9,4 +9,5 @@ fun HomeFilteringInfoResponseDto.toHomeFilteringInfo(): HomeFilteringInfo = workingPeriod = this.workingPeriod, startYear = this.startYear, startMonth = this.startMonth, + jobType = this.jobType, ) \ No newline at end of file diff --git a/domain/home/src/main/java/com/terning/domain/home/entity/ChangeFilteringRequestModel.kt b/domain/home/src/main/java/com/terning/domain/home/entity/ChangeFilteringRequestModel.kt index ab722760..7da40f18 100644 --- a/domain/home/src/main/java/com/terning/domain/home/entity/ChangeFilteringRequestModel.kt +++ b/domain/home/src/main/java/com/terning/domain/home/entity/ChangeFilteringRequestModel.kt @@ -1,8 +1,9 @@ package com.terning.domain.home.entity data class ChangeFilteringRequestModel( - val grade: String, - val workingPeriod: String, - val startYear: Int, - val startMonth: Int, + val grade: String?, + val workingPeriod: String?, + val startYear: Int?, + val startMonth: Int?, + val jobType: String, ) diff --git a/domain/home/src/main/java/com/terning/domain/home/entity/HomeFilteringInfo.kt b/domain/home/src/main/java/com/terning/domain/home/entity/HomeFilteringInfo.kt index 9f117640..1a8392e6 100644 --- a/domain/home/src/main/java/com/terning/domain/home/entity/HomeFilteringInfo.kt +++ b/domain/home/src/main/java/com/terning/domain/home/entity/HomeFilteringInfo.kt @@ -5,4 +5,5 @@ data class HomeFilteringInfo( val workingPeriod: String?, val startYear: Int?, val startMonth: Int?, + val jobType: String, ) diff --git a/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt b/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt index ba0a25c7..ee307342 100644 --- a/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt +++ b/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt @@ -32,7 +32,6 @@ import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.terning.core.analytics.EventType import com.terning.core.analytics.LocalTracker import com.terning.core.designsystem.component.bottomsheet.SortingBottomSheet -import com.terning.core.designsystem.component.button.SortingButton import com.terning.core.designsystem.component.image.TerningImage import com.terning.core.designsystem.component.item.InternItemWithShadow import com.terning.core.designsystem.extension.noRippleClickable @@ -44,20 +43,20 @@ import com.terning.core.designsystem.theme.Grey400 import com.terning.core.designsystem.theme.TerningMain import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White -import com.terning.core.designsystem.type.Grade -import com.terning.core.designsystem.type.WorkingPeriod +import com.terning.core.designsystem.type.JobType import com.terning.domain.home.entity.HomeFilteringInfo import com.terning.domain.home.entity.HomeRecommendedIntern import com.terning.domain.home.entity.HomeUpcomingIntern import com.terning.feature.dialog.cancel.ScrapCancelDialog import com.terning.feature.dialog.detail.ScrapDialog -import com.terning.feature.home.component.HomeFilteringBottomSheet import com.terning.feature.home.component.HomeFilteringScreen import com.terning.feature.home.component.HomeRecommendEmptyIntern +import com.terning.feature.home.component.HomeSortingButton import com.terning.feature.home.component.HomeUpcomingEmptyFilter import com.terning.feature.home.component.HomeUpcomingEmptyIntern import com.terning.feature.home.component.HomeUpcomingInternScreen -import okhttp3.internal.toImmutableList +import com.terning.feature.home.component.bottomsheet.HomeFilteringBottomSheet +import kotlinx.collections.immutable.toImmutableList const val NAME_MAX_LENGTH = 5 private const val ZERO_TOTAL_COUNT = 0 @@ -150,13 +149,21 @@ fun HomeScreen( val homeFilteringInfo = when (homeState.homeFilteringInfoState) { is UiState.Success -> (homeState.homeFilteringInfoState as UiState.Success).data - else -> HomeFilteringInfo(null, null, null, null) + else -> HomeFilteringInfo( + grade = null, + workingPeriod = null, + startYear = null, + startMonth = null, + jobType = JobType.TOTAL.stringValue + ) } val homeRecommendInternTotal = remember(recommendedInternList.loadState.refresh) { - if(recommendedInternList.itemCount > 0) { + if (recommendedInternList.itemCount > 0) { recommendedInternList[0]?.totalCount ?: ZERO_TOTAL_COUNT - } else { ZERO_TOTAL_COUNT } + } else { + ZERO_TOTAL_COUNT + } } var changeFilteringSheetState by remember { mutableStateOf(false) } @@ -187,19 +194,14 @@ fun HomeScreen( if (changeFilteringSheetState) { HomeFilteringBottomSheet( - defaultGrade = homeFilteringInfo.grade?.let { Grade.fromString(it) }, - defaultWorkingPeriod = homeFilteringInfo.workingPeriod?.let { - WorkingPeriod.fromString(it) - }, - defaultStartYear = homeFilteringInfo.startYear, - defaultStartMonth = homeFilteringInfo.startMonth, onDismiss = { changeFilteringSheetState = false }, - onChangeButtonClick = { grade, workingPeriod, year, month -> + defaultFilteringInfo = homeFilteringInfo, + onChangeButtonClick = { grade, workingPeriod, year, month, jobType -> amplitudeTracker.track( type = EventType.CLICK, name = "home_filtering_save" ) - viewModel.putFilteringInfo(grade, workingPeriod, year, month) + viewModel.putFilteringInfo(grade, workingPeriod, year, month, jobType) changeFilteringSheetState = false } ) @@ -306,7 +308,7 @@ fun HomeScreen( ) } Spacer(modifier = Modifier.weight(1f)) - SortingButton( + HomeSortingButton( sortBy = homeState.sortBy.ordinal, onCLick = { updateSortingSheetVisibility(true) }, ) @@ -319,13 +321,10 @@ fun HomeScreen( } } - if (recommendedInternList.itemCount == 0) { item { HomeRecommendEmptyIntern( - text = - if (homeState.homeFilteringInfoState is UiState.Success && homeFilteringInfo.grade == null) R.string.home_recommend_no_filtering - else R.string.home_recommend_no_intern + text = R.string.home_recommend_no_intern ) } } else { diff --git a/feature/home/src/main/java/com/terning/feature/home/HomeViewModel.kt b/feature/home/src/main/java/com/terning/feature/home/HomeViewModel.kt index ffb82a7a..ed55e3ac 100644 --- a/feature/home/src/main/java/com/terning/feature/home/HomeViewModel.kt +++ b/feature/home/src/main/java/com/terning/feature/home/HomeViewModel.kt @@ -103,14 +103,21 @@ class HomeViewModel @Inject constructor( } } - fun putFilteringInfo(grade: String, workingPeriod: String, year: Int, month: Int) { + fun putFilteringInfo( + grade: String?, + workingPeriod: String?, + year: Int?, + month: Int?, + jobType: String + ) { viewModelScope.launch { homeRepository.putFilteringInfo( ChangeFilteringRequestModel( grade, workingPeriod, year, - month + month, + jobType ) ).onSuccess { getFilteringInfo() diff --git a/feature/home/src/main/java/com/terning/feature/home/component/HomeFilteringBottomSheet.kt b/feature/home/src/main/java/com/terning/feature/home/component/HomeFilteringBottomSheet.kt deleted file mode 100644 index 47d7df74..00000000 --- a/feature/home/src/main/java/com/terning/feature/home/component/HomeFilteringBottomSheet.kt +++ /dev/null @@ -1,270 +0,0 @@ -package com.terning.feature.home.component - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.itemsIndexed -import androidx.compose.material3.Checkbox -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Text -import androidx.compose.material3.rememberModalBottomSheetState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import com.terning.core.designsystem.R -import com.terning.core.designsystem.component.bottomsheet.TerningBasicBottomSheet -import com.terning.core.designsystem.component.button.ChangeFilterButton -import com.terning.core.designsystem.component.button.RoundButton -import com.terning.core.designsystem.extension.currentMonth -import com.terning.core.designsystem.extension.currentYear -import com.terning.core.designsystem.theme.Black -import com.terning.core.designsystem.theme.Grey200 -import com.terning.core.designsystem.theme.TerningTheme -import com.terning.core.designsystem.type.Grade -import com.terning.core.designsystem.type.WorkingPeriod -import kotlinx.collections.immutable.toImmutableList -import java.util.Calendar - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun HomeFilteringBottomSheet( - modifier: Modifier = Modifier, - defaultGrade: Grade?, - defaultWorkingPeriod: WorkingPeriod?, - defaultStartYear: Int?, - defaultStartMonth: Int?, - onDismiss: () -> Unit, - onChangeButtonClick: (String, String, Int, Int) -> Unit, -) { - val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) - - var currentGrade by remember { mutableStateOf(defaultGrade) } - var currentPeriod by remember { mutableStateOf(defaultWorkingPeriod) } - var currentStartYear by remember { - mutableIntStateOf( - defaultStartYear ?: Calendar.getInstance().currentYear - ) - } - var currentStartMonth by remember { - mutableIntStateOf( - defaultStartMonth ?: Calendar.getInstance().currentMonth - ) - } - - var isYearNull by remember { mutableStateOf(defaultStartYear != null) } - var isMonthNull by remember { mutableStateOf(defaultStartMonth != null) } - - var isCheckBoxChecked by remember { mutableStateOf(false) } - - var isInitialNullState by remember { mutableStateOf(false) } - - val yearsList by remember(isYearNull) { - mutableStateOf( - if (isYearNull || isInitialNullState) years + NULL_DATE - else years - ) - } - val monthsList by remember(isMonthNull) { - mutableStateOf( - if (isMonthNull || isInitialNullState) months + NULL_DATE - else months - ) - } - - TerningBasicBottomSheet( - content = { - Column( - modifier = modifier - .fillMaxWidth(), - ) { - Text( - text = stringResource(id = R.string.change_filter_top_bar_title), - style = TerningTheme.typography.title2, - color = Black, - modifier = Modifier - .padding(horizontal = 24.dp) - .padding(bottom = 16.dp), - ) - - HorizontalDivider( - thickness = 1.dp, - color = Grey200, - modifier = Modifier - .padding(horizontal = 24.dp), - ) - - ChangeFilteringTitleText( - text = stringResource(id = R.string.change_filter_grade_title), - modifier = Modifier - .padding(top = 18.dp, bottom = 12.dp) - .padding(horizontal = 24.dp) - ) - - ChangeFilteringRadioGroup( - initOption = defaultGrade?.ordinal ?: -1, - optionList = listOf( - R.string.change_filter_grade_1, - R.string.change_filter_grade_2, - R.string.change_filter_grade_3, - R.string.change_filter_grade_4, - ), - onButtonClick = { index -> - currentGrade = Grade.entries[index] - }, - modifier = Modifier - .padding(horizontal = 24.dp), - ) - - ChangeFilteringTitleText( - text = stringResource(id = R.string.change_filter_period_title), - modifier = Modifier - .padding(top = 32.dp, bottom = 12.dp) - .padding(horizontal = 24.dp) - ) - - ChangeFilteringRadioGroup( - initOption = defaultWorkingPeriod?.ordinal ?: -1, - optionList = listOf( - R.string.change_filter_period_1, - R.string.change_filter_period_2, - R.string.change_filter_period_3, - ), - onButtonClick = { index -> - currentPeriod = WorkingPeriod.entries[index] - }, - modifier = Modifier - .padding(horizontal = 24.dp), - ) - - ChangeFilteringTitleText( - text = stringResource(id = R.string.change_filter_start_work_title), - modifier = Modifier - .padding(top = 32.dp, bottom = 49.dp) - .padding(horizontal = 24.dp) - ) - - //TODO: 아래는 임시 체크박스로, 추후 수정 부탁합니다! - Checkbox( - checked = isCheckBoxChecked, - onCheckedChange = { isChecked -> - if (isChecked) { - isYearNull = true - isMonthNull = true - } - isCheckBoxChecked = isChecked - }, - modifier = Modifier.padding(start = 20.dp) - ) - - HomeYearMonthPicker( - chosenYear = defaultStartYear, - chosenMonth = defaultStartMonth, - onYearChosen = { year, isInitialSelection -> - if (year != null) { - currentStartYear = year - isCheckBoxChecked = false - isYearNull = false - isInitialNullState = isInitialSelection - } - }, - onMonthChosen = { month, isInitialSelection -> - if (month != null) { - currentStartMonth = month - isCheckBoxChecked = false - isMonthNull = false - isInitialNullState = isInitialSelection - } - }, - isYearNull = isYearNull, - isMonthNull = isMonthNull, - yearsList = yearsList.toImmutableList(), - monthsList = monthsList.toImmutableList(), - isInitialNullState = isInitialNullState - ) - - RoundButton( - style = TerningTheme.typography.button0, - paddingVertical = 19.dp, - text = R.string.change_filter_save, - cornerRadius = 10.dp, - modifier = Modifier - .padding(horizontal = 24.dp) - .padding(top = 51.dp), - onButtonClick = { - currentGrade?.let { grade -> - currentPeriod?.let { workingPeriod -> - onChangeButtonClick( - grade.stringValue, - workingPeriod.stringValue, - currentStartYear, - currentStartMonth, - ) - } - } - }, - isEnabled = currentGrade != null && currentPeriod != null - ) - } - }, - onDismissRequest = onDismiss, - sheetState = sheetState, - ) -} - -@Composable -fun ChangeFilteringTitleText( - text: String, - modifier: Modifier = Modifier, -) { - Text( - text = text, - style = TerningTheme.typography.title4, - color = Black, - modifier = modifier, - ) -} - -@Composable -fun ChangeFilteringRadioGroup( - optionList: List, - initOption: Int, - onButtonClick: (Int) -> Unit, - modifier: Modifier = Modifier, -) { - var selectedIndex by remember { mutableIntStateOf(initOption) } - - LazyVerticalGrid( - columns = GridCells.Fixed(optionList.size), - horizontalArrangement = Arrangement.spacedBy(13.dp), - modifier = modifier - .fillMaxWidth() - .wrapContentHeight() - - ) { - itemsIndexed(optionList) { index, option -> - ChangeFilterButton( - isSelected = selectedIndex == index, - modifier = Modifier - .wrapContentHeight(), - text = option, - cornerRadius = 10.dp, - paddingVertical = 10.dp, - onButtonClick = { - selectedIndex = index - onButtonClick(index) - } - ) - } - } -} \ No newline at end of file diff --git a/feature/home/src/main/java/com/terning/feature/home/component/HomeSortingButton.kt b/feature/home/src/main/java/com/terning/feature/home/component/HomeSortingButton.kt new file mode 100644 index 00000000..15415de5 --- /dev/null +++ b/feature/home/src/main/java/com/terning/feature/home/component/HomeSortingButton.kt @@ -0,0 +1,62 @@ +package com.terning.feature.home.component + +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +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.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.R +import com.terning.core.designsystem.extension.noRippleClickable +import com.terning.core.designsystem.theme.Grey350 +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.type.SortBy + +@Composable +internal fun HomeSortingButton( + modifier: Modifier = Modifier, + sortBy: Int = 0, + onCLick: () -> Unit, +) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = modifier + .border( + width = 1.dp, + color = Grey350, + shape = RoundedCornerShape(5.dp) + ) + .noRippleClickable(onCLick), + ) { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_down_18), + contentDescription = stringResource(id = R.string.sort_button_description), + tint = Grey350, + modifier = Modifier + .padding( + start = 7.dp, + end = 6.dp, + top = 5.dp, + bottom = 5.dp, + ) + .size(20.dp) + ) + Text( + text = stringResource( + id = SortBy.entries[sortBy].sortBy + ), + style = TerningTheme.typography.button3, + color = Grey350, + modifier = Modifier + .padding(end = 11.dp) + ) + } +} diff --git a/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/HomeFilteringBottomSheet.kt b/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/HomeFilteringBottomSheet.kt new file mode 100644 index 00000000..e56e6e70 --- /dev/null +++ b/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/HomeFilteringBottomSheet.kt @@ -0,0 +1,263 @@ +package com.terning.feature.home.component.bottomsheet + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +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.width +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider +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.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +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.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.component.bottomsheet.TerningBasicBottomSheet +import com.terning.core.designsystem.component.button.RoundButton +import com.terning.core.designsystem.extension.noRippleClickable +import com.terning.core.designsystem.theme.Black +import com.terning.core.designsystem.theme.Grey200 +import com.terning.core.designsystem.theme.Grey300 +import com.terning.core.designsystem.theme.TerningMain +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.type.Grade +import com.terning.core.designsystem.type.JobType +import com.terning.core.designsystem.type.WorkingPeriod +import com.terning.domain.home.entity.HomeFilteringInfo +import com.terning.feature.home.R +import kotlinx.coroutines.launch +import okhttp3.internal.toImmutableList + +private val filterType = + listOf(R.string.change_job_type_filter, R.string.change_plan_type_filter).toImmutableList() + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun HomeFilteringBottomSheet( + defaultFilteringInfo: HomeFilteringInfo, + onDismiss: () -> Unit, + onChangeButtonClick: (String?, String?, Int?, Int?, String) -> Unit, + modifier: Modifier = Modifier, +) { + val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) + + var currentFilteringInfo by remember { + mutableStateOf(defaultFilteringInfo) + } + val pagerState = rememberPagerState { filterType.size } + val coroutineScope = rememberCoroutineScope() + + val density = LocalDensity.current + var pageHeight by remember { mutableIntStateOf(0) } + + LaunchedEffect(pagerState.currentPage) { + currentFilteringInfo = defaultFilteringInfo + } + + GetPagerHeight( + onHeightMeasured = { + pageHeight = it + } + ) + + TerningBasicBottomSheet( + content = { + Column( + modifier = modifier + .fillMaxWidth(), + ) { + Text( + text = stringResource(id = R.string.change_filter_top_bar_title), + style = TerningTheme.typography.title2, + color = Black, + modifier = Modifier + .padding(horizontal = 24.dp) + .padding(bottom = 16.dp), + ) + + Row( + modifier = Modifier + .padding(horizontal = 23.dp), + verticalAlignment = Alignment.Bottom, + horizontalArrangement = Arrangement.spacedBy(28.dp), + ) { + filterType.forEachIndexed { index, option -> + TerningTab( + tabText = stringResource(id = option), + selected = pagerState.currentPage == index, + onTabClick = { + coroutineScope.launch { + pagerState.animateScrollToPage(index) + } + } + ) + } + } + + HorizontalDivider( + thickness = 1.dp, + color = Grey200, + modifier = Modifier + .padding(horizontal = 24.dp), + ) + + HorizontalPager( + state = pagerState, + beyondViewportPageCount = 1, + modifier = Modifier + .padding(top = 16.dp), + ) { currentPage -> + when (currentPage) { + 0 -> { + JobFilteringScreen( + initOption = JobType.fromString(currentFilteringInfo.jobType).ordinal, + onButtonClick = { jobType -> + currentFilteringInfo = currentFilteringInfo.copy( + jobType = jobType.stringValue + ) + }, + modifier = Modifier.height(with(density) { pageHeight.toDp() }) + ) + } + + 1 -> { + PlanFilteringScreen( + currentFilteringInfo = currentFilteringInfo, + updateGrade = { + currentFilteringInfo = currentFilteringInfo.copy( + grade = if (it != null) { + Grade.entries[it].stringValue + } else null + ) + }, + updateWorkingPeriod = { + currentFilteringInfo = currentFilteringInfo.copy( + workingPeriod = if (it != null) { + WorkingPeriod.entries[it].stringValue + } else null + ) + }, + updateStartYear = { + currentFilteringInfo = currentFilteringInfo.copy( + startYear = it + ) + }, + updateStartMonth = { + currentFilteringInfo = currentFilteringInfo.copy( + startMonth = it + ) + }, + ) + } + } + } + + RoundButton( + style = TerningTheme.typography.button0, + paddingVertical = 19.dp, + text = R.string.change_filter_save, + cornerRadius = 10.dp, + modifier = Modifier + .padding(horizontal = 24.dp), + onButtonClick = { + with(currentFilteringInfo) { + onChangeButtonClick( + grade, + workingPeriod, + startYear, + startMonth, + jobType + ) + } + }, + isEnabled = checkButtonEnable(currentFilteringInfo = currentFilteringInfo) + ) + } + + }, + onDismissRequest = onDismiss, + sheetState = sheetState, + ) +} + +@Composable +fun ChangeFilteringTitleText( + text: String, + modifier: Modifier = Modifier, +) { + Text( + text = text, + style = TerningTheme.typography.title4, + color = Black, + modifier = modifier, + ) +} + +@Composable +fun TerningTab( + tabText: String, + selected: Boolean, + onTabClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier + .width(IntrinsicSize.Max) + .noRippleClickable { onTabClick() }, + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + Text( + text = tabText, + style = TerningTheme.typography.title4, + color = if (selected) TerningMain else Grey300, + modifier = Modifier + .padding(bottom = 7.dp), + ) + + Spacer( + modifier = Modifier + .height(4.dp) + .fillMaxWidth() + .background(if (selected) TerningMain else Color.Transparent) + ) + } +} + +private fun checkButtonEnable(currentFilteringInfo: HomeFilteringInfo): Boolean = + with(currentFilteringInfo) { + listOf(grade, workingPeriod, startYear, startMonth).all { it == null || it == 0 } || + listOf(grade, workingPeriod, startYear, startMonth).none { it == null || it == 0 } + } + +@Composable +private fun GetPagerHeight( + onHeightMeasured: (Int) -> Unit, +) { + PlanFilteringScreen( + currentFilteringInfo = HomeFilteringInfo(null, null, null, null, "total"), + modifier = Modifier + .onGloballyPositioned { + onHeightMeasured(it.size.height) + } + ) +} \ No newline at end of file diff --git a/feature/home/src/main/java/com/terning/feature/home/component/HomeYearMonthPicker.kt b/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/HomeYearMonthPicker.kt similarity index 93% rename from feature/home/src/main/java/com/terning/feature/home/component/HomeYearMonthPicker.kt rename to feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/HomeYearMonthPicker.kt index d1f613ea..ff588aa2 100644 --- a/feature/home/src/main/java/com/terning/feature/home/component/HomeYearMonthPicker.kt +++ b/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/HomeYearMonthPicker.kt @@ -1,4 +1,4 @@ -package com.terning.feature.home.component +package com.terning.feature.home.component.bottomsheet import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior import androidx.compose.foundation.layout.Arrangement @@ -52,11 +52,10 @@ class PickerState { } @Composable -fun rememberPickerState() = remember { PickerState() } +private fun rememberPickerState() = remember { PickerState() } @Composable -fun HomeYearMonthPicker( - modifier: Modifier = Modifier, +internal fun HomeYearMonthPicker( chosenYear: Int?, chosenMonth: Int?, onYearChosen: (Int?, Boolean) -> Unit, @@ -65,7 +64,8 @@ fun HomeYearMonthPicker( isMonthNull: Boolean, yearsList: ImmutableList, monthsList: ImmutableList, - isInitialNullState: Boolean + isInitialNullState: Boolean, + modifier: Modifier = Modifier, ) { val yearPickerState = rememberPickerState() val monthPickerState = rememberPickerState() @@ -74,10 +74,10 @@ fun HomeYearMonthPicker( val startYearIndex = if (isYearNull) yearsList.lastIndex else yearsList.indexOf("${chosenYear ?: "-"}년") - .takeIf { it >= 0 } ?: 0 + .takeIf { it >= 0 } ?: yearsList.lastIndex val startMonthIndex = if (isMonthNull) monthsList.lastIndex else monthsList.indexOf("${chosenMonth ?: "-"}월") - .takeIf { it >= 0 } ?: 0 + .takeIf { it >= 0 } ?: monthsList.lastIndex Row( modifier = modifier @@ -116,7 +116,7 @@ fun HomeYearMonthPicker( } @Composable -fun DatePicker( +private fun DatePicker( items: ImmutableList, modifier: Modifier = Modifier, pickerState: PickerState = rememberPickerState(), @@ -135,6 +135,12 @@ fun DatePicker( if (itemHeightPixel > 0 && startIndex >= 0) scrollState.scrollToItem(startIndex) } + val savedIndex by remember { mutableIntStateOf(startIndex) } + + LaunchedEffect(itemHeightPixel, savedIndex) { + scrollState.scrollToItem(savedIndex) + } + LaunchedEffect(scrollState) { snapshotFlow { scrollState.firstVisibleItemIndex } .map { index -> @@ -196,7 +202,7 @@ fun DatePicker( } @Composable -fun DatePickerContent( +private fun DatePickerContent( color: Color, text: String, modifier: Modifier = Modifier, diff --git a/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/JobFilteringScreen.kt b/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/JobFilteringScreen.kt new file mode 100644 index 00000000..03f24343 --- /dev/null +++ b/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/JobFilteringScreen.kt @@ -0,0 +1,102 @@ +package com.terning.feature.home.component.bottomsheet + +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.itemsIndexed +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +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.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.extension.noRippleClickable +import com.terning.core.designsystem.theme.Grey200 +import com.terning.core.designsystem.theme.Grey300 +import com.terning.core.designsystem.theme.Grey350 +import com.terning.core.designsystem.theme.TerningMain +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.type.JobType + +@Composable +internal fun JobFilteringScreen( + initOption: Int, + onButtonClick: (JobType) -> Unit, + modifier: Modifier = Modifier, +) { + var selectedIndex by remember { mutableIntStateOf(initOption) } + + LazyVerticalGrid( + columns = GridCells.Fixed(3), + horizontalArrangement = Arrangement.spacedBy(10.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(bottom = 60.dp, start = 23.dp, end = 23.dp), + + ) { + itemsIndexed(JobType.entries) { index, option -> + JobTypeItem( + jobType = option, + onButtonClick = { + selectedIndex = index + onButtonClick(option) + }, + isSelected = selectedIndex == index + ) + } + } +} + +@Composable +private fun JobTypeItem( + jobType: JobType, + isSelected: Boolean, + onButtonClick: (JobType) -> Unit, + modifier: Modifier = Modifier, +) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = modifier + .border( + width = 1.dp, + color = if (isSelected) TerningMain else Grey200, + shape = RoundedCornerShape(10.dp) + ) + .noRippleClickable { onButtonClick(jobType) } + .padding( + top = 31.dp, + bottom = 33.dp, + start = 27.dp, + end = 26.dp + ), + ) { + Icon( + imageVector = ImageVector.vectorResource(id = jobType.drawableResId), + contentDescription = jobType.stringValue, + tint = if (isSelected) TerningMain else Grey300 + ) + + Text( + text = stringResource(id = jobType.stringResId), + style = TerningTheme.typography.body6, + color = if (isSelected) TerningMain else Grey350, + modifier = Modifier + .padding(top = 7.dp) + ) + } +} \ No newline at end of file diff --git a/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/PlanFilteringScreen.kt b/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/PlanFilteringScreen.kt new file mode 100644 index 00000000..8f3eca20 --- /dev/null +++ b/feature/home/src/main/java/com/terning/feature/home/component/bottomsheet/PlanFilteringScreen.kt @@ -0,0 +1,242 @@ +package com.terning.feature.home.component.bottomsheet + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.itemsIndexed +import androidx.compose.material3.Checkbox +import androidx.compose.material3.CheckboxDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.LocalMinimumInteractiveComponentEnforcement +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +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.res.stringResource +import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.component.button.ChangeFilterButton +import com.terning.core.designsystem.theme.Grey300 +import com.terning.core.designsystem.theme.TerningMain +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.theme.White +import com.terning.core.designsystem.type.Grade +import com.terning.core.designsystem.type.WorkingPeriod +import com.terning.core.designsystem.util.NoRippleInteractionSource +import com.terning.domain.home.entity.HomeFilteringInfo +import com.terning.feature.home.R +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun PlanFilteringScreen( + currentFilteringInfo: HomeFilteringInfo, + modifier: Modifier = Modifier, + updateGrade: (Int?) -> Unit = {}, + updateWorkingPeriod: (Int?) -> Unit = {}, + updateStartYear: (Int?) -> Unit = {}, + updateStartMonth: (Int?) -> Unit = {}, +) { + var isYearNull by remember { mutableStateOf(currentFilteringInfo.startYear == 0 || currentFilteringInfo.startYear == null) } + var isMonthNull by remember { mutableStateOf(currentFilteringInfo.startMonth == 0 || currentFilteringInfo.startMonth == null) } + + var isCheckBoxChecked by remember { mutableStateOf(false) } + + var isInitialNullState by remember { mutableStateOf(false) } + + val yearsList by remember(isYearNull) { + mutableStateOf( + if (isYearNull || isInitialNullState) years + NULL_DATE + else years + ) + } + val monthsList by remember(isMonthNull) { + mutableStateOf( + if (isMonthNull || isInitialNullState) months + NULL_DATE + else months + ) + } + + Column( + modifier = modifier + ) { + ChangeFilteringTitleText( + text = stringResource(id = R.string.change_filter_grade_title), + modifier = Modifier + .padding( + start = 23.dp, + end = 23.dp, + bottom = 12.dp + ) + ) + + ChangePlanFilteringRadioGroup( + initOption = currentFilteringInfo.grade?.let { Grade.fromString(it).ordinal } ?: -1, + isCheckBoxChecked = isCheckBoxChecked, + optionList = listOf( + R.string.change_filter_grade_1, + R.string.change_filter_grade_2, + R.string.change_filter_grade_3, + R.string.change_filter_grade_4, + ).toImmutableList(), + onButtonClick = { + updateGrade(it) + isCheckBoxChecked = false + }, + columns = 4, + modifier = Modifier + .padding(horizontal = 23.dp), + ) + + ChangeFilteringTitleText( + text = stringResource(id = R.string.change_filter_period_title), + modifier = Modifier + .padding(top = 24.dp, bottom = 12.dp) + .padding(horizontal = 24.dp) + ) + + ChangePlanFilteringRadioGroup( + initOption = currentFilteringInfo.workingPeriod?.let { WorkingPeriod.fromString(it).ordinal } + ?: -1, + isCheckBoxChecked = isCheckBoxChecked, + optionList = listOf( + R.string.change_filter_period_1, + R.string.change_filter_period_2, + R.string.change_filter_period_3, + ).toImmutableList(), + onButtonClick = { + updateWorkingPeriod(it) + isCheckBoxChecked = false + }, + modifier = Modifier + .padding(horizontal = 23.dp), + ) + + ChangeFilteringTitleText( + text = stringResource(id = R.string.change_filter_start_work_title), + modifier = Modifier + .padding(24.dp) + ) + + HomeYearMonthPicker( + chosenYear = currentFilteringInfo.startYear, + chosenMonth = currentFilteringInfo.startMonth, + onYearChosen = { year, isInitialSelection -> + updateStartYear(year) + if (year != null) { + isCheckBoxChecked = false + isYearNull = false + isInitialNullState = isInitialSelection + } + }, + onMonthChosen = { month, isInitialSelection -> + updateStartMonth(month) + if (month != null) { + isCheckBoxChecked = false + isMonthNull = false + isInitialNullState = isInitialSelection + } + }, + isYearNull = isYearNull, + isMonthNull = isMonthNull, + yearsList = yearsList.toImmutableList(), + monthsList = monthsList.toImmutableList(), + isInitialNullState = isInitialNullState + ) + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.End, + modifier = Modifier + .fillMaxWidth() + .padding( + bottom = 13.dp, + top = 26.dp, + end = 24.dp + ), + ) { + CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) { + Checkbox( + checked = isCheckBoxChecked, + onCheckedChange = { isChecked -> + if (isChecked) { + isYearNull = true + isMonthNull = true + updateGrade(null) + updateWorkingPeriod(null) + updateStartYear(null) + updateStartMonth(null) + } + isCheckBoxChecked = isChecked + }, + colors = CheckboxDefaults.colors( + checkedColor = TerningMain, + uncheckedColor = Grey300, + checkmarkColor = White, + ), + interactionSource = NoRippleInteractionSource + ) + } + + Text( + text = stringResource(id = R.string.intern_with_no_plan_filter), + style = TerningTheme.typography.button3, + color = Grey300, + modifier = Modifier.padding(start = 6.dp), + ) + } + } +} + +@Composable +private fun ChangePlanFilteringRadioGroup( + optionList: ImmutableList, + initOption: Int, + isCheckBoxChecked: Boolean, + onButtonClick: (Int) -> Unit, + modifier: Modifier = Modifier, + columns: Int = 3, +) { + var selectedIndex by remember { mutableIntStateOf(initOption) } + + LaunchedEffect(isCheckBoxChecked) { + if (isCheckBoxChecked) { + selectedIndex = -1 + } + } + + LazyVerticalGrid( + columns = GridCells.Fixed(columns), + horizontalArrangement = Arrangement.spacedBy(13.dp), + modifier = modifier + .fillMaxWidth() + .wrapContentHeight() + ) { + itemsIndexed(optionList) { index, option -> + ChangeFilterButton( + isSelected = selectedIndex == index && !isCheckBoxChecked, + modifier = Modifier + .wrapContentHeight(), + text = option, + cornerRadius = 10.dp, + paddingVertical = 10.dp, + onButtonClick = { + selectedIndex = index + onButtonClick(index) + } + ) + } + } +} \ No newline at end of file diff --git a/feature/home/src/main/res/values/strings.xml b/feature/home/src/main/res/values/strings.xml index 02b22856..390dfff0 100644 --- a/feature/home/src/main/res/values/strings.xml +++ b/feature/home/src/main/res/values/strings.xml @@ -13,9 +13,6 @@ %s년 %s월 아직 채용중인 인턴 공고가 없어요!\n새로운 공고가 올라오면 보여드릴게요 인턴 공고가 없어요! - - 지금 공고 필터링을 설정하고\n내 계획에 딱 맞는 대학생 인턴 공고를 추천받아보세요! - 설정된 필터링 정보가 없어요 @@ -24,4 +21,20 @@ - 오늘 마감인 공고가 없어요 지원마감 + + 필터링 + 직무 카테고리 + 계획 + 재학 상태 + 저장하기 + 1학년 + 2학년 + 3학년 + 4학년 + 희망 근무 기간 + 1 ~ 3개월 + 4 ~ 6개월 + 7개월 이상 + 근무 시작 시기 + 계획 필터링 없이 모든 공고 보기