Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ dependencies {
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
testImplementation(libs.assertj.core)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
// coroutine
Expand Down
Empty file.
28 changes: 28 additions & 0 deletions android/app/src/main/java/com/on/turip/domain/region/Region.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.on.turip.domain.region

enum class Region(
private val regionType: RegionType,
) {
SEOUL(RegionType.METROPOLITAN_CITY),
BUSAN(RegionType.METROPOLITAN_CITY),
DAEGU(RegionType.METROPOLITAN_CITY),
INCHEON(RegionType.METROPOLITAN_CITY),
GWANGJU(RegionType.METROPOLITAN_CITY),
DAEJEON(RegionType.METROPOLITAN_CITY),
ULSAN(RegionType.METROPOLITAN_CITY),
SEJONG(RegionType.METROPOLITAN_CITY),
GYEONGGI(RegionType.PROVINCE),
GANGWON(RegionType.PROVINCE),
CHUNGCHEONGBUK(RegionType.PROVINCE),
CHUNGCHEONGNAM(RegionType.PROVINCE),
JEOLLABUK(RegionType.PROVINCE),
JEOLLANAM(RegionType.PROVINCE),
GYEONGSANGBUK(RegionType.PROVINCE),
GYEONGSANGNAM(RegionType.PROVINCE),
JEJU(RegionType.METROPOLITAN_CITY),
;

companion object {
fun from(regionType: RegionType): List<Region> = Region.entries.filter { it.regionType == regionType }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.on.turip.domain.region

enum class RegionType {
METROPOLITAN_CITY,
PROVINCE,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.on.turip.ui.common.model

import com.on.turip.domain.region.Region

enum class RegionModel(
val korean: String,
val english: String,
private val origin: Region,
) {
SEOUL("서울", "seoul", Region.SEOUL),
BUSAN("부산", "busan", Region.BUSAN),
DAEGU("대구", "daegu", Region.DAEGU),
INCHEON("인천", "incheon", Region.INCHEON),
GWANGJU("광주", "gwangju", Region.GWANGJU),
DAEJEON("대전", "daejeon", Region.DAEJEON),
ULSAN("울산", "ulsan", Region.ULSAN),
SEJONG("세종", "sejong", Region.SEJONG),
GYEONGGI("경기", "gyeonggi", Region.GYEONGGI),
GANGWON("강원", "gangwon", Region.GANGWON),
CHUNGCHEONGBUK("충북", "chungcheongbuk", Region.CHUNGCHEONGBUK),
CHUNGCHEONGNAM("충남", "chungcheongnam", Region.CHUNGCHEONGNAM),
JEOLLABUK("전북", "jeollabuk", Region.JEOLLABUK),
JEOLLANAM("전남", "jeollanam", Region.JEOLLANAM),
GYEONGSANGBUK("경북", "gyeongsangbuk", Region.GYEONGSANGBUK),
GYEONGSANGNAM("경남", "gyeongsangnam", Region.GYEONGSANGNAM),
JEJU("제주", "jeju", Region.JEJU),
;

companion object {
fun find(region: Region): RegionModel =
RegionModel.entries.find { it.origin == region }
?: throw IllegalArgumentException("해당 $region 에 일치하는 Model이 없습니다.")
}
}
35 changes: 35 additions & 0 deletions android/app/src/main/java/com/on/turip/ui/main/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.core.content.ContextCompat
import com.on.turip.R
import com.on.turip.databinding.ActivityMainBinding
import com.on.turip.ui.common.base.BaseActivity
import com.on.turip.ui.common.model.RegionModel

class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>() {
override val viewModel: MainViewModel by viewModels()
Expand All @@ -17,10 +18,29 @@ class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>() {
ActivityMainBinding.inflate(layoutInflater)
}

private val metropolitanCitiesAdapter: RegionAdapter =
RegionAdapter(
object : RegionViewHolder.OnRegionListener {
override fun onRegionClick(region: RegionModel) {
// TODO: 지역 검색 결과 뷰로 이동
}
},
)
private val provincesAdapter: RegionAdapter =
RegionAdapter(
object : RegionViewHolder.OnRegionListener {
override fun onRegionClick(region: RegionModel) {
// TODO: 지역 검색 결과 뷰로 이동
}
},
)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setupTextHighlighting()
setupAdapters()
setupObservers()
}

private fun setupTextHighlighting() {
Expand All @@ -46,4 +66,19 @@ class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>() {

binding.tvMainWhereShouldWeGoTitle.text = spannableText
}

private fun setupAdapters() {
binding.rvMainMetropolitanCity.adapter = metropolitanCitiesAdapter
binding.rvMainProvince.adapter = provincesAdapter
}

private fun setupObservers() {
viewModel.metropolitanCities.observe(this) { metropolitanCities: List<RegionModel> ->
metropolitanCitiesAdapter.submitList(metropolitanCities)
}

viewModel.provinces.observe(this) { provinces: List<RegionModel> ->
provincesAdapter.submitList(provinces)
}
}
}
19 changes: 18 additions & 1 deletion android/app/src/main/java/com/on/turip/ui/main/MainViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
package com.on.turip.ui.main

import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.liveData
import com.on.turip.domain.region.Region
import com.on.turip.domain.region.RegionType
import com.on.turip.ui.common.model.RegionModel

class MainViewModel : ViewModel()
class MainViewModel : ViewModel() {
val metropolitanCities: LiveData<List<RegionModel>> =
liveData {
val metropolitans: List<Region> = Region.from(RegionType.METROPOLITAN_CITY)
emit(metropolitans.map(RegionModel::find))
}

val provinces: LiveData<List<RegionModel>> =
liveData {
val provinces: List<Region> = Region.from(RegionType.PROVINCE)
emit(provinces.map(RegionModel::find))
}
}
34 changes: 34 additions & 0 deletions android/app/src/main/java/com/on/turip/ui/main/RegionAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.on.turip.ui.main

import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import com.on.turip.ui.common.model.RegionModel

class RegionAdapter(
private val onRegionListener: RegionViewHolder.OnRegionListener,
) : ListAdapter<RegionModel, RegionViewHolder>(
RegionDiffUtil,
) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
): RegionViewHolder = RegionViewHolder.of(parent, onRegionListener)

override fun onBindViewHolder(
holder: RegionViewHolder,
position: Int,
): Unit = holder.bind(getItem(position))

private object RegionDiffUtil : DiffUtil.ItemCallback<RegionModel>() {
override fun areItemsTheSame(
oldItem: RegionModel,
newItem: RegionModel,
): Boolean = oldItem.english == newItem.english

override fun areContentsTheSame(
oldItem: RegionModel,
newItem: RegionModel,
): Boolean = oldItem == newItem
}
}
41 changes: 41 additions & 0 deletions android/app/src/main/java/com/on/turip/ui/main/RegionViewHolder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.on.turip.ui.main

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.on.turip.databinding.ItemSearchingRegionBinding
import com.on.turip.ui.common.model.RegionModel

class RegionViewHolder(
private val binding: ItemSearchingRegionBinding,
onRegionListener: OnRegionListener,
) : RecyclerView.ViewHolder(binding.root) {
private var region: RegionModel? = null

init {
binding.root.setOnClickListener {
region?.let { onRegionListener.onRegionClick(it) }
}
}

fun bind(region: RegionModel) {
this.region = region
binding.tvSearchingRegion.text = region.korean
}

companion object {
fun of(
parent: ViewGroup,
onRegionListener: OnRegionListener,
): RegionViewHolder {
val inflater: LayoutInflater = LayoutInflater.from(parent.context)
val binding: ItemSearchingRegionBinding =
ItemSearchingRegionBinding.inflate(inflater, parent, false)
return RegionViewHolder(binding, onRegionListener)
}
}

fun interface OnRegionListener {
fun onRegionClick(region: RegionModel)
}
}
20 changes: 12 additions & 8 deletions android/app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="@string/main_where_should_we_go_title"
android:textAppearance="@style/title1"
android:textAppearance="@style/display"
android:textColor="@color/gray_500_1e1e1e"
app:layout_constraintStart_toStartOf="@id/iv_main_logo"
app:layout_constraintTop_toBottomOf="@id/iv_main_logo" />
Expand All @@ -36,7 +36,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:text="@string/main_searching_metropolitan_city"
android:textAppearance="@style/title2"
android:textAppearance="@style/title1"
android:textColor="@color/gray_400_2b2b2b"
app:layout_constraintStart_toStartOf="@id/tv_main_where_should_we_go_title"
app:layout_constraintTop_toBottomOf="@id/tv_main_where_should_we_go_title" />
Expand All @@ -49,34 +49,38 @@
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingVertical="20dp"
android:paddingStart="20dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/tv_main_searching_metropolitan_city"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_main_searching_metropolitan_city"
tools:listitem="@layout/item_searching_region" />
tools:listitem="@layout/item_searching_region"
tools:ignore="RtlSymmetry" />

<TextView
android:id="@+id/tv_main_searching_province"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/main_searching_province"
android:textAppearance="@style/title2"
android:textAppearance="@style/title1"
android:textColor="@color/gray_400_2b2b2b"
app:layout_constraintStart_toStartOf="@id/rv_main_metropolitan_city"
app:layout_constraintStart_toStartOf="@id/tv_main_searching_metropolitan_city"
app:layout_constraintTop_toBottomOf="@id/rv_main_metropolitan_city" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_main_searching_province"
android:id="@+id/rv_main_province"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingVertical="20dp"
android:paddingStart="20dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/tv_main_searching_province"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_main_searching_province"
tools:ignore="RtlSymmetry"
tools:listitem="@layout/item_searching_region" />
</androidx.constraintlayout.widget.ConstraintLayout>
4 changes: 2 additions & 2 deletions android/app/src/main/res/layout/item_searching_region.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:background="@drawable/bg_gra400_radius_24dp"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:paddingHorizontal="20dp"
android:paddingVertical="10dp"
android:textAppearance="@style/title2"
android:textColor="@color/pure_white_ffffff"
app:layout_constraintBottom_toBottomOf="parent"
Expand Down
51 changes: 51 additions & 0 deletions android/app/src/test/java/com/on/turip/domain/region/RegionTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.on.turip.domain.region

import org.assertj.core.api.Assertions.assertThat
import org.junit.Test

class RegionTest {
@Test
fun `지역 타입이 광역시인 지역을 반환한다`() {
// given:
val expected: List<Region> =
listOf(
Region.SEOUL,
Region.BUSAN,
Region.DAEGU,
Region.INCHEON,
Region.GWANGJU,
Region.DAEJEON,
Region.ULSAN,
Region.SEJONG,
Region.JEJU,
)

// when:
val result = Region.from(RegionType.METROPOLITAN_CITY)

// then:
assertThat(result).isEqualTo(expected)
}

@Test
fun `지역 타입이 도인 지역을 반환한다`() {
// given:
val expected: List<Region> =
listOf(
Region.GYEONGGI,
Region.GANGWON,
Region.CHUNGCHEONGBUK,
Region.CHUNGCHEONGNAM,
Region.JEOLLABUK,
Region.JEOLLANAM,
Region.GYEONGSANGBUK,
Region.GYEONGSANGNAM,
)

// when:
val result = Region.from(RegionType.PROVINCE)

// then:
assertThat(result).isEqualTo(expected)
}
}
2 changes: 2 additions & 0 deletions android/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[versions]
agp = "8.9.0"
assertjCore = "3.27.3"
fragmentKtx = "1.8.8"
kotlin = "2.1.0"
coreKtx = "1.16.0"
Expand All @@ -23,6 +24,7 @@ androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragmentKtx" }
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertjCore" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
Expand Down