Apis benerin dong
This commit is contained in:
parent
f64bff7933
commit
912c489123
8
.idea/deploymentTargetSelector.xml
generated
8
.idea/deploymentTargetSelector.xml
generated
@ -4,6 +4,14 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<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>
|
||||
</selectionStates>
|
||||
</component>
|
||||
|
||||
2
.idea/deviceManager.xml
generated
2
.idea/deviceManager.xml
generated
@ -5,7 +5,7 @@
|
||||
<list>
|
||||
<ColumnSorterState>
|
||||
<option name="column" value="Name" />
|
||||
<option name="order" value="ASCENDING" />
|
||||
<option name="order" value="DESCENDING" />
|
||||
</ColumnSorterState>
|
||||
</list>
|
||||
</option>
|
||||
|
||||
@ -6,8 +6,9 @@ import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
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.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Send
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@ -40,8 +41,6 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Initialize PDFBox
|
||||
com.example.notebook.utils.PdfHelper.initialize(this)
|
||||
|
||||
setContent {
|
||||
@ -50,9 +49,9 @@ class MainActivity : ComponentActivity() {
|
||||
NotebookTheme(darkTheme = isDarkMode) {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background
|
||||
color = MaterialTheme.colorScheme.background // [DIUBAH] Menggunakan warna tema
|
||||
) {
|
||||
NotebookApp(
|
||||
NotebookBottomSheetApp(
|
||||
viewModel = viewModel,
|
||||
isDarkMode = isDarkMode,
|
||||
onThemeChange = { isDarkMode = it }
|
||||
@ -63,130 +62,26 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun NotebookApp(viewModel: NotebookViewModel, isDarkMode: Boolean, onThemeChange: (Boolean) -> Unit) {
|
||||
var selectedTabIndex by remember { mutableIntStateOf(0) }
|
||||
val tabs = listOf("Studio", "Chat", "Sources")
|
||||
var showGoogleAppsMenu by remember { mutableStateOf(false) }
|
||||
var showSettingsMenu by remember { mutableStateOf(false) }
|
||||
var showAccountScreen by remember { mutableStateOf(false) }
|
||||
var chatInput by remember { mutableStateOf("") }
|
||||
fun NotebookBottomSheetApp(
|
||||
viewModel: NotebookViewModel,
|
||||
isDarkMode: Boolean,
|
||||
onThemeChange: (Boolean) -> Unit
|
||||
) {
|
||||
val notebooks by viewModel.notebooks.collectAsState()
|
||||
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) {
|
||||
println("✨ Menampilkan NotebookDetailScreen untuk ID: $selectedNotebookId")
|
||||
com.example.notebook.ui.screens.NotebookDetailScreen(
|
||||
viewModel = viewModel,
|
||||
notebookId = selectedNotebookId,
|
||||
onBack = {
|
||||
println("⬅️ Kembali dari detail screen")
|
||||
selectedNotebookId = -1
|
||||
}
|
||||
onBack = { selectedNotebookId = -1 }
|
||||
)
|
||||
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) {
|
||||
CreateNotebookDialog(
|
||||
onDismiss = { showCreateDialog = false },
|
||||
@ -197,153 +92,467 @@ fun StudioScreen(viewModel: NotebookViewModel, onNotebookClick: (Int) -> Unit) {
|
||||
)
|
||||
}
|
||||
|
||||
if (showAccountScreen) {
|
||||
AccountScreen(onDismiss = { showAccountScreen = false })
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.background) // [DIUBAH] Menggunakan warna tema
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.White)
|
||||
.padding(16.dp)
|
||||
.shadow(
|
||||
elevation = 8.dp,
|
||||
shape = RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp)
|
||||
)
|
||||
.clip(RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp))
|
||||
.background(MaterialTheme.colorScheme.surface) // [DIUBAH] Menggunakan warna tema
|
||||
) {
|
||||
NotebookHeader(
|
||||
isDarkMode = isDarkMode,
|
||||
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 terbaru",
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
"Notebook Saya",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = Color.Black
|
||||
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))
|
||||
|
||||
LazyColumn(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
// Card untuk buat notebook baru
|
||||
item {
|
||||
NewNotebookCard(onClick = { showCreateDialog = true })
|
||||
}
|
||||
CreateNotebookButton(onClick = { showCreateDialog = true })
|
||||
|
||||
// List notebooks yang sudah ada
|
||||
items(notebooks) { notebook ->
|
||||
NotebookCard(
|
||||
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 = {
|
||||
println("🟢 onClick triggered untuk notebook ID: ${notebook.id}")
|
||||
onNotebookClick(notebook.id)
|
||||
},
|
||||
onDelete = {
|
||||
println("🔴 Delete triggered untuk notebook ID: ${notebook.id}")
|
||||
viewModel.deleteNotebook(notebook)
|
||||
}
|
||||
onClick = { selectedNotebookId = notebook.id },
|
||||
onDelete = { viewModel.deleteNotebook(notebook) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NewNotebookCard(onClick: () -> Unit) {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(120.dp)
|
||||
.clickable(onClick = onClick),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = Color(0xFFF0F4F7))
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(40.dp)
|
||||
.clip(CircleShape)
|
||||
.background(Color(0xFFE1E3E6)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(Icons.Default.Add, contentDescription = "Buat notebook baru", tint = Color.Black)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text("Buat notebook baru", color = Color.Black)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NotebookCard(
|
||||
notebook: com.example.notebook.data.NotebookEntity,
|
||||
onClick: () -> Unit,
|
||||
onDelete: () -> Unit
|
||||
) {
|
||||
val dateFormat = SimpleDateFormat("dd MMM yyyy, HH:mm", Locale.getDefault())
|
||||
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = Color(0xFFF8F9FA)),
|
||||
onClick = {
|
||||
println("🔵 Card onClick: ID=${notebook.id}, Title=${notebook.title}")
|
||||
onClick()
|
||||
}
|
||||
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]
|
||||
)
|
||||
}
|
||||
|
||||
IconButton(onClick = onAccountClick) {
|
||||
Icon(
|
||||
Icons.Default.AccountCircle,
|
||||
contentDescription = "Account",
|
||||
tint = Color(0xFF7C3AED),
|
||||
modifier = Modifier.size(28.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AccountScreen(onDismiss: () -> Unit) {
|
||||
Dialog(onDismissRequest = onDismiss, properties = DialogProperties(usePlatformDefaultWidth = false)) {
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text("Akun") },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onDismiss) {
|
||||
Icon(Icons.Default.Close, contentDescription = "Tutup")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) { 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 notebook
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
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
|
||||
.size(48.dp)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.background(Color(0xFFE8EAF6)),
|
||||
.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,
|
||||
onClick: () -> Unit,
|
||||
onDelete: () -> Unit
|
||||
) {
|
||||
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(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onClick),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = MaterialTheme.colorScheme.surfaceContainerLowest // [DIUBAH]
|
||||
),
|
||||
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(44.dp)
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.background(iconColor),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Description,
|
||||
contentDescription = null,
|
||||
tint = Color(0xFF5C6BC0)
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
|
||||
// Info notebook
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = notebook.title,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
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
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.colorScheme.onSurface // [DIUBAH]
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
text = dateFormat.format(Date(notebook.updatedAt)),
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
IconButton(
|
||||
onClick = { showMenu = true },
|
||||
modifier = Modifier.size(32.dp)
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.MoreVert,
|
||||
contentDescription = "Menu",
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant // [DIUBAH]
|
||||
)
|
||||
}
|
||||
|
||||
// Delete button
|
||||
IconButton(onClick = onDelete) {
|
||||
DropdownMenu(
|
||||
expanded = showMenu,
|
||||
onDismissRequest = { showMenu = false }
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text("Hapus") },
|
||||
onClick = {
|
||||
showMenu = false
|
||||
showDeleteDialog = true
|
||||
},
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
Icons.Default.Delete,
|
||||
contentDescription = "Hapus",
|
||||
tint = Color.Gray
|
||||
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
|
||||
fun CreateNotebookDialog(
|
||||
@ -355,23 +564,58 @@ fun CreateNotebookDialog(
|
||||
|
||||
AlertDialog(
|
||||
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 = {
|
||||
Column {
|
||||
OutlinedTextField(
|
||||
value = title,
|
||||
onValueChange = { title = it },
|
||||
label = { Text("Judul Notebook") },
|
||||
placeholder = { Text("Contoh: Catatan Kuliah") },
|
||||
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(
|
||||
value = description,
|
||||
onValueChange = { description = it },
|
||||
label = { Text("Deskripsi (opsional)") },
|
||||
placeholder = { Text("Tambahkan deskripsi singkat...") },
|
||||
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)
|
||||
}
|
||||
},
|
||||
enabled = title.isNotBlank()
|
||||
enabled = title.isNotBlank(),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color(0xFF7C3AED)
|
||||
)
|
||||
) {
|
||||
Text("Buat")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
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) }
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user