diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6dfe38b..9ccbfc2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -79,6 +79,9 @@ dependencies { implementation(libs.converter.gson) implementation(libs.androidx.core.splashscreen) + implementation(libs.androidx.material) + implementation(libs.androidx.material.icons.core) + implementation(libs.androidx.material.icons.extended) implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.activity.compose) diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png index 4007c41..abf6dd4 100644 Binary files a/app/src/main/ic_launcher-playstore.png and b/app/src/main/ic_launcher-playstore.png differ diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index da7e9d9..3368d4b 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -1,11 +1,7 @@ package com.sampoom.android.app.navigation -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Button +import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem @@ -14,7 +10,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.navigation.NavHostController @@ -30,23 +25,25 @@ const val ROUTE_LOGIN = "login" const val ROUTE_HOME = "home" // Main Screen -const val ROUTE_PART = "part" -const val ROUTE_INVENTORY = "inventory" -const val ROUTE_PROFILE = "profile" -const val ROUTE_SETTINGS = "settings" +const val ROUTE_DASHBOARD = "dashboard" +const val ROUTE_DELIVERY = "delivery" +const val ROUTE_CART = "cart" +const val ROUTE_ORDERS = "orders" // Detail Screen -const val ROUTE_DETAIL = "detail" +const val ROUTE_PARTS = "parts" +const val ROUTE_EMPLOYEE = "employee" +const val ROUTE_SETTINGS = "settings" sealed class BottomNavItem( val route: String, val title: Int, val icon: Int ) { - object Part : BottomNavItem(ROUTE_PART, R.string.nav_part, R.drawable.outline_home_24) - object Inventory : BottomNavItem(ROUTE_INVENTORY, R.string.nav_inventory, R.drawable.outline_home_24) - object Profile : BottomNavItem(ROUTE_PROFILE, R.string.nav_profile, R.drawable.outline_home_24) - object Settings : BottomNavItem(ROUTE_SETTINGS, R.string.nav_setting, R.drawable.outline_home_24) + object Dashboard : BottomNavItem(ROUTE_DASHBOARD, R.string.nav_dashboard, R.drawable.dashboard) + object Delivery : BottomNavItem(ROUTE_DELIVERY, R.string.nav_delivery, R.drawable.delivery) + object Cart : BottomNavItem(ROUTE_CART, R.string.nav_cart, R.drawable.cart) + object Orders : BottomNavItem(ROUTE_ORDERS, R.string.nav_order, R.drawable.orders) } @Composable @@ -68,7 +65,7 @@ fun AppNavHost() { }) } composable(ROUTE_HOME) { MainScreen(navController) } - composable(ROUTE_DETAIL) { DetailScreen() } + composable(ROUTE_PARTS) { PartScreen() } } } @@ -79,30 +76,46 @@ fun MainScreen( val navController = rememberNavController() Scaffold( - bottomBar = { - BottomNavigationBar(navController) - } + floatingActionButton = { PartsFab(parentNavController) }, + bottomBar = { BottomNavigationBar(navController) } ) { innerPadding -> NavHost( navController = navController, - startDestination = ROUTE_PART, - modifier = Modifier.background(Color.Green).padding(innerPadding) + startDestination = ROUTE_DASHBOARD, + modifier = Modifier.padding(innerPadding) ) { - composable(ROUTE_PART) { PartScreen() } - composable(ROUTE_INVENTORY) { InventoryScreen() } - composable(ROUTE_PROFILE) { ProfileScreen() } - composable(ROUTE_SETTINGS) { SettingsScreen(parentNavController) } + composable(ROUTE_DASHBOARD) { DashboardScreen() } + composable(ROUTE_DELIVERY) { DeliveryScreen() } + composable(ROUTE_CART) { CartScreen() } + composable(ROUTE_ORDERS) { OrderScreen() } + } + } +} + +@Composable +fun PartsFab(navController: NavHostController) { + FloatingActionButton( + onClick = { + navController.navigate(ROUTE_PARTS) { + popUpTo(navController.graph.startDestinationId) { + saveState = true + } + launchSingleTop = true + restoreState = true + } } + ) { + Icon(painterResource(R.drawable.parts), contentDescription = stringResource(R.string.part_title)) } } @Composable fun BottomNavigationBar(navController: NavHostController) { val bottomNavItems = listOf( - BottomNavItem.Part, - BottomNavItem.Inventory, - BottomNavItem.Profile, - BottomNavItem.Settings, + BottomNavItem.Dashboard, + BottomNavItem.Delivery, + BottomNavItem.Cart, + BottomNavItem.Orders, ) NavigationBar { @@ -130,41 +143,25 @@ fun BottomNavigationBar(navController: NavHostController) { // 임시 화면들 (실제로는 각각의 feature 모듈에서 구현) @Composable -private fun InventoryScreen() { +private fun DashboardScreen() { // 홈 화면 구현 - Text("인벤토리 화면") + Text("대시보드 화면") } @Composable -private fun ProfileScreen() { +private fun DeliveryScreen() { // 프로필 화면 구현 - Text("프로필 화면") + Text("Delivery 화면") } @Composable -private fun SettingsScreen( - navController: NavHostController -) { - Column( - modifier = Modifier.fillMaxSize() - ) { - // 설정 화면 구현 - Text("설정 화면") - Button( - onClick = { navController.navigate(ROUTE_DETAIL) } - ) { - Text("상세 화면") - } - } +private fun CartScreen() { + // 프로필 화면 구현 + Text("Cart 화면") } @Composable -private fun DetailScreen() { - // 설정 화면 구현 - Scaffold { innerPadding -> - Box(Modifier.fillMaxSize().background(Color.Red).padding(innerPadding) - ) { - Text("상세 화면") - } - } +private fun OrderScreen() { + // 프로필 화면 구현 + Text("Order 화면") } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/.gitkeep b/app/src/main/java/com/sampoom/android/core/ui/component/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt new file mode 100644 index 0000000..a9ba4d0 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt @@ -0,0 +1,256 @@ +package com.sampoom.android.core.ui.component + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.FilledTonalButton +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +/** + * Sampoom common button with multiple visual variants. + * + * Usage + * ----- + * CommonButton( + * text = "Button", + * variant = ButtonVariant.Primary, + * onClick = { ... } + * ) + * + * Optionally pass a leading icon: + * CommonButton( + * text = "Button", + * variant = ButtonVariant.Primary, + * leadingIcon = { Icon(painterResource(R.drawable.parts), contentDescription = null) }, + * onClick = { ... } + * ) + */ +@Composable +fun CommonButton( + text: String, + modifier: Modifier = Modifier, + enabled: Boolean = true, + variant: ButtonVariant = ButtonVariant.Primary, + size: ButtonSize = ButtonSize.Large, + leadingIcon: (@Composable (() -> Unit))? = null, + onClick: () -> Unit +) { + val cs = MaterialTheme.colorScheme + val shape = MaterialTheme.shapes.large + val height = when (size) { + ButtonSize.Large -> 56.dp + ButtonSize.Medium -> 48.dp + ButtonSize.Small -> 40.dp + } + + when (variant) { + ButtonVariant.Primary -> { + Button( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + colors = ButtonDefaults.buttonColors( + containerColor = cs.primary, + contentColor = cs.onPrimary, + disabledContainerColor = cs.onSurface.copy(alpha = 0.12f), + disabledContentColor = cs.onSurface.copy(alpha = 0.38f), + ) + ) { + if (leadingIcon != null) { + leadingIcon() + } + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold, + modifier = Modifier.padding(start = if (leadingIcon != null) 8.dp else 0.dp) + ) + } + } + + // Light/secondary (tonal) filled button + ButtonVariant.Secondary -> { + FilledTonalButton( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + colors = ButtonDefaults.filledTonalButtonColors( + containerColor = cs.secondaryContainer, + contentColor = cs.onSecondaryContainer, + disabledContainerColor = cs.onSurface.copy(alpha = 0.08f), + disabledContentColor = cs.onSurface.copy(alpha = 0.38f) + ) + ) { + if (leadingIcon != null) { + leadingIcon() + } + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold, + modifier = Modifier.padding(start = if (leadingIcon != null) 8.dp else 0.dp) + ) + } + } + + // Outlined with primary border + ButtonVariant.Outlined -> { + OutlinedButton( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + border = BorderStroke(1.dp, cs.primary), + colors = ButtonDefaults.outlinedButtonColors( + contentColor = cs.primary, + disabledContentColor = cs.onSurface.copy(alpha = 0.38f) + ) + ) { + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold + ) + } + } + + // Ghost: no container, subtle onSurface content + ButtonVariant.Ghost -> { + TextButton( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + colors = ButtonDefaults.textButtonColors( + contentColor = cs.onSurface, + disabledContentColor = cs.onSurface.copy(alpha = 0.38f) + ) + ) { + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold + ) + } + } + + // Destructive/Neutral (dark) filled – matches the black fill example + ButtonVariant.Neutral -> { + Button( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + colors = ButtonDefaults.buttonColors( + containerColor = Color(0xFF000000), + contentColor = Color.White, + disabledContainerColor = cs.onSurface.copy(alpha = 0.12f), + disabledContentColor = cs.onSurface.copy(alpha = 0.38f), + ) + ) { + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold + ) + } + } + } +} + +enum class ButtonVariant { + /** Primary filled (purple in design). Accepts optional [leadingIcon]. */ + Primary, + + /** Filled tonal (light purple in design). */ + Secondary, + + /** Outlined with primary border. */ + Outlined, + + /** No container; text only. */ + Ghost, + + /** Solid dark/neutral fill. */ + Neutral, +} + +enum class ButtonSize { Large, Medium, Small } + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_All() { + // Primary + CommonButton( + text = "Button", + variant = ButtonVariant.Primary, + onClick = {} + ) +} + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_Primary_WithIcon() { + CommonButton( + text = "Button", + variant = ButtonVariant.Primary, + leadingIcon = { Icon(painterResource(android.R.drawable.ic_menu_call), contentDescription = null) }, + onClick = {} + ) +} + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_Tonal() { + CommonButton( + text = "Button", + variant = ButtonVariant.Secondary, + onClick = {} + ) +} + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_Outlined() { + CommonButton( + text = "Button", + variant = ButtonVariant.Outlined, + onClick = {} + ) +} + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_Ghost() { + CommonButton( + text = "Button", + variant = ButtonVariant.Ghost, + onClick = {} + ) +} + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_Neutral_Disabled() { + CommonButton( + text = "Button", + variant = ButtonVariant.Neutral, + enabled = false, + onClick = {} + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt new file mode 100644 index 0000000..52ba4bf --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt @@ -0,0 +1,164 @@ +package com.sampoom.android.core.ui.component + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Visibility +import androidx.compose.material.icons.filled.VisibilityOff +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +enum class TextFieldVariant { Outlined, Filled } + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun CommonTextField( + value: String, + onValueChange: (String) -> Unit, + label: String, + placeholder: String, + modifier: Modifier = Modifier, + enabled: Boolean = true, + isPassword: Boolean = false, + variant: TextFieldVariant = TextFieldVariant.Outlined +) { + var passwordVisible by remember { mutableStateOf(false) } + val darkTheme = isSystemInDarkTheme() + val cs = MaterialTheme.colorScheme + + val textColor = if (darkTheme) Color.White else Color.Black + val containerColor = if (variant == TextFieldVariant.Filled) { + if (darkTheme) Color(0xFF1C1C1E) else Color(0xFFF3F3F3) + } else Color.Transparent + + val focusedBorderColor = cs.primary + val unfocusedBorderColor = if (darkTheme) Color(0xFF666666) else Color(0xFFCCCCCC) + + val trailingIconView = if (isPassword) { + @Composable { + IconButton(onClick = { passwordVisible = !passwordVisible }) { + Icon( + imageVector = if (passwordVisible) Icons.Default.Visibility else Icons.Default.VisibilityOff, + contentDescription = null, + tint = if (darkTheme) Color.White else Color.Black + ) + } + } + } else null + + when (variant) { + TextFieldVariant.Outlined -> { + OutlinedTextField( + value = value, + onValueChange = onValueChange, + label = { Text(text = label, color = textColor) }, + placeholder = { Text(text = placeholder, color = textColor.copy(alpha = 0.4f)) }, + modifier = modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + singleLine = true, + enabled = enabled, + trailingIcon = trailingIconView, + visualTransformation = if (isPassword && !passwordVisible) PasswordVisualTransformation() else VisualTransformation.None, + keyboardOptions = KeyboardOptions(keyboardType = if (isPassword) KeyboardType.Password else KeyboardType.Text), + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = focusedBorderColor, + unfocusedBorderColor = unfocusedBorderColor, + disabledBorderColor = Color.Gray, + focusedLabelColor = focusedBorderColor, + unfocusedLabelColor = textColor.copy(alpha = 0.7f), + cursorColor = focusedBorderColor, + focusedTextColor = textColor, + unfocusedTextColor = textColor + ), + shape = MaterialTheme.shapes.medium + ) + } + + TextFieldVariant.Filled -> { + TextField( + value = value, + onValueChange = onValueChange, + label = { Text(text = label, color = textColor) }, + placeholder = { Text(text = placeholder, color = textColor.copy(alpha = 0.4f)) }, + modifier = modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + singleLine = true, + enabled = enabled, + trailingIcon = trailingIconView, + visualTransformation = if (isPassword && !passwordVisible) PasswordVisualTransformation() else VisualTransformation.None, + keyboardOptions = KeyboardOptions(keyboardType = if (isPassword) KeyboardType.Password else KeyboardType.Text), + colors = TextFieldDefaults.colors( + focusedContainerColor = containerColor, + unfocusedContainerColor = containerColor, + disabledContainerColor = containerColor.copy(alpha = 0.5f), + focusedIndicatorColor = focusedBorderColor, + unfocusedIndicatorColor = unfocusedBorderColor, + cursorColor = focusedBorderColor, + focusedTextColor = textColor, + unfocusedTextColor = textColor + ), + shape = MaterialTheme.shapes.medium + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun Preview_Light_CommonTextFields() { + MaterialTheme { + Column { + CommonTextField( + value = "Example@naver.com", + onValueChange = {}, + label = "이메일 입력", + placeholder = "Example@naver.com", + variant = TextFieldVariant.Outlined + ) + CommonTextField( + value = "", + onValueChange = {}, + label = "비밀번호 입력", + placeholder = "비밀번호 입력", + isPassword = true, + variant = TextFieldVariant.Outlined + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun Preview_Dark_CommonTextFields() { + MaterialTheme(colorScheme = darkColorScheme()) { + Column { + CommonTextField( + value = "Example@naver.com", + onValueChange = {}, + label = "이메일 입력", + placeholder = "Example@naver.com", + variant = TextFieldVariant.Filled + ) + CommonTextField( + value = "", + onValueChange = {}, + label = "비밀번호 입력", + placeholder = "비밀번호 입력", + isPassword = true, + variant = TextFieldVariant.Filled + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 2f48b78..1164887 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -20,60 +20,63 @@ fun PartScreen( ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() - Column( - modifier = Modifier - .fillMaxSize() - .padding(16.dp) - ) { - Text( - text = stringResource(R.string.part_title), - style = MaterialTheme.typography.headlineMedium, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(bottom = 16.dp) - ) + Scaffold { innerPadding -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding) + .padding(16.dp) + ) { + Text( + text = stringResource(R.string.part_title), + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(bottom = 16.dp) + ) - when { - uiState.loading -> { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() + when { + uiState.loading -> { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } - } - - uiState.error != null -> { - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Text( - text = "${stringResource(R.string.common_error)}: ${uiState.error}", - color = MaterialTheme.colorScheme.error - ) - Spacer(modifier = Modifier.height(16.dp)) - Button(onClick = { viewModel.refreshPart() }) { - Text(stringResource((R.string.common_retry))) + + uiState.error != null -> { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = "${stringResource(R.string.common_error)}: ${uiState.error}", + color = MaterialTheme.colorScheme.error + ) + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = { viewModel.refreshPart() }) { + Text(stringResource((R.string.common_retry))) + } } } - } - - uiState.partList.isEmpty() -> { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text(stringResource(R.string.part_empty)) + + uiState.partList.isEmpty() -> { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text(stringResource(R.string.part_empty)) + } } - } - - else -> { - LazyColumn( - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(uiState.partList) { inventory -> - PartItemCard(part = inventory) + + else -> { + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(uiState.partList) { inventory -> + PartItemCard(part = inventory) + } } } } diff --git a/app/src/main/res/drawable-night/ic_launcher_foreground.xml b/app/src/main/res/drawable-night/ic_launcher_foreground.xml index a41ec78..60f045c 100644 --- a/app/src/main/res/drawable-night/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable-night/ic_launcher_foreground.xml @@ -11,10 +11,10 @@ android:pathData="M0,0h512v512h-512z" android:fillColor="#36393F"/> diff --git a/app/src/main/res/drawable/cart.xml b/app/src/main/res/drawable/cart.xml new file mode 100644 index 0000000..afc4912 --- /dev/null +++ b/app/src/main/res/drawable/cart.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/dashboard.xml b/app/src/main/res/drawable/dashboard.xml new file mode 100644 index 0000000..c2c0e05 --- /dev/null +++ b/app/src/main/res/drawable/dashboard.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/delivery.xml b/app/src/main/res/drawable/delivery.xml new file mode 100644 index 0000000..ca411d4 --- /dev/null +++ b/app/src/main/res/drawable/delivery.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/employee.xml b/app/src/main/res/drawable/employee.xml new file mode 100644 index 0000000..8ac942e --- /dev/null +++ b/app/src/main/res/drawable/employee.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index 1c28491..078cfa1 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -11,10 +11,10 @@ android:pathData="M0,0h512v512h-512z" android:fillColor="#ffffff"/> diff --git a/app/src/main/res/drawable/orders.xml b/app/src/main/res/drawable/orders.xml new file mode 100644 index 0000000..7521789 --- /dev/null +++ b/app/src/main/res/drawable/orders.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/parts.xml b/app/src/main/res/drawable/parts.xml new file mode 100644 index 0000000..ff89964 --- /dev/null +++ b/app/src/main/res/drawable/parts.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/search.xml b/app/src/main/res/drawable/search.xml new file mode 100644 index 0000000..519d2d6 --- /dev/null +++ b/app/src/main/res/drawable/search.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/settings.xml b/app/src/main/res/drawable/settings.xml new file mode 100644 index 0000000..20ed042 --- /dev/null +++ b/app/src/main/res/drawable/settings.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp index 7f4c78a..1ed8d22 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.webp and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp index 09b2c83..46762f5 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp index 719851c..371dc79 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.webp and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp index 46f6e2c..4898eeb 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp index 75b8c6f..5b3a93f 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp index d92ac47..e963f60 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp index 188e558..0e089a9 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp index dbf8648..7581993 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp index 7b5e294..71adf05 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp index 61466d1..c436d4d 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9ebea0a..8a5d69e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,10 +2,10 @@ 삼품관리 - 부품 조회 - 인벤토리 - 프로필 - 설정 + 대시보드 + 출고목록 + 장바구니 + 주문관리 로그인 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 14f873b..3c44195 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,9 @@ junitVersion = "1.3.0" espressoCore = "3.7.0" lifecycleRuntimeKtx = "2.9.4" activityCompose = "1.11.0" -composeBom = "2025.09.01" +composeBom = "2025.10.00" +material = "1.9.3" +materialIconsCore = "1.7.8" navigationCompose = "2.9.5" retrofitVersion = "3.0.0" @@ -20,6 +22,9 @@ androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", versi androidx-hilt-lifecycle-viewmodel-compose = { module = "androidx.hilt:hilt-lifecycle-viewmodel-compose", version.ref = "hiltNavigationCompose" } androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } +androidx-material = { module = "androidx.compose.material:material", version.ref = "material" } +androidx-material-icons-core = { module = "androidx.compose.material:material-icons-core", version.ref = "materialIconsCore" } +androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" } converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofitVersion" } hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" } hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" }