V1 fonctionnelle
This commit is contained in:
@@ -53,6 +53,7 @@ dependencies {
|
|||||||
implementation(libs.androidx.compose.ui.graphics)
|
implementation(libs.androidx.compose.ui.graphics)
|
||||||
implementation(libs.androidx.compose.ui.tooling.preview)
|
implementation(libs.androidx.compose.ui.tooling.preview)
|
||||||
implementation(libs.androidx.compose.material3)
|
implementation(libs.androidx.compose.material3)
|
||||||
|
implementation(libs.androidx.ui.graphics)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
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.enableEdgeToEdge
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -14,13 +15,17 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Divider
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -29,22 +34,28 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.dev.collectiondvd.data.local.AppDatabase
|
import com.dev.collectiondvd.data.local.AppDatabase
|
||||||
|
import com.dev.collectiondvd.data.local.entities.Dvd
|
||||||
import com.dev.collectiondvd.data.repository.LocalDvdRepository
|
import com.dev.collectiondvd.data.repository.LocalDvdRepository
|
||||||
import com.dev.collectiondvd.ui.screen.AjoutDvdActivity
|
import com.dev.collectiondvd.ui.screen.AjoutDvdActivity
|
||||||
import com.dev.collectiondvd.ui.screen.SupprDvdActivity
|
|
||||||
import com.dev.collectiondvd.ui.theme.CollectionDvdTheme
|
import com.dev.collectiondvd.ui.theme.CollectionDvdTheme
|
||||||
import com.dev.collectiondvd.ui.theme.MyButton
|
|
||||||
import com.dev.collectiondvd.viewmodel.LocalDvdViewModel
|
import com.dev.collectiondvd.viewmodel.LocalDvdViewModel
|
||||||
import com.dev.collectiondvd.viewmodel.factory.LocalDvdViewModelFactory
|
import com.dev.collectiondvd.viewmodel.factory.LocalDvdViewModelFactory
|
||||||
import java.nio.file.WatchEvent
|
import androidx.compose.material3.*
|
||||||
import kotlin.system.exitProcess
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
|
import androidx.compose.material.icons.filled.Delete
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
private lateinit var viewModel: LocalDvdViewModel
|
private lateinit var viewModel: LocalDvdViewModel
|
||||||
@@ -55,9 +66,30 @@ class MainActivity : ComponentActivity() {
|
|||||||
val repository = LocalDvdRepository(dvdDao)
|
val repository = LocalDvdRepository(dvdDao)
|
||||||
val factory = LocalDvdViewModelFactory(repository)
|
val factory = LocalDvdViewModelFactory(repository)
|
||||||
viewModel = ViewModelProvider(this, factory).get(LocalDvdViewModel::class.java)
|
viewModel = ViewModelProvider(this, factory).get(LocalDvdViewModel::class.java)
|
||||||
setContent { MenuScreen(onQuit = { finish() }, viewModel = viewModel) }
|
setContent {
|
||||||
|
CollectionDvdTheme(darkTheme = true) {
|
||||||
|
MenuScreen(
|
||||||
|
onQuit = { finish() },
|
||||||
|
viewModel = viewModel
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum class SortType(
|
||||||
|
val label: String
|
||||||
|
) {
|
||||||
|
TITLE_ASC("Titre (ascendant)"),
|
||||||
|
TITLE_DESC("Titre (descendant)"),
|
||||||
|
DIRECTOR_ASC("Réalisateur (ascendant)"),
|
||||||
|
DIRECTOR_DESC("Réalisateur (descendant)"),
|
||||||
|
YEAR_ASC("Année (ascendant)"),
|
||||||
|
YEAR_DESC("Année (descendant)")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -69,86 +101,222 @@ fun MenuScreen(
|
|||||||
val dvds by viewModel.dvds.collectAsState(initial = emptyList())
|
val dvds by viewModel.dvds.collectAsState(initial = emptyList())
|
||||||
var searchQuery by remember { mutableStateOf("") }
|
var searchQuery by remember { mutableStateOf("") }
|
||||||
|
|
||||||
// 🔍 Filtrage
|
|
||||||
val filteredDvds = dvds.filter { dvd ->
|
val filteredDvds = dvds.filter { dvd ->
|
||||||
val query = searchQuery.lowercase()
|
val query = searchQuery.lowercase()
|
||||||
|
|
||||||
dvd.titre.orEmpty().lowercase().contains(query) ||
|
dvd.titre.orEmpty().lowercase().contains(query) ||
|
||||||
dvd.realisateur.orEmpty().lowercase().contains(query) ||
|
dvd.realisateur.orEmpty().lowercase().contains(query) ||
|
||||||
dvd.genre.orEmpty().lowercase().contains(query) ||
|
dvd.genre.orEmpty().lowercase().contains(query) ||
|
||||||
dvd.annee.orEmpty().lowercase().contains(query)
|
dvd.annee.orEmpty().lowercase().contains(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sortType by remember { mutableStateOf(SortType.TITLE_ASC) }
|
||||||
|
|
||||||
|
val filteredAndSortedDvds = when (sortType) {
|
||||||
|
SortType.TITLE_ASC ->
|
||||||
|
filteredDvds.sortedBy { it.titre.orEmpty().lowercase() }
|
||||||
|
|
||||||
|
SortType.TITLE_DESC ->
|
||||||
|
filteredDvds.sortedByDescending { it.titre.orEmpty() }
|
||||||
|
|
||||||
|
SortType.DIRECTOR_ASC ->
|
||||||
|
filteredDvds.sortedBy { it.realisateur.orEmpty() }
|
||||||
|
|
||||||
|
SortType.DIRECTOR_DESC ->
|
||||||
|
filteredDvds.sortedByDescending { it.realisateur.orEmpty() }
|
||||||
|
|
||||||
|
SortType.YEAR_ASC ->
|
||||||
|
filteredDvds.sortedBy { it.annee.orEmpty() }
|
||||||
|
|
||||||
|
SortType.YEAR_DESC ->
|
||||||
|
filteredDvds.sortedByDescending { it.annee.orEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔍 Filtrage
|
||||||
|
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
floatingActionButtonPosition = FabPosition.Center,
|
||||||
|
floatingActionButton = {
|
||||||
|
ExtendedFloatingActionButton(
|
||||||
|
text = { Text("Ajouter") },
|
||||||
|
icon = { Text("+") },
|
||||||
|
onClick = {
|
||||||
|
context.startActivity(
|
||||||
|
Intent(context, AjoutDvdActivity::class.java)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
) { padding ->
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(8.dp)
|
.padding(padding)
|
||||||
|
.padding(12.dp)
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(15.dp))
|
|
||||||
|
|
||||||
Text(
|
TopBar()
|
||||||
"Votre collection",
|
|
||||||
fontSize = 24.sp,
|
SearchBar(searchQuery) { searchQuery = it }
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
modifier = Modifier.padding(bottom = 8.dp)
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
SortChip(
|
||||||
|
currentSort = sortType,
|
||||||
|
onSortSelected = { sortType = it }
|
||||||
)
|
)
|
||||||
|
|
||||||
OutlinedTextField(
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
value = searchQuery,
|
|
||||||
onValueChange = { searchQuery = it },
|
DvdList(filteredAndSortedDvds)
|
||||||
label = { Text("Rechercher un DVD") },
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TopBar() {
|
||||||
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(bottom = 8.dp),
|
.padding(vertical = 8.dp),
|
||||||
singleLine = true
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
)
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
|
||||||
if (filteredDvds.isEmpty()) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
) {
|
||||||
Text("Aucun DVD correspondant")
|
Text(
|
||||||
}
|
text = "Votre Vidéothèque",
|
||||||
} else {
|
fontSize = 22.sp,
|
||||||
LazyColumn(modifier = Modifier.weight(1f)) {
|
fontWeight = FontWeight.Bold
|
||||||
items(filteredDvds, key = { it.id }) { dvd ->
|
|
||||||
Column(modifier = Modifier.padding(8.dp)) {
|
|
||||||
Text(dvd.titre.orEmpty(), fontWeight = FontWeight.Bold)
|
|
||||||
Text("Réalisateur : ${dvd.realisateur.orEmpty()}")
|
|
||||||
Text("Année : ${dvd.annee.orEmpty()}")
|
|
||||||
Text("Genre : ${dvd.genre.orEmpty()}")
|
|
||||||
Divider()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Row(modifier = Modifier.fillMaxWidth()){
|
|
||||||
MyButton("+ Ajouter") {
|
|
||||||
context.startActivity(
|
|
||||||
Intent(
|
|
||||||
context,
|
|
||||||
AjoutDvdActivity::class.java
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
MyButton("- Supprimer") {
|
|
||||||
context.startActivity(
|
|
||||||
(Intent(
|
|
||||||
context,
|
|
||||||
SupprDvdActivity::class.java
|
|
||||||
))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Row {
|
||||||
|
// Text("ⓘ", fontSize = 20.sp)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
@Composable
|
||||||
|
fun SearchBar(
|
||||||
Row(
|
value: String,
|
||||||
|
onValueChange: (String) -> Unit
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = onValueChange,
|
||||||
|
placeholder = { Text("Chercher votre film (Par: titre, réal, etc)") },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.Center
|
singleLine = true,
|
||||||
|
shape = RoundedCornerShape(50),
|
||||||
|
colors = TextFieldDefaults.colors(
|
||||||
|
focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
focusedIndicatorColor = Color.Transparent,
|
||||||
|
unfocusedIndicatorColor = Color.Transparent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SortChip(
|
||||||
|
currentSort: SortType,
|
||||||
|
onSortSelected: (SortType) -> Unit
|
||||||
) {
|
) {
|
||||||
MyButton("Quitter") { onQuit() }
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
Card(
|
||||||
|
modifier = Modifier.clickable { expanded = true },
|
||||||
|
shape = RoundedCornerShape(50),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceVariant
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "≡ ${currentSort.label}",
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
|
fontSize = 14.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false }
|
||||||
|
) {
|
||||||
|
SortType.values().forEach { sort ->
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(sort.label) },
|
||||||
|
onClick = {
|
||||||
|
expanded = false
|
||||||
|
onSortSelected(sort)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DvdList(
|
||||||
|
dvds: List<Dvd>
|
||||||
|
) {
|
||||||
|
LazyColumn {
|
||||||
|
items(dvds, key = { it.id }) { dvd ->
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 6.dp),
|
||||||
|
shape = RoundedCornerShape(16.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.padding(12.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
|
||||||
|
// 📀 Affiche (image fictive si pas encore stockée)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.height(90.dp)
|
||||||
|
.width(60.dp)
|
||||||
|
.background(
|
||||||
|
MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
RoundedCornerShape(8.dp)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
|
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
dvd.titre.orEmpty().uppercase(),
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = Color(0xFFFFA405)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
"Réalisateur: ${dvd.realisateur.orEmpty().uppercase()}",
|
||||||
|
fontSize = 13.sp,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
"Année: ${dvd.annee.orEmpty()}",
|
||||||
|
fontSize = 13.sp,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
"Genre: ${dvd.genre.orEmpty().uppercase()}",
|
||||||
|
fontSize = 13.sp,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ espressoCore = "3.7.0"
|
|||||||
lifecycleRuntimeKtx = "2.10.0"
|
lifecycleRuntimeKtx = "2.10.0"
|
||||||
activityCompose = "1.12.1"
|
activityCompose = "1.12.1"
|
||||||
composeBom = "2024.09.00"
|
composeBom = "2024.09.00"
|
||||||
|
uiGraphics = "1.10.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
@@ -24,6 +25,7 @@ androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "u
|
|||||||
androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||||
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||||
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
|
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||||
|
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics", version.ref = "uiGraphics" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|||||||
Reference in New Issue
Block a user