diff --git a/Near/app/build.gradle.kts b/Near/app/build.gradle.kts
index 50357e74..7165d602 100644
--- a/Near/app/build.gradle.kts
+++ b/Near/app/build.gradle.kts
@@ -4,6 +4,7 @@ plugins {
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.hilt.application)
alias(libs.plugins.kotlin.kapt)
+ alias(libs.plugins.kotlin.serialization)
}
android {
@@ -73,4 +74,8 @@ dependencies {
implementation(libs.room.ktx)
kapt(libs.room.compiler)
implementation(libs.room.paging)
+ // Navigation
+ implementation(libs.navigation.compose)
+ // Serialization
+ implementation(libs.kotlin.serialization.json)
}
diff --git a/Near/app/src/main/AndroidManifest.xml b/Near/app/src/main/AndroidManifest.xml
index 1101a1e5..1a2cc18e 100644
--- a/Near/app/src/main/AndroidManifest.xml
+++ b/Near/app/src/main/AndroidManifest.xml
@@ -14,7 +14,7 @@
android:theme="@style/Theme.Near"
tools:targetApi="31">
@@ -26,4 +26,4 @@
-
\ No newline at end of file
+
diff --git a/Near/app/src/main/java/com/alarmy/near/MainActivity.kt b/Near/app/src/main/java/com/alarmy/near/MainActivity.kt
deleted file mode 100644
index 738551df..00000000
--- a/Near/app/src/main/java/com/alarmy/near/MainActivity.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.alarmy.near
-
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.activity.enableEdgeToEdge
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material3.Scaffold
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.tooling.preview.Preview
-import com.alarmy.near.ui.theme.NearTheme
-
-class MainActivity : ComponentActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- enableEdgeToEdge()
- setContent {
- NearTheme {
- Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
- Greeting(
- name = "Android",
- modifier = Modifier.padding(innerPadding),
- )
- }
- }
- }
- }
-}
-
-@Composable
-fun Greeting(
- name: String,
- modifier: Modifier = Modifier,
-) {
- Text(
- text = "Hello $name!",
- modifier = modifier,
- )
-}
-
-@Preview(showBackground = true)
-@Composable
-fun GreetingPreview() {
- NearTheme {
- Greeting("Android")
- }
-}
diff --git a/Near/app/src/main/java/com/alarmy/near/data/di/RepositoryModule.kt b/Near/app/src/main/java/com/alarmy/near/data/di/RepositoryModule.kt
new file mode 100644
index 00000000..f63b55df
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/data/di/RepositoryModule.kt
@@ -0,0 +1,17 @@
+package com.alarmy.near.data.di
+
+import com.alarmy.near.data.repository.ExampleRepository
+import com.alarmy.near.data.repository.ExampleRepositoryImpl
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+interface RepositoryModule {
+ @Binds
+ @Singleton
+ abstract fun bindExampleRepository(exampleRepositoryImpl: ExampleRepositoryImpl): ExampleRepository
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/data/mapper/ExampleMapper.kt b/Near/app/src/main/java/com/alarmy/near/data/mapper/ExampleMapper.kt
new file mode 100644
index 00000000..67093aaf
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/data/mapper/ExampleMapper.kt
@@ -0,0 +1,9 @@
+package com.alarmy.near.data.mapper
+
+import com.alarmy.near.model.Example
+import com.alarmy.near.network.response.ExampleEntity
+
+fun ExampleEntity.toModel(): Example =
+ Example(
+ id = id.toString(),
+ )
diff --git a/Near/app/src/main/java/com/alarmy/near/data/repository/ExampleRepository.kt b/Near/app/src/main/java/com/alarmy/near/data/repository/ExampleRepository.kt
new file mode 100644
index 00000000..631d9a57
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/data/repository/ExampleRepository.kt
@@ -0,0 +1,10 @@
+package com.alarmy.near.data.repository
+
+import com.alarmy.near.model.Example
+import kotlinx.coroutines.flow.Flow
+
+interface ExampleRepository {
+ fun getExampleData(): String
+
+ fun getData(): Flow
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/data/repository/ExampleRepositoryImpl.kt b/Near/app/src/main/java/com/alarmy/near/data/repository/ExampleRepositoryImpl.kt
new file mode 100644
index 00000000..f98375eb
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/data/repository/ExampleRepositoryImpl.kt
@@ -0,0 +1,18 @@
+package com.alarmy.near.data.repository
+
+import com.alarmy.near.model.Example
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
+import javax.inject.Inject
+
+class ExampleRepositoryImpl
+ @Inject
+ constructor() : ExampleRepository {
+ override fun getExampleData(): String = "Hello from Repository"
+
+ override fun getData(): Flow =
+ flow {
+ // val result = exampleService.fetchExample()
+ // emit(result.data.toModel())
+ }
+ }
diff --git a/Near/app/src/main/java/com/alarmy/near/model/.gitkeep b/Near/app/src/main/java/com/alarmy/near/model/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/Near/app/src/main/java/com/alarmy/near/model/Example.kt b/Near/app/src/main/java/com/alarmy/near/model/Example.kt
new file mode 100644
index 00000000..c6c1dd7c
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/model/Example.kt
@@ -0,0 +1,5 @@
+package com.alarmy.near.model
+
+data class Example(
+ val id: String,
+)
diff --git a/Near/app/src/main/java/com/alarmy/near/di/AppModule.kt b/Near/app/src/main/java/com/alarmy/near/network/di/AppModule.kt
similarity index 96%
rename from Near/app/src/main/java/com/alarmy/near/di/AppModule.kt
rename to Near/app/src/main/java/com/alarmy/near/network/di/AppModule.kt
index 464b8cda..369900cc 100644
--- a/Near/app/src/main/java/com/alarmy/near/di/AppModule.kt
+++ b/Near/app/src/main/java/com/alarmy/near/network/di/AppModule.kt
@@ -1,4 +1,4 @@
-package com.alarmy.near.di
+package com.alarmy.near.network.di
// @Module
// @InstallIn(SingletonComponent::class)
diff --git a/Near/app/src/main/java/com/alarmy/near/network/response/ExampleEntity.kt b/Near/app/src/main/java/com/alarmy/near/network/response/ExampleEntity.kt
new file mode 100644
index 00000000..b2c04583
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/network/response/ExampleEntity.kt
@@ -0,0 +1,5 @@
+package com.alarmy.near.network.response
+
+data class ExampleEntity(
+ val id: Long,
+)
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/HomeScreen.kt b/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/HomeScreen.kt
new file mode 100644
index 00000000..fd8eebb9
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/HomeScreen.kt
@@ -0,0 +1,51 @@
+package com.alarmy.near.presentation.feature.home
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+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.tooling.preview.Preview
+import androidx.hilt.navigation.compose.hiltViewModel
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.alarmy.near.presentation.feature.home.model.HomeUiState
+import com.alarmy.near.presentation.ui.theme.NearTheme
+
+@Composable
+internal fun HomeRoute(
+ viewModel: HomeViewModel = hiltViewModel(),
+ onShowErrorSnackBar: (throwable: Throwable?) -> Unit,
+) {
+ val uiState = viewModel.uiStateFlow.collectAsStateWithLifecycle()
+ HomeScreen(
+ uiState = uiState.value,
+ onContactClick = {},
+ onRemoveContact = viewModel::removeContact,
+ )
+}
+
+@Composable
+internal fun HomeScreen(
+ modifier: Modifier = Modifier,
+ uiState: HomeUiState,
+ onContactClick: (Long) -> Unit = { _ -> },
+ onRemoveContact: (Long) -> Unit = { _ -> },
+) {
+ Column(modifier = Modifier.fillMaxSize().background(Color.White)) {
+ Text("홈 화면")
+ }
+}
+
+@Preview
+@Composable
+internal fun HomeScreenPreview() {
+ NearTheme {
+ HomeScreen(
+ uiState = HomeUiState.Loading,
+ onContactClick = {},
+ onRemoveContact = {},
+ )
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/HomeViewModel.kt b/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/HomeViewModel.kt
new file mode 100644
index 00000000..6a0b0496
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/HomeViewModel.kt
@@ -0,0 +1,54 @@
+package com.alarmy.near.presentation.feature.home
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.alarmy.near.data.repository.ExampleRepository
+import com.alarmy.near.presentation.feature.home.model.HomeUiState
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@HiltViewModel
+class HomeViewModel
+ @Inject
+ constructor(
+ private val exampleRepository: ExampleRepository,
+ ) : ViewModel() {
+ // Example: 여러번 초기화되는 StateFlow
+ private val _uiStateFlow = MutableStateFlow(HomeUiState.Loading)
+ val uiStateFlow = _uiStateFlow.asStateFlow()
+
+ // Example: 한 번만 초기화되는 StateFlow
+ private val exampleStateFlow =
+ exampleRepository
+ .getData()
+ .map {
+ // Mapping to UIState
+ }.stateIn(
+ scope = viewModelScope,
+ started = SharingStarted.WhileSubscribed(5_000),
+ initialValue = HomeUiState.Loading,
+ )
+
+ fun fetchContacts() {
+ viewModelScope.launch {
+ exampleRepository
+ .getData()
+ .catch {
+ // handle error
+ }.collect {
+ // updateUI
+ }
+ }
+ }
+
+ fun removeContact(id: Long) {
+ // contactRepository.removeContact(id)
+ }
+ }
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/model/HomeUiState.kt b/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/model/HomeUiState.kt
new file mode 100644
index 00000000..c4510aef
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/model/HomeUiState.kt
@@ -0,0 +1,9 @@
+package com.alarmy.near.presentation.feature.home.model
+
+sealed interface HomeUiState {
+ data object Loading : HomeUiState
+
+ data class Success(
+ val data: Any,
+ ) : HomeUiState
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/navigation/HomeNavigation.kt b/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/navigation/HomeNavigation.kt
new file mode 100644
index 00000000..748b9ab4
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/feature/home/navigation/HomeNavigation.kt
@@ -0,0 +1,29 @@
+package com.alarmy.near.presentation.feature.home.navigation
+
+import androidx.navigation.NavController
+import androidx.navigation.NavGraphBuilder
+import androidx.navigation.NavOptions
+import androidx.navigation.compose.composable
+import com.alarmy.near.presentation.feature.home.HomeRoute
+import kotlinx.serialization.Serializable
+
+@Serializable
+object RouteHome
+
+/*
+* 추후 홈으로 화면 이동이 필요할 때 이 함수를 사용합니다.
+* */
+fun NavController.navigateToHome(navOptions: NavOptions) {
+ navigate(RouteHome, navOptions)
+}
+
+fun NavGraphBuilder.homeNavGraph(
+ onShowErrorSnackBar: (throwable: Throwable?) -> Unit,
+ onClickContact: (id: Long) -> Unit,
+) {
+ composable { backStackEntry ->
+ HomeRoute(
+ onShowErrorSnackBar = onShowErrorSnackBar,
+ )
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/feature/main/MainActivity.kt b/Near/app/src/main/java/com/alarmy/near/presentation/feature/main/MainActivity.kt
new file mode 100644
index 00000000..35f00fdc
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/feature/main/MainActivity.kt
@@ -0,0 +1,21 @@
+package com.alarmy.near.presentation.feature.main
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import com.alarmy.near.presentation.ui.theme.NearTheme
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+class MainActivity : ComponentActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ setContent {
+ NearTheme {
+ NearApp()
+ }
+ }
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/feature/main/NearApp.kt b/Near/app/src/main/java/com/alarmy/near/presentation/feature/main/NearApp.kt
new file mode 100644
index 00000000..4730b2ac
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/feature/main/NearApp.kt
@@ -0,0 +1,57 @@
+package com.alarmy.near.presentation.feature.main
+
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.exclude
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.ime
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
+import androidx.compose.foundation.layout.windowInsetsPadding
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.SnackbarDuration
+import androidx.compose.material3.SnackbarHost
+import androidx.compose.material3.SnackbarHostState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Modifier
+import androidx.navigation.NavHostController
+import androidx.navigation.compose.rememberNavController
+import kotlinx.coroutines.launch
+
+@Composable
+internal fun NearApp(
+ modifier: Modifier = Modifier,
+ navController: NavHostController = rememberNavController(),
+) {
+ val snackBarState = remember { SnackbarHostState() }
+ val scope = rememberCoroutineScope()
+
+ Scaffold(
+ modifier = Modifier.fillMaxSize(),
+ snackbarHost = {
+ SnackbarHost(
+ hostState = snackBarState,
+ modifier =
+ Modifier.windowInsetsPadding(
+ WindowInsets.safeDrawing.exclude(
+ WindowInsets.ime,
+ ),
+ ),
+ )
+ },
+ ) { innerPadding ->
+ NearNavHost(
+ modifier = Modifier.padding(innerPadding),
+ navController = navController,
+ onShowSnackbar = {
+ scope.launch {
+ snackBarState.showSnackbar(
+ message = it?.message ?: return@launch,
+ duration = SnackbarDuration.Short,
+ )
+ }
+ },
+ )
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/feature/main/NearNavHost.kt b/Near/app/src/main/java/com/alarmy/near/presentation/feature/main/NearNavHost.kt
new file mode 100644
index 00000000..ee75ae08
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/feature/main/NearNavHost.kt
@@ -0,0 +1,28 @@
+package com.alarmy.near.presentation.feature.main
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.navigation.NavHostController
+import androidx.navigation.compose.NavHost
+import com.alarmy.near.presentation.feature.home.navigation.RouteHome
+import com.alarmy.near.presentation.feature.home.navigation.homeNavGraph
+
+@Composable
+internal fun NearNavHost(
+ modifier: Modifier = Modifier,
+ navController: NavHostController,
+ onShowSnackbar: (Throwable?) -> Unit = { _ -> },
+) {
+ /*
+ * 화면 이동 및 구성을 위한 컴포저블 함수입니다.
+ * */
+ NavHost(
+ modifier = modifier,
+ navController = navController,
+ startDestination = RouteHome,
+ ) {
+ homeNavGraph(onShowErrorSnackBar = onShowSnackbar, onClickContact = {
+ // 예시: navController.navigate(RouteContact(it))
+ })
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/button/LineTypeButton.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/button/LineTypeButton.kt
new file mode 100644
index 00000000..20ed331a
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/button/LineTypeButton.kt
@@ -0,0 +1,67 @@
+package com.alarmy.near.presentation.ui.component.button
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.presentation.ui.theme.NearTheme
+
+@Composable
+fun NearLineTypeButton(
+ modifier: Modifier = Modifier,
+ enabled: Boolean = false,
+ onClick: () -> Unit,
+ contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
+ text: String,
+) {
+ NearBasicButton(
+ modifier = modifier,
+ onClick = onClick,
+ colors =
+ ButtonDefaults.buttonColors(
+ containerColor = NearTheme.colors.WHITE_FFFFFF,
+ contentColor = NearTheme.colors.BLACK_1A1A1A,
+ disabledContainerColor = NearTheme.colors.WHITE_FFFFFF,
+ disabledContentColor = NearTheme.colors.GRAY02_B7B7B7,
+ ),
+ enabled = enabled,
+ border = BorderStroke(width = 1.dp, color = NearTheme.colors.GRAY02_B7B7B7),
+ contentPadding = contentPadding,
+ ) {
+ Text(text = text, style = NearTheme.typography.B1_16_BOLD)
+ }
+}
+
+@Preview(widthDp = 360, heightDp = 70, showBackground = true)
+@Composable
+fun NearLineEnabledButtonPreview() {
+ Surface {
+ NearLineTypeButton(
+ modifier = Modifier.padding(horizontal = 20.dp),
+ enabled = true,
+ text = "Button",
+ onClick = {},
+ contentPadding = PaddingValues(vertical = 17.dp),
+ )
+ }
+}
+
+@Preview(widthDp = 360, heightDp = 70, showBackground = true)
+@Composable
+fun NearLineDisabledButtonPreview() {
+ Surface {
+ NearLineTypeButton(
+ modifier = Modifier.padding(horizontal = 20.dp),
+ enabled = false,
+ text = "Button",
+ onClick = {},
+ contentPadding = PaddingValues(vertical = 17.dp),
+ )
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/button/NearBasicButton.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/button/NearBasicButton.kt
new file mode 100644
index 00000000..68ded9eb
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/button/NearBasicButton.kt
@@ -0,0 +1,60 @@
+package com.alarmy.near.presentation.ui.component.button
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.heightIn
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonColors
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.presentation.ui.theme.NearTheme
+
+@Composable
+fun NearBasicButton(
+ modifier: Modifier = Modifier,
+ onClick: () -> Unit,
+ colors: ButtonColors = ButtonDefaults.buttonColors(
+ containerColor = NearTheme.colors.BLUE01_5AA2E9,
+ contentColor = NearTheme.colors.WHITE_FFFFFF,
+ ),
+ enabled: Boolean = true,
+ border: BorderStroke? = null,
+ contentPadding: PaddingValues,
+ content: @Composable RowScope.() -> Unit,
+) {
+ Button(
+ modifier =
+ modifier
+ .heightIn(min = 56.dp)
+ .wrapContentHeight(),
+ colors = colors,
+ enabled = enabled,
+ onClick = onClick,
+ border = border,
+ shape = RoundedCornerShape(12.dp),
+ contentPadding = contentPadding,
+ content = content,
+ )
+}
+
+@Preview(widthDp = 360, heightDp = 70, showBackground = true)
+@Composable
+fun NearBasicButtonPreview() {
+ Surface {
+ NearBasicButton(
+ modifier = Modifier.padding(horizontal = 20.dp),
+ content = { Text("Button", style = NearTheme.typography.B1_16_BOLD) },
+ onClick = {},
+ contentPadding = PaddingValues(vertical = 17.dp),
+ )
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/button/NearSolidTypeButton.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/button/NearSolidTypeButton.kt
new file mode 100644
index 00000000..1d36d99c
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/button/NearSolidTypeButton.kt
@@ -0,0 +1,65 @@
+package com.alarmy.near.presentation.ui.component.button
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.presentation.ui.theme.NearTheme
+
+@Composable
+fun NearSolidTypeButton(
+ modifier: Modifier = Modifier,
+ enabled: Boolean = false,
+ onClick: () -> Unit,
+ contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
+ text: String,
+) {
+ NearBasicButton(
+ modifier = modifier,
+ onClick = onClick,
+ colors =
+ ButtonDefaults.buttonColors(
+ containerColor = NearTheme.colors.BLUE01_5AA2E9,
+ contentColor = NearTheme.colors.WHITE_FFFFFF,
+ disabledContainerColor = NearTheme.colors.GRAY02_B7B7B7,
+ disabledContentColor = NearTheme.colors.WHITE_FFFFFF,
+ ),
+ enabled = enabled,
+ contentPadding = contentPadding,
+ ) {
+ Text(text = text, style = NearTheme.typography.B1_16_BOLD)
+ }
+}
+
+@Preview(widthDp = 360, heightDp = 70, showBackground = true)
+@Composable
+fun NearSolidEnabledButtonPreview() {
+ Surface {
+ NearSolidTypeButton(
+ modifier = Modifier.padding(horizontal = 20.dp),
+ enabled = true,
+ text = "Button",
+ onClick = {},
+ contentPadding = PaddingValues(vertical = 17.dp),
+ )
+ }
+}
+
+@Preview(widthDp = 360, heightDp = 70, showBackground = true)
+@Composable
+fun NearSolidDisabledButtonPreview() {
+ Surface {
+ NearSolidTypeButton(
+ modifier = Modifier.padding(horizontal = 20.dp),
+ enabled = false,
+ text = "Button",
+ onClick = {},
+ contentPadding = PaddingValues(vertical = 17.dp),
+ )
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/checkbox/NearBackgroundCheckbox.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/checkbox/NearBackgroundCheckbox.kt
new file mode 100644
index 00000000..3e71272a
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/checkbox/NearBackgroundCheckbox.kt
@@ -0,0 +1,63 @@
+package com.alarmy.near.presentation.ui.component.checkbox
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.R
+
+@Composable
+fun NearBackgroundCheckbox(
+ modifier: Modifier = Modifier,
+ checked: Boolean,
+ onCheckedChange: (Boolean) -> Unit,
+) {
+ Image(
+ modifier =
+ modifier.clickable(
+ onClick = { onCheckedChange(!checked) },
+ ),
+ painter =
+ if (checked) {
+ painterResource(R.drawable.btn_checkbox_h1_on)
+ } else {
+ painterResource(R.drawable.btn_checkbox_h1_off)
+ },
+ contentDescription =
+ if (checked) {
+ stringResource(
+ R.string.content_description_checkbox_check,
+ )
+ } else {
+ stringResource(
+ R.string.content_description_checkbox_un_check,
+ )
+ },
+ )
+}
+
+@Preview(widthDp = 360, heightDp = 70, showBackground = true)
+@Composable
+fun NearBackgroundCheckboxPreview() {
+ Surface {
+ Row {
+ NearBackgroundCheckbox(
+ checked = true,
+ onCheckedChange = {},
+ )
+ Spacer(modifier = Modifier.width(50.dp))
+ NearBackgroundCheckbox(
+ checked = false,
+ onCheckedChange = {},
+ )
+ }
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/checkbox/NearCheckbox.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/checkbox/NearCheckbox.kt
new file mode 100644
index 00000000..e2ce96aa
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/checkbox/NearCheckbox.kt
@@ -0,0 +1,53 @@
+package com.alarmy.near.presentation.ui.component.checkbox
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.R
+
+@Composable
+fun NearCheckbox(
+ modifier: Modifier = Modifier,
+ checked: Boolean,
+ onCheckedChange: (Boolean) -> Unit,
+) {
+ Image(
+ modifier =
+ modifier.clickable(
+ onClick = { onCheckedChange(!checked) },
+ ),
+ painter =
+ if (checked) {
+ painterResource(R.drawable.btn_checkbox_h2_on)
+ } else {
+ painterResource(R.drawable.btn_checkbox_h2_off)
+ },
+ contentDescription = null,
+ )
+}
+
+@Preview(widthDp = 360, heightDp = 70, showBackground = true)
+@Composable
+fun NearCheckboxPreview() {
+ Surface {
+ Row {
+ NearCheckbox(
+ checked = true,
+ onCheckedChange = {},
+ )
+ Spacer(modifier = Modifier.width(50.dp))
+ NearCheckbox(
+ checked = false,
+ onCheckedChange = {},
+ )
+ }
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/radiobutton/NearLargeRadioButton.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/radiobutton/NearLargeRadioButton.kt
new file mode 100644
index 00000000..5d24e427
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/radiobutton/NearLargeRadioButton.kt
@@ -0,0 +1,53 @@
+package com.alarmy.near.presentation.ui.component.radiobutton
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.R
+
+@Composable
+fun NearLargeRadioButton(
+ modifier: Modifier = Modifier,
+ selected: Boolean,
+ onClick: (Boolean) -> Unit,
+) {
+ Image(
+ modifier =
+ modifier.clickable(
+ onClick = { onClick(!selected) },
+ ),
+ painter =
+ if (selected) {
+ painterResource(R.drawable.btn_radio_h1_on)
+ } else {
+ painterResource(R.drawable.btn_radio_h1_off)
+ },
+ contentDescription = null,
+ )
+}
+
+@Preview(widthDp = 360, heightDp = 70, showBackground = true)
+@Composable
+fun NearLargeRadioButtonPreview() {
+ Surface {
+ Row {
+ NearLargeRadioButton(
+ selected = true,
+ onClick = {},
+ )
+ Spacer(modifier = Modifier.width(50.dp))
+ NearLargeRadioButton(
+ selected = false,
+ onClick = {},
+ )
+ }
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/radiobutton/NearSmallRadioButton.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/radiobutton/NearSmallRadioButton.kt
new file mode 100644
index 00000000..a8e10f30
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/radiobutton/NearSmallRadioButton.kt
@@ -0,0 +1,53 @@
+package com.alarmy.near.presentation.ui.component.radiobutton
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.R
+
+@Composable
+fun NearSmallRadioButton(
+ modifier: Modifier = Modifier,
+ selected: Boolean,
+ onClick: (Boolean) -> Unit,
+) {
+ Image(
+ modifier =
+ modifier.clickable(
+ onClick = { onClick(!selected) },
+ ),
+ painter =
+ if (selected) {
+ painterResource(R.drawable.btn_radio_h2_on)
+ } else {
+ painterResource(R.drawable.btn_radio_h2_off)
+ },
+ contentDescription = null,
+ )
+}
+
+@Preview(widthDp = 360, heightDp = 70, showBackground = true)
+@Composable
+fun NearSmallRadioButtonPreview() {
+ Surface {
+ Row {
+ NearSmallRadioButton(
+ selected = true,
+ onClick = {},
+ )
+ Spacer(modifier = Modifier.width(50.dp))
+ NearSmallRadioButton(
+ selected = false,
+ onClick = {},
+ )
+ }
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/NearLimitedTextField.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/NearLimitedTextField.kt
new file mode 100644
index 00000000..c5fb4381
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/NearLimitedTextField.kt
@@ -0,0 +1,121 @@
+package com.alarmy.near.presentation.ui.component.textfield
+
+import androidx.compose.foundation.interaction.InteractionSource
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.presentation.ui.component.textfield.internal.NearOutlinedTextFieldDecorationBox
+import com.alarmy.near.presentation.ui.component.textfield.internal.NearTextFieldColors
+import com.alarmy.near.presentation.ui.component.textfield.internal.NearTextFieldDecorationContainer
+import com.alarmy.near.presentation.ui.theme.NearTheme
+
+private const val MAX_TEXT_COUNT = 200
+
+@Composable
+fun NearLimitedTextField(
+ modifier: Modifier = Modifier,
+ value: String,
+ maxTextCount: Int = MAX_TEXT_COUNT,
+ onValueChange: (String) -> Unit,
+ enabled: Boolean,
+ placeHolderText: String,
+ singleLine: Boolean = false,
+ interactionSource: InteractionSource = remember { MutableInteractionSource() },
+) {
+ val colors = NearTextFieldColors()
+
+ // TextCount에서 End,Bottom에 Margin을 주고자 했는데, 원인은 모르곘으나 마진차가 있었음
+ // 이를 해결하기 위한 임시 해결책으로 1줄일 때 가운데 정렬 설정
+ val lineCount = remember { mutableIntStateOf(1) }
+
+ NearTextField(
+ modifier = modifier,
+ value = value,
+ enabled = enabled,
+ onValueChange = onValueChange,
+ placeHolderText = placeHolderText,
+ onTextLayout = {
+ lineCount.intValue = it.lineCount
+ },
+ singleLine = singleLine,
+ interactionSource = interactionSource,
+ decorationBox = { innerTextField ->
+ NearOutlinedTextFieldDecorationBox(
+ value = value,
+ innerTextField = innerTextField,
+ enabled = enabled,
+ singleLine = singleLine,
+ interactionSource = interactionSource,
+ colors = colors,
+ placeHolderText = placeHolderText,
+ contentPadding =
+ PaddingValues(
+ top = 16.dp,
+ bottom = 16.dp,
+ start = 16.dp,
+ end = 76.dp,
+ // Container 구조상 Row를 통해 TextCount의 텍스트와 마진을 줄 수 없는 구조
+ // 현재 차선책으로 강제 value 설정
+ ),
+ container = {
+ NearTextFieldDecorationContainer(
+ enabled = enabled,
+ interactionSource = interactionSource,
+ colors = colors,
+ )
+ if (value.count() > 0 && enabled) {
+ Row(
+ modifier = Modifier,
+ horizontalArrangement = Arrangement.End,
+ verticalAlignment =
+ if (lineCount.intValue == 1) {
+ Alignment.CenterVertically
+ } else {
+ Alignment.Bottom
+ },
+ ) {
+ Text(
+ text = "${value.count()}/$maxTextCount",
+ modifier =
+ Modifier.padding(
+ end = 16.dp,
+ bottom = if (lineCount.intValue == 1) 0.dp else 16.dp,
+ ),
+ style = NearTheme.typography.B2_14_MEDIUM,
+ color = NearTheme.colors.GRAY02_B7B7B7,
+ )
+ }
+ }
+ },
+ )
+ },
+ )
+}
+
+@Preview(widthDp = 370, heightDp = 52, showBackground = true)
+@Composable
+fun NearEnabledLimitedTextFieldPreview() {
+ Surface(modifier = Modifier.padding(horizontal = 20.dp)) {
+ NearLimitedTextField(
+ modifier =
+ Modifier
+ .wrapContentHeight(),
+ enabled = true,
+ value = "테스트",
+ onValueChange = {},
+ placeHolderText = "플레이스 홀더",
+ )
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/NearTextField.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/NearTextField.kt
new file mode 100644
index 00000000..77c47934
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/NearTextField.kt
@@ -0,0 +1,106 @@
+package com.alarmy.near.presentation.ui.component.textfield
+
+import androidx.compose.foundation.interaction.InteractionSource
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.presentation.ui.component.textfield.internal.NearOutlinedTextFieldDecorationBox
+import com.alarmy.near.presentation.ui.component.textfield.internal.NearTextFieldColors
+import com.alarmy.near.presentation.ui.theme.NearTheme
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun NearTextField(
+ modifier: Modifier = Modifier,
+ value: String,
+ enabled: Boolean = true,
+ onValueChange: (String) -> Unit,
+ placeHolderText: String = "",
+ singleLine: Boolean = false,
+ onTextLayout: (textLayoutResult: TextLayoutResult) -> Unit = {},
+ interactionSource: InteractionSource = remember { MutableInteractionSource() },
+ decorationBox: (@Composable (innerTextField: @Composable () -> Unit) -> Unit)? = null,
+) {
+ val colors = NearTextFieldColors()
+
+ BasicTextField(
+ value = value,
+ modifier = modifier,
+ enabled = enabled,
+ textStyle =
+ NearTheme.typography.B2_14_MEDIUM.copy(
+ color = if (enabled) colors.focusedTextColor else colors.disabledTextColor,
+ ),
+ cursorBrush = SolidColor(NearTheme.colors.BLACK_1A1A1A),
+ onValueChange = onValueChange,
+ decorationBox =
+ decorationBox
+ ?: { innerTextField ->
+ NearOutlinedTextFieldDecorationBox(
+ value = value,
+ innerTextField = innerTextField,
+ enabled = enabled,
+ singleLine = singleLine,
+ interactionSource = interactionSource,
+ colors = colors,
+ placeHolderText = placeHolderText,
+ )
+ },
+ onTextLayout = onTextLayout
+ )
+}
+
+@Preview(widthDp = 370, heightDp = 80, showBackground = true)
+@Composable
+fun NearUnFocusedTextFieldPreview() {
+ Surface(modifier = Modifier.padding(horizontal = 20.dp)) {
+ NearTextField(
+ modifier = Modifier.wrapContentHeight(),
+ value = "",
+ onValueChange = {},
+ placeHolderText = "플레이스 홀더",
+ )
+ }
+}
+
+@Preview(widthDp = 370, heightDp = 80, showBackground = true)
+@Composable
+fun NearDisabledTextFieldPreview() {
+ Surface(modifier = Modifier.padding(horizontal = 20.dp)) {
+ NearTextField(
+ modifier =
+ Modifier
+ .wrapContentHeight(),
+ enabled = false,
+ value = "비활성화",
+ onValueChange = {},
+ placeHolderText = "플레이스 홀더",
+ )
+ }
+}
+
+@Preview(widthDp = 370, heightDp = 80, showBackground = true)
+@Composable
+fun NearEnabledTextFieldPreview() {
+ Surface(modifier = Modifier.padding(horizontal = 20.dp)) {
+ NearTextField(
+ modifier =
+ Modifier
+ .wrapContentHeight(),
+ enabled = true,
+ value = "입력완료",
+ onValueChange = {},
+ placeHolderText = "플레이스 홀더",
+ )
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/internal/NearOutlinedTextFieldDecorationBox.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/internal/NearOutlinedTextFieldDecorationBox.kt
new file mode 100644
index 00000000..9e48fad5
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/internal/NearOutlinedTextFieldDecorationBox.kt
@@ -0,0 +1,69 @@
+package com.alarmy.near.presentation.ui.component.textfield.internal
+
+import androidx.compose.foundation.interaction.InteractionSource
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.OutlinedTextFieldDefaults
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextFieldColors
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.text.input.VisualTransformation
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.presentation.ui.theme.NearTheme
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+internal fun NearOutlinedTextFieldDecorationBox(
+ value: String,
+ innerTextField: @Composable () -> Unit,
+ enabled: Boolean,
+ singleLine: Boolean,
+ interactionSource: InteractionSource,
+ colors: TextFieldColors,
+ contentPadding: PaddingValues = PaddingValues(16.dp),
+ placeHolderText: String,
+ container: (@Composable () -> Unit) = {
+ NearTextFieldDecorationContainer(
+ enabled = enabled,
+ interactionSource = interactionSource,
+ colors = colors
+ )
+ }
+) {
+ OutlinedTextFieldDefaults.DecorationBox(
+ contentPadding = contentPadding,
+ value = value,
+ innerTextField = innerTextField,
+ enabled = enabled,
+ singleLine = singleLine,
+ interactionSource = interactionSource,
+ visualTransformation = VisualTransformation.None,
+ placeholder = {
+ Text(
+ text = placeHolderText,
+ style = NearTheme.typography.B2_14_MEDIUM,
+ color = NearTheme.colors.GRAY02_B7B7B7,
+ )
+ },
+ container = container,
+ )
+}
+
+@Composable
+@OptIn(ExperimentalMaterial3Api::class)
+internal fun NearTextFieldDecorationContainer(
+ enabled: Boolean,
+ interactionSource: InteractionSource,
+ colors: TextFieldColors,
+) {
+ OutlinedTextFieldDefaults.Container(
+ enabled = enabled,
+ isError = false,
+ interactionSource = interactionSource,
+ colors = colors,
+ shape = RoundedCornerShape(12.dp),
+ focusedBorderThickness = (1.5).dp,
+ unfocusedBorderThickness = (1.5).dp,
+ )
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/internal/NearTextFieldColors.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/internal/NearTextFieldColors.kt
new file mode 100644
index 00000000..47bdb9c2
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/textfield/internal/NearTextFieldColors.kt
@@ -0,0 +1,21 @@
+package com.alarmy.near.presentation.ui.component.textfield.internal
+
+import android.annotation.SuppressLint
+import androidx.compose.material3.OutlinedTextFieldDefaults
+import androidx.compose.runtime.Composable
+import com.alarmy.near.presentation.ui.theme.NearTheme
+
+@SuppressLint("ComposableNaming")
+@Composable
+fun NearTextFieldColors() =
+ OutlinedTextFieldDefaults.colors(
+ focusedBorderColor = NearTheme.colors.BLUE02_8ACCFF,
+ focusedTextColor = NearTheme.colors.BLACK_1A1A1A,
+ focusedContainerColor = NearTheme.colors.WHITE_FFFFFF,
+ unfocusedTextColor = NearTheme.colors.BLACK_1A1A1A,
+ unfocusedBorderColor = NearTheme.colors.GRAY03_EBEBEB,
+ unfocusedContainerColor = NearTheme.colors.WHITE_FFFFFF,
+ disabledTextColor = NearTheme.colors.GRAY02_B7B7B7,
+ disabledContainerColor = NearTheme.colors.GRAY04_F7F7F7,
+ disabledBorderColor = NearTheme.colors.GRAY03_EBEBEB,
+ )
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/toggle/NearToggleButton.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/toggle/NearToggleButton.kt
new file mode 100644
index 00000000..e56cc837
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/component/toggle/NearToggleButton.kt
@@ -0,0 +1,116 @@
+package com.alarmy.near.presentation.ui.component.toggle
+
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.scale
+import androidx.compose.ui.geometry.CornerRadius
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import com.alarmy.near.presentation.ui.theme.NearTheme
+
+@Composable
+fun NearToggleButton(
+ modifier: Modifier = Modifier,
+ checked: Boolean,
+ onCheckedChange: (Boolean) -> Unit,
+) {
+ NearCustomSwitch(
+ isChecked = checked,
+ onCheckedChange,
+ scale = 1f,
+ width = 48.dp,
+ height = 26.dp,
+ strokeWidth = 0.dp,
+ checkedTrackColor = NearTheme.colors.BLUE02_8ACCFF,
+ uncheckedTrackColor = Color(0xffDEDEDE),
+ )
+}
+
+@Composable
+private fun NearCustomSwitch(
+ isChecked: Boolean,
+ onCheckedChange: (Boolean) -> Unit,
+ scale: Float = 2f,
+ width: Dp = 36.dp,
+ height: Dp = 20.dp,
+ strokeWidth: Dp = 2.dp,
+ checkedTrackColor: Color = Color(0xFF35898F),
+ uncheckedTrackColor: Color = Color(0xFFe0e0e0),
+ gapBetweenThumbAndTrackEdge: Dp = 4.dp,
+) {
+ val thumbRadius = (height / 2) - gapBetweenThumbAndTrackEdge
+
+ // To move thumb, we need to calculate the position (along x axis)
+ val animatePosition =
+ animateFloatAsState(
+ targetValue =
+ if (isChecked) {
+ with(LocalDensity.current) { (width - thumbRadius - gapBetweenThumbAndTrackEdge).toPx() }
+ } else {
+ with(LocalDensity.current) { (thumbRadius + gapBetweenThumbAndTrackEdge).toPx() }
+ },
+ )
+
+ Canvas(
+ modifier =
+ Modifier
+ .size(width = width, height = height)
+ .scale(scale = scale)
+ .pointerInput(Unit) {
+ detectTapGestures(
+ onTap = {
+ // This is called when the user taps on the canvas
+ onCheckedChange(!isChecked)
+ },
+ )
+ },
+ ) {
+ // Track
+ drawRoundRect(
+ color = if (isChecked) checkedTrackColor else uncheckedTrackColor,
+ cornerRadius = CornerRadius(x = 13.dp.toPx(), y = 13.dp.toPx()),
+ )
+
+ // Thumb
+ drawCircle(
+ color = Color(0xffffffff),
+ radius = thumbRadius.toPx(),
+ center =
+ Offset(
+ x = animatePosition.value,
+ y = size.height / 2,
+ ),
+ )
+ }
+}
+
+@Preview(widthDp = 360, heightDp = 70, showBackground = true)
+@Composable
+fun NearToggleButtonPreview() {
+ Surface {
+ Row {
+ NearToggleButton(
+ checked = true,
+ onCheckedChange = {},
+ )
+ Spacer(modifier = Modifier.width(50.dp))
+ NearToggleButton(
+ checked = false,
+ onCheckedChange = {},
+ )
+ }
+ }
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/theme/Color.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/theme/Color.kt
new file mode 100644
index 00000000..61de2917
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/theme/Color.kt
@@ -0,0 +1,39 @@
+@file:Suppress("SpellCheckingInspection")
+
+package com.alarmy.near.presentation.ui.theme
+
+import androidx.compose.ui.graphics.Color
+
+object NearColorPallete {
+ val BLACK_1A1A1A = Color(0xFF1A1A1A)
+ val WHITE_FFFFFF = Color(0xFFFFFFFF)
+ val GRAY01_888888 = Color(0xFF888888)
+ val GRAY02_B7B7B7 = Color(0xFFB7B7B7)
+ val GRAY03_EBEBEB = Color(0xFFEBEBEB)
+ val GRAY04_F7F7F7 = Color(0xFFF7F7F7)
+ val BLUE01_5AA2E9 = Color(0xFF5AA2E9)
+ val BLUE02_8ACCFF = Color(0xFF8ACCFF)
+ val BG01_E3F0F9 = Color(0xFFE3F0F9)
+ val BG02_F4F9FD = Color(0xFFF4F9FD)
+ val NEGATIVE_F04E4E = Color(0xFFF04E4E)
+ val DIM_000000 = Color(0x99000000)
+}
+
+@Suppress("PropertyName")
+data class NearColor(
+ val BLACK_1A1A1A: Color = NearColorPallete.BLACK_1A1A1A,
+ val WHITE_FFFFFF: Color = NearColorPallete.WHITE_FFFFFF,
+ val GRAY01_888888: Color = NearColorPallete.GRAY01_888888,
+ val GRAY02_B7B7B7: Color = NearColorPallete.GRAY02_B7B7B7,
+ val GRAY03_EBEBEB: Color = NearColorPallete.GRAY03_EBEBEB,
+ val GRAY04_F7F7F7: Color = NearColorPallete.GRAY04_F7F7F7,
+ val BLUE01_5AA2E9: Color = NearColorPallete.BLUE01_5AA2E9,
+ val BLUE02_8ACCFF: Color = NearColorPallete.BLUE02_8ACCFF,
+ val BG01_E3F0F9: Color = NearColorPallete.BG01_E3F0F9,
+ val BG02_F4F9FD: Color = NearColorPallete.BG02_F4F9FD,
+ val NEGATIVE_F04E4E: Color = NearColorPallete.NEGATIVE_F04E4E,
+ val DIM_000000: Color = NearColorPallete.DIM_000000,
+)
+
+val darkColor = NearColor()
+val lightColor = NearColor()
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/theme/Theme.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/theme/Theme.kt
new file mode 100644
index 00000000..b6167e82
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/theme/Theme.kt
@@ -0,0 +1,42 @@
+package com.alarmy.near.presentation.ui.theme
+
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.staticCompositionLocalOf
+
+val LocalCustomColors =
+ staticCompositionLocalOf {
+ NearColor()
+ }
+
+val LocalCustomTypography =
+ staticCompositionLocalOf {
+ Typography
+ }
+
+@Composable
+fun NearTheme(
+ darkTheme: Boolean = isSystemInDarkTheme(),
+ content: @Composable () -> Unit,
+) {
+ val colorScheme =
+ when {
+ darkTheme -> lightColor // TODO DarkTheme 추가시 수정
+ else -> lightColor
+ }
+ CompositionLocalProvider(
+ LocalCustomColors provides colorScheme,
+ LocalCustomTypography provides Typography,
+ content = content,
+ )
+}
+
+object NearTheme {
+ val colors: NearColor
+ @Composable
+ get() = LocalCustomColors.current
+ val typography: NearTypography
+ @Composable
+ get() = LocalCustomTypography.current
+}
diff --git a/Near/app/src/main/java/com/alarmy/near/presentation/ui/theme/Type.kt b/Near/app/src/main/java/com/alarmy/near/presentation/ui/theme/Type.kt
new file mode 100644
index 00000000..99b830e4
--- /dev/null
+++ b/Near/app/src/main/java/com/alarmy/near/presentation/ui/theme/Type.kt
@@ -0,0 +1,221 @@
+package com.alarmy.near.presentation.ui.theme
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.Font
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.alarmy.near.R
+
+@Suppress("PropertyName")
+@Immutable
+data class NearTypography(
+ val H1_24_BOLD: TextStyle,
+ val H1_24_MEDIUM: TextStyle,
+ val H1_24_REGULAR: TextStyle,
+ val H2_18_BOLD: TextStyle,
+ val B1_16_BOLD: TextStyle,
+ val B1_16_MEDIUM: TextStyle,
+ val B2_14_BOLD: TextStyle,
+ val B2_14_MEDIUM: TextStyle,
+ val FC_12_BOLD: TextStyle,
+ val FC_12_MEDIUM: TextStyle,
+)
+
+val Pretendard =
+ FontFamily(
+ Font(
+ resId = R.font.pretendard_bold,
+ weight = FontWeight.Bold,
+ ),
+ Font(
+ resId = R.font.pretendard_regular,
+ weight = FontWeight.Normal,
+ ),
+ Font(
+ resId = R.font.pretendard_extra_bold,
+ weight = FontWeight.ExtraBold,
+ ),
+ Font(
+ resId = R.font.pretendard_extra_light,
+ weight = FontWeight.ExtraLight,
+ ),
+ Font(
+ resId = R.font.pretendard_extra_light,
+ weight = FontWeight.Light,
+ ),
+ Font(
+ resId = R.font.pretendard_medium,
+ weight = FontWeight.Medium,
+ ),
+ Font(
+ resId = R.font.pretendard_semi_bold,
+ weight = FontWeight.SemiBold,
+ ),
+ Font(
+ resId = R.font.pretendard_thin,
+ weight = FontWeight.Thin,
+ ),
+ )
+
+internal val Typography =
+ NearTypography(
+ H1_24_BOLD =
+ TextStyle(
+ fontFamily = Pretendard,
+ fontWeight = FontWeight.Bold,
+ fontSize = 24.sp,
+ lineHeight = 34.sp,
+ letterSpacing =
+ letterSpacingToSp(
+ fontSize = 24.sp,
+ letterSpacingPercent = -0.25f,
+ ),
+ ),
+ H1_24_MEDIUM =
+ TextStyle(
+ fontFamily = Pretendard,
+ fontWeight = FontWeight.Medium,
+ fontSize = 24.sp,
+ lineHeight = 34.sp,
+ letterSpacing =
+ letterSpacingToSp(
+ fontSize = 24.sp,
+ letterSpacingPercent = -0.25f,
+ ),
+ ),
+ H1_24_REGULAR =
+ TextStyle(
+ fontFamily = Pretendard,
+ fontWeight = FontWeight.Normal,
+ fontSize = 24.sp,
+ lineHeight = 34.sp,
+ letterSpacing =
+ letterSpacingToSp(
+ fontSize = 24.sp,
+ letterSpacingPercent = -0.25f,
+ ),
+ ),
+ H2_18_BOLD =
+ TextStyle(
+ fontFamily = Pretendard,
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp,
+ lineHeight = 24.sp,
+ letterSpacing =
+ letterSpacingToSp(
+ fontSize = 18.sp,
+ letterSpacingPercent = -0.25f,
+ ),
+ ),
+ B1_16_BOLD =
+ TextStyle(
+ fontFamily = Pretendard,
+ fontWeight = FontWeight.Bold,
+ fontSize = 16.sp,
+ lineHeight = 22.sp,
+ letterSpacing =
+ letterSpacingToSp(
+ fontSize = 16.sp,
+ letterSpacingPercent = -0.25f,
+ ),
+ ),
+ B1_16_MEDIUM =
+ TextStyle(
+ fontFamily = Pretendard,
+ fontWeight = FontWeight.Medium,
+ fontSize = 16.sp,
+ lineHeight = 22.sp,
+ letterSpacing =
+ letterSpacingToSp(
+ fontSize = 16.sp,
+ letterSpacingPercent = -0.25f,
+ ),
+ ),
+ B2_14_BOLD =
+ TextStyle(
+ fontFamily = Pretendard,
+ fontWeight = FontWeight.Bold,
+ fontSize = 14.sp,
+ lineHeight = 20.sp,
+ letterSpacing =
+ letterSpacingToSp(
+ fontSize = 14.sp,
+ letterSpacingPercent = -0.25f,
+ ),
+ ),
+ B2_14_MEDIUM =
+ TextStyle(
+ fontFamily = Pretendard,
+ fontWeight = FontWeight.Medium,
+ fontSize = 14.sp,
+ lineHeight = 20.sp,
+ letterSpacing =
+ letterSpacingToSp(
+ fontSize = 14.sp,
+ letterSpacingPercent = -0.25f,
+ ),
+ ),
+ FC_12_BOLD =
+ TextStyle(
+ fontFamily = Pretendard,
+ fontWeight = FontWeight.Bold,
+ fontSize = 12.sp,
+ lineHeight = 18.sp,
+ letterSpacing =
+ letterSpacingToSp(
+ fontSize = 12.sp,
+ letterSpacingPercent = -0.25f,
+ ),
+ ),
+ FC_12_MEDIUM =
+ TextStyle(
+ fontFamily = Pretendard,
+ fontWeight = FontWeight.Medium,
+ fontSize = 12.sp,
+ lineHeight = 18.sp,
+ letterSpacing =
+ letterSpacingToSp(
+ fontSize = 12.sp,
+ letterSpacingPercent = -0.25f,
+ ),
+ ),
+ )
+
+@Preview(showBackground = true)
+@Composable
+private fun TypographyPreview() {
+ Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 20.dp)) {
+ Text("소중한 사람들과 더 가까워지는 시간 24", style = Typography.H1_24_BOLD)
+ Text("소중한 사람들과 더 가까워지는 시간 24", style = Typography.H1_24_MEDIUM)
+ Text("소중한 사람들과 더 가까워지는 시간 24", style = Typography.H1_24_REGULAR)
+ Text("소중한 사람들과 더 가까워지는 시간 18", style = Typography.H2_18_BOLD)
+ Text("소중한 사람들과 더 가까워지는 시간 16", style = Typography.B1_16_BOLD)
+ Text("소중한 사람들과 더 가까워지는 시간 16", style = Typography.B1_16_MEDIUM)
+ Text("소중한 사람들과 더 가까워지는 시간 14", style = Typography.B2_14_BOLD)
+ Text("소중한 사람들과 더 가까워지는 시간 14", style = Typography.B2_14_MEDIUM)
+ Text("소중한 사람들과 더 가까워지는 시간 12", style = Typography.FC_12_BOLD)
+ Text("소중한 사람들과 더 가까워지는 시간 12", style = Typography.FC_12_MEDIUM)
+ }
+}
+
+/**
+ * Converts Figma letterSpacing (%) to Android Compose TextUnit (sp).
+ *
+ * @param fontSize Font size in sp.
+ * @param letterSpacingPercent Letter spacing in percent (e.g., -0.25 for -0.25%)
+ * @return Converted letterSpacing in sp
+ */
+private fun letterSpacingToSp(
+ fontSize: TextUnit,
+ letterSpacingPercent: Float,
+): TextUnit = (fontSize.value * (letterSpacingPercent / 100f)).sp
diff --git a/Near/app/src/main/java/com/alarmy/near/repository/ExampleRepository.kt b/Near/app/src/main/java/com/alarmy/near/repository/ExampleRepository.kt
deleted file mode 100644
index d6ea4d99..00000000
--- a/Near/app/src/main/java/com/alarmy/near/repository/ExampleRepository.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.alarmy.near.repository
-
-interface ExampleRepository {
- fun getExampleData(): String
-}
diff --git a/Near/app/src/main/java/com/alarmy/near/repository/ExampleRepositoryImpl.kt b/Near/app/src/main/java/com/alarmy/near/repository/ExampleRepositoryImpl.kt
deleted file mode 100644
index 4709a51f..00000000
--- a/Near/app/src/main/java/com/alarmy/near/repository/ExampleRepositoryImpl.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.alarmy.near.repository
-
-class ExampleRepositoryImpl : ExampleRepository {
- override fun getExampleData(): String = "Hello from Repository"
-}
diff --git a/Near/app/src/main/java/com/alarmy/near/ui/theme/Color.kt b/Near/app/src/main/java/com/alarmy/near/ui/theme/Color.kt
deleted file mode 100644
index 869c5ab5..00000000
--- a/Near/app/src/main/java/com/alarmy/near/ui/theme/Color.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.alarmy.near.ui.theme
-
-import androidx.compose.ui.graphics.Color
-
-val Purple80 = Color(0xFFD0BCFF)
-val PurpleGrey80 = Color(0xFFCCC2DC)
-val Pink80 = Color(0xFFEFB8C8)
-
-val Purple40 = Color(0xFF6650a4)
-val PurpleGrey40 = Color(0xFF625b71)
-val Pink40 = Color(0xFF7D5260)
\ No newline at end of file
diff --git a/Near/app/src/main/java/com/alarmy/near/ui/theme/Theme.kt b/Near/app/src/main/java/com/alarmy/near/ui/theme/Theme.kt
deleted file mode 100644
index 7ed827c7..00000000
--- a/Near/app/src/main/java/com/alarmy/near/ui/theme/Theme.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.alarmy.near.ui.theme
-
-import android.app.Activity
-import android.os.Build
-import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.darkColorScheme
-import androidx.compose.material3.dynamicDarkColorScheme
-import androidx.compose.material3.dynamicLightColorScheme
-import androidx.compose.material3.lightColorScheme
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.platform.LocalContext
-
-private val DarkColorScheme = darkColorScheme(
- primary = Purple80,
- secondary = PurpleGrey80,
- tertiary = Pink80
-)
-
-private val LightColorScheme = lightColorScheme(
- primary = Purple40,
- secondary = PurpleGrey40,
- tertiary = Pink40
-
- /* Other default colors to override
- background = Color(0xFFFFFBFE),
- surface = Color(0xFFFFFBFE),
- onPrimary = Color.White,
- onSecondary = Color.White,
- onTertiary = Color.White,
- onBackground = Color(0xFF1C1B1F),
- onSurface = Color(0xFF1C1B1F),
- */
-)
-
-@Composable
-fun NearTheme(
- darkTheme: Boolean = isSystemInDarkTheme(),
- // Dynamic color is available on Android 12+
- dynamicColor: Boolean = true,
- content: @Composable () -> Unit
-) {
- val colorScheme = when {
- dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
- val context = LocalContext.current
- if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
- }
-
- darkTheme -> DarkColorScheme
- else -> LightColorScheme
- }
-
- MaterialTheme(
- colorScheme = colorScheme,
- typography = Typography,
- content = content
- )
-}
\ No newline at end of file
diff --git a/Near/app/src/main/java/com/alarmy/near/ui/theme/Type.kt b/Near/app/src/main/java/com/alarmy/near/ui/theme/Type.kt
deleted file mode 100644
index fdc85618..00000000
--- a/Near/app/src/main/java/com/alarmy/near/ui/theme/Type.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.alarmy.near.ui.theme
-
-import androidx.compose.material3.Typography
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.sp
-
-// Set of Material typography styles to start with
-val Typography = Typography(
- bodyLarge = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 16.sp,
- lineHeight = 24.sp,
- letterSpacing = 0.5.sp
- )
- /* Other default text styles to override
- titleLarge = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 22.sp,
- lineHeight = 28.sp,
- letterSpacing = 0.sp
- ),
- labelSmall = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Medium,
- fontSize = 11.sp,
- lineHeight = 16.sp,
- letterSpacing = 0.5.sp
- )
- */
-)
\ No newline at end of file
diff --git a/Near/app/src/main/res/drawable/btn_checkbox_h1_off.xml b/Near/app/src/main/res/drawable/btn_checkbox_h1_off.xml
new file mode 100644
index 00000000..33746460
--- /dev/null
+++ b/Near/app/src/main/res/drawable/btn_checkbox_h1_off.xml
@@ -0,0 +1,18 @@
+
+
+
+
diff --git a/Near/app/src/main/res/drawable/btn_checkbox_h1_on.xml b/Near/app/src/main/res/drawable/btn_checkbox_h1_on.xml
new file mode 100644
index 00000000..1c158816
--- /dev/null
+++ b/Near/app/src/main/res/drawable/btn_checkbox_h1_on.xml
@@ -0,0 +1,18 @@
+
+
+
+
diff --git a/Near/app/src/main/res/drawable/btn_checkbox_h2_off.xml b/Near/app/src/main/res/drawable/btn_checkbox_h2_off.xml
new file mode 100644
index 00000000..3e4aac37
--- /dev/null
+++ b/Near/app/src/main/res/drawable/btn_checkbox_h2_off.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/Near/app/src/main/res/drawable/btn_checkbox_h2_on.xml b/Near/app/src/main/res/drawable/btn_checkbox_h2_on.xml
new file mode 100644
index 00000000..70b78948
--- /dev/null
+++ b/Near/app/src/main/res/drawable/btn_checkbox_h2_on.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/Near/app/src/main/res/drawable/btn_radio_h1_off.xml b/Near/app/src/main/res/drawable/btn_radio_h1_off.xml
new file mode 100644
index 00000000..2e05b5cd
--- /dev/null
+++ b/Near/app/src/main/res/drawable/btn_radio_h1_off.xml
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/Near/app/src/main/res/drawable/btn_radio_h1_on.xml b/Near/app/src/main/res/drawable/btn_radio_h1_on.xml
new file mode 100644
index 00000000..c7a463ab
--- /dev/null
+++ b/Near/app/src/main/res/drawable/btn_radio_h1_on.xml
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/Near/app/src/main/res/drawable/btn_radio_h2_off.xml b/Near/app/src/main/res/drawable/btn_radio_h2_off.xml
new file mode 100644
index 00000000..8b5686cc
--- /dev/null
+++ b/Near/app/src/main/res/drawable/btn_radio_h2_off.xml
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/Near/app/src/main/res/drawable/btn_radio_h2_on.xml b/Near/app/src/main/res/drawable/btn_radio_h2_on.xml
new file mode 100644
index 00000000..c2de1784
--- /dev/null
+++ b/Near/app/src/main/res/drawable/btn_radio_h2_on.xml
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/Near/app/src/main/res/font/pretendard_black.ttf b/Near/app/src/main/res/font/pretendard_black.ttf
new file mode 100644
index 00000000..d0c1db81
Binary files /dev/null and b/Near/app/src/main/res/font/pretendard_black.ttf differ
diff --git a/Near/app/src/main/res/font/pretendard_bold.ttf b/Near/app/src/main/res/font/pretendard_bold.ttf
new file mode 100644
index 00000000..fb07fc65
Binary files /dev/null and b/Near/app/src/main/res/font/pretendard_bold.ttf differ
diff --git a/Near/app/src/main/res/font/pretendard_extra_bold.ttf b/Near/app/src/main/res/font/pretendard_extra_bold.ttf
new file mode 100644
index 00000000..9d5fe072
Binary files /dev/null and b/Near/app/src/main/res/font/pretendard_extra_bold.ttf differ
diff --git a/Near/app/src/main/res/font/pretendard_extra_light.ttf b/Near/app/src/main/res/font/pretendard_extra_light.ttf
new file mode 100644
index 00000000..09e65428
Binary files /dev/null and b/Near/app/src/main/res/font/pretendard_extra_light.ttf differ
diff --git a/Near/app/src/main/res/font/pretendard_light.ttf b/Near/app/src/main/res/font/pretendard_light.ttf
new file mode 100644
index 00000000..2e8541d6
Binary files /dev/null and b/Near/app/src/main/res/font/pretendard_light.ttf differ
diff --git a/Near/app/src/main/res/font/pretendard_medium.ttf b/Near/app/src/main/res/font/pretendard_medium.ttf
new file mode 100644
index 00000000..1db67c68
Binary files /dev/null and b/Near/app/src/main/res/font/pretendard_medium.ttf differ
diff --git a/Near/app/src/main/res/font/pretendard_regular.ttf b/Near/app/src/main/res/font/pretendard_regular.ttf
new file mode 100644
index 00000000..01147e99
Binary files /dev/null and b/Near/app/src/main/res/font/pretendard_regular.ttf differ
diff --git a/Near/app/src/main/res/font/pretendard_semi_bold.ttf b/Near/app/src/main/res/font/pretendard_semi_bold.ttf
new file mode 100644
index 00000000..9f2690f0
Binary files /dev/null and b/Near/app/src/main/res/font/pretendard_semi_bold.ttf differ
diff --git a/Near/app/src/main/res/font/pretendard_thin.ttf b/Near/app/src/main/res/font/pretendard_thin.ttf
new file mode 100644
index 00000000..fe9825f1
Binary files /dev/null and b/Near/app/src/main/res/font/pretendard_thin.ttf differ
diff --git a/Near/app/src/main/res/values/strings.xml b/Near/app/src/main/res/values/strings.xml
index 7d9190ac..deaa8adc 100644
--- a/Near/app/src/main/res/values/strings.xml
+++ b/Near/app/src/main/res/values/strings.xml
@@ -1,3 +1,5 @@
Near
-
\ No newline at end of file
+ 체크
+ 체크 해제
+
diff --git a/Near/gradle/libs.versions.toml b/Near/gradle/libs.versions.toml
index b5aa516e..b0336eb5 100644
--- a/Near/gradle/libs.versions.toml
+++ b/Near/gradle/libs.versions.toml
@@ -1,6 +1,6 @@
[versions]
agp = "8.10.1"
-kotlin = "2.0.21"
+kotlin = "2.2.0"
coreKtx = "1.16.0"
junit = "4.13.2"
junitVersion = "1.2.1"
@@ -9,7 +9,7 @@ lifecycleRuntimeKtx = "2.9.1"
activityCompose = "1.10.1"
composeBom = "2024.09.00"
# Hilt
-hiltVersion = "2.51.1"
+hiltVersion = "2.57"
hiltNavigationVersion = "1.2.0"
# Retrofit
retrofitVersion = "2.9.0"
@@ -19,6 +19,10 @@ glideVersion = "4.16.0"
roomVersion = "2.6.1"
# Ktlint
ktlintVersion = "13.0.0"
+# Navigation
+navigationVersion = "2.9.2"
+# Kotlin Serialization
+kotlinSerializationVersion = "1.9.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -46,6 +50,8 @@ room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "
room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "roomVersion" }
room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "roomVersion" }
room-paging = { group = "androidx.room", name = "room-paging", version.ref = "roomVersion" }
+navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationVersion" }
+kotlin-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinSerializationVersion" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
@@ -54,4 +60,5 @@ kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "ko
hilt-application = { id = "com.google.dagger.hilt.android", version.ref = "hiltVersion" }
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlintVersion" }
+kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }