V1 fonctionnelle

This commit is contained in:
MalcuitEmile
2025-12-17 17:58:53 +01:00
parent 9c6e229826
commit 190380dc4a
3 changed files with 243 additions and 72 deletions

View File

@@ -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)

View File

@@ -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,11 +66,32 @@ 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
fun MenuScreen( fun MenuScreen(
viewModel: LocalDvdViewModel, viewModel: LocalDvdViewModel,
@@ -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 },
label = { Text("Rechercher un DVD") },
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 8.dp),
singleLine = true
)
if (filteredDvds.isEmpty()) { DvdList(filteredAndSortedDvds)
Box( }
modifier = Modifier.weight(1f), }
contentAlignment = Alignment.Center }
) {
Text("Aucun DVD correspondant") @Composable
} fun TopBar() {
} else { Row(
LazyColumn(modifier = Modifier.weight(1f)) { modifier = Modifier
items(filteredDvds, key = { it.id }) { dvd -> .fillMaxWidth()
Column(modifier = Modifier.padding(8.dp)) { .padding(vertical = 8.dp),
Text(dvd.titre.orEmpty(), fontWeight = FontWeight.Bold) verticalAlignment = Alignment.CenterVertically,
Text("Réalisateur : ${dvd.realisateur.orEmpty()}") horizontalArrangement = Arrangement.SpaceBetween
Text("Année : ${dvd.annee.orEmpty()}") ) {
Text("Genre : ${dvd.genre.orEmpty()}") Text(
Divider() text = "Votre Vidéothèque",
} fontSize = 22.sp,
} fontWeight = FontWeight.Bold
} )
}
Row(modifier = Modifier.fillMaxWidth()){ // Row {
MyButton("+ Ajouter") { // Text("ⓘ", fontSize = 20.sp)
context.startActivity( // }
Intent( }
context, }
AjoutDvdActivity::class.java
) @Composable
) fun SearchBar(
} value: String,
MyButton("- Supprimer") { onValueChange: (String) -> Unit
context.startActivity( ) {
(Intent( OutlinedTextField(
context, value = value,
SupprDvdActivity::class.java onValueChange = onValueChange,
)) placeholder = { Text("Chercher votre film (Par: titre, réal, etc)") },
) modifier = Modifier.fillMaxWidth(),
} singleLine = true,
} shape = RoundedCornerShape(50),
colors = TextFieldDefaults.colors(
Spacer(modifier = Modifier.height(16.dp)) focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant,
unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant,
Row( focusedIndicatorColor = Color.Transparent,
modifier = Modifier.fillMaxWidth(), unfocusedIndicatorColor = Color.Transparent
horizontalArrangement = Arrangement.Center )
) { )
MyButton("Quitter") { onQuit() } }
@Composable
fun SortChip(
currentSort: SortType,
onSortSelected: (SortType) -> Unit
) {
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
)
}
}
}
} }
} }
} }

View File

@@ -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" }