Apis benerin dong

This commit is contained in:
202310715082 FAZRI ABDURRAHMAN 2025-11-17 14:48:17 +07:00
parent f64bff7933
commit 912c489123
3 changed files with 467 additions and 326 deletions

View File

@ -4,6 +4,14 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-11-14T10:53:18.219362400Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=10DEC90GZE0004R" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState> </SelectionState>
</selectionStates> </selectionStates>
</component> </component>

View File

@ -5,7 +5,7 @@
<list> <list>
<ColumnSorterState> <ColumnSorterState>
<option name="column" value="Name" /> <option name="column" value="Name" />
<option name="order" value="ASCENDING" /> <option name="order" value="DESCENDING" />
</ColumnSorterState> </ColumnSorterState>
</list> </list>
</option> </option>

View File

@ -6,8 +6,9 @@ import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.compose.animation.*
import androidx.compose.animation.core.*
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
@ -15,16 +16,16 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.* import androidx.compose.material.icons.filled.*
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
@ -40,8 +41,6 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// Initialize PDFBox
com.example.notebook.utils.PdfHelper.initialize(this) com.example.notebook.utils.PdfHelper.initialize(this)
setContent { setContent {
@ -50,9 +49,9 @@ class MainActivity : ComponentActivity() {
NotebookTheme(darkTheme = isDarkMode) { NotebookTheme(darkTheme = isDarkMode) {
Surface( Surface(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background color = MaterialTheme.colorScheme.background // [DIUBAH] Menggunakan warna tema
) { ) {
NotebookApp( NotebookBottomSheetApp(
viewModel = viewModel, viewModel = viewModel,
isDarkMode = isDarkMode, isDarkMode = isDarkMode,
onThemeChange = { isDarkMode = it } onThemeChange = { isDarkMode = it }
@ -63,130 +62,26 @@ class MainActivity : ComponentActivity() {
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun NotebookApp(viewModel: NotebookViewModel, isDarkMode: Boolean, onThemeChange: (Boolean) -> Unit) { fun NotebookBottomSheetApp(
var selectedTabIndex by remember { mutableIntStateOf(0) } viewModel: NotebookViewModel,
val tabs = listOf("Studio", "Chat", "Sources") isDarkMode: Boolean,
var showGoogleAppsMenu by remember { mutableStateOf(false) } onThemeChange: (Boolean) -> Unit
var showSettingsMenu by remember { mutableStateOf(false) } ) {
var showAccountScreen by remember { mutableStateOf(false) } val notebooks by viewModel.notebooks.collectAsState()
var chatInput by remember { mutableStateOf("") }
var selectedNotebookId by remember { mutableIntStateOf(-1) } var selectedNotebookId by remember { mutableIntStateOf(-1) }
var showCreateDialog by remember { mutableStateOf(false) }
var showAccountScreen by remember { mutableStateOf(false) }
// Log setiap kali selectedNotebookId berubah
LaunchedEffect(selectedNotebookId) {
println("🎯 selectedNotebookId berubah menjadi: $selectedNotebookId")
}
// Kalau ada notebook yang dipilih, tampilkan detail screen
if (selectedNotebookId != -1) { if (selectedNotebookId != -1) {
println("✨ Menampilkan NotebookDetailScreen untuk ID: $selectedNotebookId")
com.example.notebook.ui.screens.NotebookDetailScreen( com.example.notebook.ui.screens.NotebookDetailScreen(
viewModel = viewModel, viewModel = viewModel,
notebookId = selectedNotebookId, notebookId = selectedNotebookId,
onBack = { onBack = { selectedNotebookId = -1 }
println("⬅️ Kembali dari detail screen")
selectedNotebookId = -1
}
) )
return return
} }
if (showAccountScreen) {
AccountScreen(onDismiss = { showAccountScreen = false })
}
Scaffold(
topBar = {
TopAppBar(
title = { Text("NoteBook") },
actions = {
Box {
IconButton(onClick = { showSettingsMenu = true }) {
Icon(Icons.Filled.Settings, contentDescription = "Settings")
}
SettingsMenu(
expanded = showSettingsMenu,
onDismiss = { showSettingsMenu = false },
isDarkMode = isDarkMode,
onThemeChange = onThemeChange
)
}
Box(
modifier = Modifier
.size(32.dp)
.clip(CircleShape)
.background(Color.Magenta)
.clickable { showAccountScreen = true },
contentAlignment = Alignment.Center
) {
Text("M", color = Color.White, fontWeight = FontWeight.Bold)
}
Spacer(modifier = Modifier.width(8.dp))
}
)
},
bottomBar = {
if (selectedTabIndex == 1) {
BottomAppBar {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = 8.dp)
) {
OutlinedTextField(
value = chatInput,
onValueChange = { chatInput = it },
placeholder = { Text("Message...") },
modifier = Modifier.weight(1f)
)
IconButton(
onClick = {
if (chatInput.isNotBlank()) {
// TODO: Kirim ke notebook yang aktif
// viewModel.sendUserMessage(notebookId, chatInput)
chatInput = ""
}
}
) {
Icon(Icons.AutoMirrored.Filled.Send, contentDescription = "Send")
}
}
}
}
}
) { innerPadding ->
Column(modifier = Modifier.padding(innerPadding)) {
TabRow(selectedTabIndex = selectedTabIndex) {
tabs.forEachIndexed { index, title ->
Tab(
selected = selectedTabIndex == index,
onClick = { selectedTabIndex = index },
text = { Text(title) }
)
}
}
when (selectedTabIndex) {
0 -> StudioScreen(
viewModel = viewModel,
onNotebookClick = { notebookId ->
println("📱 Navigasi ke notebook ID: $notebookId")
selectedNotebookId = notebookId
}
)
1 -> ChatScreen(viewModel)
2 -> SourcesScreen(viewModel)
}
}
}
}
// === STUDIO SCREEN (UPDATED) ===
@Composable
fun StudioScreen(viewModel: NotebookViewModel, onNotebookClick: (Int) -> Unit) {
val notebooks by viewModel.notebooks.collectAsState()
var showCreateDialog by remember { mutableStateOf(false) }
if (showCreateDialog) { if (showCreateDialog) {
CreateNotebookDialog( CreateNotebookDialog(
onDismiss = { showCreateDialog = false }, onDismiss = { showCreateDialog = false },
@ -197,154 +92,468 @@ fun StudioScreen(viewModel: NotebookViewModel, onNotebookClick: (Int) -> Unit) {
) )
} }
Column( if (showAccountScreen) {
AccountScreen(onDismiss = { showAccountScreen = false })
}
Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(Color.White) .background(MaterialTheme.colorScheme.background) // [DIUBAH] Menggunakan warna tema
.padding(16.dp)
) { ) {
Text( Column(
"Notebook terbaru", modifier = Modifier
style = MaterialTheme.typography.titleLarge, .fillMaxSize()
fontWeight = FontWeight.Bold, .shadow(
color = Color.Black elevation = 8.dp,
) shape = RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp)
Spacer(modifier = Modifier.height(16.dp)) )
.clip(RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp))
LazyColumn( .background(MaterialTheme.colorScheme.surface) // [DIUBAH] Menggunakan warna tema
verticalArrangement = Arrangement.spacedBy(12.dp)
) { ) {
// Card untuk buat notebook baru NotebookHeader(
item { isDarkMode = isDarkMode,
NewNotebookCard(onClick = { showCreateDialog = true }) onThemeChange = onThemeChange,
onAccountClick = { showAccountScreen = true }
)
Divider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f), thickness = 1.dp)
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp)
.padding(top = 16.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
"Notebook Saya",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.onSurface // [DIUBAH]
)
Text(
"${notebooks.size} notebook tersimpan",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant // [DIUBAH]
)
}
Spacer(modifier = Modifier.height(16.dp))
CreateNotebookButton(onClick = { showCreateDialog = true })
Spacer(modifier = Modifier.height(20.dp))
if (notebooks.isEmpty()) {
EmptyNotebookMessage()
} else {
LazyColumn(
verticalArrangement = Arrangement.spacedBy(12.dp),
contentPadding = PaddingValues(bottom = 16.dp)
) {
items(notebooks, key = { it.id }) { notebook ->
NotebookCardItem(
notebook = notebook,
onClick = { selectedNotebookId = notebook.id },
onDelete = { viewModel.deleteNotebook(notebook) }
)
}
}
}
}
}
}
}
@Composable
fun NotebookHeader(
isDarkMode: Boolean,
onThemeChange: (Boolean) -> Unit,
onAccountClick: () -> Unit
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Box(
modifier = Modifier
.size(32.dp)
.clip(RoundedCornerShape(8.dp))
.background(
Brush.linearGradient(
listOf(Color(0xFF7C3AED), Color(0xFF9333EA))
)
),
contentAlignment = Alignment.Center
) {
Icon(
Icons.Default.Book,
contentDescription = null,
tint = Color.White,
modifier = Modifier.size(20.dp)
)
}
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(
"NoteBook",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.onSurface // [DIUBAH]
)
Text(
"Selamat datang kembali!",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, // [DIUBAH]
fontSize = 11.sp
)
}
}
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
IconButton(onClick = { onThemeChange(!isDarkMode) }) {
Icon(
imageVector = if (isDarkMode) Icons.Default.LightMode else Icons.Default.DarkMode,
contentDescription = "Toggle Theme",
tint = MaterialTheme.colorScheme.onSurfaceVariant // [DIUBAH]
)
} }
// List notebooks yang sudah ada IconButton(onClick = onAccountClick) {
items(notebooks) { notebook -> Icon(
NotebookCard( Icons.Default.AccountCircle,
notebook = notebook, contentDescription = "Account",
onClick = { tint = Color(0xFF7C3AED),
println("🟢 onClick triggered untuk notebook ID: ${notebook.id}") modifier = Modifier.size(28.dp)
onNotebookClick(notebook.id)
},
onDelete = {
println("🔴 Delete triggered untuk notebook ID: ${notebook.id}")
viewModel.deleteNotebook(notebook)
}
) )
} }
} }
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun NewNotebookCard(onClick: () -> Unit) { fun AccountScreen(onDismiss: () -> Unit) {
Card( Dialog(onDismissRequest = onDismiss, properties = DialogProperties(usePlatformDefaultWidth = false)) {
modifier = Modifier Scaffold(
.fillMaxWidth()
.height(120.dp)
.clickable(onClick = onClick),
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(containerColor = Color(0xFFF0F4F7))
) {
Column(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center, topBar = {
horizontalAlignment = Alignment.CenterHorizontally TopAppBar(
) { title = { Text("Akun") },
Box( navigationIcon = {
modifier = Modifier IconButton(onClick = onDismiss) {
.size(40.dp) Icon(Icons.Default.Close, contentDescription = "Tutup")
.clip(CircleShape) }
.background(Color(0xFFE1E3E6)), }
contentAlignment = Alignment.Center )
) { }
Icon(Icons.Default.Add, contentDescription = "Buat notebook baru", tint = Color.Black) ) { paddingValues ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(32.dp))
Box(
modifier = Modifier
.size(80.dp)
.clip(CircleShape)
.background(MaterialTheme.colorScheme.primary), // [DIUBAH]
contentAlignment = Alignment.Center
) {
Text("A", fontSize = 40.sp, color = MaterialTheme.colorScheme.onPrimary, fontWeight = FontWeight.Bold) // [DIUBAH]
}
Spacer(modifier = Modifier.height(16.dp))
Text("user@google.com", fontWeight = FontWeight.Bold, fontSize = 20.sp, color = MaterialTheme.colorScheme.onSurface)
Spacer(modifier = Modifier.height(8.dp))
Text("Fazri Abdurrahman", fontSize = 16.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
Spacer(modifier = Modifier.height(24.dp))
// [DIUBAH] Tombol Kelola Akun menjadi OutlinedButton
OutlinedButton(onClick = { /* TODO: Logika Google Sign-In */ }, modifier = Modifier.fillMaxWidth()) {
Text("Kelola Akun Google Anda")
}
Spacer(modifier = Modifier.height(24.dp))
// [BARU] Kartu untuk menambah dan mengelola akun
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceContainer)
) {
Column {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { /* TODO */ }
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(Icons.Default.PersonAdd, contentDescription = null, tint = MaterialTheme.colorScheme.onSurfaceVariant)
Spacer(modifier = Modifier.width(16.dp))
Text("Tambah akun lain", color = MaterialTheme.colorScheme.onSurface)
}
Divider(modifier = Modifier.padding(horizontal = 16.dp))
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { /* TODO */ }
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(Icons.Default.ManageAccounts, contentDescription = null, tint = MaterialTheme.colorScheme.onSurfaceVariant)
Spacer(modifier = Modifier.width(16.dp))
Text("Kelola akun di perangkat ini", color = MaterialTheme.colorScheme.onSurface)
}
}
}
Spacer(modifier = Modifier.weight(1f))
Row(
modifier = Modifier.padding(bottom = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
Text("Kebijakan Privasi", fontSize = 12.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
Text("", fontSize = 12.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
Text("Persyaratan Layanan", fontSize = 12.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
}
} }
Spacer(modifier = Modifier.height(8.dp))
Text("Buat notebook baru", color = Color.Black)
} }
} }
} }
@Composable @Composable
fun NotebookCard( fun CreateNotebookButton(onClick: () -> Unit) {
Button(
onClick = onClick,
modifier = Modifier
.fillMaxWidth()
.height(56.dp),
shape = RoundedCornerShape(12.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent
),
contentPadding = PaddingValues(0.dp)
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(
Brush.horizontalGradient(
listOf(Color(0xFF7C3AED), Color(0xFF9333EA))
)
),
contentAlignment = Alignment.Center
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Icon(
Icons.Default.Add,
contentDescription = null,
tint = Color.White,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Column(horizontalAlignment = Alignment.Start) {
Text(
"Buat notebook baru",
color = Color.White,
fontWeight = FontWeight.Bold,
fontSize = 15.sp
)
}
}
}
}
}
@Composable
fun NotebookCardItem(
notebook: com.example.notebook.data.NotebookEntity, notebook: com.example.notebook.data.NotebookEntity,
onClick: () -> Unit, onClick: () -> Unit,
onDelete: () -> Unit onDelete: () -> Unit
) { ) {
val dateFormat = SimpleDateFormat("dd MMM yyyy, HH:mm", Locale.getDefault()) val dateFormat = SimpleDateFormat("dd MMM yyyy, HH:mm", Locale("id", "ID"))
var showMenu by remember { mutableStateOf(false) }
var showDeleteDialog by remember { mutableStateOf(false) }
val iconColors = listOf(
Color(0xFFEC4899), // Pink
Color(0xFF8B5CF6), // Purple
Color(0xFF3B82F6), // Blue
Color(0xFF10B981), // Green
Color(0xFFF59E0B), // Orange
)
val iconColor = remember { iconColors.random() }
if (showDeleteDialog) {
AlertDialog(
onDismissRequest = { showDeleteDialog = false },
icon = { Icon(Icons.Default.Delete, contentDescription = null) },
title = { Text("Hapus Notebook?") },
text = { Text("Notebook \"${notebook.title}\" dan semua isinya akan dihapus permanen.") },
confirmButton = {
Button(
onClick = {
onDelete()
showDeleteDialog = false
},
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFFEF4444)
)
) {
Text("Hapus")
}
},
dismissButton = {
TextButton(onClick = { showDeleteDialog = false }) {
Text("Batal")
}
}
)
}
Card( Card(
modifier = Modifier.fillMaxWidth(), modifier = Modifier
.fillMaxWidth()
.clickable(onClick = onClick),
shape = RoundedCornerShape(12.dp), shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(containerColor = Color(0xFFF8F9FA)), colors = CardDefaults.cardColors(
onClick = { containerColor = MaterialTheme.colorScheme.surfaceContainerLowest // [DIUBAH]
println("🔵 Card onClick: ID=${notebook.id}, Title=${notebook.title}") ),
onClick() elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
}
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(16.dp), .padding(12.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
// Icon notebook
Box( Box(
modifier = Modifier modifier = Modifier
.size(48.dp) .size(44.dp)
.clip(RoundedCornerShape(8.dp)) .clip(RoundedCornerShape(10.dp))
.background(Color(0xFFE8EAF6)), .background(iconColor),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Icon( Icon(
Icons.Default.Description, Icons.Default.Description,
contentDescription = null, contentDescription = null,
tint = Color(0xFF5C6BC0) tint = Color.White,
modifier = Modifier.size(24.dp)
) )
} }
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))
// Info notebook
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Text( Text(
text = notebook.title, text = notebook.title,
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis,
) color = MaterialTheme.colorScheme.onSurface // [DIUBAH]
Spacer(modifier = Modifier.height(4.dp))
Text(
text = if (notebook.description.isNotBlank()) notebook.description
else "Belum ada deskripsi",
style = MaterialTheme.typography.bodySmall,
color = Color.Gray,
maxLines = 1,
overflow = TextOverflow.Ellipsis
) )
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
Text( Text(
text = dateFormat.format(Date(notebook.updatedAt)), text = dateFormat.format(Date(notebook.updatedAt)),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = Color.Gray color = MaterialTheme.colorScheme.onSurfaceVariant, // [DIUBAH]
fontSize = 12.sp
) )
if (notebook.description.isNotBlank()) {
Spacer(modifier = Modifier.height(4.dp))
Text(
text = notebook.description,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.outline, // [DIUBAH]
maxLines = 1,
overflow = TextOverflow.Ellipsis,
fontSize = 12.sp
)
}
} }
// Delete button Box {
IconButton(onClick = onDelete) { IconButton(
Icon( onClick = { showMenu = true },
Icons.Default.Delete, modifier = Modifier.size(32.dp)
contentDescription = "Hapus", ) {
tint = Color.Gray Icon(
) Icons.Default.MoreVert,
contentDescription = "Menu",
tint = MaterialTheme.colorScheme.onSurfaceVariant // [DIUBAH]
)
}
DropdownMenu(
expanded = showMenu,
onDismissRequest = { showMenu = false }
) {
DropdownMenuItem(
text = { Text("Hapus") },
onClick = {
showMenu = false
showDeleteDialog = true
},
leadingIcon = {
Icon(
Icons.Default.Delete,
contentDescription = null,
tint = Color(0xFFEF4444)
)
}
)
}
} }
} }
} }
} }
@Composable
fun EmptyNotebookMessage() {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 32.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
Icons.Default.Description,
contentDescription = null,
modifier = Modifier.size(64.dp),
tint = MaterialTheme.colorScheme.surfaceVariant // [DIUBAH]
)
Spacer(modifier = Modifier.height(16.dp))
Text(
"Belum ada notebook",
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant // [DIUBAH]
)
Text(
"Klik tombol di atas untuk membuat notebook baru",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.outline // [DIUBAH]
)
}
}
@Composable @Composable
fun CreateNotebookDialog( fun CreateNotebookDialog(
onDismiss: () -> Unit, onDismiss: () -> Unit,
@ -355,23 +564,58 @@ fun CreateNotebookDialog(
AlertDialog( AlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
title = { Text("Buat Notebook Baru") }, icon = {
Box(
modifier = Modifier
.size(56.dp)
.clip(CircleShape)
.background(
Brush.linearGradient(
listOf(Color(0xFF7C3AED), Color(0xFF9333EA))
)
),
contentAlignment = Alignment.Center
) {
Icon(
Icons.Default.Add,
contentDescription = null,
tint = Color.White,
modifier = Modifier.size(28.dp)
)
}
},
title = {
Text(
"Buat Notebook Baru",
fontWeight = FontWeight.Bold
)
},
text = { text = {
Column { Column {
OutlinedTextField( OutlinedTextField(
value = title, value = title,
onValueChange = { title = it }, onValueChange = { title = it },
label = { Text("Judul Notebook") }, label = { Text("Judul Notebook") },
placeholder = { Text("Contoh: Catatan Kuliah") },
singleLine = true, singleLine = true,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth(),
colors = OutlinedTextFieldDefaults.colors(
focusedBorderColor = Color(0xFF7C3AED),
focusedLabelColor = Color(0xFF7C3AED)
)
) )
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(12.dp))
OutlinedTextField( OutlinedTextField(
value = description, value = description,
onValueChange = { description = it }, onValueChange = { description = it },
label = { Text("Deskripsi (opsional)") }, label = { Text("Deskripsi (opsional)") },
placeholder = { Text("Tambahkan deskripsi singkat...") },
maxLines = 3, maxLines = 3,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth(),
colors = OutlinedTextFieldDefaults.colors(
focusedBorderColor = Color(0xFF7C3AED),
focusedLabelColor = Color(0xFF7C3AED)
)
) )
} }
}, },
@ -382,129 +626,18 @@ fun CreateNotebookDialog(
onConfirm(title, description) onConfirm(title, description)
} }
}, },
enabled = title.isNotBlank() enabled = title.isNotBlank(),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF7C3AED)
)
) { ) {
Text("Buat") Text("Buat")
} }
}, },
dismissButton = { dismissButton = {
TextButton(onClick = onDismiss) { TextButton(onClick = onDismiss) {
Text("Batal") Text("Batal", color = MaterialTheme.colorScheme.onSurfaceVariant) // [DIUBAH]
} }
} }
) )
} }
// === CHAT & SOURCES SCREEN (Placeholder - akan diupdate nanti) ===
@Composable
fun ChatScreen(viewModel: NotebookViewModel) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Chat Screen - Coming Soon")
}
}
@Composable
fun SourcesScreen(viewModel: NotebookViewModel) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Sources Screen - Coming Soon")
}
}
// === MENU COMPONENTS (Tetap sama) ===
@Composable
fun AccountScreen(onDismiss: () -> Unit) {
Dialog(
onDismissRequest = onDismiss,
properties = DialogProperties(usePlatformDefaultWidth = false)
) {
Scaffold(
topBar = {
TopAppBar(
title = {
Column {
Text("202310715190@mhs.ubharajaya.ac.id", fontSize = 14.sp)
Text("Managed by mhs.ubharajay.ac.id", fontSize = 12.sp, color = Color.Gray)
}
},
actions = {
IconButton(onClick = onDismiss) {
Icon(Icons.Default.Close, contentDescription = "Close")
}
}
)
}
) { paddingValues ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.padding(horizontal = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(48.dp))
Box {
Box(
modifier = Modifier
.size(80.dp)
.clip(CircleShape)
.background(Color.Magenta),
contentAlignment = Alignment.Center
) {
Text("M", color = Color.White, fontWeight = FontWeight.Bold, fontSize = 40.sp)
}
}
Spacer(modifier = Modifier.height(16.dp))
Text("Hi, 202310715190!", fontSize = 20.sp)
}
}
}
}
@Composable
fun SettingsMenu(
expanded: Boolean,
onDismiss: () -> Unit,
isDarkMode: Boolean,
onThemeChange: (Boolean) -> Unit
) {
DropdownMenu(expanded = expanded, onDismissRequest = onDismiss) {
// Dark Mode Toggle
DropdownMenuItem(
text = {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
if (isDarkMode) Icons.Default.DarkMode else Icons.Default.LightMode,
contentDescription = null
)
Spacer(modifier = Modifier.width(12.dp))
Text(if (isDarkMode) "Mode Gelap" else "Mode Terang")
}
Switch(
checked = isDarkMode,
onCheckedChange = onThemeChange
)
}
},
onClick = { onThemeChange(!isDarkMode) }
)
Divider()
DropdownMenuItem(
text = { Text("NotebookLM Help") },
onClick = { },
leadingIcon = { Icon(Icons.Default.HelpOutline, contentDescription = null) }
)
}
}