diff --git a/app/src/main/java/eu/gaudian/translator/view/Navigation.kt b/app/src/main/java/eu/gaudian/translator/view/Navigation.kt index dff415e..bd6abeb 100644 --- a/app/src/main/java/eu/gaudian/translator/view/Navigation.kt +++ b/app/src/main/java/eu/gaudian/translator/view/Navigation.kt @@ -41,6 +41,8 @@ import eu.gaudian.translator.view.vocabulary.CategoryDetailScreen import eu.gaudian.translator.view.vocabulary.CategoryListScreen import eu.gaudian.translator.view.vocabulary.LanguageProgressScreen import eu.gaudian.translator.view.vocabulary.MainVocabularyScreen +import eu.gaudian.translator.view.vocabulary.NewWordReviewScreen +import eu.gaudian.translator.view.vocabulary.NewWordScreen import eu.gaudian.translator.view.vocabulary.NoGrammarItemsScreen import eu.gaudian.translator.view.vocabulary.StageDetailScreen import eu.gaudian.translator.view.vocabulary.VocabularyCardHost @@ -157,6 +159,12 @@ fun NavGraphBuilder.homeGraph(navController: NavHostController) { composable("main_home") { HomeScreen(navController = navController) } + composable("new_word") { + NewWordScreen(navController = navController) + } + composable("new_word_review") { + NewWordReviewScreen(navController = navController) + } } } diff --git a/app/src/main/java/eu/gaudian/translator/view/home/HomeScreen.kt b/app/src/main/java/eu/gaudian/translator/view/home/HomeScreen.kt index 7591a3a..719881f 100644 --- a/app/src/main/java/eu/gaudian/translator/view/home/HomeScreen.kt +++ b/app/src/main/java/eu/gaudian/translator/view/home/HomeScreen.kt @@ -65,9 +65,10 @@ fun HomeScreen( modifier = Modifier .widthIn(max = 700.dp) // Prevents extreme stretching on tablets .fillMaxSize() - .padding(horizontal = 20.dp, vertical = 24.dp), - verticalArrangement = Arrangement.spacedBy(20.dp) + .padding(horizontal = 16.dp, vertical = 0.dp), + verticalArrangement = Arrangement.spacedBy(15.dp) ) { + item { Spacer(modifier = Modifier.height(16.dp)) } item { TopProfileSection(navController = navController) } item { StreakAndGoalSection() } item { @@ -85,7 +86,8 @@ fun HomeScreen( subtitle = "Expand your vocabulary", icon = Icons.Default.AddCircle, containerColor = MaterialTheme.colorScheme.surfaceVariant, - contentColor = MaterialTheme.colorScheme.onSurfaceVariant + contentColor = MaterialTheme.colorScheme.onSurfaceVariant, + onClick = { navController.navigate("new_word") } ) } item { WeeklyProgressSection(navController = navController) } @@ -240,13 +242,10 @@ fun ActionCard( subtitle: String, icon: ImageVector, containerColor: Color, - contentColor: Color + contentColor: Color, + onClick: (() -> Unit)? = null ) { - Card( - modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(20.dp), - colors = CardDefaults.cardColors(containerColor = containerColor, contentColor = contentColor) - ) { + val cardContent: @Composable () -> Unit = { Row( modifier = Modifier.padding(20.dp), verticalAlignment = Alignment.CenterVertically @@ -268,6 +267,25 @@ fun ActionCard( ) } } + + if (onClick != null) { + Card( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + colors = CardDefaults.cardColors(containerColor = containerColor, contentColor = contentColor), + onClick = onClick + ) { + cardContent() + } + } else { + Card( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + colors = CardDefaults.cardColors(containerColor = containerColor, contentColor = contentColor) + ) { + cardContent() + } + } } @Composable diff --git a/app/src/main/java/eu/gaudian/translator/view/vocabulary/NewWordReviewScreen.kt b/app/src/main/java/eu/gaudian/translator/view/vocabulary/NewWordReviewScreen.kt new file mode 100644 index 0000000..6450a0b --- /dev/null +++ b/app/src/main/java/eu/gaudian/translator/view/vocabulary/NewWordReviewScreen.kt @@ -0,0 +1,288 @@ +package eu.gaudian.translator.view.vocabulary + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.WarningAmber +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.navigation.NavHostController +import eu.gaudian.translator.R +import eu.gaudian.translator.model.VocabularyCategory +import eu.gaudian.translator.model.VocabularyItem +import eu.gaudian.translator.utils.findActivity +import eu.gaudian.translator.view.composable.AppButton +import eu.gaudian.translator.view.composable.AppCheckbox +import eu.gaudian.translator.view.composable.AppScaffold +import eu.gaudian.translator.view.composable.AppTopAppBar +import eu.gaudian.translator.view.dialogs.CategoryDropdown +import eu.gaudian.translator.viewmodel.VocabularyViewModel + +@Composable +fun NewWordReviewScreen( + navController: NavHostController, + modifier: Modifier = Modifier +) { + val activity = LocalContext.current.findActivity() + val vocabularyViewModel: VocabularyViewModel = hiltViewModel(activity) + + val generatedItems by vocabularyViewModel.generatedVocabularyItems.collectAsState() + val selectedItems = remember { mutableStateListOf() } + val duplicates = remember { mutableStateListOf() } + var selectedCategories by remember { mutableStateOf>(emptyList()) } + + LaunchedEffect(generatedItems) { + val duplicateResults = vocabularyViewModel.findDuplicates(generatedItems) + duplicates.clear() + duplicates.addAll(duplicateResults) + selectedItems.clear() + selectedItems.addAll(generatedItems.filterIndexed { index, _ -> !duplicateResults[index] }) + } + + AppScaffold( + topBar = { + AppTopAppBar( + title = stringResource(R.string.found_items), + onNavigateBack = { navController.popBackStack() } + ) + }, + modifier = modifier.fillMaxSize() + ) { paddingValues -> + Column( + modifier = Modifier + .padding(paddingValues) + .fillMaxSize() + ) { + SummaryHeader( + totalCount = generatedItems.size, + selectedCount = selectedItems.size, + modifier = Modifier.padding(horizontal = 20.dp, vertical = 12.dp) + ) + + if (generatedItems.isEmpty()) { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(24.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = stringResource(R.string.text_no_data_available), + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } else { + ReviewList( + generatedItems = generatedItems, + selectedItems = selectedItems, + duplicates = duplicates, + modifier = Modifier + .weight(1f) + .padding(horizontal = 16.dp) + ) + } + + Text( + text = stringResource(R.string.select_list_optional), + style = MaterialTheme.typography.labelLarge, + modifier = Modifier.padding(horizontal = 20.dp, vertical = 8.dp) + ) + CategoryDropdown( + onCategorySelected = { selectedCategories = it }, + noneSelectable = false, + multipleSelectable = true, + onlyLists = true, + addCategory = true, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + ) + + ActionRow( + selectedCount = selectedItems.size, + onCancel = { navController.popBackStack() }, + onConfirm = { + val selectedCategoryIds = selectedCategories.filterNotNull().map { it.id } + vocabularyViewModel.addVocabularyItems(selectedItems.toList(), selectedCategoryIds) + navController.popBackStack("new_word", inclusive = false) + }, + modifier = Modifier.padding(16.dp) + ) + } + } +} + +@Composable +private fun SummaryHeader( + totalCount: Int, + selectedCount: Int, + modifier: Modifier = Modifier +) { + Card( + modifier = modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.35f)) + ) { + Row( + modifier = Modifier.padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column { + Text( + text = stringResource(R.string.found_items), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold + ) + Text( + text = stringResource(R.string.text_amount_2d, totalCount), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + Column(horizontalAlignment = Alignment.End) { + Text( + text = stringResource(R.string.label_add_, selectedCount), + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.SemiBold, + color = MaterialTheme.colorScheme.primary + ) + Text( + text = stringResource(R.string.select_items_to_add), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + } +} + +@Composable +private fun ReviewList( + generatedItems: List, + selectedItems: MutableList, + duplicates: List, + modifier: Modifier = Modifier +) { + val duplicateLabel = stringResource(R.string.duplicate) + LazyColumn(modifier = modifier) { + itemsIndexed(generatedItems) { index, item -> + val isDuplicate = duplicates.getOrNull(index) == true + val isSelected = selectedItems.contains(item) + + Card( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 6.dp), + shape = RoundedCornerShape(16.dp), + colors = CardDefaults.cardColors( + containerColor = if (isDuplicate) { + MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.25f) + } else { + MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.25f) + } + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + AppCheckbox( + checked = isSelected, + onCheckedChange = { checked -> + if (checked) { + selectedItems.add(item) + } else { + selectedItems.remove(item) + } + } + ) + Spacer(modifier = Modifier.size(12.dp)) + Column(modifier = Modifier.weight(1f)) { + Text(text = item.wordFirst, style = MaterialTheme.typography.titleMedium) + Text(text = item.wordSecond, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant) + } + if (isDuplicate) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .clip(RoundedCornerShape(12.dp)) + .background(MaterialTheme.colorScheme.error.copy(alpha = 0.15f)) + .padding(horizontal = 8.dp, vertical = 4.dp) + ) { + Icon( + imageVector = Icons.Default.WarningAmber, + contentDescription = null, + tint = MaterialTheme.colorScheme.error + ) + Spacer(modifier = Modifier.size(4.dp)) + Text( + text = duplicateLabel, + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.error + ) + } + } + } + } + } + } +} + +@Composable +private fun ActionRow( + selectedCount: Int, + onCancel: () -> Unit, + onConfirm: () -> Unit, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + TextButton(onClick = onCancel) { + Text(stringResource(R.string.label_cancel)) + } + AppButton( + onClick = onConfirm, + enabled = selectedCount > 0 + ) { + Text(stringResource(R.string.label_add_, selectedCount)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/gaudian/translator/view/vocabulary/NewWordScreen.kt b/app/src/main/java/eu/gaudian/translator/view/vocabulary/NewWordScreen.kt new file mode 100644 index 0000000..59c7c84 --- /dev/null +++ b/app/src/main/java/eu/gaudian/translator/view/vocabulary/NewWordScreen.kt @@ -0,0 +1,490 @@ +package eu.gaudian.translator.view.vocabulary + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AutoAwesome +import androidx.compose.material.icons.filled.DriveFolderUpload +import androidx.compose.material.icons.filled.EditNote +import androidx.compose.material.icons.filled.LibraryBooks +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringArrayResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.navigation.NavHostController +import eu.gaudian.translator.R +import eu.gaudian.translator.model.VocabularyItem +import eu.gaudian.translator.utils.findActivity +import eu.gaudian.translator.view.composable.AppButton +import eu.gaudian.translator.view.composable.AppSlider +import eu.gaudian.translator.view.composable.AppTopAppBar +import eu.gaudian.translator.view.composable.InspiringSearchField +import eu.gaudian.translator.view.composable.SourceLanguageDropdown +import eu.gaudian.translator.view.composable.TargetLanguageDropdown +import eu.gaudian.translator.viewmodel.LanguageViewModel +import eu.gaudian.translator.viewmodel.VocabularyViewModel +import kotlinx.coroutines.launch + +@Composable +fun NewWordScreen( + navController: NavHostController, + modifier: Modifier = Modifier +) { + val activity = LocalContext.current.findActivity() + val vocabularyViewModel: VocabularyViewModel = hiltViewModel(viewModelStoreOwner = activity) + val languageViewModel: LanguageViewModel = hiltViewModel(viewModelStoreOwner = activity) + val isGenerating by vocabularyViewModel.isGenerating.collectAsState() + val generatedItems by vocabularyViewModel.generatedVocabularyItems.collectAsState() + val coroutineScope = rememberCoroutineScope() + var category by remember { mutableStateOf("") } + var amount by remember { mutableFloatStateOf(8f) } + var navigateToReview by remember { mutableStateOf(false) } + + LaunchedEffect(isGenerating, generatedItems, navigateToReview) { + if (navigateToReview && !isGenerating) { + if (generatedItems.isNotEmpty()) { + navController.navigate("new_word_review") + } + navigateToReview = false + } + } + + Box( + modifier = modifier.fillMaxSize(), + contentAlignment = Alignment.TopCenter + ) { + Column( + modifier = Modifier + .widthIn(max = 700.dp) // Perfect scaling for tablets/foldables + .fillMaxSize() + .verticalScroll(rememberScrollState()) + ) { + AppTopAppBar( + title = "New Words", + onNavigateBack = { navController.popBackStack() } + ) + + Spacer(modifier = Modifier.height(16.dp)) + + AIGeneratorCard( + category = category, + onCategoryChange = { category = it }, + amount = amount, + onAmountChange = { amount = it }, + languageViewModel = languageViewModel, + isGenerating = isGenerating, + onGenerate = { + if (category.isNotBlank() && !isGenerating) { + coroutineScope.launch { + vocabularyViewModel.generateVocabularyItems(category.trim(), amount.toInt()) + navigateToReview = true + } + } + }, + modifier = Modifier.padding(horizontal = 24.dp) + ) + + Spacer(modifier = Modifier.height(24.dp)) + + AddManuallyCard( + languageViewModel = languageViewModel, + vocabularyViewModel = vocabularyViewModel, + modifier = Modifier.padding(horizontal = 24.dp) + ) + + Spacer(modifier = Modifier.height(24.dp)) + + BottomActionCardsRow( + modifier = Modifier.padding(horizontal = 24.dp) + ) + + // Extra padding at the bottom for scroll clearance + Spacer(modifier = Modifier.height(100.dp)) + } + } +} + +// --- AI GENERATOR CARD (From previous implementation) --- + +@Composable +fun AIGeneratorCard( + category: String, + onCategoryChange: (String) -> Unit, + amount: Float, + onAmountChange: (Float) -> Unit, + languageViewModel: LanguageViewModel, + isGenerating: Boolean, + onGenerate: () -> Unit, + modifier: Modifier = Modifier +) { + val hints = stringArrayResource(R.array.vocabulary_hints) + Card( + modifier = modifier.fillMaxWidth(), + shape = RoundedCornerShape(24.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f) + ) + ) { + Column(modifier = Modifier.padding(24.dp)) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon( + imageVector = Icons.Default.AutoAwesome, + contentDescription = null, + tint = MaterialTheme.colorScheme.primary + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = "AI Generator", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold + ) + } + + Spacer(modifier = Modifier.height(24.dp)) + Text( + text = stringResource(R.string.text_search_term), + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold + ) + Spacer(modifier = Modifier.height(8.dp)) + InspiringSearchField( + value = category, + hints = hints, + onValueChange = onCategoryChange + ) + Spacer(modifier = Modifier.height(24.dp)) + Text( + text = stringResource(R.string.text_select_languages), + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold + ) + Spacer(modifier = Modifier.height(8.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + SourceLanguageDropdown( + modifier = Modifier.weight(1f), + languageViewModel = languageViewModel, + iconEnabled = false, + noBorder = true + ) + TargetLanguageDropdown( + modifier = Modifier.weight(1f), + languageViewModel = languageViewModel, + iconEnabled = false, + noBorder = true + ) + } + Spacer(modifier = Modifier.height(24.dp)) + Text( + text = stringResource(R.string.text_select_amount), + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold + ) + Spacer(modifier = Modifier.height(8.dp)) + AppSlider( + value = amount, + onValueChange = onAmountChange, + valueRange = 1f..25f, + steps = 24, + modifier = Modifier.fillMaxWidth() + ) + Text( + text = stringResource(R.string.text_amount_2d, amount.toInt()), + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.padding(top = 8.dp) + ) + Spacer(modifier = Modifier.height(32.dp)) + + if (isGenerating) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + CircularProgressIndicator() + } + Spacer(modifier = Modifier.height(16.dp)) + } + + AppButton( + onClick = onGenerate, + modifier = Modifier + .fillMaxWidth() + .height(56.dp), + enabled = category.isNotBlank() && !isGenerating + ) { + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Icon(imageVector = Icons.Default.AutoAwesome, contentDescription = null, modifier = Modifier.size(20.dp)) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = stringResource(R.string.text_generate), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold + ) + } + } + } + } +} + +// --- NEW COMPONENTS START HERE --- + +@Composable +fun AddManuallyCard( + languageViewModel: LanguageViewModel, + vocabularyViewModel: VocabularyViewModel, + modifier: Modifier = Modifier +) { + var wordText by remember { mutableStateOf("") } + var translationText by remember { mutableStateOf("") } + val selectedSourceLanguage by languageViewModel.selectedSourceLanguage.collectAsState() + val selectedTargetLanguage by languageViewModel.selectedTargetLanguage.collectAsState() + + val languageLabel = when { + selectedSourceLanguage != null && selectedTargetLanguage != null -> + "${selectedSourceLanguage?.name} → ${selectedTargetLanguage?.name}" + else -> stringResource(R.string.text_select_languages) + } + + val canAdd = wordText.isNotBlank() && translationText.isNotBlank() && + selectedSourceLanguage != null && selectedTargetLanguage != null + + Card( + modifier = modifier.fillMaxWidth(), + shape = RoundedCornerShape(24.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f) + ) + ) { + Column(modifier = Modifier.padding(24.dp)) { + // Header Row + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Box( + modifier = Modifier + .size(40.dp) + .clip(RoundedCornerShape(12.dp)) + .background(MaterialTheme.colorScheme.surfaceVariant), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Default.EditNote, + contentDescription = null, + tint = MaterialTheme.colorScheme.primary + ) + } + Spacer(modifier = Modifier.width(16.dp)) + Text( + text = stringResource(R.string.label_add_vocabulary), + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold + ) + } + + Surface( + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f), + shape = RoundedCornerShape(12.dp) + ) { + Text( + text = languageLabel, + style = MaterialTheme.typography.labelSmall, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp) + ) + } + } + + Spacer(modifier = Modifier.height(24.dp)) + + // Input Fields + TextField( + value = wordText, + onValueChange = { wordText = it }, + placeholder = { Text(stringResource(R.string.text_label_word), color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f)) }, + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(12.dp), + colors = TextFieldDefaults.colors( + focusedContainerColor = MaterialTheme.colorScheme.surface, // Very dark background + unfocusedContainerColor = MaterialTheme.colorScheme.surface, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent + ), + singleLine = true + ) + + Spacer(modifier = Modifier.height(16.dp)) + + TextField( + value = translationText, + onValueChange = { translationText = it }, + placeholder = { Text(stringResource(R.string.text_translation), color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f)) }, + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(12.dp), + colors = TextFieldDefaults.colors( + focusedContainerColor = MaterialTheme.colorScheme.surface, + unfocusedContainerColor = MaterialTheme.colorScheme.surface, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent + ), + singleLine = true + ) + + Spacer(modifier = Modifier.height(24.dp)) + + // Add to List Button (Darker variant) + AppButton( + onClick = { + val newItem = VocabularyItem( + languageFirstId = selectedSourceLanguage?.nameResId, + languageSecondId = selectedTargetLanguage?.nameResId, + wordFirst = wordText.trim(), + wordSecond = translationText.trim(), + id = 0 + ) + vocabularyViewModel.addVocabularyItems(listOf(newItem)) + wordText = "" + translationText = "" + }, + modifier = Modifier + .fillMaxWidth() + .height(56.dp), + enabled = canAdd + ) { + Text( + text = stringResource(R.string.label_add), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold + ) + } + } + } +} + +@Composable +fun BottomActionCardsRow(modifier: Modifier = Modifier) { + Row( + modifier = modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + // Explore Packs Card + Card( + modifier = Modifier.weight(1f).height(120.dp), + shape = RoundedCornerShape(20.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f) + ), + onClick = { /* TODO: Navigate to Explore */ } + ) { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Box( + modifier = Modifier + .size(48.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.surfaceVariant), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Default.LibraryBooks, + contentDescription = null, + tint = MaterialTheme.colorScheme.primary + ) + } + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = "Explore Packs", + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.Bold + ) + } + } + + // Import CSV Card + Card( + modifier = Modifier.weight(1f).height(120.dp), + shape = RoundedCornerShape(20.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f) + ), + onClick = { /* TODO: Navigate to Import */ } + ) { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Box( + modifier = Modifier + .size(48.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.surfaceVariant), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Default.DriveFolderUpload, + contentDescription = null, + tint = MaterialTheme.colorScheme.primary + ) + } + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = "Import CSV", + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.Bold + ) + } + } + } +} \ No newline at end of file